mirror of
https://github.com/simonmichael/hledger.git
synced 2024-12-26 03:42:25 +03:00
Allow separator to be overridden from command line
This also fixes that parsing separators on the command line and the rules file was not handled the same way.
This commit is contained in:
parent
b524a088c7
commit
02d9205af7
@ -50,6 +50,7 @@ module Hledger.Read.Common (
|
||||
getAccountAliases,
|
||||
clearAccountAliases,
|
||||
journalAddFile,
|
||||
getSpecialSeparators,
|
||||
|
||||
-- * parsers
|
||||
-- ** transaction bits
|
||||
@ -162,7 +163,7 @@ data InputOpts = InputOpts {
|
||||
mformat_ :: Maybe StorageFormat -- ^ a file/storage format to try, unless overridden
|
||||
-- by a filename prefix. Nothing means try all.
|
||||
,mrules_file_ :: Maybe FilePath -- ^ a conversion rules file to use (when reading CSV)
|
||||
,separator_ :: Char -- ^ the separator to use (when reading CSV)
|
||||
,separator_ :: Maybe Char -- ^ the separator to use (when reading CSV)
|
||||
,aliases_ :: [String] -- ^ account name aliases to apply
|
||||
,anon_ :: Bool -- ^ do light anonymisation/obfuscation of the data
|
||||
,ignore_assertions_ :: Bool -- ^ don't check balance assertions
|
||||
@ -175,14 +176,14 @@ data InputOpts = InputOpts {
|
||||
instance Default InputOpts where def = definputopts
|
||||
|
||||
definputopts :: InputOpts
|
||||
definputopts = InputOpts def def ',' def def def def True def def
|
||||
definputopts = InputOpts def def def def def def def True def def
|
||||
|
||||
rawOptsToInputOpts :: RawOpts -> InputOpts
|
||||
rawOptsToInputOpts rawopts = InputOpts{
|
||||
-- files_ = listofstringopt "file" rawopts
|
||||
mformat_ = Nothing
|
||||
,mrules_file_ = maybestringopt "rules-file" rawopts
|
||||
,separator_ = fromMaybe ',' (maybecharopt "separator" rawopts)
|
||||
,separator_ = maybestringopt "separator" rawopts >>= getSpecialSeparators
|
||||
,aliases_ = listofstringopt "alias" rawopts
|
||||
,anon_ = boolopt "anon" rawopts
|
||||
,ignore_assertions_ = boolopt "ignore-assertions" rawopts
|
||||
@ -194,6 +195,14 @@ rawOptsToInputOpts rawopts = InputOpts{
|
||||
|
||||
--- * parsing utilities
|
||||
|
||||
-- | Parse special separator names TAB and SPACE, or return the first
|
||||
-- character. Return Nothing on empty string
|
||||
getSpecialSeparators :: String -> Maybe Char
|
||||
getSpecialSeparators "SPACE" = Just ' '
|
||||
getSpecialSeparators "TAB" = Just '\t'
|
||||
getSpecialSeparators (x:_) = Just x
|
||||
getSpecialSeparators [] = Nothing
|
||||
|
||||
-- | Run a text parser in the identity monad. See also: parseWithState.
|
||||
runTextParser, rtp
|
||||
:: TextParser Identity a -> Text -> Either (ParseErrorBundle Text CustomErr) a
|
||||
|
@ -71,7 +71,7 @@ import Text.Printf (printf)
|
||||
|
||||
import Hledger.Data
|
||||
import Hledger.Utils
|
||||
import Hledger.Read.Common (Reader(..),InputOpts(..),amountp, statusp, genericSourcePos, finaliseJournal)
|
||||
import Hledger.Read.Common (Reader(..),InputOpts(..),amountp, statusp, genericSourcePos, getSpecialSeparators, finaliseJournal)
|
||||
|
||||
type CSV = [Record]
|
||||
|
||||
@ -104,13 +104,13 @@ parse iopts f t = do
|
||||
-- better preemptively reverse them once more. XXX inefficient
|
||||
pj' = journalReverse pj
|
||||
|
||||
getSeparatorFromRules :: Char -> CsvRules -> Char
|
||||
getSeparatorFromRules defaultSeparator rules =
|
||||
maybe defaultSeparator id (getSeparator <$> getDirective "separator" rules)
|
||||
where getSeparator :: String -> Char
|
||||
getSeparator "SPACE" = ' '
|
||||
getSeparator "TAB" = '\t'
|
||||
getSeparator x = head x
|
||||
-- | Decide which separator to get.
|
||||
-- If the external separator is provided, take it. Otherwise, look at the rules. Finally, return ','.
|
||||
getSeparator :: Maybe Char -> CsvRules -> Char
|
||||
getSeparator externalSeparator rules = head $
|
||||
catMaybes [ externalSeparator
|
||||
, getDirective "separator" rules >>= getSpecialSeparators
|
||||
, Just ',']
|
||||
|
||||
-- | Read a Journal from the given CSV data (and filename, used for error
|
||||
-- messages), or return an error. Proceed as follows:
|
||||
@ -123,9 +123,9 @@ getSeparatorFromRules defaultSeparator rules =
|
||||
-- 4. if the rules file didn't exist, create it with the default rules and filename
|
||||
-- 5. return the transactions as a Journal
|
||||
-- @
|
||||
readJournalFromCsv :: Char -> Maybe FilePath -> FilePath -> Text -> IO (Either String Journal)
|
||||
readJournalFromCsv :: Maybe Char -> Maybe FilePath -> FilePath -> Text -> IO (Either String Journal)
|
||||
readJournalFromCsv _ Nothing "-" _ = return $ Left "please use --rules-file when reading CSV from stdin"
|
||||
readJournalFromCsv separator mrulesfile csvfile csvdata =
|
||||
readJournalFromCsv commandLineSeparator mrulesfile csvfile csvdata =
|
||||
handle (\(e::IOException) -> return $ Left $ show e) $ do
|
||||
|
||||
-- make and throw an IO exception.. which we catch and convert to an Either above ?
|
||||
@ -156,7 +156,7 @@ readJournalFromCsv separator mrulesfile csvfile csvdata =
|
||||
records <- (either throwerr id .
|
||||
dbg2 "validateCsv" . validateCsv rules skiplines .
|
||||
dbg2 "parseCsv")
|
||||
`fmap` parseCsv (getSeparatorFromRules separator rules) parsecfilename csvdata
|
||||
`fmap` parseCsv (getSeparator commandLineSeparator rules) parsecfilename csvdata
|
||||
dbg1IO "first 3 csv records" $ take 3 records
|
||||
|
||||
-- identify header lines
|
||||
|
@ -527,7 +527,7 @@ $ ./hledger-csv
|
||||
|
||||
>=0
|
||||
|
||||
# 25. specify alternative delimiter in rules
|
||||
# 25. specify alternative whitespace delimiter in rules
|
||||
<
|
||||
2009/10/01 Flubber Co 50 123
|
||||
|
||||
@ -539,7 +539,40 @@ separator TAB
|
||||
|
||||
$ ./hledger-csv
|
||||
2009/10/01 Flubber Co
|
||||
(assets:myacct) $50 = $123
|
||||
(assets:myacct) $50 = $123
|
||||
|
||||
>=0
|
||||
|
||||
# 26. specify char delimiter in rules
|
||||
<
|
||||
2009/10/01;Flubber Co;50;123
|
||||
|
||||
RULES
|
||||
fields date, description, amount, balance
|
||||
currency $
|
||||
account1 (assets:myacct)
|
||||
separator ;
|
||||
|
||||
$ ./hledger-csv
|
||||
2009/10/01 Flubber Co
|
||||
(assets:myacct) $50 = $123
|
||||
|
||||
>=0
|
||||
|
||||
# 27. command line delimiter overrides configuration file
|
||||
<
|
||||
2009/10/01 Flubber Co 50 123
|
||||
|
||||
RULES
|
||||
fields date, description, amount, balance
|
||||
currency $
|
||||
account1 (assets:myacct)
|
||||
separator ;
|
||||
|
||||
$ ./hledger-csv --separator 'TAB'
|
||||
2009/10/01 Flubber Co
|
||||
(assets:myacct) $50 = $123
|
||||
|
||||
>=0
|
||||
|
||||
## 25. A single unbalanced posting with number other than 1 also should not generate a balancing posting.
|
||||
|
Loading…
Reference in New Issue
Block a user