subtitleParser 0.3 → 0.4
raw patch · 9 files changed
+111/−11 lines, 9 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
+ Text.Subtitles.SRT.Datatypes: R :: Int -> Int -> Int -> Int -> Rectangle
+ Text.Subtitles.SRT.Datatypes: data Rectangle
+ Text.Subtitles.SRT.Datatypes: geometry :: Line -> Maybe Rectangle
+ Text.Subtitles.SRT.Datatypes: instance Eq Rectangle
+ Text.Subtitles.SRT.Datatypes: instance Ord Rectangle
+ Text.Subtitles.SRT.Datatypes: instance Show Rectangle
+ Text.Subtitles.SRT.Datatypes: x1 :: Rectangle -> Int
+ Text.Subtitles.SRT.Datatypes: x2 :: Rectangle -> Int
+ Text.Subtitles.SRT.Datatypes: y1 :: Rectangle -> Int
+ Text.Subtitles.SRT.Datatypes: y2 :: Rectangle -> Int
+ Text.Subtitles.SUB.Datatypes: instance Eq Line
+ Text.Subtitles.SUB.Datatypes: instance Eq TextProperty
- Text.Subtitles.SRT.Datatypes: Line :: Int -> Range -> Text -> Line
+ Text.Subtitles.SRT.Datatypes: Line :: Int -> Range -> Maybe Rectangle -> Text -> Line
Files
- CHANGELOG +14/−0
- Text/Subtitles/SRT.hs +21/−8
- Text/Subtitles/SRT/Datatypes.hs +7/−0
- Text/Subtitles/SUB/Datatypes.hs +2/−2
- subtitleParser.cabal +6/−1
- test/TestSRT.hs +24/−0
- test/TestSUB.hs +24/−0
- test/example.srt +9/−0
- test/example.sub +4/−0
+ CHANGELOG view
@@ -0,0 +1,14 @@+0.3+ - Show instances for SRT now are simpler and more related on how is defined+ the ADT. this is a PARSER not a prettyPrinter nor a valid .srt producer+ - SUB files added support for optional flag as underline and bold+ - SRT's parseDialog now uses peekChar so attoparsec dependency is upgraded and+ the code is cleaner. As a bug we provide for now parseOnly' until is fixed+ upstream+0.2+ - Basic support for .sub files added+ - Separated Datatypes for .sub and .srt files+0.1.2+ - Now haddock documentation is build correctly+0.1+ - Initial release
Text/Subtitles/SRT.hs view
@@ -50,7 +50,7 @@ -- "Text.Subtitles.SRT.Datatypes" -- -- >2--- >00:00:50,050 --> 00:00:52,217+-- >00:00:50,050 --> 00:00:52,217 X1:1 X2:2 Y1:1 Y2:2 -- >Drama here -- -- The whole Line is represented in the 'Line' ADT which constructors@@ -61,7 +61,10 @@ -- -- * The second one is called 'Range', which correspond to two separated 'Time'. ----- * The last one is the 'subs'. which is just Text and correspond to the third+-- * After the range is an optional field called Rectangle which says what+-- geometry should the text obey.+--+-- * The last one is the 'subs'. Which is just Text and correspond to the third -- constructor of 'Line'. -- |Main Parser, gives you a list of all the Lines of the subtitle. It fails if@@ -73,7 +76,7 @@ -- corresponding Line representation parseSingleLine :: Parser Line parseSingleLine = - Line <$> parseIndex <*> parseRange <*> parseDialog T.empty+ Line <$> parseIndex <*> parseRange <*> optionalGeometry <*> parseDialog T.empty parseIndex :: Parser Int parseIndex = decimal <* eol@@ -93,6 +96,14 @@ arrowString :: Parser Text arrowString = string (T.pack " --> ") +{- the order X1 X2 Y1 Y2 seems to be enforced, so we can check only for order+ - instead of keywords -}+optionalGeometry :: Parser (Maybe Rectangle)+optionalGeometry = option Nothing (Just <$> rectangle <* eol)+ where rectangle = R <$> valueSpace <*> valueSpace <*> valueSpace <*> value+ value = letter *> digit *> char ':' *> decimal + valueSpace = value <* space+ parseTime :: Parser Time parseTime = Time <$> numDot <*> numDot <*> decimal <* char ',' <*> decimal where@@ -102,14 +113,16 @@ {- 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 +parseDialog stateLine = do line <- takeWhile1 (not . isEndOfLine) endOfLine- let lineState = T.append t (T.snoc line '\n') --takeWhile1 didn't consume \n+ let stateCurrent = T.append stateLine line+ lineState = T.snoc stateCurrent '\n' --takeWhile1 didn't consume \n next <- peekChar case next of- Nothing -> return lineState - (Just '\n') -> eol >> return lineState - (Just _) -> parseDialog lineState + Nothing -> return stateCurrent -- the end of the file+ (Just '\n') -> eol >> return stateCurrent -- End of this Line, new Line coming.+ (Just _) -> parseDialog lineState {- in between lines, the next one belong to this Line+ explicit eol required -}
Text/Subtitles/SRT/Datatypes.hs view
@@ -17,6 +17,7 @@ -- * Datatypes Subtitles,+ Rectangle(..), Line(..), Range(..), Time(..)@@ -26,6 +27,11 @@ import Data.Text (Text, unpack) import Data.Attoparsec.Text (Parser) +-- |This represent the position on screen of the Line. Is usually optional in+-- the file.+data Rectangle = R { x1 :: Int, x2 :: Int, y1 :: Int, y2 :: Int}+ deriving (Eq, Ord, Show)+ data Time = Time { hour :: Int , minutes :: Int@@ -43,6 +49,7 @@ data Line = Line { index :: Int , range :: Range+ , geometry :: Maybe Rectangle , dialog :: Text } deriving (Eq, Ord, Show)
Text/Subtitles/SUB/Datatypes.hs view
@@ -38,11 +38,11 @@ -- |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)+ deriving (Show, Eq) data Line = Line { startFrame :: Frame, finalFrame :: Frame, property :: Maybe TextProperty, dialog :: Text }- deriving (Show)+ deriving (Show, Eq)
subtitleParser.cabal view
@@ -1,5 +1,5 @@ name: subtitleParser-version: 0.3+version: 0.4 license: BSD3 license-file: LICENSE category: Text, Parsing@@ -17,6 +17,11 @@ extra-source-files: LICENSE THANKS+ CHANGELOG+ test/TestSUB.hs+ test/example.srt+ test/example.sub+ test/TestSRT.hs Flag developer Description: Whether to build the library in development mode
+ test/TestSRT.hs view
@@ -0,0 +1,24 @@+module Main where++import Test.HUnit+import Test.HUnit.Text+import Data.Text.IO as TI +import Data.Text (pack)+import Text.Subtitles.SRT++main :: IO ()+main = runTestTT (TestList [test srtAssert]) >> return ()++srtAssert :: Assertion+srtAssert = do+ srtContents <- TI.readFile "./test/example.srt"+ case parseOnly' parseSRT srtContents of+ Left _ -> assertFailure "Error while parsing the example .srt"+ Right r -> assertEqual "Parser didn't produce the expected value" expectedValue r++{- I wanted the parser to produce this output, when it accomplish it, it will be+ - complete -}+expectedValue :: Subtitles+expectedValue = [ Line 1 (Range (Time 0 2 26 407) (Time 0 2 31 356)) (Just (R 100 100 100 100)) (pack "<font color=\"#00ff00\">Detta handlar om min storebrors</font> \n<b><i><u>kriminella beteende och foersvinnade.</u></i></b>"),+ Line 2 (Range (Time 0 2 31 567) (Time 0 2 37 164)) Nothing (pack "Vi talar inte laengre om Wade. Det aer \nsom om han aldrig hade existerat.")]+
+ test/TestSUB.hs view
@@ -0,0 +1,24 @@+module Main where++import Test.HUnit+import Test.HUnit.Text+import Text.Subtitles.SUB+import Data.Text (pack)+import Data.Text.IO as TI (readFile)+import Data.Attoparsec.Text (parseOnly)++main :: IO ()+main = runTestTT (test assertSUB) >> return ()++expectedSUB :: Subtitles+expectedSUB = [Line 13187 13215 (Just Italic) (pack "Áno!"),+ Line 13430 13456 Nothing (pack "Áno!"),+ Line 13935 14020 (Just (C (pack "$0000ff"))) (pack "Nezdie¾am vašu rados..."),+ Line 14034 14147 Nothing (pack "- Dobrá práca, agentka Marcusová.|- Ïakujem.")]++assertSUB :: Assertion+assertSUB = do+ example <- TI.readFile "./test/example.sub"+ case parseOnly parseSUB example of+ Left _ -> assertFailure "parseSUB failed on example"+ Right r -> assertEqual "parseSUB result didn't match expected" expectedSUB r
+ test/example.srt view
@@ -0,0 +1,9 @@+1+00:02:26,407 --> 00:02:31,356 X1:100 X2:100 Y1:100 Y2:100+<font color="#00ff00">Detta handlar om min storebrors</font> +<b><i><u>kriminella beteende och foersvinnade.</u></i></b>++2+00:02:31,567 --> 00:02:37,164 +Vi talar inte laengre om Wade. Det aer +som om han aldrig hade existerat.
+ test/example.sub view
@@ -0,0 +1,4 @@+{13187}{13215}{y:i}Áno!+{13430}{13456}Áno!+{13935}{14020}{C:$0000ff}Nezdie¾am vašu rados...+{14034}{14147}- Dobrá práca, agentka Marcusová.|- Ïakujem.