Quantcast
Channel: Vimタグが付けられた新着記事 - Qiita
Viewing all 5692 articles
Browse latest View live

vimをはじめて3ヶ月の僕が初心者に紹介するvimコマンド

$
0
0

最初に

いざ、まとめてみると、めっちゃ多くなったので、個人的に最低限必要な便利コマンドをまとめておきます.(とか言いつつ、バカみたいに多い.....)

vimにはモードがあるのはご存じ?

  • ノーマルモード
  • インサートモード
  • ビジュアルモード
  • コマンドモード

ノーマルモードがモードの軸になっています.
Escを押せば、ノーマルモードに戻ります.
(迷ったら、連打ダダダダダダ....)

以下、:が書いているやつがコマンドモードです.
:noh検索でハイライトしてるやつを消す.(nohlsearch)

あと、ノーマルモードでの移動がhjklでできるのが、面白いですよね.
なれてしまうと、キー移動が面倒になってきますよ(笑)

コマンド一覧

ノーマルモード

モード変更

おすすめはoですね.行末にいなくても改行できるのが神

cmdfunction
iインサートモードへ
o下に行を追加して、インサートモードへ
vビジュアルモードへ
C-vビジュアルモード矩形

移動

C-uC-dは意外と便利で、長文の移動は流石にhjklではキツいっす.

cmdfunction
gg最初の行に移動
G最後の行に移動
C-u1ページ上に移動
C-d1ページ下に移動
0行頭に移動
$行末に移動
zz現在のカーソル位置を中心に持ってくる
w1ワード後ろに移動(ワード先頭)
e1ワード後ろに移動(ワード末尾)
b1ワード前に移動(ワード先頭)
b1ワード前に移動(ワード末尾)

編集

C-rがredoなんですね.あと、数字の増減がコマンドで出来るなんて、あと、vimrcの記述で数字だけじゃなくて、文字も増減できるんですよ.(a->b->c...)

cmdfunction
u1つ前に戻る (undo)
C-r1つ先に進む (redo)
xカーソル位置の文字を削除
dd1行削除
yy1行コピー (yank)
pコピーしたやつをペースト (paste)
C-a数字をインクリメント
C-x数字をデクリメント

 検索・置き換え

ここは''で囲まれたやつは変更できる

cmdfunction
r '1word'カーソル一の1文字を'1word'に置き換え
/'word''word'で検索してハイライト
:%s/'before'/'after'/'before'から'after'に置き換え

 その他

cmdfunction
:w上書き (write)
:q終了 (quite)
:q!上書きせずに強制終了

インサートモード

コレはMakefileくらいでしか使わないですけど

cmdfunction
C-v + tabvimrcの設定でtabきーがスペースになっちゃた時にtabを打つ方法

最後に

本当は便利コマンドはもっといっぱいあって、奥が深いんですよね.
個人的にワード単位での処理ができるのが面白いんですんが、
それはまた別の記事で(書くとは言っていない.)


他人のvimrcでコーディングをする

$
0
0

この記事はVim Advent Calendar 2017 15日目の記事です。

12月も早いもので15日です。もう半分ですね。
今回この記事を書くきっかけになったTweetを載せておきます。

 本題

さて、Vimmerにとってのパンツ、もとい”褌”であるvimrcですが、みなさんはゼロから書きましたか?
はっきり言って僕は書いてません。
コピペからはじめました。
Vim Bootstrapとかいう便利なツールもありますが、それはなんか違うな―って人向けに独断と偏見によるvimrcのタイプを紹介します。

1.はじめてのパンツはブリーフでした

まずは誰もが通る、ブリーフタイプのvimrcを紹介します。

"文字コードをUFT-8に設定setfenc=utf-8" 行番号を表示setnumber" シンタックスオンsyntaxon"バックスペースでなんでも消せるようにするsetbackspace=indent,eol,start" 入力モード中に素早くjjと入力した場合はESCとみなすinoremap jj <Esc>" ESCを二回押すことでハイライトを消す
nmap <silent><Esc><Esc> :nohlsearch<CR>

というか、これだけあれば最低限なんとかなるんじゃないですかね。
ちなみに僕は小学校中学年くらいまでブリーフを履いてました。
宿泊学習の時にちょっと恥ずかしいんじゃないか!?と誕生日プレゼントにトランクスがほしいと言ったのはいい思い出です。

2.ちょっと背伸びして履いたトランクスタイプ

次にちょっと大人の階段を登ってトランクスタイプのvimrcにカスタムしてみましょう。
vimrc、Vimのカスタムで最も手っ取り早いのは、やはりPluginの導入でしょう。
ここでおすすめPluginの紹介を!と思いましたが、uypさんがVim Bootstrap 基本プラグインという良まとめを書いていらっしゃるので割愛します。
個人的にいつも使っているのは、

  • NERDTree
  • vim-go

の2つです。

3.在るべきとろこに収まるボクサータイプ

同じく大人の階段を登ってボクサータイプのvimrcにカスタムしてみます。
ここのカスタムは"きれいで実用的なvimrcを作る"ことに収束して行きます(独断)。
あと、アレです。
vimrcの先頭に書いてあるやつです。

"        _           " __   _(_)_ __ ___  " \ \ / / | '_ ` _ \ "  \ V /| | | | | | |"   \_/ |_|_| |_| |_|"                  

もちろん僕のvimrcにも書いてあります。
アスキーアート テキスト
とかでググるといい感じの海外サイトがヒットします。

僕はもう10年近くボクサー派です。
ずっと地元企業であるユ◯ク◯のボクサー(前とじ)を愛用していましたが、最近見かけなくなったので
無◯良◯のボクサー(前とじ)に鞍替えしました。
でも、Vimからは鞍替えしてません。

4.人とかぶるのが嫌だ!我道を行く越中褌タイプ

ここまで来るともうこだわりの塊ですね。
こういう方々のvimrcがみたい!って人は、Githubとかでvimrcでレポジトリ検索すると良いと思います。
14425件もヒットしました。みんなVim大好きですね。
僕は使えればいいやの精神なので、ボクサー止まりです。

5.人は生まれたままの姿が一番美しい。ノーパンタイプ

最後は、生まれたままの姿、vimrc無しという荒業です。

ここで一句。

一度で良いから見てみたい
全裸で Vimを 使うとこ(字足らず)

僕には無理そうですが、サーバサイドを触る時はとりあえずノーパンVimを使うことがあるので
なんとかなる気がしますね。

さぁあなたはどのタイプでしたか?

Vimのレジスタを使う

$
0
0

Vimのレジスタを5秒後に使えるように最小限だけ書く。

レジスタへ登録

ノーマルモード(ESCを連打して戻ったモード)で操作する。

vim
aaa
bbb <-- ここの行にカーソルを置いて "ayy を実行する。
ccc
ddd
文字意味備考
"レジスタ操作始めるよ:w(保存)のコロンは「コマンド始めるよ」
aaという名前を使うよ。名前はa~zまで使える
yyヤンク(yy=行コピー)だから登録するよ。2yy(2行コピー)等でもOK

これで レジスタa に bbb を登録。

レジスタ内容をペースト(ノーマルモード版)

vim
aaa
bbb
ccc <-- ここの行にカーソルを置いて "ap と入力する。
ddd

↓↓↓

vim
aaa
bbb
ccc
bbb <-- 行コピー内容がペーストされる。
ddd
文字意味備考
"レジスタ操作始めるよ:w(保存)のコロンは「コマンド始めるよ」
aaという名前を使うよ。名前はa~zまで使える
pペーストだから登録内容を呼び出すよ。PでもOK(挿入位置が変わる)

レジスタ内容をペースト(インサートモード版)

文字入力するインサートモードでレジスタ内容を使うときは ctrlキー + r
vim.png
レジスタの印(”)が出てくるので、あとはレジスタ名(aとか)を入力するとペーストできます。

PlantUML のコードをインデント略記から生成する Vim プラグイン(雑)

$
0
0

多用するのでプラグイン作ってみた。
classって書いたりpackage ... {って括弧書いたり面倒だよね。

超適当配布なので VimScript 1ファイル製。

仕様

変換ルール

記法変換備考
. foopackage foohtml の class 属性のイメージで . にした
# foonamespace foohtml の id 属性のイメージで # にした
+ Fooclass Foo
- Fooenum Foo
* Foointerface Foo
空行捨てられる実装辛くてどーでも良くなってしまった
それ以外そのまま線とかコメントとか

HTML のリスト記法のイメージなので、

. foo
  + FooId
  # FooType

package foo {
  class FooId
  enum FooType
}

になるってこと。

ソース

command! PlantVim call PlantVim()function! PlantVim()call s:init(getline(1,'$'))let node = s:subs(0)

    execute 'normal ggdG'call s:put('@startuml')call s:put('')call s:indentingSetLine(node,'')call s:put('')call s:put('@enduml')

    execute 'normal Gddgg0'endfunctionfunction! s:init(input)letg:n=0letg:input = filter(a:input,'v:val != ""')letg:max = len(g:input)-1endfunctionfunction! s:subs(depth)let xs = []whileg:n<=g:max && s:depth(g:input[g:n])>=a:depthletg:n=g:n+1if s:depth(g:input[g:n-1])==a:depthif s:needParse(g:input[g:n-1])=='true'let parsed = s:parse(g:input[g:n-1])let parsed['subs'] = s:subs(a:depth +1)let xs = xs + [parsed]elselet xs = xs + [{'line': g:input[g:n-1],'output': 'raw','subs': []}]endifendifendwhilereturn xsendfunctionfunction! s:depth(line)letx=0forcin split(a:line,'\zs')ifc==' 'letx=x+1elsebreakendifendforreturnx / 2endfunctionfunction! s:parse(line)let type = {'.': 'package','#': 'namespace','+': 'class','-': 'enum','*': 'interface'}[split(a:line,'^ ')[0][0]]let containable = get({'package': 'containable','namespace': 'containable'}, type,'no_contains')let content = split(a:line,' ')[1]return {'line': type . ' ' . content,'output': containable}endfunctionfunction! s:needParse(line)return(a:line =~'\.\|#\|+\|- \|\*')==1 ? 'true' : 'false'endfunctionfunction! s:indentingSetLine(node, pad)for elm ina:nodeif elm['output'] =='containable'call s:put(a:pad . elm['line'] . ' {')call s:indentingSetLine(elm['subs'],a:pad . '  ')call s:put(a:pad . '}')elseif elm['output'] =='no_contains'call s:put(a:pad . elm['line'])elsecall s:put(elm['line'])endifendforendfunctionfunction! s:put(line)call append(line('$')-1,a:line)endfunction

導入

上のファイルをplant.vimという名前で保存して、vi を起動して:so ~/Downloads/plant.vimをする。(パスは読み替えて)

インデント略記が書き終わったら:PlantVimとすると変換される。

デモ

アニメ

こうなる
model.png

おしまい

whileとかグローバル変数と添字アクセスとか数年ぶりに書いた。ちょー辛い、もう二度とやりたくない。

本当は改行を保ちたいとか不可逆だしファイルを書き換えちゃうのでやり直しが効かないとか対応したかったけど、これ以上を VimScript 1ファイルでやるのはもう無理。

気に入って、かつ機能追加したくなったらメインロジックは全部 haskell か何かに移して VimScript はすっかすかにする。

ノシ

vimのおすすめしたい小技集

$
0
0

vimを業務で使い始めて約半年がたちました!
その過程で私が手にしたよく使う小技をいくつか紹介します!

検索系

現在のカーソル上の文字を検索

編集モードで検索したい文字列にカーソルを合わし*を押してあげるだけです!

asutarisuku.gif

複数の文字を検索

|を使うことで複数の文字列を検索することができます!

/検索文字列\|検索文字列2

orsearch.gif

検索で役立つvimrcの設定

.vimrc
setincsearch" インクリメンタルサーチ. 1文字入力毎に検索を行うsetignorecase" 検索パターンに大文字小文字を区別しないsetsmartcase" 検索パターンに大文字を含んでいたら大文字小文字を区別するsethlsearch" 検索結果をハイライト

vimgrepとQuickfixで検索結果一覧を表示!

通常の検索も便利ですが、vimgrepとQuickfixを用いた検索は検索結果一覧を表示できるの便利です!
画面移動を行ってEnterを押すだけで対象の行まで移動してくれるので非常にオススメです!

コマンド

編集モードで下記を入力
:vim検索文字列(正規表現も使えます!)検索対象ファイル

vimrcの設定

.vimrc
" vim grepすると自動的にあたらしいウィンドウで検索結果一覧を表示する
autocmd QuickFixCmdPost *grep* cwindow

ファイル内検索

現在開いているファイル内で文字列を検索する際は%を使用します!

編集モードで下記を入力
:vimfunction %

vimgrep1.gif

別ファイル内の文字列検索

srcディレクトリ配下のファイルから特定の文字列を検索する場合

編集モードで下記を入力
:vimfunction src/*

vimgrep2.gif

移動系

タイプした文字が次に出てくるところに移動

編集モードでfを押した後に任意の文字列を入力すると、その文字列が次に現れるところに移動します。

(まで移動したい時:f(

fidou.gif

画面移動

半画面下:Ctrl + d
半画面上:Ctrl + u
ファイルトップ:gg
ファイルの最後:G

idou.gif

入力&削除系

1行削除:dd
1単語削除:de
削除した行をペースと: dd + p
カーソルより後ろの文字列削除:D

delete.gif

{}'', ()の中の文字をまとめて削除

di'''ないの文字をまとめて削除します!
また、削除して入力モードに入りたい婆はci'と入力します。
()内を削除したい場合はdi(, ci(に変わるだけです!

個人的にはコレがかなり優秀です!
DBのIPや条件文を修正する時に大活躍してます

kakko.gif

ヴィジュアルモード

編集モードでvを押すと、ヴィジュアルモードになります。
その状態でカーソルを移動、yを押すと範囲コピーができます!
yではなくxを押すと選択した範囲を切り取れます!

visual.gif

矩形選択最高です

Ctrl + vで矩形選択になります。
その状態で、yを押すと選択した範囲をコピーします!

また、選択している状態でIを入力後、特定の文字を入力しESCすると選択した箇所に入力した文字を入れてくれます!

kukei.gif

vimの動作環境に関する小技

カラースキーマ編

molkaiを設定した時、macの時は色鮮やかなカラースキーマが設定されますが、別の環境だと色合いがおかしいときがあります。そんな時はTERM変数を確認してください!

macでのvim:カラースキーマmolokai
xterm-256.png

debianでのvim:カラースキーマmolokai
xterm.png

TERM変数について

TERM変数は扱う端末の種類を表しています。

mac, debian, centosなど、linux系のOSでTERM変数をechoしてあげると、異なる値が出てきます。

mac
$ echo$TERM
xterm-256color
debian
root@1896d623ecce:/# echo$TERM
xterm
root@1896d623ecce:/#
centos7
[root@c7154b6a2960 /]# echo $TERM
xterm[root@c7154b6a2960 /]#

termとxterm-256colorではcolorが違うということがわかります!

xterm-256color: colors#256, cols#80, it#8, lines#24, pairs#32767,
xterm: colors#8, cols#80, it#8, lines#24, pairs#64,

vimでカラースキーマを使うにあたり、TERM変数は重要

この流れだと、わかるとおもいますがxtermだと256colorに対応していないため綺麗なカラースキーマが実現されません。

そのため、新しく環境を用意した際などはTERM変数を確認するようにしましょう。
echoでも問題ないですしenvコマンドを打つと登録されている環境変数一覧を確認できます!

debian
root@1896d623ecce:/# envHOSTNAME=1896d623ecceNJS_VERSION=1.13.6.0.1.14-1~stretchNGINX_VERSION=1.13.6-1~stretchPWD=/HOME=/rootno_proxy=*.local, 169.254/16TERM=xtermSHLVL=1PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin_=/usr/bin/env

その後、TERM変数にxterm-256colorが入るように設定してあげましょう

debian
root@1896d623ecce:/# echoexportTERM=xterm-256color >> ~/.bashrc

Vim のエラーメッセージから Vim script を追う

$
0
0

環境は Windows。

そろそろ Python2 とはお別れして Python3 とだけ仲良くしたいので、Python2 のない生活を送っていたところ、Vim から gist を編集できる便利プラグインの vim-gistaでエラーが出てしまった。

function gista#autocmd#call[14]..<SNR>159_on_BufWriteCmd[13]..gista#command#patch#call[14]..gista#resource#remote#patch[17]..gista#resource#remote#get[19]..159[9]..157[34]..<SNR>137_request[33]..166 の処理中にエラーが検出されました:
行   94:
E887: このコマンドは無効です,ごめんなさい. Python の site モジュールをロードできませんでした.

gista#autocmd#call[14]は gista#autocmd#call の 14 行目を読めばいいのじゃろ? くらいはわかるのだけれど末尾とか追うの辛すぎる……と思っていた。

Vimmer の集う Meguro.vimで質問したところ thinca さんに一瞬で便利情報をいただけた。

エラーメッセージの 157[34]から :verbose function {157}を実行すると、対象の関数がわかる。

   function 157(...) abort dict
最後にセットしたスクリプト: ~\_vim\dein\repos\github.com\lambdalisue\vim-gista\autoload\vital\__vim_gista__\Web\API\GitHub.vim
1    if a:0 == 3
2      let settings = a:3$
3      let settings.method = get(settings, 'method', a:1)$
4      let settings.url = get(settings, 'url', a:2)$
5    elseif a:0 == 2$
6      if type(a:2) == type({})$
7        let settings = a:2$
8        let settings.method = get(settings, 'method', 'GET')$
9        let settings.url = get(settings, 'url', a:1)$
10     else$
11       let settings = {}$
12       let settings.method = get(settings, 'method', a:1)$
13       let settings.url = get(settings, 'url', a:2)$
14     endif$
15   else$
16     let settings = a:1$
17   endif$
18   let settings.url = settings.url =~# '^https\?://' ? settings.url : self.get_absolute_url(settings.url)$
21   let settings.headers = extend( s:_get_header(self.get_token()), get(settings, 'headers', {}),)$
25   " Most of API request is json$
26   let settings.headers = extend({ 'Content-Type': 'application/json',}, settings.headers)$
30   " neovim currently does not support 'bindeval'$
31   if has('nvim')$
32     let settings.client = ['curl', 'wget']$
33   endif$
34   return s:HTTP.request(settings)$
   endfunction

ファイル名だけなら :filter 157 scriptnamesで。

157: ~\_vim\dein\repos\github.com\lambdalisue\vim-gista\autoload\gista\util.vim

便利。

んで、結局 VimからPython 3.xを使うと落ちることがある · Issue #610 · vim-jp/issuesと同じ原因で Pythoon2 との付き合いが続くということかな?

Vim patchダイジェスト [2017/12] (仮)

$
0
0

Vim patchダイジェスト [2017/12] (仮)
(8.0.13618.0.1373)

  • 8.0.1373: Windows GUI: GUI開始時に'renderoptions'のエラーチェックをおこなうようにしました。
  • 8.0.1372: プロファイルログにinvalid byte sequenceが含まれることがある件を修正しました。
  • 8.0.1371: Windows CUI: Shift-Insertが効かなくなっていた件を修正しました。
  • 8.0.1369: Windows GUI: 画面描画処理においていくつかのパフォーマンスの改善をおこないました。
  • 8.0.1368: terminalウィンドウのステータスラインやセパレーターがマウスでドラッグ出来ない件を修正しました。
  • 8.0.1366: カーソルがWinBar(ウィンドウツールバー)にあるときにBalloonが表示されてしまう件を修正しました。※commitコメントミス。こちらが正。
  • 8.0.1364: :four_leaf_clover:win_screenpos()を追加しました。
  • 8.0.1363: .stz で終わるスワップファイルでリカバリーがおこなえない件を修正しました。
  • 8.0.1362: highlightグループTerminalを使用した時にterminalウィンドウの色がおかしいのを修正しました。
  • 8.0.1361: :four_leaf_clover:'diffopt'の項目にhiddenoffを追加しました。指定時は'hidden'なバッファを閉じた場合に'diff'を解除するようになります。(関連URI: vim-jp/issues/1054)

凡例

表記意味
:four_leaf_clover:新機能、大幅な仕様変更
'hoge'オプション (:h options参照)
:hogeExコマンド (:h :index参照)
hoge()組み込み関数 (:h functions参照)
v:hogeVim定義済変数 (:h v:参照)
+hogefeature (:h +feature-list参照)

方針

こちらを参照。

MonoDevelop 6.3とJust Enough ViでVimライクなUnity開発

$
0
0

前置き

「EclipseならVrapper」、「IntelliJならIdeaVim」とIDEはVimな環境にする私。
Unity標準のMonoDevelopにもViモードというのがありますが、Shiftキーが効かないという致命的なバグがあり使い物にならず、
アドインマネージャーのVimAddinは入れるとMonoDevelopがクラッシュし、Unityを再インストールしても治りません。
(ユーザー\AppData内のUnityのデータを片っ端から消したら治りました…)
Visual Studio 2017 はプラグイン入れないといけないのでプロジェクトの他のメンバーに影響がでそうなので飛ばしました。

「UnityでVimって言ったらOmniSharpだよね」が大衆の意見のようですが、
「自分ってVimのフルCUIな画面でずっと開発し続けられるほど意識高くない…」GUIも欲しいのでOmniSharpも断念

で辿り着いたのが MonoDevelop 6.3 と Just Enough Vi を使う方法。
結構手こずったので記事に残そうと思います。
OS:Windows8.1
Unity:5.4.1f1(プロジェクト指定なので古め…

参考&MonoDevelopダウンロード先
https://forum.unity.com/threads/monodevelop-unity-6-x-preview-builds.472058/

注意

  1. MonoDevelop-Unity 6.x Preview Builds は名前の通り正式版ではありません。 デバッグモードでstatic変数の内容が見れないなど挙動が怪しい箇所があります。
  2. DLLの場所を移動したりと結構無理矢理です。
  3. Just Enough Viは":"からの操作がなかったりと、かなり機能は少ないです。名前の通り「これだけで十分」な機能だけを持ってきたようです。使ってみて確かに「これだけあればいっか」って思いました。

MonoDevelop-Unity 6.x Preview Buildsを入れる

下記からWindows用のZipをダウンロードします。
https://forum.unity.com/threads/monodevelop-unity-6-x-preview-builds.472058/
zipを展開する前に右クリック->[プロパティ]->[全般]の下部のブロック解除というのをしないといけないそうです。
image.png

Unityの設定

Unityで[Editor]->[Preference]->[External Tools]->[External Script Editor]に先ほど展開したMonoDevelopのexeを設定。
フォーラムの説明ではこれで完了ですが、
私はUnity上でスクリプトを開くとMonoDevelopが「MonoDevelopo.Projects.MSBUild.MSBUildEvaluationContextが初期化できなかった」という内容のエラーが出てプロジェクトが開けませんでした。
フォーラムでも何人か報告してます。
無題.png

原因はDLLが正しく読み込めなかったからのようです。
無理矢理ですが MonoDevelop\bin\MSBuild以下のDLLをMonoDevelop.exeと同じディレクトリに入れたら動きました。
言語ごとに分かれてる同名のDLLはjaを移動させてます。
コピーした一覧は下記です。

  • MonoDevelop\bin\MSBuild\dotnet.12.0\Microsoft.Build.Utilities.v12.0.dll
  • MonoDevelop\bin\MSBuild\dotnet.14.0\Microsoft.Build.dll
  • MonoDevelop\bin\MSBuild\dotnet.14.0\Microsoft.Build.Engine.dll
  • MonoDevelop\bin\MSBuild\dotnet.14.0\Microsoft.Build.Framework.dll
  • MonoDevelop\bin\MSBuild\dotnet.14.0\Microsoft.Build.Utilities.Core.dll
  • MonoDevelop\bin\MSBuild\dotnet.12.0\ja\Microsoft.Build.Engine.resources.dll
  • MonoDevelop\bin\MSBuild\dotnet.12.0\ja\Microsoft.Build.resources.dll
  • MonoDevelop\bin\MSBuild\dotnet.12.0\ja\Microsoft.Build.Utilities.v12.0.resources.dll
  • MonoDevelop\bin\MSBuild\dotnet.12.0\Microsoft.Build.dll
  • MonoDevelop\bin\MSBuild\dotnet.12.0\Microsoft.Build.Engine.dll
  • MonoDevelop\bin\MSBuild\dotnet.12.0\Microsoft.Build.Framework.dll

Just Enough Vi の設定

失敗

[Tools]->[Add-in Manager]でVimで検索してインストール ではないのでご注意ください。
上記で入れるとエラーメッセージすらないエラーになります。
image.png

原因不明、Unity向けにビルドされたときの設定が原因でしょうか?
別の方法を探すしかないです。

直接入れる

MonoDevelop Add-in Repositoryからaddinのファイル(mpackファイル)を直接ダウンロードします。
http://addins.monodevelop.com/Project/Index/214

このファイルを直接MonoDevelopで読み込む でもないのでご注意
Add-in Managerでファイルを読み込んでもうんともすんとも言わず、インストールもされません。

mpackファイルは中身はzipなので拡張子をzipにして開きます。
すると下記の二つのファイルがあります。

  • addin.info
  • JustEnoughVi.dll

あとはアドイン置き場 MonoDevelop\Addinsディレクトリ内にJustEnoughViなどの名前のディレクトリを作って上記二つを放り込むだけ...
では足りませんでした
無題.png

やっぱり無理だったんだ!なんてめげずに
素直にエラーメッセージ検索したら早々に下記のサイトがでてきました。
http://chomstudio.sblo.jp/article/173128609.html
上の「ブロック解除」って結構重要なものなんですね。。。
JustEnoughVi.dll も右クリック->[プロパティ]からブロック解除です。

完了

image.png
でました!インストールされてます。
エディタがVim風な操作になります。


tsuquyomiのマッピングを変更する

$
0
0

TsuquyomiでVim+TypeScriptの環境を触っていたときに、自分はCtrl+T:tabnewをマッピングしていたところがプラグインによってオーバーライドされてしまったのを変更したときのメモ。

後で読んだらREADMEにばっちり書いてあったけど、備忘録として。

デフォルトマッピングの無効化

letg:tsuquyomi_disable_default_mappings =1
map <buffer><Nop><Plug>(TsuquyomiGoBack)

とりあえず上を書いておけばCtrl+Tは取り戻せる。

そもそもプラグインのマッピングは再割当てできない?

そもそもvimrc側でプラグインによって割り当てられたマッピングは変更できないのだろうか。

Plugins are sourced after your vimrc so there's no way to override a plugin mapping in your vimrc if the plugin doesn't provide a way to do so.

このスレッドによると、そもそも設定ファイルの読み込まれる順番がvimrc→プラグインなので、vimrc側でやれることはないとのこと。なるほど。

余談

ちなみにプラグイン内部の実装で該当するのはこの部分

function! tsuquyomi#config#applyBufLocalDefaultMap()if(!exists('g:tsuquyomi_disable_default_mappings'))if!hasmapto('<Plug>(TsuquyomiDefinition)')
        map <buffer><C-]><Plug>(TsuquyomiDefinition)endifif!hasmapto('<Plug>(TsuquyomiSplitDefinition)')
        map <buffer><C-W>] <Plug>(TsuquyomiSplitDefinition)
        map <buffer><C-W><C-]><Plug>(TsuquyomiSplitDefinition)endifif!hasmapto('<Plug>(TsuquyomiGoBack)')
        map <buffer><C-t><Plug>(TsuquyomiGoBack)endifif!hasmapto('<Plug>(TsuquyomiReferences)')
        map <buffer><C-^><Plug>(TsuquyomiReferences)endifendifendfunction

思ったより読みやすかった。

【vimでscala-sbtプロジェクトを快適に開発したい】scala-sbt用のvim-compilerプラグインを作成

$
0
0

githubはこちら
※英語が苦手なので、READMEはかなりテキトーです
https://github.com/daikitigogo/vim-scala-sbt-compiler

このプラグインで出来ること

  • vimで設定済みのキーマップ叩くと、コンパイルエラーが出た場所に順にジャンプ出来る
  • 「sbt ~compile」で待機してても、更新されるごとにジャンプ出来る

最低限の設定

基本的にファイルタイプごとにvimプラグインを設定する場合は拡張子で判断しますが、sbtでは決まったディレクトリ配下のファイルはすべて同じファイルタイプとしたいので、sbtプロジェクトのルートパスを.vimrcに追加する必要があります。
こんな感じに。

~/.vimrc
let g:ssc_application_settings = {
\   "sample1" : {
\       "rootPath" : $HOME."/workspace/sample1",
\   },
\   "sample2" : {
\       "rootPath" : $HOME."/workspace/sample2",
\   },
\   "sample3" : {
\       "rootPath" : $HOME."/workspace/sample3",
\   }
\}

キーマップの設定

キーマップを設定する場合は、以下を設定してください。
※それぞれの使い方は後ほど説明します。

~/.vimrc
nmap [お好きなキー] <Plug>ScalaSbtCompilerMake
nmap [お好きなキー] <Plug>ScalaSbtCompilerShow
nmap [お好きなキー] <Plug>ScalaSbtCompilerNext
nmap [お好きなキー] <Plug>ScalaSbtCompilerSet

使い方

まず初めのキーマップ(ScalaSbtCompilerMake)を叩きます。
すると↑で設定したrootPathで「sbt compile」を実行し、コンパイルエラーがある場合はその場所にジャンプします。

その後、2番めのキーマップ(ScalaSbtCompilerShow)を叩きます。
エラーの詳細が見れます。(↓参照)

type mismatch;
 found   : Int(2)
 required: String
    val samp1 = new Sample(2)

次のコンパイルエラー箇所にジャンプするには3番めのキーマップ(ScalaSbtCompilerNext)を叩きます。

4番目のキーマップ(ScalaSbtCompilerSet)はsbtの継続的ビルド時に使用します。
まず、普段「sbt ~compile」と叩くところを「sbt -Dsbt.log.noformat=true compile | tee quickFixFile」のような感じにします。
※linuxの場合
※要するに、「sbt compile」コマンドの実行結果を別のファイルにも出力出来るようにしてください。(こんな感じでOKです。 sbt -Dsbt.log.noformat=true compile > quickFixFile)
※-Dsbt.log.noformat=trueは出力に色付けしないようにするオプションです。

4番目のキーマップ(ScalaSbtCompilerSet)では、デフォルトでrootPath直下のquickFixFileを読み込むように設定しています。
読み込むファイルを指定したい場合はコマンドで、「:SSCSet 任意のファイル」と入力してください。

すいません。説明があまり上手くないので(というか雑)、少しでも興味持った方は気軽にご質問ください。
すべてはscala-vimmerを増やしたい一心です。

一応、自分への備忘メモも兼ねて、vim-compilerプラグインの作成手順を書いておきます。
興味のある方はどうぞ。。

vimのmakeコマンドとは

vimでmakeコマンドを実行すると、makeprgに設定されているコマンドをパイプでteeに渡しつつ実行します。(ubuntuの場合)
具体的にいうと、以下のような感じに動きます。

:set makeprg=scalac
:make sample1
→scalac sample1 2>$1| tee /tmp/xxxx/1

2>$1が何なのかはよく分かっていないのですが、要はmakeprgで設定したコンパイル結果を別ファイルにも出力しておき、そのファイルをquickfixlistに読み込んでいるようです。
※quickfixlistとは、vimgrepとかにも使われる、まあvimの便利機能ですね。
※errorformatというものを正しく設定しておくことで、コンパイル結果をquickfixlistに読み込むことが出来ます。

vim-compilerプラグインの作り方

vimで「:compiler sbt」のような感じでコマンドを打ちます。
するとvimは$VIMRUNTIME/compiler/配下のsbt.vimファイルを探しに行きます。

makeでsbtを実行させるには、↑で書いたようにmakeprgにsbtを設定すれば良いので、$VIMRUNTIME/conpiler/配下にこんな感じのファイルを置きます。

$VIMRUNTIME/compiler/sbt.vim
 1 if exists("current_compiler")
 2   finish
 3 endif
 4 let current_compiler = "sbt"
 5
 6 if exists(":CompilerSet") != 2       " older Vim always used
 7 :setlocal
 8  command -nargs=* CompilerSet setlocal <args>
 9 endif
10
11 let s:cpo_save = &cpo
12 set cpo&vim
13
14 CompilerSet makeprg=sbt
15 CompilerSet errorformat=%A[%t%.%#]\ %f:%l:%c:\ %m,
16             \%Z[error]\ %.%#errors\ found,
17             \%Z[warn]\ %.%#warning\ found,
18             \%C[%.%#]\ %m
19
20 let &cpo = s:cpo_save
21 unlet s:cpo_save

まあ14行目〜18行目以外はvimプラグインを作る際のテンプレみたいなものなので、詳細は説明しません。
※基本、vimでscala書く人は僕よりvim上級者ではないかと勝手に決めつけているので。

で、14行目ですが、↑でも書いた通りmakeprg時の実行コマンドを設定しています。
これはまあそれだけです。

で、重要なのは15〜18行目、このerrorformatを正しく設定しないとコンパイルエラー箇所をジャンプすることが出来ません。
ただ、このerrorformatの設定が難解なんですよね

errorformat読み込み時のルール

  • %A以降に指定されたパターンが見つかった場合は複数行エラーの開始とする
  • %Z以降に指定されたパターンが見つかった場合は複数行エラーの終了とする
  • %C以降に指定されたパターンが見つかった場合は複数行エラーの継続とする

まあ、すいません。上手く説明出来ないですが、sbtでコンパイルした場合、こんな出力が出ると思います。

[info] Loading project definition from ~/workspace/vim-make-test/sbt/project
[info] Loading settings from build.sbt ...
[info] Set current project to My-Item-Search (in build file:~/workspace/vim-make-test/sbt/)
[info] Executing in batch mode. For better performance use sbt's shell
[info] Compiling 1 Scala source to ~/workspace/vim-make-test/sbt/target/scala-2.12/classes ...
[error] ~/workspace/vim-make-test/sbt/src/main/scala/sample/Main.scala:7:28: type mismatch;
[error]  found   : Int(2)
[error]  required: String
[error]     val samp1 = new Sample(2)
[error]                            ^
[error] ~/workspace/vim-make-test/sbt/src/main/scala/sample/Main.scala:8:17: not found: value Sample
[error]     val samp2 = Sample("Scala")
[error]                 ^
[warn] ~/workspace/vim-make-test/sbt/src/main/scala/sample/Main.scala:3:13: Unused import
[warn] import test._
[warn]             ^
[warn] one warning found
[error] two errors found
[error] (compile:compileIncremental) Compilation failed
[error] Total time: 2 s, completed 2017/12/17 0:07:21

これに対して、errorformatはカンマ区切りで指定された各パターンに一致するかを確認します。
1個目の指定だと、
- %tはエラー(警告)の種別を取得します()
- %.%#は正規表現の .* と同じ意味です。
- スペースは\でエスケープします。
- %fはファイル名を取得します。
- %lは行番号を取得します。
- %cは絡む番号を取得します。
- %mはエラーメッセージを取得します。

要するに、
[error] /home/daikitigogo/workspace/vim-make-test/sbt/src/main/scala/sample/Main.scala:7:28: type mismatch;
は、
[%t(エラータイプ)rror] %f(ファイルゲット):(行番号ゲット):(カラム番号ゲット) (残りはエラーメッセージ)
と解析され、
{type : "e", "file" : "~/workspace/vim-make-test/sbt/src/main/scala/sample/Main.scala", line : "7", col : "28", msg : "type mismatch;"}
こんな感じのオブジェクトに変換されます。(オブジェクト構成は例えです)

ダメですね。このerrorformatについては上手く説明出来る気がしません。
詳細は以下を、もしくは初心者で気になる方はお気軽にご質問ください(私もまだまだ理解が足りないとは思いますが。。)
- http://vim-jp.org/vimdoc-ja/quickfix.html#error-file-format

次はscala用のtag設定の予定。
ctagsを使うとすぐにvimで「scalaの関数定義先にジャンブ」とかが出来るようになるが、もうちょい使い勝手良く改良したい。

vimでscalaプログラミングの需要ってあるんやろうか?
相性は良いと思うんですが。。

scala-sbtプロジェクト用のvimコンパイラプラグインを作成

$
0
0

このプラグインで出来ること

  • vimでコンパイルエラーが出ている場所を順にジャンプ出来る

導入方法

deinとかNeoBundleを使っている場合は、いつも通り。
プラグインマネージャーとかを特に使用していない場合は、

git clone https://github.com/daikitigogo/vim-scala-sbt-compiler

として、クローンしたディレクトリをVIMのRUNTIMEPATHに追加する。

~/.vimrc
set runtimepath+=クローンしたディレクトリ

設定

基本的にファイルタイプごとにvimプラグインを設定する場合は拡張子で判断するが、sbtでは決まったディレクトリ配下のファイルはすべて同じファイルタイプとしたい。
なので、.vimrcにsbtプロジェクトのルートパスを設定し、その配下のファイルに.scala-sbt-compilerというファイルタイプを追加するようにしている。
※vimでは.区切りで複数ファイルタイプを付加出来る。

以下、設定例。

~/.vimrc
let g:ssc_application_settings = {
\   "sample1" : {
\       "rootPath" : $HOME."/workspace/sample1",
\   },
\   "sample2" : {
\       "rootPath" : $HOME."/workspace/sample2",
\   },
\   "sample3" : {
\       "rootPath" : $HOME."/workspace/sample3",
\   }
\}

キーマップの設定

4つほどキーマップを用意。

~/.vimrc
nmap [お好きなキー] <Plug>ScalaSbtCompilerMake
nmap [お好きなキー] <Plug>ScalaSbtCompilerShow
nmap [お好きなキー] <Plug>ScalaSbtCompilerNext
nmap [お好きなキー] <Plug>ScalaSbtCompilerSet

使い方

ScalaSbtCompilerMake

.vimrcに設定したルートディレクトリ上で「sbt compile」コマンドが実行される。
で、コンパイル結果をvimが解析し、コンパイルエラー箇所を順番にジャンプしていくことが可能となる。

  • vim上のカレントがルートディレクトリにある場合は、「:make compile」とコマンドを実行しても同じ
  • ScalaSbtCompilerMakeを実行した場合は、ルートに移動してから「:make compile」コマンドを実行、元のディレクトリに戻るということをしているだけ

ScalaSbtCompilerShow

エラーの詳細が見れる。

type mismatch;
 found   : Int(2)
 required: String
    val samp1 = new Sample(2)
  • vimの標準コマンドの「:cc」とほぼ同じだが、「:cc」の場合は改行含みのメッセージも1行で表示されてしまう
  • ScalaSbtCompilerShowから実行した場合は、複数行で表示されるようにしただけ

ScalaSbtCompilerNext

次のコンパイルエラー箇所にジャンプする。

  • これもほぼvim標準の「:cn」コマンドを実行しているだけ
  • ただし、ScalaSbtCompilerShowを正しく機能させるためにはScalaSbtCompilerNextを使う必要がある

ScalaSbtCompilerSet

sbtのルートディレクトリにあるquickFixFileというファイルをコンパイル実行結果として取得する。
これはsbtの継続的ビルドと一緒に使う想定。ターミナルから以下のようにコマンドを実行する。

sbt -Dsbt.log.noformat=true ~compile | tee quickFixFile

これでファイルが変更されたら自動的にコンパイルされるようになり、コンパイル結果はコンソールとquickFixFileというファイルに出力される。
ファイルを編集しながら現在のコンパイル状況を確認したくなった場合、ScalaSbtCompilerSetを実行すれば良い。
※「-Dsbt.log.noformat=true」は出力の色付けをなくすオプション(これを指定しとかないと端末制御コードも一緒にファイル出力されてしまう)

と、まあ色々と書いたものの、ほとんどvim標準コマンドを使いやすいようにラップしているだけ。
単純にvimコンパイラプラグインを作成する場合は、「makeprg」オプションと「errorformat」オプションを設定したvimファイルを、VIMRUNTIMEPATHのcompilerディレクトリ内に置けば良い。

makeprgオプションとは

例えば以下のように設定している場合、

sbt.vim
set makeprg=scalac

vimから「make hoge.scala」を実行すると「scalac hoge.scala」が実行される。
単純に「make」が「makeprg」に設定した内容に置き換わるだけ。

errorformatオプションとは

これが重要であり難解。今回設定した内容は以下のようなもの。

sbt.vim
set errorformat=%A[%t%.%#]\ %f:%l:%c:\ %m,
            \%Z[error]\ %.%#errors\ found,
            \%Z[warn]\ %.%#warning\ found,
            \%C[%.%#]\ %m
  • %A以降に指定されたパターンが見つかった場合は複数行エラーの開始となる
  • %Z以降に指定されたパターンが見つかった場合は複数行エラーの終了となる
  • %C以降に指定されたパターンが見つかった場合は複数行エラーの継続となる
  • %tはマッチ内容をエラータイプとして取得する(1文字限定マッチ)
  • %fはマッチ内容をファイル名として取得する
  • %lはマッチ内容を行番号として取得する
  • %cはマッチ内容を列番号として取得する
  • %mはマッチ内容をエラーメッセージとして取得する
  • %.%#は一般的な正規表現でいう .*

以下、sbtのコンソール出力例

 1 [info] Loading project definition from ~/workspace/vim-make- test/sbt/project
 2 [info] Loading settings from build.sbt ...
 3 [info] Set current project to My-Item-Search (in build file:~/workspace/vim-make-test/sbt/)
 4 [info] Executing in batch mode. For better performance use sbt's shell
 5 [info] Compiling 1 Scala source to ~/workspace/vim-make-test/sbt/target/scala-2.12/classes ...
 6 [error] ~/workspace/vim-make-test/sbt/src/main/scala/sample/Main.scala:7:28: type mismatch;
 7 [error]  found   : Int(2)
 8 [error]  required: String
 9 [error]     val samp1 = new Sample(2)
10 [error]                            ^
11 [error] ~/workspace/vim-make-test/sbt/src/main/scala/sample/Main.scala:8:17: not found: value Sample
12 [error]     val samp2 = Sample("Scala")
13 [error]                 ^
14 [warn] ~/workspace/vim-make-test/sbt/src/main/scala/sample/Main.scala:3:13: Unused import
15 [warn] import test._
16 [warn]             ^
17 [warn] one warning found
18 [error] two errors found
19 [error] (compile:compileIncremental) Compilation failed
20 [error] Total time: 2 s, completed 2017/12/17 0:07:21

6行目をerrorformatと比較すると

  • []の中の先頭1文字がエラータイプとして取得されるので、エラータイプは"e"となる
  • 半角スペース〜コロンまでの間がファイル名として取得されるので、ファイル名は"~/workspace/vim-make-test/sbt/src/main/scala/sample/Main.scala"となる
  • ↑のコロン〜次のコロンまでが行番号として取得されるので、行番号は7となる
  • ↑のコロン〜次のコロンまでが列番号として取得されるので、列番号は28となる
  • ↑のコロンの後、半角スペースを挟んで以降がエラーメッセージとして取得されるので、エラーメッセージは"type mismatch;"となる
  • %Aのパターンとマッチしたので、複数行エラーメッセージの開始と判断される

7〜10行目は

  • %Aや%Zのパターンとはマッチせず%Cのパターンとマッチするので、複数行エラーの継続と判断される
  • 6行目で設定されたエラーメッセージに、半角スペース以降の文字が追加されていく

11行目は

  • %Aのパターンとマッチするので、新しいエラーメッセージの開始と判断される
  • 新しいエラーメッセージが開始されると、6行目で設定されたエラーメッセージは自動的に終了となる模様

17行目は

  • %Zのパターンとマッチするため、複数行エラーの終了となる

このように設定方法は非常に分かりにくいが、これを正しく設定していれば、「:cfile 任意のファイル」コマンドで任意のファイルを解析&quickfixfileに設定することが出来る。

github

https://github.com/daikitigogo/vim-scala-sbt-compiler

VsVimとPerforceのコマンド活用で快適なコーディング生活を送る

$
0
0

最初に

記事中にある開発環境は以下のとおりです。

  • VsVimのバージョン:2.4.1.0
  • IDE:Visual Studio 2017
  • CLI:Windows PowerShell

また、本記事はVim Advent Calendar 2017の記事です。

結構ギリギリの投稿になってしまって申し訳ありません(´・ω・`)

目的

私が現在所属しているプロジェクトではUE4を用いたゲーム開発をしており、バージョン管理ツールにはPerforceを、IDEにはVisual Studio 2017を採用しています。最近がっつり開発していく中で、Windows PowerShellを使用し、Perforceのコマンドを打ち込んだり、開発コードをVSで書いたりが多くなってきています。

ただ私は、「やりたい事があって、そのコマンドが存在していることまではわかるんだけど、コマンド名自体が思い出せない。接頭辞さえ思い出せない。」という痴呆が多々あリます。そのため、ブラウザの新規タブを開き、コマンド探しの旅に出かける、という無駄な手順が発生しがちです…。

なので、少しでも開発の方に集中して時間を避ける様に、使用頻度が高いコマンド等を、この記事に集めておこうと思います。

あわよくば、誰か似た様な境遇の人の支えにも慣れたら幸いです。

VsVimとは

Visual Studio 2012以降で使用できるプラグインです。MSで開発されたものではなく、一開発者の方から生み出されました。Vimユーザーが快適にVSを操作できる様なキーバイディングを提供しています。

VsVim:https://marketplace.visualstudio.com/items?itemName=JaredParMSFT.VsVim

導入方法は以下の記事で詳しく説明されています。

参考:VsVimの宣伝!

Perforceとは

今回の記事では詳しい説明は省きますが、簡単に紹介をしておきます。

Perforce社から出ている有料の企業向けバージョン管理システムです。
Windows,Linux,MacOSでも動作するマルチプラットフォームで、ツール自体が軽快で高速に動作します。

GitやSubstanceとの比較も載せておきます。

image.png

ちなみに、もちろんPerforceにも様々なコマンドが存在しています。

コマンドリファレンス:http://www.toyo.co.jp/files/user/img/product/ss/help/perforce/r15.1/manuals/cmdref/index.html

コマンド一覧

⇧ Shift
^ Ctrl

共通操作(VS2017)

行の編集

キー動作備考
[^]+[X]行の切り取り未選択状態の行全体を切り取り
[^]+[C]行のコピー未選択状態の行全体をコピー
[^]+[⇧]+[L]カーソル行を削除行全体を削除(複数行を選択中は全ての行)
[Tab]行をインデント
[⇧]+[Tab]行をアンインデント

コメントの編集

キー動作備考
[^]+[K],[^]+[C]行コメント記号をトグル複数行を選択中はその行数分
[^]+[K],[^]+[U]ブロックコメント記号をトグル選択中は選択部分

ファイル/フォルダ自体の表示

キー動作備考
[^]+[Tab]開いているエディターの切り替え表示開いた後は^を押下したままTabで切り替えられる

検索/置換(シンボルに関しては後述)

キー動作備考
[^]+[⇧]+[F]全ファイルにまたがってキーワード検索をするポップアップ表示
[^]+[⇧]+[H]全ファイルにまたがって置換をするポップアップ表示
[F3]次を検索マッチワードがあればその単語で検索
[⇧]+[F3]前を検索同上

エディタ移動操作

キー動作備考
[^]+[-]前に表示していた箇所に戻る
[^]+[⇧]+[-]次の箇所に進む

コーディング時の操作

シンボル検索/表示

キー動作備考
[Alt]+[F12]シンボルの定義を表示シンボルは変数名、メソッド名のこと
[F12]シンボルの定義を表示基本はこっちの方が使い勝手が良い
[^]+[T]全ファイルにまたがって参照検索しファイルを開く
[⇧]+[F12]シンボル参照箇所のインライン表示[esc]で消せる

デバッグ操作

キー動作備考
[F9]ブレークポイントの切り替え
[F5]デバッグスタート又はコンティニュー
[⇧]+[F5]ストップ
[F6]ポーズ
[F10]ステップオーバー
[F11]ステップイン
[⇧]+[F11]ステップアウト

VsVimコマンド

モード切り替え

キー動作備考
[i]挿入モードカーソルの前から
[a]挿入モードカーソルの後から
[:]コマンドラインモード
[v]ビジュアルモード
[esc]ノーマルモード

ファイル操作

キー動作備考
[:]+[q]開いているファイルを閉じるエディタウィンドウが複数なら右から順番に

エディタ操作(ノーマルモード)

キー動作備考
[dd]カーソルがある行を切り取り[dd]の前に数値を入れて切り取る行数の指定が可能
[yy]カーソルがある行のコピー[yy]の前に数値を入れてコピーする行数の指定が可能
[P]カーソルがある行にペースト
[p]カーソルの下の行にペースト
[u]Undo
[^]+[r]Redo
[U]行に対して行った変更の全てを取り消す
[v]選択開始
[V]行選択
[Alt]+[⇧]+[矢印キー]矩形選択
[gv]直前の選択範囲を再選択

検索/置換(ノーマルモード)

キー動作備考
[/]+[文字列]前方検索
[?]+[文字列]後方検索
[#]カーソル位置の単語を前方検索
[*]カーソル位置の単語を後方検索
[n]次の候補
[N]前の候補
[gd]カーソル位置のローカル宣言を検索
[gD]カーソル位置のグローバル宣言を検索
[:]+[%s/from/to/g]ページ全体で置換fromが検索語句,toが置換語句
[:]+[32,50s/from/to/g]32〜50行目まで置換gは繰り返し、cなら一回毎に確認

テキスト操作(ノーマルモード)

キー動作備考
[x]1文字削除Deleteキーと同じ
[X]1文字削除BSキーと同じ
[D]カーソル位置から行末まで削除
[s]1文字削除して挿入モードへ切り替え
[S]現在の行を削除して挿入モードへ切り替え
[r]カーソル位置の一文字だけ置換
[R]置換モードに切り替え
[J]現在の行と下の行をスペースありで連結
[gJ]現在の行と下の行をスペースなしで連結

インデント操作(ノーマルモード)

キー動作備考
[⇧]+[>],[⇧]+[>]現在の行をインデント
[⇧]+[<],[⇧]+[<]現在の行を逆インデント

移動操作(ノーマルモード)

キー動作備考
[gg]最初の行へ
[G]最後の行へ
[数値]+[G]指定した行へ
[0]行の最初へインデント無視
[^(Ctrlではない)]現在の行の最初へテキストの最初
[$]行の末尾へ
[-]前の行の最初へ
[+]次の行の最初へ
[%]カーソル位置にある括弧に対応する括弧へ
[H]エディタの上端へ移動Hの前に数値で上から数えた行へ
[M]エディタの中央行へ移動
[L]エディタの下端へ移動Lの前に数値で上から数えた行へ
[^]+[o]前回のジャンプ位置へ戻る
[^]+[i]次回のジャンプ位置へ戻る
[z]+[↩︎]現在の行の最初へテキストの最初
[w]次の単語に移動
[b]前の単語に移動
[e]単語の末尾に移動
[W]次の単語に移動記号は無視
[B]前の単語に移動記号は無視
[E]単語の末尾に移動記号は無視
[f]+[一文字]カーソルを指定した文字まで移動3fiで3つ目のiまで移動
[t]+[一文字]カーソルを指定した文字の左端まで移動3tiで3つ目のiの左側まで移動

スクロール操作(ノーマルモード)

キー動作備考
[^]+[b]1画面上に移動
[^]+[u]半画面上に移動
[^]+[y]1行上に移動
[^]+[f]1画面下に移動
[^]+[d]半画面下に移動
[^]+[e]1行下に移動

Perfoceコマンド

使用頻度が高い順に並べてみました。

コマンド動作備考
p4 add指定した新規ファイルをチェンジリストに追加。参照URL
p4 edit指定したファイルを作業中にし、チェンジリストに追加。参照URL
p4 delete指定したファイルを削除としてチェンジリストに追加。参照URL
p4 cleanチェンジリスト内の全てのファイルを復元。参照URL
p4 lock作業中のファイルをロックしてサブミットされない様にする。参考URL
p4 unlockロックを解除する。参考URL
p4 submitチェンジリストに含まれている作業中のファイル群をディポにコミットする。参考URL
p4 syncディポの内容をクライアント側に反映させる。参考URL
p4 depot新規ディポ作成。参照URL
p4 diffローカルファイルとディポファイルとで比較を行う。参照URL
p4 grepパターンに一致する行を検索。参照URL
p4 helpPerforceのオンラインヘルプ情報表示。参考URL
p4 info現在のPerforceのバージョン情報などを表示します。参考URL
p4 openedチェンジリスト内にある作業状態のファイルをリスト表示する。参考URL
p4 rename指定したファイルの名前変更。参考URL
p4 revert作業中のファイルに加えられた変更を全て破棄する。参考URL
p4 switch別のストリームに切り替える事ができる。参考URL

LaravelをVimで開発してて、マジックメソッドの定義元にタグジャンプしたい時

$
0
0

恥ずかしながら、 ctagsの設定ちゃんとしてませんでした。情弱でした。

下記の設定を ~/.ctagsに書いておきます。

~/.ctags
--regex-php=/get([a-z|A-Z|0-9]+)Attribute/\1/
--regex-php=/scope([a-z|A-Z|0-9]+)/\1/

これで ctagsを打てば、Vimの C-]でLaravelのマジックメソッドである getHogeAttributescopeOfHogeに飛べるようになります。

かなり快適になりそう。

Vimと外部コマンドをつなぐ!コマンド(仮称)

$
0
0

この記事はVimのアドベントカレンダー(その2)の18日目の記事です。

Vimを使っているとき、
「あの外部コマンドの出力結果が欲しい」、
「この範囲をあの外部コマンドで処理したい」、
「Vimを抜けるのが面倒だがちょっと外部コマンドを実行したい」、
といったときは無いでしょうか。

そういったときに要望を叶える機能がVimにはあります。
それが!コマンド(仮称)1です。

この記事ではこの!コマンドについて紹介します。

!がつく4つのコマンド

:!

http://vim-jp.org/vimdoc-ja/various.html#:!cmd

外部コマンドを実行するコマンドです。
mkdirfirefoxといった単体で実行する外部コマンドを実行したいときに使います。

" cssというディレクトリを作成する:!mkdir css" 今開いているファイルをFirefoxで開く(%は後述する特殊文字で今開いてるファイルに置き換えられます):!firefox %

よく使う外部コマンドがあるなら以下のような設定をvimrcに一時的に書くと楽かもしれません。

" F5で今開いているJavaのプログラムをコンパイルし実行するnnoremap<F5> :<C-u>javac %; java %:r<CR>" F6で今開いているJavaのプログラムをコンパイルするnnoremap<F6> :<C-u>javac %<CR>

:{range}!

http://vim-jp.org/vimdoc-ja/change.html#filter

バッファの中身を外部コマンドで処理するコマンドです。
{range}には.%'<,'>などの範囲を指定します。
sedawkといったパイプで繋いで使うコマンドを使ってテキストを処理したい際に使います。

" カーソル行に書いた数式を計算結果に書き換える:.!bc" カーソル行の文字列をbase64に変換する:.!ruby-r base64 -nle 'puts Base64.encode64($_)'" 選択範囲にある全ての数字をその数字に1を足した数字へと書き換える:'<,'>!perl -pe's/\d+/$&+1/ge'" 管理者権限を得て現在のファイルに書き込みを行う:%!sudo tee %

範囲は直接指定してもいいのですが、このコマンドに入るためのキーマップが用意されているのでそれらを使うとより気軽にフィルタコマンドを利用できると思います。

モードキーマップ内容
ノーマルモード!{motion}カーソル行から{motion}で指定した範囲までを外部コマンドで処理する
ノーマルモード!!カーソル行を外部コマンドで処理する
ビジュアルモード!選択範囲を外部コマンドで処理する

またコマンドはシェルによって処理されるため、パイプやリダイレクト、コマンド置換、プロセス置換といった機能も使うことが可能で、以下のようなことも可能です。

" httpbinで取得したuuidを書き出す:.!curl -s httpbin.org/uuid | jq -r .uuid" カスミガセキ・ジグラットの階数を書き出す:.!seq 700| awk '\!/4|9/'|wc-l" ファイル内の頻出行トップ10を書き出す:%!sort| uniq -c|sort-rn | head -10| sed 's/^ *[0-9] //'

:r!

http://vim-jp.org/vimdoc-ja/insert.html#:r!

外部コマンドの出力結果をバッファに読み込むコマンドです。

datemanなどの入力無しで扱うコマンドの出力結果が欲しいときには使います。

" 今日の日付を読み込む:r!date +%Y-%m-%d" curlのマニュアルを読み込む:r!man curl" 自身のグローバルIPアドレスを取得する:r!curl -s ifconfig.io

:w !

http://vim-jp.org/vimdoc-ja/editing.html#:w_c

外部コマンドの標準入力にバッファの中身を流し込んで実行するコマンドです。
w!を繋げてはだめで:w !といったように間に空白を挟む必要がある点に注意(例えば:w!shとすると今開いているファイルがshという名前で保存されます)

bashperlなど標準入力から読んだスクリプトを実行できるコマンドを実行する際に使います。
こちらを改めて使わずとも:!:{range}!で済むケースも多いかもですが。

" 今開いているファイルに書いたシェルスクリプトを実行する:w!sh" 今開いているファイルに書いたRubyのスクリプトを実行する:w!perl

特殊文字

http://vim-jp.org/vimdoc-ja/cmdline.html#cmdline-special

!コマンドを使う際に便利なもの……でかつ、気をつけないといけないものとして、特殊文字というものがあります。

特殊文字は、%:rで拡張子を省いたファイル名が得られたり、%:p:hでファイルのあるディレクトリの絶対パスが得られたりと便利なものなのですが、
引数のどこかで%#を使ってハマることのほうが多い気がします。
何か実行結果がおかしいと思ったら以下の文字を疑ってみてください。

特殊文字展開内容
%カレントファイル名を展開します
#代替ファイル名を展開します
!前回実行したコマンドを展開します
<なになに>なになににはcwordcWORDが入り、それによって展開内容が変わります

いずれも以下のようにバックスラッシュ(Windowsだと円マーク)を文字の前につけることでエスケープできます。

文字展開内容
%カレントファイル名
\%%
\\%\%
\<cword><cword>

また、エスケープせずに特殊文字を意図して使う場合、今度は%<cfile>をそのまま使うとシェルのメタ文字がエスケープされない点に注意。
基本的には%:S<cfile>:Sといったように、特殊文字の末尾に:Sをつければ大丈夫ですが、
<cword><cWORD>につけても:Sが無視される、シェルがfishのようにエスケープの仕方が違うシェルだといけない、などあるので、
エッジケースをカバーしないといけない場面では他の手段を利用したほうがいいと思います。
逆にいえば展開する内容が分かっていて、手打ちで使うだけ、vimrcの中で定義した関数の中で使うだけ、という感じであれば付けても付けなくても。

" カーソル上にあるファイル名のファイルを作成する:!touch <cfile>:S" 今開いているファイルを削除する:!rm %:p:S

外部コマンドを扱う他の手段

!コマンドはどちらかというとユーザが直接使うのに向いていて、
Vim scriptの中で使う分には不都合な部分があります(DOS窓が出る、入出力にバッファが必要、同期的に実行してしまう、など)

そのため、Vimでは外部コマンドを利用するための手段が別途用意されています。
Vim scriptを書く際には以下の機能を利用することになると思います。

http://vim-jp.org/vimdoc-ja/eval.html#system()
http://vim-jp.org/vimdoc-ja/channel.html#job

また、Vimで作業するより、シェルで作業するほうがやりやすい場合もあるでしょう。
その際には以下の機能を利用することになると思います。

http://vim-jp.org/vimdoc-ja/starting.html#CTRL-Z
http://vim-jp.org/vimdoc-ja/various.html#:sh
http://vim-jp.org/vimdoc-ja/terminal.html#:terminal

全部を使わないといけないということはなくて、目的にあった、自分の作業の仕方にあったものを使えば大丈夫です。
何かしら不満が出てきたら上記の機能を試してみるぐらいがいいのかなと。

余談

!コマンドはVimに限らずedやviでも使えます。

http://pubs.opengroup.org/onlinepubs/9699919799/utilities/ed.html
http://pubs.opengroup.org/onlinepubs/9699919799/utilities/vi.html

Vimは無いがviとPerlはある……という場面がもしあれば重宝すると思います。


  1. 仮称なのは、その、このコマンド群の名称を見つけられなかったため……(もし知っている方がいたら教えてほしいです) 

Jupyter notebookのスニペット機能を使って機械学習案件の生産性をあげる話

$
0
0

デフォルトのJupyter notebookにスニペット(ショートカット)呼び出しの拡張機能を追加し、生産性をあげた話です。

以下の順に沿って記していきます。

  1. 前提となる環境
  2. 拡張ツールの導入(jupyter_contrib_nbextensions)
  3. デフォルトスニペットの使用
  4. オリジナルスニペットの登録

前提となる環境

自宅で使っているMacBooK Airを用います。

2011 MacBook Air 3,1
1.4 GHz Intel Core 2 Duo
2 GB 1067 MHz DDR3
128 GB SSD
High Sierra 10.13.2

また、pyenv 1.1.5 + anaconda3-4.0.0でJupiter notebookの環境を実現しています。

拡張ツールの導入(jupyter_contrib_nbextensions)

データベースへの接続や、matplotlibでのグラフの書き方など、頻繁に使用するが一から書きたくないものはスニペット化して、すぐに呼び出せるようにすると楽です。

これを実現するために、jupyter_contrib_nbextensionsを用います。
https://github.com/ipython-contrib/jupyter_contrib_nbextensions

~$ conda install -c conda-forge jupyter_contrib_nbextensions

上記コマンドを実行したら、Jupyter notebookを立ち上げ、下記にアクセスしましょう。(お使いの環境によって適宜読み替えてください。)

localhost:8888/nbextensions

するとこのような画面が立ち上がります

スクリーンショット 0029-12-17 23.55.44.png

この中から必要そうなものを選びチェックボックスをつけます。それぞれの説明は下の方にちゃんと書いてありますので、それを読みましょう。

おすすめは下記です。

  • Nbextensions dashboard tab(ほぼ必須。Extensionsのタブを新しく追加してくれる。)
  • Snippets Menu(スニペットを登録するのに用いる)
  • ExecuteTime(セルごとの実行時間を示してくれる)

他にも使える拡張はたくさんあります。ただ欲張ってたくさん入れすぎるとJupyter notebookの起動が遅くなりますのでそこは注意してください。

デフォルトスニペットの使用

さて、上記の拡張のチェックボックスをつけたら、

localhost:8888/tree

に戻り適当なノートブックを開いてください。下記のようにスニペットのタブが増えているのが分かるかと思います。

スクリーンショット 0029-12-18 0.10.20.png

このうちNew array of given shapeを選びますと、セル上に下記のように書かれます。

スクリーンショット 0029-12-18 0.12.33.png

デフォルトで登録されているものでも、かなり使えますので是非使用してみてください。

オリジナルスニペットの登録

さて本題です。自分だけのスニペットを登録する手順について記します。

まず、~/.jupyter/custom/custom.jsを編集し、サンプルのスニペットを加えてみましょう。

~$ mkdir ~/.jupyter/custom/ & touch ~/.jupyter/custom/custom.js
~$ vim ~/.jupyter/custom/custom.js
custom.js
require(["nbextensions/snippets_menu/main"],function(snippets_menu){console.log('Loading `snippets_menu` customizations from `custom.js`');varmy_favorites={'name':'My favorites','sub-menu':[{'name':'Menu item text','snippet':['new_command',],},{'name':'Another menu item','snippet':['another_new_command',],},],};snippets_menu.options['menus'].push(snippets_menu.default_menus[0]);snippets_menu.options['menus'].push(my_favorites);console.log('Loaded `snippets_menu` customizations from `custom.js`');});

すると下記の画面のように「My favorites」というスニペットが増えているはずです。

スクリーンショット 0029-12-18 0.36.57.png

さてそれでは、今度はこれを書き換え、機械学習へのスニペットを入れて見ましょう。

custom.js
require(["nbextensions/snippets_menu/main"],function(snippets_menu){console.log('Loading `snippets_menu` customizations from `custom.js`');varmy_favorites={'name':'My favorites','sub-menu':[{'name':'LogisticRegression','snippet':["from sklearn.linear_model import LogisticRegression","lr = LogisticRegression()","lr.fit(X_train, y_train)","print(lr.score(X_test, y_test))","y_predict = lr.predict(X_test)",],},{'name':'SGDClassifier','snippet':["from sklearn.linear_model import SGDClassifier","sgd = SGDClassifier(loss=\"hinge\", penalty=\"l2\")","sgd.fit(X_train, y_train)","print(sgd.score(X_test, y_test))","y_predict = sgd.predict(X_test)"],},],};snippets_menu.options['menus'].push(snippets_menu.default_menus[0]);snippets_menu.options['menus'].push(my_favorites);console.log('Loaded `snippets_menu` customizations from `custom.js`');});

このように書き換えることで、スニペットを登録することができます。

スクリーンショット 0029-12-18 1.19.48.png

JavaScriptで登録するのが若干面倒ですので、僕はいつも下記のようにしています。

  1. 登録したいスニペットをノートブックに書き込んで保存
  2. 保存されたipynb形式のファイルをエディタで開き該当部分をコピー
  3. custom.jsにペースト
  4. ペーストした部分の改行記号を削除
  5. 完成

以上、スニペットを活用した機械学習案件の生産性向上でした。


Neovimがどういうプロジェクトなのかまとめ

$
0
0

はじめに

今年からVimからNeovimに移行してもうすぐ一年になろうとしています。
Neovimを使いだしたきっかけは、暗黒美夢王がリリースしている数々の良プラグインがNeovimでしか使えなかったからでした。
逆に言えばそれ以外具体的にNeovimがVimとどう違うのか、何がすぐれているのか全く知りませんでした。
VimConf2017で刺激を受けた私は、その膨大なインプットのなかでもっと私が使っているエディタについて知る必要があると考えました。
本稿ではNeovimとVimの違いを調べ、互いにどのような影響を与えているのかを述べます。

注意

私は中学生レベルの英語能力なので解釈に誤りがあることが多々あると思います。
もし誤りを見つけたのであれば教えていただければ幸いです。

Neovim Introduction

そもそもNeovimとはなにかREADMEを読んでみてもピンと来なくて、他になにかいいものはないか地味に探し回りました。
結果Neovim wikiが最も詳しかったので、ザクッと翻訳してみました。
以下翻訳...

vimは強力なテキストエディタであり、巨大なコミュニティとともに成長し続けています。
このエディタは開発から20年たった今でも、拡張や改善を続けており、主にVimscriptやサポートされたスクリプト言語を使用しています。

Motivation

20年以上に渡る歴史の中で、Vimはおよそ30万に渡るコード行を蓄積しており、
理解できる人材の少ないC89のコードがあるため、これ理解するためには混乱に立ち向かう勇気が要ります。
また、Vimの巨大なコードベースのメンテナーはBram Moolenaar氏ただ一人となっており、
一度新たなコードをマージしてしまえば、彼が責任を負う必要があるため、パッチを受け入れることに対して慎重です。

これらの問題は、機能追加やバグフィックスが取り込まれることへの足かせとなっており、
Vimはプラグインエコシステムの開発スピードに追いつけていません。

Solution

Neovimは以下の目標を達成するためにVimのソースコードを積極的にリファクタリングします。

  • メンテナンスを簡略化し、機能追加やバグフィックスの速度を改善する
  • 複数開発者で作業を分割する
  • コアのソースコード変更をせずにモダンなUIの構築を可能にする
  • コプロセッサ上で動作する新しいプラグインのアーキテクチャにより拡張性を向上する
  • エディタでサポートされていないプログラミング言語でプラグインは記述できるようにする

これらのゴールを達成することによりに新たな開発者がコミュニティに参加し、結果としてすべてのユーザのエディタが改善されます。
重要なこととして、このプロジェクトによりVimのフルスクラッチやVimをIDEへ変化させる事はないということを強調します。
実装の変更がVimの編集モデルやVimscript全般に影響をおよぼすことはありません。
Vimscriptで記述されたほとんどのプラグインは正常に動作します。

Neovim Features

Neovimの思想はなんとなくわかってきました。
ではNeovimの開発が始まって約3年(NeovimのフォークはVim 7.4.160時点)を経て、どのような機能が実装されているのかを具体的に見ていきます。
とりあえずNeovim上で :help nvim-featuresしてみると目次が出てきます。
全部見ていくとキリがないので今回ご紹介するのは以下の通り

  • API
  • Job control
  • Remote plugins
  • Embedded terminal

API

Nvim exposes a powerful API that can be used by plugins and external processes
via RPC, Lua and VimL (eval-api).

nvimはプラグインや外部プロセスからRPC、Lua、VimL経由で使用するための強力なAPIを公開しています。

いきなりですが正直このあたりは、開発者でないとどういう恩恵を得ているのかわかりませんでした!
そのうち自分でもプラグインを作成してみたときに具体的な話をしようと思いますので今はざっくり理解でお茶を濁します。

Neovimの関連プロジェクトはいろいろあるのですが、
特に印象的なのはNeovimのGUIとしてatomやvscodeで有名なElectronで表現しているOniNyaoVimでした。

VimはCUIベースの無骨なエディタの代表格でもあるのですが、
他のモダンのリッチな外観を羨ましいと思うVimmerも一定数いらっしゃるのでは無いでしょうか。

かくいう私もVimからatomやvscodeなどのモダンなエディタに何回か浮気したこともあり、

  • カーソルをfunctionの上に置くと勝手にdoc引用
  • かっこいいポップアップでプロジェクト内をgrep
  • なめらかなトランジションのある操作フィードバック
  • インタラクティブに反応するmarkdown preview

とかモダンなGUI表現が欲しくなるといったことがあります。
VimにそういうGUI表現が付けばもはや最強(絶対にありえん)と思っていたらまさにそれをやっちゃってました。

Onifeaturesやら
NyaoVimui-plugin-examples
を一度ご覧ください。綺麗なUIしてるだろ...Vimなんだぜ...これ...

これらがどうやってやっているんだと思い。調べてみるとNyaoVim作者さんの記事を発見したので、
『Web Components と Electron でつくる Neovim フロントエンドの未来』を見てみました。

読んでみた私のざっくりした理解だと、
Neovimをバックエンドとして起動し、ElectronでUIを構築。ユーザ操作を受け取ったElectron側が入出力の情報をNeovimと通信する。
通信の際には、Electron側のnode.jsクライアント(後述するRemote plugin)からmsgpack-RPCで通信してNeovimのAPIを叩く。ということなのかなと。

こうしてモダンなUI上でVimが稼働している例を見ているとNeovimのfeatureである

  • コアのソースコード変更をせずにモダンなUIの構築を可能にする
  • コプロセッサ上で動作する新しいプラグインのアーキテクチャにより拡張性を向上する

の一例といえるでしょうか。
軽く試したところ、VimなのにUIがモダンというとてもつなく可能性を秘めてるなと思いました。
幾つかNeovim本体とは違う挙動をする部分もあり、本格導入には至りませんでしたが、
ターミナルにこもってるタイプのプログラマの私でもmarkdown編集時のサブエディタとして使用するなど、
有用な点が既に幾つかあり、今後も動向をウォッチしていこうと思います。

job-control

Job control is a way to perform multitasking in Nvim,
so scripts can spawn and control multiple processes without blocking the current Nvim instance.

ジョブコントロールはNvim上でマルチタスキングを実行する方法です。
幾つかのスクリプトは複数プロセスの発行管理することができ、Nvim のインスタンスをブロックしません

私がVimを使い始めた当初(2013年くらいだったと記憶している)、プログラミングに必要そうなプラグインを幾つか入れて動作させてみたところ、
不意にバックグラウンドで動作が走って画面が固まることがありました。

例えばsyntasticなど。
これはファイル保存をした際に、自動的にlinterを実行し、処理結果をVim上QuickFixで表示するプラグインですが、
linterが処理を完了するまで画面が固まり、なぜ動かんのじゃとイラついたことがあります。

その一方でneocompletevim-quickrunを使っている際は、普通に非同期処理でVimをブロックしないようにできていたので、
この差は何なのだろうと思っていました。
要するにvimproc.vimを裏側で利用していた事を全然理解していなかったわけですが...

というわけNeovimではこれまでvimproc.vimなど外部プラグインに依存する必要性があった非同期実行機能が本体側で存在するわけです。

この非同期処理を活用したプラグインは今では沢山あり、今私が常用しているだけでも以下のようなものがあり、便利に使わせていただいています。

しかし、このjob機能はVim本家において実装(Neovimのjobと全く同じものではない)されており、
具体的にVimとNeovimでjob機能がどのように違うのか、そもそもVim本体に取り込まれるまでにどのような経緯があり、
それにNeovimがどのような影響をもたらしたのか、興味深いところではありますが、それはまたおいおい調べます。

Remote plugins

Extensibility is a primary goal of Nvim.
Any programming language may be used to extend Nvim without changes to Nvim itself.
This is achieved with remote plugins, coprocesses that have a direct communication channel (via |RPC|) with the Nvim process.

拡張性はNvimの最優先の目標です。
どのようなプログラミング言語でもNvim自体を変更することなく、Nvimを拡張することができます。
これはリモートプラグインやコプロセスがチャネルによりNvimプロセスと直接通信することで実現します。

Vimを常用している人であれば、よりVimを便利にするためのプラグインを書いてみたいと思っている人も多いハズ。
しかし、Vimプラグインを作成するためにはVimscriptを覚える必要があります。
VimscriptはもともとVimの設定を記載するためのスクリプトという経緯(らしい)から、
個人的には最近のモダンな言語と比較すると冗長でわかりづらく見えます。

  • エディタでサポートされていないプログラミング言語でプラグインは記述できるようにする

リモートプラグインは上記の Neovim feature を実現するための機能であります。
なので普段仕事で使用しているような言語であれば、ノウハウがあるし、書いてみてもいいかも...
と思っているVimmerも安心というわけですね。

それで具体的にどうやっているんだろと軽く調べてみました。登場人物は以下の通りで

  • Neovimプロセス
  • Neovimクライアント
  • リモートプラグイン

Neovimプロセスとの通信プロトコルがRPCでその通信で使用されるフォーマットがmagpackなのね。という雑な理解

Neovimプロセス <=== msgpack-RPC ===> Neovimクライアント <=== ライブラリ/実装 ===> リモートプラグイン

msgpack-RPCについては以下の資料が詳しそう。
whats-messagepack

Neovim APIのクライアントは各言語ごとにある。
api-clients

ただ欠点として

  • Neovim APIのクライアントが適切に動作する環境を用意する必要があるなど依存関係が多いため、導入に際してハードルが高い(少なくとも私はdeniteとdeopleteが安定動作するまで結構かかった)
  • リモートプラグインはNeovimの独自機構だからvimでは使えないNeovim専用プラグインとなる(プラグイン実装者が頑張ればなんとかなる?)

ちなみにNeovimのリモートプラグインとして作成されているdeniteやdeopleteがなぜVim8で使えるんだおかしいだろと思って調べてみたら、
vim-hug-Neovim-rpcというリモートプラグインがNeovimに対して送信した内容を
パースしてvimと通信するというライブラリがdeniteやdeopleteのRequirementsに記載されていました。

作ってないやつが何偉そうに解説してんだといわれそうだからそのうち作ろう。そのうち...

Embedded terminal

Nvim embeds a VT220/xterm terminal emulator based on libvterm. The terminal is
presented as a special buffer type, asynchronously updated from the virtual
terminal as data is received from the program connected to it.

NvimにはlibvtermベースのVT220/xtermターミナルエミュレータが組込されています。
このターミナルは特殊なバッファタイプとなっており、仮想ターミナルに接続されたプログラムからデータ受信をすると非同期、このバッファが更新されます。

Neovimにはターミナルエミュレータがあるから:terminalで実行できるよって話なのですが、
実はtmuxユーザの私はあまり魅力的に写ってなかったんですよね。tmuxでペイン分ければいいじゃんくらいに思ってました。
けどよくよく調べてみると、確かに幾つかの利点があることがわかりました。

  • ヤンクペーストがNeovim上ですべて完結する(tmuxのvisual modeはそのあたりちょっと弱い気がする)
  • そもそもGVimユーザからしてみるとターミナルを直叩けなかった(文字描画はGVimのが速いから確かに魅力)
  • その他プラグインからターミナルを制御することで色々できることが増える(らしい)

ちなみにターミナル機能はVim8に追いても実装されているため、Neovim独自ではなくなっている

その他 Neovim Features

上記に上げたのが比較的大きなFeatureなんですが、その他にも以下のような変更がいろいろあります。
これも1つずつ見ていくのはだいぶ辛いので、個人的に印象的なものを少し抜粋します。

  • Options:
    • 'cpoptions' flags: |cpo-_|
    • 'guicursor' works in the terminal
    • 'inccommand' shows interactive results for |:substitute|-like commands
    • 'scrollback'
    • 'statusline' supports unlimited alignment sections
    • 'tabline' %@Func@foo%X can call any function on mouse-click
    • 'winhighlight' window-local highlights
  • Variables:
    • v:event
    • v:exiting
    • v:progpath: is always absolute ("full")
    • v:windowid: is always available (for use by external UIs)
  • Commands:
    • checkhealth
    • drop: is available on all platforms
    • Man: is available by default, with many improvements such as completion
    • tchdir: tab-local |current-directory|
  • Functions:
    • dictwatcheradd(): notifies a callback whenever a |Dict| is modified
    • dictwatcherdel()
    • menu_get()
    • msgpackdump(): msgpackparse() provide msgpack de/serialization
  • Events:
    • DirChanged
    • TabNewEntered
    • TermClose
    • TermOpen
    • TextYankPost
  • Highlight groups:
    • hl-QuickFixLine
    • hl-Substitute
    • hl-TermCursor
    • hl-TermCursorNC
    • hl-Whitespace: highlights 'listchars' whitespace

inccommand

inccommandは今回調べた結果初めて知ったオプションなのですが、
試しに導入してみたところ、3日でこれ便利だわってなってvimrcに入れた。

一言で言うと、文字列置換をインタラクティブに表示するオプション。
動画を見れば一発でわかります。

Neovim: incremental substitution ('inccommand')

設定は以下の通り

set inccommand=split

この動きを実現するvim-overというプラグインがあり、inccommandとほぼ同様の動作を行えるのですが、オプション設定のみでできる点や:%sをそのまま使えるのがいい感じです。

TextYankPost

vim-highlightedyankというヤンクした範囲をインタラクティブに表示するというプラグインがあるのですが、
Vimであればyankキーバインドをvim-highlightedyankの用意したプラグインコマンドと差し替える必要があるのですが、
Neovimであれば TextYankPostというAutoCommandによりインストール時点で無設定で使用することができます。

vim diff

上記で有名どこの違いはザラッとおさらいできたかなと思いますので次は、もうちょい地味めの違いについて。
:help vim_diffを見てみましよう。

nvim-configuration

NeovimとVimでは設定ファイルの位置が変わっていて、これはXDG Base Directory Specificationに準拠した結果とのこと。
詳しくは今後調べる予定。
設定ファイルの位置が.vimrcじゃなくて$XDG_CONFIG_HOME/nvim/init.vimに変わってたのはビビった。

nvim-default

NeovimとVimではオプションのデフォルトが異なります。
確かに、Vimのオプションにはこりゃデフォルト有効でよくね?っていうオプションとかが結構あって、
Neovimではそのあたりのからみや設定ファイルのディレクトリが変更になった影響などもあり、
デフォルトオプションが変わっています。

詳細は次の通り

  • Syntax highlighting is enabled by default
  • ":filetype plugin indent on" is enabled by default
  • 'autoindent' is set by default
  • 'autoread' is set by default
  • 'backspace' defaults to "indent,eol,start"
  • 'backupdir' defaults to .,~/.local/share/nvim/backup (xdg)
  • 'belloff' defaults to "all"
  • 'complete' doesn't include "i"
  • 'directory' defaults to ~/.local/share/nvim/swap// (xdg), auto-created
  • 'display' defaults to "lastline"
  • 'formatoptions' defaults to "tcqj"
  • 'history' defaults to 10000 (the maximum)
  • 'hlsearch' is set by default
  • 'incsearch' is set by default
  • 'langnoremap' is enabled by default
  • 'langremap' is disabled by default
  • 'laststatus' defaults to 2 (statusline is always shown)
  • 'listchars' defaults to "tab:> ,trail:-,nbsp:+"
  • 'nocompatible' is always set
  • 'nrformats' defaults to "bin,hex"
  • 'ruler' is set by default
  • 'sessionoptions' doesn't include "options"
  • 'showcmd' is set by default
  • 'smarttab' is set by default
  • 'tabpagemax' defaults to 50
  • 'tags' defaults to "./tags;,tags"
  • 'ttyfast' is always set
  • 'undodir' defaults to ~/.local/share/nvim/undo (xdg), auto-created
  • 'viminfo' includes "!"
  • 'wildmenu' is set by default

autoindent, hlsearch, incsearch, listchars, wildmenu辺りは私も必ずONにするのでもうデフォルトでよくね?とは思う。

NeovimがVimに与えた影響とは

Vimの作者であるBram Moolenaar氏はVim の作者 Bram Moolenaar への10の質問(10 Questions with Vim’s creator, Bram Moolenaar - Binpress の翻訳)
にてNeovimに対して聞かれた際に以下のコメントをしています。

Q. Neovim の開発はおよそ 8 ヶ月に渡って続いています。Neovim の勢いについてどのようにお考えですか?

A.
さあ。最終目標に対していくつかの基本的な選択は奇妙で不適切に見えます。
例えばあるシステムのサポートを切ったり後方互換性を維持していないことなどです。そのようなことをしなくてもうまく実装できたのではないでしょうか。
彼らは Vim の古いコードが嫌いでそれを “正しく” しようとしているように感じます。古いコードが醜いことには同意です。
しかし新しく実装するには膨大な手間がかかるでしょう。これは Elvis に起こったことによく似ています: Elvis は再実装により改善を行いました。
それは Vim が多くの機能拡張を行っている間も行われ続け、とても長い時間が費やされました。
最終的には Elvis は非常に多くのユーザーを失ってしまいました。再実装された Elvis は良いコードで書かれているかもしれませんが、ユーザーはそのことに気付きません。

Neovim から生じた良いものが Vim にも還元できたらと願っています。
より良いプラグインサポートや改善された GUI、Vim の他のアプリケーションへの埋め込みを望まない人はいませんよね?
大きな問題は、それをどのようにきちんと実装するかです。

Neovim Introductionを見た際にもなるほどと思いましたが、真逆の事を言っているこの回答に関してもなるほどと思います。
結局のところVimユーザに対してどのような価値を届けられるかなのかと。
リファクタリングした結果開発効率が早くなるのが先か、リファクタリングしている最中に機能拡張されるのが先か
どちらも正しいことを言っていてこの回答は結果が全てなのかなと思います。

私はVimやNeovimのpatchを書いているわけでも無いので推測でしか無いのですが、
NeovimがVimに与えた影響はけして小さなものでは無いのではと思いました。
Neovimが先んじて実装したjobやterminalといった機能は上記の通りVimにも還元されていますし、
同じようにVimのpatchはNeovim側においても取り込まれています。

雑感

この記事作成を通して、今までおぼろげであったNeovimの外観がやっとつかめてきました。
まず思ったのが、NeovimはVimに対してとてつもないリスペクトをしているということでした。
一度でもVimのマニュアルを眺めたことがあれば、
あれほどシンプルなエディタの中によくぞあの膨大な拡張性を持たせたものだと、感心したことがあると思います。

Neovimはそれらの拡張性を、下位互換性を保持したまま(すべてができているわけでは無いと思うが)リファクタリングし、
更には新機能追加までやってのけたのです。強力なVimに対するリスペクトなくしてできることではないでしょう。
私はこれまでNeovimを使っていて、vimで構築してきたvimrcをNeovimに合わせて苦労して修正したこともなく、
だからこそ今でもNeovimをメインのエディタに据えています。
(当然クリップボード設定など独自のアーキテクチャになっている部分については対応いますが)

この記事を作成する当初では、 Vim8がリリースされ、job/terminalなどがマージされたことや、
暗黒美夢王のnvim専用プラグインもVim8対応が実施されたことなどもあり、
現状ではNeovimを使用する利点はあまりないのではと思っていました。
しかし依然NeovimはRemotePluginやinccommand等の独自オプションや関数群などVimとの違いを見せています。

こうした現状を改めて見てみると、NeovimとVimのどっちが優れているということを論じるのはあまり意味は無いのではないかと思えてきます。
この先これらのテキストエディタがどのようになっていくかは誰にもわからない。だからこそ、これからの行く末が非常に楽しみです。

vim 8 でパッケージ管理

$
0
0

これまで vim のパッケージ管理は dein.vim を使っていたのですが、 vim 単体でもパッケージ管理できるらしいので試してみました。 macOS Sierra へ vim 8 をインストールし、 vim の plugin をインストールします。

vim 8 インストール

lua の plugin を使いたいので、vim インストール前に lua をインストールします。

$ wget http://www.lua.org/ftp/lua-5.3.4.tar.gz
$ tar zxvf ./lua-5.3.4.tar.gz
$ cd ./lua-5.3.4
$ make macosx
$ make install
$ ln -s /usr/local/include /usr/local/bin/include

vim 本体をインストール。

$ wget https://github.com/vim/vim/archive/v8.0.1290.tar.gz
$ tar zxvf ./v8.0.1290.tar.gz
$ cd ./vim-8.0.1290
$ ./configure --enable-luainterp=yes --with-lua-prefix=/usr/local/bin --enable-pythoninterp=dynamic
$ make
$ make install

plugin インストール

まず plugin を設置する為の、ディレクトリを作成します。
ディレクトリは ~/.vim/pack/任意の名前/{opt,start} で作成します。
今回は 任意の名前 = mypackage とします。

$ mkdir -p ~/.vim/pack/mypackage/opt
$ mkdir -p ~/.vim/pack/mypackage/start

plugin は start または opt ディレクトリ以下に設置すれば動くようです。
試しに neocmplete を設置してみます。

$ cd ~/.vim/pack/mypackage/start
$ wget https://github.com/Shougo/neocomplete.vim/archive/ver.2.1.tar.gz
$ tar zxvf ./ver.2.1.tar.gz
$ rm -f ./ver.2.1.tar.gz

.vimrc 設置

neocomplete を有効化する為 ~/.vimrc に下記設定を書きます。

~/.vimrc
" neocomplete有効化
let g:neocomplete#enable_at_startup = 1

上記の状態で vim を起動すれば neocomplete が使えます。

終わりに

ディレクトリ作成して、 plugin 設置するだけ。
お手軽にパッケージ管理できるので、ぜひ試してみて下さい。

年末が近づいてきたのでRuby開発用に.vimrcとプラグインを大掃除した

$
0
0

こちらはフロムスクラッチ Advent Calendar 2017の12日目の記事です。

はじめに

前回の記事でdein.vimを使ってプラグインのTOML化まで行いました。
今回は普段開発しているRubyやJavaScript向けにプラグイン周りを整えたいと思います。
NeoVimではなく、Vim8を使用しています。

ゴール

  • vimをIDE化するつもりはない
  • デフォルト機能を少しずつ強化するプラグインを中心に入れる
  • 基本はRuby・JavaScript向けにプラグインを入れる
  • ついでに.vimrcも整理する

.vimrc

表示・設定系(.vimrc)
" 挿入モードでTABキーを押した際、対応する数のスペースを入力setexpandtab" 画面上でタブ文字が占める幅の指定settabstop=2" 自動インデントでずれる幅の指定setshiftwidth=2" 連続した空白に対してタブキーやバックスペースキーでカーソルが動く幅の指定setsofttabstop=2" 改行時に前の行のインデントを継続するsetautoindent" 改行時に入力された行の末尾に合わせて次の行のインデントを増減するsetsmartindent" 一旦ファイルタイプ関連を無効化filetype off" 256色対応sett_Co=256" エンコード, ファイルエンコードsetencoding=utf-8setfileencoding=utf-8" スクロールする時に下が見えるようにするsetscrolloff=5" .swapファイルを作らないsetnoswapfile" バックアップファイルを作らないsetnowritebackup" バックアップをしないsetnobackup" ビープ音を消すset belloff=all" OSのクリップボードを使うsetclipboard=unnamed" 行番号を表示setnumber" compatibleオプションをオフにするsetnocompatible" 移動コマンドを使ったとき、行頭に移動しないsetnostartofline" 対応括弧に<と>のペアを追加setmatchpairs& matchpairs+=<:>" 対応括弧をハイライト表示するsetshowmatch" 対応括弧の表示秒数を3秒にするsetmatchtime=3" ウィンドウの幅より長い行は折り返され、次の行に続けて表示されるsetwrap" 入力されているテキストの最大幅を無効にするsettextwidth=0" 不可視文字を表示setlistsetlistchars=tab-,trail:-,extends:»,precedes:«,nbsp:%,eol:↲
" インデントをshiftwidthの倍数に丸めるsetshiftround" 補完の際の大文字小文字の区別しないsetinfercase" 行末1文字までカーソルを移動できるようにするsetvirtualedit=onemore" 変更中のファイルでも、保存しないで他のファイルを表示sethidden" 新しく開く代わりにすでに開いてあるバッファを開くsetswitchbuf=useopen" 小文字の検索でも大文字も見つかるようにするsetignorecase" ただし大文字も含めた検索の場合はその通りに検索するsetsmartcase" インクリメンタルサーチを行うsetincsearch" 検索結果をハイライト表示sethlsearch" マウスモード有効setmouse=a" コマンドを画面最下部に表示するsetshowcmd" ◆や○文字が崩れる問題を解決"setambiwidth=double

表示や設定をいじるのはこれくらいで十分な気がしています。
set cursorlineも好きですが、相当重くなるため使用していません。

操作・入力系(.vimrc)
" インサートモードでbackspaceを有効にsetbackspace=indent,eol,start" 入力モード中に素早くjjと入力した場合はESCとみなすinoremap jj <Esc>" ビジュアルモードの選択範囲を * で検索vnoremap<silent> * "vy/\V<C-r>=substitute(escape(@v, '\/'), "\n",'\\n','g')<CR><CR>" vを二回で行末まで選択vnoremapv $h" Ctrl + hjkl でウィンドウ間を移動nnoremap<C-h><C-w>hnnoremap<C-j><C-w>jnnoremap<C-k><C-w>knnoremap<C-l><C-w>l" /{pattern}の入力中は「/」をタイプすると自動で「\/」が、" ?{pattern}の入力中は「?」をタイプすると自動で「\?」が 入力されるようになる
cnoremap <expr>/ getcmdtype() == '/' ? '\/' : '/'
cnoremap <expr> ? getcmdtype()=='?' ? '\?' : '?'

特にオススメなのはインサートモード中にjjをESCとする設定です。めちゃくちゃ使っています。
/での検索中に「/」をタイプすると自動で「\/」と入力される設定も地味に便利です。
閉じカッコ補完はあまり好きではないのと、プラグインと競合したりするので、入れていません。

dein.vim関連(.vimrc)
" dein.vimによるプラグイン管理if&compatiblesetnocompatibleendif" dein.vimのclone先を指定するsetruntimepath+=~/dotfiles/.vim/dein/repos/github.com/Shougo/dein.vimlet s:dein_dir = expand('~/dotfiles/.vim/dein')if dein#load_state(s:dein_dir)call dein#begin(s:dein_dir)call dein#load_toml(s:dein_dir . '/plugins.toml', {'lazy': 0})call dein#load_toml(s:dein_dir . '/lazy.toml', {'lazy': 1})call dein#end()call dein#save_state()endif

プラグイン(plugins.toml)

とりあえず

とりあえず入れる(plugins.toml)
# plugin管理[[plugins]]repo='Shougo/dein.vim'# 非同期処理全般[[plugins]]repo='Shougo/vimproc.vim'

このあたりはMustで入れるものかと思います。

表示系プラグイン(plugins.toml)

カラースキーマ、ステータスライン(plugins.toml)
# colorschema[[plugins]]repo='chriskempson/vim-tomorrow-theme'# statusline[[plugins]]repo='itchyny/lightline.vim'# インデントを可視化[[plugins]]repo='Yggdroot/indentLine'# 無駄な空白をハイライト[[plugins]]repo='bronson/vim-trailing-whitespace'

カラースキーマはお好みで。
statuslineはairlineやpowerlineなどありますが、lightlineが軽量でオススメです。
インデント可視化、無駄な空白のハイライトは地味に便利です。

カラースキーマ、ステータスライン設定(.vimrc)
" カラースキーマcolorscheme Tomorrow-Night-Bright" シンタックスハイライトの最大行数setsynmaxcol=200" シンタックスハイライトsyntaxon" .vueシンタックスハイライト
autocmd BufNewFile,BufRead *.vue setfiletype=html" 全角スペースのハイライトfunction! ZenkakuSpace()highlight ZenkakuSpace cterm=underline ctermfg=lightblue guibg=darkgrayendfunctionif has('syntax')
    augroup ZenkakuSpace
        autocmd!
        autocmd ColorScheme * call ZenkakuSpace()
        autocmd VimEnter,WinEnter,BufRead * letw:m1=matchadd('ZenkakuSpace',' ')
    augroup ENDcall ZenkakuSpace()endif" for lightline.vimsetlaststatus=2letg:lightline = {
  \ 'colorscheme': 'wombat',
  \ 'active': {
  \   'left': [
  \     ['mode','paste'],
  \     ['readonly','filename','modified','anzu']
  \   ]
  \ },
  \ 'component_function': {
  \   'anzu': 'anzu#search_status'
  \ }
  \ }

趣味で.vueファイルをいじることがあるので、filetypeをhtmlにしてシンタックスハイライトを効かせています。
全角スペースのハイライトも便利です。
lightline.vimの設定の中にanzuとチラホラあるのは、後ほど登場するプラグインであるvim-anzuを前提にしています。

操作系プラグイン(plugins.toml)

操作系プラグイン(plugins.toml)
# j, k移動高速化[[plugins]]repo='rhysd/accelerated-jk'# /検索強化[[plugins]]repo='osyo-manga/vim-anzu'# f検索強化[[plugins]]repo='rhysd/clever-f.vim'
操作系プラグイン用設定(.vimrc)
" for accelerated-jk
nmap j<Plug>(accelerated_jk_gj)
nmap k<Plug>(accelerated_jk_gk)" for vim-anzu
nmap n nzz<Plug>(anzu-update-search-status)
nmap N Nzz<Plug>(anzu-update-search-status)
nmap * <Plug>(anzu-star)
nmap # <Plug>(anzu-sharp)
nmap <silent><ESC><ESC> :<C-u>nohlsearch<CR><Plug>(anzu-clear-search-status)

j, kでの移動が爆速になったり、検索ヒット数が表示されたり、f検索の結果がハイライトされ、検索の繰り返しが;ではなくfの連打でいけるようになります。

遅延読み込みプラグイン(lazy.toml)

シンタックスハイライト

シンタックスハイライト(lazy.toml)
# slimのシンタックスハイライト[[plugins]]repo='slim-template/vim-slim'on_ft=['slim']# ES6のシンタックスハイライト[[plugins]]repo='othree/yajs.vim'on_ft=['javascript']

この辺は必要があれば。

自動補完

自動補完プラグイン(lazy.toml)
# コードの自動補完[[plugins]]repo='Shougo/deoplete.nvim'on_i=1hook_add='letg:deoplete#enable_at_startup = 1'# vim8でdeopleteを使うのに必要[[plugins]]repo='roxma/nvim-yarp'on_ft=['ruby']# vim8でdeopleteを使うのに必要[[plugins]]repo='roxma/vim-hug-neovim-rpc'on_ft=['ruby']

deoplete.nvimの導入にめちゃめちゃハマりました。
python3付きのvim8を入れ直し、その他諸々設定を見直しつつ、今の状態でやっと動くようになりました。

自動補完用設定(.vimrc)
" for deoplete.vim" 一つ目の候補を選択状態にするsetcompleteopt+=noinsert

これ地味に便利です。候補の一番上にあればEnterで補完されるようになります。

Ruby用

Ruby補完用(lazy.toml)
# Rubyの自動補完[[plugins]]repo='Shougo/deoplete-rct'on_ft=['ruby']# Rubyの自動補完[[plugins]]repo='fishbullet/deoplete-ruby'on_ft=['ruby']# Rubyの自動補完[[plugins]]repo='osyo-manga/vim-monster'on_i=1hook_add='''letg:monster#completion#rcodetools#backend = "async_rct_complete"letg:deoplete#sources#omni#input_patterns = {\"ruby":'[^.*\t]\.\w*\|\h\w*::',\}'''

とりあえずよくわからんので全部突っ込みました。どうやら動いているっぽい。
fastri, neovim, rcodetoolsというgemを入れる必要があるみたいです。

Ruby定番(lazy.toml)
# Rubyのend補完[[plugins]]repo='tpope/vim-endwise'on_i=1on_ft=['ruby']# Rubyのメソッドの定義元にジャンプ[[plugins]]repo='szw/vim-tags'

Rubyのend補完と、メソッドの定義元にジャンプできるvim-tagsを入れました。
vim-tagsはbrew install ctagsが必要です。
他にも色々Ruby向けプラグインはありますが、重くなっても嫌ですし、これくらいで十分な気がしています。

最後に

Unite.vimとかNERDTreeとかvim-railsとか使いこなせば便利だとは思うんですけど、結局高機能すぎて操作覚えられないんですよね...
今使っているプラグインに慣れてきたら、また見直していきたいと思います。

コピペして使い人用に

.vimrc

.vimrc
" 表示・設定系" 挿入モードでTABキーを押した際、対応する数のスペースを入力setexpandtab" 画面上でタブ文字が占める幅の指定settabstop=2" 自動インデントでずれる幅の指定setshiftwidth=2" 連続した空白に対してタブキーやバックスペースキーでカーソルが動く幅の指定setsofttabstop=2" 改行時に前の行のインデントを継続するsetautoindent" 改行時に入力された行の末尾に合わせて次の行のインデントを増減するsetsmartindent" 一旦ファイルタイプ関連を無効化filetype off" 256色対応sett_Co=256" エンコード, ファイルエンコードsetencoding=utf-8setfileencoding=utf-8" スクロールする時に下が見えるようにするsetscrolloff=5" .swapファイルを作らないsetnoswapfile" バックアップファイルを作らないsetnowritebackup" バックアップをしないsetnobackup" ビープ音を消すset belloff=all" OSのクリップボードを使うsetclipboard=unnamed" 行番号を表示setnumber" compatibleオプションをオフにするsetnocompatible" 移動コマンドを使ったとき、行頭に移動しないsetnostartofline" 対応括弧に<と>のペアを追加setmatchpairs& matchpairs+=<:>" 対応括弧をハイライト表示するsetshowmatch" 対応括弧の表示秒数を3秒にするsetmatchtime=3" ウィンドウの幅より長い行は折り返され、次の行に続けて表示されるsetwrap" 入力されているテキストの最大幅を無効にするsettextwidth=0" 不可視文字を表示setlistsetlistchars=tab-,trail:-,extends:»,precedes:«,nbsp:%,eol:↲
" インデントをshiftwidthの倍数に丸めるsetshiftround" 補完の際の大文字小文字の区別しないsetinfercase" 行末1文字までカーソルを移動できるようにするsetvirtualedit=onemore" 変更中のファイルでも、保存しないで他のファイルを表示sethidden" 新しく開く代わりにすでに開いてあるバッファを開くsetswitchbuf=useopen" 小文字の検索でも大文字も見つかるようにするsetignorecase" ただし大文字も含めた検索の場合はその通りに検索するsetsmartcase" インクリメンタルサーチを行うsetincsearch" 検索結果をハイライト表示sethlsearch" マウスモード有効setmouse=a" コマンドを画面最下部に表示するsetshowcmd" ◆や○文字が崩れる問題を解決"setambiwidth=double" 操作系" インサートモードでbackspaceを有効にsetbackspace=indent,eol,start" 入力モード中に素早くjjと入力した場合はESCとみなすinoremap jj <Esc>" ビジュアルモードの選択範囲を * で検索vnoremap<silent> * "vy/\V<C-r>=substitute(escape(@v, '\/'), "\n",'\\n','g')<CR><CR>" vを二回で行末まで選択vnoremapv $h" Ctrl + hjkl でウィンドウ間を移動nnoremap<C-h><C-w>hnnoremap<C-j><C-w>jnnoremap<C-k><C-w>knnoremap<C-l><C-w>l" /{pattern}の入力中は「/」をタイプすると自動で「\/」が、" ?{pattern}の入力中は「?」をタイプすると自動で「\?」が 入力されるようになる
cnoremap <expr>/ getcmdtype() == '/' ? '\/' : '/'
cnoremap <expr> ? getcmdtype()=='?' ? '\?' : '?'" dein.vimによるプラグイン管理if&compatiblesetnocompatibleendif" dein.vimのclone先を指定するsetruntimepath+=~/dotfiles/.vim/dein/repos/github.com/Shougo/dein.vimlet s:dein_dir = expand('~/dotfiles/.vim/dein')if dein#load_state(s:dein_dir)call dein#begin(s:dein_dir)call dein#load_toml(s:dein_dir . '/plugins.toml', {'lazy': 0})call dein#load_toml(s:dein_dir . '/lazy.toml', {'lazy': 1})call dein#end()call dein#save_state()endif" カラースキーマcolorscheme Tomorrow-Night-Bright" シンタックスハイライトの最大行数setsynmaxcol=200" シンタックスハイライトsyntaxon" .vueシンタックスハイライト
autocmd BufNewFile,BufRead *.vue setfiletype=html" 全角スペースのハイライトfunction! ZenkakuSpace()highlight ZenkakuSpace cterm=underline ctermfg=lightblue guibg=darkgrayendfunctionif has('syntax')
    augroup ZenkakuSpace
        autocmd!
        autocmd ColorScheme * call ZenkakuSpace()
        autocmd VimEnter,WinEnter,BufRead * letw:m1=matchadd('ZenkakuSpace',' ')
    augroup ENDcall ZenkakuSpace()endif" for lightline.vimsetlaststatus=2letg:lightline = {
  \ 'colorscheme': 'wombat',
  \ 'active': {
  \   'left': [
  \     ['mode','paste'],
  \     ['readonly','filename','modified','anzu']
  \   ]
  \ },
  \ 'component_function': {
  \   'anzu': 'anzu#search_status'
  \ }
  \ }" for accelerated-jk
nmap j<Plug>(accelerated_jk_gj)
nmap k<Plug>(accelerated_jk_gk)" for vim-anzu
nmap n nzz<Plug>(anzu-update-search-status)
nmap N Nzz<Plug>(anzu-update-search-status)
nmap * <Plug>(anzu-star)
nmap # <Plug>(anzu-sharp)
nmap <silent><ESC><ESC> :<C-u>nohlsearch<CR><Plug>(anzu-clear-search-status)" for vim-tags" tagジャンプの時に複数候補がある時に一覧表示するnnoremap<C-]>g<C-]>" for deoplete.vim" 一つ目の候補を選択状態にするsetcompleteopt+=noinsert

plugins.toml

plugins.toml
# plugin管理[[plugins]]repo='Shougo/dein.vim'# 非同期処理全般[[plugins]]repo='Shougo/vimproc.vim'# colorschema[[plugins]]repo='chriskempson/vim-tomorrow-theme'# statusline[[plugins]]repo='itchyny/lightline.vim'# インデントを可視化[[plugins]]repo='Yggdroot/indentLine'# 無駄な空白をハイライト[[plugins]]repo='bronson/vim-trailing-whitespace'# j, k高速化[[plugins]]repo='rhysd/accelerated-jk'# /検索強化[[plugins]]repo='osyo-manga/vim-anzu'# f検索強化[[plugins]]repo='rhysd/clever-f.vim'

lazy.toml

lazy.toml
# slimのシンタックスハイライト[[plugins]]repo='slim-template/vim-slim'on_ft=['slim']# ES6のシンタックスハイライト[[plugins]]repo='othree/yajs.vim'on_ft=['javascript']# コードの自動補完[[plugins]]repo='Shougo/deoplete.nvim'on_i=1hook_add='letg:deoplete#enable_at_startup = 1'# vim8でdeopleteを使うのに必要[[plugins]]repo='roxma/nvim-yarp'on_ft=['ruby']# vim8でdeopleteを使うのに必要[[plugins]]repo='roxma/vim-hug-neovim-rpc'on_ft=['ruby']# Rubyの自動補完[[plugins]]repo='Shougo/deoplete-rct'on_ft=['ruby']# Rubyの自動補完[[plugins]]repo='fishbullet/deoplete-ruby'on_ft=['ruby']# Rubyの自動補完[[plugins]]repo='osyo-manga/vim-monster'on_i=1hook_add='''letg:monster#completion#rcodetools#backend = "async_rct_complete"letg:deoplete#sources#omni#input_patterns = {\"ruby":'[^.*\t]\.\w*\|\h\w*::',\}'''# Rubyのend補完[[plugins]]repo='tpope/vim-endwise'on_i=1on_ft=['ruby']# Rubyのメソッドの定義元にジャンプ[[plugins]]repo='szw/vim-tags'

vim勉強メモ

$
0
0

新米のvimtutor勉強メモを続き、勉強した内容をメモします。

  • 行頭にindentationを追加

    • >>: 現在の行
    • >33gg: 現在の行から33行まで
    • visual modeで>: 選択した行
  • 前のcommandを繰り返す: .

Vimのコマンドラインモードともう少し仲良くする

$
0
0

はじめに

iRidge No1 Vimmerのlighttiger2505です
なおiRidgeでVimmerを名乗っているのは私だけなので、自動的に私が一位です。

Vimの操作に慣れてくると、まるで呪文だった:wやら:qやら:eといったVimのコマンドを覚える余裕ができてきます。
そうなってくると、これまでなんとなく:で遷移してきたコマンドラインモードもっともっと知りたくなってきます。
自然な流れですね。

なお今回の話はVim上で:h usr_20と入力すればより詳しい話があります。興味がある人は是非Vim上で打ち込んでください。

コマンドを忘れがちなあなたに

人は物事を忘れるものです。これは仕方がないことです。
当然膨大な量を誇るVimのコマンド郡のことも忘れてしまいます。
忘れてしまったら、またGoogle先生にコマンドを調べる作業が発生します。大変な時間の損失です。

でも安心してください。コマンドラインモードにはそんなあなたを助ける機能があります。

コマンドモードの履歴をたどる

履歴をたどることは重要です。なぜならよく使うコマンドの殆どは既に履歴にあるからです。
bashのctrl-rは皆さん使っていますか?同じことがVimでもできます。

例えばvimgrepですがこのコマンドはこういった規約になっています。
:vim[grep][!] /{pattern}/[g][j] {file}私はこの{file}の指定方法の
**とかsrc/**とかsrc/views/*.pyとかものすごい忘れます。記憶力のなさには自身があります。

そんな時:vimと打ち込んだあとで矢印キーの上<Up>を押してください。
以前入力したコマンドの中から:vimを前方一致で絞った結果が出てきます。
:vim src/views/*.pyとか復元されます。幸せ。

コマンドモードの履歴を一覧で見る

でも<Up>で辿れないほどはるか昔に実行したコマンドも当然ありますよね。
そんなときは:hisotryです。過去の履歴を一覧表示してくれます。

コマンドラインウィンドウで履歴から即座に実行

さて上記を覚えれば履歴を快適に辿れます。ですがまだ不満がありませんか?
<Up>は一覧で見れないですし、:historyは履歴を引用して実行できません。
そんなときはq:です。

q:を実行すればコマンドラインウィンドウが起動します。
コマンドラインウィンドウはこれまで実行したコマンドの履歴が表示されます。
その上ノーマルモードと同様のキーバインドで移動でき、
iでインサートモードに遷移もできます。
/で検索もできます。
要は通常のバッファーとほぼおなじ扱いになるのです。

使い方としては

  1. コマンドラインウィンドウを開いたら目当てのコマンドを探します
  2. 目当てのコマンドを実行する場合のそのまま<Enter>を押してください
  3. ちょっと編集したいならiでインサートモードに遷移して編集してください
    • 編集しても履歴が汚れることは無いのでご安心ください。
  4. 編集できたらインサートモードのまま<Enter>を押してください。編集後のコマンドが実行されます

これまでの内容を覚えておけば必死にコマンドを覚えたり忘れるたびにGoogle先生に聞くこともなくなりますね。

もっとコマンドラインモードを好きになりたいあなたに

さてデフォルトでも便利なコマンドラインですが、.vimrcをいじればもっと便利になるし、自分の手に馴染むようにカスタマイズもできます。

補完する

履歴と同様に重要なのが補完です。コマンドの一部さえ覚えていればコマンドを簡単に探すことができます。
コマンドを途中まで打ち込んでから<ctrl-e>を押してください。補完できます。

<ctrl-e>だと違和感がある<tab>が良いという方もいらっしゃることでしょう。
しかしコマンドラインモードで<tab>を押すと虚しく^Iと入力されます。
そんなときは:set nocompatibleです。これで<tab>補完が効きます

補完を見やすくする

さて上記をやってみた結果。貧弱な補完と思ったりしてませんか?
モダンなIDEであれば補完候補が一覧で見れてそこからチョイスできるのに...と

安心してくださいwildmenuがあります。
:set wildmenuをしてみてください。補完候補がステータスメニュー上に一覧表示されます。素敵。

コマンドラインモードのキーバインドをいじる

bashの操作に慣れているような人からするとコマンドラインモードのキーバインドは変に感じるかもしれません。
<ctrl-h>でバックスペースの代わりにならないし、<ctrl-b><ctrl-f>で前後の移動になりません。
Vimの標準に合わせろとスパルタンな方々はおっしゃると思うのですが、私は貧弱Vimmerなのでいじってしまいます。
cmapcnoremapbashをいじることでbash同様の動きにしてしまします。

cnoremap <C-b><Left>
cnoremap <C-f><Right>
cnoremap <C-n><Down>
cnoremap <C-p><Up>
cnoremap <C-a><Home>
cnoremap <C-e><End>
cnoremap <C-d><Del>

雑感

以前はコマンドやコマンドラインモードを全然覚える気がなくて、プラグインに頼りきりな私でしたが、
これらを覚えてコマンドラインモードが好きになってきました。
皆さんもいじってコマンドラインモードと仲良くなりましょう。

Viewing all 5692 articles
Browse latest View live


<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>