Isabelle Snippets — Standalone LaTeX for your formal development

Make snippets from LaTeX files:

Copy snippets to clipboard:

Save snippets:

Information

The following command in the terminal makes the proof assistant Isabelle generate LaTeX code for the theories in the current directory:

isabelle build -D . -o document=pdf -o document_output=output
Note that this requires a ROOT file in that directory. Such a file can be generated by isabelle mkroot (but must be adjusted afterwards).

For each theory T.thy, the command generates a LaTeX file output/document/T.tex. This webpage takes such LaTeX files and chops them into pieces. One can either copy/paste the LaTeX of a single theory in the text area to the left or upload multiple files. The results are displayed to the right.

This process makes it possible to include only the desired parts of the theory when writing a paper: that cartouche containing a crucial definition or lines 2-5 of that important proof.

The LaTeX code can also be used when collaborating on sites like Overleaf to easily include Isabelle code in papers with multiple authors.

Required LaTeX

The tool generates a number of \SNIP{name}{body} commands where the names have the following shape:

[Theory:]cmd:name[-no]-line[-cartouche]

To use the snippets you must include the *.sty files from output/document/ in your own LaTeX directory.

Recommended

The following LaTeX code is recommended. In particular, the tool outputs \SNIP and \Cartouche commands that must be defined to use the snippets.

\usepackage{isabelle, isabellesym}
\isabellestyle{it} % optional
\newcommand{\SNIPTEXT}[1]{#1} % remove #1 to ignore text commands
\newcommand{\SNIP}[2]{\expandafter\newcommand\csname snippet--#1\endcsname{#2}}
\input{snips} % assuming the snippets are saved as snips.tex

% \GetSnip{name} gets the snippet defined by `name' or produces a warning that it does not exist.
\newcommand{\GetSnip}[1]{%
    \ifcsname snippet--#1\endcsname%
        \csname snippet--#1\endcsname%
    \else%
        \PackageWarning{snips}{Snippet ``#1'' is undefined.}%
        \emph{Warning: Snippet ``#1'' is undefined.}%
    \fi%
}

% \RawCartouche{name}{line}{n}: content of cartouche `n' on line `line' of snippet `name'
\newcommand{\RawCartouche}[3]{\GetSnip{#1-#2-#3}}

% \Cartouche{name}{line}{n}: enclosed cartouche `n' on line `line' of snippet `name'
\newcommand{\Cartouche}[3]{%
    {\isacartoucheopen}%
    \RawCartouche{#1}{#2}{#3}%
    {\isacartoucheclose}%
}
The LaTeX error "Command \guilsinglright unavailable in encoding OT1." can be fixed by also adding \usepackage[T1]{fontenc}.

As desired

The following LaTeX code can be useful:

% \Snippet{name}: the full snippet `name'
\newcommand{\Snippet}[1]{{%
  \newcount\i
  \i=0
  \loop
    \GetSnip{#1-\the\i}%
    \advance \i 1
  \ifcsname snippet--#1-\the\i\endcsname
  \repeat
}}

% \SnippetPart{n}{m}{name}: the snippet `name' from line `n' to line `m' inclusive
\newcommand{\SnippetPart}[3]{{%
  \newcount\i
  \i=#1
  \loop
    \ifnum \i=#2
      \renewcommand{\isanewline}{}%
    \fi
    \GetSnip{#3-\the\i}%
    \advance \i 1
    \ifnum \i>#2 {}
    \else \repeat
}}
        

In some cases

The following code can be necessary to make the snippets work with some document classes.

\def\isadelimtheory{}\def\endisadelimtheory{}
\def\isatagtheory{}\def\endisatagtheory{}
\def\isadelimML{}\def\endisadelimML{}
\def\isadelimdocument{}\def\endisadelimdocument{}
\def\isatagML{}\def\endisatagML{}
\def\isatagdocument{}\def\endisatagdocument{}
\def\isafoldML{}
\def\isadelimproof{}\def\endisadelimproof{}
\def\isatagproof{}\def\endisatagproof{}
\def\isafoldproof{}
    

Example

Take the following Isabelle theory as example:

theory Scratch imports Main begin

lemma myConjI: ‹P ⟹ Q ⟹ P ∧ Q›
  ..

end
        
To include the whole lemma with proof in your paper you can use:
\begin{isabelle}
  \Snippet{lemma:myConjI}
\end{isabelle}
        
To include just the first line of the lemma:
\begin{isabelle}
  \SnippetPart{0}{0}{lemma:myConjI}
\end{isabelle}
        
Or to include just the contents of the cartouche (P ⟹ Q ⟹ P ∧ Q):
\begin{isabelle}
  \RawCartouche{lemma:myConjI}{0}{0}
\end{isabelle}
        

Disclaimer

This tool was built for Isabelle 2022 and may not support the LaTeX output of other versions. The processing of the LaTeX is ad hoc and may result in unexpected behaviour, especially regarding the names of snippets.

The tool reduces duplication, to save space in the final output, by trying to replace the cartouches on each line with a \Cartouche command that references the \SNIP for that cartouche. However, it can only do so for cartouches without newlines: those that contain newlines are left in place.

This means that every cartouche is not necessarily inserted by the \Cartouche macro. In particular, to modify the delimiters around cartouches that are inserted via \Snippet and \SnippetPart it is safest to use code like \renewcommand{\isacartoucheopen}{...}. Depending on the Isabelle code, it may not be enough to modify the definition of \Cartouche.

Limitations

The tool assumes that the Isabelle theories use the ‹› cartouche delimiters, not the older double quotes. See Section 2.7 of the Isabelle System Manual for how to update your theory file accordingly. Alternatively, to update a single theory using Isabelle/jEdit, search for "([^"]+)" and replace it with ‹$1›. Some manual cleanup is likely necessary afterwards.

The source code is available on GitHub: astahfrom/cartouches.

Author

Asta Halkjær From. Github: github.com/astahfrom/