Z.OOL.ネット信託統治領 はてな諸島

こちらは "Z.OOL.ネット信託統治領 はてな諸島" です。

github の HEAD 版の tmux において powerline を使用する際の問題点とその回避手法

久し振りに tmux 上で powerline を使ってみました。 Debian noroot 環境では
若干重くなるのが難点です。


[BGM]: METAFIVE - Gravetrippin' (METALIVE VERSION)

本稿について

本稿は、 Z.OOL.ネット信託統治領 Qrunch 諸島に投稿した技術的事項についての速報的で簡易な短信についての投稿です。 この投稿は、以下の Qrunch 諸島の投稿でも御覧になれます。

z80oolong.qrunch.io

追記 (2018/11/16)

HEAD 版の tmux のバージョン番号の修正に基づく問題回避の手法の確認に伴い、本稿を加筆及び修正しました。どうか御了承下さい。

追記 (2018/11/18)

本稿について、大幅な加筆及び修正・訂正を行い、以下の通り、 Qiita 半島にて投稿を行いました。

今後の本稿の修正及び訂正等については、 Qiita 半島にて行いますので、どうか御了承下さい。

qiita.com

はじめに

powerline は、 tmux 及び zsh 等の各種コマンドシェルのステータスライン及びプロンプトの表示を装飾するためのソフトウェアです。

powerline を用いることで、 tmux のステータスライン等に、端末の状態等の各種状態等を明瞭に表示させることが出来ます。

しかし、 Github 上における HEAD 版の tmux 上において、 powerline を起動する設定を行うと、 tmux のステータスラインの装飾が全く行われず、 powerline が正常に起動しない問題が発生する場合があります。

この問題は、 powerline を構成するコマンドの一つである powerline-config が、端末上の tmux のバージョンを検出する際に、 tmux コマンドが異常なバージョン番号を返すために powerline-config が異常終了する事が原因であると考えられます。

そこで、 powerlinetmux に関する設定を行うコードにおいて、 tmux のバージョン番号を検出する関数を修正するか、若しくは HEAD 版の tmux のバージョン番号を修正することにより、 Github 上における HEAD 版の tmux 上において、 powerline を正常に動作させることが可能となりました。

問題の概要

まず最初に、 powerline の公式ページを参考に、以下のようにして、 powerlineディレクト${HOME}/.local 以下に導入します。

  $ tar -zxvf powerline-2.7.tar.gz
  $ pip install --user ./powerline-2.7

そして、 tmux の設定ファイルである ${HOME}/.tmux.conf に以下の設定を追記します。

...
run-shell "/home/u0_a216/.local/bin/powerline-daemon -q"
source "/home/u0_a216/.local/lib/python2.7/site-packages/powerline/bindings/tmux/powerline.conf
...

以上の設定の後、 tmux の再起動を行っても、 tmux のステータスラインはデフォルトの状態で変化が無く、 powerline が正常に動作していないことが判ります。

問題の原因

ここで、 powerline-daemon デーモンが起動している状態で、コマンド powerline-config を以下のように起動すると、以下のようなエラーメッセージを出力して停止することが判ります。

  $ ~/.local/bin/powerline-config tmux setup
Traceback (most recent call last):
  File "/home/u0_a216/.local/bin/powerline-config", line 22, in <module>
    args.function(pl, args)
  File "/home/u0_a216/.local/lib/python2.7/site-packages/powerline/commands/config.py", line 15, in __call__
    self.function(*args, **kwargs)
  File "/home/u0_a216/.local/lib/python2.7/site-packages/powerline/bindings/config.py", line 184, in tmux_setup
    tmux_version = get_tmux_version(pl)
  File "/home/u0_a216/.local/lib/python2.7/site-packages/powerline/bindings/tmux/__init__.py", line 84, in get_tmux_version
    return TmuxVersionInfo(int(major), int(minor), suffix)
ValueError: invalid literal for int() with base 10: 'next-2'
  $ 

上記のエラーメッセージの内容から、 powerline を構成するファイルの一つである ${HOME}/.local/lib/python2.7/site-packages/powerline/bindings/tmux/__init__.py 内の関数である get_tmux_version で異常終了を起こしており、メソッド get_tmux_version の処理内容より、このメソッドは、 tmux のバージョン番号を検出するためのメソッドである事が判ります。

また、端末上の tmux のバージョン番号を表示させるために、 tmux コマンドに -V オプションを付与して実行すると、以下のバージョン番号を出力することが判ります。

  $ tmux -V
  tmux next-2.9
  $

ここで、関数 get_tmux_version の内容は以下のようになっています。

...
def get_tmux_version(pl):
        version_string = get_tmux_output(pl, '-V')
        _, version_string = version_string.split(' ')
        version_string = version_string.strip()
        if version_string == 'master':
            return TmuxVersionInfo(float('inf'), 0, version_string)
        major, minor = version_string.split('.')
        suffix = DIGITS.subn('', minor)[0] or None
        minor = NON_DIGITS.subn('', minor)[0]
        return TmuxVersionInfo(int(major), int(minor), suffix)

上記の関数 get_tmux_version の処理内容より、 tmux のバージョン番号として、 2.6 や 2.7 等の安定版のバージョン番号もしくは、 git のリポジトリからビルドされたことを示す "master" 以外の文字列が出力される場合は、関数 get_tmux_version は例外を発生し、 powerline-config コマンドが異常終了する事が判りました。

以上で述べた不具合が、 Github 上における HEAD 版の tmux 上において、 powerline が正常に動作しない原因であると考えられます。

問題の回避

以上で述べた原因を踏まえて、前述した Github 上における HEAD 版の tmux 上において、 powerline が正常に動作しない問題を回避するには、以下の2通りの手法を用いれば良いことが判ります。

  • powerline を構成するファイル ${HOME}/.local/lib/python2.7/site-packages/powerline/bindings/tmux/__init__.py 内の関数 get_tmux_version において、 tmux のバージョン番号が安定版のバージョンを返さない場合は、 git のリポジトリからのビルド版を始めとした HEAD 版の tmux として扱うように、関数 get_tmux_version を修正する。
  • HEAD 版の tmux のコマンド tmux にオプション -V を付与して起動すると、 tmux master を出力結果として返すように、 tmuxソースコードを修正する。

以下に、それぞれの問題回避手法について述べます。

powerline の修正による問題回避

まず、 powerline の修正に基づいて前述した問題を回避するには、 powerlineソースコードに、以下に示す差分ファイルを適用すれば良い事が判ります。

diff --git a/powerline/bindings/tmux/__init__.py b/powerline/bindings/tmux/__init__.py
index 011cd689..26cc7dfd 100644
--- a/powerline/bindings/tmux/__init__.py
+++ b/powerline/bindings/tmux/__init__.py
@@ -78,7 +78,11 @@ def get_tmux_version(pl):
    version_string = version_string.strip()
    if version_string == 'master':
        return TmuxVersionInfo(float('inf'), 0, version_string)
-   major, minor = version_string.split('.')
-   suffix = DIGITS.subn('', minor)[0] or None
-   minor = NON_DIGITS.subn('', minor)[0]
-   return TmuxVersionInfo(int(major), int(minor), suffix)
+   try:
+       major, minor = version_string.split('.')
+       suffix = DIGITS.subn('', minor)[0] or None
+       minor = NON_DIGITS.subn('', minor)[0]
+       return TmuxVersionInfo(int(major), int(minor), suffix)
+   except:
+       # If version_string == "next-2.9", and etc., then version of tmux is 'master'.
+       return TmuxVersionInfo(float('inf'), 0, version_string)

上記の差分ファイルを適用した後、 powerline の再インストールを行い、 tmux の再起動を行った所、正常に powerline が動作したことを確認しました。

tmux の修正による問題回避

まず、 HEAD 版の tmux における tmux -V コマンドの出力結果を修正するには、 HEAD 版の tmux におけるバージョン番号を修正する必要があり、このバージョン番号は、ソースコードのファイル confifgure.acAC_INIT マクロに示されていることが判ります。

# configure.ac

AC_INIT([tmux], next-2.9)  # ここでは、バージョン番号が "next-2.9" に設定されている
AC_PREREQ([2.60])
...

そこで、以下の通りに、ファイル configure.acAC_INIT マクロが書かれている行を修正します。

# configure.ac

AC_INIT([tmux], master)  # next-2.9 → master に修正。
AC_PREREQ([2.60])
...

ファイル configure.ac を修正した後は、以下に示す手順で、 configure スクリプトを生成し、 ./configure スクリプトの実行と tmux のビルド及びインストールを行います。

  $ sh ./autogen.sh
  $ ./configure
  $ make
  $ make install

以上の tmux のインストールが完了した後は、以下のようにして、コマンド tmux -V を実行して出力結果を確認します。

  $ tmux -V
  tmux master
  $

上記の修正を行った後、 tmux の再起動を行った所、正常に powerline が動作したことを確認しました。