我怎麼能像這樣突出顯示互動式 GAP 會話?

我怎麼能像這樣突出顯示互動式 GAP 會話?

假設我想用某種程式語言(在我的例子中是 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包裹(或其他東西)到

  1. 為提示著色gap>>、 和brk>;比如說,藍色和紅色;
  2. 反白關鍵字,如fordo、 和od;說,讓他們大膽;
  3. 僅有的突出顯示以提示開頭的行中的關鍵字,因此不在我的命令的輸出中。

最後一點是給我帶來麻煩的一點。我想不出辦法做到這一點。當諸如andnot、 和 之類的字詞in在錯誤訊息等中突出顯示為關鍵字時,結果通常非常難看。

類似的問題以前曾被問過,但在我設法找到的那些問題中,沒有一個人問過這個問題。得到了一個符合我想要的答案。

作為記錄,這是我現在使用的語言定義:

\lst定義語言{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{blue}]{間隙}{>},%
    moredelim=[s][\color{red}]{brk}{>},%
    %moredelim=*[l][\顏色{藍色}]{間隙>},%
    %moredelim=*[l][\color{red}]{brk>},%
    敏感=真,%
    更多評論=[l]\#,%
    更多字串=[b]',%
    更多字串=[b]",%
    }%

PS:為了說明我想要的內容,請考慮此圖像,該圖像顯示了上面的示例的外觀(除了上面描述的內容之外,我還將所有用戶輸入設置為斜體):

在此輸入影像描述

答案1

這個listings答案遲了大約一年,但我相信它滿足了您的所有要求。

編輯:修正了與行中間出現的提示「關鍵字」相關的錯誤。

所需輸出

期望的輸出

獲得的輸出

獲得的輸出

程式碼

\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}

在此輸入影像描述

相關內容