3

In the answer to this question, the following solution is suggested to raise an asterisk:

\documentclass{scrbook}
\usepackage[T1]{fontenc}
\usepackage{lmodern}
\usepackage{listings}

\usepackage{color} \definecolor{stringColor}{RGB}{42,0.0,255} \definecolor{keyword1Color}{RGB}{63,127,95} \definecolor{keyword2Color}{RGB}{63,127,200} \definecolor{singleLineCommentColor}{RGB}{127,0,85} \definecolor{multiLineCommentColor}{RGB}{200,0,127}

\lstdefinelanguage{test}{ basicstyle=\linespread{0.83}\small\ttfamily, % Global Code Style %literate={}{\normalfont{}}1, morecomment=[l][\color{singleLineCommentColor}]{//}, morecomment=[s][\color{multiLineCommentColor}]{/}{*/}, morestring=[b]", morestring=[b]', commentstyle=\color{commentColor}, keywordstyle=[1]{\bfseries\color{keyword1Color}}, keywordstyle=[2]{\bfseries\color{keyword2Color}}, stringstyle=\color{stringColor}, %... }

\begin{document} \begin{lstlisting}[language=test] /* Bad asterisk placement! / x*3 \end{lstlisting}

\makeatletter \lst@CCPutMacro \lst@ProcessOther {"2A}{% \lst@ttfamily {\raisebox{2pt}{*}}% used with ttfamily \textasteriskcentered}% used with other fonts @empty\z@@empty \makeatother

\begin{lstlisting}[language=test] /* good asterisk placement! / x*3 \end{lstlisting}

\end{document}

I noticed two things:

i) The code only works if the line

basicstyle=\linespread{0.83}\small\ttfamily, % Global Code Style
    %literate=*{*}{\normalfont{*}}1,

is used in the test environment, which I don't want to use, however, as it seems to change the fonttype. Any way to keep the usual fonttype of lstlisting?

ii) How is it possible to have a "usual" and a raised asterisk in the same lstlisting environment, which is not possible with the solution?

Thanks.

EDIT: I'm afraid there seems to be a bug in the answer: When I write

\begin{lstlisting}[language=test]
test_one, test_two = do_tests()
\end{lstlisting}

the output contains an asterisk where there shouldn't be one!? How can that be? enter image description here

EDIT 2: While we're getting closer, when using > or <, also the edited solution breaks, I'm afraid:

\documentclass{scrbook}
\usepackage{listings}

\begin{document} % https://tex.stackexchange.com/questions/654560/follow-up-to-higher-asterisks-in-lstlisting-environment \makeatletter \lst@CCPutMacro \lst@ProcessOther {"2A}{% \lst@ttfamily {\raisebox{2pt}{}}% used with ttfamily {\raisebox{1pt}{}}% used with other fonts } \lst@ProcessOther{"40}{\textasteriskcentered}% centered asterisk typed as @ @empty\z@@empty \makeatother

\begin{lstlisting}[language=python, alsoletter={[,]}]
    # Regular font 
    x**3
    # Using &quot;at&quot; symbol to print centered asterisk 
    x@@3

    test_one, test_two = do_tests()
    x &gt; y
    x &lt; y
\end{lstlisting}

\end{document}

leads to this output: enter image description here

How can the asterisk be fixed this time, and why does it occur in the first time? I thought we baked it?

EDIT 3: There seems to be a nasty interference when I want to use nice ~ and a literate, as proposed in the answer:

\documentclass{scrbook}
\usepackage{listings}

\begin{document}

% https://tex.stackexchange.com/questions/17266/how-to-insert-a-nice-tilde-in-a-lstlisting
\lstset{
    literate={~} {$\sim$}{1}
}

\makeatletter
\lst@CCPutMacro
\lst@ProcessOther {&quot;2A}{%
    \lst@ttfamily 
    {\raisebox{0pt}{*}}% used with ttfamily
    {\raisebox{1pt}{*}}% used with other fonts
}
\@empty\z@\@empty
\makeatother  

\begin{lstlisting}[language=python, literate={(*)}{\textasteriskcentered}{1}]
    /* Raised and cencetred asterisks */
    x**3, x(*)(*)3
    x[~mask] = 0
\end{lstlisting}

\end{document}

Output: enter image description here

When I leave out literate={(*)}{\textasteriskcentered}{1}, the output looks like this:

enter image description here

How can I use both the literate and simultaneously have a nice-looking ~?

Hermi
  • 234

1 Answers1

4

Update 24-08-2022:

There is a much easier and much more flexible approach to replace something inside lstlisting.

In 5.4 Literate programming section of the manual it's described literate key that does exactly what you're trying to achieve -- replace something with custom text.

enter image description here

Thus the solution to your problem as simple as adding

literate={(*)}{\textasteriskcentered}{1}

to your test language definition.

Note that it's really flexible since you're not limited to a single character replacement, but any sequence. The option written above replaces all occurrences of (*) with a regular (centered by default) asterisk. So basically if you want, you can change (*) to myCenteredAsterisk or anything you find convenient and simple to use.

However, using this approach to replace all * with raised ones doesn't work well, since multline comments will be broken, so you will have to use the old approach for * replacement.

\documentclass{scrbook}
\usepackage[T1]{fontenc}
\usepackage{lmodern}
\usepackage{listings}

\usepackage{color} \definecolor{stringColor}{RGB}{42,0.0,255} \definecolor{keyword1Color}{RGB}{63,127,95} \definecolor{keyword2Color}{RGB}{63,127,200} \definecolor{singleLineCommentColor}{RGB}{127,0,85} \definecolor{multiLineCommentColor}{RGB}{200,0,127}

\lstdefinelanguage{test}{ literate={()}{\textasteriskcentered}{1}, morecomment=[l][\color{singleLineCommentColor}]{//}, morecomment=[s][\color{multiLineCommentColor}]{/}{*/}, morestring=[b]", morestring=[b]', % alsoletter={[,]}, commentstyle=\color{commentColor}, keywordstyle=[1]{\bfseries\color{keyword1Color}}, keywordstyle=[2]{\bfseries\color{keyword2Color}}, stringstyle=\color{stringColor}, }

\begin{document}

\makeatletter \lst@CCPutMacro \lst@ProcessOther {"2A}{% \lst@ttfamily {\raisebox{2pt}{}}% used with ttfamily {\raisebox{1pt}{}}% used with other fonts } @empty\z@@empty \makeatother

\begin{lstlisting}[language=test] /* Raised and cencetred asterisks / x3, x()(*)3 \end{lstlisting}

\end{document}

With a predefined language, such as python, just use

\begin{lstlisting}[language=python, literate={(*)}{\textasteriskcentered}{1}]
        /* Raised and cencetred asterisks */
        x**3, x(*)(*)3
\end{lstlisting}

enter image description here


Despite the approach above is suggested, the original way to go can be fixed as well. Since , is a special character in lstlisting, it uses some intermediate macros that contain @ in it, thus a weird extra asterisk before a comma. To fix it, you can bake , to be treated as a letter by adding

alsoletter={[,]}

option to test language definition. In case you use a predefined language, such as python, just do

\begin{lstlisting}[language=python, alsoletter={[,]}]
   text... 
\end{lstlisting}

Original Answer:

Asterisk with any font

Ulrike Fischer intentionally put comments to the code so that you can follow how it works.

Specifically, this part

\lst@ttfamily 
         {\raisebox{2pt}{*}}% used with ttfamily
         \textasteriskcentered}% used with other fonts

from here you immediately can understand why this doesn't work if you remove basicstyle option that contains \ttfamily which makes the changes apply when typewriter family font is used, otherwise \textasteriskcentered put.

Probably it would be easier to follow if the code was formatted this way

\lst@ttfamily{<when tt font>}{<any other font>}

So that if you want to have the asterisk raised up despite on the font, simply replace

\lst@ttfamily{...}{...}

with

\raisebox{2pt}{*}

enter image description here

IMHO, with the normal font the asterisk is a bit too high, so I would use

\lst@ttfamily 
     {\raisebox{2pt}{*}}% used with ttfamily
     {\raisebox{1pt}{*}}% used with other fonts

instead.

Using both raised and centered asterisks

Since lstlisting is a verbatim environment, you cannot accomplish the task via user-defined macros to typeset a centered asterisk, so you will have to change another symbol in the same way.

For example, this part of code will replace all @ with centered asterisks.

\lst@ProcessOther{"40}{\textasteriskcentered}

If you want to use another symbol instead, pass its ascii code in HEX as a first argument of \lst@ProcessOther with leading " that lets LaTeX to know it's actually a HEX number. You can use a converter to easily find out the HEX code of any character.

Full MWE

\documentclass{scrbook}
\usepackage[T1]{fontenc}
\usepackage{lmodern}
\usepackage{listings}

\usepackage{color} \definecolor{stringColor}{RGB}{42,0.0,255} \definecolor{keyword1Color}{RGB}{63,127,95} \definecolor{keyword2Color}{RGB}{63,127,200} \definecolor{singleLineCommentColor}{RGB}{127,0,85} \definecolor{multiLineCommentColor}{RGB}{200,0,127}

\lstdefinelanguage{test}{ basicstyle=\linespread{0.83}\small, % Global Code Style morecomment=[l][\color{singleLineCommentColor}]{//}, morecomment=[s][\color{multiLineCommentColor}]{/}{/}, morestring=[b]", morestring=[b]', commentstyle=\color{commentColor}, keywordstyle=[1]{\bfseries\color{keyword1Color}}, keywordstyle=[2]{\bfseries\color{keyword2Color}}, stringstyle=\color{stringColor}, alsoletter={[,]} % was added after an edit } \lstdefinelanguage{testt}{ basicstyle=\linespread{0.83}\small\ttfamily, % Global Code Style morecomment=[l][\color{singleLineCommentColor}]{//}, morecomment=[s][\color{multiLineCommentColor}]{/}{/}, morestring=[b]", morestring=[b]', commentstyle=\color{commentColor}, keywordstyle=[1]{\bfseries\color{keyword1Color}}, keywordstyle=[2]{\bfseries\color{keyword2Color}}, stringstyle=\color{stringColor}, alsoletter={[,]} % was added after an edit }

\begin{document}

\makeatletter \lst@CCPutMacro \lst@ProcessOther {"2A}{% \lst@ttfamily {\raisebox{2pt}{}}% used with ttfamily {\raisebox{1pt}{}}% used with other fonts } \lst@ProcessOther{"40}{\textasteriskcentered}% centered asterisk typed as @ @empty\z@@empty \makeatother

\begin{lstlisting}[language=test] /* Regular font / x3 / Using "at" symbol to print centered asterisk / x@@3 \end{lstlisting} \medskip \begin{lstlisting}[language=testt] / Regular font / x3 / Using "at" symbol to print centered asterisk */ x@@3 \end{lstlisting}

\end{document}

enter image description here

antshar
  • 4,238
  • 9
  • 30
  • Please see my edited question. – Hermi Aug 23 '22 at 17:40
  • @Hermi updated the answer as well – antshar Aug 23 '22 at 22:03
  • I'm afraid there's another problem, please see my edited question. – Hermi Aug 25 '22 at 16:55
  • @Hermi without full MWE, I can't tell what's the problem in your case. For me, it works perfectly https://i.stack.imgur.com/E3gtV.png – antshar Aug 26 '22 at 05:15
  • I edited my question with a full MWE. – Hermi Aug 26 '22 at 08:49
  • @Hermi Then again you have two options, add < and > into alsoletter= key as we did with a comma, so that you have alsoletter={<,>,[,]}. However, it's a fragile way, since @ is a special character and it's used all over the source code and you will have to add to alsoletter= for each character that produces unexpected asterisk. So you'd better give up this approach and use suggested literate= approach that's even more flexible. – antshar Aug 26 '22 at 09:19
  • Please see my edited question for a problem when trying to use the literate approach. – Hermi Aug 26 '22 at 10:34
  • @Hermi honestly, it's going further and further from the original question. If you have additional listings questions, you can create an additional post, so other can be involved into a help, because it's less likely that people are tracking all the edits in posts. – antshar Aug 26 '22 at 10:42
  • @Hermi anyway, the new problem is expected, since adding literate= option overrides the global one, so you need to add ~ change manually to have something like literate={~}{$\sim$}{1} {(*)}{\textasteriskcentered}{1} – antshar Aug 26 '22 at 10:42