ShellPrompt: traverse $PATH once per invocation. Major speed improvement

This commit is contained in:
Spencer Janssen
2007-10-16 09:05:52 +00:00
parent 53c9038b53
commit 452ba366ad

View File

@@ -52,31 +52,35 @@ data Shell = Shell
instance XPrompt Shell where instance XPrompt Shell where
showXPrompt Shell = "Run: " showXPrompt Shell = "Run: "
shellPrompt :: XPConfig -> X () shellPrompt :: XPConfig -> X ()
shellPrompt c = mkXPrompt Shell c getShellCompl spawn shellPrompt c = do
cmds <- io $ getCommands
mkXPrompt Shell c (getShellCompl cmds) spawn
getShellCompl :: String -> IO [String] getShellCompl :: [String] -> String -> IO [String]
getShellCompl s getShellCompl cmds s | s == "" || last s == ' ' = return []
| s /= "" && last s /= ' ' = do | otherwise = do
f <- fmap lines $ runProcessWithInput "/bin/bash" [] ("compgen -A file " ++ s ++ "\n") f <- fmap lines $ runProcessWithInput "/bin/bash" [] ("compgen -A file " ++ s ++ "\n")
c <- commandCompletionFunction s return . map escape . uniqSort $ f ++ commandCompletionFunction cmds s
return . map escape . sort . (toList . fromList) $ f ++ c
| otherwise = return []
commandCompletionFunction :: String -> IO [String] uniqSort :: Ord a => [a] -> [a]
commandCompletionFunction str uniqSort = toList . fromList
| '/' `elem` str = return []
| otherwise = do commandCompletionFunction :: [String] -> String -> [String]
p <- getEnv "PATH" `catch` const (return []) commandCompletionFunction cmds str | '/' `elem` str = []
let ds = split ':' p | otherwise = filter (isPrefixOf str) cmds
fp d f = d ++ "/" ++ f
es <- forM ds $ \d -> do getCommands :: IO [String]
exists <- doesDirectoryExist d getCommands = do
if exists p <- getEnv "PATH" `catch` const (return [])
then getDirectoryContents d >>= filterM (isExecutable . fp d) let ds = split ':' p
else return [] fp d f = d ++ "/" ++ f
return . filter (isPrefixOf str) . concat $ es 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 :: FilePath ->IO Bool
isExecutable f = do isExecutable f = do