aboutsummaryrefslogtreecommitdiffstats
path: root/ManPrompt.hs
diff options
context:
space:
mode:
authorValery V. Vorotyntsev <valery.vv@gmail.com>2007-10-22 21:14:43 +0200
committerValery V. Vorotyntsev <valery.vv@gmail.com>2007-10-22 21:14:43 +0200
commita5ded0ec647f908988678525b0be0a4f5186063e (patch)
tree458829873f11c7e51de1d8592878e401cd224de9 /ManPrompt.hs
parentad9639398dfb0a960f7e4a2ee9bc9f5c3819806f (diff)
downloadXMonadContrib-a5ded0ec647f908988678525b0be0a4f5186063e.tar.gz
XMonadContrib-a5ded0ec647f908988678525b0be0a4f5186063e.tar.xz
XMonadContrib-a5ded0ec647f908988678525b0be0a4f5186063e.zip
ManPrompt.hs: a manual page prompt (new module)
darcs-hash:20071022191443-ae588-2062c1cf18050861d8cee344117d07f13f653605.gz
Diffstat (limited to '')
-rw-r--r--ManPrompt.hs115
1 files changed, 115 insertions, 0 deletions
diff --git a/ManPrompt.hs b/ManPrompt.hs
new file mode 100644
index 0000000..c4144d4
--- /dev/null
+++ b/ManPrompt.hs
@@ -0,0 +1,115 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module : XMonadContrib.ManPrompt
+-- Copyright : (c) 2007 Valery V. Vorotyntsev
+-- License : BSD3-style (see LICENSE)
+--
+-- Maintainer : valery.vv@gmail.com
+-- Stability : unstable
+-- Portability : unportable
+--
+-- A manual page prompt for XMonad window manager.
+--
+-- TODO
+--
+-- * narrow completions by section number, if the one is specified
+-- (like @\/etc\/bash_completion@ does)
+--
+-- * quickcheck properties
+-----------------------------------------------------------------------------
+
+module XMonadContrib.ManPrompt (
+ -- * Usage
+ -- $usage
+ manPrompt
+ , getCommandOutput
+ , uniqSort
+ ) where
+
+import XMonad
+import XMonadContrib.XPrompt
+import XMonadContrib.Run
+import XMonadContrib.ShellPrompt ( split )
+
+import System.Directory
+import System.Process
+import System.IO
+
+import qualified Control.Exception as E
+import Control.Monad
+import Data.List
+import Data.Maybe
+import Data.Set (toList, fromList)
+
+-- $usage
+-- 1. In Config.hs add:
+--
+-- > import XMonadContrib.ManPrompt
+--
+-- 2. In your keybindings add something like:
+--
+-- > , ((modMask, xK_F1), manPrompt defaultXPConfig)
+
+-- %import XMonadContrib.XPrompt
+-- %import XMonadContrib.ManPrompt
+-- %keybind , ((modMask, xK_F1), manPrompt defaultXPConfig)
+
+data Man = Man
+
+instance XPrompt Man where
+ showXPrompt Man = "Manual page: "
+
+-- | Query for manual page to be displayed.
+manPrompt :: XPConfig -> X ()
+manPrompt c = mkXPrompt Man c manCompl man
+ where
+ man :: String -> X ()
+ man s = runInXTerm ("man " ++ s)
+
+manCompl :: String -> IO [String]
+manCompl s = getManpages >>= flip mkComplFunFromList s
+
+-- | Sort a list and remove duplicates.
+--
+-- /XXX Code duplication!/
+-- The function with the same name exists in "ShellPrompt" module.
+uniqSort :: Ord a => [a] -> [a]
+uniqSort = toList . fromList
+
+-- | Obtain the list of manual pages.
+--
+-- /XXX Code duplication!/
+-- Adopted from 'ShellPrompt.getCommands'.
+getManpages :: IO [String]
+getManpages = do
+ p <- getCommandOutput "manpath -g 2>/dev/null" `E.catch` const (return [])
+ let sections = ["man" ++ show n | n <- [1..9 :: Int]] -- XXX "cat1".."cat9"?
+ ds = [d ++ "/" ++ s | d <- split ':' p, s <- sections]
+ stripSec = reverse . drop 1 . dropWhile (/= '.') . reverse
+ ms <- forM ds $ \d -> do
+ exists <- doesDirectoryExist d
+ if exists
+ then map (stripSec . stripSuffixes [".gz", ".bz2"]) `fmap`
+ getDirectoryContents d
+ else return []
+ return . uniqSort . concat $ ms
+
+-- | Run a command using shell and return its output.
+getCommandOutput :: String -> IO String
+getCommandOutput s = do
+ (pin, pout, perr, ph) <- runInteractiveCommand s
+ hClose pin
+ output <- hGetContents pout
+ E.evaluate (null output)
+ hClose perr
+ waitForProcess ph
+ return output
+
+stripSuffixes :: Eq a => [[a]] -> [a] -> [a]
+stripSuffixes sufs fn =
+ head . catMaybes $ map (flip rstrip fn) sufs ++ [Just fn]
+
+rstrip :: Eq a => [a] -> [a] -> Maybe [a]
+rstrip suf lst
+ | suf `isSuffixOf` lst = Just $ take (length lst - length suf) lst
+ | otherwise = Nothing