hpygments (empty) → 0.1.0
raw patch · 9 files changed
+370/−0 lines, 9 filesdep +aesondep +basedep +bytestringsetup-changed
Dependencies added: aeson, base, bytestring, process, process-extras
Files
- LICENSE +19/−0
- README.md +10/−0
- Setup.hs +2/−0
- hpygments.cabal +44/−0
- pygments_dump_json.py +29/−0
- src/Text/Highlighting/Pygments.hs +99/−0
- src/Text/Highlighting/Pygments/Formatters.hs +58/−0
- src/Text/Highlighting/Pygments/JSON.hs +27/−0
- src/Text/Highlighting/Pygments/Lexers.hs +82/−0
+ LICENSE view
@@ -0,0 +1,19 @@+Copyright (c) 2012 David Lazar <lazar6@illinois.edu>++Permission is hereby granted, free of charge, to any person obtaining a copy+of this software and associated documentation files (the "Software"), to deal+in the Software without restriction, including without limitation the rights+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell+copies of the Software, and to permit persons to whom the Software is+furnished to do so, subject to the following conditions:++The above copyright notice and this permission notice shall be included in+all copies or substantial portions of the Software.++THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN+THE SOFTWARE.
+ README.md view
@@ -0,0 +1,10 @@+# About++**hpygments** is a Haskell library for highlighting source code using [Pygments](http://pygments.org).+See the [Hackage page](http://hackage.haskell.org/package/hpygments) for documentation and examples.++# Contributing++This project is available on [GitHub](https://github.com/davidlazar/hpygments) and [Bitbucket](https://bitbucket.org/davidlazar/hpygments/). You may contribute changes using either.++Please report bugs and feature requests using the [GitHub issue tracker](https://github.com/davidlazar/hpygments/issues).
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ hpygments.cabal view
@@ -0,0 +1,44 @@+Name: hpygments+Version: 0.1.0+Synopsis: Highlight source code using Pygments+Description:+ Highlight source code using Pygments <http://pygments.org>. This package+ depends on Pygments and its accompanying @pygmentize@ script.+License: MIT+License-file: LICENSE+Author: David Lazar+Maintainer: David Lazar <lazar6@illinois.edu>+Category: Text+Build-type: Simple+Cabal-version: >=1.6++Extra-source-files:+ README.md++Data-files:+ pygments_dump_json.py++source-repository head+ Type: git+ Location: https://github.com/davidlazar/hpygments++Library+ ghc-options: -Wall++ Hs-source-dirs: src++ Exposed-modules:+ Text.Highlighting.Pygments+ Text.Highlighting.Pygments.Lexers+ Text.Highlighting.Pygments.Formatters++ Other-modules:+ Text.Highlighting.Pygments.JSON+ Paths_hpygments++ Build-depends:+ base >= 4 && < 5,+ bytestring,+ process,+ process-extras >= 0.1.3,+ aeson == 0.6.0.*
+ pygments_dump_json.py view
@@ -0,0 +1,29 @@+#!/usr/bin/env python+import sys+import json+from pygments.lexers import get_all_lexers+from pygments.formatters import get_all_formatters++def lexer_dict(name, aliases, filetypes, mimetypes):+ return { '_lexerName': name+ , '_lexerAliases': list(aliases)+ , '_lexerFileTypes': list(filetypes)+ , '_lexerMimeTypes': list(mimetypes)+ }++def formatter_dict(f):+ return { '_formatterName': f.name+ , '_formatterAliases': list(f.aliases)+ }++if len(sys.argv) < 2:+ print('Usage: {} (lexers|formatters)'.format(sys.argv[0]))+ sys.exit(1)++if sys.argv[1] == "lexers":+ lexers = [lexer_dict(*x) for x in get_all_lexers()]+ json.dump(lexers, sys.stdout)++if sys.argv[1] == "formatters":+ formatters = [formatter_dict(x) for x in get_all_formatters()]+ json.dump(formatters, sys.stdout)
+ src/Text/Highlighting/Pygments.hs view
@@ -0,0 +1,99 @@+-----------------------------------------------------------------------------+-- |+-- Module : Text.Highlighting.Pygments+-- Copyright : (c) David Lazar, 2012+-- License : MIT+--+-- Maintainer : lazar6@illinois.edu+-- Stability : experimental+-- Portability : unknown+--+-- This library uses the @pygmentize@ script that comes with Pygments to+-- highlight code in many languages. For documentation on the various lexers,+-- formatters, and options, see the Pygments documentation+-- <http://pygments.org/docs/>.+-----------------------------------------------------------------------------++module Text.Highlighting.Pygments+ (+ highlight+ , pygmentize++ , module Text.Highlighting.Pygments.Lexers+ , module Text.Highlighting.Pygments.Formatters++ -- * Options+ , Option+ , Options++ -- * Examples+ -- $examples+ ) where++import System.Process (readProcess)++import Text.Highlighting.Pygments.Lexers+import Text.Highlighting.Pygments.Formatters++-- | Highlight code robustly. This function is more robust than the+-- lower-level 'pygmentize' function since this library forbids the +-- construction of invalid 'Lexer' and 'Formatter' values. Invalid+-- 'Options' may still cause this function to raise an exception.+highlight :: Lexer -> Formatter -> Options -> String -> IO String+highlight lexer formatter options code = do+ let (lexerAlias : _) = lexerAliases lexer+ let (formatterAlias : _) = formatterAliases formatter+ pygmentize lexerAlias formatterAlias options code++-- | Highlight code (less robustly) using the @pygmentize@ script that comes+-- with Pygments. Invalid values for 'LexerAlias', 'FormatterAlias', or+-- 'Options' will cause this function to raise an exception.+pygmentize :: LexerAlias -> FormatterAlias -> Options -> String -> IO String+pygmentize lexer formatter options code = do+ let args = ["-l", lexer, "-f", formatter] ++ optionsToArgs options+ readProcess "pygmentize" args code++-- | The lexer/formatter option @(key, value)@ is passed to the @pygmentize@ +-- script via the command-line flag @-P key=value@.+--+-- Examples:+--+-- > [("hl_lines", "16,23,42"), ("encoding", "utf-8"), ("anchorlines", "True")]+--+type Option = (String, String)+type Options = [Option]++optionsToArgs :: Options -> [String]+optionsToArgs options = concatMap optionToArg options++optionToArg :: Option -> [String]+optionToArg (name, value) = ["-P", name ++ "=" ++ value]++{- $examples++Highlight a proposition:++>>> Just coqLexer <- getLexerByName "coq"+>>> highlight coqLexer terminalFormatter [("encoding", "utf-8")] "∀ x y : Z, x * y = 0 -> x = 0 \\/ y = 0" >>= putStr+∀ x y : Z, x * y = 0 -> x = 0 \/ y = 0++Output a complete HTML document:++>>> highlight haskellLexer htmlFormatter [("full", "True"), ("linenos", "table"), ("style", "emacs")] "fix f = let x = f x in x" >>= writeFile "fix.html"++Self-highlighting quine:++> quine = pygmentize "hs" "terminal" [] (s ++ show s) >>= putStr+> where s = "quine = pygmentize \"hs\" \"terminal\" [] (s ++ show s) >>= putStr\n where s = "++Highlight the code \"answer = 42\" using every language Pygments knows about:++>>> lexers <- getAllLexers+>>> forM_ lexers $ \l -> highlight l terminalFormatter [] "answer = 42" >>= printf "(%s) %s" (lexerName l)+...+(Prolog) answer = 42+(CSS+Django/Jinja) answer = 42+(Smalltalk) answer = 42+...++-}
+ src/Text/Highlighting/Pygments/Formatters.hs view
@@ -0,0 +1,58 @@+{-# LANGUAGE TemplateHaskell #-}+module Text.Highlighting.Pygments.Formatters+ (+ FormatterAlias+ , Formatter+ , getAllFormatters+ , getFormatterByName++ -- ** Accessors+ , formatterName+ , formatterAliases++ -- ** Common formatters+ , htmlFormatter+ , terminalFormatter+ ) where++import Data.Aeson.TH (deriveJSON)+import Data.Maybe (listToMaybe)++import Text.Highlighting.Pygments.JSON++type FormatterAlias = String++data Formatter = Formatter+ { _formatterName :: String+ , _formatterAliases :: [FormatterAlias]+ } deriving (Eq, Ord, Show)++$(deriveJSON id ''Formatter)++getAllFormatters :: IO [Formatter]+getAllFormatters = getPygmentsJSON "formatters"++-- | Similar to the @get_formatter_by_name()@ function in Pygments+getFormatterByName :: FormatterAlias -> IO (Maybe Formatter)+getFormatterByName name = do+ formatters <- getAllFormatters+ let fs = filter (\f -> name `elem` _formatterAliases f) formatters+ return $ listToMaybe fs++formatterName :: Formatter -> String+formatterName = _formatterName++formatterAliases :: Formatter -> [FormatterAlias]+formatterAliases = _formatterAliases++htmlFormatter :: Formatter+htmlFormatter = Formatter+ { _formatterName = "HTML"+ , _formatterAliases = ["html"]+ }++terminalFormatter :: Formatter+terminalFormatter = Formatter+ { _formatterName = "Terminal"+ , _formatterAliases = ["terminal", "console"]+ }
+ src/Text/Highlighting/Pygments/JSON.hs view
@@ -0,0 +1,27 @@+{-# LANGUAGE OverloadedStrings #-}+module Text.Highlighting.Pygments.JSON + (+ getPygmentsJSON+ ) where++import Control.Monad (when)+import Data.Aeson (decode, FromJSON)+import Data.ByteString.Lazy.Char8 ()+import System.Exit+import System.Process.ByteString.Lazy++import Paths_hpygments++getJSONDumper :: IO FilePath+getJSONDumper = getDataFileName "pygments_dump_json.py"++getPygmentsJSON :: FromJSON a => String -> IO a+getPygmentsJSON what = do+ jsonDumper <- getJSONDumper+ (exitCode, stdout, _) <- readProcessWithExitCode jsonDumper [what] ""+ when (exitCode /= ExitSuccess) $+ fail $ jsonDumper ++ " failed: " ++ show exitCode+ case decode stdout of+ Nothing -> fail $ "failed to decode " ++ what+ Just ls -> return ls+
+ src/Text/Highlighting/Pygments/Lexers.hs view
@@ -0,0 +1,82 @@+{-# LANGUAGE TemplateHaskell #-}+module Text.Highlighting.Pygments.Lexers+ (+ LexerAlias+ , Lexer+ , getAllLexers+ , getLexerByName++ -- ** Accessors+ , lexerName+ , lexerAliases+ , lexerFileTypes+ , lexerMimeTypes++ -- ** Common lexers+ , haskellLexer+ , literateHaskellLexer+ , textLexer+ ) where++import Data.Aeson.TH (deriveJSON)+import Data.Maybe (listToMaybe)++import Text.Highlighting.Pygments.JSON++type LexerAlias = String++data Lexer = Lexer+ { _lexerName :: String+ , _lexerAliases :: [LexerAlias]+ , _lexerFileTypes :: [String]+ , _lexerMimeTypes :: [String]+ } deriving (Eq, Ord, Show)++$(deriveJSON id ''Lexer)++getAllLexers :: IO [Lexer]+getAllLexers = getPygmentsJSON "lexers"++-- | Similar to the @get_lexer_by_name()@ function in Pygments+getLexerByName :: LexerAlias -> IO (Maybe Lexer)+getLexerByName name = do+ lexers <- getAllLexers+ let ls = filter (\l -> name `elem` _lexerAliases l) lexers+ return $ listToMaybe ls++lexerName :: Lexer -> String+lexerName = _lexerName++lexerAliases :: Lexer -> [LexerAlias]+lexerAliases = _lexerAliases++lexerFileTypes :: Lexer -> [String]+lexerFileTypes = _lexerFileTypes++lexerMimeTypes :: Lexer -> [String]+lexerMimeTypes = _lexerMimeTypes++haskellLexer :: Lexer+haskellLexer = Lexer+ { _lexerName = "Haskell"+ , _lexerAliases = ["haskell","hs"]+ , _lexerFileTypes = ["*.hs"]+ , _lexerMimeTypes = ["text/x-haskell"]+ }++literateHaskellLexer :: Lexer+literateHaskellLexer = Lexer + { _lexerName = "Literate Haskell"+ , _lexerAliases = ["lhs","literate-haskell"]+ , _lexerFileTypes = ["*.lhs"]+ , _lexerMimeTypes = ["text/x-literate-haskell"]+ }++-- | No highlighting+textLexer :: Lexer+textLexer = Lexer+ { _lexerName = "Text only"+ , _lexerAliases = ["text"]+ , _lexerFileTypes = ["*.txt"]+ , _lexerMimeTypes = ["text/plain"]+ }