Highlighting in the manual

* Replace caml-sl with the standard listings package
and ulem package
* update caml_tex to output nicer latex code
* simplify escaping in caml_tex
master
Florian Angeletti 2019-10-31 17:48:10 +01:00
parent 3bd80fbb6e
commit b768c0be59
12 changed files with 292 additions and 219 deletions

View File

@ -23,9 +23,11 @@ TEXINPUTS = ".:..:../refman:../library:../cmds:../tutorials:../../styles:"
RELEASE = $$HOME/release/$${RELEASENAME}
HEVEA = hevea
HACHA = hacha
INFO_FLAGS = -fix -exec xxdate.exe -info -w 79
# We suppress warnings in info and text mode (with -s) because hevea listings emit
# DIV blocks that the text modes do not know how to interpret.
INFO_FLAGS = -fix -exec xxdate.exe -info -w 79 -s
HTML_FLAGS = -fix -exec xxdate.exe -O
TEXT_FLAGS = -fix -exec xxdate.exe -text -w 79
TEXT_FLAGS = -fix -exec xxdate.exe -text -w 79 -s
manual: files

View File

@ -1,10 +1,9 @@
% Colors for links
\def\visited@color{\#0d46a3}
\def\link@color{\#4286f4}
\def\hover@color{\@getstylecolor{subsection}}
\newstyle{a:link}{color:\link@color;text-decoration:underline;}
\newstyle{a:visited}{color:\visited@color;text-decoration:underline;}
\newstyle{a:hover}{color:black;text-decoration:underline;background-color:\hover@color}
\newstyle{a:hover}{color:black;text-decoration:underline;}
\newstyle{@media all}{@font-face \{
@ -49,7 +48,40 @@
border: 1px solid grey;
padding: 10px;
overflow-y:auto;
white-space: pre-wrap;
display:flex;
flex-direction: column;
flex-wrap: nowrap;
/* white-space: pre-wrap;*/
}
\newstyle{.ocamlkeyword}{
font-weight:bold;
}
\newstyle{.ocamlhighlight}{
font-weight:bold;
text-decoration:underline;
}
\newstyle{.ocamlerror}{
font-weight:bold;
color:red;
}
\newstyle{.ocamlwarning}{
font-weight:bold;
color:purple;
}
\newstyle{.ocamlcomment}{
color:grey;
}
\newstyle{.ocamlstring}{
opacity:0.75;
}
% Creative commons license logo
@ -69,7 +101,8 @@
\newstyle{div.caml-example.toplevel div.caml-input::before}
{content:"\#"; color:black;}
\newstyle{div.caml-example.toplevel div.caml-input}{color:\#006000;}
%%%
%%% Code examples
\newcommand{\input@color}{\htmlcolor{006000}}
\newcommand{\output@color}{\maroon}
\newcommand{\machine}{\tt}
@ -79,14 +112,10 @@
\newcommand{\nextline}{\examplespace\ }
\newcommand{\@zyva}{\firstline\renewcommand{\?}{\nextline}}
\let\?=\@zyva
\newenvironment{camlunder}{\@style{U}}{}
\newcommand{\caml}{\begin{alltt}\renewcommand{\;}{}\renewcommand{\\}{\char92}\def\<{\begin{camlunder}}\def\>{\end{camlunder}}\activebracefalse}
\newcommand{\endcaml}{\activebracetrue\end{alltt}
}
\renewcommand{\:}{\renewcommand{\?}{\@zyva}}
\newcommand{\var}[1]{\textit{#1}}
% Caml-example environment
%% Caml-example environment
\newcommand{\camlexample}[1]{
\ifthenelse{\equal{#1}{toplevel}}
{\renewcommand{\examplespace}{\ }}
@ -99,14 +128,16 @@
\renewcommand{\examplespace}{\ }
}
\newcommand{\camlinput}{\@open{div}{class="caml-input"}}
\newcommand{\endcamlinput}{\@close{div}}
\newcommand{\camloutput}{\@open{div}{class="caml-output ok"}}
\newcommand{\endcamloutput}{\@close{div}}
\newcommand{\camlerror}{\@open{div}{class="caml-output error"}}
\newcommand{\endcamlerror}{\@close{div}}
\newcommand{\camlwarn}{\@open{div}{class="caml-output warn"}}
\newcommand{\endcamlwarn}{\@close{div}}
\newenvironment{caml}{\@open{pre}{class=ocaml}}{\@close{pre}}
\newcommand{\ocamlkeyword}{\@span{class="ocamlkeyword"}}
\newcommand{\ocamlhighlight}{\@span{class="ocamlhighlight"}}
\newcommand{\ocamlerror}{\@span{class="ocamlerror"}}
\newcommand{\ocamlwarning}{\@span{class="ocamlwarning"}}
\newcommand{\ocamlcomment}{\@span{class="ocamlcomment"}}
\newcommand{\ocamlstring}{\@span{class="ocamlstring"}}
%%% End of code example
\newenvironment{library}{}{}
\newcounter{page}

View File

@ -205,4 +205,27 @@
\newenvironment{maintitle}{\begin{center}}{\end{center}}
% Caml-example related command
\newenvironment{camlexample}[1]{
\ifnum\pdfstrcmp{#1}{toplevel}=0
\renewcommand{\hash}{\#}
\else
\renewcommand{\hash}{}
\fi
}{}
\newenvironment{caml}{}{}
\newcommand{\ocamlkeyword}{\bfseries}
\newcommand{\ocamlhighlight}{\bfseries\uline}
\newcommand{\ocamlerror}{\bfseries}
\newcommand{\ocamlwarning}{\bfseries}
\definecolor{gray}{gray}{0.5}
\newcommand{\ocamlcomment}{\color{gray}\normalfont\small}
\newcommand{\ocamlstring}{\color{gray}\bfseries}
\newcommand{\?}{\normalsize\tt\hash{} }
\renewcommand{\:}{\small\ttfamily\slshape}
\makeatother

View File

@ -4,18 +4,19 @@
\newcommand{\machine}{\tt}
\newenvironment{machineenv}{\begin{alltt}}{\end{alltt}}
\newenvironment{camlunder}{\@style{U}}{}
\newcommand{\caml}{\begin{alltt}\renewcommand{\\}{\char92}\def\<{\begin{camlunder}}\def\>{\end{camlunder}}\activebracefalse}
\newcommand{\endcaml}{\activebracetrue\end{alltt}}
\newcommand{\?}{\black\#\blue }
\renewcommand{\:}{\maroon}
\def\camlinput{}
\def\endcamlinput{}
\def\camloutput{}
\def\endcamloutput{}
\def\camlerror{}
\def\endcamlerror{}
\def\camlwarn{}
\def\endcamlwarn{}
\newcommand{\ocamlkeyword}{\bfseries}
\newcommand{\ocamlhighlight}{\bfseries\underline}
\newcommand{\ocamlerror}{\bfseries}
\newcommand{\ocamlwarning}{\bfseries}
\newcommand{\ocamlcomment}{\normalfont\small}
\newcommand{\ocamlstring}{\bfseries}
\newenvironment{caml}{\begin{alltt}}{\\\end{alltt}}
\newenvironment{camlexample}[1]{}{}
\newcommand{\var}[1]{\textit{#1}}
\newenvironment{library}{}{}

View File

@ -3,17 +3,102 @@
\usepackage[utf8]{inputenc}
\usepackage[T1]{fontenc}
% HEVEA\@def@charset{UTF-8}%
\usepackage{alltt}
\usepackage{fullpage}
\usepackage{syntaxdef}
\usepackage{multind}
\usepackage{html}
\usepackage{textcomp}
\usepackage{caml-sl}
\usepackage{ocamldoc}
\usepackage{xspace}
\usepackage{color}
% Package for code examples:
\usepackage{listings}
\usepackage{alltt}
\usepackage{lmodern}% for supporting bold ttfamily in code examples
\usepackage[normalem]{ulem}% for underlining errors in code examples
\input{macros.tex}
\newcommand{\hash}{\#}
\lstnewenvironment{camloutput}{
\lstset{
basicstyle=\small\ttfamily\slshape,
showstringspaces=false,
language=caml,
escapeinside={$}{$},
columns=fullflexible,
stringstyle=\ocamlstring,
keepspaces=true,
keywordstyle=\ocamlkeyword,
keywords={[2]{val}}, keywordstyle={[2]\ocamlkeyword},
aboveskip=0\baselineskip,
}
\ifouthtml
\setenvclass{lstlisting}{caml-output ok}
\lstset {basicstyle=\ttfamily}
\else
\lstset{upquote=true}
\fi
}{}
\lstnewenvironment{camlinput}{
\lstset{
basicstyle=\ttfamily,
showstringspaces=false,
language=caml,
escapeinside={$}{$},
columns=fullflexible,
stringstyle=\ocamlstring,
commentstyle=\ocamlcomment,
keepspaces=true,
keywordstyle=\ocamlkeyword,
moredelim=[is][\ocamlhighlight]{<<}{>>},
moredelim=[s][\ocamlstring]{\{|}{|\}},
moredelim=[s][\ocamlstring]{\{delimiter|}{|delimiter\}},
keywords={[2]{val,initializer,nonrec}}, keywordstyle={[2]\ocamlkeyword},
belowskip=0\baselineskip
}
\ifouthtml
\setenvclass{lstlisting}{caml-input}
\else
%not implemented in hevea: upquote
\lstset{upquote=true}
\fi
}{}
\lstnewenvironment{camlerror}{
\lstset{
escapeinside={$}{$},
showstringspaces=false,
basicstyle=\small\ttfamily\slshape,
emph={Error}, emphstyle={\ocamlerror},
}
\ifouthtml
\setenvclass{lstlisting}{caml-output error}
\lstset { basicstyle=\ttfamily }
\else
\lstset{upquote=true}
\fi
}
{}
\lstnewenvironment{camlwarn}{
\lstset{
escapeinside={$}{$},
showstringspaces=false,
basicstyle=\small\ttfamily\slshape,
emph={Warning}, emphstyle={\ocamlwarning},
}
\ifouthtml
\setenvclass{lstlisting}{caml-output warn}
\lstset { basicstyle=\ttfamily }
\else
\lstset{upquote=true}
\fi
}{}
% Add meta tag to the generated head tag
\ifouthtml
@ -36,5 +121,3 @@
%HEVEA\setcounter{cuttingdepth}{1}
%HEVEA\title{The OCaml system, release \ocamlversion}
\input{allfiles.tex}

View File

@ -1,61 +0,0 @@
% CAML style option, for use with the caml-latex filter.
\typeout{Document Style option `caml-sl' <7 Apr 92>.}
\newcommand{\hash}{\#}
{\catcode`\^^M=\active %
\gdef\@camlinputline#1^^M{\normalsize\tt\hash{} #1\par} %
\gdef\@camloutputline#1^^M{\small\ttfamily\slshape#1\par} } %
\def\@camlblankline{\medskip}
\chardef\@camlbackslash="5C
\def\@bunderline{\setbox0\hbox\bgroup\let\par\@parinunderline}
\def \@parinunderline {\futurelet \@next \@@parinunderline}
\def \@@parinunderline {\ifx \@next \? \let \@do \@@par@inunderline \else \let \@do \@@@parinunderline \fi \@do}
\def \@@par@inunderline #1{\@eunderline\@oldpar\?\@bunderline}
\def \@@@parinunderline {\@eunderline\@oldpar\@bunderline}
\def\@eunderline{\egroup\underline{\box0}}
\def\@camlnoop{}
\def\caml{
\bgroup
\parindent 0pt
\parskip 0pt
\let\do\@makeother\dospecials
\catcode13=\active % 13 = ^M = CR
\catcode92=0 % 92 = \
\catcode32=\active % 32 = SPC
\frenchspacing
\@vobeyspaces
\let\@oldpar\par
\let\?\@camlinputline
\let\:\@camloutputline
\let\;\@camlblankline
\let\<\@bunderline
\let\>\@eunderline
\let\\\@camlbackslash
\let\-\@camlnoop
}
\def\endcaml{
\egroup
\addvspace{\medskipamount}
}
% Caml-example related command
\def\camlexample#1{
\ifnum\pdfstrcmp{#1}{toplevel}=0
\renewcommand{\hash}{\#}
\else
\renewcommand{\hash}{}
\fi
\begin{flushleft}
}
\def\endcamlexample{\end{flushleft}\renewcommand{\hash}{\#}}
\def\camlinput{}
\def\endcamlinput{}
\def\camloutput{}
\def\endcamloutput{}
\def\camlerror{}
\def\endcamlerror{}
\def\camlwarn{}
\def\endcamlwarn{}

View File

@ -1,31 +0,0 @@
% CAML style option, for use with the caml-latex filter.
\typeout{Document Style option `caml' <7 Apr 92>.}
{\catcode`\^^M=\active %
\gdef\@camlinputline#1^^M{\tt\##1\par} %
\gdef\@camloutputline#1^^M{\tt#1\par} } %
\def\@camlblankline{\medskip}
\chardef\@camlbackslash="5C
\def\caml{
\bgroup
\flushleft
\parindent 0pt
\parskip 0pt
\let\do\@makeother\dospecials
\catcode`\^^M=\active
\catcode`\\=0
\catcode`\ \active
\frenchspacing
\@vobeyspaces
\let\?\@camlinputline
\let\:\@camloutputline
\let\;\@camlblankline
\let\\\@camlbackslash
}
\def\endcaml{
\endflushleft
\egroup\noindent
}

View File

@ -81,7 +81,7 @@ let process_line line = function
| Normal ->
if is_prefix "\\begin{caml_" line || is_prefix "\\begin{rawhtml}" line
then (print_string line; Verbatim_like)
else if is_prefix "\\camlexample" line
else if is_prefix "\\begin{camlexample}" line
then (print_endline line; Caml)
else if is_prefix "\\begin{verbatim}" line
then begin
@ -100,7 +100,7 @@ let process_line line = function
end
| Caml ->
print_endline line;
if is_prefix "\\endcamlexample" line then Normal else Caml
if is_prefix "\\end{camlexample}" line then Normal else Caml
| Verbatim (verbatim_end_in, verbatim_end_out) as env ->
if is_prefix verbatim_end_in line
then begin

View File

@ -14,7 +14,7 @@ rule main = parse
"\\begin{syntax}" {
print_string "\\begin{syntax}";
syntax lexbuf }
| "\\begin{verbatim}" | "\\camlexample" as s {
| "\\begin{verbatim}" | "\\begin{camlexample}" as s {
print_string s;
verbatim lexbuf }
| "\\@" {
@ -99,7 +99,7 @@ and indoublequote = parse
indoublequote lexbuf }
and verbatim = parse
"\n\\end{verbatim}"|"\\endcamlexample" as s {
"\n\\end{verbatim}"|"\\end{camlexample}" as s {
print_string s;
main lexbuf }
| _ {

View File

@ -1,46 +1,48 @@
\camlexample{verbatim}
\caml\camlinput\?let start = 0
\?\ldots
\?let mid = succ hidden
\?\ldots
\begin{camlexample}{verbatim}
\begin{caml}
\begin{camlinput}
$\?$let start = 0
$\?$$\ldots$
$\?$let mid = succ hidden
$\?$$\ldots$
\?module E = struct end
\?\ldots
$\?$module E = struct end
$\?$$\ldots$
\?let expr = \ldots
$\?$let expr = $\ldots$
\?let pat = match start with
\? | \ldots | 1 -> succ expr
\? | _ -> succ expr
$\?$let pat = match start with
$\?$ | $\ldots$ | 1 -> succ expr
$\?$ | _ -> succ expr
\?let case = match start with
\? | 0 -> succ pat
\? | \ldots
$\?$let case = match start with
$\?$ | 0 -> succ pat
$\?$ | $\ldots$
\?let annot: \ldots = succ case
$\?$let annot: $\ldots$ = succ case
\?let subexpr = succ annot + (\ldots * 2) - 2
$\?$let subexpr = succ annot + ($\ldots$ * 2) - 2
\?\ldots
$\?$$\ldots$
\?class c2 = object
\? \ldots
\? val y = 1
\? \ldots
\? method n = 3
\? \ldots
\?end
$\?$class c2 = object
$\?$ $\ldots$
$\?$ val y = 1
$\?$ $\ldots$
$\?$ method n = 3
$\?$ $\ldots$
$\?$end
\?type t = \ldots | B \ldots | F
\?type arrow = int -> (\ldots)
\?type record = { a:int; \ldots c:int;
\? \ldots
\? g:int }
\?type polyvar = [\textasciigrave\-A|\ldots |\textasciigrave\-C
\? |\ldots
\? | \textasciigrave\-G ]
\?type exn += \ldots | B \ldots | F
\endcamlinput
\endcaml
\endcamlexample
$\?$type t = $\ldots$ | B $\ldots$ | F
$\?$type arrow = int -> ($\ldots$)
$\?$type record = { a:int; $\ldots$ c:int;
$\?$ $\ldots$
$\?$ g:int }
$\?$type polyvar = [`A|$\ldots$ |`C
$\?$ |$\ldots$
$\?$ | `G ]
$\?$type exn += $\ldots$ | B $\ldots$ | F
\end{camlinput}
\end{caml}
\end{camlexample}

View File

@ -1,21 +1,39 @@
\camlexample{toplevel}
\caml\camlinput\?[@@@warning "+A"];;
\endcamlinput\endcaml
\caml\camlinput\?1 + \<2.\> ;;
\endcamlinput\camlerror\:Error: This expression has type float but an expression was expected of type
\: int
\endcamlerror\endcaml
\caml\camlinput\?let f \<x\> = () ;;
\endcamlinput\camlwarn\:Warning 27: unused variable x.
\:val f : \textquotesingle\-a -> unit = <fun>
\endcamlwarn\endcaml
\endcamlexample
\begin{camlexample}{toplevel}
\begin{caml}
\begin{camlinput}
$\?$[@@@warning "+A"];;
\end{camlinput}
\end{caml}
\begin{caml}
\begin{camlinput}
$\?$1 + <<2.>> ;;
\end{camlinput}
\begin{camlerror}
$\:$Error: This expression has type float but an expression was expected of type
$\:$ int
\end{camlerror}
\end{caml}
\begin{caml}
\begin{camlinput}
$\?$let f <<x>> = () ;;
\end{camlinput}
\begin{camlwarn}
$\:$Warning 27: unused variable x.
$\:$val f : 'a -> unit = <fun>
\end{camlwarn}
\end{caml}
\end{camlexample}
\camlexample{toplevel}
\caml\camlinput\?Format.printf "Hello@.";
\?print_endline "world";;
\endcamlinput\camloutput\:Hello
\:world
\:- : unit = ()
\endcamloutput\endcaml
\endcamlexample
\begin{camlexample}{toplevel}
\begin{caml}
\begin{camlinput}
$\?$Format.printf "Hello@.";
$\?$print_endline "world";;
\end{camlinput}
\begin{camloutput}
$\:$Hello
$\:$world
$\:$- : unit = ()
\end{camloutput}
\end{caml}
\end{camlexample}

View File

@ -19,39 +19,46 @@
open StdLabels
open Str
let camlbegin = "\\caml"
let camlend = "\\endcaml"
let camlin = {|\\?\1|}
let camlout = {|\\:\1|}
let camlbunderline = "\\<"
let camleunderline = "\\>"
let camlprefix = "caml"
let start newline out s args =
Format.fprintf out "%s%s" camlbegin s;
let latex_escape s = String.concat "" ["$"; s; "$"]
let camlin = latex_escape {|\\?|} ^ {|\1|}
let camlout = latex_escape {|\\:|} ^ {|\1|}
let camlbunderline = "<<"
let camleunderline = ">>"
(** Restrict the number of latex environment *)
type env = Env of string
let main = Env "example"
let input_env = Env "input"
let ok_output = Env "output"
let error = Env "error"
let warning = Env "warn"
let phrase_env = Env ""
let start out (Env s) args =
Format.fprintf out "\\begin{%s%s}" camlprefix s;
List.iter (Format.fprintf out "{%s}") args;
if newline then Format.fprintf out "\n"
Format.fprintf out "\n"
let stop newline out s =
Format.fprintf out "%s%s" camlend s;
if newline then Format.fprintf out "\n"
let stop out (Env s) =
Format.fprintf out "\\end{%s%s}" camlprefix s;
Format.fprintf out "\n"
let code_env ?(newline=true) env out s =
let code_env env out s =
let sep = if s.[String.length s - 1] = '\n' then "" else "\n" in
Format.fprintf out "%a%s%s%a"
(fun ppf env -> start false ppf env []) env s sep (stop newline) env
(fun ppf env -> start ppf env [])
env s sep stop env
let main = "example"
type example_mode = Toplevel | Verbatim | Signature
let string_of_mode = function
| Toplevel -> "toplevel"
| Verbatim -> "verbatim"
| Signature -> "signature"
let input_env = "input"
let ok_output ="output"
let error ="error"
let warning ="warn"
let phrase_env = ""
let verbose = ref true
let linelen = ref 72
@ -417,25 +424,23 @@ module Text_transform = struct
let ellipsis start stop = { kind = Ellipsis; start; stop }
let escape_specials s =
let s1 = global_replace ~!"\\\\" "\\\\\\\\" s in
let s2 = global_replace ~!"'" "\\\\textquotesingle\\\\-" s1 in
let s3 = global_replace ~!"`" "\\\\textasciigrave\\\\-" s2 in
s3
s
|> global_replace ~!{|\$|} {|$\textdollar$|}
let rec apply_transform input (pos,underline_stop,out) t =
if pos >= String.length input then pos, underline_stop, out
else match underline_stop with
| Some stop when stop <= t.start ->
let f = escape_specials (String.sub input ~pos ~len:(stop - pos)) in
let out = {|\>|} :: f :: out in
let out = camleunderline :: f :: out in
apply_transform input (stop,None,out) t
| _ ->
let out =
escape_specials (String.sub input ~pos ~len:(t.start - pos))::out in
match t.kind with
| Ellipsis -> t.stop, underline_stop, {|\ldots|} :: out
| Ellipsis -> t.stop, underline_stop, latex_escape {|\ldots|} :: out
| Underline ->
t.start, Some t.stop, {|\<|} :: out
t.start, Some t.stop, camlbunderline :: out
(** Check that all ellipsis are strictly nested inside underline transform
and that otherwise no transform starts before the end of the previous
@ -483,7 +488,7 @@ module Text_transform = struct
| None -> last, ls
| Some stop ->
let f = escape_specials (String.sub s ~pos:last ~len:(stop - last)) in
stop, {|\>|} :: f :: ls in
stop, camleunderline :: f :: ls in
let ls =
let n = String.length s in
if last = n then ls else
@ -614,7 +619,7 @@ let process_file file =
| Toplevel -> true in
let global_expected = try Output.expected @@ matched_group 4 !input
with Not_found -> Output.Ok in
start true tex_fmt main [string_of_mode mode];
start tex_fmt main [string_of_mode mode];
let first = ref true in
let read_phrase () =
let phrase = Buffer.create 256 in
@ -692,16 +697,16 @@ let process_file file =
global_replace ~!{|^\(.\)|} camlout error_msgs
else if omit_answer then ""
else output in
start false tex_fmt phrase_env [];
code_env ~newline:omit_answer input_env tex_fmt phrase;
start tex_fmt phrase_env [];
code_env input_env tex_fmt phrase;
if String.length final_output > 0 then
code_env ~newline:false (Output.env status) tex_fmt final_output;
stop true tex_fmt phrase_env;
code_env (Output.env status) tex_fmt final_output;
stop tex_fmt phrase_env;
flush oc;
first := false;
if implicit_stop then raise End_of_file
done
with End_of_file -> phrase_start:= !phrase_stop; stop true tex_fmt main
with End_of_file -> phrase_start:= !phrase_stop; stop tex_fmt main
end
else if string_match ~!"\\\\begin{caml_eval}[ \t]*$" !input 0
then begin