Wie kann man erreichen, dass in Listen nur der Header einer Matlab-Datei gedruckt wird?

Wie kann man erreichen, dass in Listen nur der Header einer Matlab-Datei gedruckt wird?

So extrahieren Sie die erste Zeile einer einfachen Matlab-DateiUnddie folgenden Zeilen beginnen direkt danach mit dem Zeichen %? Die Anzahl der zu extrahierenden Zeilen ist unbekannt. Dann möchte ich verwenden, listingsutf8um den extrahierten Code anzuzeigen.

Beispiel einer Matlab-Datei:

function myfunction(args)
% Comments
% about the function
% with an unknown number of lines
command1(); % another comment
command2();
% another comment
command3();
end

zu extrahierende Zeilen:

function myfunction(args)
% Comments
% about the function
% with an unknown number of lines

Antwort1

Sie können das mit einer Kombination relativ geheimnisvoller listingsinterner Makros tun; es ist nicht nötig, in eine externe Datei zu schreiben. Der Einfachheit halber habe ich einen neuen booleschen Schlüssel namens definiert onlyheader. Wenn dieser Schlüssel gesetzt ist, wird jede Ausgabe nach dem ersten zusammenhängenden Block von Kommentarzeilen (also dem Funktionskopf) gelöscht.

Bearbeiten: Diese Funktion wurde implementiert inVersion 0.2 vonmatlab-prettifierüber eine Taste namens mlonlyheader.

mlpr-Ausgabe

\documentclass{article}

\usepackage[T1]{fontenc}

% --- write to file ---
\usepackage{filecontents}
\begin{filecontents*}{code.txt}
function myfunction(args)
%MYFUNCTION One-line description goes here
% Comments
% about the function
% with an unknown number of lines
[ 2 3 4 ]
command1(); % another comment
command2();
% another comment
command3();
end
\end{filecontents*}

\usepackage[framed]{matlab-prettifier}

\lstset{style = Matlab-editor}

\begin{document}

\lstinputlisting
  [caption  = {\texttt{mlonlyheader=false}}]
  {code.txt}

\lstinputlisting
[
  caption    = {\texttt{mlonlyheader=true}},
  mlonlyheader = true,
]{code.txt}

\end{document}

Nur mitlistings

Listings-Ausgabe

\documentclass{article}

% --- write to file ---
\usepackage{filecontents}
\begin{filecontents*}{code.txt}
function myfunction(args)
%MYFUNCTION One-line description goes here
% Comments
% about the function
% with an unknown number of lines
[ 2 3 4 ]
command1(); % another comment
command2();
% another comment
command3();
end
\end{filecontents*}

\usepackage{listings}

\makeatletter
% We define a new boolean key for convenience
\lst@Key{onlyheader}{false}[t]{\lstKV@SetIf{#1}\lst@ifonlyheader}

% We'll use this switch to keep track of where we are
\newif\iffirstnoncommentline

% --- Careful! the following modifications are global ---
% (i.e. will apply to all listings)
\lst@AddToHook{PreInit}{\global\firstnoncommentlinetrue}
\lst@AddToHook{Output}{\dropOutput}

\lst@AddToHook{OutputOther}{\dropOutput}

% helper macro
\newcommand\dropOutput
{%
  \lst@ifonlyheader%
    \ifnum\lst@lineno>1%  
      \lst@ifLmode%
      \else
        \iffirstnoncommentline%
          \lst@EnterMode\lst@Pmode{}%
          \lst@BeginDropOutput\lst@Pmode%
        \fi
        \global\firstnoncommentlinefalse%
      \fi
    \fi
  \fi
}
\makeatother

\lstset{
  language = Matlab,
  frame    = single,
}

\begin{document}

\lstinputlisting
  [caption  = {\texttt{onlyheader=false}}]
  {code.txt}

\lstinputlisting
[
  caption    = {\texttt{onlyheader=true}},
  onlyheader = true,
]{code.txt}

\lstinputlisting
[
  caption    = {\texttt{onlyheader=true}},
  onlyheader = true,
]{code.txt}

\end{document}

Antwort2

Die Dateiverwaltung auf diese Weise ist nicht unbedingt etwas, das am besten mit TeX erledigt werden kann. Es wäre viel besser, die Verarbeitung außerhalb von TeX durchzuführen und das Ergebnis dann in TeX zu verwenden.

Diese Methode (auszugsweise ausWie kann ich Shell-Ausgabe in einer Variablen in LaTeX speichern?) ist ein gewisser Kompromiss. Es verwendet das write18TeX-Primitiv, um einen Shell-Befehl auszuführen, der die gewünschte Ausgabe in einer temporären Datei speichert. Diese temporäre Datei wird dann als Auflistungsquelle verwendet.

Ich arbeite noch daran, ob und wie dies mit allen TeX-Grundelementen gemacht werden kann, ohne den Workaround mit Shell-Befehlen zu verwenden.

\documentclass{article}
\usepackage{listingsutf8}    
\begin{document}

% Execute a sed script to identify the lines that are desired
% from the top of your code file (note that the % sign has to be 
% escaped in this line, due to LaTeX interpreting it differently)
% This command was developed with sed on Mac OSX 10.9
\immediate\write18{sed -ne '1 h; 2,/^[^\%]/ {x;p;}' myfunction.txt > '\jobname.temp'}
                % Sed command:
                % 1 h; Take first line, hold in buffer
                % 2,/^[^%]/ Lines 2 through the next line that doesn't
                %     begin with a %
                % ... {x;p;}  Hold current line in buffer (swap with previous)
                %             and then print out previously held line
                % This results in line 1 + next continuous lines beginning with % printed

% Set language -- looked like MATLAB was a prime candidate given the syntax
\lstset{language=Matlab}

% Print out original function
Contents of \verb!myfunction.txt!:
\lstinputlisting{myfunction.txt}

% Print out newly created file
Dynamic header of \verb!myfunction.txt!:
\lstinputlisting{\jobname.temp}

% Clean up temporary file
\immediate\write18{rm -f -- '\jobname.temp'}

\end{document}

Das Ergebnis ist

Ergebnis des Codebeispiels

Antwort3

Das filecontentsPaket dient ausschließlich der Erstellung der einzugebenden Dateien.

Der Code holt sich die gewünschten Zeilen. Diese können direkt oder mit dem listingsPaket bearbeitet werden. Dazu schreibe ich die Zeilen nochmal in eine Datei und gebe sie ein: es geht sicher einfacher und eleganter, aber ich kenne mich damit nicht aus listings. [Das Update fügt hinzu \lstset{language=Matlab}]

Beachten Sie, dass bei diesem Ansatz weder Shell-Escape noch externe Tools erforderlich sind. Das Makro \GetHeaderAndDisplayWithListingerledigt die Aufgabe in einem Durchgang. Ich vermute, dass die Auflistung selbst anpassbar ist, \lstsetaber ich bin erst bei Seite 3 des Handbuchs angekommen.

\documentclass{article}

\usepackage{listings}

\usepackage{filecontents}% only to create files for this example
\begin{filecontents*}{badboysamplefile.txt}
function myfunction(args)
% Comments
% about the function
% with an unknown number of lines
command1(); % another comment
command2();
% another comment
command3();
end
\end{filecontents*}

\begin{filecontents*}{badboyotherfile.txt}
function myfunction(args)
% 1 Comments
% 2 about the function
% 3 with an unknown number of lines
% 4 Comments
% 5 about the function
% 6 with an unknown number of lines
% 7 comments
% 1 Comments
% 2 about the function
% 3 with an unknown number of lines
% 4 Comments
% 5 about the function
% 6 with an unknown number of lines
% 7 comments
command1(); % another comment
command2();
% another comment
command3();
end
\end{filecontents*}

\makeatletter

\def\ExtractLines #1{%
 \newread\badboy 
 \openin\badboy #1\relax 
 \edef\ELrestore{\endlinechar\the\endlinechar\relax\catcode`\%=14 }%
 \endlinechar -1
 \ExtractLines@
 \ELrestore
 %\show\ELrestore
}%

\def\ExtractLines@ {%
    \ifeof\badboy 
       \def\ExtractedLines{}\closein\badboy
    \else
      \read\badboy to \ExtractedLines
      \edef\ExtractedLines{\detokenize\expandafter{\ExtractedLines}}%
      \catcode`\% 12
      \ExtractLines@@
    \fi
}

\def\ELSEP{\par}
\def\ELgetfirst #1#2\ELgetfirst {\def\ELFirst{#1}}

\catcode`\% 12
\catcode`! 14
\def\ExtractLines@@ {!
  \ifeof\badboy \closein\badboy\else
    \read\badboy to \Extract@OneLine
    \edef\Extract@@OneLine{\detokenize\expandafter{\Extract@OneLine}}!
    \expandafter\ELgetfirst\Extract@@OneLine.\ELgetfirst
    \if %\ELFirst 
      \expandafter\expandafter\expandafter
      \def\expandafter\expandafter\expandafter
      \ExtractedLines\expandafter\expandafter\expandafter
           {\expandafter\ExtractedLines\expandafter\ELSEP\Extract@@OneLine}!
      \expandafter\expandafter\expandafter
      \ExtractLines@@
    \else
       \closein\badboy
    \fi
  \fi
}
\catcode`% 14
\catcode`\! 12
\makeatother

\newcommand\GetHeaderAndDisplayWithListing [1]{%
   \def\ELSEP {^^J}%
   \ExtractLines {#1}%
   \newwrite\badboy
   \immediate\openout\badboy badboy-extracted.temp\relax
   \immediate\write\badboy {\ExtractedLines}%
   \immediate\closeout\badboy\relax
   \lstinputlisting {badboy-extracted.temp}%
   \def\ELSEP {\par}% just in case one wants to use \ExtractLines
   % and the produced \ExtractedLines directly
}

\begin{document}
% added in update:
\lstset{language=Matlab}

First file with \verb|listings|:\medskip

\GetHeaderAndDisplayWithListing {badboysamplefile.txt}

% \ExtractLines {badboysamplefile.txt}%
%  \texttt{\ExtractedLines}
% \bigskip

And the second file with \verb|listings|:\medskip

% \ExtractLines {badboyotherfile.txt}%
% \texttt{\ExtractedLines}

\GetHeaderAndDisplayWithListing {badboyotherfile.txt}

\end{document}

Die Ausgabe (jetzt mit \lstset{language=Matlab}):

extrahierte Zeilen mit Auflistungen Matlab

Die Ausgabe der ursprünglichen Antwort (für die nicht einmal das Paket erforderlich war listings) unter Verwendung des jetzt auskommentierten \ExtractLinesund \texttt{\ExtractedLines}:

Zeilen extrahieren

verwandte Informationen