Humanity

Edit the world by your favorite way

日記:Google 検索のデフォルト言語を変えた、Devtools の Disable cache、等

あんま Twitter の転載とかするの(両方見てる人やまとまったブログ記事がほしい人にとっては)ノイズが増えるのでやりたくないんだけど、 かといって全くやらないのももったいない気がしてくるんだよな…

こういう tips 系はまとまった技術記事よりも見る人にとって分かりやすいのは良い。
まぁ最近は tips は Twitter でいいじゃんみたいな気がしてるけど、 本来フロー系のサービスに技術系の情報を垂れ流したままにするというのもモヤモヤする(保存性の観点からも)。

あと Twitter は検索がいつもバグってる印象しかないのがちょっと致命的。
やっぱりふと思い出した時に検索できる場所に置いておきたい気持ちが強い。
Vim Short Tips Advent Calendar 2019 みたいにまとまってれば辿れるんだけども。





年末年始に送った PR や作った Vim の terminal 関連プラグインと振り返りとか

なんだかんだこういう振り返り記事を書いたの初めてかもしれません。
最近やったことを書く機会があって書き出したらいい感じに振り返り記事になったので丁度よかった(?)。

なぜ terminal 関連のプラグインのみなのかというと今自分の中で一番熱いからです。
前のメジャーバージョン (Vim 8.1) の機能なんですけどね…

しかしこう見ると Vim の terminal は毎日使うので実用重視のプラグインしか作ってないですね。
もっとくだらないプラグインを作っていきたい。

あと去年は自分も LSP を使うようになったり、LSP 環境が改善した年でもあると思います。

qiita.com

自分も関数定義をステータスラインに表示するプラグインとか作ってたので、 LSP がそういうのを全て不要にしてくれる現実が来たのを実感して、 確実に Vim の未来が良くなってるのを感じます。

自分も LSP に限らず外部コマンドと連携するプラグインを作るアイデアがいくつかあり、色々面白いことができそうだと思います。
channel/job は前の前のメジャーバージョンの(ryf

最近やったことなんかをつらつらと書いていきます。
あといっちょ前に振り返りと来年の抱負。

gof に超便利プルリクを送った

TL;DR

Vim の terminal window で実行すると直接外側の Vim でファイルを開けたり、

こんなコマンドを定義してやることで :Gof で fuzzy finder vim plugin っぽく使えます。

command! -nargs=* -complete=dir Gof execute 'terminal ++close gof -t' .. (<q-args> !=# '' ? ' ' .. <q-args> : '')

詳しくは

github.com

経緯とか

gof という Go 製の fuzzy finder があります。 fuzzy finder って何よ?って人は、似たものに junegunn/fzf, (Vim プラグインですが) Shougo/unite.vim, kien/ctrlp.vim などがあります。 (Reddit のスレにまとまってました)

もともとこのコマンドを知ったのは mattn/vim-fz という Vim プラグインが元なのですが、これも gof を使った fuzzy finder plugin です。
最初 mattn さんがこれを作った時こういうのが欲しかったんだよな(外部コマンドのラッパーとしての Vim プラグイン、かつ自分は色んな source がほしい訳じゃなくファイル選択ができればよい)という気持ちだったのですが、正直あまり fuzzy finder を使う機会が最近まで無く、ずっと導入を見送っていました。

しかしふと最近 vim-fz が必要になり、いくつかほしい機能やバグっぽい挙動があったのでコードを見た所、色んな人からの PR の結果なのか正直ちょっと見辛い感じのコードになっていました(個人的に用途がよく分からない if 文が結構あった)。
gof コマンドを呼び出すだけの Vim プラグインを再発明するのも面倒なのでまぁこのままでもいいかと思っていたものの、 ふと別の terminal 関連のプラグインを作っていた時に Terminal API を使って gof コマンドから直接 Vim にファイル開かせるのを思いつきました。 その結果が冒頭のやつです。

Terminal API とはざっくばらんに言うと特殊な JSON を含んだエスケープシーケンスをターミナル上で出力することで Vim に限られた操作を行わせることができるものです。
詳しくは

vim-jp.org

これを使うとこんな感じに内(シェル上のコマンド)から外(Vim)に働きかけることができるので色々面白いことができます。 こんな感じに。

tyru.hatenablog.com

tyru.hatenablog.com

vargs

さらに gof -t を実装した時思いついたのが「これ単体のコマンドにすると便利なのでは?」と思ったのでこういうのも作りました。
xargs っぽく標準入力の文字列(デフォルトのセパレータは改行)に Vim Terminal API を呼び出すエスケープシーケンスを出力するニッチなコマンドです。
ニッチですがそれなりに面白いことができそうではあります。思いつきませんが。

github.com

ただ xargs ライクにしたインターフェースは我ながらよくできていると思います。
あと Slack でも呟いたんですが、最初 Rust で書こうと思ったけど、 指定文字までバッファリングしながら都度読んでいくのが bufio.Scanner のおかげでかなり楽だったり、 goroutine, channel, context も結局使いまくったので Go で書いてよかったと心底思いました。
まぁ小粒のツールなので Rust で書いても作れるは作れると思いますが、どこかで妥協してしまいそう…

project-guide.vim

github.com

vargs を作った勢いでこんなのも作りました。
やりたいことは $GOPATH/src/*/*/*$HOME/volt/repos/*/*/*リポジトリに毎回 :tcdbash の cd で移動するのが面倒なので、 素早く開ける方法が欲しかった。 (peco, gof コマンドが必要です)

このプラグインを入れて以下を vimrc に書くと $GOPATH/src/*/*/*ディレクトリが列挙されて カレントディレクトリの移動とファイルを開くのが fuzzy finder UI でできます(これがやりたかった)。
パスのパターンがそれぞれ違うのでそういうことができる Ex コマンドを定義してくれるライブラリとして公開しました。

function! s:gopath_dirs_pattern() abort
  let root_dir = exists('$GOPATH') ? expand('$GOPATH') : expand('$HOME/go')
  let dirs_pattern = root_dir .. '/src/*/*/*'
  return dirs_pattern
endfunction
" call project_guide#define_command() at VimEnter,
" because project-guide.vim is not loaded yet in your vimrc.
autocmd VimEnter * call project_guide#define_command('Gopath', function('s:gopath_dirs_pattern'))
" Or with custom options
" autocmd VimEnter * call project_guide#define_command('Gopath', function('s:gopath_dirs_pattern'), #{peco_args: ['--select-1'], gof_args: ['-f']})

詳しくは結構しっかり README に書いたつもりなのでそちらを参照してください(上記も README からの引用です)。

あと TODO としてこれらを Volt のプラグインとして提供できるよう考えています(もちろん opt-out できる形で)。
plugconf や repos(は Vim プラグイン作ってる人じゃないといじらないですが)にアクセスするために $GOPATH と同じく長いパスを参照しないといけないので。

peco

で、project-guide.vim を作った時に気付いたのが、peco は --select-1 と --query を同時に指定した時 --query でフィルタされた結果が1個でも終了してくれないこと。
バグか仕様か悩みましたがとりあえず issue で報告したらバグとして認識して頂き速攻直してくれました。流石すぎる…

github.com

これで project-guide.vim#{peco_args: ['--select-1']} を指定すれば(絞り込み結果が1個だったら)プロジェクト選択すらスキップできます。
設定例は先程の project-guide.vim の設定例のコメントアウトされた部分に書いてあります。

sync-term-cwd.vim

これは年末年始に作り始めたものではないですが、まぁ年末年始に手を入れたのでついでに…

github.com

なにこれ

  • Vim の :terminal 上のシェルで cd しても Vim のカレントディレクトリは変わらない
    • :e {フルパス} で指定する必要があり面倒
  • プラグインをインストールするとカレントディレクトリを :terminal 上のシェルと同期してくれる
    • :e {相対パス} で開けて地味に便利

本当に地味なんだけど便利。
Vim の :terminal は毎日使っているので、まず間違いなく今一番(無意識に)使っているプラグイン
詳しくは README とか help 読んでください。

tyru.hatenablog.com

最近の変更

sync-term-cwd.vimcd コマンドを上書きするというちょっと行儀の悪い方法を取っていました。
しかし terminal-api を使えば PS1 で $PWD 取得すれば cd コマンド上書きしなくてもカレントディレクトリ取れることに(いまさら)気付き、修正しました。
その他諸々お行儀が良くなっています。

github.com

ちなみにこれ別のプラグインを作ってる最中に同じく terminal 上のプロセス(e.g. bash)のカレントディレクトリがほしくなって、 前みたく cd コマンドを上書きしてたんじゃバッティングするんで気付いたというものです(遅い)。

あと最近デフォルトの設定値を変更したりしました。 おそらく困る人はいないと思いますが…

empty-prompt.vim

詳しくはこちらの記事を見てください。
個人的に terminal window を使うなら入れておいて損のないプラグインだと思います。
また余計なプラグインを入れたくない & 自分で管理するのが好きな方は、同じことを素 Vim でやる設定例も書いてあるので見てみてください。

tyru.hatenablog.com

転職

あと去年あったことと言えば

  • フルリモートオンリーの会社に転職した
  • 20代最後の年

でした。

フルリモートは難しいと言われていますが、個人的には物凄く仕事しやすくなりました。
確かに向き不向きはあると思います。

  • 一人の孤独感とうまく付き合えない人
  • テキストやビデオ会議等でのリモートコミュニケーションが苦手な人

は厳しいと思います。当たり前と言ったら当たり前なんですが…

あとこれもよく言われてることですが働きすぎてしまうこととか。
自分の場合働きすぎると眠れなくなって次の日に確実に影響出たりするのでセーブしていきたい。

そんな感じで色々難しさもあるものの、基本的に自由度は高くなるので良いものだと思ってます。
エンジニア募集中らしいのでぜひフルリモート興味ある人いたら気軽に話だけでもできますのでぜひ。

www.heartrails.com

あと20代最後のほしいものリストはこちらです。

Amazon.co.jp

趣味開発のモチベーション

またこれは周りにいる(Vimmer の)人達からも度々聞かれる困りごとではあるものの、 OSS として公開したリポジトリのメンテをあまり(思ったより)上手くやれていませんでした。
なかなか触れず issue が溜まってしまい申し訳ないと感じることも多く、それがさらにモチベーションを下げて負のループに陥る等々。

モチベーションのコントロールは仕事でも趣味でも難しいですが、 フルリモートになったことで精神的な余裕が得られ改めて色々考えたりしているので、来年は何か行動に移したいですね。

ここら辺仕事だと強制力が働くので幾分楽だったりしますが。
特に自分は何かをやり始めると朝から晩まで止まらなかったりするので、そういう推進力をうまくコントロールできればいいかなと思います。
何年言ってるんだろうなぁ…

Vim の terminal でも : や <Esc> でノーマルモードに移りたい。けど完全に潰したくはない

そんな方のための Hack をふと某 slack に公開したらウケが良かったのでブログに書いておきます。

一言で言うと

  • 「シェルのプロンプトが空の場合は他のバッファと同じように振舞う」ようにしたら便利だった
  • ついでにプラグイン化した

という話です。

前置き

Vim の terminal window では動いているプロセスにキー入力が送られるため :コマンドラインウィンドウに移ったり、 <Esc>ノーマルモードに移ることができません。
コマンドラインウィンドウに移るには <C-w>:ノーマルモードに移る*1には <C-w>N を押す必要があります。
これを terminal window かそうでないかで使い分ける必要があり、それが地味にストレスでした。

しかし下記の設定を行うことで上記を意識せずに操作を行うことができます。

" Enter command-line / normal-mode if current line is empty prompt
function! s:is_empty_prompt() abort
  return term_getline(bufnr(''), '.') =~# (&shell =~# 'sh$' ? '\$ $' : '> $')
endfunction
tnoremap <expr> :     <SID>is_empty_prompt() ? "\<C-w>:" : ':'
tnoremap <expr> <Esc> <SID>is_empty_prompt() ? "\<C-w>N" : "<Esc>"

というのを某 slack に共有したらウケが良かったのとウーパールーパーのアイコンの人に勧められたのでプラグイン化してみました。
以下で上記と同じことができます。

" Enter command-line / normal-mode if current line is empty prompt
function! s:empty_prompt_mappings() abort
  call empty_prompt#map(#{lhs: ':', rhs: "<C-w>:"})
  call empty_prompt#map(#{lhs: '<Esc>', rhs: "<C-w>N"})
endfunction
autocmd VimEnter * ++once call s:empty_prompt_mappings()

行数増えてない?というのはもっともなツッコミですが、プラグイン化することで

  • (今後の予定として) PS1 を検知して空のプロンプト行をより正確に検知できるようになる
    • デフォルトだと簡易的に 'shell' オプションが *sh だったら $ で終わる行、そうでなかったら (cmd.exe/powershell を想定して) > で終わる行としてある
  • 名前がつくことで管理しやすく & 外部からわかりやすくなる (ポリシー的な意味で)

という感じでプラグイン化することにしました。

github.com

注意

Vim 8.2 が必要

それ以前の Vim を使っている方は、すみませんが Vim 本体のアップデートをお願いします。

デフォルトの空プロンプトの判定

デフォルトだと「プロンプトが空かどうか」の判定には

  • シェルが *sh 系 (&shell =~# 'sh$') なら $ で終わる行
  • それ以外なら (cmd.exe/powershell を想定して) > で終わる行

を空のプロンプトと判定しています。
そのためプロンプト文字列をいじっている方はうまくいかない場合があります。

その場合は g:empty_prompt#pattern を変更していただくようお願いします (現在行に対する Vim正規表現です)。

*1:正確には Terminal-Normal mode (:help Terminal-Normal)