BlogLiterately- A tool for posting Haskelly articles to blogs

MaintainerBrent Yorgey <>
Safe HaskellNone




Format specially marked blocks as interactive ghci sessions. Uses some ugly but effective code for interacting with an external ghci process taken from lhs2TeX.


Running ghci

type ProcessInfo = (Handle, Handle, Handle, ProcessHandle)Source

Information about a running process: stdin, stdout, stderr, and a handle.

ghciEval :: GhciInput -> ReaderT ProcessInfo IO GhciOutputSource

Evaluate an expression using an external ghci process.

withGhciProcess :: FilePath -> ReaderT ProcessInfo IO a -> IO aSource

Start an external ghci process, run a computation with access to it, and finally stop the process.

isLiterate :: String -> BoolSource

Poor man's check to see whether we have a literate Haskell file.

stopGhci :: ProcessInfo -> IO ()Source

Stop a ghci process by passing it :q and waiting for it to exit.

Extracting output

To extract the answer from ghci's output we use a simple technique which should work in most cases: we print the string magic before and after the expression we are interested in. We assume that everything that appears before the first occurrence of magic on the same line is the prompt, and everything between the first magic and the second magic plus prompt is the result we look for.

magic :: StringSource

There is nothing magic about the magic string.

breaks :: ([a] -> Bool) -> [a] -> ([a], [a])Source


formatInlineGhci :: FilePath -> Pandoc -> IO PandocSource

Given the path to the .lhs source and its representation as a Pandoc document, formatInlineGhci finds any [ghci] blocks in it, runs them through ghci, and formats the results as an interactive ghci session.

Lines beginning in the first column of the block are interpreted as inputs. Lines indented by one or more space are interpreted as expected outputs. Consecutive indented lines are interpreted as one multi-line expected output, with a number of spaces removed from the beginning of each line equal to the number of spaces at the start of the first indented line.

If the output for a given input is the same as the expected output (or if no expected output is given), the result is typeset normally. If the actual and expected outputs differ, the actual output is typeset first in red, then the expected output in blue.