subtitleParser 0.2 → 0.3
raw patch · 5 files changed
+81/−43 lines, 5 filesdep ~attoparsecPVP ok
version bump matches the API change (PVP)
Dependency ranges changed: attoparsec
API changes (from Hackage documentation)
+ Text.Subtitles.SRT: parseOnly' :: Parser a -> Text -> Either String a
+ Text.Subtitles.SUB.Datatypes: Bold :: TextProperty
+ Text.Subtitles.SUB.Datatypes: C :: Color -> TextProperty
+ Text.Subtitles.SUB.Datatypes: Italic :: TextProperty
+ Text.Subtitles.SUB.Datatypes: Stroked :: TextProperty
+ Text.Subtitles.SUB.Datatypes: UnderLine :: TextProperty
+ Text.Subtitles.SUB.Datatypes: data TextProperty
+ Text.Subtitles.SUB.Datatypes: instance Show TextProperty
+ Text.Subtitles.SUB.Datatypes: property :: Line -> Maybe TextProperty
+ Text.Subtitles.SUB.Datatypes: type Color = Text
- Text.Subtitles.SUB.Datatypes: Line :: Frame -> Frame -> Text -> Line
+ Text.Subtitles.SUB.Datatypes: Line :: Frame -> Frame -> Maybe TextProperty -> Text -> Line
Files
- Text/Subtitles/SRT.hs +34/−11
- Text/Subtitles/SRT/Datatypes.hs +3/−23
- Text/Subtitles/SUB.hs +29/−6
- Text/Subtitles/SUB/Datatypes.hs +12/−0
- subtitleParser.cabal +3/−3
Text/Subtitles/SRT.hs view
@@ -10,6 +10,9 @@ module Text.Subtitles.SRT (+ -- * Don't use parseOnly!+ -- $noParseOnly + -- * Terminology of the module -- $example @@ -18,16 +21,29 @@ -- * Main parsers parseSRT,- parseSingleLine+ parseSingleLine,++ -- * Temporal solutions+ parseOnly' ) where import Prelude hiding (takeWhile) import Control.Applicative-import Data.Attoparsec.Text +import Data.Attoparsec.Text hiding (parseOnly) import qualified Data.Text as T -- in project modules import Text.Subtitles.SRT.Datatypes +-- $noParseOnly+--+-- This module uses now peekChar in parseDialog, which replaces the ad-hoc+-- method used before. As a consequence it doesn't play well with+-- Data.Attoparsec.Text.parseOnly on some conditions.+--+-- You should use just 'parse' or the parseOnly' function I provide to avoid+-- problems until further notice. /Hopefully/ in the next version of attoparsec+-- this will be solved , so keep an eye for removal!.+ -- $example -- -- All the sections of a Line have their corresponding ADT in@@ -53,11 +69,11 @@ parseSRT :: Parser Subtitles parseSRT = many1 parseSingleLine --- |The individual Line parser. given the upper example return the+-- |The individual Line parser. Given the upper example return the -- corresponding Line representation parseSingleLine :: Parser Line parseSingleLine = - Line <$> parseIndex <*> parseRange <* eol <*> parseDialog T.empty+ Line <$> parseIndex <*> parseRange <*> parseDialog T.empty parseIndex :: Parser Int parseIndex = decimal <* eol@@ -65,9 +81,14 @@ eol :: Parser () eol = endOfLine +-- |This version avoid the problems associated with peekChar and thus is safe to+-- use in this module. Subject to removal once parseOnly is fixed.+parseOnly' :: Parser a -> Text -> Either String a+parseOnly' p t = eitherResult $ feed (parse p t) T.empty+ {- Is clear that this just aplies parseTime breaking down the "-->" string -} parseRange :: Parser Range-parseRange = Range <$> parseTime <* arrowString <*> parseTime +parseRange = Range <$> parseTime <* arrowString <*> parseTime <* skipSpace where arrowString :: Parser Text arrowString = string (T.pack " --> ") @@ -78,15 +99,17 @@ numDot :: Parser Int numDot = decimal <* char ':' -{- return the dialog checking for newlines that could be in there. that why is- - written in a monad instead of applicative. more efficient version welcome -}+{- return the dialog checking for newlines that could be in there. That why is+ - written in a monad instead of applicative. More efficient version welcome -} parseDialog :: Text -> Parser Text parseDialog t = do line <- takeWhile1 (not . isEndOfLine) endOfLine- let lineState = T.append t (T.snoc line '\n')- next <- anyChar+ let lineState = T.append t (T.snoc line '\n') --takeWhile1 didn't consume \n+ next <- peekChar case next of- '\n' -> return lineState - _ -> parseDialog (T.snoc lineState next)+ Nothing -> return lineState + (Just '\n') -> eol >> return lineState + (Just _) -> parseDialog lineState +
Text/Subtitles/SRT/Datatypes.hs view
@@ -31,12 +31,12 @@ , minutes :: Int , seconds :: Int , frame :: Int- } deriving (Eq, Ord)+ } deriving (Eq, Ord, Show) data Range = Range { from :: Time , to :: Time- } deriving (Eq, Ord)+ } deriving (Eq, Ord, Show) -- | The core of the parser. each one of the constructor representing one part -- of the Line@@ -44,27 +44,7 @@ { index :: Int , range :: Range , dialog :: Text- } deriving (Eq, Ord)+ } deriving (Eq, Ord, Show) type Subtitles = [Line] -instance Show Time where- show (Time h m s f) = concat [showT h, ":", showT m, ":", showT s, ",", showF f]--instance Show Range where- show (Range f t) = concat [show f, " --> ", show t]--instance Show Line where- show (Line i t s) = intercalate "\n" (show i : show t : [unpack s]) ++ "\n"--{- showT stands for showTime. In the parsing process "00" is read as "0", and- - that tailing 0 is lost unless we add it manually when showing -}-showT :: Int -> String-showT a | a < 10 = '0' : show a- | otherwise = show a--{- showF stands for showFrame -}-showF :: Int -> String-showF a | a < 10 = '0':'0': show a- | a < 100 = '0': show a- | otherwise = show a
Text/Subtitles/SUB.hs view
@@ -6,7 +6,7 @@ -- Maintainer : ruben.astud@gmail.com -- Portability : unknown ----- A basic parser for .sub files (subtitles) based on 'Attoparsec' and 'Text'+-- A basic parser for .sub files (microDVD) based on 'Attoparsec' and 'Text' module Text.Subtitles.SUB (@@ -23,27 +23,50 @@ import Control.Applicative import Data.Attoparsec.Text+import Data.Text (pack, Text)+import Data.Maybe (Maybe) import Text.Subtitles.SUB.Datatypes -- $example --+-- I strongly recommend to understand the 'Line' Datatype , which is the+-- foundation of this module.+-- -- Refering to the parts of a single line of a subtitle file. ----- >{50}{100}Drama here!+-- >{50}{100}{y:i}Drama here! ----- the first to numbers correspond to the frame in which the text Drama here!--- is displayed. +-- The first to numbers correspond to the frame in which the text Drama here!+-- is displayed. Note that this implementation support the optional flags about+-- text format and color frame :: Parser Frame-frame = char '{' *> decimal <* char '}'+frame = enclosed decimal -- | Given the example return the corresponding Line representation. At the -- moment this not handles modifiers as underlines or bold text parseSingleLine :: Parser Line -parseSingleLine = Line <$> frame <*> frame <*> takeTill isEndOfLine+parseSingleLine = Line <$> frame <*> frame <*> parseProperty <*> takeTill isEndOfLine -- | Main parser of .sub files, given a .sub file it return a list of the dialog -- lines parseSUB :: Parser Subtitles parseSUB = sepBy1 parseSingleLine endOfLine++parseProperty :: Parser (Maybe TextProperty) +parseProperty = option Nothing (Just <$> enclosed (choice allProp))+ where+ bold = matchText "y:b" *> pure Bold+ italic = matchText "y:i" *> pure Italic+ underline = matchText "y:u" *> pure UnderLine+ stroked = matchText "y:s" *> pure Stroked+ color = matchText "C:" *> (C <$> takeWhile1 ('}' /=))+ allProp = [bold, italic, underline, stroked, color]++-- All .sub command are enclosed in bracket. Worth defining.+enclosed :: Parser a -> Parser a+enclosed p = char '{' *> p <* char '}'++matchText :: String -> Parser Text+matchText s = string (pack s)
Text/Subtitles/SUB/Datatypes.hs view
@@ -18,19 +18,31 @@ -- * Datatypes Frame, Subtitles,+ Color,+ TextProperty(..), Line(..) ) where import Data.Text (Text) import Data.Attoparsec.Text (Parser)+import Data.Maybe (Maybe) type Subtitles = [Line] {- Should this be a newtype? or just a type? -} type Frame = Int +-- .sub utilize a non-standard RGB format, is better to keep them as Text +type Color = Text++-- |Optional property of text, the constructor should be clear.+data TextProperty = Italic | Bold | UnderLine | Stroked + | C Color -- ^ This is just text because is non-standard RGB+ deriving (Show)+ data Line = Line { startFrame :: Frame, finalFrame :: Frame,+ property :: Maybe TextProperty, dialog :: Text } deriving (Show)
subtitleParser.cabal view
@@ -1,5 +1,5 @@ name: subtitleParser-version: 0.2+version: 0.3 license: BSD3 license-file: LICENSE category: Text, Parsing@@ -26,14 +26,14 @@ build-depends: base < 5, containers, text >= 0.11.1.5,- attoparsec+ attoparsec >= 0.10.2.0 exposed-modules: Text.Subtitles.SRT Text.Subtitles.SRT.Datatypes Text.Subtitles.SUB Text.Subtitles.SUB.Datatypes - ghc-options: -Wall+ ghc-options: if flag(developer) ghc-prof-options: -auto-all