~yoctocell/flaskell

1e9dff39ed7a4cfc24e97a03a1af1c1b8714cb16 — yoctocell 1 year, 8 months ago f718e4e
Use Data.Text and attoparsec
3 files changed, 54 insertions(+), 43 deletions(-)

M flaskell.cabal
M src/Flaskell/Cli.hs
M src/Flaskell/Parser.hs
M flaskell.cabal => flaskell.cabal +2 -2
@@ 1,4 1,4 @@
-- cabal-version:       >=2.1.0
cabal-version:       >=2.0.0
name:                flaskell
version:             1.0.0.0
-- synopsis:


@@ 27,7 27,7 @@ library
                 , parsec >= 3.1.13.0
                 , orgmode-parse >= 0.2.3
                 , attoparsec >= 0.13.2.4
                 -- , text >= 1.2.4.0
                 , text >= 1.2.4.0
  default-language: Haskell2010

executable flaskell

M src/Flaskell/Cli.hs => src/Flaskell/Cli.hs +6 -8
@@ 8,8 8,8 @@ import           Flaskell.Ui

import           Options.Applicative
-- import qualified Data.ByteString               as B
-- import qualified Data.Text                     as T
-- import           Data.Text.IO                   ( readFile )
import           Data.Text                      ( Text )
import qualified Data.Text.IO                  as T
import           System.Environment             ( getArgs
                                                , getProgName
                                                )


@@ 48,13 48,11 @@ parseCliArgs :: Options -> IO ()
parseCliArgs options = case options of
  (Options True  _               ) -> putStrLn versionNumber
  (Options False (FileInput file)) -> do
    contents <- readFile file
    -- print $ getCards contents
    contents <- T.readFile file
    let result = getCards contents
    if result == [] then handleError else feedCards result
    -- feedCards . getCards $ contents
    if null result then handleError else feedCards result
    -- FIXME hGetLine closed handle error
  (Options False (StdInput)) -> do
  (Options False StdInput) -> do
    contents <- getArgs
    putStrLn $ last contents
    -- contents <- getContents


@@ 62,7 60,7 @@ parseCliArgs options = case options of
    -- feedCards . getCards $ contents

-- | Take contents of a file and return a list of Flashcard
getCards :: String -> [Flashcard]
getCards :: Text -> [Flashcard]
getCards contents =
  let result = parseFlashcard contents
  in  case result of

M src/Flaskell/Parser.hs => src/Flaskell/Parser.hs +46 -33
@@ 1,19 1,40 @@
module Flaskell.Parser where
{-# LANGUAGE OverloadedStrings #-}
module Flaskell.Parser
  -- ( parseFlashcard
  -- , Hint
  -- , Answer
  -- , Guess
  -- , Flashcard
  -- )
                       where

import           Text.Parsec.Char               ( noneOf
                                                , oneOf
                                                , endOfLine
                                                )
import           Text.Parsec                    ( sepBy
                                                , many
                                                , endBy
                                                , ParseError
                                                , parse
                                                , string
-- import           Text.Parsec.Char               ( noneOf
--                                                 , oneOf
--                                                 , endOfLine
--                                                 )
-- import           Text.Parsec                    ( sepBy
--                                                 , many
--                                                 , endBy
--                                                 , ParseError
--                                                 , parse
--                                                 , string
--                                                 , char
--                                                 )
-- import           Text.Parsec.Text               ( Parser )
import           Data.Attoparsec.Text           ( Parser
                                                , char
                                                , many'
                                                , notChar
                                                , sepBy
                                                , parseOnly
                                                )
import           Text.Parsec.String             ( Parser )
import           Data.OrgMode.Parse.Attoparsec.Headline
import           Control.Monad
import           Data.Text                      ( Text )
import           Control.Applicative            ( (<*)
                                                , (*>)
                                                , liftA2
                                                )

type Hint = String
type Answer = String


@@ 23,30 44,22 @@ type Flashcard = (Hint, Answer)
-- swap :: Hint -> Answer -> Answer -> Hint
-- swap h a = a h

-- Helper functions
-- Yanked from https://jakewheat.github.io/intro_to_parsing/#_whitespace
whitespace :: Parser ()
whitespace = void $ many $ oneOf " \n\t"
-- | Parse hint from flashcard
parseHint :: Parser String
parseHint = char '-' *> char ' ' *> many' (notChar '|')

lexeme :: Parser a -> Parser a
lexeme p = do
  x <- p
  whitespace
  return x
-- | Parse answer from flashcard
parseAnswer :: Parser String
parseAnswer = char '|' *> char ' ' *> many' (notChar '\n')

-- | Return a tuple of hint and answer
flashcard :: Parser Flashcard
flashcard = do
  lexeme $ char '-'
  -- FIXME trailing whitespace "hint 1 "
  h <- many $ noneOf "-"
  lexeme $ char '-'
  a <- many $ noneOf "\n"
  return (h, a)
-- flashcard :: Parser Flashcard
flashcard :: Parser (String, String)
flashcard = liftA2 (,) parseHint parseAnswer

-- | Separate each line
flashcardFile :: Parser [Flashcard]
flashcardFile = endBy flashcard endOfLine
flashcardFile :: Parser [(String, String)]
flashcardFile = sepBy flashcard (char '\n')

parseFlashcard :: String -> Either ParseError [Flashcard]
parseFlashcard = parse flashcardFile ""
parseFlashcard :: Text -> Either String [Flashcard]
parseFlashcard = parseOnly flashcardFile