% xlistings.sty % This package is not intended to work with the 'minted'-Package % % Copyright (C) 2024-2026 Florian Sihler % % This work may be distributed and/or modified under the conditions of % the LaTeX Project Public License, either version 1.3c of this license % or (at your option) any later version. The latest version of this % license is in https://www.latex-project.org/lppl.txt and version 1.3c % or later is part of all distributions of LaTeX version 2008 or later. % % This work has the LPPL maintenance status 'maintained'. % The Current Maintainer of this work is Florian Sihler. % % This work consists of the file xlistings.sty, the language definitions % langs/xlistings-*.cfg, and the documentation xlistings-doc.tex. \NeedsTeXFormat{LaTeX2e} \ProvidesPackage{xlistings}[2026/08/17 v1.0.0 extended listings] % TODO: auto fallback to lstlistings % TODO: fail if language is not found! % TODO: allow to post add language specific keywords % TODO: link to doc support like magic haskell \RequirePackage{kvoptions} \SetupKeyvalOptions{family=xlst,prefix=@xlst@} \DeclareBoolOption{print} % in print, ink will be reduced, adapted to gray scale \DeclareComplementaryOption{digital}{print} \DeclareBoolOption[true]{guardspace} % ensure that listings are not broken over pages \DeclareBoolOption{numinpar} % if enabled numbers would be outside of the left margin \DeclareBoolOption[true]{hlnumbers} % highlight numbers \DeclareBoolOption{upshape} % upshape for basic style \DeclareBoolOption{inlinesize} % don't change font? \DeclareBoolOption{highlights} % special (tikz based) highlights \DeclareBoolOption[true]{fakeminted} % use minted for output \DeclareBoolOption{extendednums} % extended number support \DeclareBoolOption{debug} % debug output \DeclareStringOption[default]{style} % the (default) style to use % internals: \newif\ifxlst@lst@lastwas@character@ % last segment was from char-class \newif\ifxlst@lst@lastwas@charkeep@ % in char-mode (pass through) \newif\ifxlst@lst@innumber@ % last segment was a highlighted number \newif\ifxlst@lst@inhex@ % within a 0x-prefixed literal \ProcessKeyvalOptions* \newif\if@xlst@accuspp@available@ % remove line numbers from selection if possible \if@xlst@debug\let\xlst@debug\typeout\else\let\xlst@debug\@gobble\fi \newdimen\xlst@length@lst@numsep \xlst@length@lst@numsep=9\p@ \newdimen\xlst@length@lst@famerule \xlst@length@lst@famerule=.75\p@ \newdimen\xlst@length@lst@xleftmargin \xlst@length@lst@xleftmargin=3\p@ \newdimen\xlst@length@lst@xrightmargin \xlst@length@lst@xrightmargin=3\p@ \RequirePackage{etoolbox} \RequirePackage{xcolor} \RequirePackage{pgfkeys} \def\xlstsetstyle#1{\def\xlst@style@default{#1}} \xlstsetstyle{\@xlst@style} % Listings-Base: \IfFileExists{listingsutf8.sty}{\RequirePackage{listingsutf8}}{\RequirePackage{listings}} \IfFileExists{accsupp.sty}{\RequirePackage{accsupp}\@xlst@accuspp@available@true}{\@xlst@accuspp@available@false}% \RequirePackage{lstautogobble} % in the future we may want to use something like https://tex.stackexchange.com/a/728534 % [* to overwrite + to append] #1 language, #2 overwrite \def\xlstlangoverride{\@ifstar\@xlstlangoverride@overwrite\@xlstlangoverride@append} \def\@xlstlangoverride@overwrite#1#2{\csdef{xlst@@lang@#1}{#2}}% \def\@xlstlangoverride@append#1#2{\csgappto{xlst@@lang@#1}{,#2}}% % #1: language to overwrite \def\xlst@get@overwrites#1{% \ifcsname xlst@@lang@#1\endcsname\csname xlst@@lang@#1\endcsname\else\@empty\fi } % define the lstkey % working with lstset and setting lstkeys broke stuff (realizing this was very painful), so we go the bottom route \define@key{lst}{language addons}{\protected@edef\@tmp{\noexpand\setkeys{lst}{\xlst@get@overwrites{#1}}}\@tmp}% \protected@edef\@tmp{\noexpand \if@xlst@accuspp@available@ \def\xlst@lst@prebreak{\rlap{\BeginAccSupp{method=escape,ActualText={}}\xlst@font@fs@numbers$\hookleftarrow$\EndAccSupp{}}} \else \def\xlst@lst@prebreak{\rlap{\xlst@font@fs@numbers$\hookleftarrow$}} \fi \let\xlst@lst@inline@prebreak\xlst@lst@prebreak \if@xlst@guardspace\RequirePackage{needspace}\fi \if@xlst@highlights\RequirePackage{tikz}\fi \let\xlst@ttfamily\ttfamily \def\xlst@font@fs@numbers{\footnotesize} \def\xlstNumFs#1{\gdef\xlst@font@fs@numbers{#1}} \def\xlst@font@fs@normal{} \newcommand*\lstfs[1][1]{\@ifstar{\@lstfs@star{#1}}{\@lstfs{#1}}} \def\@lstfs@star#1{\protected@edef\@tmp{\noexpand\@lstfs{#1}{\xlst@font@size}}\@tmp} % #1 linespread, #2 font size in pt \def\@lstfs#1#2{% \def\xlst@font@fs@normal{\fontsize{#2}{#2}\linespread{#1}\selectfont}% \ifnum#2>7\protected@edef\xlst@lst@@subfs{\the\numexpr #2-4}\def\xlst@font@fs@numbers{\fontsize\xlst@lst@@subfs\xlst@lst@@subfs\linespread{#1}\selectfont}% \else\def\xlst@font@fs@numbers{\tiny\linespread{#1}}\fi } % Color & Style Definitions \if@xlst@print \definecolor{xlst@colors@border}{HTML}{DDDFE2} \definecolor{xlst@colors@background}{HTML}{FFFFFF}% save ink :D \else \definecolor{xlst@colors@border}{HTML}{EAECF0} \definecolor{xlst@colors@background}{HTML}{FCFBFB} \fi % default palette \definecolor{xlst@colors@lst@keywordA}{RGB}{192,55,100} % e.g.: class, public, static... \colorlet{xlst@colors@lst@keywordB}{xlst@colors@lst@keywordA!75!white} % e.g.: int, double ... \colorlet{xlst@colors@lst@keywordC}{xlst@colors@lst@keywordA!90!black} % e.g.: class-names? \colorlet{xlst@colors@lst@numbers}{teal!80!white} % well, numbers \colorlet{xlst@colors@lst@numprefix}{gray} % the '0x' of '0x2a' \colorlet{xlst@colors@lst@literals}{orange!80!green!60!xlst@colors@lst@keywordA!80!white} % strings and friends \colorlet{xlst@colors@lst@comments}{lightgray!65!gray} % well, comments \colorlet{xlst@colors@lst@highlight}{lime} % sweetspots \colorlet{xlst@colors@lst@command}{xlst@colors@lst@keywordB} % sweetspots \colorlet{xlst@colors@lst@linenumbers}{gray} % define the styling definitions % as we don't know, if 'foreach' is available, we will built our own iter: \def\xlst@lst@style@iter@step#1: #2\@nil{% \ifx!#1!\else \expandafter\def\csname#1\endcsname{#2}% \fi} \def\xlst@lst@style@iter#1,#2\@nil{% \ifx!#1!\else \xlst@lst@style@iter@step xlst@styles@lst@#1\@nil \ifx!#2!\else\xlst@lst@style@iter#2,\@nil\fi\fi} \def\xlstSetStyle#1#2{\expandafter\def\csname xlst@styles@lst@#1\endcsname{#2}} \def\xlst@list@define@styles#1{\xlst@lst@style@iter#1,\@nil} \let\xlstDefineStyles\xlst@list@define@styles % we will write the colors anyway. This way it is easy visible on how to change the % styles. Will define e.g. \xlst@styles@lst@keywo \if@xlst@print \xlst@list@define@styles{% {keywordA: \@declaredcolor{xlst@colors@lst@keywordA}\bfseries},% {keywordB: \@declaredcolor{xlst@colors@lst@keywordB}},% {keywordC: \@declaredcolor{xlst@colors@lst@keywordC}},% {keywordD: \itshape},% {numbers: \@declaredcolor{xlst@colors@lst@numbers}\itshape},% {numprefix: \@declaredcolor{xlst@colors@lst@numprefix}},% {literals: \@declaredcolor{xlst@colors@lst@literals}\itshape},% {comments: \@declaredcolor{xlst@colors@lst@comments}},% \scshape {basic: \xlst@ttfamily},% {command: \@declaredcolor{xlst@colors@lst@command}},% {highlight: \@declaredcolor{xlst@colors@lst@highlight}\itshape},% {linenumbers: \@declaredcolor{xlst@colors@lst@linenumbers}\xlst@font@fs@numbers\sffamily}% } \else \xlst@list@define@styles{% {keywordA: \@declaredcolor{xlst@colors@lst@keywordA}},% {keywordB: \@declaredcolor{xlst@colors@lst@keywordB}},% {keywordC: \@declaredcolor{xlst@colors@lst@keywordC}},% {keywordD: \itshape},% {numbers: \@declaredcolor{xlst@colors@lst@numbers}},% {numprefix: \@declaredcolor{xlst@colors@lst@numprefix}},% {literals: \@declaredcolor{xlst@colors@lst@literals}},% {comments: \@declaredcolor{xlst@colors@lst@comments}},% {basic: \xlst@ttfamily},% {command: \@declaredcolor{xlst@colors@lst@command}},% {linenumbers: \@declaredcolor{xlst@colors@lst@linenumbers}\xlst@font@fs@numbers\sffamily},% {highlight: \@declaredcolor{xlst@colors@lst@highlight}\itshape}% } \fi \if@xlst@upshape \xlst@list@define@styles{{basic: \xlst@ttfamily\upshape},} \fi % Helper Functions \def\xlst@font@size{\the\numexpr\dimexpr\f@size\p@\relax/65536\relax} % We want language specific literate additions: \def\xlst@lst@addToLiterate#1{\protected@edef\lst@literate{\unexpanded\expandafter{\lst@literate}\unexpanded{#1}}} \lst@Key{add to literate}{}{\xlst@lst@addToLiterate{#1}} % If possible we want to make the line numbers unmarkable, so you can copy % code without selecting them: % locally blacklist some numbers \newif\if@xlst@lst@blacklist@is@ghost@ \let\xlstblacklistisghost\@xlst@lst@blacklist@is@ghost@true \let\xlstblacklistispresent\@xlst@lst@blacklist@is@ghost@false \def\xlstblacklistlinenumbers{\@ifstar{\xlstblacklistispresent\@xlst@lst@blacklistlinenumers}{\xlstblacklistisghost\@xlst@lst@blacklistlinenumers}} \def\@xlst@lst@blacklistlinenumers#1{\@for\@num:={#1}\do{\expandafter\let\csname xlst@lst@nl@blacklist@\@num\endcsname\@empty}} % TODO: support for non-integer line markers by not adding stuff if ispresent is true? % we have to keep a different offset for blacklisted and ghost line numbers % 1. we must keep ranges intact and % 2. otherwise the line to be blacklisted would repeat \newcount\c@xlst@lst@blacklisted@linenum@counter \lst@AddToHook{PreInit}{\c@xlst@lst@blacklisted@linenum@counter\z@} \if@xlst@accuspp@available@ \def\xlst@lst@num@consume#1{\@ifundefined{xlst@lst@nl@blacklist@#1}{\BeginAccSupp{method=escape,ActualText={}}\the\numexpr#1+\c@xlst@lst@blacklisted@linenum@counter\EndAccSupp{}}{\if@xlst@lst@blacklist@is@ghost@\global\advance\c@xlst@lst@blacklisted@linenum@counter\m@ne\fi}} \else\def\xlst@lst@num@consume#1{\@ifundefined{xlst@lst@nl@blacklist@#1}{\the\numexpr#1+\c@xlst@lst@blacklisted@linenum@counter}{\if@xlst@lst@blacklist@is@ghost@\global\advance\c@xlst@lst@blacklisted@linenum@counter\m@ne\fi}} \fi % So if possible we will eat the number and produce unmarkable text % Here we will make a small rainbow to present the selected color-theme :D \def\xlst@lst@showstyles@iter#1,#2\@nil{% \ifx!#1!\else {\xlst@style@get{#1}#1\space}% \ifx!#2!\else\xlst@lst@showstyles@iter#2,\@nil\fi% recursion \fi } \def\xlst@lst@showstyles#1{\xlst@lst@showstyles@iter#1,\@nil} \def\xlstStyles{\xlst@lst@showstyles{basic,keywordA,keywordB,keywordC,keywordD,numbers,linenumbers,literals,comments,highlight}} \def\xlst@style@get#1{\xlst@styles@lst@basic\csname xlst@styles@lst@#1\endcsname} \long\def\xlstGet#1#2{\begingroup\xlstGetStyle{#1}#2\endgroup} \let\xlstGetStyle\xlst@style@get \def\xlstSetLeftMargin#1{\setlength{\xlst@length@lst@xleftmargin}{#1}} \def\xlstSetRightMargin#1{\setlength{\xlst@length@lst@xrightmargin}{#1}} \def\xlstSetNumSep#1{\setlength{\xlst@length@lst@numsep}{#1}} \def\xlstSetFrameRule#1{\setlength{\xlst@length@lst@famerule}{#1}} \def\xlstPreBreak#1{\def\xlst@lst@prebreak{#1}} \def\xlstInlinePreBreak#1{\def\xlst@lst@inline@prebreak{#1}} \def\@@xlst@numinpar@length{2em} \if@xlst@numinpar\xlstSetLeftMargin{\@@xlst@numinpar@length}\fi % Handling of automated number-highlighting in listings; % #1 style, #2 code to run if the segment starts a number, #3 the segment \def\xlst@lst@hl@num#1#2#3{\begingroup \ifxlst@lst@lastwas@character@ \global\xlst@lst@lastwas@charkeep@true\xlst@lst@nonum#3\else\global\xlst@lst@lastwas@charkeep@false \ifnum\lst@mode=\lst@Pmode\relax% PMode: Not in any special Mode \xlst@lst@hl@num@{#1}{#2}{#3}% or if keywords are active: \else\lst@ifkeywords\xlst@lst@hl@num@{#1}{#2}{#3}\else\xlst@lst@nonum#3\fi\fi \fi \endgroup} \def\xlst@lst@hl@num@#1#2#3{#2\global\xlst@lst@innumber@true{\xlst@style@get{#1}#3}} \def\xlst@@lst@hl@digit#1{\xlst@lst@hl@num{numbers}\@empty{#1}} % #1 marks the literal as hexadecimal \def\xlst@@lst@hl@prefix#1#2{\xlst@lst@hl@num{numprefix}{#1}{#2}} \def\xlst@lst@hex{\global\xlst@lst@inhex@true} \def\xlstdisablenumhl{\def\xlst@dgt##1{##1}\def\xlst@pfx##1##2{##2}} \def\xlstenablenumhl{\let\xlst@dgt\xlst@@lst@hl@digit\let\xlst@pfx\xlst@@lst@hl@prefix} \if@xlst@hlnumbers\xlstenablenumhl\else\xlstdisablenumhl\fi \def\xlst@lst@nonum{\ifxlst@lst@innumber@ \global\xlst@lst@innumber@false\global\xlst@lst@inhex@false\fi} % overwrite processor routines to adapt to number \def\xlst@lst@plainletter{% \xlst@lst@nonum\xlst@lst@lastwas@character@true\lst@AppendLetter} \def\lst@ProcessLetter{% \lst@whitespacefalse \ifxlst@lst@innumber@\expandafter\xlst@lst@numletter\else\expandafter\xlst@lst@plainletter\fi} \def\lst@ProcessOther{% \lst@whitespacefalse\xlst@lst@nonum\xlst@lst@lastwas@charkeep@false\xlst@lst@lastwas@character@false\lst@AppendOther} \def\lst@whitespacetrue{\xlst@lst@nonum\xlst@lst@lastwas@charkeep@false\xlst@lst@lastwas@character@false\global\let\lst@ifwhitespace\iftrue} \def\lst@whitespacefalse{\global\let\lst@ifwhitespace\iffalse} \lst@AddToHook{PreInit}{\xlst@lst@nonum \global\xlst@lst@lastwas@character@false\global\xlst@lst@lastwas@charkeep@false} \def\xlst@nc{\ifxlst@lst@lastwas@charkeep@\else\xlst@lst@lastwas@character@false\fi} % modify lst-literate routine to apply to the mechanism \def\lst@Literate#1#2#3{% \ifx\relax#2\@empty\else \lst@CArgX #1\relax\lst@CDef\relax {\let\lst@next\@empty \lst@ifxliterate \lst@ifmode\let\lst@next\lst@CArgEmpty\fi \fi\ifx\lst@next\@empty \ifx\lst@OutputBox\@gobble\else \lst@XPrintToken \let\lst@scanmode\lst@scan@m \lst@token{#2}\lst@length#3\relax \lst@XPrintToken \lst@whitespacefalse\xlst@nc \fi \let\lst@next\lst@CArgEmptyGobble \fi\lst@next}% \@empty% splitter for constants \expandafter\lst@Literate \fi} % The basic literate table \def\xlstSetLiterateTable{% \lstset{add to literate=% {Í}{{\'I}}1 {Ó}{{\'O}}1 {Ú}{{\'U}}1 {à}{{\`a}}1 {è}{{\`e}}1 {ì}{{\`i}}1 {ò}{{\`o}}1 {ù}{{\`u}}1 {À}{{\`A}}1 {È}{{\'E}}1 {Ì}{{\`I}}1 {Ò}{{\`O}}1 {Ù}{{\`U}}1 {ä}{{\"a}}1 {ë}{{\"e}}1 {ï}{{\"i}}1 {ö}{{\"o}}1 {ü}{{\"u}}1 {Ä}{{\"A}}1 {Ë}{{\"E}}1 {Ï}{{\"I}}1 {Ö}{{\"O}}1 {Ü}{{\"U}}1 {â}{{\^a}}1 {ê}{{\^e}}1 {î}{{\^i}}1 {ô}{{\^o}}1 {û}{{\^u}}1 {æ}{{\ae}}1 {Æ}{{\AE}}1 {ß}{{\ss}}1 {ø}{{\o}}1 {€}{{\texteuro}}1 {£}{{\pounds}}1 {:bs:}{{\@declaredcolor{xlst@colors@lst@keywordA}\textbackslash\normalcolor}}1 {:bmath:}{{\xlst@style@get{numbers}\$\normalcolor}}1 {:percent:}{{\%}}1 {:emath:}{{{\xlst@style@get{numbers}\$\normalcolor}}}1 {:dollar:}{{{\xlst@style@get{numbers}\$\normalcolor}}}1 {:plaindollar:}{{\$}}1%spaces % brace fix {:space:}{{{ }}}1 {:ws:}{{{ }}}1 {:cdots:}{{{$\cdots$}}}1 {:cdot:}{{{$\cdot$}}}1 {:ldots:}{{{\ldots}}}1 {:circ:}{{{\ensuremath{\circ}}}}1 {:!:}{{!}}1 {:c:}{{{}}}0 {:star:}{{*}}1 {:minus:}{{-}}1 {:float:}{{{\xlst@style@get{numbers}f\normalcolor}}}1 {:exp:}{{{\xlst@style@get{numbers}e\normalcolor}}}1 {:yields:}{{{$\rightarrow$}}}1% {:lan:}{{{$\langle$\thinspace}}}1 {:ran:}{{{\thinspace$\rangle$}}}1 {:to:}{{{$\to$}}}2 {:equiv:}{{{$\equiv$}}}1% {:bcmd:}{\@declaredcolor{xlst@colors@lst@keywordA}\textbackslash\normalcolor}1 {:ecmd:}{\normalcolor}0 {0}{{\xlst@dgt{0}}}1 {1}{{\xlst@dgt{1}}}1 {2}{{\xlst@dgt{2}}}1 {3}{{\xlst@dgt{3}}}1 {4}{{\xlst@dgt{4}}}1 {5}{{\xlst@dgt{5}}}1 {6}{{\xlst@dgt{6}}}1 {7}{{\xlst@dgt{7}}}1 {8}{{\xlst@dgt{8}}}1 {9}{{\xlst@dgt{9}}}1 {.0}{{\xlst@dgt{.0}}}2 {.1}{{\xlst@dgt{.1}}}2 {.2}{{\xlst@dgt{.2}}}2 {.3}{{\xlst@dgt{.3}}}2 {.4}{{\xlst@dgt{.4}}}2 {.5}{{\xlst@dgt{.5}}}2 {.6}{{\xlst@dgt{.6}}}2 {.7}{{\xlst@dgt{.7}}}2 {.8}{{\xlst@dgt{.8}}}2 {.9}{{\xlst@dgt{.9}}}2 {:lmath:}{{\textcolor{xlst@colors@lst@numbers}{\textbackslash(}}}2 {:rmath:}{{\textcolor{xlst@colors@lst@numbers}{\textbackslash)}}}2 {:ldmath:}{{\textcolor{xlst@colors@lst@numbers}{\textbackslash[}}}2 {:rdmath:}{{\textcolor{xlst@colors@lst@numbers}{\textbackslash]}}}2 {:ul:}{{\_}}1} \if@xlst@extendednums\xlst@lst@extendedliterates\fi } % The digit separator and the radix prefixes have to be registered after the % plain digits, otherwise the single digit wins the (longer) match. \def\xlst@lst@extendedliterates{% \lstset{add to literate={_0}{{\xlst@dgt{\textunderscore0}}}2 {_1}{{\xlst@dgt{\textunderscore1}}}2 {_2}{{\xlst@dgt{\textunderscore2}}}2 {_3}{{\xlst@dgt{\textunderscore3}}}2 {_4}{{\xlst@dgt{\textunderscore4}}}2 {_5}{{\xlst@dgt{\textunderscore5}}}2 {_6}{{\xlst@dgt{\textunderscore6}}}2 {_7}{{\xlst@dgt{\textunderscore7}}}2 {_8}{{\xlst@dgt{\textunderscore8}}}2 {_9}{{\xlst@dgt{\textunderscore9}}}2 {0x}{{\xlst@pfx\xlst@lst@hex{0x}}}2 {0X}{{\xlst@pfx\xlst@lst@hex{0X}}}2 {0b}{{\xlst@pfx\@empty{0b}}}2 {0B}{{\xlst@pfx\@empty{0B}}}2 {0o}{{\xlst@pfx\@empty{0o}}}2 {0O}{{\xlst@pfx\@empty{0O}}}2 }} \def\xlst@lst@numletter{\futurelet\xlst@lst@nexttok\xlst@lst@numletter@} \def\xlst@lst@numletter@{% \ifxlst@lst@inhex@\xlst@lst@scan\xlst@lst@hexletters \else\xlst@lst@scan\xlst@lst@numsuffixes\fi \ifxlst@lst@match@\expandafter\xlst@lst@numletter@@\else\expandafter\xlst@lst@plainletter\fi} \def\xlst@lst@numletter@@#1{% \lst@XPrintToken\let\lst@scanmode\lst@scan@m \lst@token{{\xlst@dgt{#1}}}\lst@length\@ne \lst@XPrintToken} \newif\ifxlst@lst@match@ \def\xlst@lst@scan#1{\xlst@lst@match@false\expandafter\xlst@lst@scan@#1\@nil} \def\xlst@lst@scan@#1{% \ifx#1\@nil\let\xlst@lst@next\relax \else\ifx#1\xlst@lst@nexttok \xlst@lst@match@true\let\xlst@lst@next\xlst@lst@scan@@ \else\let\xlst@lst@next\xlst@lst@scan@\fi\fi\xlst@lst@next} \def\xlst@lst@scan@@#1\@nil{} % the characters of a listing are of category code 12, the lists have to match \begingroup \lccode`\0=`\a \lccode`\1=`\b \lccode`\2=`\c \lccode`\3=`\d \lccode`\4=`\e \lccode`\5=`\f \lccode`\6=`\A \lccode`\7=`\B \lccode`\8=`\C \lccode`\9=`\D \lccode`\!=`\E \lccode`\?=`\F \lowercase{\endgroup\gdef\xlst@lst@hexletters{0123456789!?}}% a-f, A-F \lst@Key{number suffixes}{eE}{\edef\xlst@lst@numsuffixes{\detokenize{#1}}} \if@xlst@extendednums\else\let\xlst@lst@numletter\xlst@lst@plainletter\fi \xlstSetLiterateTable % Basic and internal highlighting definitions % please note, that they will apply under every condition! \newif\if@lst@within@inline@ \newcommand*\xlst@dlst@default[2][]{% \begingroup\fboxsep=\z@\fcolorbox{xlst@colors@border}{xlst@colors@background}{% \if@xlst@inlinesize\@lst@within@inline@true\fi\thinspace\strut\lstinline[prebreak=\xlst@lst@inline@prebreak,#1,keepspaces=true,breakatwhitespace,]`#2`\thinspace }\endgroup} \newcommand*\xlst@dlst@blank[2][]{% \begingroup\thinspace\if@xlst@inlinesize\@lst@within@inline@true\fi\lstinline[prebreak=\xlst@lst@inline@prebreak,#1,keepspaces=true,breakatwhitespace]`#2`\endgroup} \newcommand*\xlst@dlst@input[2][]{\begingroup\if@xlst@inlinesize\@lst@within@inline@true\fi\lstinputlisting[#1]{#2}\endgroup} % the defaults come second to overwrite the "ultimate"/global defaults passed in ##1 :D \def\xlstSetInputDefaults#1{\renewcommand*\xlst@dlst@input[2][]{\begingroup\if@xlst@inlinesize\@lst@within@inline@true\fi\lstinputlisting[##1,#1]{##2}\endgroup}} \def\xlstRemoveInputBackground{\xlstSetInputDefaults{frame=none,% rulecolor={},backgroundcolor={}}} % Lst styles that will be shipped in each case \lstdefinestyle{xlst@nonum}{xleftmargin=3\p@,xrightmargin=3\p@,%will fix some overhead :D numbers=none,numbersep=\z@} % Basic - we-work-in-the-back-hey-bud-environments \lstnewenvironment{lstplain}[1][] {\lstset{xleftmargin=\z@,xrightmargin=\z@,% numbers=none,numbersep=\z@,frame=none,rulecolor={},backgroundcolor={},#1}}{} \lstnewenvironment{lstnonum}[1][]{\lstset{style=xlst@nonum,#1}}{} % Here we will handle the language-control - right now, tcb will not be used % for cleaner setup, we will use pgfkeys \gdef\xlstset#1{\pgfkeys{/xlst@lst@family/.cd,#1}} % Here we define globals, which are basically applied to every listing - like for example the initial style \pgfkeys{/xlst@lst@family/globals/.cd,listing style/.initial={xlst@MAIN}} % Just to provide a clearer structure the keys will be defined seperate for all different styles. \pgfkeys{/xlst@lst@family/default/.cd, listing style/.initial = {\pgfkeysvalueof{/xlst@lst@family/globals/listing style}}, command name prefix/.initial={},command name suffix/.initial={},% constructor command/.initial={xlst@NewLstEnvCore}, /xlst@lst@family/nonumber/.cd, listing style/.initial = {\pgfkeysvalueof{/xlst@lst@family/globals/listing style}}, command name prefix/.initial={},command name suffix/.initial={*},% constructor command/.initial={xlst@NewLstEnvCoreStarred}, /xlst@lst@family/plain/.cd, listing style/.initial = {\pgfkeysvalueof{/xlst@lst@family/globals/listing style},xleftmargin=\z@,xrightmargin=\z@,numbers=none,numbersep=\z@,frame=none,% rulecolor={},backgroundcolor={}}, command name prefix/.initial={plain},command name suffix/.initial={},% constructor command/.initial={xlst@NewLstEnvPlain}, /xlst@lst@family/plain number/.cd, listing style/.initial = {\pgfkeysvalueof{/xlst@lst@family/globals/listing style},% xrightmargin=\z@,xleftmargin=\dimexpr\xlst@length@lst@xleftmargin-3\p@,frame=none,rulecolor={},backgroundcolor={}}, command name prefix/.initial={plain},command name suffix/.initial={},% constructor command/.initial={xlst@NewLstEnvPlain}} % Inlines \pgfkeys{/xlst@lst@family/inline default/.cd, listing style/.initial = {\pgfkeysvalueof{/xlst@lst@family/globals/listing style}}, command name prefix/.initial={c},command name suffix/.initial={}, draw command/.initial={xlst@dlst@default}} \pgfkeys{/xlst@lst@family/inline blank/.cd, listing style/.initial = {\pgfkeysvalueof{/xlst@lst@family/globals/listing style}}, command name prefix/.initial={b},command name suffix/.initial={}, draw command/.initial={xlst@dlst@blank}} \pgfkeys{/xlst@lst@family/inline input/.cd, listing style/.initial = {\pgfkeysvalueof{/xlst@lst@family/globals/listing style}}, command name prefix/.initial={i},command name suffix/.initial={}, draw command/.initial={xlst@dlst@input}} % for names that cannot be part of a command name (\bx86 reads as \bx and '86') % #1 keys, #2 language, #3 code \newcommand*\xlstc[3][]{\xlst@inline@call{default}{#2}{#1}{#3}} \newcommand*\xlstb[3][]{\xlst@inline@call{blank}{#2}{#1}{#3}} \newcommand*\xlsti[3][]{\xlst@inline@call{input}{#2}{#1}{#3}} % #1 inline variant, #2 language, #3 keys, #4 code \def\xlst@inline@call#1#2#3#4{% \protected@edef\xlst@inline@name{% \pgfkeysvalueof{/xlst@lst@family/inline #1/command name prefix}#2% \pgfkeysvalueof{/xlst@lst@family/inline #1/command name suffix}}% \expandafter\ifx\csname\xlst@inline@name\endcsname\relax \PackageError{xlistings}{The language '#2' is not loaded}% {Load it with \string\LoadLanguages{#2} before you use it.}% \else\csname\xlst@inline@name\endcsname[#3]{#4}\fi} % Language-Registration-Helper % spacing control \def\xlst@ensure#1{\needspace{#1\baselineskip}} \def\xlstguard#1{\gdef\@xlst@guard@default{#1}} \xlstguard{.8} \def\xlst@guardspace{\if@xlst@guardspace\xlst@ensure{\@xlst@guard@default}\fi} % on line: \lst@AddToHook{PreInit}{\if@lst@within@inline@\else\xlst@font@fs@normal\fi} % we want to allow to overwrite existing envs \def\lst@allow@redefinition#1{% \ifcsname #1\endcsname \PackageWarning{xlistings}{Environment '#1' already defined, overwriting it!}% \expandafter\let\csname#1\endcsname\relax \expandafter\let\csname end#1\endcsname\relax \fi } % #1 Name #2 Key #3 In Extra #4 Out Extra #5 Language \def\xlst@NewLstEnvCore#1#2#3#4#5{% \lstnewenvironment{#1}[1][]{#3\lstset{##1}\xlst@guardspace}{#4}% } % #1 Name #2 Key #3 In Extra #4 Out Extra #5 Language \def\xlst@NewLstEnvCoreStarred#1#2#3#4#5{% \lstnewenvironment{#1}[1][]{#3\lstset{style=xlst@nonum,##1}\xlst@guardspace}{#4}% } % #1 Name #2 Key #3 In Extra #4 Out Extra #5 Language \def\xlst@NewLstEnvPlain#1#2#3#4#5{% \lstnewenvironment{#1}[1][]{#3\lstset{##1}\xlst@guardspace}{#4}% } % #1 KeyName, #2 LanguageName, #3 EnvironName, #4 OverrideKey \def\xlst@@NewLstEnv#1#2#3#4{% \begingroup \lst@allow@redefinition{#3}% \lst@allow@redefinition{#3@}% lstlistings wrap \protected@edef\xlst@xcurlst{\expandafter\noexpand\csname\pgfkeysvalueof{/xlst@lst@family/\environName/constructor command}\endcsname{#3}{#1}{\noexpand\lstset{style=\pgfkeysvalueof{/xlst@lst@family/\environName/listing style},language=#2,language addons=#4}}{}{#2}}% \global\xlst@xcurlst\endgroup } % The colossos: core registration handler % #1 list of aliases % #2: Name of the Language [java,latex] % #3: Name of the corresponding lst-Language [java, latex,...] \newcommand*\RegisterLanguage[3][]{\begingroup\makeatletter \if@xlst@fakeminted \expandafter\gdef\csname xlst@@minted@#2\endcsname{#3}% \protected@edef\@tmp{#1}\ifx\@tmp\@empty\else \@for\@alias:=\@tmp\do{\expandafter\gdef\csname xlst@@minted@\@alias\endcsname{#3}}% \fi\fi % Register the Environments \def\xlst@foreach@basic@env@iter##1,##2\@nil{% \ifx!##1!\else \def\environName{##1}% \protected@edef\environCurName{\pgfkeysvalueof{/xlst@lst@family/\environName/command name prefix}#2\pgfkeysvalueof{/xlst@lst@family/\environName/command name suffix}}% assign \xlst@debug{> #2/#3 e '##1' (name: \environCurName, ctor: \pgfkeysvalueof{/xlst@lst@family/\environName/constructor command})}% \protected@edef\xlst@CreateAnLstEnviron{\noexpand\xlst@@NewLstEnv{\environName}{#3}{\environCurName}{#2}}% fully expand the Name, otherwise it would be undefined when the environment gets used \xlst@CreateAnLstEnviron \ifx!##2!\else\xlst@foreach@basic@env@iter##2,\@nil\fi \fi} \def\xlst@foreach@basic@env##1{\xlst@foreach@basic@env@iter##1,\@nil} \xlst@foreach@basic@env{default,nonumber,plain}%,presentation} % This procedure can be used in persistence to iterate over the pgf-keys % Register 'inline default' \def\xlst@foreach@inline@env@iter##1,##2\@nil{% \ifx!##1!\else \def\inlineName{##1}% \protected@edef\inlineCurName{\pgfkeysvalueof{/xlst@lst@family/inline \inlineName/command name prefix}#2\pgfkeysvalueof{/xlst@lst@family/inline \inlineName/command name suffix}}% assign \xlst@debug{> #2/#3 i '\inlineName' (cmd: \inlineCurName, sty: \pgfkeysvalueof{/xlst@lst@family/inline \inlineName/listing style}, d: \pgfkeysvalueof{/xlst@lst@family/inline \inlineName/draw command})}% % We will construct those with optional arguments, to give the user a chance to pass optional Arguments :D % luckily we can construct the main Argument without any expansion problems :D \expandafter\xdef\csname\inlineCurName\endcsname{\noexpand\protect\noexpand\@ifnextchar[{\noexpand\protect\expandafter\noexpand\csname @@hasopt@@\inlineCurName\endcsname}{\noexpand\protect\expandafter\noexpand\csname @@noopt@@\inlineCurName\endcsname}}% % Variant without optionals :D \expandafter\xdef\csname @@noopt@@\inlineCurName\endcsname####1{\noexpand\protect\expandafter\noexpand\csname\pgfkeysvalueof{/xlst@lst@family/inline \inlineName/draw command}\endcsname[style=\pgfkeysvalueof{/xlst@lst@family/inline \inlineName/listing style},language=#3,language addons=#2]{####1}}% \expandafter\xdef\csname @@hasopt@@\inlineCurName\endcsname[####1]####2{\noexpand\protect\expandafter\noexpand\csname\pgfkeysvalueof{/xlst@lst@family/inline \inlineName/draw command}\endcsname[style=\pgfkeysvalueof{/xlst@lst@family/inline \inlineName/listing style},language=#3,language addons=#2,####1]{####2}}% \expandafter\robustify\csname\inlineCurName\endcsname% robustify \ifx!##2!\else\xlst@foreach@inline@env@iter##2,\@nil\fi \fi}% \def\xlst@foreach@inline@env##1{\xlst@foreach@inline@env@iter##1,\@nil} \xlst@foreach@inline@env{default,blank,input}%,present} % END: Register Language as present, by definig a command \endgroup} % The [hopefully] beautiful 'sopra-style' \lstdefinestyle{xlst@MAIN}{% % background and border, the frame frame = single, framerule = \xlst@length@lst@famerule, lineskip = \z@, rulecolor = \@declaredcolor{xlst@colors@border}, backgroundcolor = \@declaredcolor{xlst@colors@background}, xleftmargin = \xlst@length@lst@xleftmargin, xrightmargin = \xlst@length@lst@xrightmargin, aboveskip = \medskipamount, belowskip = \medskipamount, % the 'key'-styles: stringstyle = \xlst@styles@lst@basic\xlst@styles@lst@literals, commentstyle = \xlst@styles@lst@basic\xlst@styles@lst@comments, keywordstyle = \xlst@styles@lst@basic\xlst@styles@lst@keywordA, keywordstyle = [2]{\xlst@styles@lst@basic\xlst@styles@lst@keywordB}, keywordstyle = [3]{\xlst@styles@lst@basic\xlst@styles@lst@keywordC}, keywordstyle = [4]{\xlst@styles@lst@basic\xlst@styles@lst@keywordD}, keywordstyle = [5]{\xlst@styles@lst@basic\xlst@styles@lst@literals}, keywordstyle = [6]{\xlst@styles@lst@basic\xlst@styles@lst@command}, basicstyle = \xlst@styles@lst@basic, % fixed columns would stretch narrow fonts and break math in a literate columns = flexible, showstringspaces=false, % line numbers: numbers = left, numbersep = \xlst@length@lst@numsep, numberstyle = \xlst@styles@lst@basic\xlst@styles@lst@linenumbers\xlst@lst@num@consume, % line break: breaklines = true, extendedchars = true, prebreak = \xlst@lst@prebreak, % escapes: escapeinside = {!*}{*!}, % space control keepspaces = false} % Always present 'void'-Language \lstdefinelanguage{void}{moredelim=[is][{}]{|plain|}{|plain|},moredelim=[is][\xlstGet{highlight}]{|ihl|}{|ihl|}} \RegisterLanguage{void}{void} % Now we will define some languages \def\xlstLanguageSearchPath{{langs/}} % a language will be loaded by the default latex-file mechanis % the file has to have the signature 'xlistings-.cfg'; the prefix keeps % the shipped definitions out of the flat TDS namespace (a bare 'python.cfg' % would be visible to every document on the system). The unprefixed % '.cfg' is still honoured as a fallback so private language definitions % keep working. \def\xlstLanguageFilePrefix{xlistings-} \newif\if@xlst@lang@found@ \def\xlst@LoadLanguage@try#1{% #1: file name without the '.cfg' extension \if@xlst@lang@found@\else \InputIfFileExists{#1.cfg}{% \@xlst@lang@found@true \xlst@debug{Loaded '\xlst@curlanginputfile' from '#1.cfg'}% }{}% \fi} \def\xlst@LoadLanguage@searchPath@iter#1,#2\@nil{% \ifx!#1!\else \xlst@LoadLanguage@try{#1\xlstLanguageFilePrefix\xlst@curlanginputfile}% \xlst@LoadLanguage@try{#1\xlst@curlanginputfile}% \ifx!#2!\else\xlst@LoadLanguage@searchPath@iter#2,\@nil\fi\fi } \def\xlst@LoadLanguage@searchPath% {% the local directory always wins \xlst@LoadLanguage@try{\xlstLanguageFilePrefix\xlst@curlanginputfile}% \xlst@LoadLanguage@try{\xlst@curlanginputfile}% \expandafter\xlst@LoadLanguage@searchPath@iter\xlstLanguageSearchPath,\@nil} % a language is loaded at most once, so languages may require each other \def\xlst@LoadLanguage@single#1\@nil{% \ifcsname xlst@lang@loaded@#1\endcsname \xlst@debug{Language '#1' is already loaded}% \else \csgdef{xlst@lang@loaded@#1}{}% \def\xlst@curlanginputfile{#1}% \@xlst@lang@found@false \xlst@LoadLanguage@searchPath{}% \if@xlst@lang@found@\else \PackageWarning{xlistings}{No definition found for the language '#1', neither '\xlstLanguageFilePrefix#1.cfg' nor '#1.cfg' in the current directory or in the search path}% \fi \fi} \def\xlst@LoadLanguage@iter#1,#2\@nil{% \ifx!#1!\else\xlst@LoadLanguage@single#1\@nil \ifx!#2!\else\xlst@LoadLanguage@iter#2,\@nil \fi\fi } \def\xlst@LoadLanguage#1{% \protected@edef\xlst@@langlist{\zap@space#1 \@empty}% \expandafter\xlst@LoadLanguage@iter\xlst@@langlist,\@nil} \let\LoadLanguage\xlst@LoadLanguage \let\LoadLanguages\LoadLanguage % Change colors \let\xlst@registered@colors@keywordA\@empty \let\xlst@registered@colors@keywordB\@empty \let\xlst@registered@colors@keywordC\@empty \let\xlst@registered@colors@numbers\@empty \let\xlst@registered@colors@literals\@empty \let\xlst@registered@colors@comments\@empty \let\xlst@registered@colors@highlight\@empty \let\xlst@registered@colors@command\@empty \let\xlst@registered@colors@linenumbers\@empty \let\xlst@registered@colors@numprefix\@empty % #1 color name #2 color \newcommand*\lstcolorlet[2]{% \@ifundefined{xlst@registered@colors@#1}{% \PackageError{xlistings}{The color '#1' is undefined.}% {Choose one of 'keywordA,keywordB,keywordC,numbers,numprefix,literals,comments,highlight,command,linenumbers'}% }{\colorlet{xlst@colors@lst@#1}{#2}}% } % #1 color mode #2 color name #3 color \newcommand*\lstcolordef[3][RGB]{% \@ifundefined{xlst@registered@colors@#2}{% \PackageError{xlistings}{The color '#2' is undefined.}% {Choose one of 'keywordA,keywordB,keywordC,numbers,numprefix,literals,comments,highlight,command,linenumbers'}% }{\definecolor{xlst@colors@lst@#2}{#1}{#3}}% } % Highlights support \if@xlst@highlights \newenvironment{xlst@listings@highlight@env}[1][] {\begingroup\tikzset{xlst@listings@highlight/.style={#1}}\begin{lrbox}{\@tempboxa}} {\end{lrbox}\xlst@highlights@box[xlst@listings@highlight]{\@tempboxa}\endgroup} \newcommand*\xlst@highlights@box[2][]{% \hspace*{-\p@}\tikz[#1]{% \pgfpathrectangle{\pgfpoint\p@\z@}{\pgfpoint{\wd #2}{\ht #2}}% \pgfusepath{use as bounding box}% \node[anchor=base west,outer sep=\z@,inner xsep=\z@,outer xsep=\p@,inner ysep=\z@,rounded corners=1.65\p@,minimum height=\ht\strutbox+\p@,#1]{\hspace*\p@\strut\box#2\hspace*{-.5\p@}}; }\hspace*{\p@}% } \def\@xlstLstHL#1{\begin{xlst@listings@highlight@env}[#1]\bgroup\aftergroup\xlst@highlights@endenv} \def\xlst@highlights@endenv{\end{xlst@listings@highlight@env}\egroup} \def\xlsthlboxd#1{\protected@edef\@tmp{\noexpand\@xlstLstHL{#1}}\@tmp} \def\xlsthlbox#1{\@xlstLstHL{fill=#1!30,draw=#1}} \else % without tikz we can still color the segment \def\xlsthlboxd#1{\xlst@style@get{highlight}} \def\xlsthlbox#1{\@declaredcolor{#1}} \fi \colorlet{xlstwarning}{yellow!90!red} \colorlet{xlsterror}{red!80!black} \colorlet{xlstinfo}{cyan!70!black} \def\xlstcustom{fill=purple!30} \def\xlsthlwarning{\xlsthlbox{xlstwarning}} \def\xlsthlerror{\xlsthlbox{xlsterror}} \def\xlsthlinfo{\xlsthlbox{xlstinfo}} % only pmode % Comfort guards \def\xlstIfPmode#1#2{\ifnum\lst@mode=\lst@Pmode\relax#1\else#2\fi} % Hook discretionary \colorlet{xlst@breakcolor}{gray} \preto\lst@@discretionary{\@declaredcolor{xlst@breakcolor}} \appto\lst@@discretionary{\normalcolor} \if@xlst@fakeminted % #1 style, #2 lst-language, #3 name of the language, #4 further keys \def\xlst@minted@setup#1#2#3#4{\lstset{style=#1,language=#2,language addons=#3,#4}} % allows to map languages \def\xlst@minted@language@mapping#1{\@ifundefined{xlst@@minted@#1}{#1}{\csname xlst@@minted@#1\endcsname}} \def\xlst@minted@ensure#1{% \@ifundefined{xlst@@minted@#1}{% \xlst@debug{Loading '#1' for the minted environment}% % the environment already runs under the catcodes of a listing \begingroup\catcode`\^^M=5\relax\endlinechar=13\relax\catcode`\ =10\relax \makeatletter\xlst@LoadLanguage{#1}\endgroup \@ifundefined{xlst@@minted@#1}{% \PackageError{xlistings}{The language '#1' is not available}% {Load it with \string\LoadLanguages{#1} or map an existing one onto it with \string\xlstmintedmap.}% }{}% }{}} \def\xlstmintedmap#1#2{\expandafter\def\csname xlst@@minted@#1\endcsname{#2}} % TODO: auto load a language if a requested one is not loaded \def\xlstsetmintedstyle#1{\def\xlst@minted@style{#1}} \xlstsetmintedstyle{\xlst@style@default} \def\xlstlangbadgestyle#1{\raisebox{2.5pt}{\normalfont\color{lightgray}\textsf{\footnotesize#1}}} \if@xlst@accuspp@available@ \def\xlst@typesetlang#1{\BeginAccSupp{method=escape,ActualText={}}\xlstlangbadgestyle{#1}\EndAccSupp{}} \else \def\xlst@typesetlang#1{\xlstlangbadgestyle{#1}} \fi \def\xlst@shownextcodelang#1{% \DeclareCommandCopy\xlst@holdEveryPar\lsthk@EveryPar\relax% \protected@edef\xlst@currcodelang{#1}% \appto\lsthk@EveryPar{\rlap{\smash{\hspace*{\linewidth}\llap{\xlst@typesetlang{\xlst@currcodelang}}}}\DeclareCommandCopy\lsthk@EveryPar\xlst@holdEveryPar\xdef\xlst@currcodelang{}% }} \NewCommandCopy\BadgeNextListing\xlst@shownextcodelang \newif\if@xlistings@mintedlangbadge \let\xlstmintedwithlangbadge\@xlistings@mintedlangbadgetrue \let\xlstmintedwithoutlangbadge\@xlistings@mintedlangbadgefalse \lstnewenvironment{minted}[2][]{\xlst@minted@ensure{#2}\protected@edef\@tmp{\pgfkeysvalueof{/xlst@lst@family/\xlst@minted@style/listing style}}\protected@edef\@temp{\xlst@minted@language@mapping{#2}}\expandafter\expandafter\expandafter\xlst@minted@setup\expandafter\expandafter\expandafter{\expandafter\@tmp\expandafter}\expandafter{\@temp}{#2}{#1}% \if@xlistings@mintedlangbadge\xlst@shownextcodelang{#2}\fi }{} \fi \endinput