일부 프로그래밍 언어(내 경우에는 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>
그 후에 사용자가 여러 줄 입력을 입력합니다. 그 다음에는 출력 줄이 나오고 또 다른 프롬프트가 나옵니다 gap>
. 이는 명령이 오류를 트리거할 때까지 반복되며, 오류가 발생하면 프롬프트가 로 변경됩니다 brk>
.
나는listings
패키지 (또는 다른 것)
- 프롬프트에 색상을 지정합니다
gap>
.>
, 및brk>
; 예를 들어, 파란색과 빨간색; for
,do
및 와 같은 키워드를 강조 표시합니다od
. 말하자면, 그들을 대담하게 만들어서;- 하지만오직프롬프트로 시작하는 줄의 키워드를 강조 표시하므로 내 명령의 출력 내부가 아닙니다.
마지막 요점은 나에게 문제를 일으키는 것입니다. 나는 그렇게 할 방법을 찾지 못했습니다. 오류 메시지 등에서 , 및 와 같은 단어가 키워드로 강조 표시되면 결과가 상당히 보기 흉한 경우가 많습니다 and
.not
in
비슷한 질문이 이전에 요청되었지만 내가 찾은 질문 중 정확히 이와 같은 질문을 한 사람은 없었습니다. 내가 원하는 대로 답변을 받았습니다.
기록을 위해 현재 사용하고 있는 언어 정의는 다음과 같습니다.
\lstdefine언어{GAP}{% 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{파란색}]{gap}{>},% moredelim=[s][\color{red}]{brk}{>},% %moredelim=*[l][\color{blue}]{gap>},% %moredelim=*[l][\color{red}]{brk>},% 민감함=사실,% morecomment=[l]\#,% morestring=[b]',% morestring=[b]",% }%
추신: 내가 원하는 것을 설명하기 위해 위의 예가 어떻게 보이는지 보여주는 이 이미지를 고려하십시오(위에서 설명한 것 외에도 모든 사용자 입력을 기울임꼴로 설정했습니다).
답변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에서는 그렇지 않습니다. 원시(형식화되지 않은) 세션 출력을 파일에 복사했습니다.세션.인그리고 거기에서 갔다.
\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}