more convenient timelog querying when invoked as "hours"
This commit is contained in:
parent
f733a3de80
commit
a26a56eafe
59
Options.hs
59
Options.hs
@ -3,7 +3,9 @@ where
|
|||||||
import System
|
import System
|
||||||
import System.Console.GetOpt
|
import System.Console.GetOpt
|
||||||
import System.Directory
|
import System.Directory
|
||||||
|
import System.Environment
|
||||||
import Text.Printf
|
import Text.Printf
|
||||||
|
import Data.Char (toLower)
|
||||||
import Ledger.Parse
|
import Ledger.Parse
|
||||||
import Ledger.Utils
|
import Ledger.Utils
|
||||||
import Ledger.Types
|
import Ledger.Types
|
||||||
@ -12,9 +14,13 @@ import Ledger.Dates
|
|||||||
|
|
||||||
versionno = "0.3"
|
versionno = "0.3"
|
||||||
version = printf "hledger version %s \n" versionno :: String
|
version = printf "hledger version %s \n" versionno :: String
|
||||||
defaultfile = "~/.ledger"
|
ledgerdefault = "~/.ledger"
|
||||||
fileenvvar = "LEDGER"
|
ledgerenvvar = "LEDGER"
|
||||||
usagehdr = "Usage: hledger [OPTS] COMMAND [ACCTPATTERNS] [-- DESCPATTERNS]\n" ++
|
timelogdefault = "~/.timelog"
|
||||||
|
timelogenvvar = "TIMELOG"
|
||||||
|
timeprogname = "hours"
|
||||||
|
usagehdr = "Usage: hledger [OPTION] COMMAND [ACCTPATTERNS] [-- DESCPATTERNS]\n" ++
|
||||||
|
"or: hours [OPTIONS] [PERIOD [COMMAND]]\n" ++
|
||||||
"\n" ++
|
"\n" ++
|
||||||
"Options (before command, unless using --options-anywhere):"
|
"Options (before command, unless using --options-anywhere):"
|
||||||
usageftr = "\n" ++
|
usageftr = "\n" ++
|
||||||
@ -27,7 +33,7 @@ usageftr = "\n" ++
|
|||||||
"Account and description patterns are regular expressions which filter by\n" ++
|
"Account and description patterns are regular expressions which filter by\n" ++
|
||||||
"account name and entry description. Prefix a pattern with - to negate it,\n" ++
|
"account name and entry description. Prefix a pattern with - to negate it,\n" ++
|
||||||
"and separate account and description patterns with --.\n" ++
|
"and separate account and description patterns with --.\n" ++
|
||||||
"(With --options-anywhere, use ^ and ^^.)\n" ++
|
"(With --options-anywhere, use ^ and ^^. \"hours\" implies --options-anywhere.)\n" ++
|
||||||
"\n" ++
|
"\n" ++
|
||||||
"Also: hledger [-v] test [TESTPATTERNS] to run self-tests.\n" ++
|
"Also: hledger [-v] test [TESTPATTERNS] to run self-tests.\n" ++
|
||||||
"\n"
|
"\n"
|
||||||
@ -61,7 +67,7 @@ options = [
|
|||||||
]
|
]
|
||||||
where
|
where
|
||||||
filehelp = printf "ledger file; - means use standard input. Defaults\nto the %s environment variable or %s"
|
filehelp = printf "ledger file; - means use standard input. Defaults\nto the %s environment variable or %s"
|
||||||
fileenvvar defaultfile
|
ledgerenvvar ledgerdefault
|
||||||
|
|
||||||
-- | An option value from a command-line flag.
|
-- | An option value from a command-line flag.
|
||||||
data Opt =
|
data Opt =
|
||||||
@ -97,18 +103,33 @@ optValuesForConstructor f opts = concatMap get opts
|
|||||||
optValuesForConstructors fs opts = concatMap get opts
|
optValuesForConstructors fs opts = concatMap get opts
|
||||||
where get o = if any (\f -> f v == o) fs then [v] else [] where v = value o
|
where get o = if any (\f -> f v == o) fs then [v] else [] where v = value o
|
||||||
|
|
||||||
-- | Parse the command-line arguments into ledger options, ledger command
|
-- | Parse the command-line arguments into options, command name, and
|
||||||
-- name, and ledger command arguments. Also any dates in the options are
|
-- command arguments. Any dates in the options are converted to full
|
||||||
-- converted to full YYYY/MM/DD format, while we are in the IO monad
|
-- YYYY/MM/DD format, while we are in the IO monad and can get the current
|
||||||
-- and can get the current time.
|
-- time. Arguments are parsed differently if the program was invoked as
|
||||||
|
-- "hours".
|
||||||
parseArguments :: IO ([Opt], String, [String])
|
parseArguments :: IO ([Opt], String, [String])
|
||||||
parseArguments = do
|
parseArguments = do
|
||||||
args <- getArgs
|
args <- getArgs
|
||||||
let order = if "--options-anywhere" `elem` args then Permute else RequireOrder
|
istimequery <- usingTimeProgramName
|
||||||
case (getOpt order options args) of
|
let order = if "--options-anywhere" `elem` args || istimequery
|
||||||
(opts,cmd:args,[]) -> do {opts' <- fixOptDates opts; return (opts',cmd,args)}
|
then Permute
|
||||||
(opts,[],[]) -> do {opts' <- fixOptDates opts; return (opts',[],[])}
|
else RequireOrder
|
||||||
|
let (os,as,es) = getOpt order options args
|
||||||
|
os' <- fixOptDates os
|
||||||
|
case istimequery of
|
||||||
|
False ->
|
||||||
|
case (os,as,es) of
|
||||||
|
(opts,cmd:args,[]) -> return (os',cmd,args)
|
||||||
|
(opts,[],[]) -> return (os',"",[])
|
||||||
(opts,_,errs) -> ioError (userError (concat errs ++ usage))
|
(opts,_,errs) -> ioError (userError (concat errs ++ usage))
|
||||||
|
True ->
|
||||||
|
case (os,as,es) of
|
||||||
|
(opts,p:cmd:args,[]) -> return (os' ++ [Period p],cmd,args)
|
||||||
|
(opts,p:args,[]) -> return ([Period p,SubTotal] ++ os',"balance",args)
|
||||||
|
(opts,[],[]) -> return ([Period "today",SubTotal] ++ os',"balance",[])
|
||||||
|
(opts,_,errs) -> ioError (userError (concat errs ++ usage))
|
||||||
|
|
||||||
|
|
||||||
-- | Convert any fuzzy dates within these option values to explicit ones,
|
-- | Convert any fuzzy dates within these option values to explicit ones,
|
||||||
-- based on today's date.
|
-- based on today's date.
|
||||||
@ -170,10 +191,20 @@ displayFromOpts opts = listtomaybe $ optValuesForConstructor Display opts
|
|||||||
listtomaybe [] = Nothing
|
listtomaybe [] = Nothing
|
||||||
listtomaybe vs = Just $ last vs
|
listtomaybe vs = Just $ last vs
|
||||||
|
|
||||||
|
-- | Was the program invoked via the \"hours\" alias ?
|
||||||
|
usingTimeProgramName :: IO Bool
|
||||||
|
usingTimeProgramName = do
|
||||||
|
progname <- getProgName
|
||||||
|
return $ map toLower progname == timeprogname
|
||||||
|
|
||||||
-- | Get the ledger file path from options, an environment variable, or a default
|
-- | Get the ledger file path from options, an environment variable, or a default
|
||||||
ledgerFilePathFromOpts :: [Opt] -> IO String
|
ledgerFilePathFromOpts :: [Opt] -> IO String
|
||||||
ledgerFilePathFromOpts opts = do
|
ledgerFilePathFromOpts opts = do
|
||||||
envordefault <- getEnv fileenvvar `catch` \_ -> return defaultfile
|
istimequery <- usingTimeProgramName
|
||||||
|
let (e,d) = if istimequery
|
||||||
|
then (timelogenvvar,timelogdefault)
|
||||||
|
else (ledgerenvvar,ledgerdefault)
|
||||||
|
envordefault <- getEnv e `catch` \_ -> return d
|
||||||
paths <- mapM tildeExpand $ [envordefault] ++ optValuesForConstructor File opts
|
paths <- mapM tildeExpand $ [envordefault] ++ optValuesForConstructor File opts
|
||||||
return $ last paths
|
return $ last paths
|
||||||
|
|
||||||
|
|||||||
31
README
31
README
@ -37,9 +37,12 @@ To get the latest development code do::
|
|||||||
darcs get http://joyful.com/repos/hledger
|
darcs get http://joyful.com/repos/hledger
|
||||||
|
|
||||||
|
|
||||||
Examples
|
Usage
|
||||||
--------
|
-----
|
||||||
Here are some commands to try::
|
hledger looks for your ledger file at ~/.ledger by default. To use a
|
||||||
|
different file, specify it with the LEDGER environment variable or -f
|
||||||
|
option (which may be - for standard input). Here are some commands to
|
||||||
|
try::
|
||||||
|
|
||||||
hledger --help
|
hledger --help
|
||||||
hledger -f sample.ledger balance
|
hledger -f sample.ledger balance
|
||||||
@ -50,9 +53,27 @@ Here are some commands to try::
|
|||||||
hledger reg -- shop
|
hledger reg -- shop
|
||||||
hledger ui
|
hledger ui
|
||||||
|
|
||||||
hledger looks for your ledger file at ~/.ledger by default. To use a different file,
|
|
||||||
specify it with -f or the LEDGER environment variable.
|
|
||||||
|
|
||||||
|
Time reporting
|
||||||
|
--------------
|
||||||
|
hledger can parse a timelog file in timeclock.el's format, treating time
|
||||||
|
categories as accounts. If hledger is invoked by the "hours" alias it
|
||||||
|
looks for your timelog, and parses arguments slightly differently for
|
||||||
|
convenient querying:
|
||||||
|
|
||||||
|
hours [OPTIONS] [PERIOD [COMMAND]]
|
||||||
|
|
||||||
|
PERIOD and COMMAND default to "today" and "balance --subtotal"
|
||||||
|
respectively, and --options-anywhere is assumed. The timelog is found in
|
||||||
|
the same way as your ledger: ~/.timelog or the file specified by $TIMELOG
|
||||||
|
or an -f option. Examples:
|
||||||
|
|
||||||
|
hours # today's balances
|
||||||
|
hours today # the same
|
||||||
|
hours 'this week' # so far this week
|
||||||
|
hours week # the same
|
||||||
|
hours lastmonth # last month, the space is optional
|
||||||
|
hours 'monthly in 2008' reg --depth 1 # monthly register, top-level only
|
||||||
|
|
||||||
Features
|
Features
|
||||||
--------
|
--------
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user