I found it difficult to phrase this question briefly. Therefore I will try to construct it in such a way that I at least ask it clearly.
My question is specific to: "otherkeywords" in the LaTeX package: "listings".
The background for my question is: I tried to create a rule to syntax highlight code (the language is not important today, I want a principle/"proof of concept"). Specifically, I want to emphasise the difference between variables, functions and methods. The reason is that they may have the same name (e.g. a global function, a class method and a class constant).
Consider the following imaginary language where "print" clearly has three different meanings.
print 'HelloWorld'
my_class.print()
my_class::print
My solution produces the LaTeX output shown below (this illustrates my idea of "different meaning, same name"). I stumbled over the somewhat satisfactory, but obviously hacked, solution when I first defined ".print" and "::print" as "otherkeywords" and later used "more keywords" to redefine them in a different "classoffset". The problem is that I cannot cannot explain why this produced the output I wanted (see \lstdefinestyle
in the LaTeX code for language definition).
My questions are:
- Is "otherkeywords" always linked to the lowest "classoffset", and if so, is it merely an extension of "keywords"?
- Why can I use ".print" and "::print" in "morekeywords" after defining them in "otherkeywords"? (My logic dictates that "." and ":" should still be "other" characters.)
For anyone interested in retracing my steps:
Produce the output shown earlier by using the LaTeX file below.
\documentclass{standalone}
\usepackage{xcolor,listings}
% Define Dummy (empty) language
\makeatletter
\lst@definelanguage{prettyprint}%
{%
}[keywords]
\makeatother
\lstdefinestyle{PRETTYPRINT}{
language=prettyprint,%
classoffset=0,%
keywordstyle=\color{red!70!brown}\ttfamily,%
morekeywords={print},%
otherkeywords={.print,::print},%
classoffset=1,%
keywordstyle=\color{cyan!80!black}\ttfamily,%
morekeywords={.print},%
classoffset=2,%
keywordstyle=\color{orange!90!black}\ttfamily,%
morekeywords={::print},%
}
\lstnewenvironment{print}{%
\lstset{style=PRETTYPRINT}
}{}
\begin{document}
\begin{minipage}{5cm}
This is a hack...
\begin{print}
print 'HelloWorld'
my_class.print()
my_class::print()
\end{print}
\end{minipage}
\end{document}
Thank you for following to the bitter end. If you have answers to my questions, ideas for an alternative approach or any other pointers/comments, please leave a comment.
Two a side notes:
I have read the documentation and I am aware that I am not supposed to use a keyword in more than one list.
Also, I am "dead set" on using the listings package even though I know there are alternatives.
Best Answer
In the world of
listings
, there are mainly three kinds of characters: letter, digit, and other. (It is not pronounce or adjective, but a class named o-t-h-e-r literally.) The manual says that all keywords (should) consist of a letter followed by alpha-numeric characters. That is to say thatab
,a2
are good keywords and that12
,1b
,1?
,a?
,!b
,!2
, and!?
are not keywords.So, what makes others so special? An answer is that others are used to separate tokens. In your example, we recognize
print
as a method/function because it is separated by.
/::
and()
. Otherwise if.
and:
were letters we can only see two tokens, namelymy_class.print()
andmy_class::print
.In this example, only the second
bar
is bold becauselistings
setsalsoletter={.},
for[5.0]Lua
.But sometimes we really need to color such symbols. So
listings
allows one to writeotherkeywords={=>}
. Notice that the secondbar
is still bold --- becauselistings
still regards=
as other.But
otherkeywords
does not support class number. In your example,is equivalent to
keywordstyle=[2]\hakuna
, meaning applying\hakuna
for all second class keyword, andmorekeywords=[2]{matata}
, meaning addingmatata
as a second class keyword.However, as in your question 1, there is no
otherkeywords=[2]
syntax.For question 2 it is hard to tell why it works. The remaining is my guess: writing
morekeywords=[3]{Aal::Izz.Well}
will makelistings
addAal::Izz.Well
as a third class key word. Butlistings
will not see this keyword when parsing your code because, as I explained, others separates tokens. However,otherkeywords={Aal::Izz.Well}
forceslistings
take a look, after it readsAal
, at:
and do further checks.You may try something like:
and found that even
otherkeywords
add the keyword to the first class. The latter appear to be in the third class. (guess why~~)