如何取得清單以僅列印 Matlab 檔案的標題?

如何取得清單以僅列印 Matlab 檔案的標題?

如何提取簡單 matlab 檔案的第一行接下來的幾行以字元%?開頭要提取的行數未知。然後我想用它listingsutf8來顯示提取的程式碼。

matlab 檔案範例:

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

要提取的行:

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

答案1

您可以透過組合相對神秘的listings內部巨集來做到這一點;無需寫入外部文件。為了方便起見,我定義了一個名為 的新布林鍵onlyheader。如果設定了該鍵,則第一個連續註解行區塊(即函數頭)之後的任何輸出都會被刪除。

編輯:該功能已實現0.2 版本matlab-prettifier透過一個名為 的鍵mlonlyheader

MLPR 輸出

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

僅使用listings

列表輸出

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

答案2

以這種方式進行文件處理並不一定最好用 TeX 來處理。最好在 TeX 之外進行處理,然後在 TeX 內使用結果。

該方法(摘自如何將 shell 輸出保存到 LaTeX 中的變數?)是一種妥協。它使用write18TeX 原語來運行 shell 命令,該命令將您查找的輸出保存到臨時檔案中。然後,該臨時檔案將用作清單來源。

我仍在研究是否/如何使用所有 TeX 原語來完成此操作,而不是使用 shell 命令解決方法。

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

結果是

程式碼範例的結果

答案3

filecontents套件僅用於建立要輸入的檔案。

該程式碼獲取所請求的行。它們可以直接操作,也可以與listings套件一起操作。為此,我再次將這些行寫入文件並輸入它們:肯定有一些更簡單、更優雅的東西,但事實證明我完全不熟悉listings. [更新補充\lstset{language=Matlab}]

請注意,此方法不需要 shell 轉義或外部工具。宏\GetHeaderAndDisplayWithListing一次性完成了這項工作。我想清單本身可以透過自訂\lstset,但我只到達了手冊的第 3 頁。

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

輸出(現在使用\lstset{language=Matlab}):

提取帶有清單的行 Matlab

初始答案的輸出(甚至不需要 package listings),使用現在註解掉的\ExtractLinesand \texttt{\ExtractedLines}

提取行

相關內容