Wie kann ich eine interaktive GAP-Sitzung auf diese Weise hervorheben?

Wie kann ich eine interaktive GAP-Sitzung auf diese Weise hervorheben?

Angenommen, ich möchte eine Bildschirmsitzung in einer Programmiersprache setzen (in meinem Fall GAP, aber es könnte genauso gut Python, BASH oder etwas anderes mit einer interaktiven Leseaufforderung sein). Auf meinem Bildschirm könnte also etwa Folgendes angezeigt werden:

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>

Das heißt, es gibt eine Eingabeaufforderung gap>, nach der der Benutzer eine mehrzeilige Eingabe macht. Danach folgt eine Ausgabezeile und dann eine weitere Eingabeaufforderung gap>. Dies wiederholt sich, bis ein Befehl einen Fehler auslöst. An diesem Punkt ändert sich die Eingabeaufforderung zu brk>.

Ich möchte dielistingsPaket (oder etwas anderes) zu

  1. Färben Sie die Eingabeaufforderungen gap>, >, und brk>, beispielsweise blau und rot.
  2. Heben Sie Schlüsselwörter wie for, do, und odhervor, indem Sie sie beispielsweise fett formatieren.
  3. AbernurMarkieren Sie die Schlüsselwörter in Zeilen, die mit einer Eingabeaufforderung beginnen, daher nicht in der Ausgabe meiner Befehle.

Der letzte Punkt bereitet mir Probleme. Ich konnte keine Möglichkeit finden, das zu tun. Das Ergebnis ist oft ziemlich hässlich, wenn Wörter wie and, not, und inals Schlüsselwörter beispielsweise in einer Fehlermeldung hervorgehoben werden.

Es wurden schon früher ähnliche Fragen gestellt, aber von denen, die ich gefunden habe, war keine genau danach gefragt bzw. hat keine Antwort erhalten, die meinen Wünschen entspricht.

Zur Klarstellung, hier ist die Sprachdefinition, die ich derzeit verwende:

\lstdefinelanguage{LÜCKE}{%
    morekeywords=[2]{und,brechen,fortsetzen,machen,elif,sonst,ende,fehlschlagen,falsch,fi,für,%
        Funktion, wenn, in, lokal, mod, nicht, od, oder, rec, wiederholen, zurückgeben, dann, wahr, %
        bis,während},%
    moredelim=[s][\color{blue}]{gap}{>},%
    mehrdelim=[s][\color{red}]{brk}{>},%
    %moredelim=*[l][\color{blue}]{Lücke>},%
    %moredelim=*[l][\color{red}]{brk>},%
    empfindlich=wahr,%
    mehrkommentar=[l]\#,%
    morestring=[b]',%
    morestring=[b]",%
    }%

PS: Um zu verdeutlichen, was ich möchte, betrachten Sie dieses Bild, das zeigt, wie mein Beispiel von oben aussehen könnte (zusätzlich zu dem, was ich oben beschrieben habe, habe ich auch alle Benutzereingaben kursiv gesetzt):

Bildbeschreibung hier eingeben

Antwort1

Diese listingsAntwort kommt etwa ein Jahr zu spät, aber ich glaube, sie deckt alle Ihre Anforderungen ab.

Bearbeiten: Ein Fehler im Zusammenhang mit der Eingabeaufforderung „Schlüsselwörter“ wurde behoben, die mitten in einer Zeile auftrat.

Gewünschte Ausgabe

gewünschte Ausgabe

Erhaltene Ausgabe

erhaltene Ausgabe

Code

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

Antwort2

Der einzige Nachteil ist, dass ich ganze Wörter verarbeite, keine Teilwörter. Daher od;ist ein separates Wort von od. Das kann überwunden werden, aber nicht in diesem MWE. Ich habe Ihre rohe (unformatierte) Sitzungsausgabe in die Datei kopiertSitzung.inund ging von dort weiter.

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

Bildbeschreibung hier eingeben

verwandte Informationen