imp: improve/format errors for various failures [#2367]
These now call error' and show errors in the standard style: - reading a nonexistent data file - reading an unsafe dotted file name on windows - web: using --socket on windows - demo: demo not found - demo: error while running asciinema - diff: bad arguments - print --match: no match found - register --match: no match found - roi: no investment transactions found
This commit is contained in:
parent
454c669fe4
commit
9340b73aae
@ -143,10 +143,9 @@ import Data.Time (Day)
|
|||||||
import Safe (headDef, headMay)
|
import Safe (headDef, headMay)
|
||||||
import System.Directory (doesFileExist, getHomeDirectory)
|
import System.Directory (doesFileExist, getHomeDirectory)
|
||||||
import System.Environment (getEnv)
|
import System.Environment (getEnv)
|
||||||
import System.Exit (exitFailure)
|
|
||||||
import System.FilePath ((<.>), (</>), splitDirectories, splitFileName, takeFileName)
|
import System.FilePath ((<.>), (</>), splitDirectories, splitFileName, takeFileName)
|
||||||
import System.Info (os)
|
import System.Info (os)
|
||||||
import System.IO (Handle, hPutStr, stderr)
|
import System.IO (Handle, hPutStrLn, stderr)
|
||||||
|
|
||||||
import Hledger.Data.Dates (getCurrentDay, parsedateM, showDate)
|
import Hledger.Data.Dates (getCurrentDay, parsedateM, showDate)
|
||||||
import Hledger.Data.Types
|
import Hledger.Data.Types
|
||||||
@ -348,23 +347,22 @@ requireJournalFileExists :: FilePath -> IO ()
|
|||||||
requireJournalFileExists "-" = return ()
|
requireJournalFileExists "-" = return ()
|
||||||
requireJournalFileExists f = do
|
requireJournalFileExists f = do
|
||||||
exists <- doesFileExist f
|
exists <- doesFileExist f
|
||||||
unless exists $ do
|
unless exists $ error' $ unlines
|
||||||
hPutStr stderr $ "The hledger data file \"" <> f <> "\" was not found.\n"
|
[ "data file \"" <> f <> "\" was not found."
|
||||||
hPutStr stderr "Please create it first, eg with \"hledger add\" or a text editor.\n"
|
,"Please create it first, eg with \"hledger add\" or a text editor."
|
||||||
hPutStr stderr "Or, specify an existing data file with -f or $LEDGER_FILE.\n"
|
,"Or, specify an existing data file with -f or $LEDGER_FILE."
|
||||||
exitFailure
|
]
|
||||||
|
|
||||||
-- | Ensure there is a journal file at the given path, creating an empty one if needed.
|
-- | Ensure there is a journal file at the given path, creating an empty one if needed.
|
||||||
-- On Windows, also ensure that the path contains no trailing dots
|
-- On Windows, also ensure that the path contains no trailing dots
|
||||||
-- which could cause data loss (see 'isWindowsUnsafeDotPath').
|
-- which could cause data loss (see 'isWindowsUnsafeDotPath').
|
||||||
ensureJournalFileExists :: FilePath -> IO ()
|
ensureJournalFileExists :: FilePath -> IO ()
|
||||||
ensureJournalFileExists f = do
|
ensureJournalFileExists f = do
|
||||||
when (os=="mingw32" && isWindowsUnsafeDotPath f) $ do
|
when (os=="mingw32" && isWindowsUnsafeDotPath f) $
|
||||||
hPutStr stderr $ "Part of file path \"" <> show f <> "\"\n ends with a dot, which is unsafe on Windows; please use a different path.\n"
|
error' $ "Part of file path \"" <> show f <> "\"\n ends with a dot, which is unsafe on Windows; please use a different path.\n"
|
||||||
exitFailure
|
|
||||||
exists <- doesFileExist f
|
exists <- doesFileExist f
|
||||||
unless exists $ do
|
unless exists $ do
|
||||||
hPutStr stderr $ "Creating hledger journal file " <> show f <> ".\n"
|
hPutStrLn stderr $ "Creating hledger journal file " <> show f
|
||||||
-- note Hledger.Utils.UTF8.* do no line ending conversion on windows,
|
-- note Hledger.Utils.UTF8.* do no line ending conversion on windows,
|
||||||
-- we currently require unix line endings on all platforms.
|
-- we currently require unix line endings on all platforms.
|
||||||
newJournalContent >>= T.writeFile f
|
newJournalContent >>= T.writeFile f
|
||||||
|
|||||||
@ -942,7 +942,7 @@ readJournalFromCsv merulesfile csvfile csvhandle sep = do
|
|||||||
skiplines <- case getDirective "skip" rules of
|
skiplines <- case getDirective "skip" rules of
|
||||||
Nothing -> return 0
|
Nothing -> return 0
|
||||||
Just "" -> return 1
|
Just "" -> return 1
|
||||||
Just s -> maybe (throwError $ "could not parse skip value: " ++ show s) return . readMay $ T.unpack s
|
Just s -> maybe (throwError $ "could not parse skip value: " ++ T.unpack s) return . readMay $ T.unpack s
|
||||||
let csvlines2 = dbg9 "csvlines2" $ drop skiplines csvlines1
|
let csvlines2 = dbg9 "csvlines2" $ drop skiplines csvlines1
|
||||||
|
|
||||||
-- convert back to text and parse as csv records
|
-- convert back to text and parse as csv records
|
||||||
@ -1117,7 +1117,7 @@ transactionFromCsvRecord timesarezoned mtzin tzout sourcepos rules record = t
|
|||||||
mdateformat = rule "date-format"
|
mdateformat = rule "date-format"
|
||||||
parsedate = parseDateWithCustomOrDefaultFormats timesarezoned mtzin tzout mdateformat
|
parsedate = parseDateWithCustomOrDefaultFormats timesarezoned mtzin tzout mdateformat
|
||||||
mkdateerror datefield datevalue mdateformat' = T.unpack $ T.unlines
|
mkdateerror datefield datevalue mdateformat' = T.unpack $ T.unlines
|
||||||
["error: could not parse \""<>datevalue<>"\" as a date using date format "
|
["could not parse \""<>datevalue<>"\" as a date using date format "
|
||||||
<>maybe "\"YYYY/M/D\", \"YYYY-M-D\" or \"YYYY.M.D\"" (T.pack . show) mdateformat'
|
<>maybe "\"YYYY/M/D\", \"YYYY-M-D\" or \"YYYY.M.D\"" (T.pack . show) mdateformat'
|
||||||
,showRecord record
|
,showRecord record
|
||||||
,"the "<>datefield<>" rule is: "<>(fromMaybe "required, but missing" $ field datefield)
|
,"the "<>datefield<>" rule is: "<>(fromMaybe "required, but missing" $ field datefield)
|
||||||
@ -1147,7 +1147,7 @@ transactionFromCsvRecord timesarezoned mtzin tzout sourcepos rules record = t
|
|||||||
Just s -> either statuserror id $ runParser (statusp <* eof) "" s
|
Just s -> either statuserror id $ runParser (statusp <* eof) "" s
|
||||||
where
|
where
|
||||||
statuserror err = error' . T.unpack $ T.unlines
|
statuserror err = error' . T.unpack $ T.unlines
|
||||||
["error: could not parse \""<>s<>"\" as a cleared status (should be *, ! or empty)"
|
["could not parse status value \""<>s<>"\" (should be *, ! or empty)"
|
||||||
,"the parse error is: "<>T.pack (customErrorBundlePretty err)
|
,"the parse error is: "<>T.pack (customErrorBundlePretty err)
|
||||||
]
|
]
|
||||||
code = maybe "" singleline' $ fieldval "code"
|
code = maybe "" singleline' $ fieldval "code"
|
||||||
@ -1362,7 +1362,7 @@ parseAmount rules record currency s =
|
|||||||
where
|
where
|
||||||
journalparsestate = nulljournal{jparsedecimalmark=parseDecimalMark rules}
|
journalparsestate = nulljournal{jparsedecimalmark=parseDecimalMark rules}
|
||||||
mkerror e = error' . T.unpack $ T.unlines
|
mkerror e = error' . T.unpack $ T.unlines
|
||||||
["error: could not parse \"" <> s <> "\" as an amount"
|
["could not parse \"" <> s <> "\" as an amount"
|
||||||
,showRecord record
|
,showRecord record
|
||||||
,showRules rules record
|
,showRules rules record
|
||||||
-- ,"the default-currency is: "++fromMaybe "unspecified" (getDirective "default-currency" rules)
|
-- ,"the default-currency is: "++fromMaybe "unspecified" (getDirective "default-currency" rules)
|
||||||
@ -1395,7 +1395,7 @@ parseBalanceAmount rules record currency n s =
|
|||||||
where
|
where
|
||||||
journalparsestate = nulljournal{jparsedecimalmark=parseDecimalMark rules}
|
journalparsestate = nulljournal{jparsedecimalmark=parseDecimalMark rules}
|
||||||
mkerror n' s' e = error' . T.unpack $ T.unlines
|
mkerror n' s' e = error' . T.unpack $ T.unlines
|
||||||
["error: could not parse \"" <> s' <> "\" as balance"<> T.pack (show n') <> " amount"
|
["could not parse \"" <> s' <> "\" as balance"<> T.pack (show n') <> " amount"
|
||||||
,showRecord record
|
,showRecord record
|
||||||
,showRules rules record
|
,showRules rules record
|
||||||
-- ,"the default-currency is: "++fromMaybe "unspecified" mdefaultcurrency
|
-- ,"the default-currency is: "++fromMaybe "unspecified" mdefaultcurrency
|
||||||
|
|||||||
@ -26,6 +26,7 @@ module Hledger.Utils.IO (
|
|||||||
ansiFormatWarning,
|
ansiFormatWarning,
|
||||||
exitOnExceptions,
|
exitOnExceptions,
|
||||||
exitWithError,
|
exitWithError,
|
||||||
|
printError,
|
||||||
|
|
||||||
-- * Time
|
-- * Time
|
||||||
getCurrentLocalTime,
|
getCurrentLocalTime,
|
||||||
@ -254,11 +255,16 @@ exitOnExceptions = flip catches
|
|||||||
where
|
where
|
||||||
rstrip = reverse . dropWhile isSpace . reverse
|
rstrip = reverse . dropWhile isSpace . reverse
|
||||||
|
|
||||||
-- | Print an error message on stderr, with a standard program name prefix,
|
-- | Print an error message with printError,
|
||||||
-- and styling the first line with ansiFormatError if that's allowed;
|
|
||||||
-- then exit the program with a non-zero exit code.
|
-- then exit the program with a non-zero exit code.
|
||||||
exitWithError :: String -> IO ()
|
exitWithError :: String -> IO ()
|
||||||
exitWithError msg = do
|
exitWithError msg = printError msg >> exitFailure
|
||||||
|
|
||||||
|
-- | Print an error message to stderr,
|
||||||
|
-- with a standard program name prefix,
|
||||||
|
-- and styling the first line with ansiFormatError if that's allowed.
|
||||||
|
printError :: String -> IO ()
|
||||||
|
printError msg = do
|
||||||
progname <- getProgName
|
progname <- getProgName
|
||||||
usecolor <- useColorOnStderr
|
usecolor <- useColorOnStderr
|
||||||
let
|
let
|
||||||
@ -269,8 +275,6 @@ exitWithError msg = do
|
|||||||
-- Use a stupid heuristic for now: add it again unless already there.
|
-- Use a stupid heuristic for now: add it again unless already there.
|
||||||
<> (if "Error:" `isPrefixOf` msg then "" else "Error: ")
|
<> (if "Error:" `isPrefixOf` msg then "" else "Error: ")
|
||||||
hPutStrLn stderr $ style $ prefix <> msg
|
hPutStrLn stderr $ style $ prefix <> msg
|
||||||
exitFailure
|
|
||||||
|
|
||||||
|
|
||||||
-- Time
|
-- Time
|
||||||
|
|
||||||
|
|||||||
@ -37,7 +37,6 @@ import Network.Wai.Handler.Warp (runSettings, runSettingsSocket, defaultSettings
|
|||||||
import Network.Wai.Handler.Launch (runHostPortFullUrl)
|
import Network.Wai.Handler.Launch (runHostPortFullUrl)
|
||||||
import System.Directory (removeFile)
|
import System.Directory (removeFile)
|
||||||
import System.Environment ( getArgs, withArgs )
|
import System.Environment ( getArgs, withArgs )
|
||||||
import System.Exit (exitFailure)
|
|
||||||
import System.IO (hFlush, stdout)
|
import System.IO (hFlush, stdout)
|
||||||
import System.PosixCompat.Files (getFileStatus, isSocket)
|
import System.PosixCompat.Files (getFileStatus, isSocket)
|
||||||
import Text.Printf (printf)
|
import Text.Printf (printf)
|
||||||
@ -162,10 +161,10 @@ web opts j = do
|
|||||||
when (isSocket sockstat) $ removeFile s
|
when (isSocket sockstat) $ removeFile s
|
||||||
)
|
)
|
||||||
(\sock -> Network.Wai.Handler.Warp.runSettingsSocket warpsettings sock app)
|
(\sock -> Network.Wai.Handler.Warp.runSettingsSocket warpsettings sock app)
|
||||||
else do
|
else error $ unlines
|
||||||
putStrLn "Unix domain sockets are not available on your operating system"
|
["Unix domain sockets are not available on your operating system."
|
||||||
putStrLn "Please try again without --socket"
|
,"Please try again without --socket."
|
||||||
exitFailure
|
]
|
||||||
|
|
||||||
Nothing -> Network.Wai.Handler.Warp.runSettings warpsettings app
|
Nothing -> Network.Wai.Handler.Warp.runSettings warpsettings app
|
||||||
|
|
||||||
|
|||||||
@ -457,7 +457,7 @@ main = exitOnExceptions $ withGhcDebug' $ do
|
|||||||
system shellcmd >>= exitWith
|
system shellcmd >>= exitWith
|
||||||
|
|
||||||
-- deprecated command found
|
-- deprecated command found
|
||||||
-- cmdname == "convert" = error' (modeHelp oldconvertmode) >> exitFailure
|
-- cmdname == "convert" = error' (modeHelp oldconvertmode)
|
||||||
|
|
||||||
-- 6.7. something else (shouldn't happen) - show an error
|
-- 6.7. something else (shouldn't happen) - show an error
|
||||||
| otherwise -> usageError $
|
| otherwise -> usageError $
|
||||||
|
|||||||
@ -435,7 +435,7 @@ hledgerCommandMode :: CommandHelpStr -> [Flag RawOpts] -> [(String, [Flag RawOpt
|
|||||||
-> [Flag RawOpts] -> ([Arg RawOpts], Maybe (Arg RawOpts)) -> Mode RawOpts
|
-> [Flag RawOpts] -> ([Arg RawOpts], Maybe (Arg RawOpts)) -> Mode RawOpts
|
||||||
hledgerCommandMode helpstr unnamedflaggroup namedflaggroups hiddenflaggroup argsdescr =
|
hledgerCommandMode helpstr unnamedflaggroup namedflaggroups hiddenflaggroup argsdescr =
|
||||||
case parseCommandHelp helpstr of
|
case parseCommandHelp helpstr of
|
||||||
Nothing -> error' $ "Could not parse command doc:\n"++helpstr++"\n" -- PARTIAL:
|
Nothing -> error' $ "could not parse command doc:\n"++helpstr++"\n" -- PARTIAL:
|
||||||
Just CommandHelp{cmdName, mcmdShortName, cmdHelpPreamble, cmdHelpPostamble} ->
|
Just CommandHelp{cmdName, mcmdShortName, cmdHelpPreamble, cmdHelpPostamble} ->
|
||||||
(defCommandMode $ cmdName : maybeToList mcmdShortName) {
|
(defCommandMode $ cmdName : maybeToList mcmdShortName) {
|
||||||
modeHelp = cmdHelpPreamble
|
modeHelp = cmdHelpPreamble
|
||||||
|
|||||||
@ -38,9 +38,6 @@ module Hledger.Cli.Commands.Demo (
|
|||||||
,demo
|
,demo
|
||||||
) where
|
) where
|
||||||
|
|
||||||
import Hledger
|
|
||||||
import Hledger.Cli.CliOptions
|
|
||||||
import System.Exit (exitFailure)
|
|
||||||
import Text.Printf
|
import Text.Printf
|
||||||
import Control.Concurrent (threadDelay)
|
import Control.Concurrent (threadDelay)
|
||||||
import System.Process (callProcess)
|
import System.Process (callProcess)
|
||||||
@ -56,6 +53,9 @@ import System.IO.Temp (withSystemTempFile)
|
|||||||
import System.IO (hClose)
|
import System.IO (hClose)
|
||||||
import System.Console.CmdArgs.Explicit (flagReq)
|
import System.Console.CmdArgs.Explicit (flagReq)
|
||||||
|
|
||||||
|
import Hledger
|
||||||
|
import Hledger.Cli.CliOptions
|
||||||
|
|
||||||
demos :: [Demo]
|
demos :: [Demo]
|
||||||
demos = map readDemo [
|
demos = map readDemo [
|
||||||
-- XXX these are confusing, redo
|
-- XXX these are confusing, redo
|
||||||
@ -93,14 +93,14 @@ demo :: CliOpts -> Journal -> IO ()
|
|||||||
demo CliOpts{rawopts_=rawopts, reportspec_=ReportSpec{_rsQuery=_query}} _j = do
|
demo CliOpts{rawopts_=rawopts, reportspec_=ReportSpec{_rsQuery=_query}} _j = do
|
||||||
-- demos <- getCurrentDirectory >>= readDemos
|
-- demos <- getCurrentDirectory >>= readDemos
|
||||||
case listofstringopt "args" rawopts of
|
case listofstringopt "args" rawopts of
|
||||||
[] -> putStrLn usagestr >> printDemos
|
[] -> putStrLn usagestr >> putStr listDemos
|
||||||
(a:as) ->
|
(a:as) ->
|
||||||
case findDemo demos a of
|
case findDemo demos a of
|
||||||
Nothing -> do
|
Nothing -> error' $ unlines
|
||||||
putStrLn $ "No demo \"" <> a <> "\" was found."
|
["No demo \"" <> a <> "\" was found."
|
||||||
putStrLn usagestr
|
,usagestr
|
||||||
printDemos
|
,listDemos
|
||||||
exitFailure
|
]
|
||||||
Just (Demo t c) -> do
|
Just (Demo t c) -> do
|
||||||
let
|
let
|
||||||
-- try to preserve the original pauses a bit while also moving things along
|
-- try to preserve the original pauses a bit while also moving things along
|
||||||
@ -139,8 +139,8 @@ findDemo ds s =
|
|||||||
where
|
where
|
||||||
sl = lowercase s
|
sl = lowercase s
|
||||||
|
|
||||||
printDemos :: IO ()
|
listDemos :: String
|
||||||
printDemos = putStrLn $ unlines $
|
listDemos = unlines $
|
||||||
"Demos:" :
|
"Demos:" :
|
||||||
-- "" :
|
-- "" :
|
||||||
[show i <> ") " <> bold' t | (i, Demo t _) <- zip [(1::Int)..] demos]
|
[show i <> ") " <> bold' t | (i, Demo t _) <- zip [(1::Int)..] demos]
|
||||||
@ -160,12 +160,15 @@ runAsciinemaPlay speed idlelimit content args =
|
|||||||
,[f]
|
,[f]
|
||||||
,args
|
,args
|
||||||
])
|
])
|
||||||
`catchIOError` \err -> do
|
`catchIOError` \err -> do
|
||||||
putStrLn $ "\n" <> show err
|
printError $ unlines
|
||||||
putStrLn "Error: running asciinema failed. Trying 'asciinema --version':"
|
[""
|
||||||
callProcess "asciinema" ["--version"] `catchIOError` \_ ->
|
,show err
|
||||||
putStrLn "This also failed. Check that asciinema is installed in your PATH."
|
,"Running asciinema failed. Trying 'asciinema --version':"
|
||||||
exitFailure
|
]
|
||||||
|
callProcess "asciinema" ["--version"]
|
||||||
|
`catchIOError` \_ ->
|
||||||
|
error' "This also failed. Check that asciinema is installed in your PATH."
|
||||||
where
|
where
|
||||||
showwithouttrailingzero = dropWhileEnd (=='.') . dropWhileEnd (=='0') . show
|
showwithouttrailingzero = dropWhileEnd (=='.') . dropWhileEnd (=='0') . show
|
||||||
|
|
||||||
|
|||||||
@ -21,7 +21,6 @@ import Data.Either (partitionEithers)
|
|||||||
import qualified Data.Text.IO as T
|
import qualified Data.Text.IO as T
|
||||||
import Lens.Micro (set)
|
import Lens.Micro (set)
|
||||||
import Safe (headDef)
|
import Safe (headDef)
|
||||||
import System.Exit (exitFailure)
|
|
||||||
|
|
||||||
import Hledger
|
import Hledger
|
||||||
import Hledger.Cli.CliOptions
|
import Hledger.Cli.CliOptions
|
||||||
@ -114,6 +113,4 @@ diff CliOpts{file_=[f1, f2], reportspec_=ReportSpec{_rsQuery=Acct acctRe}} _ = d
|
|||||||
putStrLn "These transactions are in the second file only:\n"
|
putStrLn "These transactions are in the second file only:\n"
|
||||||
mapM_ (T.putStr . showTransaction) unmatchedtxn2
|
mapM_ (T.putStr . showTransaction) unmatchedtxn2
|
||||||
|
|
||||||
diff _ _ = do
|
diff _ _ = error' "Please specify two input files. Usage: hledger diff -f FILE1 -f FILE2 FULLACCOUNTNAME"
|
||||||
putStrLn "Please specify two input files. Usage: hledger diff -f FILE1 -f FILE2 FULLACCOUNTNAME"
|
|
||||||
exitFailure
|
|
||||||
|
|||||||
@ -31,7 +31,6 @@ import qualified Data.Text.Lazy.Builder as TB
|
|||||||
import Lens.Micro ((^.), _Just, has)
|
import Lens.Micro ((^.), _Just, has)
|
||||||
import Safe (lastMay, minimumDef)
|
import Safe (lastMay, minimumDef)
|
||||||
import System.Console.CmdArgs.Explicit
|
import System.Console.CmdArgs.Explicit
|
||||||
import System.Exit (exitFailure)
|
|
||||||
|
|
||||||
import Hledger
|
import Hledger
|
||||||
import Hledger.Write.Beancount (accountNameToBeancount, showTransactionBeancount, showBeancountMetadata)
|
import Hledger.Write.Beancount (accountNameToBeancount, showTransactionBeancount, showBeancountMetadata)
|
||||||
@ -124,7 +123,7 @@ print' opts j = do
|
|||||||
-- XXX should match similarly to register --match
|
-- XXX should match similarly to register --match
|
||||||
case journalSimilarTransaction opts j' (dbg1 "finding best match for description" $ T.pack desc) of
|
case journalSimilarTransaction opts j' (dbg1 "finding best match for description" $ T.pack desc) of
|
||||||
Just t -> printEntries opts j'{jtxns=[t]}
|
Just t -> printEntries opts j'{jtxns=[t]}
|
||||||
Nothing -> putStrLn "no matches found." >> exitFailure
|
Nothing -> error' $ "no transactions found with descriptions like " <> show desc
|
||||||
|
|
||||||
printEntries :: CliOpts -> Journal -> IO ()
|
printEntries :: CliOpts -> Journal -> IO ()
|
||||||
printEntries opts@CliOpts{rawopts_=rawopts, reportspec_=rspec} j =
|
printEntries opts@CliOpts{rawopts_=rawopts, reportspec_=rspec} j =
|
||||||
|
|||||||
@ -41,7 +41,6 @@ import qualified Lucid
|
|||||||
import Data.List (sortBy)
|
import Data.List (sortBy)
|
||||||
import Data.Char (toUpper)
|
import Data.Char (toUpper)
|
||||||
import Data.List.Extra (intersect)
|
import Data.List.Extra (intersect)
|
||||||
import System.Exit (exitFailure)
|
|
||||||
import qualified System.IO as IO
|
import qualified System.IO as IO
|
||||||
|
|
||||||
registermode = hledgerCommandMode
|
registermode = hledgerCommandMode
|
||||||
@ -88,7 +87,7 @@ register opts@CliOpts{rawopts_=rawopts, reportspec_=rspec} j
|
|||||||
| Just desc <- maybestringopt "match" rawopts = do
|
| Just desc <- maybestringopt "match" rawopts = do
|
||||||
let ps = [p | (_,_,_,p,_) <- rpt]
|
let ps = [p | (_,_,_,p,_) <- rpt]
|
||||||
case similarPosting ps desc of
|
case similarPosting ps desc of
|
||||||
Nothing -> putStrLn "no matches found." >> exitFailure
|
Nothing -> error' $ "no postings found with description like " <> show desc
|
||||||
Just p -> TL.putStr $ postingsReportAsText opts [pri]
|
Just p -> TL.putStr $ postingsReportAsText opts [pri]
|
||||||
where pri = (Just (postingDate p)
|
where pri = (Just (postingDate p)
|
||||||
,Nothing
|
,Nothing
|
||||||
|
|||||||
@ -16,7 +16,6 @@ module Hledger.Cli.Commands.Roi (
|
|||||||
) where
|
) where
|
||||||
|
|
||||||
import Control.Monad
|
import Control.Monad
|
||||||
import System.Exit
|
|
||||||
import Data.Time.Calendar
|
import Data.Time.Calendar
|
||||||
import Text.Printf
|
import Text.Printf
|
||||||
import Data.Bifunctor (second)
|
import Data.Bifunctor (second)
|
||||||
@ -92,9 +91,8 @@ roi CliOpts{rawopts_=rawopts, reportspec_=rspec@ReportSpec{_rsReportOpts=ReportO
|
|||||||
filteredj = filterJournalTransactions investmentsQuery j
|
filteredj = filterJournalTransactions investmentsQuery j
|
||||||
trans = dbg3 "investments" $ jtxns filteredj
|
trans = dbg3 "investments" $ jtxns filteredj
|
||||||
|
|
||||||
when (null trans) $ do
|
when (null trans) $
|
||||||
putStrLn "No relevant transactions found. Check your investments query"
|
error' "No relevant transactions found. Check your investments query"
|
||||||
exitFailure
|
|
||||||
|
|
||||||
let (fullPeriod, spans) = reportSpan filteredj rspec
|
let (fullPeriod, spans) = reportSpan filteredj rspec
|
||||||
|
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
$$$ hledger check -f csvamountparse.csv
|
$$$ hledger check -f csvamountparse.csv
|
||||||
>>>2 /hledger: Error: error: could not parse "badamount" as an amount
|
>>>2 /hledger: Error: could not parse "badamount" as an amount
|
||||||
CSV record: "2022-01-03","badamount"
|
CSV record: "2022-01-03","badamount"
|
||||||
the amount rule is: %2
|
the amount rule is: %2
|
||||||
the date rule is: %1
|
the date rule is: %1
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
$$$ hledger check -f csvbalanceparse.csv
|
$$$ hledger check -f csvbalanceparse.csv
|
||||||
>>>2 /hledger: Error: error: could not parse "badbalance" as balance1 amount
|
>>>2 /hledger: Error: could not parse "badbalance" as balance1 amount
|
||||||
CSV record: "2022-01-03","badbalance"
|
CSV record: "2022-01-03","badbalance"
|
||||||
the balance rule is: %2
|
the balance rule is: %2
|
||||||
the date rule is: %1
|
the date rule is: %1
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
$$$ hledger print -f csvdateformat.csv
|
$$$ hledger print -f csvdateformat.csv
|
||||||
>>>2 /hledger: Error: error: could not parse "a" as a date using date format "YYYY\/M\/D", "YYYY-M-D" or "YYYY.M.D"
|
>>>2 /hledger: Error: could not parse "a" as a date using date format "YYYY\/M\/D", "YYYY-M-D" or "YYYY.M.D"
|
||||||
CSV record: "a","b"
|
CSV record: "a","b"
|
||||||
the date rule is: %1
|
the date rule is: %1
|
||||||
the date-format is: unspecified
|
the date-format is: unspecified
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
$$$ hledger check -f csvdateparse.csv
|
$$$ hledger check -f csvdateparse.csv
|
||||||
>>>2 /hledger: Error: error: could not parse "baddate" as a date using date format "%Y-%m-%d"
|
>>>2 /hledger: Error: could not parse "baddate" as a date using date format "%Y-%m-%d"
|
||||||
CSV record: "baddate","b"
|
CSV record: "baddate","b"
|
||||||
the date rule is: %1
|
the date rule is: %1
|
||||||
the date-format is: %Y-%m-%d
|
the date-format is: %Y-%m-%d
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
$$$ hledger check -f csvskipvalue.csv
|
$$$ hledger check -f csvskipvalue.csv
|
||||||
>>>2 /hledger: Error: could not parse skip value: "badval"
|
>>>2 /hledger: Error: could not parse skip value: badval
|
||||||
/
|
/
|
||||||
>>>= 1
|
>>>= 1
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
$$$ hledger print -f csvstatusparse.csv
|
$$$ hledger print -f csvstatusparse.csv
|
||||||
>>>2 /hledger: Error: error: could not parse "badstatus" as a cleared status \(should be \*, ! or empty\)
|
>>>2 /hledger: Error: could not parse status value "badstatus" \(should be \*, ! or empty\)
|
||||||
the parse error is: 1:1:
|
the parse error is: 1:1:
|
||||||
\|
|
\|
|
||||||
1 \| badstatus
|
1 \| badstatus
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user