yeganesh 2.0 → 2.1
raw patch · 3 files changed
+41/−12 lines, 3 files
Files
- Version.hs +4/−2
- yeganesh.cabal +1/−1
- yeganesh.hs +36/−9
Version.hs view
@@ -1,11 +1,13 @@ -- boilerplate {{{-module Version (CurrentFormat, parseCurrentFormat) where+module Version (CurrentFormat, parseCurrentFormat, version) where import Data.Map (Map, elems, empty) import Data.Time (UTCTime, getCurrentTime) type CurrentFormat = FormatV2-+version :: String parseCurrentFormat :: String -> IO CurrentFormat++version = "yeganesh version 2.1" parseCurrentFormat = parseFormatV2 -- }}} -- v2 {{{
yeganesh.cabal view
@@ -1,5 +1,5 @@ name: yeganesh-version: 2.0+version: 2.1 cabal-version: >=1.2 build-type: Simple license: BSD3
yeganesh.hs view
@@ -8,26 +8,47 @@ import Data.Map (Map, insert, findWithDefault, fromList, toList, union) import Data.Ord (comparing) import Data.Time (UTCTime, diffUTCTime, getCurrentTime)-import System.Console.GetOpt (ArgDescr(ReqArg), ArgOrder(RequireOrder), OptDescr(Option), getOpt)+import System.Console.GetOpt (ArgDescr(NoArg, ReqArg), ArgOrder(RequireOrder), OptDescr(Option), getOpt, usageInfo) import System.Directory (createDirectoryIfMissing) import System.Environment (getArgs, getEnv) import System.FilePath ((</>))-import System.IO (hClose, hGetContents, hPutStr, hPutStrLn, stderr, stdout)+import System.IO (hClose, hGetContents, hPutStr, stderr, stdout) import System.Process (runInteractiveProcess, waitForProcess)-import Version (CurrentFormat, parseCurrentFormat)+import Version (CurrentFormat, parseCurrentFormat, version) import qualified System.IO.Strict as Strict (getContents, readFile) -- }}} -- getopt {{{-options :: [OptDescr String]-options = [Option "p" ["profile"] (ReqArg id "PROFILE") "which popularity profile to use"]+options :: [OptDescr Flag]+options = [Option "p" ["profile"] (ReqArg Profile "PROFILE") "which popularity profile to use"+ ,Option "v" ["version"] (NoArg Version) "print the version number"+ ,Option "h" ["help" ] (NoArg Help) "show usage information"+ ] -data Options = Options { dmenuOpts :: [String], profile :: String } deriving Show+data Options = Options { dmenuOpts :: [String], profile :: String }+data Flag = Profile String | Version | Help +compactFlags :: [Flag] -> Flag+compactFlags = foldr1 compactFlags' . (Profile "default" :) where+ compactFlags' Help _ = Help+ compactFlags' _ Help = Help+ compactFlags' Version _ = Version+ compactFlags' _ Version = Version+ compactFlags' _ p = p++introText :: String+introText = unlines $ [+ version,+ "Usage: yeganesh [OPTIONS] -- [DMENU_OPTIONS]",+ "OPTIONS are described below, and DMENU_OPTIONS are passed on verbatim to dmenu.",+ "Profiles are stored in the $HOME/.yeganesh directory."]+ parseOptions :: [String] -> Either String Options parseOptions ss = fmap (Options dOpts) p where (opts, dOpts) = fmap (drop 1) . break (== "--") $ ss- p = case getOpt RequireOrder options opts of- (ps, [], []) -> Right . last $ "default" : ps+ p = case onFirst compactFlags $ getOpt RequireOrder options opts of+ (Profile f, [], []) -> Right f+ (Version , [], []) -> Left version+ (Help , [], []) -> Left $ usageInfo introText options (_ , ns, []) -> Left $ "Unknown options: " ++ unwords ns (_ , _ , es) -> Left . concat $ es -- }}}@@ -44,6 +65,9 @@ readPossiblyNonExistent file = catch (Strict.readFile file) (const . return $ "") >>= parseCurrentFormat -- }}} -- pure {{{+onFirst :: (a -> a') -> (a, b, c) -> (a', b, c)+onFirst f (a, b, c) = (f a, b, c)+ sortOn :: Ord b => (a -> b) -> [a] -> [a] sortOn f = map snd . sortBy (comparing fst) . map (f &&& id) @@ -54,6 +78,9 @@ showPriority = unlines . map fst . sortOn descSnd . toList -- decay exponentially, with a one-month half-life+-- The key for decay is that it be monotonic, so that commands will appear in+-- the same order before and after a decay operation; this means we can delay+-- the decay until *after* the user has selected an option. decay :: UTCTime -> UTCTime -> Commands -> Commands decay old new = fmap (/factor) where seconds = fromRational . toRational $ diffUTCTime new old@@ -86,7 +113,7 @@ dmenu :: [String] -> CurrentFormat -> IO CurrentFormat dmenu opts cv@(_, cmds) = do (hIn, hOut, hErr, p) <- runInteractiveProcess "dmenu" opts Nothing Nothing- hPutStrLn hIn (showPriority cmds)+ hPutStr hIn (showPriority cmds) hClose hIn o <- hGetContents hOut e <- hGetContents hErr