我读到一篇令人惊奇的文章,它叫做JR Heard 的《美丽的代码,令人信服的证据》。我想知道是否有一个包或东西可以让我以类似于 JR Heard 展示他的代码的方式展示我的代码。
虽然我想要行号,但我认为首先我需要找到他用来创建这种格式的东西。注意:代码是 Haskell,但我想将其用于伪代码。
PS:如果能在竖线后进行行号标注就更好了。不过我也想知道是否可以真正固定左列的宽度。
下面是他令人惊叹的作品中的一个例子:
感谢您花时间和精力来帮助我!
答案1
我没有使用提供的 Haskell 突出显示listings
,因为它突出显示了太多未在示例中突出显示的单词(例如 List 等)。
\documentclass[12pt,DIV13]{scrartcl}
\usepackage{fontspec,listings,xcolor,lipsum}
% Fonts
\defaultfontfeatures{Ligatures=TeX}
\setmainfont{Gill Sans Std}
\setmonofont{Lucida Sans Typewriter OT}
% Colors
\definecolor{darkgray}{HTML}{404040}
\definecolor{rulegray}{HTML}{DADADA}
\definecolor{keywordblue}{HTML}{1F497C}
% Listings
\lstdefinestyle{code}{
basicstyle=\ttfamily,
keywordstyle=\color{keywordblue},
keywords={import,qualified,as,do,where}
}
\newcommand\clearlines[1]{%
\if#10\else%
\leavevmode\\%
\expandafter\clearlines\expandafter{\the\numexpr#1-1}%
\fi}
\begin{document}
\lipsum[1]
\begin{center}
\footnotesize
\begin{minipage}{.25\linewidth}
\color{darkgray}\raggedleft\itshape
imports, aliases (1-3) \clearlines{5}
Split all lines in the file. (6-7) \clearlines{3}
Insert them into the map (9)
\end{minipage}
\hfill{\color{rulegray}\vrule}\hfill
\begin{minipage}{.73\linewidth}
\begin{lstlisting}[style=code]
import Data.List (foldl')
import qualified Data.ByteString.Lazy.Char8 as BStr
import qualified Data.Map as Map
readDatafile name = do
sheet <- (map (BStr.split '\t') . BStr.lines) `fmap`
BStr.readFile name
return $ foldl’ go Map.empty sheet
where go m (x:xs) = Map.insert (BStr.unpack x) xs m
\end{lstlisting}
\end{minipage}
\end{center}
\lipsum[1]
\end{document}
适应Martin Scharrer 的回答对于类似的问题,可以得到一个更简单的版本:
\documentclass[12pt,DIV13]{scrartcl}
\usepackage{fontspec,listings,xcolor,lipsum}
% Fonts
\defaultfontfeatures{Ligatures=TeX}
\setmainfont{Gill Sans Std}
\setmonofont{Lucida Console}
% Colors
\definecolor{darkgray}{HTML}{404040}
\definecolor{rulegray}{HTML}{DADADA}
\definecolor{keywordblue}{HTML}{1F497C}
% Listings
\lstnewenvironment{beautifulcode}{
\lstset{
basicstyle=\footnotesize\ttfamily,
keywordstyle=\color{keywordblue},
keywords={import,qualified,as,do,where},
frame=l,rulecolor=\color{rulegray},framesep=.5em,
escapeinside={(*@}{@*)},
escapebegin={\begin{lrbox}{0}\normalfont\itshape\footnotesize\color{darkgray}},
escapeend={\end{lrbox}\llap{\box0\hspace{1em}}}
}
\hspace*{.25\linewidth}
\minipage{.75\linewidth}
}{
\endminipage
}
\begin{document}
\lipsum[1]
\begin{beautifulcode}
(*@imports, aliases (1-3)@*)import Data.List (foldl')
import qualified Data.ByteString.Lazy.Char8 as BStr
import qualified Data.Map as Map
readDatafile name = do
(*@Split all lines in the file. (6-7)@*) sheet <- (map (BStr.split '\t') . BStr.lines) `fmap`
BStr.readFile name
return $ foldl’ go Map.empty sheet
(*@Insert them into the map (9)@*) where go m (x:xs) = Map.insert (BStr.unpack x) xs m
\end{beautifulcode}
\lipsum[1]
\end{document}
答案2
也许你想尝试tcblisting
一下tcolorbox
。接下来这只是一个起点,需要进行大量的定制。
\documentclass{article}
\usepackage[most]{tcolorbox}
\newtcblisting{Heardlisting}[2][]{%
empty,
boxsep=0pt,left=0pt,right=0pt,boxrule=2pt,leftrule=0pt,rightrule=0pt,
lefthand width=.4\linewidth,
segmentation engine=path,
segmentation style={solid,line width=1pt},
comment side listing,
fontupper=\itshape\sffamily,
listing options={% put any listing options here
language={Haskell},
aboveskip=0pt, belowskip=0pt,
basicstyle=\ttfamily,columns=fullflexible},
comment={#2},#1
}
\begin{document}
\noindent%
\begin{Heardlisting}{%
\begin{tabular}{r}%
imports, aliases (1-3)\\ \\ \\ \\ \\
Split all lines in the file. (6-7)\\ \\ \\
Insert them into the map (9)
\end{tabular}
}
import data.List (foldl`)
import qualified Data.ByteString.Lazy.Char8 as BStr
import qualified Data.Map as Map
readDatafile name = do
sheet <- (mat (BStr.split `\t`) . BStr.lines) `fmap
BStr.readFile name
return $ foldl`go Map.empty sheet
where go m (x:xs) = Map.insert (BStr.unpack x) xs m
\end{Heardlisting}
\end{document}
答案3
在这种方法中,我引入pcodeinput
环境来设置参数,同时\pcode[comment]{code}
在环境中引入代码行。这比其他将注释与源文档中的代码放在一起的方法更有优势。
用户参数包括
\leftcodesize=1.7in\relax
\leftcodegap=8pt\relax
\rightcodegap=10pt\relax
\coderulewidth=1pt\relax
\def\codecolor{blue!30!black!65}
\def\highlightcolor{blue!70!black!99}
定义注释的宽度、分隔条周围的间隙、分隔条的宽度以及代码和突出显示代码的颜色。
我对这种方法的改进是调整了文本突出显示包\titlecap
的例程。在该包中,将除用户指定的小写单词列表中提供的单词之外的每个单词大写。在这里,转换为,其中突出显示单词使用语法添加。不在列表中的单词用上色,而列表中的单词用上色。请注意,内置于定义中,因此对用户来说是透明的。titlecaps
\titlecap
\titlecap
\colorize
\AddHighlightWords{import qualified as do where}
\codecolor
\highlightcolor
\colorize
\pcode[]{}
这不是一个verbatim
环境,所以需要采取特殊措施。例如,我将$
OP 示例中出现的 设置为 catcode 12。除了反斜杠外,其他所需的符号也可以这样做。在这种情况下(因为它在 OP 的代码中似乎很少出现),我将其输入\textbackslash
为代码清单中的内容。
\documentclass{article}
\usepackage{xcolor,lipsum}
\usepackage[margin=1in]{geometry}
\newlength\leftcodesize
\newlength\leftcodegap
\newlength\rightcodegap
\newlength\coderulewidth
%%% USER PARAMETERS
\leftcodesize=1.7in\relax
\leftcodegap=8pt\relax
\rightcodegap=10pt\relax
\coderulewidth=1pt\relax
\def\codecolor{blue!30!black!65}
\def\highlightcolor{blue!70!black!99}
%%%
\newcommand\pcode[2][]{%
\fboxsep=0pt%
\fboxrule=.5\coderulewidth%
\makebox[\leftcodesize][r]{%
\scriptsize\sffamily\itshape#1\hspace{\leftcodegap}}%
\smash{\fbox{\strut}}%
\hspace{\rightcodegap}%
\ttfamily\small\colorize[n]{#2}\par%
}
\newenvironment{pcodeinput}
{\parindent 0pt\parskip 0pt\color{\codecolor}\medskip%
\catcode`$=12}
{\medskip}
%%
\makeatletter
% ADAPT THE \titlecap ROUTINE FROM titlecaps PACKAGE
\usepackage{titlecaps}
\newcommand\colorize[2][P]{%
\digest@sizes%
\if T\converttilde\def~{ }\fi%
\redefine@tertius%
\get@argsC{#2}%
\seek@lcwords{#1}%
\if P#1%
\redefine@primus%
\get@argsC{#2}%
\protected@edef\primus@argi{\argi}%
\else%
\fi%
\setcounter{word@count}{0}%
\redefine@secundus%
\def\@thestring{}%
\get@argsC{#2}%
\if P#1\protected@edef\argi{\primus@argi}\fi%
\whiledo{\value{word@count} < \narg}{%
\addtocounter{word@count}{1}%
\if F\csname found@word\roman{word@count}\endcsname%
\textcolor{\codecolor}{\csname arg\roman{word@count}\endcsname}
\expandafter\protected@edef\csname%
arg\roman{word@count}\endcsname{\@thestring}%
\else
\textcolor{\highlightcolor}{\csname arg\roman{word@count}\endcsname}
\expandafter\protected@edef\csname%
arg\roman{word@count}\endcsname{\@thestring}%
\fi%
}%
\def\@thestring{}%
\setcounter{word@count}{0}%
\whiledo{\value{word@count} < \narg}{%
\addtocounter{word@count}{1}%
\ifthenelse{\value{word@count} = 1}%
{}{\add@space}%
\protected@edef\@thestring{\@thestring%
\csname arg\roman{word@count}\endcsname}%
}%
\let~\SaveHardspace%
\@thestring%
\restore@sizes%
\un@define}
\makeatother
\let\AddHighlightWords\Addlcwords
\begin{document}
\lipsum[1]
\AddHighlightWords{import qualified as do where}
\begin{pcodeinput}
\pcode[imports, aliases (1-3)]
{import Data,List (foldl')}
\pcode%
{import qualified Data.ByteString.Lazy.Char8 as BStr}
\pcode
{import qualified Data.Map as map}
\pcode
{}
\pcode
{readDatafile name do}
\pcode[Split all lines in the file. (6-7)]
{ sheet <- (map (BStr.split `\textbackslash t') . BStr.lines) `fmap'}
\pcode
{ BStr.readFile name}
\pcode
{ return $ foldl' go Map.empty sheet}
\pcode[Insert them into the map (9)]
{ where go m (x:xs) = Map.insert (BStr.unpack x) xs m}
\end{pcodeinput}
\lipsum[2]
\end{document}