如何编写类似于 JR Heard 的《美丽的代码》中给出的伪代码

如何编写类似于 JR Heard 的《美丽的代码》中给出的伪代码

我读到一篇令人惊奇的文章,它叫做JR Heard 的《美丽的代码,令人信服的证据》。我想知道是否有一个包或东西可以让我以类似于 JR Heard 展示他的代码的方式展示我的代码。

虽然我想要行号,但我认为首先我需要找到他用来创建这种格式的东西。注意:代码是 Haskell,但我想将其用于伪代码。

PS:如果能在竖线后进行行号标注就更好了。不过我也想知道是否可以真正固定左列的宽度。

下面是他令人惊叹的作品中的一个例子: JR Heard 的《Beautiful Code》中的示例

感谢您花时间和精力来帮助我!

答案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}

在此处输入图片描述

相关内容