;bin: hledger-script-example.hs: improvements, cleanups
This commit is contained in:
parent
46c58a45dc
commit
d20d2571f8
@ -1,143 +1,128 @@
|
||||
#!/usr/bin/env stack
|
||||
-- stack runghc --verbosity error --package hledger
|
||||
-- stack runghc --package hledger
|
||||
-------------------------------------------------------------------------------
|
||||
-- About this script. You can remove this text. See also hledger-script-example-short.hs.
|
||||
--
|
||||
-- This is an example of a hledger addon command (an executable named hledger-*),
|
||||
-- implemented as a haskell script which can use hledger's API.
|
||||
-- Save it as a different name, give it execute permission, and customise it.
|
||||
--
|
||||
-- This script is run by stack. You can use any of the commands below:
|
||||
--
|
||||
-- The `stack runghc` command runs within a hledger source tree, using that local hledger version.
|
||||
-- It installs haskell packages and GHC if needed, from the stackage snapshot configured in the stack.yaml file.
|
||||
-- stack runghc --package hledger
|
||||
--
|
||||
-- The `stack script` command installs known hledger, haskell package and GHC versions from a specified stackage snapshot.
|
||||
-- This is the most robust setup. --verbosity=info shows install progress. --compile makes a standalone binary.
|
||||
-- stack script --snapshot lts-23.0 --verbosity=error --package hledger
|
||||
-- stack script --snapshot nightly-2024-12-16 --compile --verbosity=error --package hledger
|
||||
--
|
||||
-- Or the script can be run by cabal, which installs packages if needed (but not GHC).
|
||||
-- #!/usr/bin/env cabal
|
||||
-- {- cabal:
|
||||
-- build-depends: base, directory, text, hledger
|
||||
-- -}
|
||||
--
|
||||
-- If compiled to a binary, the script will run without stack or cabal or haskell packages.
|
||||
-- (It will still require certain C libraries.)
|
||||
-------------------------------------------------------------------------------
|
||||
{-
|
||||
|
||||
-- This script is run by the "stack runghc" command above.
|
||||
-- This command expects to be running in a copy of the hledger source code.
|
||||
-- Its advantage is that it uses that latest hledger source version.
|
||||
-- To show more progress output, change --verbosity to info.
|
||||
-- The main haskell package needed for scripting is "hledger".
|
||||
-- To make more packages available for import, add more --package options.
|
||||
--
|
||||
-- For more robustness, use the "stack script" command below instead.
|
||||
-- This uses a released version of hledger, and does not need the hledger source code.
|
||||
-- The version of hledger (and haskell libraries, and ghc) is determined by
|
||||
-- the stackage snapshot (lts-X.Y or nightly-YYYY-MM-DD).
|
||||
--
|
||||
-- stack script --snapshot lts-22.27 --verbosity error --package hledger --package text
|
||||
-- (Uses the specified snapshot with its hledger and ghc, https://www.stackage.org/lts-22.27)
|
||||
--
|
||||
-- stack script --snapshot nightly-2024-09-26 --verbosity error --package hledger --package hledger-lib --package text --compile
|
||||
-- (Uses a newer snapshot, hledger and ghc. The --compile flag compiles the script to a faster binary.)
|
||||
--
|
||||
------------------------------------78----------------------------------------
|
||||
script-example - my new script
|
||||
|
||||
{-# LANGUAGE OverloadedStrings, PackageImports #-}
|
||||
-}
|
||||
|
||||
-- Haskell language customisations. OverloadedStrings is a useful one.
|
||||
-- https://downloads.haskell.org/ghc/latest/docs/users_guide/exts/intro.html
|
||||
{-# LANGUAGE OverloadedStrings #-}
|
||||
|
||||
-- Import things from haskell packages - the ones specified above, or included with the GHC specified above,
|
||||
-- eg https://downloads.haskell.org/ghc/latest/docs/users_guide/9.10.1-notes.html#included-libraries
|
||||
-- This provides most of hledger's API that's useful for scripts.
|
||||
import Hledger.Cli.Script
|
||||
import qualified "text" Data.Text as T
|
||||
import qualified "text" Data.Text.IO as T
|
||||
-- Haskell has a built-in String type; hledger also uses the more efficient Text type.
|
||||
import qualified Data.Text as T
|
||||
import qualified Data.Text.IO as T
|
||||
|
||||
-- If you use hledgerCommandMode, and getHledgerCliOpts below, your script will
|
||||
-- support -h/--help, -f/--file and other common hledger options.
|
||||
cmdmode = hledgerCommandMode (unlines
|
||||
-- Command name, then --help text. Note, empty help lines get stripped.
|
||||
---------------------------standard terminal width-----------------------------
|
||||
-- command name on first line:
|
||||
["script-example"
|
||||
,"This is an example of a (hledger-lib-using) hledger script."
|
||||
-- then --help text:
|
||||
,"Usage: hledger-script-example [OPTS] [ARGS]"
|
||||
,"or: hledger script-example -- [OPTS] [ARGS]"
|
||||
,"Save it under another name and customise it."
|
||||
,"The hledger- name makes it appear in hledger's commands list."
|
||||
,"Examples:"
|
||||
,"$ hledger-script-example --help"
|
||||
,"(this help)"
|
||||
------------------------------------78----------------------------------------
|
||||
,"$ hledger-script-example # do the thing"
|
||||
,"$ hledger-script-example --help # print help"
|
||||
])
|
||||
[] [generalflagsgroup1] [] ([], Just $ argsFlag "[ARGS]") -- or Nothing
|
||||
-- you can add or change options here (see CliOptions.hs); usually not needed
|
||||
[] [generalflagsgroup1] [] ([], Just $ argsFlag "[ARGS]")
|
||||
|
||||
-- Most scripts have three steps:
|
||||
-- 1. process command line options/arguments
|
||||
-- 2. read the journal file
|
||||
-- 3. do something with it.
|
||||
main = do
|
||||
opts@CliOpts{reportspec_=rspec} <- getHledgerCliOpts cmdmode
|
||||
withJournalDo opts $ \j -> do
|
||||
putStrLn "it worked! print something more useful here"
|
||||
putStrLn "hello"
|
||||
|
||||
|
||||
-- Examples:
|
||||
-- See also bin/*.hs
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
{-
|
||||
Script code examples. You can remove this text.
|
||||
|
||||
-- Count transactions, possibly filtered by a query:
|
||||
See also: bin/*.hs
|
||||
|
||||
-- d <- getCurrentDay
|
||||
-- let
|
||||
-- q = _rsQuery rspec
|
||||
-- ts = filter (q `matchesTransaction`) $ jtxns $ journalApplyValuationFromOpts rspec j
|
||||
-- printf "File %s: %d transactions\n" (journalFilePath j) (length ts)
|
||||
Show a count of transactions, possibly filtered by a query:
|
||||
|
||||
d <- getCurrentDay
|
||||
let
|
||||
q = _rsQuery rspec
|
||||
ts = filter (q `matchesTransaction`) $ jtxns $ journalApplyValuationFromOpts rspec j
|
||||
printf "File %s: %d transactions\n" (journalFilePath j) (length ts)
|
||||
|
||||
-- register-max:
|
||||
Run a postings report (like hledger register) and print the posting(s) with highest amount
|
||||
(like hledger-register-max.hs):
|
||||
|
||||
-- withJournalDo opts $ \j -> do
|
||||
-- let
|
||||
-- postingReportItems = postingsReport rspec j
|
||||
-- maxbal = fifth5 $ maximumBy (comparing fifth5) r
|
||||
-- is = filter ((== maxbal).fifth5) r
|
||||
-- mapM_ printItem is
|
||||
--
|
||||
-- printItem (_, _, _, p, bal) = do
|
||||
-- let
|
||||
-- d = postingDate p
|
||||
-- mt = ptransaction p
|
||||
-- desc = fmt 30 $ maybe "-" tdescription mt
|
||||
-- acct = fmt 30 $ paccount p
|
||||
-- amt = fmta 12 $ T.pack $ showMixedAmountOneLine $ pamount p
|
||||
-- baltxt = fmta 12 $ T.pack $ showMixedAmountOneLine bal
|
||||
-- T.putStrLn $ T.unwords [showDate d, desc, "", acct, "", amt, " ", baltxt]
|
||||
-- where
|
||||
-- fmt w = formatText True (Just w) (Just w) . textElideRight w
|
||||
-- fmta w = formatText False (Just w) Nothing
|
||||
let
|
||||
postingReportItems = postingsReport rspec j
|
||||
maxbal = fifth5 $ maximumBy (comparing fifth5) r
|
||||
is = filter ((== maxbal).fifth5) r
|
||||
mapM_ printItem is
|
||||
|
||||
printItem (_, _, _, p, bal) = do
|
||||
let
|
||||
d = postingDate p
|
||||
mt = ptransaction p
|
||||
desc = fmt 30 $ maybe "-" tdescription mt
|
||||
acct = fmt 30 $ paccount p
|
||||
amt = fmta 12 $ T.pack $ showMixedAmountOneLine $ pamount p
|
||||
baltxt = fmta 12 $ T.pack $ showMixedAmountOneLine bal
|
||||
T.putStrLn $ T.unwords [showDate d, desc, "", acct, "", amt, " ", baltxt]
|
||||
where
|
||||
fmt w = formatText True (Just w) (Just w) . textElideRight w
|
||||
fmta w = formatText False (Just w) Nothing
|
||||
|
||||
-- Using [s|...|] for multiline string literals (requires string-qq package and {-# LANGUAGE QuasiQuotes #-}):
|
||||
Use the [s|...|] multiline string syntax (requires --package string-qq and {-# LANGUAGE QuasiQuotes #-}):
|
||||
|
||||
-- cmdmode = hledgerCommandMode (unlines
|
||||
-- -- Command name, then --help text. Note, empty help lines get stripped.
|
||||
-- [s| script-example
|
||||
-- This is an example of a (hledger-lib-using) hledger script."
|
||||
-- Usage: hledger-script-example [OPTS] [ARGS]"
|
||||
-- or: hledger script-example -- [OPTS] [ARGS]"
|
||||
-- Save it under another name and customise it."
|
||||
-- The hledger- name makes it appear in hledger's commands list."
|
||||
-- Examples:"
|
||||
-- $ hledger-script-example --help"
|
||||
-- (this help)"
|
||||
-- |]
|
||||
-- ------------------------------------78----------------------------------------
|
||||
-- [] [generalflagsgroup1] [] ([], Just $ argsFlag "[ARGS]") -- or Nothing
|
||||
|
||||
|
||||
{-
|
||||
More help:
|
||||
|
||||
This an example of an addon command (an executable named hledger-*).
|
||||
It supports many of the usual hledger options; run it with -h/--help
|
||||
to see them. When you want to create a new hledger command,
|
||||
save this script under a new name, somewhere in $PATH, give it
|
||||
execute permission, and start tweaking the code.
|
||||
|
||||
Requirements:
|
||||
|
||||
This is a stack script, best run or compiled with stack.
|
||||
Once compiled it doesn't require stack.
|
||||
If you prefer you can adapt it to be a cabal script,
|
||||
or you can manually install the required haskell libraries
|
||||
(see above) and then run/compile it just with ghc or runghc.
|
||||
|
||||
If run/compiled from inside the hledger source tree, it will use that hledger
|
||||
version and the libs of the stackage resolver in stack.yaml.
|
||||
If run/compiled from outside the hledger source tree, it will use the hledger
|
||||
and libs of the resolver in ~/.stack/global-project/stack.yaml.
|
||||
Or you can specify a --resolver in the stack command above.
|
||||
|
||||
Usage:
|
||||
|
||||
Executing this script will cause stack to run it in interpreted mode:
|
||||
|
||||
$ hledger-script-example.hs
|
||||
|
||||
Or you can compile first:
|
||||
|
||||
$ stack ghc hledger-script-example.hs --package hledger --package string-qq
|
||||
$ hledger-script-example
|
||||
|
||||
Whether compiled or not, you can also run it as a hledger subcommand, if it is in $PATH:
|
||||
|
||||
$ hledger script-example
|
||||
cmdmode = hledgerCommandMode (unlines
|
||||
-- Command name, then --help text. Note, empty help lines get stripped.
|
||||
[s| script-example
|
||||
This is an example of a (hledger-lib-using) hledger script."
|
||||
Usage: hledger-script-example [OPTS] [ARGS]"
|
||||
or: hledger script-example -- [OPTS] [ARGS]"
|
||||
Save it under another name and customise it."
|
||||
The hledger- name makes it appear in hledger's commands list."
|
||||
Examples:"
|
||||
$ hledger-script-example --help"
|
||||
(this help)"
|
||||
|]
|
||||
------------------------------------78----------------------------------------
|
||||
[] [generalflagsgroup1] [] ([], Just $ argsFlag "[ARGS]") -- or Nothing
|
||||
|
||||
-}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user