addons: try to be smarter about showing file extensions

We now hide add-ons' file extensions in the commands list except when
they are needed for disambiguation. There are three cases:

- when an add-on exists with only one file extension, the extension is
  not displayed.

- when an add-on has exactly two variants, one with the .[l]hs extension
  and the other with none or .exe - presumably the source and compiled
  versions - we omit the source version from the list.

- otherwise when an add-on has multiple variants differing by file
  extension, they are listed with their extensions displayed.
This commit is contained in:
Simon Michael 2014-04-26 10:25:32 -07:00
parent eeb48c86d1
commit 9a255051e8

View File

@ -65,6 +65,7 @@ import System.Console.CmdArgs.Text
import System.Directory import System.Directory
import System.Environment import System.Environment
import System.Exit (exitSuccess) import System.Exit (exitSuccess)
import System.FilePath (takeExtension)
import Test.HUnit import Test.HUnit
import Text.ParserCombinators.Parsec as P import Text.ParserCombinators.Parsec as P
@ -392,28 +393,36 @@ widthp = (string "auto" >> return Auto)
-- Other utils -- Other utils
-- | Get the unique suffixes (without hledger-) of hledger-* executables -- | Like getHledgerExesInPath, but convert the filenames to unique add-on names for the commands list.
-- found in the current user's PATH, or the empty list if there is any -- An add-on name is the filename without the "hledger-" prefix, and usually without the file extension.
-- problem. -- Exceptions:
-- - when there are multiple filenames differing only by file extension, their extensions are preserved
-- - when there are two variants, one with .[l]hs extension and one with none or .exe, omit the former.
--
getHledgerAddonCommands :: IO [String] getHledgerAddonCommands :: IO [String]
getHledgerAddonCommands = map (drop (length progname + 1)) `fmap` getHledgerExesInPath getHledgerAddonCommands = do
exes <- getHledgerExesInPath
let stripprefix = drop (length progname + 1)
addons = map stripprefix exes
groups = groupBy (\a b -> stripAddonExtension a == stripAddonExtension b) addons
stripext [f] = [stripAddonExtension f]
stripext [f,f2] | takeExtension f `elem` ["",".exe"] && takeExtension f2 `elem` [".hs",".lhs"] = [stripAddonExtension f]
stripext fs = fs
addons' = concatMap stripext groups
return addons'
-- | Get the unique names (including extension) of hledger add-ons -- | Get the sorted unique filenames of all hledger executables
-- (executables, named hledger-*, with no extension or one of the -- in the current user's PATH (files, named hledger-*, with either no
-- addonExtensions) found in the current user's PATH, or the empty -- extension (and no periods in the name) or one of the addonExtensions).
-- list if there is a problem. -- If there is any problem, return the empty list.
getHledgerExesInPath :: IO [String] getHledgerExesInPath :: IO [String]
getHledgerExesInPath = do getHledgerExesInPath = do
pathdirs <- regexSplit "[:;]" `fmap` getEnvSafe "PATH" pathdirs <- regexSplit "[:;]" `fmap` getEnvSafe "PATH"
pathfiles <- concat `fmap` mapM getDirectoryContentsSafe pathdirs pathfiles <- concat `fmap` mapM getDirectoryContentsSafe pathdirs
let hledgernamed = return $ nub $ sort $ filter isHledgerExeName pathfiles
-- nubBy (\a b -> stripAddonExtension a == stripAddonExtension b) $ -- XXX should exclude directories and files without execute permission.
nub $
sort $ filter isHledgerExeName pathfiles
return hledgernamed
-- Exclude directories and files without execute permission.
-- These will do a stat for each hledger-*, probably ok. -- These will do a stat for each hledger-*, probably ok.
-- They also need the path.. -- But they need paths, not just filenames
-- hledgerexes <- filterM doesFileExist hledgernamed -- hledgerexes <- filterM doesFileExist hledgernamed
-- hledgerexes' <- filterM isExecutable hledgerexes -- hledgerexes' <- filterM isExecutable hledgerexes
-- return hledgerexes -- return hledgerexes