7

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

12
  • 3
    I'm guessting the issue comes as SAS in listings defineds / and * as keywords (see lstlang3.sty), the short rules often comes first. So we probably have to get more sneaky. It is a bit sad that those the who made the SAS setup, did not include the comment stuff for SAS
    – daleif
    Aug 30, 2017 at 14:15
  • 1
    @daleif is completely correct. I don't know SAS syntax but if you copy the language definition into your document using \lstdefinelanguage and remove * and / from the list of keywords, your comments come out green.
    – Alan Munn
    Aug 30, 2017 at 14:20
  • @AlanMunn isn't there something we can do about the order? I think it just have to have hte longer ones defined first.
    – daleif
    Aug 30, 2017 at 14:23
  • May be offtopic: But the text "another comment" has to be in // and not * in c++
    – koleygr
    Aug 30, 2017 at 14:31
  • 2
    @CarLaTeX then how does SAS know that * paperino; is not an error? Probably symantics. I don't think listings can tell the difference (not sure if minted can either)
    – daleif
    Aug 30, 2017 at 14:56

1 Answer 1

10

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

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .