【gitui】見慣れたツールをTUIで爆速化

/darallium/です！ご覧いただきありがとうございます． 😊

「CLI初心者でも感動するような，それでいて汎用性・拡張性の高いCLIツール」を紹介する7日間の3日目の記事です 🙇

本日は「普段の定型作業を爆速に」をテーマに，gituiを紹介します:relaxed:

# gitui

# installation


## linux, macOS
pacman, dfn, zypper, brew, portなどのパッケージマネージャは普段の方法でインストールしてもらえればよい．
```shell
$ <package manager> install gitui
```
※対応していないパッケージマネージャが幾つかある(e.g. apt)ので，失敗した場合は[一部のlinux](#一部のlinux-パッケージマネージャ)も参照．

## 一部のlinux パッケージマネージャ

[公式のReleases](https://github.com/extrawurst/gitui/releases) へ飛び，Latest versionの`gitui-linux-<自分のarchitecture>.tar.gz`をダウンロードする．多くの場合は`gitui-linux-musl.tar.gz`だろう．
```shell
$ tar -zxvf gitui-linux-<自分のarchitecture>.tar.gz
```
上記コマンドで解凍すると，単一のバイナリが手に入る．これを自由なところに配置しよう．グローバルにインストールしたい場合は`/usr/local/bin/gitui`，自分のローカルの場合は`~/.local/bin/gitui`だろうか，パスの通るところに配置しよう．終わったら`exec $SHELL -l`を忘れずに．


## windows

```bat
winget install gitui
```
※wingetについてご存じない場合は [弊サークルブログ](https://rist.hatenablog.jp/entry/2023/12/03/145856) も参照してほしい．

# チュートリアル
gitで管理されているフォルダに入って`gitui`とすれば，画面いっぱいにTUIが開く．
上に並んでいるのがタブ，中央に大きく画面，下に使用可能なショートカットキーが表示されている．`.`キーを押すとその画面で使用可能なショートカットキーがすべて表示される．hを押すと存在するすべてのショートカットキーを表示する．
## status
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/196553/475f599b-a68a-4aa2-03d1-64d57d4d017e.png)
ワーキングディレクトリの確認が行える．
- a: 全てステージ/アンステージ
- \<Enter\>: 選択中のファイル/フォルダをステージ/アンステージ
- :arrow_right: : diffに移行→escで脱出，Enterで新しいほうを採用，Rでリセット
- e: エディタで開く(nvimなどだとシームレスに開けて気持ちがいい)
- c/F/p/f: commit / fetch / push / pull
## Log
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/196553/7f3fde72-1b82-5e68-fcf8-5f6d5486bdd5.png)
コミット履歴の確認が行える．
- \<Enter\>: 右に詳細画面を出す
- b: ブランチ画面を開く
- S: git checkout 
- r: コミットメッセージ編集
- f: コミットメッセージに検索をかける(あいまい検索可)

## Files
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/196553/79b60637-26dc-0da9-8a28-6b6dcaa08303.png)
ファイルツリーが閲覧できる
- f: ファイル検索(あいまい検索可)
- H: そのファイルの編集履歴を見る
- y: そのファイルパスをクリップボードにコピー

## Stashing
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/196553/59727872-90fc-266a-a084-a0336a9d31ec.png)
スタッシュ操作をGUI的に行える
スタッシュに考慮するファイル，インデックスを保持するファイルをu/iでトグルできる．
Filesで使用したキーバインドはここでも使用できる．

# Stashes
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/196553/ac825183-4653-412d-7637-0d74a916d1f4.png)
スタッシュ一覧を確認し，git stashを自由に操作できる．
- \<Enter\>: pop
- D: Drop 
- a: Apply

# カラースキームを導入する
正直デフォルトのカラースキームはかなり見づらい．選択されているファイル名がほとんど見えなくなるのは致命的だろう．そこで，筆者の大好きなcatppuccinを導入することを目的としてみる．
[catppuccin](https://github.com/catppuccin)/[gitui](https://github.com/catppuccin/gitui) より，`theme/*.ron`を設定フォルダにダウンロードする．
windowsの場合は`%appdata%\gitui`，Linux,macOSの場合は`~/.config/gitui`以下である．このとき，サブフォルダを作成しても相対パスでアクセスできるため管理のためにサブフォルダに入れてもよいだろう．

カラースキームがダウンロード出来たら，次は反映させよう．
実行時に`gitui -t <テーマファイルの相対パス>`で指定できる．`~/.config/gitui/theme/mocha.ron`の場合は，`gitui -t theme/mocha.ron`だ．お気に入りのカラースキームになったらエイリアスに登録して.bashrcに放り込もう．

今回はカラースキームを編集することはない．編集したい場合は [ソースコードのstyle.rs](https://github.com/extrawurst/gitui/blob/master/src/ui/style.rs#L320) の`Default for Theme`を見ると，設定項目名とそのデフォルト値が記載されている．設定ファイルはronというrustに優しいファイル形式で記載されている．見慣れないと思うが，カラースキームなので以下さえ覚えれば設定できるだろう．
```Ron
(
    <項目名>: Some(Rgb(<R>, <G>, <B>)), 
    <項目名>: Some(Rgb(<R>, <G>, <B>)), 
    ...
    
    <項目名>: Some(Rgb(<R>, <G>, <B>)),
    line_break: Some("") 
)
```
line_breakは改行を表示したい場合に置く文字である．


# キーバインドで遊ぶ

gituiはキーボードでgitを飛びまわるソフトウェアであるから，ありがたいことにキーバインドを編集する機能も実装されている．キーバインドは`~/.config/gitui/key_binds.ron`に記述する．
公式サンプルとして，vim風にするためにキーバインドが存在するので以下に添付する，

<details><summary>details</summary>
<div>

```ron
// bit for modifiers
// bits: 0  None 
// bits: 1  SHIFT
// bits: 2  CONTROL
//
// Note:
// If the default key layout is lower case,
// and you want to use `Shift + q` to trigger the exit event,
// the setting should like this `exit: Some(( code: Char('Q'), modifiers: ( bits: 1,),)),`
// The Char should be upper case, and the shift modified bit should be set to 1.
//
// Note:
// find `KeysList` type in src/keys/key_list.rs for all possible keys.
// every key not overwritten via the config file will use the default specified there
(
    open_help: Some(( code: F(1), modifiers: ( bits: 0,),)),

    move_left: Some(( code: Char('h'), modifiers: ( bits: 0,),)),
    move_right: Some(( code: Char('l'), modifiers: ( bits: 0,),)),
    move_up: Some(( code: Char('k'), modifiers: ( bits: 0,),)),
    move_down: Some(( code: Char('j'), modifiers: ( bits: 0,),)),
    
    popup_up: Some(( code: Char('p'), modifiers: ( bits: 2,),)),
    popup_down: Some(( code: Char('n'), modifiers: ( bits: 2,),)),
    page_up: Some(( code: Char('b'), modifiers: ( bits: 2,),)),
    page_down: Some(( code: Char('f'), modifiers: ( bits: 2,),)),
    home: Some(( code: Char('g'), modifiers: ( bits: 0,),)),
    end: Some(( code: Char('G'), modifiers: ( bits: 1,),)),
    shift_up: Some(( code: Char('K'), modifiers: ( bits: 1,),)),
    shift_down: Some(( code: Char('J'), modifiers: ( bits: 1,),)),

    edit_file: Some(( code: Char('I'), modifiers: ( bits: 1,),)),

    status_reset_item: Some(( code: Char('U'), modifiers: ( bits: 1,),)),

    diff_reset_lines: Some(( code: Char('u'), modifiers: ( bits: 0,),)),
    diff_stage_lines: Some(( code: Char('s'), modifiers: ( bits: 0,),)),

    stashing_save: Some(( code: Char('w'), modifiers: ( bits: 0,),)),
    stashing_toggle_index: Some(( code: Char('m'), modifiers: ( bits: 0,),)),

    stash_open: Some(( code: Char('l'), modifiers: ( bits: 0,),)),

    abort_merge: Some(( code: Char('M'), modifiers: ( bits: 1,),)),
)
```

</div>
</details>

編集したい場合は [key_list.rs](https://github.com/extrawurst/gitui/blob/master/src/keys/key_list.rs#L126) の` Default for KeyList `を見ると，設定項目名とそのデフォルト値が記載されている．
キーバインドは以下のように設定する．
```ron
(
    項目名: Some(( code: Char('<設定したいキー>'), modifiers: (bits: <0: 無し, 1: シフト, 2: ctrl(command)>)))
)
```
シフトをプレフィックスキーにバインドしたい場合は設定したいキーを大文字で記述しながら，bitsを1にすることに注意．

# あとがき

GitはCUIでやるといちいちコマンドを打つのが長くてめんどくさいことがある．
GitはGUIでやると大きすぎるリポジトリが開けなかったり，チェックボックスなどの操作が多すぎることがある．
以前まであったGitのTUIツールは軒並み1画面に収めるので，狭くて作業がしづらい．

これらの問題を全て解決し，普段使うコマンドの類だけを抽出しているのがこの`gitui`だ．ブランチ回り，変更，フェッチ→マージ→プル→コミット→プッシュ，ログやステージ，修正など，局所的なこと(e.g. force push)をしない限り使わないものが省かれてdaily useに特化している．また，非同期APIが内部に組み込まれているので応答性にも優れる．読者諸君のgitライフを快適にしてくれるのではないだろうか？

また，表示が明らかにgit経験者だけをターゲティングしている．実際に，ステージなどの概念が理解できないと何もわからない見た目をしている．エンジニア諸君には使いやすいのではないだろうか．

個人的には下にヘルプがあること，cloneやinitなどを組み込まないことで無理に完結しない精神が素晴らしいと考えている．

# references 

https://github.com/extrawurst/gitui/tree/master

https://github.com/catppuccin/gitui/tree/main