コマンドラインの実行と結果をハイライトしたい


# コマンドラインの実行と結果をハイライトしたい

コードブロックを利用してコマンドラインを記述する際、どの言語を指定すれば良いのだろうか。言語を指定せずに記述しても良いが、少々味気なく感じることもある。適切にハイライトさせたい。

:::note info
本記事において、言語に関しては斜体、コードブロックで指定する言語や言語エイリアスはインラインコードで表現することとする。
:::

<!--
:::note warn
Qiita では *Shell Session* のシンタックスハイライトが上手く当たっていないような気がします。
:::
-->

## ■ 対象にするコードブロック

- `$` や `#` などのプロンプトを含むコマンドライン

    ````markdown
    ```
    $ ls
    ```
    ````

- `$` や `#` などのプロンプトを含むコマンドラインとその結果

    ````markdown
    ```
    $ ls
    file01.ext file02.ext file03.ext
    file04.ext file05.ext file06.ext
    ```
    ````

## ■ 使うべき言語

今回、*Batch*、*PowerShell*、*Shell*、*Shell Session* (*console*) の 4 つの言語について考えたい。これらの言語はスクリプトファイルやコマンドラインとして利用される。

これらの言語の用途は大きく分けて 2 つに大別される。

- スクリプトファイル or プロンプトを含まないコマンドライン
    - *Batch*
    - *PowerShell*
    - *Shell*
- プロンプトを含むコマンドライン（実行結果を含んでも良い）
    - *Shell Session* (*console*)

したがって、プロンプトを含むコマンドラインを記述する場合は *Shell Session* を指定する。

## ■ 言語エイリアス一覧

:::note warn
2022/08/23 現在の言語エイリアス一覧です。
:::

それぞれの言語とハイライトツールのエイリアスを一覧にしておきたい。それぞれには対応している言語の一覧のリンク (⧉) を付している。ただし、一覧が常に最新のエイリアスを更新し続けているわけではないようなので、一部 GitHub 等のリポジトリを確認している。

また、複数のハイライトツールに共通するエイリアスには下線を付している。

|                 Language                 |            Prism\.js [<sup>⧉</sup>][prism-langs]             |                      Rouge [<sup>⧉</sup>][rouge-langs]                      |      highlight\.js [<sup>⧉</sup>][highlight-langs]      |               Linguist [<sup>⧉</sup>][github-langs] (GitHub)                |            Pygments [<sup>⧉</sup>][pygments-langs]             |
| :--------------------------------------: | :-----------------------------------------------------------: | :--------------------------------------------------------------------------: | :------------------------------------------------------: | :--------------------------------------------------------------------------: | :-------------------------------------------------------------: |
|               **_Batch_**                |                      <ins>`batch`</ins>                       |                    `bat`, <ins>`batch`</ins>, `batchfile`                    |                   `dos`, `bat`, `cmd`                    |        `batchfile`, `bat`, <ins>`batch`</ins>, `dosbatch`, `winbatch`        |                           `batchfile`                           |
|             **_PowerShell_**             |                    <ins>`powershell`</ins>                    |      <ins>`powershell`</ins>, `posh`, <br> `microsoftshell`, `msshell`       |           <ins>`powershell`</ins>, `ps`, `ps1`           |                   <ins>`powershell`</ins>, `posh`, `pwsh`                    |                     <ins>`powershell`</ins>                     |
|               **_Shell_**                |          `shell`, <ins>`bash`</ins>, <ins>`sh`</ins>          |          `shell`, <ins>`bash`</ins>, <ins>`sh`</ins>, `zsh`, `ksh`           |        <ins>`bash`</ins>, <ins>`sh`</ins>, `zsh`         | `shell`, <ins>`bash`</ins>, <ins>`sh`</ins>, <br> `shell-script`, <br> `zsh` |                        <ins>`bash`</ins>                        |
| **_Shell Session_** <br> (**_console_**) | `shell-session`, <br> `se-session`, <ins>`shellsession`</ins> | `shell_session`, <br> `shell-session`, <br> <ins>`console`</ins>, `terminal` | `shell`, <ins>`shellsession`</ins>, <ins>`console`</ins> |  <ins>`shellsession`</ins>, <br> `bash session`, <br> <ins>`console`</ins>   | `msdos session`, <br> `bash session`, <br> `powershell session` |

[prism-langs]: https://prismjs.com/#supported-languages
[rouge-langs]: https://github.com/rouge-ruby/rouge/wiki/List-of-supported-languages-and-lexers
[highlight-langs]: https://github.com/highlightjs/highlight.js/blob/main/SUPPORTED_LANGUAGES.md
[github-langs]: https://github.com/github/linguist/blob/master/lib/linguist/languages.yml
[pygments-langs]: https://pygments.org/languages/

highlihgt\.js の *Shell Session* は、他の *Shell* と同じエイリアスを含むため、少し注意が必要になる。複数のパーサーで互換性を求めるならば、`shell` を利用することは避けた方が良いだろう。

*Shell Session* では実行するコマンドの先頭に一般ユーザープロンプト `$` や管理者 (root) ユーザープロンプト `#` を置き、次の行に実行結果を書く。ただし、`>` を置いてもプロンプトとして理解されない場合があるようだ。

<!-- また、*Shell Session* では PowerShell のコマンドレットが上手くハイライトされない場合もあるようだ。 -->

## ■ *Shell Session* の例

- コマンドラインのみ

    ````markdown
    ```shell-session
    $ ls
    ```
    ````

    ```shell-session
    $ ls
    ```

- コマンドラインとその結果

    ````markdown
    ```shell-session
    $ ls
    file01.ext file02.ext file03.ext
    file04.ext file05.ext file06.ext
    ```
    ````

    ```shell-session
    $ ls
    file01.ext file02.ext file03.ext
    file04.ext file05.ext file06.ext
    ```

### ▽ デモページ

各ハイライトツールのデモを利用できるページを紹介しておきたい。

- Prism\.js

    https://prismjs.com/test.html#language=shell-session

- Rouge

    http://rouge.jneen.net/v3.30.0/console/

- highlight\.js

    https://highlightjs.org/static/demo/#:~:text=%40content%3B%0A%20%20%7D%0A%7D-,Shell%20Session,-%24%20echo%20%24EDITOR

## ■ プロンプトを含まないコマンドライン

:::note info
プロンプトを含まないコマンドラインは読者にとってコピーして利用しやすい利点がある。
:::

`$` や `#` などのプロンプトを含まないコマンドラインのみをコードブロックで記述したい場合は *Batch*、*PowerShell*、*Shell* を利用すると良いだろう。

以下に例として、`npm --version` と `npm install typescript` をまとめて示しておく。どの言語を選択するかは各々の判断に委ねたい。（ハイライトの結果はハイライトツールによって異なることに注意）

- *Batch* 例：

    ````markdown
    ```batch
    npm --version
    npm install typescript
    ```
    ````

    ```batch
    npm --version
    npm install typescript
    ```

- *PowerShell* 例：

    ````
    ```powershell
    npm --version
    npm install typescript
    ```
    ````

    ```powershell
    npm --version
    npm install typescript
    ```

- *Shell* 例：

    ````markdown
    ```bash
    npm --version
    npm install typescript
    ```
    ````

    ```bash
    npm --version
    npm install typescript
    ```

同一記事内でハイライトの色が異なると余計な誤解を生じさせる可能性があるため、理由がない限りこれらをごちゃまぜに使うことは避けた方が良いだろう。

# まとめ

Qiita では Rouge を利用しているので `shell_session`、`shell-session`、`console`、`terminal` によって *Shell Session* のシンタックスハイライトを付けることが出来る。他の Markdown パーサーも利用する場合は、互換性を考慮して `shell-session` や `console` を利用すると良いだろう。

Prism\.js や GitHub では正規表現 (Regular Expression) をハイライトすることが出来るが、Prism\.js では `regex`、GitHub では `regex` と `regexp` になるなど、言語とエイリアス名が少しだけ異なる。やめてくれ。目的が異なる同名エイリアスもやめてくれ。
各ハイライトツールの言語エイリアス統一協会を設立したい。

実際、highlight\.js の言語は他のシンタックスハイライトツールの命名とはかなり異なる。本記事では他のツールと比較して言語を記載しているが、本当は *Batch* → “DOS”、*Shell* → “Bash”、*Shell Session* → “Shell” となっている。

## 各サイトのハイライトツール

Markdown を利用して記事を書くことのできるサイトで利用されるシンタックスハイライトツールを明らかにしておきたい。各サイト名の横には、利用しているシンタックスハイライトツールが明示されている公式ページを参照している。

|                             サイト                              | シンタックスハイライトツール |
| :-------------------------------------------------------------: | ---------------------------- |
|                Qiita [<sup>[↗]</sup>][qiita-syn]                | Rouge                        |
|                 Zenn [<sup>[↗]</sup>][zenn-syn]                 | Prism\.js                    |
|               GitHub [<sup>[↗]</sup>][github-syn]               | Linguist                     |
|               GitLab [<sup>[↗]</sup>][gitlab-syn]               | highlight\.js, Rouge         |
| VS Code [<sup>[↗]</sup>][vscdoe-syn] <br>（デフォルトビューワ） | highlight\.js                |

[qiita-syn]: https://qiita.com/Qiita/items/e84f5aad7757afce82ba
[zenn-syn]: https://zenn.dev/zenn/articles/markdown-guide#%E3%82%B3%E3%83%BC%E3%83%89%E3%83%96%E3%83%AD%E3%83%83%E3%82%AF
[github-syn]: https://docs.github.com/ja/get-started/writing-on-github/working-with-advanced-formatting/creating-and-highlighting-code-blocks#syntax-highlighting
[gitlab-syn]: https://docs.gitlab.com/ee/user/project/highlighting.html
[vscdoe-syn]: https://github.com/microsoft/vscode/blob/e009a3b518f4b81b63d0a5c8ccf51400aa8623b7/extensions/markdown-language-features/package.json#L601

# 追記

2022/10/24: *Shell Session* のシンタックスハイライトが上手く当たるようになりました。軽微修正。