我正在使用 minted 制作一本书,但我花了(太多)时间调试 minted 问题。
例如,此示例无法构建。我收到以下错误:
% rubber --module xelatex --shell-escape bug.tex
Rubber invoked from VCS, prepending /Users/matt/Dropbox/work/pylib/rubber3 to sys.path
compiling bug.tex
executing: xelatex --shell-escape \nonstopmode \input{bug.tex}
Running xelatex resulted in a non-zero exit status.
There were errors compiling bug.tex: Recipe for bug.pdf failed.
/tmp/91A8E376AC74D855FA3944C0B7FC6AD4AA0F2A48A3BB41E9972AE82845B2144D.pygtex:7: Something's wrong--perhaps a missing \item.
/tmp/91A8E376AC74D855FA3944C0B7FC6AD4AA0F2A48A3BB41E9972AE82845B2144D.pygtex:7: leading text: \end{Verbatim}
/tmp/91A8E376AC74D855FA3944C0B7FC6AD4AA0F2A48A3BB41E9972AE82845B2144D.pygtex:7: Something's wrong--perhaps a missing \item.
/tmp/91A8E376AC74D855FA3944C0B7FC6AD4AA0F2A48A3BB41E9972AE82845B2144D.pygtex:7: leading text: \end{Verbatim}
/tmp/91A8E376AC74D855FA3944C0B7FC6AD4AA0F2A48A3BB41E9972AE82845B2144D.pygtex:7: Missing } inserted.
/tmp/91A8E376AC74D855FA3944C0B7FC6AD4AA0F2A48A3BB41E9972AE82845B2144D.pygtex:7: leading text: \end{Verbatim}
/tmp/91A8E376AC74D855FA3944C0B7FC6AD4AA0F2A48A3BB41E9972AE82845B2144D.pygtex:7: Missing } inserted.
/tmp/91A8E376AC74D855FA3944C0B7FC6AD4AA0F2A48A3BB41E9972AE82845B2144D.pygtex:7: leading text: \end{Verbatim}
/tmp/91A8E376AC74D855FA3944C0B7FC6AD4AA0F2A48A3BB41E9972AE82845B2144D.pygtex:7: Missing } inserted.
/tmp/91A8E376AC74D855FA3944C0B7FC6AD4AA0F2A48A3BB41E9972AE82845B2144D.pygtex:7: leading text: \end{Verbatim}
/tmp/91A8E376AC74D855FA3944C0B7FC6AD4AA0F2A48A3BB41E9972AE82845B2144D.pygtex:7: Extra }, or forgotten \endgroup.
/tmp/91A8E376AC74D855FA3944C0B7FC6AD4AA0F2A48A3BB41E9972AE82845B2144D.pygtex:7: leading text: \end{Verbatim}
/tmp/91A8E376AC74D855FA3944C0B7FC6AD4AA0F2A48A3BB41E9972AE82845B2144D.pygtex:7: Extra }, or forgotten \endgroup.
/tmp/91A8E376AC74D855FA3944C0B7FC6AD4AA0F2A48A3BB41E9972AE82845B2144D.pygtex:7: leading text: \end{Verbatim}
/tmp/91A8E376AC74D855FA3944C0B7FC6AD4AA0F2A48A3BB41E9972AE82845B2144D.pygtex:7: Extra }, or forgotten \endgroup.
/tmp/91A8E376AC74D855FA3944C0B7FC6AD4AA0F2A48A3BB41E9972AE82845B2144D.pygtex:7: leading text: \end{Verbatim}
./bug.tex:369: File ended while scanning use of \FancyVerbGetLine.
./bug.tex:369: leading text: \end{minted}
./bug.tex:369: FancyVerb Error:
./bug.tex:369: leading text: \end{minted}
More errors.
但是,更改第 369 行的代码没有帮助。错误似乎发生在这之前。
我在下面粘贴了一个示例文件。
我正在运行% rubber --module xelatex --shell-escape bug.tex
以构建测试文件。
但是,如果您搜索“我的困惑”并注释掉其正下方的代码,则文件可以构建(此代码不是第 369 行)。
% run command:
% rubber --module xelatex --shell-escape bug.tex
\documentclass[11pt]{memoir}
\setstocksize{9in}{6in}
\settrimmedsize{\stockheight}{\stockwidth}{*}
\setulmarginsandblock{0.75in}{0.75in}{*}
\setlrmarginsandblock{0.8in}{0.55in}{*}
\setheaderspaces{0.5in}{*}{*}
% Need this after tweaking above
\checkandfixthelayout
\usepackage[cache=true,cachedir=/tmp,newfloat=true]{minted}
% better frames - used for Note section
\usepackage{mdframed}
\usepackage[breaklinks,linktocpage=true]{hyperref}
\usepackage{needspace}
\usepackage{color}
\definecolor{litegreen}{rgb}{0.95,0.95,0.85}
\definecolor{mygreen}{rgb}{0,0.6,0}
\usepackage{fontspec}
\usepackage[Latin,Greek,Emoticons]{ucharclasses}
\newfontfamily\mydef{DejaVu Sans}
\newfontfamily\mynormal{Palatino}
\setTransitionsFor{Emoticons}{\begingroup\mydef}{\endgroup}
\newfontfamily\headfont{Roboto Condensed}
%\setchapheadstyle{\headfont}% Set \section style
\setsecheadstyle{\headfont}% Set \section style
\renewcommand{\chaptitlefont}{\headfont\huge}
\renewcommand{\chapnumfont}{\headfont\huge}
\renewcommand{\chapnamefont}{\headfont\huge}
\renewcommand{\partnumfont}{\headfont}
\renewcommand{\partnamefont}{\headfont}
\renewcommand{\parttitlefont}{\headfont}
\usepackage{longtable}
\begin{document}
% - definitions
\newcommand{\Author}{Matt Harrison}
\newcommand{\Title}{A book}
\frontmatter
% half title page
\pagestyle{empty}
\begin{center}
\huge{\Title}
\vskip25pt
\end{center}
\clearpage
% also available - on verso
\newpage
\thispagestyle{empty}
\mbox{}
\clearpage
% full title
\pagestyle{empty}
\begin{center}
\huge{\Title}
\vskip25pt
\vskip25pt
\large{}
\Author
\vskip25pt
\end{center}
\null\vfill
\begin{center}
\end{center}
\clearpage
% copyright
\null\vfill
\begin{flushleft}
COPYRIGHT © 2023
\bigskip
\vskip5pt
While every precaution has been taken in the preparation of this book, the publisher and author assumes no responsibility for errors or omissions, or for damages resulting from the use of the information contained herein.
\end{flushleft}
\clearpage
\pagestyle{ruled}
\aliaspagestyle{chapter}{ruled}
\tableofcontents*
% \dedicationpage
\mainmatter
\hypertarget{conditionals-and-whitespace}{%
\chapter{Conditionals and
Whitespace}\label{conditionals-and-whitespace}}
In this chapter, you will learn more about making comparisons in Python.
Most code needs to decide which path to execute, so you will look at how
this is done.
In addition to the boolean values, \mintinline[]{text}{True} and
\mintinline[]{text}{False}, in Python, you can also use expressions to
get boolean values. If you have two numbers, you might want to compare
them to check if they are greater than or less than each other. The
operators, \mintinline[]{text}{>} and \mintinline[]{text}{<}, do this
respectively:
\begin{minted}[]{pycon}
>>> 5 > 9
False
\end{minted}
These operations work on most types. If you create a custom class that
defines the appropriate magic methods, your class can use them as well:
My confusion. If I comment out below it works!
\begin{minted}[]{pycon}
>>> name = 'Matt'
>>> name == 'Matt'
True
>>> name != 'Fred'
True
>>> 1 > 3
False
\end{minted}
\index{\mintinline[]{text}{functools.total_ordering}}
\begin{mdframed}[needspace=6.5em,frametitle={\headfont Note
},backgroundcolor=litegreen,linewidth=0pt]
The ``rich comparison'' magic methods, \mintinline[]{text}{__gt__},
\mintinline[]{text}{__lt__}, \mintinline[]{text}{__ge__},
\mintinline[]{text}{__le__}, \mintinline[]{text}{__eq__}, and
\mintinline[]{text}{__ne__} correspond to \mintinline[]{text}{>},
\mintinline[]{text}{<}, \mintinline[]{text}{>=},
\mintinline[]{text}{<=}, \mintinline[]{text}{==}, and
\mintinline[]{text}{!=} respectively. Defining all of these can be
somewhat tedious and repetitive. For classes where these comparisons are
commonly used, the \mintinline[]{text}{functools.total_ordering} class
decorator gives you all of the comparison functionality as long as you
define \mintinline[]{text}{__eq__} and \mintinline[]{text}{__le__}. The
decorator will automatically derive the remainder of the comparison
methods. Otherwise, all six methods should be implemented:
\begin{minted}[]{pycon}
>>> import functools
>>> @functools.total_ordering
... class Abs(object):
... def __init__(self, num):
... self.num = abs(num)
... def __eq__(self, other):
... return self.num == abs(other)
... def __lt__(self, other):
... return self.num < abs(other)
>>> five = Abs(-5)
>>> four = Abs(-4)
>>> five > four # not using less than!
True
\end{minted}
Decorators are considered an intermediate subject and are not covered in
this beginning book.
\end{mdframed}
\begin{mdframed}[needspace=6.5em,frametitle={\headfont Note
},backgroundcolor=litegreen,linewidth=0pt]
The \mintinline[]{text}{is} and \mintinline[]{text}{is not} statements
are for comparing \emph{identity}. When testing for identity---if two
objects are the same actual object with the same \mintinline[]{text}{id}
(not just the same value)---use \mintinline[]{text}{is} or
\mintinline[]{text}{is not}. Since \mintinline[]{text}{None} is a
singleton and only has one identity, \mintinline[]{text}{is} and
\mintinline[]{text}{is not} are used with \mintinline[]{text}{None}:
\begin{minted}[]{pycon}
>>> if name is None:
... # initialize name
\end{minted}
\end{mdframed}
\hypertarget{combining-conditionals}{%
\section{Combining conditionals}\label{combining-conditionals}}
\index{\mintinline[]{text}{and}}
\index{\mintinline[]{text}{or}}
\index{\mintinline[]{text}{not}}
Conditional expressions are combined using \emph{boolean logic}. This
logic consists of the \mintinline[]{text}{and}, \mintinline[]{text}{or},
and \mintinline[]{text}{not} operators.
\begin{longtable}[]{@{}
>{\raggedright\arraybackslash}p{(\columnwidth - 2\tabcolsep) * \real{0.2169}}
>{\raggedright\arraybackslash}p{(\columnwidth - 2\tabcolsep) * \real{0.7831}}@{}}
\toprule\noalign{}
\begin{minipage}[b]{\linewidth}\raggedright
Boolean Operator
\end{minipage} & \begin{minipage}[b]{\linewidth}\raggedright
Meaning
\end{minipage} \\
\midrule\noalign{}
\endhead
\bottomrule\noalign{}
\endlastfoot
\mintinline[]{text}{x and y} & Both \mintinline[]{text}{x} and
\mintinline[]{text}{y} must evaluate to \mintinline[]{text}{True} for
true result \\
\mintinline[]{text}{x or y} & If \mintinline[]{text}{x} or
\mintinline[]{text}{y} is \mintinline[]{text}{True}, result is true \\
\mintinline[]{text}{not x} & Negate the value of \mintinline[]{text}{x}
(\mintinline[]{text}{True} becomes \mintinline[]{text}{False} and vice
versa) \\
\end{longtable}
Below is a simple example of setting a grade based on a
\mintinline[]{text}{score} using \mintinline[]{text}{and} to test
whether the score is between two numbers:
\begin{minted}[]{pycon}
>>> score = 91
>>> if score > 90 and score <= 100:
... grade = 'A'
\end{minted}
\index{range comparison}
\begin{mdframed}[needspace=6.5em,frametitle={\headfont Note
},backgroundcolor=litegreen,linewidth=0pt]
Python allows you to do the above example using a \emph{range
comparison} like this:
\begin{minted}[]{pycon}
>>> if 90 < score <=100:
... grade = 'A'
\end{minted}
Either style works, but range comparisons are not common in other
languages.
\end{mdframed}
Here is an example for checking if a given name is a member of a band:
\begin{minted}[]{pycon}
>>> name = 'Paul'
>>> beatle = False
>>> if name == 'George' or \
... name == 'Ringo' or \
... name == 'John' or \
... name == 'Paul':
... beatle = True
... else:
... beatle = False
\end{minted}
\begin{mdframed}[needspace=6.5em,frametitle={\headfont Note
},backgroundcolor=litegreen,linewidth=0pt]
In the above example, the \mintinline[]{text}{\} at the end of
``\mintinline[]{text}{'George' or \}'' indicates that the statement will
be continued on the next line.
Like most programming languages, Python allows you to wrap conditional
statements in parentheses. Because they are not required in Python, most
developers leave them out unless they are needed for operator
precedence. But another subtlety of using parentheses is that they serve
as a hint to the interpreter when a statement is still open and will be
continued on the next line. Hence the \mintinline[]{text}{\} is not
needed in that case:
\begin{minted}[]{pycon}
>>> name = 'Paul'
>>> beatle = False
>>> if (name == 'George' or
... name == 'Ringo' or
... name == 'John' or
... name == 'Paul'):
... beatle = True
... else:
... beatle = False
\end{minted}
\end{mdframed}
\begin{mdframed}[needspace=6.5em,frametitle={\headfont Note
},backgroundcolor=litegreen,linewidth=0pt]
An idiomatic Python version of checking membership is listed below. To
check if a value is found across a variety of values, you can throw the
values in a set and use the \mintinline[]{text}{in} operator:
\begin{minted}[]{pycon}
>>> beatles = {'George', 'Ringo', 'John', 'Paul'}
>>> beatle = name in beatles
\end{minted}
A later chapter will discuss sets further.
\end{mdframed}
Here is an example of using the \mintinline[]{text}{not} keyword in a
conditional statement:
\begin{minted}[]{pycon}
>>> last_name = 'unknown'
>>> if name == 'Paul' and not beatle:
... last_name = 'Revere'
\end{minted}
\hypertarget{if-statements}{%
\section{\texorpdfstring{\mintinline[]{text}{if}
statements}{ statements}}\label{if-statements}}
\index{\mintinline[]{text}{if}}
\index{\mintinline[]{text}{elif}}
\index{\mintinline[]{text}{else}}
Booleans (\mintinline[]{text}{True} and \mintinline[]{text}{False}) are
often used in \emph{conditional} statements. Conditional statements are
instructions that say, ``if this statement is true, perform a block of
code, otherwise execute some other code.'' Branching statements are used
frequently in Python. Sometimes, the ``if statement'' will check values
that contain booleans, other times it will check \emph{expressions} that
evaluate to booleans. Another common check is for implicit coercion to
``truthy'' or ``falsey'' values:
\begin{minted}[]{pycon}
>>> debug = True
>>> if debug: # checking a boolean
... print("Debugging")
Debugging
\end{minted}
\hypertarget{else-statements}{%
\section{\texorpdfstring{\mintinline[]{text}{else}
statements}{ statements}}\label{else-statements}}
An \mintinline[]{text}{else} statement can be used in combination with
an \mintinline[]{text}{if} statement. The body of the
\mintinline[]{text}{else} statement will execute only if the
\mintinline[]{text}{if} statement evaluates to
\mintinline[]{text}{False}. Here is an example of combining an
\mintinline[]{text}{else} statement with an \mintinline[]{text}{if}
statement. The school below appears to have grade inflation:
\begin{minted}[]{pycon}
>>> score = 87
>>> if score >= 90:
... grade = 'A'
... else:
... grade = 'B'
\end{minted}
\backmatter
\printindex
% add some empty pages at end
\clearpage
\clearpage
\newpage
\thispagestyle{empty}
\mbox{}
\newpage
\thispagestyle{empty}
\mbox{}
\end{document}