Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add support for PDF output via Pandoc #28

Draft
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

paulapatience
Copy link
Contributor

@paulapatience paulapatience commented Jun 26, 2023

This is a PR aiming to implement #26.

This is a draft for now, but generating PDF output is already possible as follows:

(uiop:with-output-file (stream "mgl-pax.pdf" :if-exists :supersede)
  (pax:document mgl-pax::@pax-manual :stream stream :format :pandoc-pdf))

(I thought I would need to make an octet stream, but I haven't run into any problems yet with the above.)

Though the PR is incomplete, it has brought some issues to light, which I would like to discuss.

First, I can see four ways to implement the PDF support:

  1. Sprinkle (eq *format* :pandoc-pdf) tests everywhere so that the intermediate Markdown output need not be modified before passing it to Pandoc.

  2. Generate Markdown output in the usual manner and post-process it via POST-PROCESS-PARSE-TREE (tentatively renamed from POST-PROCESS-FOR-W3M in this PR) before passing it to Pandoc. This would require some kind of *MARKDOWN-SUBFORMAT* (or *MARKDOWN-SUPERFORMAT*, to be more proper), similar to *HTML-SUBFORMAT*, so that within CALL-WITH-FORMAT we can bind *FORMAT* to :MARKDOWN, but still know that we want to generate PDF via Pandoc within DOCUMENT.

  3. Same as 2, but use Pandoc filters rather than modifying the Markdown parse tree from Lisp.

  4. A combination of 1 and either 2 or 3. A combination of 1 and 2 is what is currently done in this PR (there is no *MARKDOWN-SUPERFORMAT* yet, so it relies on non–*FORMAT*-specific behaviors). I haven't introduced my Lua filter yet, because I wanted to see how possible and easy it would be without it.

I think it would be easier to keep track of Pandoc PDF–specific requirements in a separate filter (be it Lisp or Lua), and thus I am partial to options 2 and 3; of course, this may just be because I am less familiar with the codebase. And between options 2 and 3, I am partial to option 3, first because the Lua filter could serve as an example to users of MGL-PAX who might want to further adjust the output, and second because I am lazy and the filter already exists.

In fact, another reason to prefer option 3 is that it basically offers users a hook to transform the MGL-PAX output in arbitrary ways, which is impossible (as far as I know) with the other formats. Perhaps MGL-PAX should provide a user hook to transform the parse tree before the output is generated. One possible problem with this is that if the intermediate Markdown format changes from one version to another, the filters or hooks may become incompatible. In the case of the Lua filter bundled with MGL-PAX (i.e., if we go for option 3), this isn't an issue since it can be updated at the same time as the intermediate Markdown representation.

Which of the four methods would you prefer?

Finally, some peculiarities of the MGL-PAX documentation cause issues in the PDF output of the PAX manual:

  1. The most problematic issue is that all MGL-PAX docstrings are indented by two spaces, except the first line, which causes Pandoc to misinterpret things like code blocks and I think some lists (e.g., the lists with ASDF system information). It's probably possible to preprocess the docstrings to deal with this, but since this is an issue specific to MGL-PAX docstrings, I don't think it should be handled by MGL-PAX itself. (The indented lines are also visible when browsing the docstrings from within Lisp.)

  2. The subheadings sometimes jump from ## to #####. On second thought, this is not such a big issue. It seemed weird to me to skip a few heading levels, but the PDF output looks fine. Note that the [in package ...] 6th level headings I've changed to an \hbox{} containing the same text but in sans serif rather than bold in my Lua filter, because I found it looked nicer. This PR doesn't contain this change yet, but if you don't agree with changing it to sans serif upon seeing it, perhaps it should be configurable in some variable.

Let me know what you think.

@melisgl
Copy link
Owner

melisgl commented Jun 26, 2023

I tried to run the example but got this:

Error producing PDF.
! Missing \endcsname inserted.
<to be read again> 
                   \T1\textbraceleft 
l.23 ...1}{1}{Indentation}{subsubsection.0.0.1}{}}

Regarding exposing the parse tree to the user, I basically agree with the points you brought up. I thought about it previously and came to the conclusion that it would be too much of a maintenance drag. Docstrings are markdown strings so that's part of the interface already. But exposing a particular markdown parser's internals would make it more difficult to move away from 3bmd if need be. Transforms bundled with PAX are, either Lua or Lisp, are fine.

As to Lua, Lisp or a combination, it depends. It's good have tightly coupled pieces of code without a good interface in between them be close (e.g. in the same function). The changes in the draft change look good in that regard. If the time comes that the multitude of formats makes this unwieldy, then there will be motivation to come up with a stable interface in between. There is none currently, and maybe with Pandoc additional formats would not require code changes.

As to *format*, and I cannot quite see why *markdown-{sub/super}format* would be necessary. Your draft looks fine without it.

Re docstring indentation, see the comments in the review.

Re subheadings, in some places I probably still use explicit '####' headings in function docstrings, although I've trying to move away from that.

src/document/document.lisp Outdated Show resolved Hide resolved
src/document/document.lisp Outdated Show resolved Hide resolved
src/document/document.lisp Outdated Show resolved Hide resolved
(format stream "---~%")
(format stream "title: ~{~A~}~%" (pt-get (pop parse-tree) :contents))
(format stream "~A~&---~%" *pandoc-metadata-block*)
(pop parse-tree) ; Skip the link to the title
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For the final version, check that this skips what it thinks it does.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've done some preliminary checking for this, let me know if it's enough.

src/document/document.lisp Outdated Show resolved Hide resolved
src/document/document.lisp Show resolved Hide resolved
src/document/document.lisp Outdated Show resolved Hide resolved
@paulapatience
Copy link
Contributor Author

paulapatience commented Jun 26, 2023

I tried to run the example but got this:

Error producing PDF.
! Missing \endcsname inserted.
<to be read again> 
                   \T1\textbraceleft 
l.23 ...1}{1}{Indentation}{subsubsection.0.0.1}{}}

What version of Pandoc did you use? I imagine it's one of the latest (i.e., post-3.0.0); I've been using 2.19.2 since that's the latest version provided with Guix, so that might be the reason for the error. I guess I'll have to manually update.

Regarding exposing the parse tree to the user, I basically agree with the points you brought up. I thought about it previously and came to the conclusion that it would be too much of a maintenance drag. Docstrings are markdown strings so that's part of the interface already. But exposing a particular markdown parser's internals would make it more difficult to move away from 3bmd if need be. Transforms bundled with PAX are, either Lua or Lisp, are fine.

As to Lua, Lisp or a combination, it depends. It's good have tightly coupled pieces of code without a good interface in between them be close (e.g. in the same function). The changes in the draft change look good in that regard. If the time comes that the multitude of formats makes this unwieldy, then there will be motivation to come up with a stable interface in between. There is none currently, and maybe with Pandoc additional formats would not require code changes.

Ok, this makes sense.

As to *format*, and I cannot quite see why *markdown-{sub/super}format* would be necessary. Your draft looks fine without it.

I was thinking of parts within the code which explicitly check for the :MARKDOWN format, for example in PAGE-SPEC-TO-PAGE. But it seems to be the only place which does that, so perhaps it's fine. I haven't investigated what would happen when providing :PAGES to DOCUMENT when generating PDF, but I can't think of a reason it would apply to it (headers and footers can be specified in the metadata block, anyway).

Re docstring indentation, see the comments in the review.

Re subheadings, in some places I probably still use explicit '####' headings in function docstrings, although I've trying to move away from that.

Thanks for the review, I'll address all your comments in my next update to the PR.

@melisgl
Copy link
Owner

melisgl commented Jun 26, 2023

$ pandoc --version
pandoc 2.17.1.1
Compiled with pandoc-types 1.22.2.1, texmath 0.12.4, skylighting 0.12.3.1,
citeproc 0.6.0.1, ipynb 0.2

@paulapatience
Copy link
Contributor Author

paulapatience commented Jun 26, 2023

$ pandoc --version
pandoc 2.17.1.1
Compiled with pandoc-types 1.22.2.1, texmath 0.12.4, skylighting 0.12.3.1,
citeproc 0.6.0.1, ipynb 0.2

I just tried with that version of Pandoc and the manual compiles fine for me. Can you add the --verbose flag and attach the log?

(let ((pax::*pandoc-options* '("--verbose")))
  (uiop:with-output-file (stream "mgl-pax.pdf" :if-exists :supersede)
    (pax:document mgl-pax::@pax-manual :stream stream :format :pandoc-pdf)))

@melisgl
Copy link
Owner

melisgl commented Jun 26, 2023

Here is a shorter one. If I try it on pax::@markdown-indentation, I can see there is some issue with escaping {}, too.

(let ((pax::*pandoc-options* '("--verbose")))
  (uiop:with-output-file (stream "mgl-pax.pdf" :if-exists :supersede)
    (pax:document mgl-pax::@links :stream stream :format :pandoc-pdf)))

[makePDF] temp dir:
/tmp/tex2pdf.-9503eca1a704e40d
[makePDF] Command line:
pdflatex "-halt-on-error" "-interaction" "nonstopmode" "-output-directory" "/tmp/tex2pdf.-9503eca1a704e40d" "/tmp/tex2pdf.-9503eca1a704e40d/input.tex"

[makePDF] Relevant environment variables:
("TEXINPUTS","/tmp/tex2pdf.-9503eca1a704e40d:")
("TEXMFOUTPUT","/tmp/tex2pdf.-9503eca1a704e40d")
("SHELL","/bin/bash")
("PWD","/home/melisgl/own/mgl-pax/xref")
("HOME","/home/melisgl")
("LANG","C")
("PATH","/home/melisgl/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin")

[makePDF] Source:
% Options for packages loaded elsewhere
\PassOptionsToPackage{unicode}{hyperref}
\PassOptionsToPackage{hyphens}{url}
%
\documentclass[
]{article}
\usepackage{amsmath,amssymb}
\usepackage{lmodern}
\usepackage{iftex}
\ifPDFTeX
  \usepackage[T1]{fontenc}
  \usepackage[utf8]{inputenc}
  \usepackage{textcomp} % provide euro and other symbols
\else % if luatex or xetex
  \usepackage{unicode-math}
  \defaultfontfeatures{Scale=MatchLowercase}
  \defaultfontfeatures[\rmfamily]{Ligatures=TeX,Scale=1}
\fi
% Use upquote if available, for straight quotes in verbatim environments
\IfFileExists{upquote.sty}{\usepackage{upquote}}{}
\IfFileExists{microtype.sty}{% use microtype if available
  \usepackage[]{microtype}
  \UseMicrotypeSet[protrusion]{basicmath} % disable protrusion for tt fonts
}{}
\makeatletter
\@ifundefined{KOMAClassName}{% if non-KOMA class
  \IfFileExists{parskip.sty}{%
    \usepackage{parskip}
  }{% else
    \setlength{\parindent}{0pt}
    \setlength{\parskip}{6pt plus 2pt minus 1pt}}
}{% if KOMA class
  \KOMAoptions{parskip=half}}
\makeatother
\usepackage{xcolor}
\IfFileExists{xurl.sty}{\usepackage{xurl}}{} % add URL line breaks if available
\IfFileExists{bookmark.sty}{\usepackage{bookmark}}{\usepackage{hyperref}}
\hypersetup{
  pdftitle={Links and Systems},
  hidelinks,
  pdfcreator={LaTeX via pandoc}}
\urlstyle{same} % disable monospaced font for URLs
\setlength{\emergencystretch}{3em} % prevent overfull lines
\providecommand{\tightlist}{%
  \setlength{\itemsep}{0pt}\setlength{\parskip}{0pt}}
\setcounter{secnumdepth}{3}
\ifLuaTeX
  \usepackage{selnolig}  % disable illegal ligatures
\fi

\title{Links and Systems}
\author{}
\date{}

\begin{document}
\maketitle

{
\setcounter{tocdepth}{3}
\tableofcontents
}
\hypertarget{in-package-mgl-pax-with-nicknames-pax}{%
\subparagraph{{[}in package MGL-PAX with nicknames
PAX{]}}\label{in-package-mgl-pax-with-nicknames-pax}}

Here is the \href{https://github.com/melisgl/mgl-pax}{official
repository} and the
\href{http://melisgl.github.io/mgl-pax-world/mgl-pax-manual.html}{HTML
documentation} for the latest version.

\hypertarget{the-mgl-pax-asdf-system}{%
\subsection{The mgl-pax ASDF System}\label{the-mgl-pax-asdf-system}}

\label\{x-28-22mgl-pax-22-20ASDF-2FSYSTEM-3ASYSTEM-29\} - Version: 0.2.4
- Description: Exploratory programming tool and documentation generator.
- Long Description: The set of dependencies of the MGL-PAX system is
kept light, and its heavier dependencies are autoloaded via ASDF when
the relevant functionality is accessed. See the
\texttt{MGL-PAX/NAVIGATE}, \texttt{MGL-PAX/DOCUMENT},
\texttt{MGL-PAX/TRANSCRIBE} and \texttt{MGL-PAX/FULL} systems. To keep
deployed code small, client systems should declare an ASDF dependency on
this system, never on the others, which are intended for autoloading and
interactive use. - Licence: MIT, see COPYING. - Author: Gábor Melis -
Mailto: \href{mailto:mega@retes.hu}{\nolinkurl{mega@retes.hu}} -
Homepage: \url{http://melisgl.github.io/mgl-pax} - Bug tracker:
\url{https://github.com/melisgl/mgl-pax/issues} - Source control:
\href{https://github.com/melisgl/mgl-pax.git}{GIT}

\hypertarget{the-mgl-paxfull-asdf-system}{%
\subsection{The mgl-pax/full ASDF
System}\label{the-mgl-paxfull-asdf-system}}

\label\{x-28-22mgl-pax-2Ffull-22-20ASDF-2FSYSTEM-3ASYSTEM-29\} -
Description: MGL-PAX with most features preloaded. - Licence: MIT, see
COPYING. - Author: Gábor Melis - Mailto:
\href{mailto:mega@retes.hu}{\nolinkurl{mega@retes.hu}}

\end{document}

[makePDF] Run #1
This is pdfTeX, Version 3.141592653-2.6-1.40.24 (TeX Live 2022/Debian) (preloaded format=pdflatex)
 restricted \write18 enabled.
entering extended mode
(/tmp/tex2pdf.-9503eca1a704e40d/input.tex
LaTeX2e <2022-11-01> patch level 1
L3 programming layer <2023-01-16>
(/usr/share/texlive/texmf-dist/tex/latex/base/article.cls
Document Class: article 2022/07/02 v1.4n Standard LaTeX document class
(/usr/share/texlive/texmf-dist/tex/latex/base/size10.clo))
(/usr/share/texlive/texmf-dist/tex/latex/amsmath/amsmath.sty
For additional information on amsmath, use the `?' option.
(/usr/share/texlive/texmf-dist/tex/latex/amsmath/amstext.sty
(/usr/share/texlive/texmf-dist/tex/latex/amsmath/amsgen.sty))
(/usr/share/texlive/texmf-dist/tex/latex/amsmath/amsbsy.sty)
(/usr/share/texlive/texmf-dist/tex/latex/amsmath/amsopn.sty))
(/usr/share/texlive/texmf-dist/tex/latex/amsfonts/amssymb.sty
(/usr/share/texlive/texmf-dist/tex/latex/amsfonts/amsfonts.sty))
(/usr/share/texmf/tex/latex/lm/lmodern.sty)
(/usr/share/texlive/texmf-dist/tex/generic/iftex/iftex.sty)
(/usr/share/texlive/texmf-dist/tex/latex/base/fontenc.sty
(/usr/share/texmf/tex/latex/lm/t1lmr.fd))
(/usr/share/texlive/texmf-dist/tex/latex/base/inputenc.sty)
(/usr/share/texlive/texmf-dist/tex/latex/base/textcomp.sty)
(/usr/share/texlive/texmf-dist/tex/latex/upquote/upquote.sty)
(/usr/share/texlive/texmf-dist/tex/latex/microtype/microtype.sty
(/usr/share/texlive/texmf-dist/tex/latex/graphics/keyval.sty)
(/usr/share/texlive/texmf-dist/tex/latex/etoolbox/etoolbox.sty)
(/usr/share/texlive/texmf-dist/tex/latex/microtype/microtype-pdftex.def)
(/usr/share/texlive/texmf-dist/tex/latex/microtype/microtype.cfg))
(/usr/share/texlive/texmf-dist/tex/latex/parskip/parskip.sty
(/usr/share/texlive/texmf-dist/tex/latex/kvoptions/kvoptions.sty
(/usr/share/texlive/texmf-dist/tex/generic/ltxcmds/ltxcmds.sty)
(/usr/share/texlive/texmf-dist/tex/latex/kvsetkeys/kvsetkeys.sty)))
(/usr/share/texlive/texmf-dist/tex/latex/xcolor/xcolor.sty
(/usr/share/texlive/texmf-dist/tex/latex/graphics-cfg/color.cfg)
(/usr/share/texlive/texmf-dist/tex/latex/graphics-def/pdftex.def)
(/usr/share/texlive/texmf-dist/tex/latex/graphics/mathcolor.ltx))
(/usr/share/texlive/texmf-dist/tex/latex/xurl/xurl.sty
(/usr/share/texlive/texmf-dist/tex/latex/url/url.sty))
(/usr/share/texlive/texmf-dist/tex/latex/bookmark/bookmark.sty
(/usr/share/texlive/texmf-dist/tex/latex/hyperref/hyperref.sty
(/usr/share/texlive/texmf-dist/tex/generic/pdftexcmds/pdftexcmds.sty
(/usr/share/texlive/texmf-dist/tex/generic/infwarerr/infwarerr.sty))
(/usr/share/texlive/texmf-dist/tex/generic/kvdefinekeys/kvdefinekeys.sty)
(/usr/share/texlive/texmf-dist/tex/generic/pdfescape/pdfescape.sty)
(/usr/share/texlive/texmf-dist/tex/latex/hycolor/hycolor.sty)
(/usr/share/texlive/texmf-dist/tex/latex/letltxmacro/letltxmacro.sty)
(/usr/share/texlive/texmf-dist/tex/latex/auxhook/auxhook.sty)
(/usr/share/texlive/texmf-dist/tex/latex/hyperref/nameref.sty
(/usr/share/texlive/texmf-dist/tex/latex/refcount/refcount.sty)
(/usr/share/texlive/texmf-dist/tex/generic/gettitlestring/gettitlestring.sty))
(/usr/share/texlive/texmf-dist/tex/latex/hyperref/pd1enc.def)
(/usr/share/texlive/texmf-dist/tex/generic/intcalc/intcalc.sty)
(/usr/share/texlive/texmf-dist/tex/generic/etexcmds/etexcmds.sty)
(/usr/share/texlive/texmf-dist/tex/latex/hyperref/puenc.def)
(/usr/share/texlive/texmf-dist/tex/generic/bitset/bitset.sty
(/usr/share/texlive/texmf-dist/tex/generic/bigintcalc/bigintcalc.sty))
(/usr/share/texlive/texmf-dist/tex/latex/base/atbegshi-ltx.sty))
(/usr/share/texlive/texmf-dist/tex/latex/hyperref/hpdftex.def
(/usr/share/texlive/texmf-dist/tex/latex/base/atveryend-ltx.sty)
(/usr/share/texlive/texmf-dist/tex/latex/rerunfilecheck/rerunfilecheck.sty
(/usr/share/texlive/texmf-dist/tex/generic/uniquecounter/uniquecounter.sty)))
(/usr/share/texlive/texmf-dist/tex/latex/bookmark/bkm-pdftex.def))
(/usr/share/texlive/texmf-dist/tex/latex/l3backend/l3backend-pdftex.def)
No file input.aux.
(/usr/share/texlive/texmf-dist/tex/latex/microtype/mt-cmr.cfg)
(/usr/share/texlive/texmf-dist/tex/context/base/mkii/supp-pdf.mkii
[Loading MPS to PDF converter (version 2006.09.02).]
) (/usr/share/texmf/tex/latex/lm/ot1lmr.fd)
(/usr/share/texmf/tex/latex/lm/omllmm.fd)
(/usr/share/texmf/tex/latex/lm/omslmsy.fd)
(/usr/share/texmf/tex/latex/lm/omxlmex.fd)
(/usr/share/texlive/texmf-dist/tex/latex/amsfonts/umsa.fd)
(/usr/share/texlive/texmf-dist/tex/latex/microtype/mt-msa.cfg)
(/usr/share/texlive/texmf-dist/tex/latex/amsfonts/umsb.fd)
(/usr/share/texlive/texmf-dist/tex/latex/microtype/mt-msb.cfg)
No file input.toc.
(/usr/share/texmf/tex/latex/lm/t1lmtt.fd) [1{/home/melisgl/.texlive2022/texmf-v
ar/fonts/map/pdftex/updmap/pdftex.map}]
(/tmp/tex2pdf.-9503eca1a704e40d/input.aux
! Missing \endcsname inserted.
<to be read again> 
                   \T1\textbraceleft 
l.23 ...he mgl-pax ASDF System}{subsection.0.1}{}}
                                                  
!  ==> Fatal error occurred, no output PDF file produced!
Transcript written on /tmp/tex2pdf.-9503eca1a704e40d/input.log.

[makePDF] Run #2
This is pdfTeX, Version 3.141592653-2.6-1.40.24 (TeX Live 2022/Debian) (preloaded format=pdflatex)
 restricted \write18 enabled.
entering extended mode
(/tmp/tex2pdf.-9503eca1a704e40d/input.tex
LaTeX2e <2022-11-01> patch level 1
L3 programming layer <2023-01-16>
(/usr/share/texlive/texmf-dist/tex/latex/base/article.cls
Document Class: article 2022/07/02 v1.4n Standard LaTeX document class
(/usr/share/texlive/texmf-dist/tex/latex/base/size10.clo))
(/usr/share/texlive/texmf-dist/tex/latex/amsmath/amsmath.sty
For additional information on amsmath, use the `?' option.
(/usr/share/texlive/texmf-dist/tex/latex/amsmath/amstext.sty
(/usr/share/texlive/texmf-dist/tex/latex/amsmath/amsgen.sty))
(/usr/share/texlive/texmf-dist/tex/latex/amsmath/amsbsy.sty)
(/usr/share/texlive/texmf-dist/tex/latex/amsmath/amsopn.sty))
(/usr/share/texlive/texmf-dist/tex/latex/amsfonts/amssymb.sty
(/usr/share/texlive/texmf-dist/tex/latex/amsfonts/amsfonts.sty))
(/usr/share/texmf/tex/latex/lm/lmodern.sty)
(/usr/share/texlive/texmf-dist/tex/generic/iftex/iftex.sty)
(/usr/share/texlive/texmf-dist/tex/latex/base/fontenc.sty
(/usr/share/texmf/tex/latex/lm/t1lmr.fd))
(/usr/share/texlive/texmf-dist/tex/latex/base/inputenc.sty)
(/usr/share/texlive/texmf-dist/tex/latex/base/textcomp.sty)
(/usr/share/texlive/texmf-dist/tex/latex/upquote/upquote.sty)
(/usr/share/texlive/texmf-dist/tex/latex/microtype/microtype.sty
(/usr/share/texlive/texmf-dist/tex/latex/graphics/keyval.sty)
(/usr/share/texlive/texmf-dist/tex/latex/etoolbox/etoolbox.sty)
(/usr/share/texlive/texmf-dist/tex/latex/microtype/microtype-pdftex.def)
(/usr/share/texlive/texmf-dist/tex/latex/microtype/microtype.cfg))
(/usr/share/texlive/texmf-dist/tex/latex/parskip/parskip.sty
(/usr/share/texlive/texmf-dist/tex/latex/kvoptions/kvoptions.sty
(/usr/share/texlive/texmf-dist/tex/generic/ltxcmds/ltxcmds.sty)
(/usr/share/texlive/texmf-dist/tex/latex/kvsetkeys/kvsetkeys.sty)))
(/usr/share/texlive/texmf-dist/tex/latex/xcolor/xcolor.sty
(/usr/share/texlive/texmf-dist/tex/latex/graphics-cfg/color.cfg)
(/usr/share/texlive/texmf-dist/tex/latex/graphics-def/pdftex.def)
(/usr/share/texlive/texmf-dist/tex/latex/graphics/mathcolor.ltx))
(/usr/share/texlive/texmf-dist/tex/latex/xurl/xurl.sty
(/usr/share/texlive/texmf-dist/tex/latex/url/url.sty))
(/usr/share/texlive/texmf-dist/tex/latex/bookmark/bookmark.sty
(/usr/share/texlive/texmf-dist/tex/latex/hyperref/hyperref.sty
(/usr/share/texlive/texmf-dist/tex/generic/pdftexcmds/pdftexcmds.sty
(/usr/share/texlive/texmf-dist/tex/generic/infwarerr/infwarerr.sty))
(/usr/share/texlive/texmf-dist/tex/generic/kvdefinekeys/kvdefinekeys.sty)
(/usr/share/texlive/texmf-dist/tex/generic/pdfescape/pdfescape.sty)
(/usr/share/texlive/texmf-dist/tex/latex/hycolor/hycolor.sty)
(/usr/share/texlive/texmf-dist/tex/latex/letltxmacro/letltxmacro.sty)
(/usr/share/texlive/texmf-dist/tex/latex/auxhook/auxhook.sty)
(/usr/share/texlive/texmf-dist/tex/latex/hyperref/nameref.sty
(/usr/share/texlive/texmf-dist/tex/latex/refcount/refcount.sty)
(/usr/share/texlive/texmf-dist/tex/generic/gettitlestring/gettitlestring.sty))
(/usr/share/texlive/texmf-dist/tex/latex/hyperref/pd1enc.def)
(/usr/share/texlive/texmf-dist/tex/generic/intcalc/intcalc.sty)
(/usr/share/texlive/texmf-dist/tex/generic/etexcmds/etexcmds.sty)
(/usr/share/texlive/texmf-dist/tex/latex/hyperref/puenc.def)
(/usr/share/texlive/texmf-dist/tex/generic/bitset/bitset.sty
(/usr/share/texlive/texmf-dist/tex/generic/bigintcalc/bigintcalc.sty))
(/usr/share/texlive/texmf-dist/tex/latex/base/atbegshi-ltx.sty))
(/usr/share/texlive/texmf-dist/tex/latex/hyperref/hpdftex.def
(/usr/share/texlive/texmf-dist/tex/latex/base/atveryend-ltx.sty)
(/usr/share/texlive/texmf-dist/tex/latex/rerunfilecheck/rerunfilecheck.sty
(/usr/share/texlive/texmf-dist/tex/generic/uniquecounter/uniquecounter.sty)))
(/usr/share/texlive/texmf-dist/tex/latex/bookmark/bkm-pdftex.def))
(/usr/share/texlive/texmf-dist/tex/latex/l3backend/l3backend-pdftex.def)
(/tmp/tex2pdf.-9503eca1a704e40d/input.aux
! Missing \endcsname inserted.
<to be read again> 
                   \T1\textbraceleft 
l.23 ...he mgl-pax ASDF System}{subsection.0.1}{}}
                                                  
!  ==> Fatal error occurred, no output PDF file produced!
Transcript written on /tmp/tex2pdf.-9503eca1a704e40d/input.log.

[makePDF] Run #3
This is pdfTeX, Version 3.141592653-2.6-1.40.24 (TeX Live 2022/Debian) (preloaded format=pdflatex)
 restricted \write18 enabled.
entering extended mode
(/tmp/tex2pdf.-9503eca1a704e40d/input.tex
LaTeX2e <2022-11-01> patch level 1
L3 programming layer <2023-01-16>
(/usr/share/texlive/texmf-dist/tex/latex/base/article.cls
Document Class: article 2022/07/02 v1.4n Standard LaTeX document class
(/usr/share/texlive/texmf-dist/tex/latex/base/size10.clo))
(/usr/share/texlive/texmf-dist/tex/latex/amsmath/amsmath.sty
For additional information on amsmath, use the `?' option.
(/usr/share/texlive/texmf-dist/tex/latex/amsmath/amstext.sty
(/usr/share/texlive/texmf-dist/tex/latex/amsmath/amsgen.sty))
(/usr/share/texlive/texmf-dist/tex/latex/amsmath/amsbsy.sty)
(/usr/share/texlive/texmf-dist/tex/latex/amsmath/amsopn.sty))
(/usr/share/texlive/texmf-dist/tex/latex/amsfonts/amssymb.sty
(/usr/share/texlive/texmf-dist/tex/latex/amsfonts/amsfonts.sty))
(/usr/share/texmf/tex/latex/lm/lmodern.sty)
(/usr/share/texlive/texmf-dist/tex/generic/iftex/iftex.sty)
(/usr/share/texlive/texmf-dist/tex/latex/base/fontenc.sty
(/usr/share/texmf/tex/latex/lm/t1lmr.fd))
(/usr/share/texlive/texmf-dist/tex/latex/base/inputenc.sty)
(/usr/share/texlive/texmf-dist/tex/latex/base/textcomp.sty)
(/usr/share/texlive/texmf-dist/tex/latex/upquote/upquote.sty)
(/usr/share/texlive/texmf-dist/tex/latex/microtype/microtype.sty
(/usr/share/texlive/texmf-dist/tex/latex/graphics/keyval.sty)
(/usr/share/texlive/texmf-dist/tex/latex/etoolbox/etoolbox.sty)
(/usr/share/texlive/texmf-dist/tex/latex/microtype/microtype-pdftex.def)
(/usr/share/texlive/texmf-dist/tex/latex/microtype/microtype.cfg))
(/usr/share/texlive/texmf-dist/tex/latex/parskip/parskip.sty
(/usr/share/texlive/texmf-dist/tex/latex/kvoptions/kvoptions.sty
(/usr/share/texlive/texmf-dist/tex/generic/ltxcmds/ltxcmds.sty)
(/usr/share/texlive/texmf-dist/tex/latex/kvsetkeys/kvsetkeys.sty)))
(/usr/share/texlive/texmf-dist/tex/latex/xcolor/xcolor.sty
(/usr/share/texlive/texmf-dist/tex/latex/graphics-cfg/color.cfg)
(/usr/share/texlive/texmf-dist/tex/latex/graphics-def/pdftex.def)
(/usr/share/texlive/texmf-dist/tex/latex/graphics/mathcolor.ltx))
(/usr/share/texlive/texmf-dist/tex/latex/xurl/xurl.sty
(/usr/share/texlive/texmf-dist/tex/latex/url/url.sty))
(/usr/share/texlive/texmf-dist/tex/latex/bookmark/bookmark.sty
(/usr/share/texlive/texmf-dist/tex/latex/hyperref/hyperref.sty
(/usr/share/texlive/texmf-dist/tex/generic/pdftexcmds/pdftexcmds.sty
(/usr/share/texlive/texmf-dist/tex/generic/infwarerr/infwarerr.sty))
(/usr/share/texlive/texmf-dist/tex/generic/kvdefinekeys/kvdefinekeys.sty)
(/usr/share/texlive/texmf-dist/tex/generic/pdfescape/pdfescape.sty)
(/usr/share/texlive/texmf-dist/tex/latex/hycolor/hycolor.sty)
(/usr/share/texlive/texmf-dist/tex/latex/letltxmacro/letltxmacro.sty)
(/usr/share/texlive/texmf-dist/tex/latex/auxhook/auxhook.sty)
(/usr/share/texlive/texmf-dist/tex/latex/hyperref/nameref.sty
(/usr/share/texlive/texmf-dist/tex/latex/refcount/refcount.sty)
(/usr/share/texlive/texmf-dist/tex/generic/gettitlestring/gettitlestring.sty))
(/usr/share/texlive/texmf-dist/tex/latex/hyperref/pd1enc.def)
(/usr/share/texlive/texmf-dist/tex/generic/intcalc/intcalc.sty)
(/usr/share/texlive/texmf-dist/tex/generic/etexcmds/etexcmds.sty)
(/usr/share/texlive/texmf-dist/tex/latex/hyperref/puenc.def)
(/usr/share/texlive/texmf-dist/tex/generic/bitset/bitset.sty
(/usr/share/texlive/texmf-dist/tex/generic/bigintcalc/bigintcalc.sty))
(/usr/share/texlive/texmf-dist/tex/latex/base/atbegshi-ltx.sty))
(/usr/share/texlive/texmf-dist/tex/latex/hyperref/hpdftex.def
(/usr/share/texlive/texmf-dist/tex/latex/base/atveryend-ltx.sty)
(/usr/share/texlive/texmf-dist/tex/latex/rerunfilecheck/rerunfilecheck.sty
(/usr/share/texlive/texmf-dist/tex/generic/uniquecounter/uniquecounter.sty)))
(/usr/share/texlive/texmf-dist/tex/latex/bookmark/bkm-pdftex.def))
(/usr/share/texlive/texmf-dist/tex/latex/l3backend/l3backend-pdftex.def)
(/tmp/tex2pdf.-9503eca1a704e40d/input.aux
! Missing \endcsname inserted.
<to be read again> 
                   \T1\textbraceleft 
l.23 ...he mgl-pax ASDF System}{subsection.0.1}{}}
                                                  
!  ==> Fatal error occurred, no output PDF file produced!
Transcript written on /tmp/tex2pdf.-9503eca1a704e40d/input.log.

Error producing PDF.
! Missing \endcsname inserted.
<to be read again> 
                   \T1\textbraceleft 
l.23 ...he mgl-pax ASDF System}{subsection.0.1}{}}

@paulapatience
Copy link
Contributor Author

You must have all the required LaTeX packages installed, because otherwise I think the compilation would fail before the error you encounter.

Can you try with the --pdf-engine=lualatex option? The mention of T1 in the error makes me wonder if it's an encoding error.

@melisgl
Copy link
Owner

melisgl commented Jun 26, 2023

I can compile the generated tex file latexmk if I replace

\label\{x-28-22mgl-pax-22-20ASDF-2FSYSTEM-3ASYSTEM-29\}

with

\label{x-28-22mgl-pax-22-20ASDF-2FSYSTEM-3ASYSTEM-29}

at multiple locations.

@paulapatience
Copy link
Contributor Author

paulapatience commented Jul 9, 2023

I've made some progress. The \label{} compilation issue should be fixed; hopefully you'll be able to compile the manual to see the output.

I think the best way to convert links to \hyperref commands is by post-processing the parse-tree before passing it to Pandoc. Otherwise there are too many parts of the code to modify. I've done the conversion in POST-PROCESS-PARSE-TREE, but I still need to make sure only local links are converted, i.e., those starting with #, and also there are spacing issues with the way I am using Pandoc's raw attributes, so spaces are added before and after the label texts.

Also, let me know what you think of the [in package ...] style (sans serif).

@melisgl
Copy link
Owner

melisgl commented Jul 9, 2023

  • For me, documenting the entire pax manual produces a zero length pdf file. pax::@navigating-in-emacs looks good, but it still has some issues with latex command being visible:
    image
  • The indentation of the markdown code block is a 3bmd issue (Code blocks in list items 3b/3bmd#57) with a proposed fix.
  • Adjusting the links in post processing looks like the best place.
  • The sans-serif for the "in package" message is probably fine. I have not been able to generate a pdf with it.

@paulapatience
Copy link
Contributor Author

  • For me, documenting the entire pax manual produces a zero length pdf file. pax::@navigating-in-emacs looks good, but it still has some issues with latex command being visible:

I do not understand how you are encountering these errors. Can you dump the parse tree and the Markdown generated from the parse tree in PRINT-OUTPUT? Something like:

(uiop:with-output-file (s "/tmp/mgl-pax.lisp-expr" :if-exists :supersede)
  (format s "~S~%" parse-tree))
(uiop:with-output-file (s "/tmp/mgl-pax.markdown" :if-exists :supersede)
  (print-markdown parse-tree s :format :markdown))

at the beginning of PRINT-OUTPUT. Maybe it will give me an idea of what is going wrong on your end.

Also, is anything printed to *ERROR-OUTPUT* when the generated PDF is empty?

* The indentation of the markdown code block is a 3bmd issue ([Code blocks in list items 3b/3bmd#57](https://github.com/3b/3bmd/issues/57)) with a proposed fix.

Great.

I have managed to detect local links so that only those are converted to \hyperref commands, but it's probably not the fully correct way to do it. There's a FIXME in POST-PROCESS-PARSE-TREE discussing this. I also fixed the spacing issues by inserting \relax{} commands instead of spaces around the text passed to \hyperref. Pandoc is able to detect LaTeX commands without the {=latex} raw attribute syntax, but I think the \hyperref command might run into issues with arbitrary text without the raw attribute syntax (and I believe I encountered some errors with 3bmd not passing through the LaTeX commands properly, though I cannot remember what the errors were).

The only major blockers left are getting the manual to compile on your side and correctly escaping TeX characters. I have made a start on escaping them, but the code is weird for now. The rest is just cleaning up the PR.

@melisgl
Copy link
Owner

melisgl commented Jul 10, 2023

Here is the short version:

CL-USER> (let (#+nil (pax::*pandoc-options* '("--verbose")))
  (uiop:with-output-file (stream "mgl-pax.pdf" :if-exists :supersede)
    (pax:document mgl-pax::@pax-manual :stream stream :format :pandoc-pdf)))
Error producing PDF.
! Missing { inserted.
<to be read again> 
                   }
l.2380 \(\int\_0^\infty e^\{-x^2\} dx=\frac\{\sqrt

@melisgl
Copy link
Owner

melisgl commented Jul 10, 2023

Only documenting @mathjax:

(uiop:with-output-file (stream "mgl-pax.pdf" :if-exists :supersede)
(pax:document mgl-pax::@mathjax :stream stream :format :pandoc-pdf))

mgl-pax.lisp-expr:

((:HEADING :LEVEL 4 :CONTENTS ("MathJax"))
 (:PARAGRAPH (:CODE "\\label{x-28MGL-PAX-3A-40MATHJAX-20MGL-PAX-3ASECTION-29}")
  "{=latex}")
 (:PARAGRAPH
  (:CODE
   "\\subsubsection*{\\normalfont\\sffamily[in package MGL-PAX with nicknames PAX]}")
  "{=latex}" "
"
  "Displaying" " " "pretty" " " "mathematics" " " "in" " " "TeX" " " "format"
  " " "is" " " "supported" " " "via" "
"
  "MathJax." " " "It" " " "can" " " "be" " " "done" " " "inline" " " "with" " "
  (:CODE "$") " " "like" " " "this:")
 (:VERBATIM "$\\int_0^\\infty e^{-x^2} dx=\\frac{\\sqrt{\\pi}}{2}$
")
 (:PARAGRAPH "which" " " "is" " " "displayed" " " "as" " " "$" "\\" "int" "_"
  "0^" "\\" "infty" " " "e^" "{" "-x^2" "}" "
"
  "dx=" "\\" "frac" "{" "\\" "sqrt" "{" "\\" "pi" "}" "}" "{" "2" "}" "$," " "
  "or" " " "it" " " "can" " " "be" " " "delimited" " " "by" " " (:CODE "$$")
  " " "like" " " "this:")
 (:VERBATIM "$$\\int_0^\\infty e^{-x^2} dx=\\frac{\\sqrt{\\pi}}{2}$$
")
 (:PARAGRAPH "to" " " "get:" " " "$$" "\\" "int" "_" "0^" "\\" "infty" " " "e^"
  "{" "-x^2" "}" " " "dx=" "\\" "frac" "{" "\\" "sqrt" "{" "\\" "pi" "}" "}"
  "{" "2" "}" "$$")
 (:PARAGRAPH "MathJax" " " "will" " " "leave" " " "code" " " "blocks" " "
  "(including" " " "those" " " "inline" " " "with" "
"
  "backticks)" " " "alone." " " "Outside" " " "code" " " "blocks," " " "escape"
  " " (:CODE "$") " " "by" " " "prefixing" " " "it" "
"
  "with" " " "a" " " "backslash" " " "to" " " "scare" " " "MathJax" " " "off.")
 (:PARAGRAPH "Escaping" " " "all" " " "those" " " "backslashes" " " "in" " "
  "TeX" " " "fragments" " " "embedded" " " "in" " " "Lisp" "
"
  "strings" " " "can" " " "be" " " "a" " " "pain." " " "Pythonic" " " "String" "
"
  "Reader" " " "can" " " "help" " " "with" " " "that.")
 (:REFERENCE :LABEL ("pythonic-string-reader") :SOURCE
  "https://github.com/smithzvk/pythonic-string-reader" :TITLE NIL))

mgl-pax.markdown:

#### MathJax

`\label{x-28MGL-PAX-3A-40MATHJAX-20MGL-PAX-3ASECTION-29}`\{=latex\}

`\subsubsection*{\normalfont\sffamily[in package MGL-PAX with nicknames PAX]}`\{=latex\}
Displaying pretty mathematics in TeX format is supported via
MathJax. It can be done inline with `$` like this:

    $\int_0^\infty e^{-x^2} dx=\frac{\sqrt{\pi}}{2}$

which is displayed as $\int\_0^\infty e^\{-x^2\}
dx=\frac\{\sqrt\{\pi\}\}\{2\}$, or it can be delimited by `$$` like this:

    $$\int_0^\infty e^{-x^2} dx=\frac{\sqrt{\pi}}{2}$$

to get: $$\int\_0^\infty e^\{-x^2\} dx=\frac\{\sqrt\{\pi\}\}\{2\}$$

MathJax will leave code blocks (including those inline with
backticks) alone. Outside code blocks, escape `$` by prefixing it
with a backslash to scare MathJax off.

Escaping all those backslashes in TeX fragments embedded in Lisp
strings can be a pain. Pythonic String
Reader can help with that.

[pythonic-string-reader]: https://github.com/smithzvk/pythonic-string-reader 

@melisgl
Copy link
Owner

melisgl commented Jul 10, 2023

I have managed to detect local links so that only those are converted to \hyperref commands, but it's probably not the fully correct way to do it. There's a FIXME in POST-PROCESS-PARSE-TREE discussing this. I also fixed the spacing issues by inserting \relax{} commands instead of spaces around the text passed to \hyperref. Pandoc is able to detect LaTeX commands without the {=latex} raw attribute syntax, but I think the \hyperref command might run into issues with arbitrary text without the raw attribute syntax (and I believe I encountered some errors with 3bmd not passing through the LaTeX commands properly, though I cannot remember what the errors were).

I think the correct way to test for local links is (eq target-page *page*),

@paulapatience
Copy link
Contributor Author

paulapatience commented Jul 10, 2023

I think I know what is causing the problems on your end: you are likely using a newer version of 3bmd which escapes the braces. I have been using 3bmd 4e08d82. Should the braces really be escaped, I wonder? They don't do anything specific in Markdown, and they are useful in passing through LaTeX commands for Pandoc, and also for the raw attribute syntax. It seems nontrivial to deal with this.

And in fact, escaping the brackets might cause problems with optional arguments to LaTeX commands. For example, \hyperref[label]{text} is understood correctly by Pandoc as LaTeX, but I suspect the brackets might cause problems with 3bmd even if the braces are not escaped by it. (I have not looked specifically at how the escaping occurs in 3bmd, though.)

@melisgl
Copy link
Owner

melisgl commented Jul 10, 2023 via email

@paulapatience
Copy link
Contributor Author

They are special characters, but they are not defined by the specification as doing anything, and Pandoc relies on them heavily for much of its Markdown-compatible special syntax.

Inline LaTeX cannot be indented. Pandoc's raw attribute syntax (i.e., `raw latex`{=latex}) is meant to allow nontrivial LaTeX commands that do not consist of just backslash and braces, for example if some characters would otherwise be escaped, but escaping braces makes it unusable.

What was the problem with MathJax? Pandoc seems to support MathJax without issue. It is my impression that liberally including LaTeX commands in Pandoc Markdown files is common for those who use it to generate LaTeX. At least I do so. It seems to me that escaping braces from 3bmd makes this impossible. Specially handling the raw attribute syntax would help, but would complicate 3bmd and still not allow the general case of simple LaTeX commands.

@melisgl
Copy link
Owner

melisgl commented Jul 10, 2023 via email

@melisgl
Copy link
Owner

melisgl commented Jul 20, 2023

I'm likely to merge #29 soonish, which will likely result in lots of conflicts. I'm happy to resolve them if you prefer.

@paulapatience
Copy link
Contributor Author

I can resolve the conflicts, don't worry. I'll try to get back to this PR soon, especially since braces are no longer escaped in 3BMD.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants