Skip to content

Commit 2ded84e

Browse files
committed
Make usages of Turtle explicit
1 parent 8127b45 commit 2ded84e

File tree

7 files changed

+228
-222
lines changed

7 files changed

+228
-222
lines changed

app/Main.hs

+8-8
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
module Main where
55

66
import Path
7-
import Turtle hiding (switch)
7+
import qualified Turtle as Turtle hiding (switch)
88
import Prelude hiding (putStrLn)
99

1010
import Options.Applicative
@@ -32,9 +32,9 @@ data BaseCommand = Version | Command { mainParams :: MainParams, command :: Comm
3232

3333
main :: IO ()
3434
main = do
35-
cmd <- options "An hledger workflow focusing on automated statement import and classification:\nhttps://github.com/apauley/hledger-flow#readme" baseCommandParser
35+
cmd <- Turtle.options "An hledger workflow focusing on automated statement import and classification:\nhttps://github.com/apauley/hledger-flow#readme" baseCommandParser
3636
case cmd of
37-
Version -> stdout $ select versionInfo
37+
Version -> Turtle.stdout $ Turtle.select versionInfo
3838
Command mainParams' (Import subParams) -> toRuntimeOptionsImport mainParams' subParams >>= importCSVs
3939
Command mainParams' (Report subParams) -> toRuntimeOptionsReport mainParams' subParams >>= generateReports
4040

@@ -73,21 +73,21 @@ baseCommandParser = (Command <$> verboseParser <*> commandParser)
7373
<|> flag' Version (long "version" <> short 'V' <> help "Display version information")
7474

7575
commandParser :: Parser Command
76-
commandParser = fmap Import (subcommand "import" "Uses hledger with your own rules and/or scripts to convert electronic statements into categorised journal files" subcommandParserImport)
77-
<|> fmap Report (subcommand "report" "Generate Reports" subcommandParserReport)
76+
commandParser = fmap Import (Turtle.subcommand "import" "Uses hledger with your own rules and/or scripts to convert electronic statements into categorised journal files" subcommandParserImport)
77+
<|> fmap Report (Turtle.subcommand "report" "Generate Reports" subcommandParserReport)
7878

7979
verboseParser :: Parser MainParams
8080
verboseParser = MainParams
8181
<$> (length <$> many (flag' () (long "verbose" <> short 'v' <> help "Print more verbose output")))
82-
<*> optional (optPath "hledger-path" 'H' "The full path to an hledger executable")
82+
<*> optional (Turtle.optPath "hledger-path" 'H' "The full path to an hledger executable")
8383
<*> switch (long "show-options" <> help "Print the options this program will run with")
8484
<*> switch (long "sequential" <> help "Disable parallel processing")
8585

8686
subcommandParserImport :: Parser ImportParams
8787
subcommandParserImport = ImportParams
88-
<$> optional (argPath "dir" "The directory to import. Use the base directory for a full import or a sub-directory for a partial import. Defaults to the current directory. This behaviour is changing: see --enable-future-rundir")
88+
<$> optional (Turtle.argPath "dir" "The directory to import. Use the base directory for a full import or a sub-directory for a partial import. Defaults to the current directory. This behaviour is changing: see --enable-future-rundir")
8989
<*> switch (long "enable-future-rundir" <> help "Enable the future (0.14.x) default behaviour now: start importing only from the directory that was given as an argument, or the currect directory. Previously a full import was always done. This switch will be removed in 0.14.x")
9090

9191
subcommandParserReport :: Parser ReportParams
9292
subcommandParserReport = ReportParams
93-
<$> optional (argPath "basedir" "The hledger-flow base directory")
93+
<$> optional (Turtle.argPath "basedir" "The hledger-flow base directory")

src/Hledger/Flow/CSVImport.hs

+47-46
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@ module Hledger.Flow.CSVImport
44
( importCSVs
55
) where
66

7-
import Turtle hiding (stdout, stderr, proc, procStrictWithErr)
7+
import qualified Turtle as Turtle hiding (stdout, stderr, proc, procStrictWithErr)
8+
import Turtle ((%), (</>), (<.>))
89
import Prelude hiding (putStrLn, take)
910
import qualified Data.Text as T
1011
import qualified Data.List.NonEmpty as NonEmpty
@@ -18,43 +19,43 @@ import Hledger.Flow.RuntimeOptions
1819
import Control.Concurrent.STM
1920

2021
importCSVs :: RuntimeOptions -> IO ()
21-
importCSVs opts = sh (
22+
importCSVs opts = Turtle.sh (
2223
do
23-
ch <- liftIO newTChanIO
24-
logHandle <- fork $ consoleChannelLoop ch
25-
liftIO $ if (showOptions opts) then channelOutLn ch (repr opts) else return ()
26-
liftIO $ logVerbose opts ch "Starting import"
27-
(journals, diff) <- time $ liftIO $ importCSVs' opts ch
28-
liftIO $ channelOutLn ch $ format ("Imported "%d%" journals in "%s) (length journals) $ repr diff
29-
liftIO $ terminateChannelLoop ch
30-
wait logHandle
24+
ch <- Turtle.liftIO newTChanIO
25+
logHandle <- Turtle.fork $ consoleChannelLoop ch
26+
Turtle.liftIO $ if (showOptions opts) then channelOutLn ch (Turtle.repr opts) else return ()
27+
Turtle.liftIO $ logVerbose opts ch "Starting import"
28+
(journals, diff) <- Turtle.time $ Turtle.liftIO $ importCSVs' opts ch
29+
Turtle.liftIO $ channelOutLn ch $ Turtle.format ("Imported "%Turtle.d%" journals in "%Turtle.s) (length journals) $ Turtle.repr diff
30+
Turtle.liftIO $ terminateChannelLoop ch
31+
Turtle.wait logHandle
3132
)
3233

3334
pathSeparators :: [Char]
3435
pathSeparators = ['/', '\\', ':']
3536

36-
inputFilePattern :: Pattern Text
37-
inputFilePattern = contains (once (oneOf pathSeparators) <> asciiCI "1-in" <> once (oneOf pathSeparators) <> plus digit <> once (oneOf pathSeparators))
37+
inputFilePattern :: Turtle.Pattern T.Text
38+
inputFilePattern = Turtle.contains (Turtle.once (Turtle.oneOf pathSeparators) <> Turtle.asciiCI "1-in" <> Turtle.once (Turtle.oneOf pathSeparators) <> Turtle.plus Turtle.digit <> Turtle.once (Turtle.oneOf pathSeparators))
3839

3940
importCSVs' :: RuntimeOptions -> TChan FlowTypes.LogMessage -> IO [TurtlePath]
4041
importCSVs' opts ch = do
4142
let baseImportDir = forceTrailingSlash $ (turtleBaseDir opts) </> "import"
42-
let runDir = forceTrailingSlash $ collapse $ (turtleBaseDir opts) </> (turtleRunDir opts)
43+
let runDir = forceTrailingSlash $ Turtle.collapse $ (turtleBaseDir opts) </> (turtleRunDir opts)
4344
let effectiveDir = if useRunDir opts
4445
then if (forceTrailingSlash $ runDir </> "import") == baseImportDir then baseImportDir else runDir
4546
else baseImportDir
46-
channelOutLn ch $ format ("Collecting input files from "%fp) effectiveDir
47-
(inputFiles, diff) <- time $ single . shellToList . onlyFiles $ find inputFilePattern effectiveDir
47+
channelOutLn ch $ Turtle.format ("Collecting input files from "%Turtle.fp) effectiveDir
48+
(inputFiles, diff) <- Turtle.time $ Turtle.single . shellToList . onlyFiles $ Turtle.find inputFilePattern effectiveDir
4849
let fileCount = length inputFiles
4950
if (fileCount == 0) then
5051
do
51-
let msg = format ("I couldn't find any input files underneath "%fp
52+
let msg = Turtle.format ("I couldn't find any input files underneath "%Turtle.fp
5253
%"\n\nhledger-flow expects to find its input files in specifically\nnamed directories.\n\n"%
53-
"Have a look at the documentation for a detailed explanation:\n"%s) effectiveDir (docURL "input-files")
54+
"Have a look at the documentation for a detailed explanation:\n"%Turtle.s) effectiveDir (docURL "input-files")
5455
errExit 1 ch msg []
5556
else
5657
do
57-
channelOutLn ch $ format ("Found "%d%" input files in "%s%". Proceeding with import...") fileCount (repr diff)
58+
channelOutLn ch $ Turtle.format ("Found "%Turtle.d%" input files in "%Turtle.s%". Proceeding with import...") fileCount (Turtle.repr diff)
5859
let actions = map (extractAndImport opts ch) inputFiles :: [IO TurtlePath]
5960
importedJournals <- parAwareActions opts actions
6061
_ <- writeIncludesUpTo opts ch effectiveDir importedJournals
@@ -81,25 +82,25 @@ importCSV opts ch importDirs srcFile = do
8182
then customConstruct opts ch constructScript bankName accountName ownerName
8283
else hledgerImport opts ch
8384
let journalOut = changePathAndExtension "3-journal" "journal" csvFile
84-
mktree $ directory journalOut
85+
Turtle.mktree $ Turtle.directory journalOut
8586
importFun csvFile journalOut
8687

87-
preprocessIfNeeded :: RuntimeOptions -> TChan FlowTypes.LogMessage -> TurtlePath -> Line -> Line -> Line -> TurtlePath -> IO TurtlePath
88+
preprocessIfNeeded :: RuntimeOptions -> TChan FlowTypes.LogMessage -> TurtlePath -> Turtle.Line -> Turtle.Line -> Turtle.Line -> TurtlePath -> IO TurtlePath
8889
preprocessIfNeeded opts ch script bank account owner src = do
8990
shouldPreprocess <- verboseTestFile opts ch script
9091
if shouldPreprocess
9192
then preprocess opts ch script bank account owner src
9293
else return src
9394

94-
preprocess :: RuntimeOptions -> TChan FlowTypes.LogMessage -> TurtlePath -> Line -> Line -> Line -> TurtlePath -> IO TurtlePath
95+
preprocess :: RuntimeOptions -> TChan FlowTypes.LogMessage -> TurtlePath -> Turtle.Line -> Turtle.Line -> Turtle.Line -> TurtlePath -> IO TurtlePath
9596
preprocess opts ch script bank account owner src = do
9697
let csvOut = changePathAndExtension "2-preprocessed" "csv" src
97-
mktree $ directory csvOut
98-
let args = [format fp src, format fp csvOut, lineToText bank, lineToText account, lineToText owner]
98+
Turtle.mktree $ Turtle.directory csvOut
99+
let args = [Turtle.format Turtle.fp src, Turtle.format Turtle.fp csvOut, Turtle.lineToText bank, Turtle.lineToText account, Turtle.lineToText owner]
99100
let relScript = relativeToBase opts script
100101
let relSrc = relativeToBase opts src
101-
let cmdLabel = format ("executing '"%fp%"' on '"%fp%"'") relScript relSrc
102-
_ <- timeAndExitOnErr opts ch cmdLabel channelOut channelErr (parAwareProc opts) (format fp script, args, empty)
102+
let cmdLabel = Turtle.format ("executing '"%Turtle.fp%"' on '"%Turtle.fp%"'") relScript relSrc
103+
_ <- timeAndExitOnErr opts ch cmdLabel channelOut channelErr (parAwareProc opts) (Turtle.format Turtle.fp script, args, Turtle.empty)
103104
return csvOut
104105

105106
hledgerImport :: RuntimeOptions -> TChan FlowTypes.LogMessage -> TurtlePath -> TurtlePath -> IO TurtlePath
@@ -117,28 +118,28 @@ hledgerImport' opts ch importDirs csvSrc journalOut = do
117118
case maybeRulesFile of
118119
Just rf -> do
119120
let relRules = relativeToBase opts rf
120-
let hledger = format fp $ FlowTypes.hlPath . hledgerInfo $ opts :: Text
121-
let args = ["print", "--rules-file", format fp rf, "--file", format fp csvSrc, "--output-file", format fp journalOut]
122-
let cmdLabel = format ("importing '"%fp%"' using rules file '"%fp%"'") relCSV relRules
123-
_ <- timeAndExitOnErr opts ch cmdLabel channelOut channelErr (parAwareProc opts) (hledger, args, empty)
121+
let hledger = Turtle.format Turtle.fp $ FlowTypes.hlPath . hledgerInfo $ opts :: T.Text
122+
let args = ["print", "--rules-file", Turtle.format Turtle.fp rf, "--file", Turtle.format Turtle.fp csvSrc, "--output-file", Turtle.format Turtle.fp journalOut]
123+
let cmdLabel = Turtle.format ("importing '"%Turtle.fp%"' using rules file '"%Turtle.fp%"'") relCSV relRules
124+
_ <- timeAndExitOnErr opts ch cmdLabel channelOut channelErr (parAwareProc opts) (hledger, args, Turtle.empty)
124125
return journalOut
125126
Nothing ->
126127
do
127128
let relativeCandidates = map (relativeToBase opts) candidates
128-
let candidatesTxt = T.intercalate "\n" $ map (format fp) relativeCandidates
129-
let msg = format ("I couldn't find an hledger rules file while trying to import\n"%fp
130-
%"\n\nI will happily use the first rules file I can find from any one of these "%d%" files:\n"%s
131-
%"\n\nHere is a bit of documentation about rules files that you may find helpful:\n"%s)
129+
let candidatesTxt = T.intercalate "\n" $ map (Turtle.format Turtle.fp) relativeCandidates
130+
let msg = Turtle.format ("I couldn't find an hledger rules file while trying to import\n"%Turtle.fp
131+
%"\n\nI will happily use the first rules file I can find from any one of these "%Turtle.d%" files:\n"%Turtle.s
132+
%"\n\nHere is a bit of documentation about rules files that you may find helpful:\n"%Turtle.s)
132133
relCSV (length candidates) candidatesTxt (docURL "rules-files")
133134
errExit 1 ch msg csvSrc
134135

135136
rulesFileCandidates :: TurtlePath -> ImportDirs -> [TurtlePath]
136137
rulesFileCandidates csvSrc importDirs = statementSpecificRulesFiles csvSrc importDirs ++ generalRulesFiles importDirs
137138

138-
importDirLines :: (ImportDirs -> TurtlePath) -> ImportDirs -> [Line]
139-
importDirLines dirFun importDirs = NonEmpty.toList $ textToLines $ format fp $ dirname $ dirFun importDirs
139+
importDirLines :: (ImportDirs -> TurtlePath) -> ImportDirs -> [Turtle.Line]
140+
importDirLines dirFun importDirs = NonEmpty.toList $ Turtle.textToLines $ Turtle.format Turtle.fp $ Turtle.dirname $ dirFun importDirs
140141

141-
importDirLine :: (ImportDirs -> TurtlePath) -> ImportDirs -> Line
142+
importDirLine :: (ImportDirs -> TurtlePath) -> ImportDirs -> Turtle.Line
142143
importDirLine dirFun importDirs = foldl (<>) "" $ importDirLines dirFun importDirs
143144

144145
generalRulesFiles :: ImportDirs -> [TurtlePath]
@@ -152,25 +153,25 @@ generalRulesFiles importDirs = do
152153

153154
statementSpecificRulesFiles :: TurtlePath -> ImportDirs -> [TurtlePath]
154155
statementSpecificRulesFiles csvSrc importDirs = do
155-
let srcSuffix = snd $ T.breakOnEnd "_" (format fp (basename csvSrc))
156+
let srcSuffix = snd $ T.breakOnEnd "_" (Turtle.format Turtle.fp (Turtle.basename csvSrc))
156157

157158
if ((T.take 3 srcSuffix) == "rfo")
158159
then
159160
do
160-
let srcSpecificFilename = fromText srcSuffix <.> "rules"
161+
let srcSpecificFilename = Turtle.fromText srcSuffix <.> "rules"
161162
map (</> srcSpecificFilename) [accountDir importDirs, bankDir importDirs, importDir importDirs]
162163
else []
163164

164-
customConstruct :: RuntimeOptions -> TChan FlowTypes.LogMessage -> TurtlePath -> Line -> Line -> Line -> TurtlePath -> TurtlePath -> IO TurtlePath
165+
customConstruct :: RuntimeOptions -> TChan FlowTypes.LogMessage -> TurtlePath -> Turtle.Line -> Turtle.Line -> Turtle.Line -> TurtlePath -> TurtlePath -> IO TurtlePath
165166
customConstruct opts ch constructScript bank account owner csvSrc journalOut = do
166-
let script = format fp constructScript :: Text
167+
let script = Turtle.format Turtle.fp constructScript :: T.Text
167168
let relScript = relativeToBase opts constructScript
168-
let constructArgs = [format fp csvSrc, "-", lineToText bank, lineToText account, lineToText owner]
169-
let constructCmdText = format ("Running: "%fp%" "%s) relScript (showCmdArgs constructArgs)
170-
let stdLines = inprocWithErrFun (channelErrLn ch) (script, constructArgs, empty)
171-
let hledger = format fp $ FlowTypes.hlPath . hledgerInfo $ opts :: Text
172-
let args = ["print", "--ignore-assertions", "--file", "-", "--output-file", format fp journalOut]
169+
let constructArgs = [Turtle.format Turtle.fp csvSrc, "-", Turtle.lineToText bank, Turtle.lineToText account, Turtle.lineToText owner]
170+
let constructCmdText = Turtle.format ("Running: "%Turtle.fp%" "%Turtle.s) relScript (showCmdArgs constructArgs)
171+
let stdLines = inprocWithErrFun (channelErrLn ch) (script, constructArgs, Turtle.empty)
172+
let hledger = Turtle.format Turtle.fp $ FlowTypes.hlPath . hledgerInfo $ opts :: T.Text
173+
let args = ["print", "--ignore-assertions", "--file", "-", "--output-file", Turtle.format Turtle.fp journalOut]
173174
let relSrc = relativeToBase opts csvSrc
174-
let cmdLabel = format ("executing '"%fp%"' on '"%fp%"'") relScript relSrc
175+
let cmdLabel = Turtle.format ("executing '"%Turtle.fp%"' on '"%Turtle.fp%"'") relScript relSrc
175176
_ <- timeAndExitOnErr' opts ch cmdLabel [constructCmdText] channelOut channelErr (parAwareProc opts) (hledger, args, stdLines)
176177
return journalOut

0 commit comments

Comments
 (0)