2

I have been following this topic about using \NewDocuentCommand with lstlisting and the accepted answer is nice except it is too big and it doesn't quite work for me.

I came up with this example to test xparse:

\documentclass{article}
\usepackage{xparse}
\usepackage{listings}

\ExplSyntaxOn \NewDocumentCommand{\code}{m +v}{ \begin{lstlisting}[style=#1,numbers=none,xleftmargin=0.35cm,framesep=0mm] #2 \end{lstlisting} } \ExplSyntaxOff

\begin{document}

\code{C}{ int x = 200; unsigned int y = 0; }

\end{document}

Like stated in the CTAN xparse documentation I first used m as a normal parameter and then +v as a multiline verbatim parameter, but it fails. It looks like I am still missing something...

Henri Menke
  • 109,596
71GA
  • 3,573

1 Answers1

5

You can just use Bruno's solution from the linked question (pretty smart I think).

\documentclass{article}
\usepackage{listings}
\usepackage{xparse}

\ExplSyntaxOn \NewDocumentCommand{\code}{m +v}{ \newlinechar=\endlinechar \exp_args:Nx \scantokens { \string\begin{lstlisting}[\unexpanded{language=#1,numbers=none,xleftmargin=0.35cm,framesep=0mm}] #2 \string\end{lstlisting} } } \ExplSyntaxOff

\begin{document}

\code{C}{ int x = 200; unsigned int y = 0; }

\end{document}

enter image description here


But please, just use a new environment instead.

\documentclass{article}
\pagestyle{empty}
\usepackage{listings}

\lstnewenvironment{code}[1]{\lstset{language=#1,numbers=none,xleftmargin=0.35cm,framesep=0mm}}{}

\begin{document}

\begin{code}{C} int x = 200; unsigned int y = 0; \end{code}

\end{document}

Output is similar.

Henri Menke
  • 109,596
  • Thank you for the answer. One more thing is bugging me. In either of the cases you provided, code is moved one tab to the right if I move source code \begin{code}...\end{code} one tab right. So source code position affects the compiled code position. Any idea on how to solve this? – 71GA Jun 21 '17 at 08:47
  • @71GA See the gobble option in the documentation. – Henri Menke Jun 21 '17 at 09:22
  • @ Henri Menke In the first solution, if the content of the second argument(+v) locates at the same line where \code{ is, this part of content will not be typeset. Why and how to deal with that? – lyl Jul 26 '22 at 13:26
  • @lyl lstlisting environment ignores the content on its first line as well, so no surprise here. To deal with it insert an explicit ^^J at the end of the lines. – user202729 Jul 27 '22 at 04:29
  • @user202729 I tried with the above example of the first solution like this ... unsigned int y = 0; ^^J, but only get ... unsigned int y = 0; ^^J – lyl Jul 27 '22 at 04:40
  • @lyl No, insert in the command definition. Ensure that the ^^J get catcode other. \iow_newline: works as well. – user202729 Jul 27 '22 at 05:37
  • @user202729 Thank you for this wonderful proposal! And \code{% ... causes error. Why and how to do that? – lyl Jul 27 '22 at 05:50
  • @HenriMenke You forgot the \newlinechar=\endlinechar. (fortunately lstlisting happily ignores it in this case) – user202729 Jul 27 '22 at 05:56
  • @lyl Because of the above. – user202729 Jul 27 '22 at 05:56
  • @user202729 @HenriMenke It seems that combination of \newlinechar=\endlinechar and ^^J causes error. And \code{% ... causes the first line(int x = 200;) disappear. – lyl Jul 28 '22 at 08:17
  • @lyl Do understand what code does instead of just test out random things. By default xparse uses char 13 to separate lines, but to write to file/scantokens you need char \newlinechar which is 10 by default. Anyway "how to keep first line" isn't really in the focus of this question. – user202729 Jul 28 '22 at 08:24