add: ui cleanups

- tidier output
- show more help
- suggest . only for recording, not for quitting (though it still works)
- show each transaction after adding it (#52)
- don't parse . as a zero amount
- don't show [] when there's no default
This commit is contained in:
Simon Michael 2013-02-23 00:57:16 +00:00
parent 2a6a028222
commit 7fcd45614b
2 changed files with 30 additions and 18 deletions

View File

@ -48,10 +48,14 @@ add :: CliOpts -> Journal -> IO ()
add opts j add opts j
| f == "-" = return () | f == "-" = return ()
| otherwise = do | otherwise = do
hPrintf stderr "Adding transactions to journal file \"%s\".\n" f hPutStrLn stderr $ unlines [
hPutStrLn stderr $ "Adding transactions to journal file "++f
"To complete a transaction, enter . (period) at an account prompt.\n" ,"Provide field values at the prompts, or press enter to accept defaults."
++"To stop adding transactions, enter . at a date prompt, or control-d/control-c." ,"Use readline keys to edit, use tab key to complete account names."
-- ,"If you make a mistake, enter < at any prompt to restart the transaction."
,"To record a transaction, enter . when prompted."
,"To quit, press control-d or control-c."
]
today <- getCurrentDay today <- getCurrentDay
getAndAddTransactions j opts today getAndAddTransactions j opts today
`C.catch` (\e -> unless (isEOFError e) $ ioError e) `C.catch` (\e -> unless (isEOFError e) $ ioError e)
@ -65,6 +69,7 @@ getAndAddTransactions :: Journal -> CliOpts -> Day -> IO ()
getAndAddTransactions j opts defaultDate = do getAndAddTransactions j opts defaultDate = do
(t, d) <- getTransaction j opts defaultDate (t, d) <- getTransaction j opts defaultDate
j <- journalAddTransaction j opts t j <- journalAddTransaction j opts t
hPrintf stderr "\nRecorded transaction:\n%s" (show t)
getAndAddTransactions j opts d getAndAddTransactions j opts d
-- | Read a transaction from the command line, with history-aware prompting. -- | Read a transaction from the command line, with history-aware prompting.
@ -72,7 +77,7 @@ getTransaction :: Journal -> CliOpts -> Day
-> IO (Transaction,Day) -> IO (Transaction,Day)
getTransaction j opts defaultDate = do getTransaction j opts defaultDate = do
today <- getCurrentDay today <- getCurrentDay
datestr <- runInteractionDefault $ askFor "date, or . to end" datestr <- runInteractionDefault $ askFor "date"
(Just $ showDate defaultDate) (Just $ showDate defaultDate)
(Just $ \s -> null s (Just $ \s -> null s
|| s == "." || s == "."
@ -97,15 +102,20 @@ getTransaction j opts defaultDate = do
,tpostings=ps ,tpostings=ps
} }
retry msg = do retry msg = do
liftIO $ hPutStrLn stderr $ "\n" ++ msg ++ "please re-enter." let msg' = capitalize msg
liftIO $ hPutStrLn stderr $ "\n" ++ msg' ++ "please re-enter."
getpostingsandvalidate getpostingsandvalidate
either retry (return . flip (,) date) $ balanceTransaction Nothing t -- imprecise balancing either retry (return . flip (,) date) $ balanceTransaction Nothing t -- imprecise balancing
unless (null historymatches) unless (null historymatches) $
(liftIO $ do liftIO $ hPutStr stderr $
hPutStrLn stderr "Similar transactions found, using the first for defaults:\n" "\nSimilar transactions found, using the first for defaults:\n"
hPutStr stderr $ concatMap (\(n,t) -> printf "[%3d%%] %s" (round $ n*100 :: Int) (show t)) $ take 3 historymatches) ++ concatMap (\(n,t) -> printf "[%3d%%] %s" (round $ n*100 :: Int) (show t)) (take 3 historymatches)
getpostingsandvalidate getpostingsandvalidate
capitalize :: String -> String
capitalize "" = ""
capitalize (c:cs) = toUpper c : cs
-- fragile -- fragile
-- | Read postings from the command line until . is entered, using any -- | Read postings from the command line until . is entered, using any
-- provided historical postings and the journal context to guess defaults. -- provided historical postings and the journal context to guess defaults.
@ -117,7 +127,7 @@ getPostings st enteredps = do
where Just ps = historicalps where Just ps = historicalps
defaultaccount = maybe Nothing (Just . showacctname) bestmatch defaultaccount = maybe Nothing (Just . showacctname) bestmatch
ordot | null enteredps || length enteredrealps == 1 = "" :: String ordot | null enteredps || length enteredrealps == 1 = "" :: String
| otherwise = ", or . to record" | otherwise = " (or . to record)"
account <- runInteraction j $ askFor (printf "account %d%s" n ordot) defaultaccount (Just accept) account <- runInteraction j $ askFor (printf "account %d%s" n ordot) defaultaccount (Just accept)
if account=="." if account=="."
then then
@ -175,7 +185,8 @@ getPostings st enteredps = do
postingtype ('(':_) = VirtualPosting postingtype ('(':_) = VirtualPosting
postingtype _ = RegularPosting postingtype _ = RegularPosting
validateamount = Just $ \s -> (null s && not (null enteredrealps)) validateamount = Just $ \s -> (null s && not (null enteredrealps))
|| isRight (runParser (amountp >> many spacenonewline >> eof) ctx "" s) || (s /= "."
&& isRight (runParser (amountp >> many spacenonewline >> eof) ctx "" s))
-- | Prompt for and read a string value, optionally with a default value -- | Prompt for and read a string value, optionally with a default value
-- and a validator. A validator causes the prompt to repeat until the -- and a validator. A validator causes the prompt to repeat until the
@ -183,7 +194,7 @@ getPostings st enteredps = do
askFor :: String -> Maybe String -> Maybe (String -> Bool) -> InputT IO String askFor :: String -> Maybe String -> Maybe (String -> Bool) -> InputT IO String
askFor prompt def validator = do askFor prompt def validator = do
l <- fmap (maybe eofErr id) l <- fmap (maybe eofErr id)
$ getInputLine $ prompt ++ maybe "" showdef def ++ ": " $ getInputLine $ prompt ++ " ? " ++ maybe "" showdef def ++ ": "
let input = if null l then fromMaybe l def else l let input = if null l then fromMaybe l def else l
case validator of case validator of
Just valid -> if valid input Just valid -> if valid input
@ -191,7 +202,8 @@ askFor prompt def validator = do
else askFor prompt def validator else askFor prompt def validator
Nothing -> return input Nothing -> return input
where where
showdef s = " [" ++ s ++ "]" showdef "" = ""
showdef s = "[" ++ s ++ "]"
eofErr = C.throw $ mkIOError eofErrorType "end of input" Nothing Nothing eofErr = C.throw $ mkIOError eofErrorType "end of input" Nothing Nothing
-- | Append this transaction to the journal's file, and to the journal's -- | Append this transaction to the journal's file, and to the journal's

View File

@ -5,14 +5,14 @@
hledgerdev -f $$-add.j add; rm -f $$-add.j hledgerdev -f $$-add.j add; rm -f $$-add.j
<<< <<<
2009/1/32 2009/1/32
>>> /date, or \. to end.*: date, or \. to end.*/ >>> /date .*: date .*/
>>>=0 >>>=0
# 2. should accept a blank date # 2. should accept a blank date
hledgerdev -f $$-add.j add; rm -f $$-add.j hledgerdev -f $$-add.j add; rm -f $$-add.j
<<< <<<
>>> /date,.*: description/ >>> /date .*: description /
>>>=0 >>>=0
############################################################################## ##############################################################################
@ -28,7 +28,7 @@ a
b b
. .
>>> /^date, or \. to end \[.*\]: description \[\]: account 1: amount 1: account 2: amount 2 \[-1000.0\]: account 3, or \. to record: date, or \. to end \[.*\]: $/ >>> /^date.*: description.*: account 1.*: amount 1.*: account 2.*: amount 2.*: account 3.*or \. to record.*: date.*: $/
>>>=0 >>>=0
# 4. default commodity with greater precision # 4. default commodity with greater precision
@ -107,7 +107,7 @@ a
b b
0.5 0.5
c c
>>> /amount 3 \[-0.75\]/ >>> /amount 3 \? \[-0.75\]/
>>>=0 >>>=0
## 10. shouldn't add decimals if there aren't any ## 10. shouldn't add decimals if there aren't any