[Tex/LaTex] How to set style for comments in listings (SAS language)

listings

Premise: I have to use ShareLaTeX (or Overleaf) because I can't install anything on the computer I'm working with.

I'm writing a document with a lot of SAS code snippets, I'm using minted and I'm quite content of the result, but I would like to add some more keywords to the pre-defined ones.

I saw this post: How to add custom C++ keywords to be recognized by Minted? but the solution is too difficult for me, and I don't even know if I could do such a thing in ShareLaTeX.

I tried with a workaround, but it's not convenient, because I have to correct the code and not simply cut and paste it from the SAS editor.

So, I decided to try with listings. I'm almost there but I don't manage to have my style \color{green}\ttfamily for comments.

\documentclass[a4paper,12pt, twoside]{book}
\usepackage{microtype}
\usepackage[T1]{fontenc}
\usepackage{lmodern}
\usepackage[utf8]{inputenc}
\usepackage[a4paper]{geometry}
\geometry{verbose,tmargin=3cm,bmargin=3.5cm,lmargin=4cm,rmargin=3cm,marginparwidth=70pt}
\usepackage{mwe}

\usepackage{minted}
\usemintedstyle{vs}
\newcommand{\saskeyword}[1]{\textcolor{blue}{#1}}
\newenvironment{sasminted}{\VerbatimEnvironment\begin{minted}[escapeinside=||,fontsize=\small,baselinestretch=1, samepage=true]{sas}}
 {\end{minted}}

\usepackage{listings}
\lstset{% 
    basicstyle=\small\ttfamily\bfseries,
    columns=flexible,
    language=SAS,
    keywordstyle=\color{blue}\bfseries,
    morecomment=[s]{/*}{*/},
    morecomment=[s]{*}{;},
    morecomment=[n]{/*}{*/},
    morecomment=[n]{*}{;},
    escapechar=|,
    commentstyle=\color{green}\ttfamily,
    stringstyle=\color[rgb]{0.639,0.082,0.082}\ttfamily,
    showstringspaces=false,
    keepspaces=true,
    sensitive=false,
    otherkeywords={*,/},
}

\newenvironment{saslst}{\VerbatimEnvironment\noindent\begin{minipage}{\linewidth}\begin{lstlisting}}
 {\end{lstlisting}\end{minipage}}


\begin{document}
\noindent Pure \texttt{minted}:
\begin{sasminted}
/* comment */
data pippo; |\emph{within escape chars}|
set  pluto (firstobs=10 obs=14);
keep paperino;
minnie='a string';
* another comment;
run;
\end{sasminted}
This is what I would like to have (without my workaround):
\begin{sasminted}
/* comment */
data pippo; |\emph{within escape chars}|
set  pluto (|\saskeyword{firstobs}|=10 |\saskeyword{obs}|=14); 
keep paperino; 
minnie='a string';
* another comment;
run;
\end{sasminted}

\noindent with \texttt{listing}: 

\begin{lstlisting}
/* comment */
data pippo; |\emph{within escape chars}|
set  pluto (firstobs=10 obs=14);
keep paperino; 
minnie='a string';
* another comment;
run;
\end{lstlisting}
\noindent\texttt{minted} also recognizes when the \texttt{*} has to be put in black or in green:
\begin{sasminted}
/* this with minted */
proc freq data = pippo; 
tables pluto * paperino; 
run;
* another comment;
\end{sasminted}

\noindent I prefer minted highlighting also here: 

\begin{lstlisting}
/* this with listings */
proc freq data = pippo; 
tables pluto * paperino; 
run;
* another comment;
\end{lstlisting}

\end{document}

enter image description here

Best Answer

As discussed in the comments, the problem lies with the otherkeywords definition of the SAS language definition, which defines both * and / as keywords. This overrides their use as comment markers.

Since there is no deleteotherkeywords macro, the simplest way to solve this is to overwrite the list of otherkeywords with those two characters removed. But since * is also used as the multiplication operator in SAS, doing this alone, will cause lines with * in them to appear as comments from the * onwards, since you have defined *...; as a delimited comment.

The way around this problem is to remove that definition of a comment and instead define * to be a comment only when it appears in column 1 using the [f] type for the comment definition.

Here's a complete example:

\documentclass[a4paper,12pt, twoside]{book}
\usepackage{microtype}
\usepackage[T1]{fontenc}
\usepackage{lmodern}
\usepackage[utf8]{inputenc}
%\usepackage[italian]{babel}
\usepackage[a4paper]{geometry}
\geometry{verbose,tmargin=3cm,bmargin=3.5cm,lmargin=4cm,rmargin=3cm,marginparwidth=70pt}
\usepackage{mwe}

\usepackage{xcolor}
\usepackage{listings}
\lstset{% 
    basicstyle=\small\ttfamily\bfseries,
    columns=flexible,
    language=SAS,
    keywordstyle=\color{blue}\bfseries,
    commentstyle=\color{green},
    morecomment=[f]{*},
    morecomment=[s]{/*}{*/},
    morecomment=[n]{/*}{*/},  
    escapechar=|,
    otherkeywords={!,!=,~,$,\&,_,<,>=,=<,>},
    stringstyle=\color[rgb]{0.639,0.082,0.082}\ttfamily,
    showstringspaces=false,
    keepspaces=true,
    sensitive=false,
}

\newenvironment{saslst}{\VerbatimEnvironment\noindent\begin{minipage}{\linewidth}\begin{lstlisting}}
 {\end{lstlisting}\end{minipage}}


\begin{document}
\noindent
With \texttt{listings}:

\noindent\begin{minipage}{\linewidth}% I don't want to break my listing across pages
\begin{lstlisting}
/* comment */
data pippo; |\emph{within escape chars}|
set  pluto (firstobs=10 obs=14);
keep paperino; 
pippo = pippo*pippo;
minnie='a string';
* another comment;
run;
\end{lstlisting}
\end{minipage}
\end{document}

output of code