fish使いがxonshを使ってみた

しばらくfishを使用していましたがここ1年くらいで急にxonshが話題に上がり始めたので興味が出てきました。
ずっとxonshを「エックスオンシェル」って読んでましたが「コンシュ」が正解(?)らしい。
タイトルにfishが入ってますがこの記事にfish成分はほとんどありません。

## なぜxonshを使ってみようと思ったか

- fishはPOSIX非互換だし、構文全然覚えられない
- xonshはPythonの構文使えて楽しそう
- Windows(非WSL環境)でも使えそう

理由をいくつか並べて見ましたが、正直話題に上がってるからとりあえず使って見たかったことが一番大きいです。使いやすいなら常用したいと思ってました。

## 導入

基本的にはpipでインストールできます。

```:bash
$ pip install xonsh
$ pip install prompt_toolkit
$ pip install Pygments
```

Pygmentsは入れなくても使用できますが一部のカラーリングがうまくできなくなるので入れた方が良いと思います。

MacOSの場合、Homebrewなどでもインストールできますが、最新バージョン(現時点での最新バージョンは0.8.12)ではないようなので、最新バージョンを使用したい場合はpipでインストールした方がよいです。

```:bash
$ brew install xonsh
$ xonsh --version          
xonsh/0.8.3
```

## .xonshrc

とりあえず必要最小限の設定だと以下な感じ。
これ以外は使用しながら設定を追加していく予定。

```
$VI_MODE = False # emacsキーバインド派なので
$XONSH_COLOR_STYLE = 'native' # みんな使ってるっぽいカラースタイル
$XONSH_SHOW_TRACEBACK = True # エラー時にトレースを全部吐かせる
```

## 使用感
現状MacOSとubuntuに導入して使用してますがかなり使いやすいです。fishとどちらが使いやすいかはもっと使って見ないとわからないので一概には言えませんが、Pythonの構文を使用できるという利点が非常に大きいです。これからどんどん使って行きたいと思います。
Windows環境では正直WSLがあるので非WSL環境で試せてませんが[他の方](http://kirk3110.hatenablog.com/entry/2018/12/23/222739) が書かれているようにGit for Windows上などでは簡単に導入できて使いやすいんじゃないかなと思います。

## 困っていたこと

導入時に困っていた(ほぼ解決済み)ことをまとめます。
あくまで私が導入時に困っていたことで最新のxonshでは修正されている可能性があります。
内容的にここが本編みたいになってしまった・・・。

### xontribを読み込むときにエラーになる

```:xonsh
$ xontrib load powerline
/usr/local/lib/python3.7/site-packages/xontrib/powerline.xsh:213: DeprecationWarning: __xonsh_env__ has been deprecated, please use __xonsh__.env instead.
  if varname not in __xonsh_env__:
xonsh: For full traceback set: $XONSH_SHOW_TRACEBACK = True
KeyError: 'Unknown environment variable: $0'
```

どうやら0.8.0からすべての`__xonsh_*__`が非推奨になり`__xonsh__.*`に置き換わっており、DeprecationWarningが出るようになり、最新バージョンだとそもそもloadもできないみたいです。

新しい仕様に追従できていないxontribが多い様なので該当する場合は、pipでインストール後手動で`__xonsh_*__`を`__xonsh__.*`に修正するか、修正が入っているリポジトリを見つけて`pip install git+https://github.com/foo/bar`でインストールし直してます。
手動で修正する場合、vimだと該当のソースを開いて以下のコマンドを叩けば置換できます。

```
:%s/__xonsh_/([a-z]*/)__/__xonsh__./1/g
```

ちなみに私は以下の2つをforkして修正して使用しています。

 - [xontrib-powerline](https://github.com/re3turn/xontrib-powerline.git)
 - [xontrib-fzf-widgets](https://github.com/re3turn/xontrib-fzf-widgets.git)

### 環境変数`LS_COLORS`が設定してあるとxonsh起動時にエラーになる

```:xonsh
$ xonsh
Traceback (most recent call last):
  File "/usr/local/lib/python3.6/dist-packages/xonsh/__amalgam__.py", line 24001, in main
    args = premain(argv)
  File "/usr/local/lib/python3.6/dist-packages/xonsh/__amalgam__.py", line 23952, in premain
    env = start_services(shell_kwargs, args)
  File "/usr/local/lib/python3.6/dist-packages/xonsh/__amalgam__.py", line 23887, in start_services
    cacheall=shell_kwargs.get("cacheall", False),
  File "/usr/local/lib/python3.6/dist-packages/xonsh/__amalgam__.py", line 23018, in __init__
    load_builtins(execer=self, ctx=xonsh_ctx)
  File "/usr/local/lib/python3.6/dist-packages/xonsh/__amalgam__.py", line 22589, in load_builtins
    builtins.__xonsh__.load(execer=execer, ctx=ctx)
  File "/usr/local/lib/python3.6/dist-packages/xonsh/__amalgam__.py", line 22665, in load
    self.env = Env(default_env())
  File "/usr/local/lib/python3.6/dist-packages/xonsh/__amalgam__.py", line 19107, in __init__
    self[key] = val
  File "/usr/local/lib/python3.6/dist-packages/xonsh/__amalgam__.py", line 19269, in __setitem__
    val = ensurer.convert(val)
  File "/usr/local/lib/python3.6/dist-packages/xonsh/__amalgam__.py", line 18215, in convert
    return cls.fromstring(x)
  File "/usr/local/lib/python3.6/dist-packages/xonsh/__amalgam__.py", line 18178, in fromstring
    esc, "default", reversed_style=reversed_default
  File "/usr/local/lib/python3.6/dist-packages/xonsh/__amalgam__.py", line 7124, in ansi_color_escape_code_to_name
    msg.format(escape_code=escape_code, names=names, name=name, n=n)
ValueError: Could not translate ANSI color code '44;5;235;38;5;33' into a known color in the palette. Specifically, the 'SLOWBLINK_235' portion of '235' in ['BACKGROUND_BLUE', 'SLOWBLINK_', '235', 'SET_FOREGROUND_', '5', 'YELLOW'] seems to missing.

```

環境変数`LS_COLORS`が設定してあるとエラーになる場合があります。
これは現在の最新バージョン(xonsh 0.8.12)では対応しているカラーが無くてエラーになるっぽい。今後修正される模様。

一時的な解決策としては少しめんどくさいですが`LS_COLORS`をunsetしてxonshを起動すればいいです。
Bashの場合、以下のようにすればよいです。

```:bash
$ unset LS_COLORS
$ xonsh
```

### pygmentsを新しくインストールするとxonsh起動時にエラーになる

恐らく、`prompt-toolkit2.0`と`Pygments`をインストールしているとPygmentsのキャッシュファイル(デフォルトだと`~/.local/share/pygments-cache/cache.py`) 作成時にエラーになるっぽい。

```:xonsh
$ xonsh
pygments cache not found, building...
Traceback (most recent call last):
  File "/usr/local/lib/python3.6/dist-packages/xonsh/__amalgam__.py", line 24002, in main
    return main_xonsh(args)
  File "/usr/local/lib/python3.6/dist-packages/xonsh/__amalgam__.py", line 24031, in main_xonsh
    shell.shell.cmdloop()
  File "/usr/local/lib/python3.6/dist-packages/xonsh/ptk2/shell.py", line 189, in cmdloop
    line = self.singleline(auto_suggest=auto_suggest)
  File "/usr/local/lib/python3.6/dist-packages/xonsh/ptk2/shell.py", line 97, in singleline
    self.styler.style_name = env.get("XONSH_COLOR_STYLE")
  File "/usr/local/lib/python3.6/dist-packages/xonsh/__amalgam__.py", line 17559, in styler
    self._styler = XonshStyle(env.get("XONSH_COLOR_STYLE"))
  File "/usr/local/lib/python3.6/dist-packages/xonsh/pyghooks.py", line 438, in __init__
    self.style_name = style_name
  File "/usr/local/lib/python3.6/dist-packages/xonsh/pyghooks.py", line 464, in style_name
    self._smap = get_style_by_name(value)().styles.copy()
  File "/usr/local/lib/python3.6/dist-packages/xonsh/pygments_cache.py", line 404, in get_style_by_name
    load_or_build()
  File "/usr/local/lib/python3.6/dist-packages/xonsh/pygments_cache.py", line 302, in load_or_build
    CACHE = build_cache()
  File "/usr/local/lib/python3.6/dist-packages/xonsh/pygments_cache.py", line 246, in build_cache
    cache["lexers"] = _discover_lexers()
  File "/usr/local/lib/python3.6/dist-packages/xonsh/pygments_cache.py", line 106, in _discover_lexers
    for longname, aliases, filenames, mimetypes in get_all_lexers():
  File "/usr/local/lib/python3.6/dist-packages/pygments/lexers/__init__.py", line 53, in get_all_lexers
    for lexer in find_plugin_lexers():
  File "/usr/local/lib/python3.6/dist-packages/pygments/plugin.py", line 54, in find_plugin_lexers
    for entrypoint in iter_entry_points(LEXER_ENTRY_POINT):
  File "/usr/local/lib/python3.6/dist-packages/pygments/plugin.py", line 50, in iter_entry_points
    return pkg_resources.iter_entry_points(group_name)
TypeError: 'NoneType' object is not callable

```

現在の最新バージョン(xonsh 0.8.12)では、prompt-toolkit2.0に対応していない部分があるためエラーになっている模様。 
この修正はすでにmasterブランチにマージ済みなので、恐らく次のバージョン(0.8.13)には入ってると思われます。

解決策としては[Pull requests #3049](https://github.com/xonsh/xonsh/pull/3049)と同じように`xonsh/ptk2/__init__.py `の内容を削除すれば問題なくxonshが起動するようになります。
私の環境だと以下のファイルの内容を削除すると起動するようになりました。

```:bash
$ cat  /usr/local/lib/python3.6/dist-packages/xonsh/ptk2/__init__.py 
# must come before ptk / pygments imports
from xonsh.lazyasd import load_module_in_background

load_module_in_background(
    "pkg_resources",
    debug="XONSH_DEBUG",
    replacements={"pygments.plugin": "pkg_resources"},
)
```