support tilde (~) in journal and rules file paths

This commit is contained in:
Simon Michael 2012-05-30 08:36:01 +00:00
parent 776ad2a098
commit 0b96a767b4
5 changed files with 30 additions and 31 deletions

View File

@ -179,7 +179,8 @@ includedirective = do
filename <- restofline filename <- restofline
outerState <- getState outerState <- getState
outerPos <- getPosition outerPos <- getPosition
return $ do filepath <- expandPath outerPos filename let curdir = takeDirectory (sourceName outerPos)
return $ do filepath <- expandPath curdir filename
txt <- readFileOrError outerPos filepath txt <- readFileOrError outerPos filepath
let inIncluded = show outerPos ++ " in included file " ++ show filename ++ ":\n" let inIncluded = show outerPos ++ " in included file " ++ show filename ++ ":\n"
case runParser journal outerState filepath txt of case runParser journal outerState filepath txt of

View File

@ -26,7 +26,9 @@ module Hledger.Utils (---- provide these frequently used modules - or not, for c
-- the rest need to be done in each module I think -- the rest need to be done in each module I think
) )
where where
import Control.Monad.Error import Control.Monad (liftM)
import Control.Monad.Error (MonadIO)
import Control.Monad.IO.Class (liftIO)
import Data.Char import Data.Char
import Data.List import Data.List
import Data.Maybe import Data.Maybe
@ -35,7 +37,7 @@ import Data.Time.LocalTime
import Data.Tree import Data.Tree
import Debug.Trace import Debug.Trace
import System.Directory (getHomeDirectory) import System.Directory (getHomeDirectory)
import System.FilePath(takeDirectory,combine) import System.FilePath((</>), isRelative)
import Test.HUnit import Test.HUnit
import Text.ParserCombinators.Parsec import Text.ParserCombinators.Parsec
import Text.Printf import Text.Printf
@ -401,15 +403,16 @@ isRight = not . isLeft
applyN :: Int -> (a -> a) -> a -> a applyN :: Int -> (a -> a) -> a -> a
applyN n f = (!! n) . iterate f applyN n f = (!! n) . iterate f
-- | Convert a possibly relative, possibly tilde-containing file path to an absolute one. -- | Convert a possibly relative, possibly tilde-containing file path to an absolute one,
-- using the current directory from a parsec source position. ~username is not supported. -- given the current directory. ~username is not supported. Leave "-" unchanged.
expandPath :: (MonadIO m) => SourcePos -> FilePath -> m FilePath expandPath :: MonadIO m => FilePath -> FilePath -> m FilePath -- general type sig for use in reader parsers
expandPath pos fp = liftM mkAbsolute (expandHome fp) expandPath _ "-" = return "-"
expandPath curdir p = (if isRelative p then (curdir </>) else id) `liftM` expandPath' p
where where
mkAbsolute = combine (takeDirectory (sourceName pos)) expandPath' ('~':'/':p) = liftIO $ (</> p) `fmap` getHomeDirectory
expandHome inname | "~/" `isPrefixOf` inname = do homedir <- liftIO getHomeDirectory expandPath' ('~':'\\':p) = liftIO $ (</> p) `fmap` getHomeDirectory
return $ homedir ++ drop 1 inname expandPath' ('~':_) = error' "~USERNAME in paths is not supported"
| otherwise = return inname expandPath' p = return p
firstJust ms = case dropWhile (==Nothing) ms of firstJust ms = case dropWhile (==Nothing) ms of
[] -> Nothing [] -> Nothing

View File

@ -456,25 +456,18 @@ defaultBalanceFormatString = [
, FormatField True Nothing Nothing AccountField , FormatField True Nothing Nothing AccountField
] ]
-- | Get the journal file path from options, an environment variable, or a default. -- | Get the (tilde-expanded, absolute) journal file path from options, an environment variable, or a default.
-- If the path contains a literal tilde raise an error to avoid confusion. XXX
journalFilePathFromOpts :: CliOpts -> IO String journalFilePathFromOpts :: CliOpts -> IO String
journalFilePathFromOpts opts = do journalFilePathFromOpts opts = do
f <- defaultJournalPath f <- defaultJournalPath
let f' = fromMaybe f $ file_ opts d <- getCurrentDirectory
if '~' `elem` f' expandPath d $ fromMaybe f $ file_ opts
then error' $ printf "~ in the journal file path is not supported, please adjust (%s)" f'
else return f'
-- | Get the rules file path from options, if any. -- | Get the (tilde-expanded) rules file path from options, if any.
-- If the path contains a literal tilde raise an error to avoid confusion. XXX rulesFilePathFromOpts :: CliOpts -> IO (Maybe FilePath)
rulesFilePathFromOpts :: CliOpts -> Maybe FilePath rulesFilePathFromOpts opts = do
rulesFilePathFromOpts opts = d <- getCurrentDirectory
case rules_file_ opts of maybe (return Nothing) (fmap Just . expandPath d) $ rules_file_ opts
Nothing -> Nothing
Just f -> if '~' `elem` f
then error' $ printf "~ in file paths is not supported, please adjust (%s)" f
else Just f
aliasesFromOpts :: CliOpts -> [(AccountName,AccountName)] aliasesFromOpts :: CliOpts -> [(AccountName,AccountName)]
aliasesFromOpts = map parseAlias . alias_ aliasesFromOpts = map parseAlias . alias_

View File

@ -48,8 +48,10 @@ withJournalDo opts cmd = do
-- We kludgily read the file before parsing to grab the full text, unless -- We kludgily read the file before parsing to grab the full text, unless
-- it's stdin, or it doesn't exist and we are adding. We read it strictly -- it's stdin, or it doesn't exist and we are adding. We read it strictly
-- to let the add command work. -- to let the add command work.
journalFilePathFromOpts opts >>= readJournalFile Nothing (rulesFilePathFromOpts opts) >>= rulespath <- rulesFilePathFromOpts opts
either error' (cmd opts . journalApplyAliases (aliasesFromOpts opts)) journalpath <- journalFilePathFromOpts opts
ej <- readJournalFile Nothing rulespath journalpath
either error' (cmd opts . journalApplyAliases (aliasesFromOpts opts)) ej
-- -- | Get a journal from the given string and options, or throw an error. -- -- | Get a journal from the given string and options, or throw an error.
-- readJournalWithOpts :: CliOpts -> String -> IO Journal -- readJournalWithOpts :: CliOpts -> String -> IO Journal

View File

@ -5,7 +5,7 @@
income:unknown $-50 income:unknown $-50
assets:myacct $50 assets:myacct $50
>>>2 /using conversion rules file t.rules/ >>>2 /using conversion rules file.*t.rules/
>>>=0 >>>=0
# 2. reading CSV with in-field and out-field # 2. reading CSV with in-field and out-field
@ -22,7 +22,7 @@
expenses:unknown $50 expenses:unknown $50
Assets:MyAccount $-50 Assets:MyAccount $-50
>>>2 /using conversion rules file [0-9]+\.rules/ >>>2 /using conversion rules file.*[0-9]+\.rules/
>>>=0 >>>=0
# 3. report rules parse error # 3. report rules parse error
@ -32,6 +32,6 @@
# income:unknown $-50 # income:unknown $-50
# assets:myacct $50 # assets:myacct $50
# >>>2 /using conversion rules file t.rules/ # >>>2 /using conversion rules file.*t.rules/
# >>>=0 # >>>=0