packages feed

Ansi2Html (empty) → 0.1

raw patch · 5 files changed

+341/−0 lines, 5 filesdep +basedep +mtldep +parsecsetup-changed

Dependencies added: base, mtl, parsec, xhtml

Files

+ Ansi2Html.cabal view
@@ -0,0 +1,16 @@+Name:                Ansi2Html+Version:             0.1+Synopsis:            Convert ANSI Terminal Sequences to nice HTML markup+Description:	     Particularly with xterm in mind, this software enables integration of terminal screen state in html pages. See project homepage for hints on how to setup xterm for it.+Homepage:            http://janzzstimmpfle.de/~jens/software/Ansi2Html/+License:             BSD3+License-file:        LICENSE+Author:              Jens Stimpfle+Maintainer:          jens@janzzstimmpfle.de+Category:            Web+Build-type:          Simple+Extra-source-files:  ansi2html.css+Cabal-version:       >=1.2+Executable ansi2html+  Main-is:           Ansi2Html.hs+  Build-depends:     parsec, mtl, base < 5, xhtml
+ Ansi2Html.hs view
@@ -0,0 +1,237 @@+import Text.ParserCombinators.Parsec+import System.Environment+import System.IO+import System.Exit+import Control.Applicative ((<$>))+import Data.Char+import Data.Maybe+import Text.XHtml as X+import Control.Monad+import Control.Monad.State as S++-- the (Integer,Integer) state holds an (couner,columns) state+type MyParser = GenParser Char (Integer,Integer)++data ANSIEnv = AnsiEnv { ansiBrightOrBold :: Bool+                       , ansiFaint :: Bool+                       , ansiItalic :: Bool+                       , ansiUnderline :: Bool+                       , ansiReverse :: Bool+                       , ansiFontNumber :: Int+                       , ansiFramed :: Bool+                       , ansiEncircled :: Bool+                       , ansiOverlined :: Bool+                       , ansiFGColor :: ANSIColor+                       , ansiBGColor :: ANSIColor+                       }++defaultEnv :: ANSIEnv+defaultEnv = AnsiEnv False False False False False 0 False False False AnsiWhite AnsiBlack++modifyEnv :: ANSIEnv -> ANSIToken -> ANSIEnv+modifyEnv env ctl = if (finalByte ctl /= 'm')+    then env+    else foldl (flip ($)) env modifiers+ where modifiers = flip map (optParms ctl)+        (\parm -> case parm of+            0  -> \_ -> defaultEnv+            1  -> \e -> e { ansiBrightOrBold = True }+            2  -> \e -> e { ansiFaint = True }+            3  -> \e -> e { ansiItalic = True }+            4  -> \e -> e { ansiUnderline = True }+            7  -> \e -> e { ansiReverse = True }+            10 -> \e -> e { ansiFontNumber = 0 }+            11 -> \e -> e { ansiFontNumber = 1 }+            12 -> \e -> e { ansiFontNumber = 2 }+            13 -> \e -> e { ansiFontNumber = 3 }+            14 -> \e -> e { ansiFontNumber = 4 }+            15 -> \e -> e { ansiFontNumber = 5 }+            16 -> \e -> e { ansiFontNumber = 6 }+            17 -> \e -> e { ansiFontNumber = 7 }+            18 -> \e -> e { ansiFontNumber = 8 }+            19 -> \e -> e { ansiFontNumber = 9 }+            21 -> \e -> e { ansiBrightOrBold = False }+            22 -> \e -> e { ansiBrightOrBold = False+                          , ansiFaint = False+                          }+            23 -> \e -> e { ansiItalic = False }+            24 -> \e -> e { ansiUnderline = False }+            26 -> \e -> e { ansiUnderline = False }+            27 -> \e -> e { ansiReverse = False }+            30 -> \e -> e { ansiFGColor = AnsiBlack }+            31 -> \e -> e { ansiFGColor = AnsiRed }+            32 -> \e -> e { ansiFGColor = AnsiGreen }+            33 -> \e -> e { ansiFGColor = AnsiYellow }+            34 -> \e -> e { ansiFGColor = AnsiBlue }+            35 -> \e -> e { ansiFGColor = AnsiMagenta }+            36 -> \e -> e { ansiFGColor = AnsiCyan }+            37 -> \e -> e { ansiFGColor = AnsiWhite }+            40 -> \e -> e { ansiBGColor = AnsiBlack }+            41 -> \e -> e { ansiBGColor = AnsiRed }+            42 -> \e -> e { ansiBGColor = AnsiGreen }+            43 -> \e -> e { ansiBGColor = AnsiYellow }+            44 -> \e -> e { ansiBGColor = AnsiBlue }+            45 -> \e -> e { ansiBGColor = AnsiMagenta }+            46 -> \e -> e { ansiBGColor = AnsiCyan }+            47 -> \e -> e { ansiBGColor = AnsiWhite }+            51 -> \e -> e { ansiFramed = True }+            52 -> \e -> e { ansiEncircled = True }+            53 -> \e -> e { ansiOverlined = True }+            54 -> \e -> e { ansiFramed = False+                          , ansiEncircled = False+                          }+            55 -> \e -> e { ansiOverlined = False }+            _  -> id)+++data ANSIColor = AnsiBlack+               | AnsiRed+               | AnsiGreen+               | AnsiYellow+               | AnsiBlue+               | AnsiMagenta+               | AnsiCyan+               | AnsiWhite+    deriving Eq++envAttrs :: ANSIEnv -> [HtmlAttr]+envAttrs e =+    let r = ansiReverse env+        env = reverseEnv r e+        bob       = when' (ansiBrightOrBold env) ("bold")+        italic    = when' (ansiItalic env) ("italic")+        underline = when' (ansiUnderline env) ("underline")+        fontnum   = when' (ansiFontNumber env /= 0) ("fontNum" ++ (show $ ansiFontNumber env))+        framed    = when' (ansiFramed env) ("framed")+        fgcolor   = when' (ansiFGColor env /= AnsiBlack) ("fg" ++ (show $ ansiFGColor env))+        bgcolor   = when' (ansiBGColor env /= AnsiBlack) ("bg" ++ (show $ ansiBGColor env))+        classes = map ("ansi2html-"++) $ catMaybes [bob, italic, underline, fontnum, framed, fgcolor, bgcolor]+        joined = foldl (\a b -> if null a then b else a ++ " " ++ b) "" classes+    in [theclass joined]+    where+        when' x y = if x then Just y else Nothing+        -- TODO+        reverseEnv = flip const++instance Show ANSIColor where+    show color = case color of+        AnsiBlack       -> "black"+        AnsiRed         -> "red"+        AnsiGreen       -> "green"+        AnsiYellow      -> "yellow"+        AnsiBlue        -> "blue"+        AnsiMagenta     -> "magenta"+        AnsiCyan        -> "cyan"+        AnsiWhite       -> "white"++data ANSIToken = AnsiText String+           | CtlSeq { privModeChars :: String+                    , optParms      :: [Int]+                    , interMedChars :: String+                    , finalByte     :: Char+                    }+    deriving Show++ansiParser :: MyParser [ANSIToken]+ansiParser = do+    result <- many ansiToken+    eof+    return result++ansiToken :: MyParser ANSIToken+ansiToken = do+    {- xterm prints a strange file with each line prefixed by '\ESC#5'+     - Let's simply remove those prefixes -}+    try (string "\ESC#5") <|> return ""+    try ctlSeq <|> ansiText++ansiText :: MyParser ANSIToken+ansiText = do+    strings <- many1 nonControlChar+    column <- getState+    return $ AnsiText $ concat strings++nonControlChar :: MyParser String+nonControlChar = do+    -- filter out \CR+    try (char '\CR') <|> return ' '+    (counter,columns) <- getState+    r <- satisfy (/='\ESC')+    implicitbreak <- if counter == columns && r /= '\n'+                        then do+                            updateState (mapFst (const 0))+                            return "\n"+                        else return ""+    rr <- if (r == '\n')+     then do+        updateState (mapFst (const 0))+        return $ replicate (fromInteger (columns - counter)) ' ' ++ "\n"+     else do+        updateState (mapFst (+1))+        return [r]+    return $ implicitbreak ++ rr+    where mapFst f (a,b) = (f a,b)++ctlSeq :: MyParser ANSIToken+ctlSeq = do+    csiCode+    parms <- number `sepBy` char ';'+    iMBs <- interMedBytes+    l <- letter+    return $ CtlSeq "" parms iMBs l++number  :: MyParser Int+number  = do{ ds <- many1 digit+            ; return (read ds)+            }+        <?> "number"++interMedBytes :: MyParser String+interMedBytes = return ""++csiCode :: MyParser ()+csiCode = do+    escapeChar+    char '['+    return ()++escapeChar :: MyParser ()+escapeChar = do+    char '\ESC'+    return ()++ansiToken2Html :: ANSIToken -> S.State ANSIEnv X.Html+ansiToken2Html tok = do+    env <- S.get+    case tok of+        AnsiText t -> let html = (linesToHtml $ lines t) +++ (if last t == '\n' then X.br else X.noHtml)+                        in return $ (X.thespan ! envAttrs env) << html+        ctlseq     -> do+                        S.put $ modifyEnv env ctlseq+                        return X.noHtml++ansi2Html :: [ANSIToken] -> X.Html+ansi2Html toks = foldl (+++) noHtml htmls+    where htmls = evalState (mapM ansiToken2Html toks) defaultEnv++makeHtml :: X.Html -> X.Html+makeHtml content = X.thespan ! [theclass "ansi2html"] << content++printUsage :: IO ()+printUsage = do+    hPutStrLn stderr "Usage: ansi2html <columns>"+    hFlush stderr++main = do+    args <- getArgs+    columns <- case args of+        []    -> return 80+        x:xs  -> case reads x :: [(Integer,String)] of+                    [(c,[])]    -> return c+                    _           -> printUsage >> exitFailure+    contents <- getContents+    tokens <- case runParser ansiParser (0,columns) "" contents of+                Left err -> do+                        error $ "parse error at " ++ show err+                Right x -> return x+    print . makeHtml $ ansi2Html tokens
+ LICENSE view
@@ -0,0 +1,30 @@+Copyright (c)2011, Jens Stimpfle++All rights reserved.++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions are met:++    * Redistributions of source code must retain the above copyright+      notice, this list of conditions and the following disclaimer.++    * 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.++    * Neither the name of Jens Stimpfle nor the names of other+      contributors may be used to endorse or promote products derived+      from this software without specific prior written permission.++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 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 COPYRIGHT+OWNER 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.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ ansi2html.css view
@@ -0,0 +1,56 @@+span.ansi2html {+	font-family: monospace;+	background-color: black;+}++/* foreground colors */+.ansi2html-fgblack {+	color: #000;+}+.ansi2html-fgcyan {+	color: #00cdcd;+}+.ansi2html-fgblue {+	color: #0000ee;+}+.ansi2html-fggreen {+	color: #00cd00;+}+.ansi2html-fgmagenta {+	color: #cd00cd;+}+.ansi2html-fgred {+	color: #cd0000;+}+.ansi2html-fgwhite {+	color: #e5e5e5;+}+.ansi2html-fgyellow {+	color: #cdcd00;+}++/* Background background-colors */+.ansi2html-bgblack {+	background-color: #000;+}+.ansi2html-bgcyan {+	background-color: #00cdcd;+}+.ansi2html-bgblue {+	background-color: #0000ee;+}+.ansi2html-bggreen {+	background-color: #00cd00;+}+.ansi2html-bgmagenta {+	background-color: #cd00cd;+}+.ansi2html-bgred {+	background-color: #cd0000;+}+.ansi2html-bgwhite {+	background-color: #e5e5e5;+}+.ansi2html-bgyellow {+	background-color: #cdcd00;+}