いろいろ備忘録日記

主に .NET とか Go とか Flutter とか Python絡みのメモを公開しています。

less コマンドで ソースコード のハイライト表示をする (GNU Source-Highlight, LESSOPEN)

概要

前回、前々回とless コマンドについて記事を書きました。

devlights.hatenablog.com

devlights.hatenablog.com

ついでなので、もうひとつTipsもメモ。

通常、less でソースコードなどを表示すると色付けがされません。

で、出来ればターミナルであってもハイライトされて表示されてほしいですよね。

GNU Source Highlight を使う

そんなときに利用するのが、以下の GNU Source Highlight というツールです。

www.gnu.org

結構昔からあるツールだと思います。見ると、ちょこちょこバージョンアップしてるんですね。

現時点での最新版は 3.1.8 みたい。ページみると、Go とかも対応してくれています。

これをインストールします。私は Debian なので、以下でインストール。RH 系の場合は yum で入ります。

$ sudo apt install source-highlight

この GNU Source Highlight さん、基本は入力を与えると指定したフォーマット(HTMLとか)にして出力してくれるのですが

ANSI color escape を付けて出力してくれるモードもありまして、それがlessと一緒に使えます。

上記のページにも以下のように記載されています。

ANSI color escape sequences (you can use this feature with less)

lessパイプ用のシェルスクリプト

さらに、less で使う人が多いのかどうかはわかりませんが、GNU Source Highlight をインストールすると

lessの環境変数 LESSOPEN で使えるシェルスクリプトもインストールされます。

シェルスクリプトの名前は src-hilite-lesspipe.sh 。場所はディストリビューションによって異なるかもしれません。

Debian系の場合は /usr/share/source-highlight の下にあります。

$ source-highlight --version
GNU Source-highlight 3.1.8 (library: 4:1:0)
Copyright (C) 1999-2008 Lorenzo Bettini <http://www.lorenzobettini.it>
This program comes with ABSOLUTELY NO WARRANTY.
This is free software; you may redistribute copies of the program
under the terms of the GNU General Public License.
For more information about these matters, see the file named COPYING.

$ find /usr -type f -name '*lesspipe.sh' -print
/usr/share/source-highlight/src-hilite-lesspipe.sh

環境変数 LESSOPEN に設定

前回利用した 環境変数 LESSOPEN に以下のように設定します。

$ export LESSOPEN='| /usr/share/source-highlight/src-hilite-lesspipe.sh %s'

オケ。ではやってみましょう。例えば、helloworld.go ってGoプログラムソースがあったとします。

それを上でLESSOPENで設定した状態で表示してみます。

$ less -X helloworld.go
ESC[01;34mpackageESC[m main

ESC[01;34mimportESC[m ESC[31m(ESC[m
        ESC[31m"fmt"ESC[m
        ESC[31m"os"ESC[m
        ESC[31m"strings"ESC[m
ESC[31m)ESC[m

ESC[01;34mfuncESC[m ESC[01;30mmainESC[mESC[31m()ESC[m ESC[31m{ESC[m
        osESC[31m.ESC[mESC[01;30mExitESC[mESC[31m(ESC[mESC[01;30mrunESC[mESC[31m())ESC[m
ESC[31m}ESC[m

ESC[01;34mfuncESC[m ESC[01;30mrunESC[mESC[31m()ESC[m int ESC[31m{ESC[m
        fmtESC[31m.ESC[mESC[01;30mPrintfESC[mESC[31m(ESC[mESC[31m"%s\n"ESC[mESC[31m,ESC[m stringsESC[31m.ESC[mESC[01;30mToUpperESC[mESC[31m(ESC[mESC[31m"hello"
ESC[mESC[31m))ESC[m
        fmtESC[31m.ESC[mESC[01;30mPrintlnESC[mESC[31m(ESC[mESC[31m"こんにちわ"ESC[mESC[31m)ESC[m
        ESC[01;34mreturnESC[m ESC[35m0ESC[m
ESC[31m}ESC[m

悲惨なことになりましたねw

less の -R オプションがセットで必要

上記のようにシェルスクリプトをLESSOPENに設定しただけだと、カラーエスケープシーケンスがそのまま出力されちゃいます。

んで、このようなときは less に -R オプションを付けます。

$ less -X -R helloworld.go
package main

import (
        "fmt"
        "os"
        "strings"
)

func main() {
        os.Exit(run())
}

func run() int {
        fmt.Printf("%s\n", strings.ToUpper("hello"))
        fmt.Println("こんにちわ")
        return 0
}

このブログ上だと色がわかりませんが、実際にターミナル上で実行すると色付きで表示されます。

補足:毎回毎回 -X -R とかつけるの面倒くさい

そんなときは、環境変数 LESS に毎回指定したいオプションを設定しておくと便利です。

以下のようにすると、上で指定しているオプションを指定した状態で less が実行されます。

$ export LESS=' -X -R '

補足:lsとかgrepで --color=always 指定しているときにも使える

ls や grep には色付きで表示するオプションがあります。この色も ANSI color escape sequence なので、結果が多いので less にパイプしたい場合に、そのまま繋ぐとエスケープシーケンスがそのまま出ちゃいます。

$ pwd
~/go/pkg

$ ls -1 --color=always
mod
sumdb

$ ls -1 --color=always | less -X
ESC[0mESC[01;34mmodESC[0m
ESC[01;34msumdbESC[0m

これも、-R オプションをつけるとちゃんと色付きでlessが表示してくれます。

$ ls -1 --color=always | less -X -R
mod
sumdb

過去の記事については、以下のページからご参照下さい。

  • いろいろ備忘録日記まとめ

devlights.github.io

サンプルコードは、以下の場所で公開しています。

  • いろいろ備忘録日記サンプルソース置き場

github.com github.com

github.com