cli, addons: reduce boilerplate a little with hledgerCommandMode helper
This commit is contained in:
parent
9f8e96d189
commit
b7092f278b
@ -43,28 +43,20 @@ defchartitems = 10
|
|||||||
defchartsize = "600x400"
|
defchartsize = "600x400"
|
||||||
|
|
||||||
------------------------------------------------------------------------------
|
------------------------------------------------------------------------------
|
||||||
cmdmode :: Mode RawOpts
|
cmdmode = hledgerCommandMode
|
||||||
cmdmode = (defAddonCommandMode "hledger-chart") {
|
[here| chart
|
||||||
modeHelp = [here|
|
Generate a pie chart for the top account balances with the same sign,
|
||||||
generate a pie chart for the top account balances with the same sign,
|
|
||||||
in SVG format.
|
in SVG format.
|
||||||
|
|
||||||
Based on the old hledger-chart package, this is not yet useful.
|
Based on the old hledger-chart package, this is not yet useful.
|
||||||
It's supposed to show only balances of one sign, but this might be broken.
|
It's supposed to show only balances of one sign, but this might be broken.
|
||||||
|]
|
|]
|
||||||
,modeHelpSuffix=lines [here|
|
[flagReq ["chart-output","o"] (\s opts -> Right $ setopt "chart-output" s opts) "IMGFILE" ("output filename (default: "++defchartoutput++")")
|
||||||
|]
|
,flagReq ["chart-items"] (\s opts -> Right $ setopt "chart-items" s opts) "N" ("number of accounts to show (default: "++show defchartitems++")")
|
||||||
,modeGroupFlags = Group {
|
,flagReq ["chart-size"] (\s opts -> Right $ setopt "chart-size" s opts) "WIDTHxHEIGHT" ("image size (default: "++defchartsize++")")
|
||||||
groupNamed = [generalflagsgroup1]
|
] [generalflagsgroup1]
|
||||||
,groupUnnamed = [
|
[]
|
||||||
flagReq ["chart-output","o"] (\s opts -> Right $ setopt "chart-output" s opts) "IMGFILE" ("output filename (default: "++defchartoutput++")")
|
([], Just $ argsFlag "[QUERY]")
|
||||||
,flagReq ["chart-items"] (\s opts -> Right $ setopt "chart-items" s opts) "N" ("number of accounts to show (default: "++show defchartitems++")")
|
|
||||||
,flagReq ["chart-size"] (\s opts -> Right $ setopt "chart-size" s opts) "WIDTHxHEIGHT" ("image size (default: "++defchartsize++")")
|
|
||||||
]
|
|
||||||
,groupHidden = []
|
|
||||||
}
|
|
||||||
,modeArgs = ([], Just $ argsFlag "[QUERY] --add-posting \"ACCT AMTEXPR\" ...")
|
|
||||||
}
|
|
||||||
------------------------------------------------------------------------------
|
------------------------------------------------------------------------------
|
||||||
|
|
||||||
data ChartOpts = ChartOpts {
|
data ChartOpts = ChartOpts {
|
||||||
|
|||||||
@ -13,24 +13,19 @@ import Hledger.Cli
|
|||||||
import Text.Printf
|
import Text.Printf
|
||||||
|
|
||||||
------------------------------------------------------------------------------
|
------------------------------------------------------------------------------
|
||||||
cmdmode =
|
cmdmode = hledgerCommandMode
|
||||||
let m = defAddonCommandMode "check-dates"
|
[here| check-dates
|
||||||
in m {
|
|
||||||
modeHelp = [here|
|
|
||||||
Check that transactions' dates are monotonically increasing.
|
Check that transactions' dates are monotonically increasing.
|
||||||
With --date2, checks secondary dates instead.
|
With --date2, checks secondary dates instead.
|
||||||
With --strict, dates must also be unique.
|
With --strict, dates must also be unique.
|
||||||
With a query, only matched transactions' dates are checked.
|
With a query, only matched transactions' dates are checked.
|
||||||
Reads the default journal file, or another specified with -f.
|
Reads the default journal file, or another specified with -f.
|
||||||
|
FLAGS
|
||||||
|]
|
|]
|
||||||
,modeHelpSuffix=lines [here|
|
[flagNone ["strict"] (\opts -> setboolopt "strict" opts) "makes date comparing strict"]
|
||||||
|]
|
[generalflagsgroup1]
|
||||||
,modeGroupFlags = (modeGroupFlags m) {
|
[]
|
||||||
groupUnnamed = [
|
([], Just $ argsFlag "[QUERY]")
|
||||||
flagNone ["strict"] (\opts -> setboolopt "strict" opts) "makes date comparing strict"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
------------------------------------------------------------------------------
|
------------------------------------------------------------------------------
|
||||||
|
|
||||||
main :: IO ()
|
main :: IO ()
|
||||||
|
|||||||
@ -19,8 +19,8 @@ import Data.String.Here
|
|||||||
import qualified Data.Text as T
|
import qualified Data.Text as T
|
||||||
|
|
||||||
------------------------------------------------------------------------------
|
------------------------------------------------------------------------------
|
||||||
cmdmode = (defAddonCommandMode "dupes") {
|
cmdmode = hledgerCommandMode
|
||||||
modeHelp = [here|
|
[here| dupes
|
||||||
Reports duplicates in the account tree: account names having the same leaf
|
Reports duplicates in the account tree: account names having the same leaf
|
||||||
but different prefixes. In other words, two or more leaves that are
|
but different prefixes. In other words, two or more leaves that are
|
||||||
categorized differently.
|
categorized differently.
|
||||||
@ -28,9 +28,10 @@ Reads the default journal file, or another specified as an argument.
|
|||||||
|
|
||||||
http://stefanorodighiero.net/software/hledger-dupes.html
|
http://stefanorodighiero.net/software/hledger-dupes.html
|
||||||
|]
|
|]
|
||||||
,modeHelpSuffix=lines [here|
|
[]
|
||||||
|]
|
[generalflagsgroup1]
|
||||||
}
|
[]
|
||||||
|
([], Nothing)
|
||||||
------------------------------------------------------------------------------
|
------------------------------------------------------------------------------
|
||||||
|
|
||||||
main = do
|
main = do
|
||||||
|
|||||||
@ -16,17 +16,15 @@ import Hledger.Cli
|
|||||||
|
|
||||||
------------------------------------------------------------------------------
|
------------------------------------------------------------------------------
|
||||||
cmdmode :: Mode RawOpts
|
cmdmode :: Mode RawOpts
|
||||||
cmdmode = (defAddonCommandMode "equity") {
|
cmdmode = hledgerCommandMode
|
||||||
modeHelp = [here|
|
[here| equity
|
||||||
|
|
||||||
Print a "closing balances" transaction that brings all accounts (or with
|
Print a "closing balances" transaction that brings all accounts (or with
|
||||||
query arguments, just the matched accounts) to a zero balance, followed by an
|
query arguments, just the matched accounts) to a zero balance, followed by an
|
||||||
opposite "opening balances" transaction that restores the balances from zero.
|
opposite "opening balances" transaction that restores the balances from zero.
|
||||||
Such transactions can be useful, eg, for bringing account balances across
|
Such transactions can be useful, eg, for bringing account balances across
|
||||||
file boundaries.
|
file boundaries.
|
||||||
|
|
||||||
|]
|
FLAGS
|
||||||
,modeHelpSuffix=lines [here|
|
|
||||||
|
|
||||||
The opening balances transaction is useful to carry over
|
The opening balances transaction is useful to carry over
|
||||||
asset/liability balances if you choose to start a new journal file,
|
asset/liability balances if you choose to start a new journal file,
|
||||||
@ -57,10 +55,11 @@ Open question: how to handle txns spanning a file boundary ? Eg:
|
|||||||
```
|
```
|
||||||
This command might or might not have some connection to the concept of
|
This command might or might not have some connection to the concept of
|
||||||
"closing the books" in accounting.
|
"closing the books" in accounting.
|
||||||
|
|
||||||
|]
|
|]
|
||||||
,modeArgs = ([], Just $ argsFlag "[QUERY]")
|
[]
|
||||||
}
|
[generalflagsgroup1]
|
||||||
|
[]
|
||||||
|
([], Just $ argsFlag "[QUERY]")
|
||||||
------------------------------------------------------------------------------
|
------------------------------------------------------------------------------
|
||||||
|
|
||||||
main :: IO ()
|
main :: IO ()
|
||||||
|
|||||||
@ -14,21 +14,14 @@ import Control.Monad
|
|||||||
import Hledger.Cli
|
import Hledger.Cli
|
||||||
|
|
||||||
------------------------------------------------------------------------------
|
------------------------------------------------------------------------------
|
||||||
cmdmode =
|
cmdmode = hledgerCommandMode
|
||||||
let m = defAddonCommandMode "hledger-prices"
|
[here| prices
|
||||||
in m {
|
|
||||||
modeHelp = [here|
|
|
||||||
Print all prices from the journal.
|
Print all prices from the journal.
|
||||||
|]
|
|]
|
||||||
,modeHelpSuffix=lines [here|
|
[flagNone ["costs"] (setboolopt "costs") "print transaction prices from postings instead of market prices"]
|
||||||
|]
|
[generalflagsgroup1]
|
||||||
,modeArgs = ([], Nothing)
|
[]
|
||||||
,modeGroupFlags = (modeGroupFlags m) {
|
([], Nothing)
|
||||||
groupUnnamed = [
|
|
||||||
flagNone ["costs"] (setboolopt "costs") "print transaction prices from postings instead of market prices"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
------------------------------------------------------------------------------
|
------------------------------------------------------------------------------
|
||||||
|
|
||||||
showPrice :: MarketPrice -> String
|
showPrice :: MarketPrice -> String
|
||||||
|
|||||||
@ -13,11 +13,11 @@ import Data.String.Here
|
|||||||
import Hledger.Cli
|
import Hledger.Cli
|
||||||
|
|
||||||
------------------------------------------------------------------------------
|
------------------------------------------------------------------------------
|
||||||
cmdmode = (defAddonCommandMode "print-unique") {
|
cmdmode = hledgerCommandMode
|
||||||
modeHelp = [here|
|
[here| print-unique
|
||||||
Remove transactions which reuse an already-seen description.
|
Remove transactions which reuse an already-seen description.
|
||||||
|]
|
|
||||||
,modeHelpSuffix=lines [here|
|
FLAGS
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
```shell
|
```shell
|
||||||
@ -31,9 +31,11 @@ $ LEDGER_FILE=unique.journal hledger print-unique
|
|||||||
2015/01/01 test
|
2015/01/01 test
|
||||||
(acct:one) 1
|
(acct:one) 1
|
||||||
```
|
```
|
||||||
|
|
||||||
|]
|
|]
|
||||||
}
|
[]
|
||||||
|
[generalflagsgroup1]
|
||||||
|
[]
|
||||||
|
([], Nothing)
|
||||||
------------------------------------------------------------------------------
|
------------------------------------------------------------------------------
|
||||||
|
|
||||||
main = do
|
main = do
|
||||||
|
|||||||
@ -21,16 +21,17 @@ import Hledger.Cli.CliOptions
|
|||||||
import Hledger.Cli ( withJournalDo, postingsReportAsText )
|
import Hledger.Cli ( withJournalDo, postingsReportAsText )
|
||||||
|
|
||||||
------------------------------------------------------------------------------
|
------------------------------------------------------------------------------
|
||||||
cmdmode = (defAddonCommandMode "register-match") {
|
cmdmode = hledgerCommandMode
|
||||||
modeHelp = [here|
|
[here| register-match
|
||||||
A helper for ledger-autosync. This prints the one posting whose transaction
|
A helper for ledger-autosync. This prints the one posting whose transaction
|
||||||
description is closest to DESC, in the style of the register command.
|
description is closest to DESC, in the style of the register command.
|
||||||
If there are multiple equally good matches, it shows the most recent.
|
If there are multiple equally good matches, it shows the most recent.
|
||||||
Query options (options, not arguments) can be used to restrict the search space.
|
Query options (options, not arguments) can be used to restrict the search space.
|
||||||
|]
|
|]
|
||||||
,modeHelpSuffix=lines [here|
|
[]
|
||||||
|]
|
[generalflagsgroup1]
|
||||||
}
|
[]
|
||||||
|
([], Nothing)
|
||||||
------------------------------------------------------------------------------
|
------------------------------------------------------------------------------
|
||||||
|
|
||||||
main = do
|
main = do
|
||||||
|
|||||||
@ -26,15 +26,11 @@ import qualified Data.Algorithm.Diff as D
|
|||||||
import Hledger.Data.AutoTransaction (runModifierTransaction)
|
import Hledger.Data.AutoTransaction (runModifierTransaction)
|
||||||
|
|
||||||
------------------------------------------------------------------------------
|
------------------------------------------------------------------------------
|
||||||
cmdmode =
|
cmdmode = hledgerCommandMode
|
||||||
let m = (defAddonCommandMode "hledger-rewrite")
|
[here| rewrite
|
||||||
in m {
|
|
||||||
modeHelp = [here|
|
|
||||||
|
|
||||||
Print all transactions, adding custom postings to the matched ones.
|
Print all transactions, adding custom postings to the matched ones.
|
||||||
|
|
||||||
|]
|
FLAGS
|
||||||
,modeHelpSuffix=lines [here|
|
|
||||||
|
|
||||||
This is a start at a generic rewriter of transaction entries.
|
This is a start at a generic rewriter of transaction entries.
|
||||||
It reads the default journal and prints the transactions, like print,
|
It reads the default journal and prints the transactions, like print,
|
||||||
@ -153,24 +149,19 @@ See also:
|
|||||||
https://github.com/simonmichael/hledger/issues/99
|
https://github.com/simonmichael/hledger/issues/99
|
||||||
|
|
||||||
|]
|
|]
|
||||||
,modeArgs = ([], Just $ argsFlag "[QUERY] --add-posting \"ACCT AMTEXPR\" ...")
|
[flagReq ["add-posting"] (\s opts -> Right $ setopt "add-posting" s opts) "'ACCT AMTEXPR'"
|
||||||
,modeGroupFlags = (modeGroupFlags m) {
|
"add a posting to ACCT, which may be parenthesised. AMTEXPR is either a literal amount, or *N which means the transaction's first matched amount multiplied by N (a decimal number). Two spaces separate ACCT and AMTEXPR."
|
||||||
groupUnnamed = [
|
,flagNone ["diff"] (setboolopt "diff") "generate diff suitable as an input for patch tool"
|
||||||
flagReq ["add-posting"] (\s opts -> Right $ setopt "add-posting" s opts) "'ACCT AMTEXPR'"
|
]
|
||||||
"add a posting to ACCT, which may be parenthesised. AMTEXPR is either a literal amount, or *N which means the transaction's first matched amount multiplied by N (a decimal number). Two spaces separate ACCT and AMTEXPR."
|
[generalflagsgroup1]
|
||||||
,flagNone ["diff"] (setboolopt "diff") "generate diff suitable as an input for patch tool"
|
[]
|
||||||
]
|
([], Just $ argsFlag "[QUERY] --add-posting \"ACCT AMTEXPR\" ...")
|
||||||
}
|
|
||||||
}
|
|
||||||
------------------------------------------------------------------------------
|
------------------------------------------------------------------------------
|
||||||
|
|
||||||
-- TODO regex matching and interpolating matched name in replacement
|
-- TODO regex matching and interpolating matched name in replacement
|
||||||
-- TODO interpolating match groups in replacement
|
-- TODO interpolating match groups in replacement
|
||||||
-- TODO allow using this on unbalanced entries, eg to rewrite while editing
|
-- TODO allow using this on unbalanced entries, eg to rewrite while editing
|
||||||
|
|
||||||
outputflags :: [Flag RawOpts]
|
|
||||||
outputflags = [flagNone ["diff"] (setboolopt "diff") "generate diff suitable as an input for patch tool"]
|
|
||||||
|
|
||||||
main :: IO ()
|
main :: IO ()
|
||||||
main = do
|
main = do
|
||||||
opts@CliOpts{rawopts_=rawopts,reportopts_=ropts} <- getHledgerCliOpts cmdmode
|
opts@CliOpts{rawopts_=rawopts,reportopts_=ropts} <- getHledgerCliOpts cmdmode
|
||||||
|
|||||||
@ -20,7 +20,8 @@ module Hledger.Cli.CliOptions (
|
|||||||
generalflagsgroup3,
|
generalflagsgroup3,
|
||||||
defMode,
|
defMode,
|
||||||
defCommandMode,
|
defCommandMode,
|
||||||
defAddonCommandMode,
|
quickAddonCommandMode,
|
||||||
|
hledgerCommandMode,
|
||||||
argsFlag,
|
argsFlag,
|
||||||
showModeUsage,
|
showModeUsage,
|
||||||
withAliases,
|
withAliases,
|
||||||
@ -206,11 +207,13 @@ defCommandMode names = defMode {
|
|||||||
,modeValue=[("command", headDef "" names)]
|
,modeValue=[("command", headDef "" names)]
|
||||||
}
|
}
|
||||||
|
|
||||||
-- | A cmdargs mode suitable for a hledger add-on command with the given name.
|
-- | A cmdargs mode representing the hledger add-on command with the given name.
|
||||||
-- Like defCommandMode, but adds a appropriate short help message if the addon name
|
-- Like defCommandMode, but adds a appropriate short help message if the addon name
|
||||||
-- is recognised, and includes hledger's common input/reporting/help flags as default.
|
-- is recognised, and includes hledger's common input/reporting/help flags as default.
|
||||||
defAddonCommandMode :: Name -> Mode RawOpts
|
-- Just used by hledger for generating the commands list I think (or possibly for
|
||||||
defAddonCommandMode name = (defCommandMode [name]) {
|
-- invoking the addons as well ?)
|
||||||
|
quickAddonCommandMode :: Name -> Mode RawOpts
|
||||||
|
quickAddonCommandMode name = (defCommandMode [name]) {
|
||||||
modeHelp = fromMaybe "" $ lookup (stripAddonExtension name) standardAddonsHelp
|
modeHelp = fromMaybe "" $ lookup (stripAddonExtension name) standardAddonsHelp
|
||||||
,modeGroupFlags = Group {
|
,modeGroupFlags = Group {
|
||||||
groupUnnamed = []
|
groupUnnamed = []
|
||||||
@ -219,6 +222,50 @@ defAddonCommandMode name = (defCommandMode [name]) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
-- | A template for a command's CLI help, influencing the content and layout
|
||||||
|
-- of the usage text generated by a cmdargs mode.
|
||||||
|
-- It is a multiline string structured like so:
|
||||||
|
-- The first line defines the command name (first word) and aliases (any other words).
|
||||||
|
-- From the second line up to a line containing just "FLAGS", or the end, is the preamble,
|
||||||
|
-- displayed above the flags list generated by cmdargs. Short help goes here.
|
||||||
|
-- Any lines after the FLAGS line are the postamble, displayed below the flags list.
|
||||||
|
-- Long help/full manual goes here.
|
||||||
|
type HelpTemplate = String
|
||||||
|
|
||||||
|
-- | Parse a help template into command names, help preamble, and help postamble lines.
|
||||||
|
parseHelpTemplate :: HelpTemplate -> Maybe ([Name], String, [String])
|
||||||
|
parseHelpTemplate t =
|
||||||
|
case lines t of
|
||||||
|
[] -> Nothing
|
||||||
|
(l:ls) -> Just (names, preamble, postamblelines)
|
||||||
|
where
|
||||||
|
names = words l
|
||||||
|
(preamblels, postamblels) = break (== "FLAGS") ls
|
||||||
|
preamble = unlines $ reverse $ dropWhile null $ reverse preamblels
|
||||||
|
postamblelines = dropWhile null $ drop 1 postamblels
|
||||||
|
|
||||||
|
-- | Build a cmdarg mode suitable for a hledger add-on command,
|
||||||
|
-- from a help template and flag/argument specifications.
|
||||||
|
-- Reduces boilerplate a little, though the complicated cmdargs
|
||||||
|
-- flag and argument specs are still required.
|
||||||
|
-- See the addons in bin/ for examples of usage.
|
||||||
|
hledgerCommandMode :: HelpTemplate -> [Flag RawOpts] -> [(Help, [Flag RawOpts])]
|
||||||
|
-> [Flag RawOpts] -> ([Arg RawOpts], Maybe (Arg RawOpts)) -> Mode RawOpts
|
||||||
|
hledgerCommandMode tmpl ungroupedflags groupedflags hiddenflags args =
|
||||||
|
case parseHelpTemplate tmpl of
|
||||||
|
Nothing -> error' $ "Could not parse help template:\n"++tmpl++"\n"
|
||||||
|
Just (names, preamble, postamblelines) ->
|
||||||
|
(defCommandMode names) {
|
||||||
|
modeHelp = preamble
|
||||||
|
,modeHelpSuffix = postamblelines
|
||||||
|
,modeGroupFlags = Group {
|
||||||
|
groupUnnamed = ungroupedflags
|
||||||
|
,groupNamed = groupedflags
|
||||||
|
,groupHidden = hiddenflags
|
||||||
|
}
|
||||||
|
,modeArgs = args
|
||||||
|
}
|
||||||
|
|
||||||
-- | Built-in descriptions for some of the known addons.
|
-- | Built-in descriptions for some of the known addons.
|
||||||
standardAddonsHelp :: [(String,String)]
|
standardAddonsHelp :: [(String,String)]
|
||||||
standardAddonsHelp = [
|
standardAddonsHelp = [
|
||||||
|
|||||||
@ -99,7 +99,7 @@ mainmode addons = defMode {
|
|||||||
])
|
])
|
||||||
]
|
]
|
||||||
++ case addons of [] -> []
|
++ case addons of [] -> []
|
||||||
cs -> [("\nAdd-on commands", map defAddonCommandMode cs)]
|
cs -> [("\nAdd-on commands", map quickAddonCommandMode cs)]
|
||||||
-- modes in the unnamed group, shown first without a heading:
|
-- modes in the unnamed group, shown first without a heading:
|
||||||
,groupUnnamed = [
|
,groupUnnamed = [
|
||||||
helpmode
|
helpmode
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user