何らかのプログラミング言語 (私の場合は GAP ですが、Python、BASH、または同様に対話型の読み取りプロンプトを備えた他の言語でもかまいません) で画面セッションをタイプセットするとします。すると、画面には次のような内容が表示されます。
gap> for i in [1..10] do
> Print(i, ":");
> od;
1:2:3:4:5:6:7:8:9:10:
gap> 2^10;
1024
gap> 1/0;
Error, Rational operations: <divisor> must not be zero
not in any function at line 5 of *stdin*
you can replace <divisor> via 'return <divisor>;'
brk> 2^10;
1024
brk>
つまり、コマンド プロンプト がありgap>
、その後にユーザーが複数行の入力を行います。その後に出力行が 1 行表示され、別の プロンプトgap>
が表示されます。コマンドがエラーをトリガーするまでこれが繰り返され、エラーが発生するとプロンプトが に変わりますbrk>
。
私はlistings
パッケージ(または他のもの)
- プロンプト
gap>
、>
、 に色を付けますbrk>
。たとえば、青と赤にします。 for
、、などのキーワードを太字にdo
しod
て強調表示します。- しかしのみプロンプトで始まる行内のキーワードを強調表示します。つまり、コマンドの出力内には強調表示されません。
最後の点は、私にとって問題となっている点です。その方法がわかりませんでした。たとえば、エラー メッセージで、、などの単語がキーワードとして強調表示されると、and
結果が非常に見苦しくなることがよくあります。not
in
以前にも同様の質問がありましたが、私が見つけた質問の中で、まさにこのことを求めているものはなく、私の求めている答えが得られました。
記録のために、私が現在使用している言語定義は次のとおりです。
\lstdefinelanguage{ギャップ}{% morekeywords=[2]{and、break、continue、do、elif、else、end、fail、false、fi、for、% 関数、if、in、local、mod、not、od、or、rec、repeat、return、then、true、% まで、その間},% moredelim=[s][\color{blue}]{gap}{>},% moredelim=[s][\color{red}]{brk}{>},% %moredelim=*[l][\color{blue}]{ギャップ>},% %moredelim=*[l][\color{red}]{brk>},% 敏感=true、% 続きコメント=[l]\#,% morestring=[b]',% morestring=[b]",% }%
PS: 私が望むものを説明するために、上記の例がどのように見えるかを示す次の画像を検討してください (上で説明した内容に加えて、すべてのユーザー入力を斜体に設定しました)。
答え1
このlistings
回答は約 1 年遅れていますが、すべての要件をカバーしていると思います。
編集: プロンプトの「キーワード」が行の途中に出現することに関連するバグを修正しました。
望ましい出力
得られた出力
コード
\documentclass[a4paper]{article}
\usepackage{xcolor}
\usepackage{textcomp}
\usepackage{listings}
\makeatletter
% switch to remember whether a prompt was found on the current line
\newif\ifprompt@GAP@
% switch to flag whether a prompt `keyword' is an bona fide GAP prompt
\newif\iftoolateforprompt@GAP@
% style of GAP keywords
\definecolor{GAPkeywords}{RGB}{077,145,021}
\newcommand\GAPkeywordstyle{\color{GAPkeywords}}
% font shape of GAP input lines
\newcommand\GAPinputfshape\slshape
\lstdefinelanguage{GAP}
{%
basicstyle =\ttfamily,
alsoletter=>,
morekeywords=[2]{%
and,break,continue,do,elif,else,end,fail,false,fi,for,function,if,in,%
local,mod,not,od,or,rec,repeat,return,then,true,until,while,
},%
keywordstyle=[2]\Process@GAP@keywords,
morekeywords=[3]{gap>,>},
keywordstyle=[3]\Process@GAP@prompt{blue},
morekeywords=[4]{brk>},
keywordstyle=[4]\Process@GAP@prompt{red},
sensitive=true,%
upquote=true,% <--- for straight single quotes
showstringspaces=false,
morecomment=[l]\#,
morestring=[b]',
morestring=[b]",
}%
% only highlight keywords if a prompt has occured on the current line
\newcommand\Process@GAP@keywords{\ifprompt@GAP@\GAPkeywordstyle\fi}
\newcommand\Process@GAP@prompt[1]
{%
\iftoolateforprompt@GAP@%
\else%
\color{#1}\upshape% customise the style of your > and gap> prompts here
\global\prompt@GAP@true%
\aftergroup\GAPinputfshape% we trigger slanted shape after > or gap>
\fi%
}
% Hook into InitVarsEOL (some hook executed right after an EOL) to:
% - reset the \ifprompt@GAP@ and \iftoolateforprompt@GAP@ switches
% - reset the font shape to \upshape
\lst@AddToHook{InitVarsEOL}%
{%
\global\prompt@GAP@false%
\global\toolateforprompt@GAP@false%
\upshape%
}
% Hook into PostOutput to signal that a GAP prompt
% can no occur on the current line
\lst@AddToHook{PostOutput}{\global\toolateforprompt@GAP@true}
\makeatother
\begin{document}
\begin{lstlisting}[language=GAP]
gap> for i in [1..10] do
> Print(i, ":");
> od;
1:2:3:4:5:6:7:8:9:10:
gap> 2^10;
1024
gap> 1/0;
Error, Rational operations: <divisor> must not be zero
not in any function at line 5 of *stdin*
you can replace <divisor> via 'return <divisor>;'
brk> 2^10;
1024
brk>
\end{lstlisting}
\end{document}
答え2
唯一の欠点は、サブワードではなく単語全体を処理することです。したがって、od;
はとは別の単語ですod
。これは克服できますが、このMWEでは克服できません。生の(フォーマットされていない)セッション出力をファイルにコピーしました。セッション.inそしてそこから出発しました。
\documentclass[12pt]{article}
\makeatletter%
\let\protectededef\protected@edef
\makeatother%
\parindent 0in
\renewcommand{\encodingdefault}{T1}
\usepackage{color}
\usepackage{readarray}
\usepackage{verbatimbox}
\usepackage{ifthen}
\catcode`^=12
\definecolor{darkgreen}{rgb}{0,0.5,0}
\newcounter{rowindex}\newcounter{wordindex}%
\newcommand\displaysource[1]{%
\sffamily%
\readdef{#1}{\x}%
\setcounter{rowindex}{0}%
\whiledo{\value{rowindex} < \nrecords}{%
\addtocounter{rowindex}{1}%
\getargsC{\csname record\roman{rowindex}\endcsname}%
\ifthenelse{\equal{\argi}{>} \OR%
\equal{\argi}{gap>} \OR%
\equal{\argi}{brk>}}%
{\def\userin{\itshape}}{\def\userin{\upshape}}%
\setcounter{wordindex}{0}%
\whiledo{\value{wordindex} < \narg}{%
\addtocounter{wordindex}{1}%
\protectededef\thisword{\csname arg\roman{wordindex}\endcsname}%
\ifthenelse{\equal{\thisword}{gap>} \OR%
\equal{\thisword}{>}}%
{%
\upshape\textcolor{blue}{\thisword~}%
}{%
\ifthenelse{\equal{\thisword}{brk>}}%
{%
\textcolor{red}{brk>~}%
}{%
\userin%
\ifthenelse{\equal{\thisword}{for} \OR%
\equal{\thisword}{in} \OR%
\equal{\thisword}{do} \OR%
\equal{\thisword}{od} \OR%
\equal{\thisword}{od;}}%
{%
\ifthenelse{\equal{\userin}{\itshape}}%
{%
\textcolor{darkgreen}{\thisword~}%
}{%
\thisword~%
}%
}{%
\thisword~%
}
}%
}%
}%
\\%
}%
\rmfamily%
}
\begin{document}
\displaysource{session.in}
\end{document}