Bash シェルスクリプトの絶対パスが、そのスクリプトの中からでも分かりますか
分かります。どう書くかを知っていると意外と便利なこの質問は Stack Overflow の こちら です。最も upvote されている回答のワンライナーは下記のとおりです。
"$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
ただし回答にも書かれているとおりこのワンライナーには少々問題があり、ファイルがシンボリックリンクだと解決できません(ディレクトリがシンボリックリンクの場合は cd
を cd -P
にすることで解決されます。pwd
を pwd -P
にしても同様だと思います)。回答ではさらにこの問題に対応できる、7行からなるコードも紹介されていますが(興味のある方は こちら)ふだん使いするには少し複雑すぎる気がします。
そこで、コメントにちらほら書かれていたり 紹介されている Gist にもあるように、
"$(dirname "$(readlink -f "$0")")"
がシンプルかつ十分な書き方です。……ただしこのワンライナーにも問題があり、Linux など GNU の readlink
がインストールされている環境でしか動きません。
Mac を使っている場合は、たとえば Homebrew
で coreutils
パッケージをインストールして greadlink
を readlink
の代わりに使うか、ファイルのシンボリックリンクの解決は諦めて(ほとんどのユースケースでは事足りると思います)上の BASH_SOURCE
を用いた書き方を使うことになるでしょう。
覚えておいて損はないのではないでしょうか。
重い腰を上げて Neovim ことはじめ ー ripgrep (rg) と fzf によるソースコード検索編
はじめに
Neovim への移行と共に実現したいことがありました。この 『コマンド一発でソースコード検索&表示できる「peco」改が凄い!』 というブログポストで紹介されているもの相当の機能を Vim 内で実現することです。記事でも『Vim にある grep とかも物色しながら「いいのないねー」……』とありますし、比較的素直な発想だと思います。さていきなりですが、これは 先日の記事 に書いた Neovim のニュースレターの 第6号 で紹介されている fzf を導入すればできる気がしたので、やってみました。
代替手段の調査
と、その前に、一応他の実現方法についても少し調べてみます。
まずは、元の記事にある peco の連携を少し調べてみましたが希望に沿うものはなさそうな雰囲気。記事の出発点が Vim の grep などを検討したが良いものがない、というものなので、もし peco
との連携が可能なら記事で言及されますよね、きっと。
続いて考えたのが CtrlP を使う方法です。結構期待したのだけれど CtrlP
はファイルのマッチングを念頭に作られたからかデフォルトでは所望の機能がないようです。CtrlP
の拡張を少し探してみたもののすぐには見つからなかったので、次へ。
最後に、できる気がするのだけれど今回は手を出さなかったのが Denite.nvim を使う方法です。先代の Unite.vim の頃から、いつか使ってみたいと思っているプラグインなのですが……、なんかどうにも億劫で試してみるには至りませんでした。
fzf
および fzf.vim
のインストール
はい。ということで fzf
です。fzf
は peco
のようないわゆる fuzzy matcher で、作者の方が Vim ユーザなこともあってか Vim との連携機能が強力です。同じ作者による fzf.vim プラグインを導入すると 幸せになれるそうです。色々と設定を試行錯誤して、そこそこ満足できる状態になりました。
インストールには TOML ファイルに fzf
および fzf.vim
のエントリを追加します。
[[plugins]] repo = 'junegunn/fzf' build = './install --bin' merged = '0' [[plugins]] repo = 'junegunn/fzf.vim' depends = 'fzf'
検索プログラムの選定
fzf.vim
の設定の前に、fzf
への入力を出力するプログラムを決めます。元の『「peco」改』のエントリは peco
への入力に Ack を使っています。Ack
は find
+grep
相当のことが実行できるもので、同種のプログラムが多数開発されています。調べた結果、ripgrep というプログラムが性能が良く一番信頼できそうだな、という結論に至りました。興味のある方は、ripgrep
の作者が性能比較を行なっている このブログポスト や、Hacker News での ag
の作者との やり取り などを読んでみてください。
fzf.vim
の設定
さてあとは fzf.vim
の設定です。なるべく元の記事の アニメーション と似たような使用感になると良いなと思って設定しました。
該当する箇所の設定を抜き出してみました。
[[plugins]] repo = 'junegunn/fzf.vim' depends = 'fzf' hook_add = ''' command! -bang -nargs=* Rg \ call fzf#vim#grep( \ 'rg --line-number --no-heading '.shellescape(<q-args>), 0, \ fzf#vim#with_preview({'options': '--exact --reverse'}, 'right:50%:wrap')) '''
fzf.vim
の README
にある :Rg
というコマンドを設定している箇所を参考にして、以下の変更を加えています。ちなみに rg
というのは ripgrep
の実行ファイル名です。README
では --column
が有効で with_column
も 1
に設定してありますが、どのような効果があるのか不明だったので無効にしました。:Rg!
コマンドは使わないと思ったので除き、また --color=always
があると速度が目に見えて遅くなってしまうのでこちらも除いてデフォルトの挙動(--color=auto
)にしてあります。
fzf#vim#with_preview
はとてつもなく素晴らしいので、デフォルトで有効にしました。長い行は wrap
した方が好みです。また、fzf
に --exact
と --reverse
を渡しています。前者はあいまい検索を無効に、後者は候補の表示をデフォルトのボトムアップからトップダウンに変更するオプションです。
追記(2017/04/29):--delimiter : --nth 3..
というオプションを追加しました。詳しくは こちら。
あとはコマンドモードで :Rg
を実行すれば良いです。
おわりに
重い腰を上げて Neovim ことはじめ ー Neobundle から Dein.vim への移行編
Vim のプラグイン管理には Neobundle というプラグイン(パッケージ)マネージャのお世話になっており、これといって不満はないんです。ただ Neobundle
はもうバグ修正しかしないようですし、いつかは他のプラグインに乗り換えるのかな(面倒くさい……)とは考えていました。そんな折に Neovim へ移行することにしたので、これを機に見通しの悪い .vimrc
を含め設定ファイルを見直して整理して、さらに Dein.vim に移行してみました、というのが今回の内容です。話が横道に逸れますが、Vim にプラグインマネージャが浸透し始めたのは 2010 年頃 のようで、自身も pathogen.vim
、Vundle
と使ってみて 2012 年の終わり頃から NeoBundle
を使ってきました。変化の早さに驚くばかりです。
さて話を戻して、このトピックに関しては日本語の情報がたくさんあります。ここ、ここ、ここ、ここ、ここ、ここ……(たぶんまだまだある)。これらの情報に加えて、SpaceVim の設定と、Dein.vim
の作者である Shougo さんの 環境 を参考に設定してみました。なるべく複雑にしないことを目標に。
結果、このような構成になりました。
~/.config/nvim/ ├── config │ ├── dein.toml │ ├── dein.vim │ ├── dein_lazy.toml │ ├── dein_local.toml │ ├── init.vim │ ├── main.vim │ └── settings.vim ├── init.vim
init.vim
は config/main.vim
を読み込み、この config/main.vim
は同じディレクトリにある init.vim
、dein.vim
、settings.vim
を順に読み込む、という感じです。dein.vim
は dein.toml
、dein_local.toml
(ローカルに保存してあるプラグイン)、dein_lazy.toml
をそれぞれ dein#load_toml()
します。
基本的には、SpaceVim の init.vim
および config/init.vim
をほとんどそのままコピーして、.vimrc
内のプラグインに関する記述を TOML ファイルに、残った設定を settings.vim
に移行しました。TOML ファイル内で、プラグインのインストール情報(repo
キー)と共に関連する設定を hook_*
というキーでまとめて書いておけるのがすっきりして良いなと思ってます。
例えば、こんな感じ。
[[plugins]] repo = 'ctrlpvim/ctrlp.vim' hook_add = ''' let g:ctrlp_map = '<Leader>cp' '''
ちなみに hook に関する情報は ここ が詳しそうです。
まとめ。Neobundle
から Dein.vim
へ移行しました。次回は、新しく導入したプラグインの紹介編です。