cli: first of several cleanups; separate commands list & usage (#297)
This commit is contained in:
		
							parent
							
								
									e24eb155e7
								
							
						
					
					
						commit
						895a66eb06
					
				| @ -102,8 +102,8 @@ import Hledger.Cli.Version | |||||||
| -- | Common help flags: --help, --debug, --version... | -- | Common help flags: --help, --debug, --version... | ||||||
| helpflags :: [Flag RawOpts] | helpflags :: [Flag RawOpts] | ||||||
| helpflags = [ | helpflags = [ | ||||||
|   flagNone ["h"]    (setboolopt "h")    "show general usage or (after COMMAND, the command's usage" |   flagNone ["h"]    (setboolopt "h")    "show general usage or (after CMD, the command's usage" | ||||||
|  ,flagNone ["help"] (setboolopt "help") "show the current program's manual as plain text (or after an add-on COMMAND, the add-on's manual)" |  ,flagNone ["help"] (setboolopt "help") "show the current program's manual as plain text (or after an addon CMD, the add-on's manual)" | ||||||
|  ,flagNone ["man"]  (setboolopt "man")  "show the current program's manual with man" |  ,flagNone ["man"]  (setboolopt "man")  "show the current program's manual with man" | ||||||
|  ,flagNone ["info"] (setboolopt "info") "show the current program's manual with info" |  ,flagNone ["info"] (setboolopt "info") "show the current program's manual with info" | ||||||
|  -- ,flagNone ["browse-args"] (setboolopt "browse-args") "use a web UI to select options and build up a command line" |  -- ,flagNone ["browse-args"] (setboolopt "browse-args") "use a web UI to select options and build up a command line" | ||||||
|  | |||||||
| @ -36,11 +36,15 @@ See "Hledger.Data.Ledger" for more examples. | |||||||
| 
 | 
 | ||||||
| -} | -} | ||||||
| 
 | 
 | ||||||
|  | {-# LANGUAGE QuasiQuotes #-} | ||||||
|  | 
 | ||||||
| module Hledger.Cli.Main where | module Hledger.Cli.Main where | ||||||
| 
 | 
 | ||||||
| -- import Control.Monad | -- import Control.Monad | ||||||
| import Data.Char (isDigit) | import Data.Char (isDigit) | ||||||
|  | import Data.String.Here | ||||||
| import Data.List | import Data.List | ||||||
|  | import Data.List.Split (splitOn) | ||||||
| import Safe | import Safe | ||||||
| import System.Console.CmdArgs.Explicit as C | import System.Console.CmdArgs.Explicit as C | ||||||
| import System.Environment | import System.Environment | ||||||
| @ -76,52 +80,63 @@ import Hledger.Utils | |||||||
| 
 | 
 | ||||||
| -- | The overall cmdargs mode describing command-line options for hledger. | -- | The overall cmdargs mode describing command-line options for hledger. | ||||||
| mainmode addons = defMode { | mainmode addons = defMode { | ||||||
|   modeNames = [progname] |   modeNames = [progname ++ " [CMD]"] | ||||||
|  ,modeHelp = unlines [] |  | ||||||
|  ,modeHelpSuffix = [""] |  | ||||||
|  ,modeArgs = ([], Just $ argsFlag "[ARGS]") |  ,modeArgs = ([], Just $ argsFlag "[ARGS]") | ||||||
|  |  ,modeHelp = unlines ["hledger's command line interface"] | ||||||
|  ,modeGroupModes = Group { |  ,modeGroupModes = Group { | ||||||
|     -- modes (commands) in named groups: |     -- subcommands in the unnamed group, shown first: | ||||||
|     groupNamed = [ |     groupUnnamed = [ | ||||||
|       ("Data entry commands", [ |  | ||||||
|         addmode |  | ||||||
|        ]) |  | ||||||
|      ,("\nReporting commands", [ |  | ||||||
|         printmode |  | ||||||
|        ,accountsmode |  | ||||||
|        ,balancemode |  | ||||||
|        ,registermode |  | ||||||
|        ,incomestatementmode |  | ||||||
|        ,balancesheetmode |  | ||||||
|        ,cashflowmode |  | ||||||
|        ,activitymode |  | ||||||
|        ,statsmode |  | ||||||
|        ]) |  | ||||||
|      ] |      ] | ||||||
|      ++ case addons of [] -> [] |     -- subcommands in named groups: | ||||||
|                        cs -> [("\nAdd-on commands", map quickAddonCommandMode cs)] |    ,groupNamed = [ | ||||||
|     -- modes in the unnamed group, shown first without a heading: |  | ||||||
|    ,groupUnnamed = [ |  | ||||||
|         helpmode |  | ||||||
|        ,manmode |  | ||||||
|        ,infomode |  | ||||||
|      ] |      ] | ||||||
|     -- modes handled but not shown |     -- subcommands handled but not shown in the help: | ||||||
|    ,groupHidden = [ |    ,groupHidden = [ | ||||||
|         testmode |       oldconvertmode | ||||||
|        ,oldconvertmode |      ,accountsmode | ||||||
|      ] |      ,activitymode | ||||||
|  |      ,addmode | ||||||
|  |      ,balancemode | ||||||
|  |      ,balancesheetmode | ||||||
|  |      ,cashflowmode | ||||||
|  |      ,helpmode | ||||||
|  |      ,incomestatementmode | ||||||
|  |      ,infomode | ||||||
|  |      ,manmode | ||||||
|  |      ,printmode | ||||||
|  |      ,registermode | ||||||
|  |      ,statsmode | ||||||
|  |      ,testmode | ||||||
|  |      ] ++ map quickAddonCommandMode addons | ||||||
|    } |    } | ||||||
|  ,modeGroupFlags = Group { |  ,modeGroupFlags = Group { | ||||||
|      -- flags in named groups: |      -- flags in named groups: | ||||||
|      groupNamed = [generalflagsgroup3] |      groupNamed = [ | ||||||
|      -- flags in the unnamed group, shown last without a heading: |         (  "General input flags",     inputflags) | ||||||
|  |        ,("\nGeneral reporting flags", reportflags) | ||||||
|  |        ,("\nGeneral help flags",      helpflags) | ||||||
|  |        ] | ||||||
|  |      -- flags in the unnamed group, shown last: | ||||||
|     ,groupUnnamed = [] |     ,groupUnnamed = [] | ||||||
|      -- flags accepted but not shown in the help: |      -- flags handled but not shown in the help: | ||||||
|     ,groupHidden = |     ,groupHidden = | ||||||
|         detailedversionflag : |         [detailedversionflag] | ||||||
|         inputflags -- included here so they'll not raise a confusing error if present with no COMMAND |         -- ++ inputflags -- included here so they'll not raise a confusing error if present with no COMMAND | ||||||
|     } |     } | ||||||
|  |  ,modeHelpSuffix = lines $ regexReplace "PROGNAME" progname [here|Examples: | ||||||
|  | PROGNAME                         list commands | ||||||
|  | PROGNAME CMD [--] [OPTS] [ARGS]  run a command (use -- with addon commands) | ||||||
|  | PROGNAME-CMD [OPTS] [ARGS]       or run addon commands directly | ||||||
|  | PROGNAME -h                      hledger usage | ||||||
|  | PROGNAME CMD -h                  command usage | ||||||
|  | PROGNAME --help                  PROGNAME manual | ||||||
|  | PROGNAME --man                   PROGNAME manual as man page | ||||||
|  | PROGNAME --info                  PROGNAME manual as info manual | ||||||
|  | PROGNAME help                    list help topics | ||||||
|  | PROGNAME help TOPIC              TOPIC manual | ||||||
|  | PROGNAME man  TOPIC              TOPIC manual as man page | ||||||
|  | PROGNAME info TOPIC              TOPIC manual as info manual | ||||||
|  | |] | ||||||
|  } |  } | ||||||
| 
 | 
 | ||||||
| oldconvertmode = (defCommandMode ["convert"]) { | oldconvertmode = (defCommandMode ["convert"]) { | ||||||
| @ -160,8 +175,8 @@ argsToCliOpts args addons = do | |||||||
| -- | -- | ||||||
| -- Since we're not parsing flags as precisely as cmdargs here, this is | -- Since we're not parsing flags as precisely as cmdargs here, this is | ||||||
| -- imperfect. We make a decent effort to: | -- imperfect. We make a decent effort to: | ||||||
| -- - move all no-argument help and input flags | -- - move all no-argument help/input/report flags | ||||||
| -- - move all required-argument help and input flags along with their values, space-separated or not | -- - move all required-argument help/input/report flags along with their values, space-separated or not | ||||||
| -- - not confuse things further or cause misleading errors. | -- - not confuse things further or cause misleading errors. | ||||||
| moveFlagsAfterCommand :: [String] -> [String] | moveFlagsAfterCommand :: [String] -> [String] | ||||||
| moveFlagsAfterCommand args = moveArgs $ ensureDebugHasArg args | moveFlagsAfterCommand args = moveArgs $ ensureDebugHasArg args | ||||||
| @ -197,11 +212,93 @@ isValue "-"     = True | |||||||
| isValue ('-':_) = False | isValue ('-':_) = False | ||||||
| isValue _       = True | isValue _       = True | ||||||
| 
 | 
 | ||||||
| flagstomove = inputflags ++ helpflags | flagstomove = inputflags ++ reportflags ++ helpflags | ||||||
| noargflagstomove  = concatMap flagNames $ filter ((==FlagNone).flagInfo) flagstomove | noargflagstomove  = concatMap flagNames $ filter ((==FlagNone).flagInfo) flagstomove | ||||||
| reqargflagstomove = -- filter (/= "debug") $ | reqargflagstomove = -- filter (/= "debug") $ | ||||||
|                     concatMap flagNames $ filter ((==FlagReq ).flagInfo) flagstomove |                     concatMap flagNames $ filter ((==FlagReq ).flagInfo) flagstomove | ||||||
| 
 | 
 | ||||||
|  | -- | Template for the commands list. Includes an entry for known (or | ||||||
|  | -- hypothetical) builtin and addon commands; these will be filtered | ||||||
|  | -- based on the commands found at runtime.  COUNT is replaced with the | ||||||
|  | -- number of commands found.  OTHERCMDS is replaced with an entry for | ||||||
|  | -- each unknown addon command found. The command descriptions here | ||||||
|  | -- should be synced with the commands' builtin help and the command | ||||||
|  | -- list in the hledger manual. | ||||||
|  | commandsListTemplate :: String | ||||||
|  | commandsListTemplate = [here|Commands available (COUNT): | ||||||
|  | 
 | ||||||
|  | Standard reports: | ||||||
|  |  accounts             show chart of accounts | ||||||
|  |  balancesheet (bs)    show a balance sheet | ||||||
|  |  cashflow (cf)        show a cashflow statement | ||||||
|  |  incomestatement (is) show an income statement | ||||||
|  |  transactions (txns)  show transactions in some account | ||||||
|  | 
 | ||||||
|  | General reporting: | ||||||
|  |  activity             show a bar chart of posting counts per interval | ||||||
|  |  balance (bal)        show accounts and balances | ||||||
|  |  budget               add automated postings/txns/bucket accts (experimental) | ||||||
|  |  chart                generate simple balance pie charts (experimental) | ||||||
|  |  check                check more powerful balance assertions | ||||||
|  |  check-dates          check transactions are ordered by date | ||||||
|  |  check-dupes          check for accounts with the same leaf name | ||||||
|  |  irr                  calculate internal rate of return of an investment | ||||||
|  |  prices               show market price records | ||||||
|  |  print                show transaction journal entries | ||||||
|  |  print-unique         show only transactions with unique descriptions | ||||||
|  |  register (reg)       show postings and running total | ||||||
|  |  register-match       show best matching transaction for a description | ||||||
|  |  stats                show some journal statistics | ||||||
|  | 
 | ||||||
|  | Interfaces: | ||||||
|  |  add                  console ui for adding transactions | ||||||
|  |  api                  web api server | ||||||
|  |  iadd                 curses ui for adding transactions | ||||||
|  |  ui                   curses ui | ||||||
|  |  web                  web ui | ||||||
|  | 
 | ||||||
|  | Misc: | ||||||
|  |  autosync             download/deduplicate/convert OFX data | ||||||
|  |  equity               generate transactions to zero & restore account balances | ||||||
|  |  interest             generate interest transactions | ||||||
|  |  rewrite              add automated postings to certain transactions | ||||||
|  |  test                 run some self tests | ||||||
|  | OTHERCMDS | ||||||
|  | 
 | ||||||
|  | Help: (see also -h, CMD -h, --help|---man|--info) | ||||||
|  |  help|man|info        show any of the hledger manuals in text/man/info format | ||||||
|  | |] | ||||||
|  | 
 | ||||||
|  | knownCommands :: [String] | ||||||
|  | knownCommands = sort $ commandsFromCommandsList commandsListTemplate | ||||||
|  | 
 | ||||||
|  | -- | Extract the command names from a commands list like the above: | ||||||
|  | -- the first word (or words separated by |) of lines beginning with a space. | ||||||
|  | commandsFromCommandsList :: String -> [String] | ||||||
|  | commandsFromCommandsList s = concatMap (splitOn "|") [w | ' ':l <- lines s, let w:_ = words l] | ||||||
|  | 
 | ||||||
|  | -- | Print the commands list, modifying the template above based on | ||||||
|  | -- the currently available addons. Missing addons will be removed, and | ||||||
|  | -- extra addons will be added under Misc. | ||||||
|  | printCommandsList :: [String] -> IO () | ||||||
|  | printCommandsList addonsFound = putStr commandsList | ||||||
|  |   where | ||||||
|  |     commandsFound = builtinCommandNames ++ addonsFound | ||||||
|  |     unknownCommandsFound = addonsFound \\ knownCommands | ||||||
|  | 
 | ||||||
|  |     adjustline (' ':l) | not $ w `elem` commandsFound = [] | ||||||
|  |       where w = takeWhile (not . (`elem` "| ")) l | ||||||
|  |     adjustline l = [l] | ||||||
|  | 
 | ||||||
|  |     commandsList1 = | ||||||
|  |       regexReplace "OTHERCMDS" (init $ unlines [' ':w | w <- unknownCommandsFound]) $ | ||||||
|  |       unlines $ concatMap adjustline $ lines commandsListTemplate | ||||||
|  | 
 | ||||||
|  |     commandsList = | ||||||
|  |       regexReplace "COUNT" (show $ length $ commandsFromCommandsList commandsList1) | ||||||
|  |       commandsList1 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
| -- | Let's go. | -- | Let's go. | ||||||
| main :: IO () | main :: IO () | ||||||
| main = do | main = do | ||||||
| @ -234,21 +331,21 @@ main = do | |||||||
|   dbgIO "raw args after command" argsaftercmd |   dbgIO "raw args after command" argsaftercmd | ||||||
| 
 | 
 | ||||||
|   -- Search PATH for add-ons, excluding any that match built-in command names |   -- Search PATH for add-ons, excluding any that match built-in command names | ||||||
|   addonNames' <- hledgerAddons |   addons' <- hledgerAddons | ||||||
|   let addonNames = filter (not . (`elem` builtinCommandNames) . dropExtension) addonNames' |   let addons = filter (not . (`elem` builtinCommandNames) . dropExtension) addons' | ||||||
| 
 | 
 | ||||||
|   -- parse arguments with cmdargs |   -- parse arguments with cmdargs | ||||||
|   opts <- argsToCliOpts args addonNames |   opts <- argsToCliOpts args addons | ||||||
| 
 | 
 | ||||||
|   -- select an action and run it. |   -- select an action and run it. | ||||||
|   let |   let | ||||||
|     cmd                  = command_ opts -- the full matched internal or external command name, if any |     cmd                  = command_ opts -- the full matched internal or external command name, if any | ||||||
|     isInternalCommand    = cmd `elem` builtinCommandNames -- not (null cmd) && not (cmd `elem` addons) |     isInternalCommand    = cmd `elem` builtinCommandNames -- not (null cmd) && not (cmd `elem` addons) | ||||||
|     isExternalCommand    = not (null cmd) && cmd `elem` addonNames -- probably |     isExternalCommand    = not (null cmd) && cmd `elem` addons -- probably | ||||||
|     isBadCommand         = not (null rawcmd) && null cmd |     isBadCommand         = not (null rawcmd) && null cmd | ||||||
|     hasVersion           = ("--version" `elem`) |     hasVersion           = ("--version" `elem`) | ||||||
|     hasDetailedVersion   = ("--version+" `elem`) |     hasDetailedVersion   = ("--version+" `elem`) | ||||||
|     printUsage           = putStr $ showModeUsage $ mainmode addonNames |     printUsage           = putStr $ showModeUsage $ mainmode addons | ||||||
|     badCommandError      = error' ("command "++rawcmd++" is not recognized, run with no command to see a list") >> exitFailure |     badCommandError      = error' ("command "++rawcmd++" is not recognized, run with no command to see a list") >> exitFailure | ||||||
|     hasShortHelpFlag args = any (`elem` args) ["-h"] |     hasShortHelpFlag args = any (`elem` args) ["-h"] | ||||||
|     hasLongHelpFlag args = any (`elem` args) ["--help"] |     hasLongHelpFlag args = any (`elem` args) ["--help"] | ||||||
| @ -276,16 +373,16 @@ main = do | |||||||
|     runHledgerCommand |     runHledgerCommand | ||||||
|       -- high priority flags and situations. -h, then --help, then --info are highest priority. |       -- high priority flags and situations. -h, then --help, then --info are highest priority. | ||||||
|       | hasShortHelpFlag argsbeforecmd = dbgIO "" "-h before command, showing general usage" >> printUsage |       | hasShortHelpFlag argsbeforecmd = dbgIO "" "-h before command, showing general usage" >> printUsage | ||||||
|       | hasLongHelpFlag  argsbeforecmd = dbgIO "" "--help before command, showing general manual" >> printHelpForTopic (topicForMode $ mainmode addonNames) |       | hasLongHelpFlag  argsbeforecmd = dbgIO "" "--help before command, showing general manual" >> printHelpForTopic (topicForMode $ mainmode addons) | ||||||
|       | hasManFlag       argsbeforecmd = dbgIO "" "--man before command, showing general manual with man" >> runManForTopic (topicForMode $ mainmode addonNames) |       | hasManFlag       argsbeforecmd = dbgIO "" "--man before command, showing general manual with man" >> runManForTopic (topicForMode $ mainmode addons) | ||||||
|       | hasInfoFlag      argsbeforecmd = dbgIO "" "--info before command, showing general manual with info" >> runInfoForTopic (topicForMode $ mainmode addonNames) |       | hasInfoFlag      argsbeforecmd = dbgIO "" "--info before command, showing general manual with info" >> runInfoForTopic (topicForMode $ mainmode addons) | ||||||
|       | not (hasSomeHelpFlag argsaftercmd) && (hasVersion argsbeforecmd || (hasVersion argsaftercmd && isInternalCommand)) |       | not (hasSomeHelpFlag argsaftercmd) && (hasVersion argsbeforecmd || (hasVersion argsaftercmd && isInternalCommand)) | ||||||
|                                  = putStrLn prognameandversion |                                  = putStrLn prognameandversion | ||||||
|       | not (hasSomeHelpFlag argsaftercmd) && (hasDetailedVersion argsbeforecmd || (hasDetailedVersion argsaftercmd && isInternalCommand)) |       | not (hasSomeHelpFlag argsaftercmd) && (hasDetailedVersion argsbeforecmd || (hasDetailedVersion argsaftercmd && isInternalCommand)) | ||||||
|                                  = putStrLn prognameanddetailedversion |                                  = putStrLn prognameanddetailedversion | ||||||
|       -- \| (null externalcmd) && "binary-filename" `inRawOpts` rawopts = putStrLn $ binaryfilename progname |       -- \| (null externalcmd) && "binary-filename" `inRawOpts` rawopts = putStrLn $ binaryfilename progname | ||||||
|       -- \| "--browse-args" `elem` args     = System.Console.CmdArgs.Helper.execute "cmdargs-browser" mainmode' args >>= (putStr . show) |       -- \| "--browse-args" `elem` args     = System.Console.CmdArgs.Helper.execute "cmdargs-browser" mainmode' args >>= (putStr . show) | ||||||
|       | isNullCommand            = dbgIO "" "no command, showing general usage" >> printUsage |       | isNullCommand            = dbgIO "" "no command, showing commands list" >> printCommandsList addons | ||||||
|       | isBadCommand             = badCommandError |       | isBadCommand             = badCommandError | ||||||
| 
 | 
 | ||||||
|       -- internal commands |       -- internal commands | ||||||
|  | |||||||
| @ -87,6 +87,7 @@ library | |||||||
|     , directory |     , directory | ||||||
|     , file-embed >=0.0.10 && <0.1 |     , file-embed >=0.0.10 && <0.1 | ||||||
|     , filepath |     , filepath | ||||||
|  |     , here | ||||||
|     , pretty-show >=1.6.4 |     , pretty-show >=1.6.4 | ||||||
|     , process |     , process | ||||||
|     , temporary |     , temporary | ||||||
| @ -171,6 +172,7 @@ executable hledger | |||||||
|     , directory |     , directory | ||||||
|     , file-embed >=0.0.10 && <0.1 |     , file-embed >=0.0.10 && <0.1 | ||||||
|     , filepath |     , filepath | ||||||
|  |     , here | ||||||
|     , pretty-show >=1.6.4 |     , pretty-show >=1.6.4 | ||||||
|     , process |     , process | ||||||
|     , temporary |     , temporary | ||||||
| @ -232,6 +234,7 @@ test-suite test | |||||||
|     , directory |     , directory | ||||||
|     , file-embed >=0.0.10 && <0.1 |     , file-embed >=0.0.10 && <0.1 | ||||||
|     , filepath |     , filepath | ||||||
|  |     , here | ||||||
|     , pretty-show >=1.6.4 |     , pretty-show >=1.6.4 | ||||||
|     , process |     , process | ||||||
|     , temporary |     , temporary | ||||||
| @ -292,6 +295,7 @@ benchmark bench | |||||||
|     , directory |     , directory | ||||||
|     , file-embed >=0.0.10 && <0.1 |     , file-embed >=0.0.10 && <0.1 | ||||||
|     , filepath |     , filepath | ||||||
|  |     , here | ||||||
|     , pretty-show >=1.6.4 |     , pretty-show >=1.6.4 | ||||||
|     , process |     , process | ||||||
|     , temporary |     , temporary | ||||||
|  | |||||||
| @ -68,6 +68,7 @@ dependencies: | |||||||
| - directory | - directory | ||||||
| - file-embed >=0.0.10 && <0.1 | - file-embed >=0.0.10 && <0.1 | ||||||
| - filepath | - filepath | ||||||
|  | - here | ||||||
| - pretty-show >=1.6.4 | - pretty-show >=1.6.4 | ||||||
| - process | - process | ||||||
| - temporary | - temporary | ||||||
|  | |||||||
| @ -71,63 +71,67 @@ hledger balance --version | |||||||
| 
 | 
 | ||||||
| # help | # help | ||||||
| 
 | 
 | ||||||
| # 3. with no command, show general help | # 3. with no command, show commands list | ||||||
| hledger | hledger | ||||||
| >>> /^hledger \[COMMAND\]/ | >>> /^Commands available/ | ||||||
| >>>=0 | >>>=0 | ||||||
| 
 | 
 | ||||||
| # 4. no-command help still works if there are flags, at least the common ones | # 4. no-command help still works if there are flags, at least the common ones | ||||||
| hledger -fsomefile | hledger -fsomefile | ||||||
| >>> /^hledger \[COMMAND\]/ | >>> /^Commands available/ | ||||||
| >>>=0 | >>>=0 | ||||||
| 
 | 
 | ||||||
| # 5. and also with a space between flag and value | # 5. and also with a space between flag and value | ||||||
| hledger -f somefile | hledger -f somefile | ||||||
| >>> /^hledger \[COMMAND\]/ | >>> /^Commands available/ | ||||||
| >>>=0 | >>>=0 | ||||||
| 
 | 
 | ||||||
| # 6. with -h, and possibly other common flags present, show general usage | # 6. with -h, and possibly other common flags present, show general usage | ||||||
| hledger -h --version -f /dev/null | hledger -h --version -f /dev/null | ||||||
| >>> /^hledger \[COMMAND\]/ | >>> /^hledger \[CMD\]/ | ||||||
| >>>=0 | >>>=0 | ||||||
| 
 | 
 | ||||||
| # 7. with -h before COMMAND, show general usage | # 7. with -h before COMMAND, show general usage | ||||||
| hledger -h balance --cost | hledger -h balance --cost | ||||||
| >>> /^hledger \[COMMAND\]/ | >>> /^hledger \[CMD\]/ | ||||||
| >>>=0 | >>>=0 | ||||||
| 
 | 
 | ||||||
| # 8. with -h after command, show command usage | # 8. with -h after command, show command usage | ||||||
| hledger balance -h | hledger balance -h | ||||||
| >>> /^balance \[OPTIONS\]/ | >>> /balance \[OPTIONS\]/ | ||||||
| >>>=0 | >>>=0 | ||||||
| 
 | 
 | ||||||
| # 9. should work with deprecated commands too | # 9. with an unrecognised command, give an error and non-zero exit status | ||||||
| hledger convert -h |  | ||||||
| >>> |  | ||||||
| >>>2 /no longer needed/ |  | ||||||
| >>>=1 |  | ||||||
| 
 |  | ||||||
| # 10. with an unrecognised command, give general usage and non-zero exit status |  | ||||||
| hledger nosuchcommand | hledger nosuchcommand | ||||||
| >>> | >>> | ||||||
| >>>2 /not recognized/ | >>>2 /not recognized.*to see a list/ | ||||||
| >>>=1 | >>>=1 | ||||||
| 
 | 
 | ||||||
| # flag positions | # flag positions | ||||||
| 
 | 
 | ||||||
| # 11. most flags can not go before command | # 10. general flags can go before command | ||||||
| hledger --daily register | hledger -f /dev/null --alias somealiases --rules-file -h --help --version --debug 1 --daily register | ||||||
| >>> | >>> /^hledger \[CMD\]/ | ||||||
| >>>2 /Unknown flag: --daily/ |  | ||||||
| >>>=1 |  | ||||||
| 
 |  | ||||||
| # 12. help and input flags can go before command |  | ||||||
| hledger -f /dev/null --alias somealiases --rules-file -h --help --version --debug 1 register --daily |  | ||||||
| >>> /^hledger \[COMMAND\]/ |  | ||||||
| >>>=0 | >>>=0 | ||||||
| 
 | 
 | ||||||
| # 13. or after it, and spaces in options are optional | # 11. or after it, and spaces in options are optional | ||||||
| hledger register -f/dev/null --alias=somealiases --rules-file -h --version --debug 1 --daily | hledger register -f/dev/null --alias=somealiases --rules-file -h --version --debug 1 --daily | ||||||
| >>> /^register \[OPTIONS\]/ | >>> /^register \[OPTIONS\]/ | ||||||
| >>>=0 | >>>=0 | ||||||
| 
 | 
 | ||||||
|  | # 12. general flags before command should work | ||||||
|  | hledger -f /dev/null --daily register | ||||||
|  | >>> | ||||||
|  | >>>=0 | ||||||
|  | 
 | ||||||
|  | # 13. command-specific flags can go after command | ||||||
|  | hledger -f /dev/null register --daily | ||||||
|  | >>> | ||||||
|  | >>>=0 | ||||||
|  | 
 | ||||||
|  | # 14. but not before it | ||||||
|  | hledger --related register | ||||||
|  | >>> | ||||||
|  | >>>2 /Unknown flag: --related/ | ||||||
|  | >>>=1 | ||||||
|  | 
 | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user