packages feed

penny-bin 0.10.0.0 → 0.12.0.0

raw patch · 9 files changed

+366/−140 lines, 9 filesdep ~multiargdep ~penny-lib

Dependency ranges changed: multiarg, penny-lib

Files

+ man/penny-examples.7 view
@@ -0,0 +1,107 @@+.TH penny-examples 7++.SH NAME+penny-examples - more examples of Penny usage++.SH DESCRIPTION+This page contains more examples of the use of+.BR penny (1).+At first you will want to read+.BR penny-basics (1)+as there are also many useful examples there.++.SH SHOWING DIFFERENT FIELDS++Each posting has many characteristics, called+.BR fields .+For example, a posting has an account, and perhaps a payee and a+flag. Only some fields are shown in the+.B postings+report by default;+.BR penny (1)+tells you which ones these are, as well as the additional fields you+can show. To show additional fields, use the --show option. For+instance, showing the line numbers of a posting can be handy if you+want to track the postings down in your ledger:++.EX+penny --account assets:checking postings \\+  --show lineNum starter.pny+.EE++This adds the line number to each posting. As you can see if you try+it out, the option does not remove any fields. If you want to start+from a clean slate, try the+.I --hide-all+option.++The width of the report adjusts automatically to accomodate the fields+you want, while fitting them to the width of your screen. Most fields+are simply as wide as they need to be to show their information;+however, the+.I payee+and+.I account+fields will wrap to multiple lines or squeeze themselves smaller by+eliminating letters (respectively) in order to help the report fit in+the width of your screen.++.SH FITERING BASED ON SIBLINGS++Each transaction has at least two postings. The postings in a single+transaction are called+.IR siblings .+When+.I penny+first runs, it splits each transaction into postings. Then it+generally deals with each posting independently. However,+.I penny+"remembers" which siblings each posting has. You can then use a+posting's siblings as criteria when you are building a filter+expression.++For example, you want to see all the activity in your checking+account. First you try this:++.EX+penny --account assets:checking postings starter.pny+.EE++This tells you each time your checking account is debited or+credited--which is quite useful. But maybe you want to know what+expenses you are paying for out of your checking account. The report+above is not too useful for that as the account is always the same:+.IR Assets:Checking .+What you want to see is the sibling postings each time there is+activity in your checking account. Try this:++.EX+penny --s-account assets:checking postings starter.pny+.EE++This works by selecting each posting that has a sibling posting with+the account+.IR Assets:Checking .+All postings are included, even those that are deposits, like+those from+.IR Income:Salary .+If you only want to see sibling postings that are also in an Expenses+account:++.EX+penny --s-account assets:checking \\+  --and --account expenses postings starter.pny+.EE++Alternatively, you can see each posting that has a sibling posting+that is in the Assets:Checking account and where the posting itself is+a debit:++.EX+penny --s-account assets:checking \\+  --and --debit postings starter.pny+.EE++.SH SEE ALSO+.BR penny (1),+.BR penny-suite (7)
man/penny-suite.7 view
@@ -50,6 +50,13 @@ .B penny  .TP+.BR penny-examples (7)++more examples of+.B penny+usage++.TP .BR penny-commodities (7)  tracking multiple commodities, such as stocks, with Penny
man/penny.1 view
@@ -214,7 +214,7 @@ Succeeds if any one of the posting's tags matches the given pattern.  .TP-.BI --number " pattern"+.BI "--number | -n " pattern Succeeds if the posting's number matches the given pattern. (This is the number that you specify in parentheses in your ledger file, not the line number or any of the serial numbers.)  If the posting has no@@ -222,13 +222,13 @@ one).  .TP-.BI --flag " pattern"+.BI "--flag | -f " pattern Succeeds if the posting's flag matches the given pattern. If the posting has no number, the flag of the parent transaction is used (if there is one).  .TP-.BI --commodity " pattern"+.BI "--commodity | -y " pattern Succeeds if the posting's commodity matches the given pattern.  .TP@@ -244,15 +244,91 @@  .SS Other posting characteristics +.TP .B --debit The entry must be a debit. +.TP .B --credit The entry must be a credit. -.BI --qty " comparer number"+.TP+.BI "--qty | -q " "comparer number" The entry's quantity must fall within the given range. +.TP+.BI "--filename " pattern+The filename from which the entry came must match this pattern.++.SS Sibling postings++All of the postings in a transaction are known as+.IR siblings .+Because every transaction has at least two postings, every posting has+at least one sibling. The options given above examine the+characteristics of a posting. The following options examine the+characteristics of the siblings of a posting; the option will match+the posting if any of its siblings match the specified+information. Otherwise, these options behave similarly to the+corresponding option which does not have the+.I --s-+prefix. Not every filter option has a corresponding+.I --s-+option; for example, there is no+.I --s-date+option because all sibling postings have the same date.++.TP+.BI "--s-globalPosting"++.TP+.BI "--s-revGlobalPosting"++.TP+.BI "--s-filePosting"++.TP+.BI "--s-revFilePosting"++.TP+.BI "--s-account"++.TP+.BI "--s-account"++.TP+.BI "--s-account-level"++.TP+.BI "--s-account-any"++.TP+.BI "--s-payee"++.TP+.BI "--s-tag"++.TP+.BI "--s-number"++.TP+.BI "--s-flag"++.TP+.BI "--s-commodity"++.TP+.BI "--s-posting-memo"++.TP+.BI "--s-debit"++.TP+.BI "--s-credit"++.TP+.BI "--s-qty"+ .SS Operators  Each of the options above is a single operand. If you have multiple@@ -279,6 +355,8 @@ . .TP .BI "--open " expr " --close"+.TQ+.BI "-( " expr " -)" Force precedence using parentheses. Enclose a complete expression between the .B --open@@ -288,12 +366,16 @@  .TP .BI "--not " expr+.TQ+.BI "-N " expr True if .I expr is false.  .TP .IB expr1 " --and " expr2+.TQ+.IB expr1 " -A " expr2 True if .I expr1 and@@ -302,6 +384,8 @@  .TP .IB expr1 " --or " expr2+.TQ+.IB expr1 " -O " expr2 True if .I expr1 or@@ -320,20 +404,26 @@ . .TP .B --and+.TQ+.B -A Pops two predicates from the top of the stack, creates a new predicate which is true only if both predicates are true, and pushes the new predicate onto the stack. . .TP .B --or+.TQ+.B -O Pops two predicates from the top of the stack, creates a new predicate which is true if either predicate is true, and pushes the new predicate onto the stack. . .TP .B --not+.TQ+.B -N Pops one predicate from the top of the stack, creates a new predicate-which is true if the origianl predicate is false, and pushes the new+which is true if the original predicate is false, and pushes the new predicate onto the stack. . .SS Options affecting patterns@@ -352,7 +442,7 @@ Patterns are case sensitive  .TP-.B --within+.B "--within | -w" Use the "within" matcher (default), which matches if the pattern given appears anywhere within the target text. This is a simple letter-for-letter match, not a regular expression, though its case@@ -363,9 +453,9 @@ options.  .TP-.B --pcre+.B "--pcre | -r" Use the "pcre" matcher, which uses Perl-compatible regular expressions (see-.BR pcresyntax "(1) and " pcrepattern (1))+.BR pcresyntax "(3) and " pcrepattern (3))  .TP .B --posix@@ -373,7 +463,7 @@ .BR regex (7))  .TP-.B --exact+.B "--exact | -x" Use the "exact" matcher, which matches if the given pattern is a letter-for-letter match of the target text, with case sensitivity determined by the@@ -442,10 +532,22 @@ .BR "--sort none" .  -.SH HELP+.SH META .TP .B --help | -h-Show help and exit+Show help and exit. If you have configured a custom+.B penny+binary (see+.BR penny-custom (7))+you might have established defaults that differ from the defaults+described in this manual page. The output of+.B penny --help+will reflect these customizations.+.TP+.B --version+Show version of the executable and of the+.B penny-lib+library (the library might have a different version number).  .SH POSTINGS REPORT @@ -455,7 +557,7 @@ .B pos for short, shows postings in order with a running balance. This report takes all the options shown above in the categories from "Posting-filters" to "Removing postings after sorting and filtering." These+filters" through "Removing postings after sorting and filtering." These options affect which postings are shown in the report. Postings that are not shown in the report but which were not filtered out in the filtering stage still affect the report's running balance.
penny-bin.cabal view
@@ -1,5 +1,5 @@ Name: penny-bin-Version: 0.10.0.0+Version: 0.12.0.0 Cabal-version: >=1.8 Build-Type: Simple License: BSD3@@ -178,9 +178,10 @@ Executable penny   Build-depends:     base ==4.*,-    penny-lib ==0.10.*+    penny-lib ==0.12.*    Main-is: penny-main.hs+  Other-modules: Paths_penny_bin   GHC-Options: -Wall   if flag(debug)     GHC-Options: -rtsopts -auto-all -caf-all@@ -191,13 +192,13 @@ Executable penny-selloff   Build-depends:     base == 4.*,-    penny-lib ==0.10.*,+    penny-lib ==0.12.*,     explicit-exception ==0.1.*,     containers ==0.5.*,     semigroups ==0.9.*,     text ==0.11.*,     parsec ==3.1.*,-    multiarg ==0.12.*,+    multiarg ==0.14.*,     transformers ==0.3.*    Main-is: penny-selloff.hs@@ -211,12 +212,13 @@ Executable penny-diff   Build-depends:     base ==4.*,-    penny-lib ==0.10.*,+    penny-lib ==0.12.*,     text ==0.11.*,-    multiarg ==0.12.*,+    multiarg ==0.14.*,     explicit-exception == 0.1.*    Main-is: penny-diff.hs+  Other-modules: Paths_penny_bin   GHC-Options: -Wall   if flag(debug)     GHC-Options: -rtsopts -auto-all -caf-all@@ -227,11 +229,13 @@ Executable penny-reprint   Build-depends:       base ==4.*-    , penny-lib ==0.10.*+    , multiarg ==0.14.*+    , penny-lib ==0.12.*     , pretty-show ==1.5.*     , text ==0.11.*    main-is: penny-reprint.hs+  Other-modules: Paths_penny_bin   ghc-options: -Wall   if ! flag(build-reprint)     buildable: False@@ -239,12 +243,13 @@ Executable penny-reconcile   Build-depends:       base ==4.*-    , penny-lib ==0.10.*+    , penny-lib ==0.12.*     , text ==0.11.*-    , multiarg ==0.12.*+    , multiarg ==0.14.*     , explicit-exception ==0.1.*    main-is: penny-reconcile.hs+  Other-modules: Paths_penny_bin   ghc-options: -Wall   if ! flag(build-reconcile)     buildable: False
penny-diff.hs view
@@ -1,11 +1,12 @@ module Main where  import qualified Control.Exception as CEx-import Control.Monad (when) import qualified Control.Monad.Exception.Synchronous as Ex+import Data.Either (partitionEithers) import Data.Maybe (fromJust) import Data.List (deleteFirstsBy) import qualified System.Console.MultiArg as M+import qualified Penny.Liberty as Ly import qualified Penny.Lincoln as L import qualified Penny.Lincoln.Predicates as P import qualified Penny.Copper as C@@ -16,23 +17,28 @@ import qualified System.Exit as E import qualified System.IO as IO +import qualified Paths_penny_bin as PPB+ groupingSpecs :: CR.GroupSpecs groupingSpecs = CR.GroupSpecs CR.NoGrouping CR.NoGrouping  main :: IO () main = runPennyDiff groupingSpecs -help :: String-help = unlines-  [ "usage: penny-diff [-12] FILE1 FILE2"+help :: String -> String+help pn = unlines+  [ "usage: " ++ pn ++ " [-12] FILE1 FILE2"   , "Shows items that exist in FILE1 but not in FILE2,"   , "as well as items that exist in FILE2 but not in FILE1."   , "Options:"   , "-1 Show only items that exist in FILE1 but not in FILE2"   , "-2 Show only items that exist in FILE2 but not in FILE1"+  , ""+  , "--help, -h - show this help and exit"+  , "--version Show version and exit"   ] -data Args = ArgFile File | Filename String | Help+data Args = ArgFile File | Filename String   deriving (Eq, Show)  data DiffsToShow = File1Only | File2Only | BothFiles@@ -43,6 +49,12 @@ optFile2 :: M.OptSpec Args optFile2 = M.OptSpec [] "2" (M.NoArg (ArgFile File2)) +allOpts :: [M.OptSpec (Either (IO ()) Args)]+allOpts = [ fmap Right optFile1+          , fmap Right optFile2+          , fmap Left (Ly.version PPB.version)+          ]+ data File = File1 | File2   deriving (Eq, Show) @@ -183,26 +195,22 @@ -- an indication of which differences to show. parseCommandLine :: IO (String, String, DiffsToShow) parseCommandLine = do-  as <- M.getArgs-  let parsed = M.simple-                M.Intersperse [optFile1, optFile2] Filename as-  ls <- case parsed of-    Ex.Exception e ->-      let err = "penny-diff: could not parse command line: "-            ++ show e-      in failure err-    Ex.Success g -> return g-  when (any (== Help) ls) (putStrLn help >> E.exitSuccess)-  let toFilename a = case a of+  as <- M.simpleWithHelp help M.Intersperse allOpts+        (Right . Filename)+  let (doVer, args) = partitionEithers as+      toFilename a = case a of         Filename s -> Just s         _ -> Nothing-  (fn1, fn2) <- case mapMaybe toFilename ls of+  case doVer of+    [] -> return ()+    x:_ -> x+  (fn1, fn2) <- case mapMaybe toFilename args of     x:y:[] -> return (x, y)     _ -> failure "penny-diff: error: you must supply two filenames."   let getDiffs-        | ((ArgFile File1) `elem` ls)-          && ((ArgFile File2) `elem` ls) = BothFiles-        | ((ArgFile File1) `elem` ls) = File1Only-        | ((ArgFile File2) `elem` ls) = File2Only+        | ((ArgFile File1) `elem` args)+          && ((ArgFile File2) `elem` args) = BothFiles+        | ((ArgFile File1) `elem` args) = File1Only+        | ((ArgFile File2) `elem` args) = File2Only         | otherwise = BothFiles   return (fn1, fn2, getDiffs)
penny-main.hs view
@@ -1,6 +1,7 @@ module Main where  import Penny+import qualified Paths_penny_bin as PPB  -- | This type contains settings for all the reports, as well as -- default settings for the global options. Some of these can be@@ -296,5 +297,5 @@   }  main :: IO ()-main = runPenny defaults+main = runPenny PPB.version defaults 
penny-reconcile.hs view
@@ -1,15 +1,16 @@ module Main where -import Data.Maybe (fromMaybe, mapMaybe, fromJust)+import Data.Maybe (fromMaybe, fromJust) import qualified Data.Text as X import qualified Data.Text.IO as TIO import Control.Monad (guard)-import qualified Control.Monad.Exception.Synchronous as Ex import qualified Penny.Copper as C import qualified Penny.Lincoln as L+import qualified Penny.Liberty as Ly import qualified System.Console.MultiArg as MA-import System.Exit (exitSuccess)+import qualified Paths_penny_bin as PPB + -- | Changes a posting to mark it reconciled, if it was already marked -- as cleared. changePosting :: L.Posting -> L.PostingChangeData@@ -36,9 +37,9 @@             $ t   in L.changeTransaction fam t -help :: String-help = unlines-  [ "usage: penny-reconcile [-h] FILE..."+help :: String -> String+help pn = unlines+  [ "usage: " ++ pn ++ " [options] FILE..."   , "Finds all transactions and postings bearing a \"C\" flag"   , "and changes them to a \"R\" flag in the listed FILEs."   , "If no FILE, or if FILE is -, read standard input."@@ -47,45 +48,34 @@   , "changed."   , ""   , "Options:"-  , "  -h, --help Show help and exit."+  , "  -h, --help - Show help and exit."+  , "  --version  - Show version and exit"   ] -toPosArg :: Arg -> Maybe String-toPosArg a = case a of-  APosArg s -> Just s-  _ -> Nothing--data Arg-  = AHelp-  | APosArg String-  deriving (Eq, Show)--data Opts-  = NeedsHelp-  | DoIt [String]-  deriving Show+groupSpecs :: C.GroupSpecs+groupSpecs = C.GroupSpecs C.NoGrouping C.NoGrouping +-- | The first element if the pair is a no-op if the user does not+-- need to see the version, or an IO action to print the version if+-- the user wants to see it. The second element is the list of command+-- line arguments.+type Opts = (IO (), [String]) -parseArgs :: [String] -> Opts-parseArgs ss =-  let opts = [ MA.OptSpec ["help"] "h" (MA.NoArg AHelp) ]-  in case MA.simple MA.Intersperse opts APosArg ss of-      Ex.Exception e -> error . show $ e-      Ex.Success g ->-        if any (== AHelp) g-        then NeedsHelp-        else DoIt $ mapMaybe toPosArg g+allOpts :: [MA.OptSpec (Opts -> Opts)]+allOpts = [ fmap (\act (_, ss) -> (act, ss)) $+            Ly.version PPB.version+          ] -groupSpecs :: C.GroupSpecs-groupSpecs = C.GroupSpecs C.NoGrouping C.NoGrouping+posArg :: String -> Opts -> Opts+posArg s (a, ss) = (a, s:ss)  main :: IO () main = do-  os <- fmap parseArgs MA.getArgs-  ls <- case os of-    NeedsHelp -> putStrLn help >> exitSuccess-    DoIt ss -> return ss-  led <- C.open ls+  as <- MA.simpleWithHelp help MA.Intersperse allOpts posArg+  let opts = foldr ($) (return (), []) as+  fst opts+  led <- C.open . snd $ opts   let led' = C.mapLedger (C.mapItem id id changeTransaction) led       rend = fromJust $ C.ledger groupSpecs led'   TIO.putStr rend+
penny-reprint.hs view
@@ -2,12 +2,15 @@  import qualified Penny.Copper as C import qualified Penny.Copper.Render as R+import qualified Penny.Liberty as Ly import qualified Data.Text.IO as TIO-import System.Environment (getArgs)+import qualified System.Console.MultiArg as MA -help :: String-help = unlines-  [ "usage: penny-reprint FILE..."+import qualified Paths_penny_bin as PPB++help :: String -> String+help pn = unlines+  [ "usage: " ++ pn ++ " FILE..."   , "Tidies the formatting of a Penny ledger file."   , "All memos, comments, and blank lines are preserved,"   , "and the order of the transactions and postings is not changed."@@ -16,15 +19,31 @@   , ""   , "If no FILE, or if FILE is \"-\", read stanard input."   , "Result is printed to standard output."+  , ""+  , "Options:"+  , "  --help, -h - show help and exit"+  , "  --version  - show version and exit"   ]  groupSpecs :: R.GroupSpecs groupSpecs = R.GroupSpecs R.NoGrouping R.NoGrouping +type MaybeShowVer = IO ()+type Opts = (MaybeShowVer, [String])++posArg :: String -> Opts -> Opts+posArg s (a, ss) = (a, s:ss)++allOpts :: [MA.OptSpec (Opts -> Opts)]+allOpts = [ fmap (\a (_, ss) -> (a, ss))+            $ Ly.version PPB.version ]+ main :: IO () main = do-  as <- getArgs-  l <- C.open as+  as <- MA.simpleWithHelp help MA.Intersperse allOpts posArg+  let opts = foldr ($) (return (), []) as+  fst opts+  l <- C.open . snd $ opts   case R.ledger groupSpecs l of     Nothing -> error "could not render final ledger."     Just x -> TIO.putStr x
penny-selloff.hs view
@@ -91,7 +91,7 @@  -- * In IO monad: Print output transaction. -module Main where+module Main (main) where  import qualified Control.Monad.Exception.Synchronous as Ex import Control.Monad (when)@@ -112,10 +112,12 @@ import qualified Penny.Copper as Cop import qualified Penny.Copper.Parsec as CP import qualified Penny.Copper.Render as CR+import qualified Penny.Liberty as Ly import qualified Penny.Lincoln as L import qualified Data.Map as M import qualified System.Console.MultiArg as MA import Text.Parsec as Parsec+import qualified Paths_penny_bin as PPB  groupingSpec :: CR.GroupSpecs groupingSpec = CR.GroupSpecs CR.NoGrouping CR.NoGrouping@@ -126,7 +128,6 @@   = ParseFail MA.Error   | NoInputArgs   | ProceedsParseFailed Parsec.ParseError-  | NoInputFiles   | LedgerParseError Cop.ErrorMsg   | NoSelloffAccount   | NotThreeSelloffSubAccounts@@ -141,56 +142,47 @@   | SaleDateParseFailed Parsec.ParseError   deriving Show -data ProceedsAcct = ProceedsAcct { unProceedsAcct :: L.Account }+data ProceedsAcct = ProceedsAcct { _unProceedsAcct :: L.Account }   deriving Show -newtype InputFilename = InputFilename { unInputFilename :: String }+newtype InputFilename = InputFilename { _unInputFilename :: String }   deriving (Eq, Show) -loadFile :: InputFilename -> IO (L.Filename, Cop.FileContents)-loadFile (InputFilename fn) = fmap f (TIO.readFile fn)-  where-    f fc = (L.Filename . pack $ fn, Cop.FileContents fc)+type MaybeShowVer = IO ()+type Opts = (MaybeShowVer, [String]) -data ParseResult-  = NeedsHelp-  | ParseResult ProceedsAcct [InputFilename]+posArg :: String -> Opts -> Opts+posArg s (a, ss) = (a, s:ss) -data Flag-  = Help-  | PosArg String-  deriving (Show, Eq)+allOpts :: [MA.OptSpec (Opts -> Opts)]+allOpts = [ fmap (\a (_, ss) -> (a, ss)) $ Ly.version PPB.version ] -parseCommandLine :: [String] -> Err ParseResult-parseCommandLine ss =-  let os = [MA.OptSpec ["help"] "h" (MA.NoArg Help)]-  in case MA.simple MA.Intersperse os PosArg ss of-    Ex.Exception e -> Ex.Exception . ParseFail $ e-    Ex.Success g ->-      if isJust . find (== Help) $ g-      then return NeedsHelp-      else do-        let toArg a = case a of-              PosArg s -> Just s-              _ -> Nothing-        x:xs <- case mapMaybe toArg g of-          [] -> Ex.throw NoInputArgs-          r -> return r-        a <- Ex.mapException ProceedsParseFailed-              . Ex.fromEither-              $ Parsec.parse CP.lvl1Acct "" (pack x)-        when (null xs) $ Ex.throw NoInputFiles-        return $ ParseResult (ProceedsAcct a) (map InputFilename xs)+data ParseResult = ParseResult ProceedsAcct Cop.Ledger -help :: String-help = "usage: penny-selloff PROCEEDS_ACCOUNT FILE..."+parseCommandLine :: IO ParseResult+parseCommandLine = do+  as <- MA.simpleWithHelp help MA.Intersperse allOpts posArg+  let opts = foldr ($) (return (), []) as+  fst opts+  x:xs <- case snd opts of+    [] -> fail (show NoInputArgs)+    r -> return r+  a <- Ex.switch (fail . show . ProceedsParseFailed) return+       . Ex.fromEither+       $ Parsec.parse CP.lvl1Acct "" (pack x)+  l <- Cop.open xs+  return $ ParseResult (ProceedsAcct a) l -parseFiles-  :: [(L.Filename, Cop.FileContents)]-  -> Err Cop.Ledger-parseFiles ls = Ex.mapException LedgerParseError-  $ Cop.parse ls +help :: String -> String+help pn = unlines+  [ "usage: " ++ pn ++ " PROCEEDS_ACCOUNT FILE..."+  , "calculate capital gains and losses from commodity sales."+  , "Options:"+  , "  -h, --help - show this help and exit."+  , "  --version  - show version and exit."+  ]+ calcBalances :: Cop.Ledger -> [(L.Account, L.Balance)] calcBalances =   let toTxn i = case i of@@ -347,7 +339,7 @@   deriving (Eq, Show)  newtype StillToRealize-  = StillToRealize { unStillToRealize :: L.Qty }+  = StillToRealize { _unStillToRealize :: L.Qty }   deriving (Eq, Show)  data BasisRealiztn = BasisRealiztn@@ -591,10 +583,10 @@  makeOutput   :: ProceedsAcct-  -> [(L.Filename, Cop.FileContents)]+  -> Cop.Ledger   -> Err X.Text-makeOutput pa ps = do-  bals <- fmap calcBalances $ parseFiles ps+makeOutput pa ldgr = do+  let bals = calcBalances ldgr   si <- selloffInfo pa bals   let basisAccts = findBasisAccounts (siGroup si) bals   purchInfos <- mapM (purchaseInfo (siStock si) (siCurrency si))@@ -610,14 +602,9 @@   main :: IO ()-main =-  MA.getArgs-  >>= Ex.switch (error . show) handleParseResult . parseCommandLine+main = parseCommandLine >>= handleParseResult   handleParseResult :: ParseResult -> IO ()-handleParseResult pr = case pr of-  NeedsHelp -> putStrLn help-  ParseResult pa fs ->-    mapM loadFile fs-    >>= Ex.switch (error . show) TIO.putStr . makeOutput pa+handleParseResult (ParseResult pa ldgr) =+  Ex.switch (error . show) TIO.putStr . makeOutput pa $ ldgr