TeXのソースコードの指定した箇所を色付けする

# はじめに

TeXのlistingのソースコードの一部分をハイライトしたい、でもどうすれば良いのか分からない、あるいは上手くいかない。
そんなお悩みをお持ちの方はぜひ呼んでいってください。

# 上手くいかない例: `escapechar`/`escapeinside`を使う

listingの中でコマンドを入力したい場合（例えば数式を組み込む場合）、`escapechar`や`escapeinside`をよく使う。
それを利用して文字の太さ、色を変えることができるはできるが、、

```tex
\lstset{
  ...
  escapeinside={(@}{@)},
}

\begin{lstlisting}
quicksort(data) {
  if (data.length <= 1) {
    return data;
  } else {
    (@\color{Purple}\textbf{p         = select\_pivot(data);}@)
    {lo, hi}  = partition(p, data);
    lo_sorted = quicksort(lo);
    hi_sorted = quicksort(hi);
    return (lo_sorted ++ p ++ hi_sorted);
  }
}
\end{lstlisting}
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/215516/bdac7a4b-0251-9566-aa24-774bf1db284a.png)

このようにアラインメントが崩れがちになる。
さらに、コードが一旦listingの外に出てしまうのでアンダーバー`_`をエスケープする必要もあって面倒。

# 上手くいく例: `moredelim`を使う

`modedelim`を指定することで、ある文字に挟まれた領域の書体を変更することが可能。

```tex
\lstset{
  ...
  moredelim=[is][\color{Purple}\bfseries]{<\#}{\#>},
}

\begin{lstlisting}
quicksort(data) {
  if (data.length <= 1) {
    return data;
  } else {
    <#p         = select_pivot(data);#>
    {lo, hi}  = partition(p, data);
    lo_sorted = quicksort(lo);
    hi_sorted = quicksort(hi);
    return (lo_sorted ++ p ++ hi_sorted);
  }
}
\end{lstlisting}
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/215516/491747ae-d79d-b989-fb96-03cb7d81ddac.png)

簡単だし、綺麗に出力される。

ちなみに複数の色を使い分けて遊ぶこともできて、

```tex
\lstset{
  ...
  moredelim=[is][\color{Blue}\bfseries]{<\#blue\#}{\#>},
  moredelim=[is][\color{Orange}\bfseries]{<\#orange\#}{\#>},
  moredelim=[is][\color{Green}\bfseries]{<\#green\#}{\#>},
  moredelim=[is][\color{Purple}\bfseries]{<\#purple\#}{\#>},
}

\begin{lstlisting}
quicksort(data) {
  if (data.length <= 1) {
    return data;
  } else {
    <#purple#p         = select_pivot(data);#>
    {<#blue#lo#>, <#orange#hi#>}  = partition(<#purple#p#>, data);
    <#blue#lo_sorted#> = quicksort(<#blue#lo#>);
    <#orange#hi_sorted#> = quicksort(<#orange#hi#>);
    return (<#blue#lo_sorted#> ++ <#purple#p#> ++ <#orange#hi_sorted#>);
  }
}
\end{lstlisting}
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/215516/2c204428-6cfe-3575-f234-109695b78101.png)

こんなこともできる。

# おわりに

vim上のシンタックスハイライトを元に`moredelim`を機械的に生成し、TeXのlistingの色に対応付けているのが
[vimのカラースキームでLaTeXのコードを彩る、carbonpaper.vim](https://qiita.com/s417-lama/items/7d74d1593a9344d880b3)
このvimプラグイン。こちらもよろしくお願いします。

ちなみにアラインメントがおかしい場合は以下の記事を参照してください。
[TeXにソースコードを等幅フォントで"ちゃんと"載せる](https://qiita.com/s417-lama/items/565167b40c28099abb04)

最後に全ソース：

```tex
\documentclass[uplatex]{jsarticle}
\usepackage{xcolor}
\usepackage{listings}
\usepackage{inconsolata}

% Color
\definecolor{Blue}{HTML}{2d5ae0}
\definecolor{Orange}{HTML}{e33900}
\definecolor{Green}{HTML}{009e73}
\definecolor{Purple}{HTML}{9400d3}

% Listings
\lstset{
  language=C++,
  basicstyle=\ttfamily\Large,
  keywordstyle=\bfseries\color{Green},
  stringstyle=\color{Orange},
  commentstyle=\color{Purple},
  showstringspaces=false,
  frame={tb},
  numbers=left,
  xrightmargin=0zw,
  xleftmargin=2zw,
  columns=fixed,
  basewidth=0.5em,
  moredelim=[is][\color{Blue}\bfseries]{<\#blue\#}{\#>},
  moredelim=[is][\color{Orange}\bfseries]{<\#orange\#}{\#>},
  moredelim=[is][\color{Green}\bfseries]{<\#green\#}{\#>},
  moredelim=[is][\color{Purple}\bfseries]{<\#purple\#}{\#>},
  escapeinside={(@}{@)},
}

\begin{document}

\begin{lstlisting}
quicksort(data) {
  if (data.length <= 1) {
    return data;
  } else {
    (@\color{Purple}\textbf{p         = select\_pivot(data);}@)
    {lo, hi}  = partition(p, data);
    lo_sorted = quicksort(lo);
    hi_sorted = quicksort(hi);
    return (lo_sorted ++ p ++ hi_sorted);
  }
}
\end{lstlisting}

\clearpage

\begin{lstlisting}
quicksort(data) {
  if (data.length <= 1) {
    return data;
  } else {
    <#purple#p         = select_pivot(data);#>
    {lo, hi}  = partition(p, data);
    lo_sorted = quicksort(lo);
    hi_sorted = quicksort(hi);
    return (lo_sorted ++ p ++ hi_sorted);
  }
}
\end{lstlisting}

\clearpage

\begin{lstlisting}
quicksort(data) {
  if (data.length <= 1) {
    return data;
  } else {
    <#purple#p         = select_pivot(data);#>
    {<#blue#lo#>, <#orange#hi#>}  = partition(<#purple#p#>, data);
    <#blue#lo_sorted#> = quicksort(<#blue#lo#>);
    <#orange#hi_sorted#> = quicksort(<#orange#hi#>);
    return (<#blue#lo_sorted#> ++ <#purple#p#> ++ <#orange#hi_sorted#>);
  }
}
\end{lstlisting}

\end{document}
```