aboutsummaryrefslogtreecommitdiffstats
path: root/XMonad/Actions/Launcher.hs
diff options
context:
space:
mode:
Diffstat (limited to 'XMonad/Actions/Launcher.hs')
-rw-r--r--XMonad/Actions/Launcher.hs177
1 files changed, 177 insertions, 0 deletions
diff --git a/XMonad/Actions/Launcher.hs b/XMonad/Actions/Launcher.hs
new file mode 100644
index 0000000..4b54571
--- /dev/null
+++ b/XMonad/Actions/Launcher.hs
@@ -0,0 +1,177 @@
+{- |
+Module : XMonad.Actions.Launcher
+Copyright : (C) 2012 Carlos López-Camey
+License : None; public domain
+
+Maintainer : <c.lopez@kmels.net>
+Stability : unstable
+
+A set of prompts for XMonad
+-}
+
+module XMonad.Actions.Launcher(
+ -- * Description and use
+ -- $description
+ defaultLauncherModes
+ , ExtensionActions
+ , LauncherConfig(..)
+ , LocateFileMode
+ , LocateFileRegexMode
+ , launcherPrompt
+ -- * ToDo
+ -- $todo
+) where
+
+import Data.List (find, findIndex, isPrefixOf, tails)
+import qualified Data.Map as M
+import Data.Maybe (fromMaybe, isJust)
+import System.Directory (doesDirectoryExist)
+import XMonad hiding (config)
+import XMonad.Prompt
+import XMonad.Util.Run
+
+{- $description
+ This module lets you combine and switch between different types of prompts (XMonad.Prompt). It includes a set of default modes:
+
+ * Hoogle mode: Search for functions using hoogle, choosing a function leads you to documentation in Haddock.
+
+ * Locate mode: Search for files using locate, choosing a file opens it with a program you specify depending on the file's extension.
+
+ * Locate regexp: Same as locate mode but autocomplete works with regular expressions.
+
+ * Calc: Uses the program calc to do calculations.
+
+ To use the default modes, modify your .xmonad:
+
+ > import XMonad.Prompt(defaultXPConfig)
+ > import XMonad.Actions.Launcher
+
+ > ((modm .|. controlMask, xK_l), launcherPrompt kmelsXPConfig $ defaultLauncherModes launcherConfig)
+
+ A LauncherConfig contains settings for the default modes, modify them accordingly.
+
+ > launcherConfig = LauncherConfig { pathToHoogle = "/home/YOU/.cabal/bin/hoogle" , actionsByExtension = extensionActions }
+
+@extensionActions :: M.Map String (String -> X())
+extensionActions = M.fromList $ [
+ (\".hs\", \p -> spawn $ \"emacs \" ++ p)
+ , (\".pdf\", \p -> spawn $ \"acroread \" ++ p)
+ , (\".*\", \p -> spawn $ \"emacs \" ++ p) --match with any files
+ , (\"/\", \p -> spawn $ \"nautilus \" ++ p) --match with directories
+ ]@
+
+ To try it, restart xmonad. Press Ctrl + Your_Modkey + L and the first prompt should pop up.
+
+ You can change mode with xK_grave if you used defaultXP or change the value of changeModeKey in your XPConfig-}
+
+data LocateFileMode = LMode ExtensionActions
+data LocateFileRegexMode = LRMode ExtensionActions
+data HoogleMode = HMode FilePath String --path to hoogle e.g. "/home/me/.cabal/bin/hoogle"
+data CalculatorMode = CalcMode
+
+data LauncherConfig = LauncherConfig {
+ browser :: String
+ , pathToHoogle :: String
+ , actionsByExtension :: ExtensionActions
+}
+
+type ExtensionActions = M.Map String (String -> X())
+
+-- | Uses the program `locate` to list files
+instance XPrompt LocateFileMode where
+ showXPrompt (LMode _) = "locate %s> "
+ completionFunction (LMode _) = \s -> if (s == "" || last s == ' ') then return [] else (completionFunctionWith "locate" ["--limit","5",s])
+ modeAction (LMode actions) _ fp = spawnWithActions actions fp
+
+-- | Uses the program `locate --regex` to list files
+instance XPrompt LocateFileRegexMode where
+ showXPrompt (LRMode _) = "locate --regexp %s> "
+ completionFunction (LRMode _) = \s -> if (s == "" || last s == ' ') then return [] else (completionFunctionWith "locate" ["--limit","5","--regexp",s])
+ modeAction (LRMode actions) _ fp = spawnWithActions actions fp
+
+-- | Uses the command `calc` to compute arithmetic expressions
+instance XPrompt CalculatorMode where
+ showXPrompt CalcMode = "calc %s> "
+ commandToComplete CalcMode = id --send the whole string to `calc`
+ completionFunction CalcMode = \s -> if (length s == 0) then return [] else do
+ fmap lines $ runProcessWithInput "calc" [s] ""
+ modeAction CalcMode _ _ = return () -- do nothing; this might copy the result to the clipboard
+
+-- | Uses the program `hoogle` to search for functions
+instance XPrompt HoogleMode where
+ showXPrompt _ = "hoogle %s> "
+ commandToComplete _ = id
+ completionFunction (HMode pathToHoogleBin' _) = \s -> completionFunctionWith pathToHoogleBin' ["--count","5",s]
+ -- This action calls hoogle again to find the URL corresponding to the autocompleted item
+ modeAction (HMode pathToHoogleBin'' browser) query result = do
+ completionsWithLink <- liftIO $ completionFunctionWith pathToHoogleBin'' ["--count","5","--link",query]
+ let link = do
+ s <- find (isJust . \c -> findSeqIndex c result) completionsWithLink
+ i <- findSeqIndex s "http://"
+ return $ drop i s
+ case link of
+ Just l -> spawn $ browser ++ " " ++ l
+ _ -> return ()
+ where
+ -- | Receives a sublist and a list. It returns the index where the sublist appears in the list.
+ findSeqIndex :: (Eq a) => [a] -> [a] -> Maybe Int
+ findSeqIndex xs xss = findIndex (isPrefixOf xss) $ tails xs
+
+-- | Creates an autocompletion function for a programm given the program's name and a list of args to send to the command.
+completionFunctionWith :: String -> [String] -> IO [String]
+completionFunctionWith cmd args = do fmap lines $ runProcessWithInput cmd args ""
+
+-- | Creates a prompt with the given modes
+launcherPrompt :: XPConfig -> [XPMode] -> X()
+launcherPrompt config modes = mkXPromptWithModes modes config
+
+-- | Create a list of modes based on :
+-- a list of extensions mapped to actions
+-- the path to hoogle
+defaultLauncherModes :: LauncherConfig -> [XPMode]
+defaultLauncherModes cnf = let
+ ph = pathToHoogle cnf
+ actions = actionsByExtension cnf
+ in [ hoogleMode ph $ browser cnf
+ , locateMode actions
+ , locateRegexMode actions
+ , calcMode]
+
+locateMode, locateRegexMode :: ExtensionActions -> XPMode
+locateMode actions = XPT $ LMode actions
+locateRegexMode actions = XPT $ LRMode actions
+hoogleMode :: FilePath -> String -> XPMode
+hoogleMode pathToHoogleBin browser = XPT $ HMode pathToHoogleBin browser
+calcMode :: XPMode
+calcMode = XPT CalcMode
+
+-- | This function takes a map of extensions and a path file. It uses the map to find the pattern that matches the file path, then the corresponding program (listed in the map) is spawned.
+spawnWithActions :: ExtensionActions -> FilePath -> X()
+spawnWithActions actions fp = do
+ isDirectoryPath <- liftIO $ doesDirectoryExist fp
+ let
+ takeExtension = \p -> "." ++ (reverse . takeWhile (/= '.') $ reverse p) --it includes the dot
+ -- Patterns defined by the user
+ extAction = M.lookup (takeExtension fp) actions
+ dirAction = if (isDirectoryPath) then M.lookup "/" actions else Nothing -- / represents a directory
+ anyFileAction = M.lookup ".*" actions -- .* represents any file
+ action = fromMaybe (spawnNoPatternMessage (takeExtension fp)) $ extAction `orElse1` dirAction `orElse1` anyFileAction
+ action fp
+ where
+ -- | This function is defined in Data.Generics.Aliases (package syb "Scrap your boilerplate"), defined here to avoid dependency
+ orElse1 :: Maybe a -> Maybe a -> Maybe a
+ x `orElse1` y = case x of
+ Just _ -> x
+ Nothing -> y
+ spawnNoPatternMessage :: String -> String -> X ()
+ spawnNoPatternMessage fileExt _ = spawn $ "xmessage No action specified for file extension " ++ fileExt ++ ", add a default action by matching the extension \".*\" in the action map sent to launcherPrompt"
+
+{- $todo
+ * Switch to mode by name of the prompt, 1. ':' at an empty(?) buffer, 2. autocomplete name in buffer should happen, 3. switch to mode with enter (cancel switch with C-g)
+
+ * Support for actions of type String -> X a
+
+ * Hoogle mode: add a setting in the action to either go to documentation or to the source code (needs hoogle change?)
+
+ * Hoogle mode: add setting to query hoogle at haskell.org instead (with &mode=json)
+-} \ No newline at end of file