Humanity

Edit the world by your favorite way

Vim script で flatmap, fold

htsign.hateblo.jp

上記記事を見てブログに書き忘れてたことを思い出した。
以前からちょくちょく引き合いに出してたものの、Vim script での flatmap, fold 実装。
おそらく :for 使うより map() とか組み込み関数使う方が速いです。*1

gist.github.com

まぁ普通にここら辺の関数入ってほしいですね…*2

*1:次期メジャーバージョン Vim 9 だと VM が導入されるので分かりませんが

*2:似た PR はいくつかある

セッション管理プラグインを作った結果あまりうまく運用できてない

github.com

  • セッションの保存・復元 (プロジェクト等)
  • 異常終了時のセッションの復元

を目的としたセッション管理プラグインを作った。
コミットログ見れば分かるけど深夜の勢いで書いたので雑な部分もあるけど普通に使えるはず。
下の例と合わせて読み取ってもらえれば。
help 駆動で書いて妙に help は充実しているのでそちらも。

  • 現在のセッションに名前をつけて保存ができる (:ForgetMeNot save {name})
  • セッションに名前をつけたり開いた (:ForgetMeNot switch {project-name}) 後は1分ごとに自動更新される
  • 名前を付けなくても現在のセッションは instance/{pid} という名前でセッションが保存されている
    • 保存しなければ正常終了時に削除される
    • ただ Vim が落ちた場合は削除されないので :ForgetMeNot read instance/12345 すれば
  • セッション一覧は :ForgetMeNot list で見れる
    • (デフォルトで) 1分ごとに保存されるので、それより前の更新日で instance/... なセッションは異常終了したセッションとみなす (表示にも stale と付く)
  • (要追加設定) 異常終了したセッションがあれば Vim 起動時に開き直すこともできる (スワップ画面のように)

使用例

help から引用

    " Switch to a saved session (show sessions list and select one to switch)
    :ForgetMeNot switch

   " Name current session (don't forget when vim exit)
    :ForgetMeNot save my-big-project

   " Switch to the named session
    :ForgetMeNot switch my-big-project
   " Or read an instance session (e.g. stale session)
    :ForgetMeNot read instance/12345

   " List all sessions
    :ForgetMeNot list

   " Delete the session
    :ForgetMeNot delete my-big-project

セッションファイル自動更新の弊害

暫定で inputlist() 使ってる部分を popup で選ぶようにしたかったり Ex コマンドの補完も付けたいのだけど、ちょっとつまづいてしまった。
というのも、便利かと思って入れた自動更新が思いの外弊害をもたらしている。
以下 vim-jp slack でつぶやいた内容。

プロジェクトごとにセッションを保存する感じで行こうと思ったんだけど、ついプロジェクト開いてから別の操作しちゃって関係ないバッファが保存されちゃったり cwd も別のものになっちゃったりすることがあって厳しい。
プラグインに合わせるのもなんだかな…

で、皆どうしてるんだろうと気になったので質問してみたら thinca さんが唯一セッションヘビーユーザだった。
セッション (プロジェクト?) ごとに 1 Vim の運用方法らしい。

thinca:vim:  1:21 PM
セッションヘビーユーザーです。プロジェクトごとにセッション作ってます

tyru  2:04 PM
手動で作成ですか?プラグイン?

thinca:vim:  4:22 PM
@tyru 
おしょーさんの reanimate.vim 使ってます >セッション管理プラグイン

tyru  4:36 PM
@thinca プロジェクトことに手動でセッション保存する感じですかね

thinca:vim:  4:38 PM
初回作成時は手動です。2回目以降はロードしたセッションは自動で適時保存するようにしてます
4:39
1Vim1セッションで、1のVimで複数のセッションは開かない運用方法です。切り替えることはできます。

tyru  5:17 PM
なるほど。切り換えることはできますが運用が体に染み付いてないんですよね…
慣らしてった方が便利なのかなぁ
5:18
thinca さん1Vimで全部のプロジェクト開くスタイルだと思ってたけどそうじゃないんだな

thinca:vim:  5:19 PM
昔はそうだった
5:20
タブを多用しまくるので1Vim で複数プロジェクト開くのに限界が来た
5:22
一時期は起動する Vim は1つだけど作業切り替え時にセッション切り替えるようにしてて、しかしセッションの切り替えがただの Vim script のロードなわけで開いてるファイル数が多いと切り替え自体が遅いので1プロジェクトにつき tmux のセッション1つ切ってその中でそれぞれ Vim 立ち上げるスタイルになった。プロジェクト切り替える時は tmux のセッションを切り替える

便利なら運用方法を変えてもいいんだけど、それほどのメリットが (自分の直感的には) あまり見つかってないのでうーーーんという状況。
あとマルチプレクサは個人的に合わなかった (これはターミナルのタブで代用できるけど)。

他の人たちも現状復帰にたまに使うぐらいでそれ位の使い方が一番便利なのかな…という気持ちになってきた。
でも異常終了時のセッション復元できたりプロジェクトをさっと開けるのは便利だし、なによりせっかく凝った名前を付けたので便利なものにしていきたい気持ちはある。
まぁセッション管理プラグインで session ってつけると被りそうだったからなんだけど。

個人的にはできれば運用方法を変えずに導入できるプラグインがいい。
かつ自分特有の運用方法に合わせたものじゃなくすんなり導入できるといい (自分は大体プラグインを作る時そういう指針で作っている)。

あと一つ何か調整するだけで便利になりそうな気はしてる。
終了時だけ保存するようにしたらまた違うのかな?
結局忘れて関係ない状態で閉じそうだけど。
プロジェクトの状態を復元したいだけなのに終了時にプロンプトするのは流石にうっとうしいし。

Git 小技集

  • 追記 (2020/03/04): git grep の -n, -E を省略
  • 追記 (2020/03/??): Git 小技集にタイトルを変えた。これまで Git 関連で運用してきて残った tips を載せる記事にすることに
  • 追記 (2020/04/08):「git blame で特定コミットを無視する(コードスタイルの修正は無視、等々)」を追加

gitconfig

config/.gitconfig at 34455e0a0de426c9a79d7cf76ad0d6fc2c374fd6 · tyru/config · GitHub

特定サブコマンドの出力をページャに渡したい or 渡したくない

git config で変えられる。 わざわざ ls = !"git ls-files | less" って alias を設定してたけど ls = ls-files でよくなった。

# ページャに渡す
git config --global pager.<command> true
# ページャに渡さない
git config --global pager.<command> false

stackoverflow.com

git grep の -n, -E を省略

こういう「いつもこのオプション指定してるけど省略できないかな?」って時は man git-grep して運良く用意されてると config のキーと説明が書いてあるのでおすすめです。

diff の a/..., b/... を表示させない

表示させないことで Vimgf, <C-w>f 等で飛べるようになって捗る。

git config --global diff.noprefix true

git diff 等でリネームを検知

git config --global diff.renames true

git blame で特定コミットを無視する(コードスタイルの修正は無視、等々)

具体的にはこういう場合に使います。

--ignore-revs-file で1行ごとにコミットハッシュを記述したファイルを渡すことで無視するコミットを指定できます。((より具体的には行頭・行末のスペースは無視され、空行、 # で始まるコメント行も書けるようです https://git-scm.com/docs/git-fsck#Documentation/git-fsck.txt-fsckskipList https://git-scm.com/docs/git-blame#Documentation/git-blame.txt---ignore-revs-fileltfilegt))
--ignore-rev というのもあるようです。こちらはファイルではなく直接引数で無視するコミットを指定します。複数指定も可能でした (--ignore-rev {rev1} --ignore-rev {rev2})。

# 無視するコミットを改行区切りで指定
$ git log --grep 'cosmetic' --pretty=%H >.git-blame-ignore-revs
$ git blame --ignore-revs-file=.git-blame-ignore-revs {file}

ちなみに1行で書く場合こんな感じ。

$ git blame --ignore-revs-file=<(git log --grep 'cosmetic' --pretty=%H) {file}

コミットメッセージでなく commit author で無視したり、色々組み合わせられる。

$ git blame --ignore-revs-file=<(git log --author 'tyru' --pretty=%H) {file}

ちなみに上記 twitter のリプライツリーで知りましたが、blame.ignoreRevsFile でファイルを指定すれば自動的に --ignore-revs-file に指定されたようになるようです。cosmetic なコミットを列挙しておいてリポジトリに追加しておくとよさそうですね。
また git-hyper-blame というのもあるようで (--ignore-revs-file 追加前のツール?)、これだと .git-blame-ignore-revs というファイルを自動的に見てくれるので同じことができるそうです(今は標準で使えるようになったので必要なさそう)。
なのでおそらく慣習的に、 .git-blame-ignore-revs というファイルを置いておいて blame.ignoreRevsFile に指定するのが良いっぽい。

# 無視するコミットを改行区切りで指定
$ git config blame.ignoreRevsFile .git-blame-ignore-revs

ちなみにそのコミットしかない場合(そのコミットで追加された場合)は無視指定したコミットも表示されます。


上記と意味合いは違いますが *1GitHub の blame のページでも似たような事はできるようです。

*1:無視するコミットを指定するのではなく、無視したいコミット以前の blame を表示する