A tool for creation of html
documents
from evaluated comments in Haskell source code.
The idea is that from a single
key press you get a refreshed "notebook" in the browser with
recomputed results and diagrams.
Using any editor that can make
the working directory it is possible to enjoy a
pleasant and productive workflow.
This is included in the artools
package, available from the easyVision repository. Clone the repo, checkout the branch reorg
, cd packages/tools, and cabal install.
The following command creates fname.html
from fname.hs
$ mkwb [--keep] [-v] fname
Multiline comments starting by {- !MARKDOWN
are interpreted as standard markdown, with the following extensions:
!TITLE(name) includes the file HEADER
located in the current directory,
which contains the desired html head of the document. We can put there
mathjax initialization scripts, fonts, etc., and link to a CSS stylesheet to customize
the final appearance of the document.
The sequence [title]
in this file (typically appearing as <TITLE>[title]</TITLE>
) is replaced by the given name
.
!THIS: The full source code in the current file (excepted the markdown comments) is silently included in the auxiliary program which creates the final document.
!HCODE: The Haskell code between this keyword and !END is silently included in the auxiliary program which creates the final document.
!CODE: The Haskell code between this keyword and !END is displayed using hscolour and included in the auxiliary program which creates the final document.
\perform{} run an IO() action and show the result inline.
All the hreplace commands described here are also available.
The following commands are available by including the following file defs.txt
, which
rely on suitably defined CSS styles.
\ eval{} show the result of a pure expression inline (similar to lhs2tex).
!eval: show a pure expression and print its value.
!print: show an IO action and print its result.
!pprint: similar to !print with a hidden "pretty printing" function delimited by the first $
.
!def: define a local value in the simulated interactive session which creates the page using let
or <-
.
!raw: insert directly the result of an IO action in the html document (e.g. a svg diagram) enclosed in a pre
block to inhibit markdown.
!wrong: used to show an incorrect expression. It is not evaluated, and the error
message that would be obtained can be included in a pre
block with hsw
sytle).
!HSDEF: include and pretty-print a file (or fragment) using hscolour.
From the following haskell program:
import Text.Printf(printf) import Data.List.Split import Numeric.LinearAlgebra.HMatrix import Graphics.SVG main = do putStrLn "Hello!" {- !MARKDOWN --------------------------------------- !TITLE(hs2html test) !THIS !INCLUDE defs.txt ## example commands Inline evaluation: the result of 2+2 is \eval{2+2}, and $\pi\simeq \perform{printf "%.4f\n" (pi::Double)}$. "Tutorial style" evaluation: !eval 2+2 !print putStrLn $ "Hello"++" Haskell" -----------------------------------------------------} x :: [String] x = splitOn "," "one, two, three and four" y = diagl [1..5] {- !MARKDOWN ----------------------------------------- !pprint dispDots 3 $ y !def a <- randn 3 5 !pprint (disp 2 . (+5)) $ a !def let b = "a short sentence" \perform{putStrLn $ "<p><strong>" ++ b ++ "</strong></p>"} A compilation error: !wrong 2+"a" <pre id="hsw"> No instance for (Num [Char]) arising from a use of ‘+’ In the expression: 2 + "a"</pre> Exposed code: !CODE c = diagl [1..3] !END !eval c Hidden code: !HCODE d = diagl [1..3] !END !eval d Show a fragment of this file: !HSDEF(test.hs x ::) !print mapM_ print x !DEFINE blue = red; red = blue; green = yellow; HASK X = <X>Haskell</X> Result of replacement rules: The sky is blue, but it looks red. We can write HASK(strong) and HASK(tt), today is !DATE. And we can hide !IGNORE!several pieces of! text. !DEFINE PRE X Y = <pre id="X">Y</pre>; EXAMPLE X = PRE(hsr X) EXAMPLE(This is formatted as demo text) !DEFINE !FCODE style filename = PRE{style <code>#!INCLUDE(filename)</code>} And this is an included file in pre code blocks with different styles: !FCODE example test.c !FCODE hsr test.c Pretty print some code (not included in the the program). #!HSCOLOUR! fact 0 = 1 fact n = n * fact (n-1) ! This is an included haskell file with the filename added as a comment. #!WITHNAME sample.hs And this is an example of using local rules (remember that Green is now green): #!REPLACE> !FCODE(example sample.hs) !LOCAL green = violet ------------------------------------------------------} plot1 = hPlot [ plot x (f x) "blue" 1 "" ] where x = linspace 200 (0,2*pi) f x = exp (-0.5*(x-3)**2) * sin (5*x) {- !MARKDOWN ---------------------------------------- This is an example of an included graphic: !raw putStr plot1 ------------------------------------------------------}
We get the following html page (the final appearance can be easily changed using the CSS styles):
If the final document contains results that require long computations we can temporarily suppress output with a definition like
!DEFINE \perform x = (OMITTED)
so we can quickly edit and see results without waiting for certain computations. To see the complete document we can "ignore" the above definition:
!IGNORE !DEFINE \perform x = (OMITTED)
A big document can also be created by including several parts coming from separate source code files.
With the option --latex
the mkwb program can also be used to generate $\LaTeX$. (There are better tools
like lhs2tex and haskintex,
but this option comes for free from the infrastructure developed for html
.)
In this case the comments must begin with {- !LaTeX
and the only commands that make sense are:
!THIS
!HCODE ... !END
\perform{action}. This can be used both to insert results and to create auxiliary files (e.g. charts) to be used and referenced later.
Other commands like \eval{} can be easily defined in the source code or in included files.