我有一个可执行文件,它对包含文学代码的文件执行语义突出显示。它输出一个.tex
文件,我可以使用 catchfilebetweentags 从中获取代码片段。
我面临的一个问题是缩进的代码总是以空格开头。我想摆脱共享前缀对应于缩进,同时保留某些行中可能存在的进一步的前导空格,因为在源语言中缩进是有意义的。
以下是作为 MWE 的一个典型示例:
\documentclass[11pt]{article}
%%% Code typesetting preamble
\newcommand{\CodeSpace}{\hphantom{ }}
\newcommand{\CodeNewLine}{\\}
\newcommand{\CodeKeyword}[1]{\textbf{#1}}
\newcommand{\CodeIdentifier}[1]{\textit{#1}}
\newenvironment{code}
{\vspace{1em}\noindent\begin{minipage}{\linewidth}\obeyspaces\ttfamily}
{\end{minipage}}
%%%
\begin{document}
\section{No leading whitespace}
\begin{code}
\CodeKeyword{let}\CodeSpace\CodeIdentifier{id}\CodeSpace\CodeIdentifier{xs}\CodeNewLine
\CodeSpace\CodeSpace\CodeKeyword{=}\CodeSpace\CodeIdentifier{xs}
\end{code}
\section{Annoying leading whitespace}
\begin{code}
\CodeSpace\CodeSpace\CodeSpace\CodeSpace\CodeKeyword{let}\CodeSpace\CodeIdentifier{id}\CodeSpace\CodeIdentifier{xs}\CodeNewLine
\CodeSpace\CodeSpace\CodeSpace\CodeSpace\CodeSpace\CodeSpace\CodeKeyword{=}\CodeSpace\CodeIdentifier{xs}
\end{code}
\end{document}
它的渲染方式如下,理想情况下,两个部分应该看起来相同:
code
我很高兴改变环境或原始命令的定义\CodeX
。
答案1
改编
- 添加布尔值
firstlinestart
和linestart
(使用\newtoggle
包etoolbox
) - 添加计数器
currentcodespaces
和codespaces
- 扩展
\CodeSpace
:- 用计数器计算空格数
currentcodespaces
- 如果在第一行的开头 (
firstlinestart
) 或者在另一行的开头 (linestart
) 并且currentcodespaces
<= 则忽略空格codespaces
- 用计数器计算空格数
- 定义了一个命令
\CodeNoSpace
,该命令应由每个代码命令调用,但以下命令除外\CodeSpace
- 切换
linestart
为 false codespaces
如果是第一行,则设置计数器
- 切换
- 扩展
\CodeNewLine
:- 重置
currentcodespaces
为 0 和linestart
true - 调试时可选:显示原来的前导空格(红色)
- 重置
code
环境将两个切换设置为 true,并将计数器设置currentcodespaces
为 0
代码
\documentclass[11pt]{article}
\usepackage{xcolor}
\usepackage{etoolbox}
%%% Code typesetting preamble
\newtoggle{firstlinestart}
\newtoggle{linestart}
\newcounter{currentcodespaces}
\newcounter{codespaces}
\newcommand{\CodeNoSpace}{%
% This command should be called by each Code command that is not \CodeSpace
\togglefalse{linestart}%
\iftoggle{firstlinestart}{%
\togglefalse{firstlinestart}%
\setcounter{codespaces}{\thecurrentcodespaces}%
}{}%
}
\newcommand{\CodeSpace}{%
\stepcounter{currentcodespaces}%
\ifboolexpe{
togl{firstlinestart} or (
togl{linestart} and test{ \ifnumless{ \value{currentcodespaces} }{ \value{codespaces} + 1 } }
)
}{%
% ignore spaces
}{%
\hphantom{ }%
}%
}
\newcommand{\CodeNewLine}{%
\CodeNoSpace%
\quad\textcolor{red}{\footnotesize\textrm{(originally: \arabic{codespaces} leading spaces)}}% this line is just for debugging
\\%
\setcounter{currentcodespaces}{0}%
\toggletrue{linestart}%
}
\newcommand{\CodeKeyword}[1]{\CodeNoSpace\textbf{#1}}
\newcommand{\CodeIdentifier}[1]{\CodeNoSpace\textit{#1}}
\newenvironment{code}{%
\vspace{1em}%
\noindent%
\begin{minipage}{\linewidth}%
\obeyspaces%
\ttfamily%
\setcounter{currentcodespaces}{0}
\toggletrue{firstlinestart}
\toggletrue{linestart}
}{%
\end{minipage}%
}
%%%
\begin{document}
\section{No leading whitespace}
\begin{code}
\CodeKeyword{let}\CodeSpace\CodeIdentifier{id}\CodeSpace\CodeIdentifier{xs}\CodeNewLine
\CodeSpace\CodeSpace\CodeKeyword{=}\CodeSpace\CodeIdentifier{xs}
\end{code}
\section{No annoying leading whitespace anymore}
\begin{code}
\CodeSpace\CodeSpace\CodeSpace\CodeSpace\CodeKeyword{let}\CodeSpace\CodeIdentifier{id}\CodeSpace\CodeIdentifier{xs}\CodeNewLine
\CodeSpace\CodeSpace\CodeSpace\CodeSpace\CodeSpace\CodeSpace\CodeKeyword{=}\CodeSpace\CodeIdentifier{xs}
\end{code}
\begin{code}
\CodeSpace\CodeSpace\CodeKeyword{let}\CodeSpace\CodeIdentifier{id}\CodeSpace\CodeIdentifier{xs}\CodeNewLine
\CodeSpace\CodeSpace\CodeSpace\CodeSpace\CodeKeyword{=}\CodeSpace\CodeIdentifier{xs}
\end{code}
\end{document}