TransWikia.com

LaTeX listings - how to apply a style to delimiters different from the content

TeX - LaTeX Asked by Guidone on December 26, 2020

How do I modify the key-value option

lstdefinelanguage{mybnf}{
  morestring   = [b]''
}

To obtain the following result:

enter image description here

that is, to be able to have the delimiters defined in a different style (in this case different color) from the content?

Following is my MWE:

documentclass{article}
usepackage{fontspec}
usepackage{longtable, booktabs}
usepackage{listings, listings-ext, listingsutf8}
usepackage{xcolor}

setmainfont{Tisa OT}
setsansfont{TeX Gyre Heros Cn}
setmonofont{Fira Code}


%
% general listing colors
%
definecolor{listing-background}{HTML}{F7F7F7}
definecolor{listing-rule}{HTML}{B3B2B3}
definecolor{listing-numbers}{HTML}{B3B2B3}
definecolor{listing-text-color}{HTML}{000000}
definecolor{listing-keyword}{HTML}{435489}
definecolor{listing-keyword-2}{HTML}{1284CA} % additional keywords
definecolor{listing-keyword-3}{HTML}{9137CB} % additional keywords
definecolor{listing-identifier}{HTML}{435489}
definecolor{listing-string}{HTML}{00999A}
definecolor{listing-comment}{HTML}{8E8E8E}

lstdefinestyle{etturaz_listings_style}{
    language         = java,
    alsolanguage     = scala,
    numbers          = left,
    xleftmargin      = 2.7em,
    framexleftmargin = 2.5em,
    backgroundcolor  = color{white},
    basicstyle       = color{listing-text-color}linespread{1.0}smallttfamily,
    breaklines       = true,
    frame            = single,
    framesep         = 0.19em,
    rulecolor        = color{listing-rule},
    frameround       = ffff,
    tabsize          = 3,
    numberstyle      = color{listing-numbers},
    aboveskip        = 1.0em,
    belowskip        = 0.1em,
    abovecaptionskip = 0em,
    belowcaptionskip = 1.0em,
    keywordstyle     = {color{listing-keyword}bfseries},
    keywordstyle     = {[2]color{listing-keyword-2}bfseries},
    keywordstyle     = {[3]color{listing-keyword-3}bfseriesitshape},
    sensitive        = true,
    identifierstyle  = color{listing-identifier},
    commentstyle     = color{listing-comment},
    stringstyle      = color{listing-string},
    showstringspaces = false,
    escapeinside     = {/*@}{@*/}, % Allow LaTeX inside these special comments
    literate         = {«}{{guillemotleft}}1 {»}{{guillemotright}}1
    {…}{{ldots}}1 {≥}{{>=}}1 {≤}{{<=}}1 {„}{{glqq}}1 {“}{{grqq}}1
    {”}{{''}}1 {<%}{{{color{listing-keyword}<%}}}2
}
lstset{style=etturaz_listings_style}


lstdefinelanguage{Scala}{
    morekeywords={
        % normal keywords (without data types)
        abstract, case, catch, class, def, do, else, extends, false, final,
        finally, for, forSome, if, implicit, import, lazy, macro, match, new,
        null, object, override, package, private, protected, return, sealed, 
        super, this, throw, trait, try, true, type, val, var, while, with, yield, 
        _, :, ;, =, =>, <-, <:
    },
    morekeywords={[2] % data types
        String, Boolean,Byte,Character,Double,Float,Integer,Long,Short, Number,BigDecimal,BigInteger
    },
    morekeywords={[2] % data types
        Seq, List, Map
    },
    sensitive,
    morecomment  = [l]//,
    morecomment  = [s]{/*}{*/},
    morecomment  = [s]{/**}{*/},
%
    morestring   = [b]',
    morestring   = [s][color{black}]{"}{"}
}

lstdefinelanguage{xbnf}{
    morekeywords={
        % normal keywords (without data types)
        ::=
    }
    sensitive,
    morecomment  = [l]//,
    morecomment  = [s]{(*}{*)},
    morestring   = [b]',
    morestring   = [s][color{black}]{"}{"}
}


begin{document}
%   lstset{language=Scala}
    begin{lstlisting}[language=Scala]
        def stringDivideBy(aStr: String, bStr: String): Option[Int] =
            parseInt(aStr).flatMap { aNum =>
                parseInt(bStr).flatMap { bNum =>
                    divide(aNum, bNum)
                }
            }
    end{lstlisting}

    begin{lstlisting}[language=xbnf]
        json ::= element
        value ::= object | array | string | number | "true" | "false" | "null"
        (* So here the two apostrophes in '{' should be green and the bracket black *)
        object ::= '{' ws '}' | '{' member {',' member} '}'
        member ::= ws string ws ':' element
        array ::= '[' ws ']' | '[' element {',' element} ']'
        element ::= ws value ws
        (* Here, again, two green black and the double quote black*)
        string ::= '"' '"' | character {character} '"'
        character ::= 'A' | ... | 'Z' | 'a' | ... | 'z' | escape
    end{lstlisting}

end{document}

Here’s the result:
enter image description here

Thanks

One Answer

Well, for some reason I missed a relevant Q&A: Emphasize (color) contents between two delimiters in listings, but not the delimiters themselves which contains the answer to part of my problem. So, accordingly, I've modified the MWE as follows:

documentclass{article}
usepackage{fontspec}
usepackage{longtable, booktabs}
usepackage{listings, listings-ext, listingsutf8}
usepackage[
                usenames,%
                svgnames,%
                dvipsnames,%
                x11names]{xcolor}

setmainfont{Tisa OT}
setsansfont{TeX Gyre Heros Cn}
setmonofont{Fira Code}


%
% general listing colors
%
definecolor{listing-background}{HTML}{F7F7F7}
definecolor{listing-rule}{HTML}{B3B2B3}
definecolor{listing-numbers}{HTML}{B3B2B3}
definecolor{listing-text-color}{HTML}{000000}
%definecolor{listing-keyword}{HTML}{435489}
definecolor{listing-keyword}{RGB}{95,95,211}
definecolor{listing-keyword-2}{HTML}{1284CA} % additional keywords
definecolor{listing-keyword-3}{HTML}{9137CB} % additional keywords
definecolor{listing-identifier}{HTML}{435489}
definecolor{listing-string}{HTML}{00999A}
definecolor{listing-comment}{HTML}{8E8E8E}
%===============================%
%% Here the suggested solution %%
%
defbeginlstdelim#1#2#3%
{%
    defendlstdelim{#2egroup}%
    smallttfamily#1bgroupcolor{#3}aftergroupendlstdelim%
}
%===============================%
%
% (X)BNF Colors
%
definecolor{xbnf-symbol}{RGB}{95,95,211}

lstdefinestyle{etturaz_listings_style}{
    language         = scala,
    numbers          = left,
    xleftmargin      = 2.7em,
    framexleftmargin = 2.5em,
    backgroundcolor  = color{white},
    basicstyle       = color{listing-text-color}linespread{1.0}smallttfamily,
    breaklines       = true,
    frame            = single,
    framesep         = 0.19em,
    rulecolor        = color{listing-rule},
    frameround       = ffff,
    tabsize          = 3,
    numberstyle      = color{listing-numbers},
    aboveskip        = 1.0em,
    belowskip        = 0.1em,
    abovecaptionskip = 0em,
    belowcaptionskip = 1.0em,
    keywordstyle     = {color{listing-keyword}bfseries},
    keywordstyle     = {[2]color{listing-keyword-2}bfseries},
    keywordstyle     = {[3]color{listing-keyword-3}bfseriesitshape},
    sensitive        = true,
    identifierstyle  = color{listing-identifier},
    commentstyle     = color{listing-comment},
    stringstyle      = color{listing-string},
    showstringspaces = false,
    escapeinside     = {/*@}{@*/}, % Allow LaTeX inside these special comments
%   mathescape       = true,
    literate         = {«}{{guillemotleft}}1 {»}{{guillemotright}}1
    {…}{{ldots}}1 {≥}{{>=}}1 {≤}{{<=}}1 {„}{{glqq}}1 {“}{{grqq}}1
    {”}{{''}}1 
}
lstset{style=etturaz_listings_style}


lstdefinelanguage{Scala}{
    morekeywords={
        % normal keywords (without data types)
        abstract, case, catch, class, def, do, else, extends, false, final,
        finally, for, forSome, if, implicit, import, lazy, macro, match, new,
        null, object, override, package, private, protected, return, sealed, 
        super, this, throw, trait, try, true, type, val, var, while, with, yield, 
        _, :, ;, =, <-, <:
    },
    morekeywords={[2] % data types
        String, Boolean,Byte,Character,Double,Float,Integer,Long,Short, Number,BigDecimal,BigInteger
    },
    morekeywords={[2] % data types
        Seq, List, Map
    },
    otherkeywords = {=>, {, }, (, ) },
    sensitive,
    morecomment  = [l]//,
    morecomment  = [s]{/*}{*/},
    morecomment  = [s]{/**}{*/},
%
    morestring   = [b]',
    morestring   = [s]{"}{"},
    alsoletter   = {%},
    literate     = 
        {+=}{{{color{listing-keyword}+=}}}2
        {=>}{{{color{listing-keyword}=>}}}2
        {<%}{{{bfseriescolor{listing-keyword}<%}}}2
        {{ }{{{bfseriescolor{listing-keyword}{}}}1
        {[}{{{bfseriescolor{listing-keyword}[}}}1
        {()}{{{bfseriescolor{listing-keyword}(}}}1
        {)}{{{bfseriescolor{listing-keyword})}}}1
        {]}{{{bfseriescolor{listing-keyword}]}}}1
        {} }{{{bfseriescolor{listing-keyword}}}}}1
        {:}{{{bfseriescolor{listing-keyword}:}}}1
        {=}{{{bfseriescolor{listing-keyword}=}}}1
}

lstdefinelanguage{xbnf}{
    keywordstyle     = {color{xbnf-symbol}bfseries},
    morekeywords={
        % normal keywords (without data types)
        {::=}
    }
    sensitive,
    morecomment  = [l]//,
    morecomment  = [s]{(*}{*)},
    morestring   = [b]',
%===============================%
%% Here the suggested solution %%
%
    moredelim = **[is][{color{red}beginlstdelim{"}{"}{listing-identifier}}]{"}{"},
    moredelim = **[is][{color{red}beginlstdelim{'}{'}{listing-identifier}}]{'}{'},
%===============================%
    literate     =
%       {::=}{{{bfseriescolor{xbnf-symbol}::=}}}3
        {|}{{{bfseriescolor{xbnf-symbol}|}}}1
        {{ }{{{bfseriescolor{xbnf-symbol}{}}}1
        {[}{{{bfseriescolor{xbnf-symbol}[}}}1
        {()}{{{bfseriescolor{xbnf-symbol}(}}}1
        {)}{{{bfseriescolor{xbnf-symbol})}}}1
        {]}{{{bfseriescolor{xbnf-symbol}]}}}1
        {} }{{{bfseriescolor{xbnf-symbol}}}}}1
}


begin{document}
%   lstset{language=Scala}
    begin{lstlisting}[language=Scala]
        /**
         * A small snippet taken from Cat UG
         */
        def stringDivideBy(aStr: String, bStr: String ) : Option[Int] =
            parseInt(aStr).flatMap { aNum =>
                parseInt(bStr).flatMap { bNum =>
                    divide(aNum, bNum)
                }
            }
        val str: String = "This is a string"
    end{lstlisting}

    begin{lstlisting}[language=xbnf]
        json ::= element
        value ::= object | array | string | number | "true" | "false" | "null"
        (* So here the two apostrophes in '{' should be green and the bracket black *)
        object ::= '{tests' ws '}' | '{' member {',' member} '}'
        member ::= ws string ws ':' element
        array ::= '[' ws ']' | '[' element {',' element} ']'
        element ::= ws value ws
        (* Here, again, two green black and the double quote black*)
        string ::= '"' '"' | character {character} '"'
        character ::= 'A' | ... | 'Z' | 'a' | ... | 'z' | escape
    end{lstlisting}

end{document}

Which gives me the following result: enter image description here

Still, as you can see, there is still a couple of problems:

  • The starting delimiter is followed by a very nasty whitespace, and I cannot figure out why, even because when I run the snippet taken from the solution of referred question, everything works fine;
  • The double and single quotes, once defined as delimiters, cannot be used also as regular text.

Any idea? Thanks

Answered by Guidone on December 26, 2020

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP