language-python-colour (empty) → 0.1
raw patch · 6 files changed
+286/−0 lines, 6 filesdep +basedep +haskell98dep +language-pythonsetup-changed
Dependencies added: base, haskell98, language-python, xhtml
Files
- LICENSE +27/−0
- Setup.lhs +3/−0
- language-python-colour.cabal +23/−0
- src/Language/Python/Colour/Colourise.hs +63/−0
- src/Language/Python/Colour/Options.hs +109/−0
- src/Main.hs +61/−0
+ LICENSE view
@@ -0,0 +1,27 @@+Copyright (c) 2009 Bernard James Pope ++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 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.lhs view
@@ -0,0 +1,3 @@+#!/usr/bin/env runhaskell+> import Distribution.Simple+> main = defaultMain
+ language-python-colour.cabal view
@@ -0,0 +1,23 @@+name: language-python-colour +version: 0.1 +cabal-version: >= 1.6+synopsis: Generate coloured XHTML for Python code. +description: Generate coloured XHTML for Python code. +category: Language+license: BSD3+license-file: LICENSE+copyright: (c) 2009 Bernard James Pope+author: Bernard James Pope +maintainer: bjpop@csse.unimelb.edu.au+homepage: http://www.cs.mu.oz.au/~bjpop/+build-type: Simple+stability: experimental+tested-with: GHC==6.10.4++Executable pycol + main-is: Main.hs+ hs-source-dirs: src+ build-depends: haskell98, base >= 4 && < 5, language-python, xhtml+ other-modules:+ Language.Python.Colour.Colourise+ Language.Python.Colour.Options
+ src/Language/Python/Colour/Colourise.hs view
@@ -0,0 +1,63 @@+-----------------------------------------------------------------------------+-- |+-- Module : Language.Python.Colour.Colourise+-- Copyright : (c) 2009 Bernie Pope +-- License : BSD-style+-- Maintainer : bjpop@csse.unimelb.edu.au+-- Stability : experimental+-- Portability : ghc+--+-- Turn Python tokens into HTML (for colouring), matching the layout of +-- the input program.+-----------------------------------------------------------------------------+module Language.Python.Colour.Colourise ( colourise ) where++import Language.Python.Common+import Text.XHtml.Transitional++colourise :: String -> [Token] -> String+colourise progName tokens = showHtml $ makeHtml progName tokens++makeHtml :: String -> [Token] -> Html+makeHtml progName tokens = theHead progName +++ theBody tokens++theHead :: String -> Html+theHead progName = + header << (title +++ link)+ where + title = thetitle << progName + link = (thelink << noHtml) ! + [ thetype "text/css", rel "stylesheet", href "pycol.css" ] ++theBody :: [Token] -> Html+theBody tokens = pre << renderTokens tokens++renderTokens :: [Token] -> Html +renderTokens [] = noHtml +renderTokens [t] = tokenSpan t +renderTokens (t1:t2:ts)+ | getSpan t1 == SpanEmpty = renderTokens (t2:ts)+ | getSpan t2 == SpanEmpty = renderTokens (t1:ts)+ | otherwise = + tokenSpan t1 ++++ (toHtml $ pad t1EndRow t1EndCol t2StartRow t2StartCol) ++++ renderTokens (t2:ts)+ where+ t1Span = getSpan t1+ t2Span = getSpan t2+ t1EndRow = endRow t1Span + t1EndCol = endCol t1Span + t2StartRow = startRow t2Span + t2StartCol = startCol t2Span ++pad :: Int -> Int -> Int -> Int -> String+pad endRow endCol startRow startCol+ | endRow /= startRow = + replicate (startRow - endRow) '\n' ++ + replicate (startCol-1) ' '+ | otherwise = replicate (startCol - endCol - 1) ' '++tokenSpan :: Token -> Html+tokenSpan token =+ (thespan << tokenString token) ! + [ theclass $ show $ classifyToken token ]
+ src/Language/Python/Colour/Options.hs view
@@ -0,0 +1,109 @@+-----------------------------------------------------------------------------+-- |+-- Module : Language.Python.Colour.Options+-- Copyright : (c) 2009 Bernie Pope +-- License : BSD-style+-- Maintainer : bjpop@csse.unimelb.edu.au+-- Stability : experimental+-- Portability : ghc+--+-- Command line option processing for the Python colouring program.+-----------------------------------------------------------------------------+module Language.Python.Colour.Options + ( processOptions+ , programName+ , Flag (..)+ , PythonVersion (..)+ , getPyVersion+ , probeFlags+ , probeFlagsFirst+ , existsFlag+ , defaultPyVersion+ )+ where++import System.Console.GetOpt +import Data.Maybe (fromMaybe)+import Data.Char (toLower, isDigit)+import Data.Maybe (catMaybes)+import IO (stderr, hPutStrLn)+import System++programName :: String+programName = "pycol"++-- This should really come from the cabal file somehow.+versionNumber :: String+versionNumber = "0.1"++versionInfo :: String+versionInfo = unwords [programName, "version", versionNumber]++processOptions :: [String] -> IO ([Flag], String)+processOptions argv = + case getOpt RequireOrder options argv of+ (flags, nonOpts, []) + | existsFlag flags Help -> do + putStrLn $ usageInfo header options+ exitWith ExitSuccess+ | existsFlag flags Version -> do + putStrLn versionInfo + exitWith ExitSuccess+ | length nonOpts /= 1 ->+ raiseError ["You must specify a single input Python file.\n"] + | otherwise -> return (flags, head nonOpts)+ (_, _, errs) -> raiseError errs+ where + header = "Usage: " ++ programName ++ " [OPTION...] file"+ failureMsg = programName ++ ": command line error.\n"+ raiseError errs = do+ hPutStrLn stderr $ failureMsg ++ concat errs ++ usageInfo header options+ exitFailure++probeFlags :: [Flag] -> (Flag -> Maybe a) -> [a]+probeFlags flags probe = catMaybes (map probe flags)++probeFlagsFirst :: [Flag] -> (Flag -> Maybe a) -> a -> a+probeFlagsFirst flags probe defaultValue+ | null probed = defaultValue + | otherwise = head probed+ where+ probed = probeFlags flags probe++existsFlag :: [Flag] -> Flag -> Bool+existsFlag flags f+ = probeFlagsFirst flags probe False + where+ probe someFlag = if f == someFlag then Just True else Nothing + +data Flag + = PyVersion PythonVersion -- ^ Which version of Python to parse (2 or 3).+ | Help -- ^ Print a help message and exit.+ | Version -- ^ Print the version number. + deriving (Eq, Ord, Show)++getPyVersion :: Flag -> Maybe PythonVersion+getPyVersion (PyVersion v) = Just v+getPyVersion _ = Nothing++data PythonVersion+ = V2 + | V3 + deriving (Eq, Ord, Show)++options :: [OptDescr Flag]+options =+ [ Option ['p'] ["pyver"] (ReqArg mkPyVersion "VERSION") "VERSION of Python to parse: 2 or 3 (default is 2)"+ , Option ['v'] ["version"] (NoArg Version) "show version number"+ , Option ['h'] ["help"] (NoArg Help) "get help about using this program"+ ]++defaultPyVersion :: PythonVersion +defaultPyVersion = V2 ++mkPyVersion :: String -> Flag+mkPyVersion = normalMkVersion . map toLower+ where+ normalMkVersion "2" = PyVersion V2 + normalMkVersion "3" = PyVersion V3 + normalMkVersion other = PyVersion defaultPyVersion
+ src/Main.hs view
@@ -0,0 +1,61 @@+-----------------------------------------------------------------------------+-- |+-- Module : Main+-- Copyright : (c) 2009 Bernie Pope +-- License : BSD-style+-- Maintainer : bjpop@csse.unimelb.edu.au+-- Stability : experimental+-- Portability : ghc+--+-- Generate coloured XHTML for a Python source file. Supports version 2 and+-- 3 of Python. The name of the file is given as a command line argument+-- and an XHTML file is produced on the standard output. +--+-----------------------------------------------------------------------------++module Main where++import Language.Python.Colour.Options +import Language.Python.Colour.Colourise+import qualified Language.Python.Version2 as V2+import qualified Language.Python.Version3 as V3+import Language.Python.Common+import Prelude hiding (lex)+import System +import Control.Monad (when, liftM)+import IO++main :: IO ()+main = do+ args <- getArgs+ (flags, filename) <- processOptions args+ tryContents <- safeReadFile filename+ case tryContents of+ Left error -> putStrLn error >> exitFailure+ Right contents -> do+ -- decide which parser and lexer to use (version 2 or 3?)+ let (parser, lexer) = getParserLexer flags+ case lexer contents filename of+ Left e -> hPutStrLn stderr (prettyText e) >> exitFailure+ Right tokens -> putStrLn $ colourise filename tokens++type Parser = String -> String -> Either ParseError (ModuleSpan, [Token])+type Lexer = String -> String -> Either ParseError [Token]++-- decide which parser and lexer to use based on command line arguments (version 2 or 3?)+getParserLexer :: [Flag] -> (Parser, Lexer)+getParserLexer [] = (V2.parseModule, V2.lex)+getParserLexer flags =+ case pyVersion of+ V2 -> (V2.parseModule, V2.lex)+ V3 -> (V3.parseModule, V3.lex)+ where+ pyVersion = probeFlagsFirst flags getPyVersion defaultPyVersion++-- Read a file and check for exceptions.+safeReadFile :: FilePath -> IO (Either String String)+safeReadFile file+ = catch (rightReadFile file) $ \error -> return $ Left $ show error+ where+ rightReadFile :: FilePath -> IO (Either String String)+ rightReadFile file = liftM Right $ readFile file