TeX - LaTeX Asked by PIC-Nico on August 6, 2020
I was asking myself how I can ease writing of long commands/phrases that are used very often in the exact same way.
Example: How can I write the following:
begin{mdframed}begin{lstlisting}[style=mystyle]
bla bla bla
end{lstlisting}end{mdframed}
In a shorter way like:
mycommand{
bla bla bla
}
Edit:
As requested I will add an update to my origin question below:
Here is the missing style definition:
lstdefinestyle{mystyle}{
language = C,
basicstyle=footnotesizettfamily,
keywordstyle = {color{DarkGreen}bfseries},
morekeywords = {Send,Receive},
mathescape=true,
columns=fullflexible,
prebreak=raisebox{0ex}[0ex][0ex]{ensuremath{rhookswarrow}},
breakindent=0
}
So as you can see I also want to have the option for mathescape inside in order to do stuff like:
mycommand{
bla bla bla $1+2=3$
}
Which should not result into text "$1+2=3$"
but into 1+2=3
as math interpretation.
I'd not recommend making the mdframed
–lstlisting
into a command with argument instead of a proper environment.
For one thing, line breaks cannot be preserved in the argument version.
I'd also suggest tcolorbox
rather than mdframed
, because it offers better integration with listings
. Anyway, you can do
documentclass{article}
usepackage{listings,mdframed}
lstnewenvironment{mylisting}
{mdframedlstset{}}
{endmdframed}
begin{document}
begin{mylisting}
bla bla bla
end{mylisting}
end{document}
Note the auxiliary commands mdframed
and endmdframed
, otherwise the lstnewenvironment
declaration would produce something that doesn't work at all. I removed style=mystyle
because I have no idea of how the style is defined. Add all the necessary options you need in the argument of lstset
.
documentclass{article}
usepackage{listings,mdframed}
usepackage[svgnames]{xcolor}
lstdefinestyle{tmstyle}{
language = C,
basicstyle=footnotesizettfamily,
keywordstyle = {color{DarkGreen}bfseries},
morekeywords = {Send,Receive},
mathescape=true,
columns=fullflexible,
prebreak=raisebox{0ex}[0ex][0ex]{ensuremath{rhookswarrow}},
breakindent=0,
}
lstnewenvironment{mylisting}
{mdframedlstset{style=tmstyle}}
{endmdframed}
begin{document}
begin{mylisting}
Send bla bla bla $1+2=3$
end{mylisting}
end{document}
Correct answer by egreg on August 6, 2020
In general, you can do something like this:
newcommand{mycommand}[1]{
begin{environment}
#1
end{environment}
}
However, the lstlisting
environment relies on changing category codes to work so the category codes won't be what they need to be when the argument is expanded.
Fortunately, this is something that was foreseen as an issue. Instead, you'll need to use the lstnewenvironment
command so you could do something like:
lstnewenvironment{mylisting}
{begin{mdframed}lstset{style=mystyle}}
{end{mdframed}}
and then use it with
begin{mylisting}
bla bla bla
end{mylisting}
Answered by Don Hosek on August 6, 2020
With the upcoming LaTeX kernel, due to be released in October, you can add to 'hooks' to achieve this. For example
documentclass{article}
usepackage{listings}
usepackage{mdframed}
AddToHook{env/lstlisting/before}{begin{mdframed}}
AddToHook{env/lstlisting/after}{end{mdframed}}
begin{document}
begin{lstlisting}
bla bla bla
end{lstlisting}
end{document}
(You'll need to run e.g. pdflatex-dev
at present for this to work: that uses the pre-release version of the kernel.)
Answered by Joseph Wright on August 6, 2020
As long as mycommand
is used on document-level only, not from within arguments of other macros, not from within definition-texts of other macros, not from within token-registers, not as part of a a moving argument, you can have LaTeX read things as verbatim-arguments and pass these to scantokens
.
But I cannot recommend this because indenting the code that is to be displayed will definitely not be easier this way:
documentclass{article}
usepackage{xparse}
usepackage{listings}
usepackage{mdframed}
lstdefinestyle{mystyle}{%
language = C,
basicstyle=footnotesizettfamily,
keywordstyle = {color{DarkGreen}bfseries},
morekeywords = {Send,Receive},
mathescape=true,
columns=fullflexible,
prebreak=raisebox{0ex}[0ex][0ex]{ensuremath{rhookswarrow}},
breakindent=0
}
newcommandmycommand{%
begingroup
catcode`^^I=12 %
newlinechar=endlinechar
MyReadVerbatimArgument
}%
begingroup
NewDocumentCommandMyReadVerbatimArgument{+v +v}{%
endgroup
NewDocumentCommandMyReadVerbatimArgument{+v}{%
scantokens{endgroup#1##1#2}%
}%
}%
MyReadVerbatimArgument|begin{mdframed}
begin{lstlisting}[style=mystyle]
||
end{lstlisting}
end{mdframed}
%|
begin{document}
mycommand{bla bla bla
bla bla bla
bla bla bla}
end{document}
If you wish, this can be extended to remove a leading endline-character from the entire verbatim-argument if present and a trailing endline-character from the entire verbatim-argument if present.
This way
mycommand{
bla bla bla
bla bla bla
This line is not indented.
bla bla bla
bla bla bla
}
and
mycommand{ bla bla bla
bla bla bla
This line is not indented.
bla bla bla
bla bla bla
}
and
mycommand{
bla bla bla
bla bla bla
This line is not indented.
bla bla bla
bla bla bla}
and
mycommand{ bla bla bla
bla bla bla
This line is not indented.
bla bla bla
bla bla bla}
will all yield the same output.
The tricks for removing a leading/trailing endline-character, i.e., a leading/trailing ^^M
-character of category code 12(other)=a leading/trailing return-character of category code 12(other) are the same as the tricks for a removing leading/trailing space-token from a macro-argument.
With the helper-macros just don't use space-tokens as argument-delimiters but use explicit return-character-tokens of category code 12(other).
The latter (removal of a leading/trailing space) is discussed in Exercise 15 of Michael Downes' "Around the Bend"-collection of TeX challenges.
A pdf-file by Peter Wilson containing all challenges/exercises and all solutions/answers belonging to the "Around the Bend"-collection of TeX challenges can be found at:
http://mirrors.ctan.org/info/challenges/AroBend/AroundTheBend.pdf
The original text of the challenge/exercise can be found at:
http://mirrors.ctan.org/info/challenges/aro-bend/exercise.015
The original text of the discussion of submitted solutions/answers can be found at:
http://mirrors.ctan.org/info/challenges/aro-bend/answer.015
documentclass{article}
usepackage{xparse}
usepackage{listings}
usepackage{mdframed}
%%/////////////////////////////////////////////////////////////////////////////
%% Begin of code for UDRemoveLeadingNTrailingEndl
%%/////////////////////////////////////////////////////////////////////////////
makeatletter
%%=============================================================================
%% Check whether argument is empty:
%%=============================================================================
%% UD@CheckWhetherNull{<Argument which is to be checked>}%
%% {<Tokens to be delivered in case that argument
%% which is to be checked is empty>}%
%% {<Tokens to be delivered in case that argument
%% which is to be checked is not empty>}%
newcommandUD@CheckWhetherNull[1]{%
romannumeral0ifrelaxdetokenize{#1}relax
expandafter@firstoftwoelseexpandafter@secondoftwofi
{@firstoftwo{expandafter}{} @firstoftwo}%
{@firstoftwo{expandafter}{} @secondoftwo}%
}%
%%=============================================================================
%% Exchange arguments
%%=============================================================================
newcommandUDExchange[2]{#2#1}%
begingroup
% Dummy-definition, will be overridden. Is used only to get ^^M of
% category code 12(other) as #1 into subsequent definition-texts:
NewDocumentCommandUD@CheckWhetherLeadingEndl{+m}{%
endgroup
%%===========================================================================
%% Check whether_verbatimized_ argument starts with a endline-character
%%===========================================================================
%% UD@CheckWhetherLeadingEndl{<Argument which is to be checked>}%
%% {<Tokens to be delivered in case <argument
%% which is to be checked>'s 1st token is a
%% endline-charactern>}%
%% {<Tokens to be delivered in case <argument
%% which is to be checked>'s 1st token is not
%% a endline-character>}%
newcommandUD@CheckWhetherLeadingEndl[1]{%
UD@@CheckWhetherLeadingEndlUD@SelDom##1UD@SelDom#1UD@@SelDom
}%
@ifdefinableUD@@CheckWhetherLeadingEndl{%
longdefUD@@CheckWhetherLeadingEndl##1UD@SelDom#1##2UD@@SelDom{%
UD@CheckWhetherNull{##2}{@secondoftwo}{@firstoftwo}%
}%
}%
%%===========================================================================
%% Remove one leading endline-character from _verbatimized_ argument
%%===========================================================================
@ifdefinableUD@@TrimLeadingEndl{longdefUD@@TrimLeadingEndl#1{}}%
%%===========================================================================
%% Check whether _verbatimized_ argument ends with a endline-character
%%===========================================================================
%% UD@CheckWhetherTrailingEndl{<Argument which is to be checked>}%
%% {<Tokens to be delivered in case <argument
%% which is to be checked>'s last token is a
%% endline-charactern>}%
%% {<Tokens to be delivered in case <argument
%% which is to be checked>'s last token is not
%% a endline-character>}%
newcommandUD@CheckWhetherTrailingEndl[1]{%
UD@@CheckWhetherTrailingEndl##1UD@SelDom#1UD@SelDomUD@@SelDom
}%
@ifdefinableUD@@CheckWhetherTrailingEndl{%
longdefUD@@CheckWhetherTrailingEndl##1#1UD@SelDom##2UD@@SelDom{%
UD@CheckWhetherNull{##2}{@secondoftwo}{@firstoftwo}%
}%
}%
%%===========================================================================
%% Remove one trailing endline-character from _verbatimized_ argument
%%===========================================================================
newcommandUD@TrimTrailingEndl[1]{UD@@TrimTrailingEndl##1UD@SelDom}%
@ifdefinableUD@@TrimTrailingEndl{%
longdefUD@@TrimTrailingEndl##1#1UD@SelDom{##1}%
}%
%%===========================================================================
%% Remove one leading and one trailing endline-character from _verbatimized_
%% argument if present. Due to romannumeral0-expansion the result is
%% delivered in 2 expansion-steps:
%%===========================================================================
newcommandUDRemoveLeadingNTrailingEndl[1]{%
romannumeral0%
UD@CheckWhetherLeadingEndl{##1}{%
UD@CheckWhetherTrailingEndl{##1}{%
UDExchange{ }{%
expandafterexpandafterexpandafterexpandafter
expandafterexpandafterexpandafter
}%
expandafterUD@TrimTrailingEndlexpandafter{UD@@TrimLeadingEndl##1}%
}{%
UDExchange{ }{expandafter}%
UD@@TrimLeadingEndl##1%
}%
}{%
UD@CheckWhetherTrailingEndl{##1}{%
UDExchange{ }{expandafterexpandafterexpandafter}%
UD@TrimTrailingEndl{##1}%
}{ ##1}%
}%
}%
}%
%%-----------------------------------------------------------------------------
%% Now let's change the catcode of ^^M and then call the dummy-definition
%% of UD@CheckWhetherLeadingEndl so that it can fetch the catcode-12-^^M,
%% close the group, override itself and define all those macros where that
%% catcode-12-^^M is needed:
catcode`^^M=12 %
UD@CheckWhetherLeadingEndl{^^M}%
makeatother
%%/////////////////////////////////////////////////////////////////////////////
%% End of code for UDRemoveLeadingNTrailingEndl
%%/////////////////////////////////////////////////////////////////////////////
lstdefinestyle{mystyle}{
language = C,
basicstyle=footnotesizettfamily,
keywordstyle = {color{DarkGreen}bfseries},
morekeywords = {Send,Receive},
mathescape=true,
columns=fullflexible,
prebreak=raisebox{0ex}[0ex][0ex]{ensuremath{rhookswarrow}},
breakindent=0
}
newcommandmycommand{%
begingroup
catcode`^^I=12 %
newlinechar=endlinechar
MyReadVerbatimArgument
}%
begingroup
NewDocumentCommandMyReadVerbatimArgument{+v +v}{%
endgroup
NewDocumentCommandMyReadVerbatimArgument{+v}{%
scantokensexpandafter{romannumeral0%
expandafterexpandafterexpandafterUDExchange
expandafterexpandafterexpandafter{%
UDRemoveLeadingNTrailingEndl{##1}%
}{ endgroup#1}#2}%
}%
}%
MyReadVerbatimArgument|begin{mdframed}
begin{lstlisting}[style=mystyle]
||
end{lstlisting}
end{mdframed}
%|
begin{document}
mycommand{
bla bla bla
bla bla bla
This line is not indented.
bla bla bla
bla bla bla
}
mycommand{ bla bla bla
bla bla bla
This line is not indented.
bla bla bla
bla bla bla
}
mycommand{
bla bla bla
bla bla bla
This line is not indented.
bla bla bla
bla bla bla}
mycommand{ bla bla bla
bla bla bla
This line is not indented.
bla bla bla
bla bla bla}
end{document}
Some remarks about subtleties with the ways in which TeX works:
TeX's mechanism for reading and tokenizing input in any case discards all space-characters at the end of a line of .tex-input and then adds a character whose coding-point-number in the TeX-engine's internal character-encoding scheme (which either is ASCII with traditional engines or is UTF‑8/Unicode with engines based on XeTeX/LuaTeX; ASCII can be considered a strict subset of Unicode) equals the value of the integer-parameter endlinechar
before starting to tokenize that line. Usually the value of the endlinechar
-parameter is 13, denoting the return-character which in TeX's ^^
-notation is also accessible as ^^M
. (M is the 13th letter in the latin alphabet.)
This implies that .tex-input-lines containing space-characters (ASCII 32(dec)/Unicode 32(dec)) only will in any case be treated as empty lines.
This also implies that with .tex-input-lines ending with space-characters (ASCII 32(dec)/Unicode 32(dec)) these space-characters will be discarded.
You can test this by putting lines of text that end with a sequence of space-characters into the verbatim*
-environment.
Answered by Ulrich Diez on August 6, 2020
Get help from others!
Recent Questions
Recent Answers
© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP