subtitleParser (empty) → 0.1
raw patch · 6 files changed
+233/−0 lines, 6 filesdep +attoparsecdep +basedep +containerssetup-changed
Dependencies added: attoparsec, base, containers, text
Files
- LICENSE +31/−0
- Setup.lhs +3/−0
- THANKS +3/−0
- Text/Subtitles/Datatypes.hs +65/−0
- Text/Subtitles/SRT.hs +89/−0
- subtitleParser.cabal +42/−0
+ LICENSE view
@@ -0,0 +1,31 @@+Copyright (c) Ruben Astudillo++All rights reserved.++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions+are met:++1. Redistributions of source code must retain the above copyright+ notice, this list of conditions and the following disclaimer.++2. Redistributions in binary form must reproduce the above copyright+ notice, this list of conditions and the following disclaimer in the+ documentation and/or other materials provided with the distribution.++3. Neither the name of the author nor the names of his contributors+ may be used to endorse or promote products derived from this software+ without specific prior written permission.++THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND ANY EXPRESS+OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE+DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS+OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,+STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN+ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE+POSSIBILITY OF SUCH DAMAGE.+
+ Setup.lhs view
@@ -0,0 +1,3 @@+#!/usr/bin/env runhaskell+> import Distribution.Simple+> main = defaultMain
+ THANKS view
@@ -0,0 +1,3 @@+This wouldn't be possible without the indirect help of Sebastiaan Visser whose+subtitles package give me the idea of a separate package just for parsing+subtitle files. He also provided me with the datatypes used in this project.
+ Text/Subtitles/Datatypes.hs view
@@ -0,0 +1,65 @@+-- |+-- Module : Text.Subtitles.Datatypes+-- Copyright : Ruben Astudillo 2012+-- License : BSD3+--+-- Maintainer : ruben.astud@gmail.com+-- Portability : unknown+--+-- Common ADT for the project. Also serves as a place to provide instance+-- declarations for the ADTs.++module Text.Subtitles.Datatypes + (+ -- * Datatypes+ Subtitles(..),+ Line(..),+ Range(..),+ Time(..)+ ) where++import Data.List (intercalate)+import Data.Text (Text, unpack)++data Time = Time+ { hour :: Int+ , minutes :: Int+ , seconds :: Int+ , frame :: Int+ } deriving (Eq, Ord)++data Range = Range + { from :: Time+ , to :: Time+ } deriving (Eq, Ord)++-- | The core of the parser. each one of the constructor representing one part+-- of the Line+data Line = Line+ { index :: Int+ , range :: Range+ , subs :: Text+ } deriving (Eq, Ord)++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/SRT.hs view
@@ -0,0 +1,89 @@+-- |+-- Module : Text.Subtitles.SRT+-- Copyright : Ruben Astudillo 2012+-- License : BSD3+--+-- Maintainer : ruben.astud@gmail.com+-- Portability : unknown+--+-- A basic parser for .srt files (subtitles) based on 'Attoparsec' and 'Text'++module Text.Subtitles.SRT + (+ -- * Terminology of the module+ -- $example+ + -- * Main parsers+ parseSubtitles,+ parseSingleLine+ ) where++import Prelude hiding (takeWhile)+import Control.Applicative+import Data.Attoparsec.Text +import qualified Data.Text as T+-- in project modules+import Text.Subtitles.Datatypes++-- $example+--+-- All the sections of a Line have their corresponding ADT in+-- "Text.Subtitles.Datatypes"+-- +-- >2+-- >00:00:50,050 --> 00:00:52,217+-- >Drama here+--+-- The whole Line is represented in the 'Line' ADT which constructors+-- represented by different ADTs+--+-- * The first line is called index, which is the first constructor of+-- 'Line'.+--+-- * 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+-- constructor of 'Line'.++-- |Main Parser, gives you a list of all the Lines of the subtitle. It fails if+-- the subtitle doesn't have any Lines.+parseSubtitles :: Parser Subtitles+parseSubtitles = many1 parseSingleLine++-- |The individual Line parser. given the upper example return the+-- corresponding Line representation+parseSingleLine :: Parser Line+parseSingleLine = + Line <$> parseIndex <*> parseRange <* eol <*> parseSubs T.empty++parseIndex :: Parser Int+parseIndex = decimal <* eol++eol :: Parser ()+eol = endOfLine ++{- Is clear that this just aplies parseTime breaking down the "-->" string -}+parseRange :: Parser Range+parseRange = Range <$> parseTime <* arrowString <*> parseTime + where+ arrowString :: Parser T.Text+ arrowString = string (T.pack " --> ") ++parseTime :: Parser Time+parseTime = Time <$> numDot <*> numDot <*> decimal <* char ',' <*> decimal+ where+ 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 -}+parseSubs :: T.Text -> Parser T.Text+parseSubs t = do + line <- takeWhile1 (not . isEndOfLine)+ endOfLine+ let lineState = T.append t (T.snoc line '\n')+ next <- anyChar+ case next of+ '\n' -> return lineState + _ -> parseSubs (T.snoc lineState next)+
+ subtitleParser.cabal view
@@ -0,0 +1,42 @@+name: subtitleParser+version: 0.1+license: BSD3+license-file: LICENSE+category: Text, Parsing+author: Ruben Astudillo <ruben.astud@gmail.com>+maintainer: Ruben Astudillo <ruben.astud@gmail.com>+stability: experimental+tested-with: GHC == 7.4.2+synopsis: A parser for .srt and .sub files+cabal-version: >= 1.8+homepage: https://patch-tag.com/r/rubenAst/subtitleParser/home+bug-reports: https://patch-tag.com/r/rubenAst/subtitleParser/home+build-type: Simple+description:+ A basic .srt and .sub parser based on attoparsec and text +extra-source-files:+ LICENSE+ THANKS++Flag developer+ Description: Whether to build the library in development mode+ Default: False++library+ build-depends: base >= 3 && < 5,+ containers,+ text >= 0.11.1.5,+ attoparsec++ exposed-modules: Text.Subtitles.SRT+ Text.Subtitles.Datatypes++ ghc-options: -Wall++ if flag(developer)+ ghc-prof-options: -auto-all++source-repository head+ type: darcs+ location: https://patch-tag.com/r/rubenAst/subtitleParser+