创建新命令时出现编译错误

创建新命令时出现编译错误

我正在尝试操纵我在互联网上找到的环境,在 GUIT 论坛. 这是最小示例

\documentclass[a4paper,10pt,twoside,openright,titlepage,fleqn,headinclude,footinclude,BCOR5mm,numbers=noenddot,cleardoublepage=empty,captions=tableheading]{scrreprt}
\usepackage[T1]{fontenc}
\usepackage[utf8]{inputenc}
\usepackage[italian]{babel}
\usepackage{amsmath,amsfonts}
\usepackage{framed,color,lipsum}
\usepackage{listings}

\newlength\sidebar
 \newlength\envrule
 \newlength\envborder
 \setlength\sidebar{1.5mm}
 \setlength\envrule{0.4pt}
 \setlength\envborder{2.5mm}

\makeatletter
 \long\def\fboxs#1{%
   \leavevmode
   \setbox\@tempboxa\hbox{%
     \color@begingroup
       \kern\fboxsep{#1}\kern\fboxsep
     \color@endgroup}%
   \@frames@x\relax}
 \def\frameboxs{%
   \@ifnextchar(%)
     \@framepicbox{\@ifnextchar[\@frameboxs\fboxs}}
 \def\@frameboxs[#1]{%
   \@ifnextchar[%]
     {\@iframeboxs[#1]}%
     {\@iframeboxs[#1][c]}}
 \long\def\@iframeboxs[#1][#2]#3{%
   \leavevmode
   \@begin@tempboxa\hbox{#3}%
     \setlength\@tempdima{#1}%
     \setbox\@tempboxa\hb@xt@\@tempdima
          {\kern\fboxsep\csname bm@#2\endcsname\kern\fboxsep}%
     \@frames@x{\kern-\fboxrule}%
   \@end@tempboxa}
 \def\@frames@x#1{%
   \@tempdima\fboxrule
   \advance\@tempdima\fboxsep
   \advance\@tempdima\dp\@tempboxa
   \hbox{%
     \lower\@tempdima\hbox{%
       \vbox{%
         %\hrule\@height\fboxrule
         \hbox{%
          \vrule\@width\fboxrule
           #1%
           \vbox{%
             \vskip\fboxsep
             \box\@tempboxa
             \vskip\fboxsep}%
           #1%
           }%\vrule\@width\fboxrule}%
         }%\hrule\@height\fboxrule}%
                           }%
         }%
 }
 \def\esefcolorbox#1#{\esecolor@fbox{#1}}
 \def\esecolor@fbox#1#2#3{%
   \color@b@x{\fboxsep\z@\color#1{#2}\fboxs}{\color#1{#3}}}
 \makeatother


 \definecolor{exampleborder}{rgb}{0,0,.7}
 \definecolor{examplebg}{rgb}{.9,.9,1}
 \definecolor{statementborder}{rgb}{.9,0,0}
 \definecolor{statementbg}{rgb}{1,.9,.9}

 \newenvironment{eseframed}{%
   \def\FrameCommand{\fboxrule=\the\sidebar  \fboxsep=\the\envborder%
   \esefcolorbox{exampleborder}{examplebg}}%
   \MakeFramed{\FrameRestore}}%
  {\endMakeFramed}

 \newcounter{codeblock}
 \numberwithin{codeblock}{section}
 \renewcommand{\thecodeblock}{\thesection.\arabic{codeblock}}

 %%% CODE ENVIRONMENT. PUT TEXT INTO COLORED FRAME %%%
 \newenvironment{codeblock}
 {\par\medskip\refstepcounter{codeblock}%
 \hbox{%
 \fboxsep=\the\sidebar\hspace{-\envborder}\hspace{-.5\sidebar}%
 \colorbox{exampleborder}{%
 \hspace{\envborder}\footnotesize\sffamily\bfseries%
 \textcolor{white}{Code\enspace\thecodeblock\hspace{\envborder}}
 }
 }
 \nointerlineskip\vspace{-\topsep}%
 \begin{eseframed}\noindent\ignorespaces%
 }
 {\end{eseframed}\vspace{-\baselineskip}\medskip}



\begin{document}
\begin{codeblock}
  \lipsum[2]
\end{codeblock}
\end{document}

现在,我想创建一个命令,它使用 listing 包获取一个 .cpp 文件并将其插入到此块中。我修改此环境以使其具有一个可选参数,该参数将是文件的名称(将其作为标题),然后在新命令中使用修改后的环境。这是我的新最小代码:

\documentclass[a4paper,10pt,twoside,openright,titlepage,fleqn,headinclude,footinclude,BCOR5mm,numbers=noenddot,cleardoublepage=empty,captions=tableheading]{scrreprt}
\usepackage[T1]{fontenc}
\usepackage[utf8]{inputenc}
\usepackage[italian]{babel}
\usepackage{amsmath,amsfonts}
\usepackage{framed,color,lipsum}
\usepackage{listings}

\newlength\sidebar
 \newlength\envrule
 \newlength\envborder
 \setlength\sidebar{1.5mm}
 \setlength\envrule{0.4pt}
 \setlength\envborder{2.5mm}

\makeatletter
 \long\def\fboxs#1{%
   \leavevmode
   \setbox\@tempboxa\hbox{%
     \color@begingroup
       \kern\fboxsep{#1}\kern\fboxsep
     \color@endgroup}%
   \@frames@x\relax}
 \def\frameboxs{%
   \@ifnextchar(%)
     \@framepicbox{\@ifnextchar[\@frameboxs\fboxs}}
 \def\@frameboxs[#1]{%
   \@ifnextchar[%]
     {\@iframeboxs[#1]}%
     {\@iframeboxs[#1][c]}}
 \long\def\@iframeboxs[#1][#2]#3{%
   \leavevmode
   \@begin@tempboxa\hbox{#3}%
     \setlength\@tempdima{#1}%
     \setbox\@tempboxa\hb@xt@\@tempdima
          {\kern\fboxsep\csname bm@#2\endcsname\kern\fboxsep}%
     \@frames@x{\kern-\fboxrule}%
   \@end@tempboxa}
 \def\@frames@x#1{%
   \@tempdima\fboxrule
   \advance\@tempdima\fboxsep
   \advance\@tempdima\dp\@tempboxa
   \hbox{%
     \lower\@tempdima\hbox{%
       \vbox{%
         %\hrule\@height\fboxrule
         \hbox{%
          \vrule\@width\fboxrule
           #1%
           \vbox{%
             \vskip\fboxsep
             \box\@tempboxa
             \vskip\fboxsep}%
           #1%
           }%\vrule\@width\fboxrule}%
         }%\hrule\@height\fboxrule}%
                           }%
         }%
 }
 \def\esefcolorbox#1#{\esecolor@fbox{#1}}
 \def\esecolor@fbox#1#2#3{%
   \color@b@x{\fboxsep\z@\color#1{#2}\fboxs}{\color#1{#3}}}
 \makeatother


 \definecolor{exampleborder}{rgb}{0,0,.7}
 \definecolor{examplebg}{rgb}{.9,.9,1}
 \definecolor{statementborder}{rgb}{.9,0,0}
 \definecolor{statementbg}{rgb}{1,.9,.9}

 \newenvironment{eseframed}{%
   \def\FrameCommand{\fboxrule=\the\sidebar  \fboxsep=\the\envborder%
   \esefcolorbox{exampleborder}{examplebg}}%
   \MakeFramed{\FrameRestore}}%
  {\endMakeFramed}

 \newcounter{codeblock}
 \numberwithin{codeblock}{section}
 \renewcommand{\thecodeblock}{\thesection.\arabic{codeblock}}

 %%% MODIFIED ENVIRONMENT WITH ARGUMENT %%%
 \newenvironment{codeblock}[1]
 {\par\medskip\refstepcounter{codeblock}%
 \hbox{%
 \fboxsep=\the\sidebar\hspace{-\envborder}\hspace{-.5\sidebar}%
 \colorbox{exampleborder}{%
 \hspace{\envborder}\footnotesize\sffamily\bfseries%
 \textcolor{white}{#1\enspace\thecodeblock\hspace{\envborder}}
 }
 }
 \nointerlineskip\vspace{-\topsep}%
 \begin{eseframed}\noindent\ignorespaces%
 }
 {\end{eseframed}\vspace{-\baselineskip}\medskip}


 %%% COMMAND THAT USE PREVIOUS ENVIRONMENT AND LISTING ENVIRONMENT %%%
 \newcommand{\sourcecode}[1]{\begin{codeblock}[#1]%
 \begin{lstlisting}%
 \input{#1}%
 \end{lstlisting}%
 \end{codeblock}}



\begin{document}
\sourcecode{code/hello_world.cpp}
\end{document}

命令 \sourcecode 将文件名作为输入,然后将其文本包含到 codeblock/lstlisting 环境中。当我尝试编译它时,无论如何,我收到以下错误:

! Missing $ inserted.
<inserted text> 
                $
l.106     \sourcecode{code/hello_world.cpp}

? 
! Emergency stop.
<inserted text> 
                $
l.106     \sourcecode{code/hello_world.cpp}

我不知道我做错了什么。任何帮助创建正确命令的帮助都会很感激。请帮帮我。

提前感谢您的回复。

答案1

将定义改为

%%% COMMAND THAT USE PREVIOUS ENVIRONMENT AND LISTING ENVIRONMENT %%%
\newcommand{\sourcecode}[1]{%
  \begin{codeblock}{#1}%
  \lstinputlisting{#1}%
  \end{codeblock}}

请注意后面的是括号\begin{codeblock}而不是方括号。

如果文件名包含下划线,则保护它:

\sourcecode{file\string_with\string_underscores.cpp}

抱歉,但调试这么大一段代码是件很困难的事。

问题是由于您试图打印带有下划线的字符串,如果下划线没有以某种方式受到保护,这是不可能的。

一个出路可能是

\newcommand{\sourcecode}{\begingroup\catcode`_=12 \dosourcecode}
\newcommand{\dosourcecode}[1]{%
  \begin{codeblock}{#1}%
  \lstinputlisting{#1}%
  \end{codeblock}\endgroup}

因此,当下划线变成可打印字符时,就会推迟读取参数。

或者,正如 Heiko 所建议的那样,

\newcommand{\sourcecode}[1]{%
  \begin{codeblock}{\detokenize{#1}}%
  \lstinputlisting{#1}%
  \end{codeblock}\endgroup}

相关内容