Skip to content

Commit c1f784b

Browse files
authored
Merge pull request #6 from danslapman/feature/progressbar
Add ProgressBar
2 parents b646d28 + 596c1f7 commit c1f784b

File tree

3 files changed

+36
-28
lines changed

3 files changed

+36
-28
lines changed

app/Main.hs

Lines changed: 34 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,9 @@ import qualified Data.ByteString.Lazy as LBS
1010
import Data.Either
1111
import Data.Foldable (toList)
1212
import qualified Data.HashMap.Strict as HM
13-
import Data.IORef
1413
import Data.HashSet (HashSet, empty, intersection, null, union)
1514
import qualified Data.HashSet as HS (toList)
15+
import Data.IORef
1616
import Data.Text (Text, intercalate)
1717
import qualified Data.Text.IO as TIO
1818
import Deque.Strict (Deque)
@@ -21,28 +21,31 @@ import GHC.Exts (fromList)
2121
import Json2Csv
2222
import Options.Applicative hiding (empty)
2323
import Options.Applicative.Text
24-
import Prelude hiding (foldl, foldl', map, null, sequence)
2524
import Schema
2625
import System.IO
26+
import System.ProgressBar
27+
import Prelude hiding (foldl, foldl', map, null, sequence)
2728

28-
data Args = Args {
29-
jsonFile :: String,
30-
csvFile :: String,
31-
separator :: Text,
32-
isect :: Bool,
33-
flatArr :: Bool
34-
}
29+
data Args = Args
30+
{ jsonFile :: String,
31+
csvFile :: String,
32+
separator :: Text,
33+
isect :: Bool,
34+
flatArr :: Bool
35+
}
3536

3637
type PathSet = HashSet JsonPath
38+
3739
type PathSetCombine = PathSet -> PathSet -> PathSet
3840

3941
args :: Parser Args
40-
args = Args
41-
<$> strArgument (metavar "jsonFile" <> help "Newline-delimited JSON input file name")
42-
<*> strArgument (metavar "csvFile" <> help "CSV output file name")
43-
<*> textOption (long "separator" <> help "CSV separator" <> showDefault <> value ";")
44-
<*> switch (long "intersect" <> short 'i' <> help "\"Inner join\" fields while constructing schema")
45-
<*> switch (long "flatten" <> short 'f' <> help "Flatten array iterators")
42+
args =
43+
Args
44+
<$> strArgument (metavar "jsonFile" <> help "Newline-delimited JSON input file name")
45+
<*> strArgument (metavar "csvFile" <> help "CSV output file name")
46+
<*> textOption (long "separator" <> help "CSV separator" <> showDefault <> value ";")
47+
<*> switch (long "intersect" <> short 'i' <> help "\"Inner join\" fields while constructing schema")
48+
<*> switch (long "flatten" <> short 'f' <> help "Flatten array iterators")
4649

4750
argsInfo :: ParserInfo Args
4851
argsInfo = info args fullDesc
@@ -59,31 +62,35 @@ main = do
5962
let combine = if (isect arguments) then isectOrNonEmpty else flip union
6063
let flat = flatArr arguments
6164
let procCols = if (flat) then dropIterators else id
62-
header <- withFile (jsonFile arguments) ReadMode $ computeHeaderMultiline combine
65+
(header, numberOfLines) <- withFile (jsonFile arguments) ReadMode $ computeHeaderMultiline combine
6366
let schema = toSchema header
6467
let columns = jsonPathText <$> (uniq $ procCols <$> header)
68+
pb <- newProgressBar defStyle 10 (Progress 0 numberOfLines ())
6569
withFile (jsonFile arguments) ReadMode $ \hIn ->
6670
withFile (csvFile arguments) WriteMode $ \hOut -> do
6771
hSetEncoding hIn utf8
6872
hSetEncoding hOut utf8
6973
TIO.hPutStrLn hOut $ mkSepString $ columns
70-
whileM_ (not <$> hIsEOF hIn) (parseAndWriteEntry mkSepString flat schema columns hIn hOut)
74+
whileM_ (not <$> hIsEOF hIn) $ do
75+
(parseAndWriteEntry mkSepString flat schema columns hIn hOut)
76+
incProgress pb 1
7177

72-
computeHeaderMultiline :: PathSetCombine -> Handle -> IO (Deque JsonPath)
78+
computeHeaderMultiline :: PathSetCombine -> Handle -> IO (Deque JsonPath, Int)
7379
computeHeaderMultiline combine handle = do
7480
currentLineNumber <- newIORef (0 :: Int)
7581
pathSet <- newIORef (empty :: HashSet JsonPath)
7682
whileM_ (not <$> hIsEOF handle) $ do
77-
modifyIORef' currentLineNumber (1+)
78-
line <- LBS.fromStrict <$> BS.hGetLine handle
79-
ln <- readIORef currentLineNumber
80-
parsed <- case eitherDecode' line of
81-
Right value -> pure value
82-
Left err -> fail $ "Can't parse JSON at line " ++ (show ln) ++ ": " ++ err
83-
let (Just header) = computePaths True parsed
84-
modifyIORef' pathSet (combine header)
83+
modifyIORef' currentLineNumber (1 +)
84+
line <- LBS.fromStrict <$> BS.hGetLine handle
85+
ln <- readIORef currentLineNumber
86+
parsed <- case eitherDecode' line of
87+
Right value -> pure value
88+
Left err -> fail $ "Can't parse JSON at line " ++ (show ln) ++ ": " ++ err
89+
let (Just header) = computePaths True parsed
90+
modifyIORef' pathSet (combine header)
8591
pathes <- readIORef pathSet
86-
return $ fromList . HS.toList $ pathes
92+
numberOfLines <- readIORef currentLineNumber
93+
return (fromList . HS.toList $ pathes, numberOfLines)
8794

8895
parseAndWriteEntry :: (Deque Text -> Text) -> Bool -> JsonSchema -> Deque Text -> Handle -> Handle -> IO ()
8996
parseAndWriteEntry mkSepString flat schema columns hIn hOut = do

package.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ dependencies:
3535
- deepseq
3636
- optparse-applicative
3737
- optparse-text
38+
- terminal-progress-bar
3839

3940
library:
4041
source-dirs: src

stack.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
#
1818
# resolver: ./custom-snapshot.yaml
1919
# resolver: https://example.com/snapshots/2018-01-01.yaml
20-
resolver: lts-19.14
20+
resolver: lts-19.31
2121

2222
# User packages to be built.
2323
# Various formats can be used as shown in the example below.

0 commit comments

Comments
 (0)