1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
|
-----------------------------------------------------------------------------
-- |
-- Module : XMonad.Prompt.DirExec
-- Copyright : (C) 2008 Juraj Hercek
-- License : BSD3
--
-- Maintainer : juhe_xmonad@hck.sk
-- Stability : unstable
-- Portability : unportable
--
-- A directory file executables prompt for XMonad. This might be useful if you
-- don't want to have scripts in your PATH environment variable (same
-- executable names, different behavior) - otherwise you might want to use
-- "XMonad.Prompt.Shell" instead - but you want to have easy access to these
-- executables through the xmonad's prompt.
--
-----------------------------------------------------------------------------
module XMonad.Prompt.DirExec
( -- * Usage
-- $usage
dirExecPrompt
, dirExecPromptNamed
) where
import Prelude hiding (catch)
import Control.Exception
import System.Directory
import Control.Monad
import Data.List
import XMonad
import XMonad.Prompt
econst :: Monad m => a -> IOException -> m a
econst = const . return
-- $usage
-- 1. In your @~\/.xmonad\/xmonad.hs@:
--
-- > import XMonad.Prompt.DirExec
--
-- 2. In your keybindings add something like:
--
-- > , ("M-C-x", dirExecPrompt defaultXPConfig spawn "/home/joe/.scipts")
--
-- or
--
-- > , ("M-C-x", dirExecPromptNamed defaultXPConfig spawn
-- > "/home/joe/.scripts" "My Scripts: ")
--
-- or add this after your default bindings:
--
-- > ++
-- > [ ("M-x " ++ key, dirExecPrompt defaultXPConfig fn "/home/joe/.scripts")
-- > | (key, fn) <- [ ("x", spawn), ("M-x", runInTerm "-hold") ]
-- > ]
-- > ++
--
-- The first alternative uses the last element of the directory path for
-- a name of prompt. The second alternative uses the provided string
-- for the name of the prompt. The third alternative defines 2 key bindings,
-- first one spawns the program by shell, second one runs the program in
-- terminal
--
-- For detailed instruction on editing the key binding see
-- "XMonad.Doc.Extending#Editing_key_bindings".
data DirExec = DirExec String
instance XPrompt DirExec where
showXPrompt (DirExec name) = name
-- | Function 'dirExecPrompt' starts the prompt with list of all executable
-- files in directory specified by 'FilePath'. The name of the prompt is taken
-- from the last element of the path. If you specify root directory - @\/@ - as
-- the path, name @Root:@ will be used as the name of the prompt instead. The
-- 'XPConfig' parameter can be used to customize visuals of the prompt.
-- The runner parameter specifies the function used to run the program - see
-- usage for more information
dirExecPrompt :: XPConfig -> (String -> X ()) -> FilePath -> X ()
dirExecPrompt cfg runner path = do
let name = (++ ": ") . last
. (["Root"] ++) -- handling of "/" path parameter
. words
. map (\x -> if x == '/' then ' ' else x)
$ path
dirExecPromptNamed cfg runner path name
-- | Function 'dirExecPromptNamed' does the same as 'dirExecPrompt' except
-- the name of the prompt is specified by 'String' parameter.
dirExecPromptNamed :: XPConfig -> (String -> X ()) -> FilePath -> String -> X ()
dirExecPromptNamed cfg runner path name = do
let path' = path ++ "/"
cmds <- io $ getDirectoryExecutables path'
mkXPrompt (DirExec name) cfg (compList cmds) (runner . (path' ++))
where
compList cmds s = return . filter (isInfixOf s) $ cmds
getDirectoryExecutables :: FilePath -> IO [String]
getDirectoryExecutables path =
(getDirectoryContents path >>=
filterM (\x -> let x' = path ++ x in
liftM2 (&&)
(doesFileExist x')
(liftM executable (getPermissions x'))))
`catch` econst []
|