Files
xmonad-contrib/ShellPrompt.hs
Christian Thiemann 830945336f Move runXXX functions to one module
This patch takes runProcessWithInput out of Dmenu, runProcessWithInputAndWait
out of Dzen, and runInXTerm out of RunInXTerm and collects them in one central
module called Run.  This way, other modules may include Run instead of Dmenu
to get what they want without giving the impression of making use of dmenu.
2007-10-12 14:52:33 +00:00

110 lines
3.0 KiB
Haskell

-----------------------------------------------------------------------------
-- |
-- Module : XMonadContrib.ShellPrompt
-- Copyright : (C) 2007 Andrea Rossato
-- License : BSD3
--
-- Maintainer : andrea.rossato@unibz.it
-- Stability : unstable
-- Portability : unportable
--
-- A shell prompt for XMonad
--
-----------------------------------------------------------------------------
module XMonadContrib.ShellPrompt (
-- * Usage
-- $usage
shellPrompt
, getShellCompl
, split
) where
import XMonad
import XMonadContrib.XPrompt
import XMonadContrib.Run
import Control.Monad
import Data.List
import Data.Set (toList, fromList)
import System.Directory
import System.IO
import System.Environment
-- $usage
--
-- 1. In Config.hs add:
--
-- > import XMonadContrib.XPrompt
-- > import XMonadContrib.ShellPrompt
--
-- 2. In your keybindings add something like:
--
-- > , ((modMask .|. controlMask, xK_x), shellPrompt defaultXPConfig)
--
-- %import XMonadContrib.XPrompt
-- %import XMonadContrib.ShellPrompt
-- %keybind , ((modMask .|. controlMask, xK_x), shellPrompt defaultXPConfig)
data Shell = Shell
instance XPrompt Shell where
showXPrompt Shell = "Run: "
shellPrompt :: XPConfig -> X ()
shellPrompt c = do
cmds <- io $ getCommands
mkXPrompt Shell c (getShellCompl cmds) spawn
getShellCompl :: [String] -> String -> IO [String]
getShellCompl cmds s | s == "" || last s == ' ' = return []
| otherwise = do
f <- fmap lines $ runProcessWithInput "/bin/bash" [] ("compgen -A file " ++ s ++ "\n")
return . map escape . uniqSort $ f ++ commandCompletionFunction cmds s
uniqSort :: Ord a => [a] -> [a]
uniqSort = toList . fromList
commandCompletionFunction :: [String] -> String -> [String]
commandCompletionFunction cmds str | '/' `elem` str = []
| otherwise = filter (isPrefixOf str) cmds
getCommands :: IO [String]
getCommands = do
p <- getEnv "PATH" `catch` const (return [])
let ds = split ':' p
fp d f = d ++ "/" ++ f
es <- forM ds $ \d -> do
exists <- doesDirectoryExist d
if exists
then getDirectoryContents d >>= filterM (isExecutable . fp d)
else return []
return . uniqSort . concat $ es
isExecutable :: FilePath ->IO Bool
isExecutable f = do
fe <- doesFileExist f
if fe
then fmap executable $ getPermissions f
else return False
split :: Eq a => a -> [a] -> [[a]]
split _ [] = []
split e l =
f : split e (rest ls)
where
(f,ls) = span (/=e) l
rest s | s == [] = []
| otherwise = tail s
escape :: String -> String
escape [] = ""
escape (' ':xs) = "\\ " ++ escape xs
escape (x:xs)
| isSpecialChar x = '\\' : x : escape xs
| otherwise = x : escape xs
isSpecialChar :: Char -> Bool
isSpecialChar = flip elem "\\@\"'#?$*()[]{};"