vim-gf-userを使って色んなパス文字列をgfできるようにする

標準コマンド gf を拡張するプラグイン kana/vim-gf-user を使ってgfを拡張した。

以下の点が通常のgfと異なる。

  • 現在行の山括弧 < > に囲まれた部分をパスとして認識する
    • 'isfname'の変更による副作用を起こさずに空白文字を含むパスを認識する
  • カーソル下になくても認識する
    • ただし、カーソル位置で標準の gf が使える時はそちらが優先される
    • また、現在行に複数の山括弧に囲まれた部分があると最初の部分が優先される(html, xml, 不等号の多い文書では厄介)
  • expand()するのでワイルドカードが使える
  • <foo"n, m>と書けば、n行m列目に移動できる
    • 行だけなら標準の gF で可能だが環境によっては'isfname'をいじる必要がある

認識する記述の例

</xxx/yyy.foo>
<$foo/xxx.bar>
<$foo/012*/xxx.bar>
<../xxx.bar>
<xxx.foo"100>
<xxx.foo"100, 10>

vimrcの設定

" vim-gf-user
""""""""""""""""""""""""""""""
" カレント行の < > で囲まれた部分
function! GfUserCLAngleBracket()
    let path = matchstr(getline("."), '\v\<\zs([^>]+)\ze\>')
    let path = fnamemodify(path, '%:p')
    let [whole, path, linecol; rest] = matchlist(path, '\v^([^"]+)(".+)?$')
    if path == ''
        return 0
    endif
    let path = split(expand(path), '\n')[0]
    if linecol =~ ','
        let [whole, line, column; rest] = matchlist(linecol, '\v^"(.+),(.+)$')
        return {'path': path, 'line': str2nr(line), 'col': str2nr(column)}
    else
        return {'path': path, 'line': str2nr(linecol[1:]), 'col': 0}
    endif
endfunction
call gf#user#extend('GfUserCLAngleBracket', 1000)

なかなか便利。

pythonのオムニ補完でVC++ランタイムエラー R6034

python - Runtime Error with Vim Omnicompletion - Stack Overflowと同じエラーが出て同じ解決法で解決した。

neocomplcache(略してneocon, neco)をアンインストールしても同様のエラーが出て
途方にくれていた所に辿り着いたのがこのページ。

解決手順
gvim.exe, python.exeからmt.exeでマニフェストファイルを抽出(?)し、
gvimのマニフェスト内のdependentAssemblyをpython.exeと同じにすればよい。

正直何をやっているのかよく分からないが、manifestとは宣言、表明といった意味らしい。
ちゃんと宣言を揃えておかないとランタイムをうまく呼び出せないということかな。

追記
この際に(?)neocomplcacheからneocompleteに移行した。

vim onlineからスクリプト検索するブックマークレット

/*
 * @desc    www.vim.orgからスクリプト検索する
 * @syntax  vims {word} {type} {order}
 * @example
 * pythonのインデントファイルを検索しダウンロード数順に表示
 * vims python i d
 */

(function(){
    var args = '%s';
    var [, word, type, order] = args.match(/^(.+)\s+(\S+)\s+(\S+)$/);
    switch(type)
    {
        case 'a':
            type = 'all'; break;
        case 'c':
            type = 'color+scheme'; break;
        case 'f':
            type = 'ftplugin'; break;
        case 'g':
            type = 'game'; break;
        case 'i':
            type = 'indent'; break;
        case 's':
            type = 'syntax'; break;
        case 'u':
            type = 'utility'; break;
        case 'p':
            type = 'patch'; break;
    }
    switch(order)
    {
        case 'r':
            order = 'rating'; break;
        case 'd':
            order = 'downloads'; break;
        case 's':
        case 'n':
            order = 'script_name'; break;
        case 'c':
            order = 'creation_date'; break;
    }
    location.href = 'http://www.vim.org/scripts/script_search_results.php?keywords=' +
        word + '&script_type=' + type + '&order_by=' + order + '&direction=descending&search=search';

})();

firefox 30.0で動作確認。

vims python i d

↓

カラフルなのは自作グリモン。

vimでバッファリストをすっきりさせる

nnoremap <expr> ,bD v:count ?
    \ ":<C-u>1," . v:count . "bdelete<CR>" :
    \ ":bdelete<C-b>"
nnoremap <expr> ,bW v:count ?
    \ ":<C-u>1," . v:count . "bwipeout<CR>" :
    \ ":bwipeout<C-b>"

すっきり。:Unite bufferがはかどる。
バッファ番号はリセットされないので :{N}b とか {N} は依然不便だけど。

あわせて使うマッピング。

nnoremap ,bo :<C-u>buffers!<CR>
nnoremap ,bd :<C-u>bdelete<CR>
nnoremap ,bw :<C-u>bwipeout<CR>

jqでvim式の値をダンプ

高機能軽量JSONパーサー jq を使ってvim式をお手軽ダンプ。これは便利。

vimrc

command! -nargs=1 -complete=expression Dump :call s:Dump(<f-args>)
function! s:Dump(expstr)
    exe 'vs ' . tempname() . '.json'
    let dumpstr = substitute(string(eval(a:expstr)), '\\', '\\\\', 'g')
    let dumpstr = substitute(dumpstr, '\n', '\\n', 'g')
    let dumpstr = substitute(dumpstr, '\r', '\\r', 'g')
    let dumpstr = substitute(dumpstr, '\t', '\\t', 'g')
    let dumpstr = substitute(dumpstr, '/', '\\/', 'g')
    let dumpstr = substitute(dumpstr, '"', '\\"', 'g')
    let dumpstr = substitute(dumpstr, "\\v[^']*\\zs'(([^']|'')*)'\\ze", '"\1"', 'g')
    let dumpstr = substitute(dumpstr, "''", "'", 'g')
    let dumpstr = substitute(dumpstr, '\(function("\(\w\+\)")\)', '"function(''\2'')"', 'g')
    call setline('.', dumpstr)
    .!jq .
    write
endfunction

使用例

:Dump g:quickrun#default_config 

結果画面


参考
JSON でのエスケープ処理 (JSONの値に""", "\" を含める場合の処理)

vimで行末を見た目の上で揃えて削除するには

これが意外と難しかった。

論理行の文字数を指定量にする 'textwidth'

でもなく

表示行がウィンドウの幅を超えると折り返す 'wrap'

でもなく

論理行の指定文字数を超える部分をカットする

:'<,'>s/\v^(.{60}).*$/\1/
:'<,'>norm 60lD

でもなく

論理行の指定表示幅を超える部分をカットするには?

表示幅というのは、半角文字を1、全角文字を2とカウントした幅。見た目の幅。'statusline'の%vでステータスラインに表示できる。
:h 'statusline'には virtual column number とあったので、最初、仮想列番号、仮想列幅と訳してみたが、表示列番号、表示列幅(表示幅)のほうがわかりやすい。

文字数ではないので、:norm 60lD や :g/./call cursor(line('.'), 60) | norm D は使えない。
eval.txtにも表示列番号への移動ができる関数が見当たらない。
virtcol()で表示列番号の取得は出来るので表示列幅も計算できる。しかし、Dコマンドで簡単にカットするには指定表示列番号への移動ができないと意味がない。

幸いにも、正規表現で表示幅を扱えることに気づいたので使ってみた。これでうまくいった。

" n+1表示列目以降を切り取る
command! -nargs=1 -range SliceLines :exe '<line1>,<line2>s/^\(.*\)\%' . (<args>+1) . 'v.*/\1/'

他にも、目視で良ければ矩形選択してDで簡単にカットできる。
指定した表示列番号にジャンプする方法があればこの方法がベストなんだけど。

jshint2.vim

いまどきのlintはES6, Mozilla JS, WSHとかも扱えるのかと感動したのでメモ。
プロジェクトルートごとに設定ファイルを置いて柔軟に設定できるのもよい。

まずリンク。
https://github.com/Shutnik/jshint2.vim
http://www.jshint.com/docs/options/

インストール

1 node.js(http://nodejs.org/download/)入れる 一昔前と違ってインストールかんたん

2 JSHint(https://github.com/jshint/jshint)入れる 
コマンドプロンプトで

npm install jshint --global

とするだけ。Windowsでエラるときは管理者権限のコマンドプロンプトでうまくいくかも。

3 .jshintrc を書く
書き方はJSONでこんな感じ
http://qiita.com/maccotsan/items/0fb82ccab014f49ff95d

各オプションの説明と和訳
http://www.jshint.com/docs/options/
http://qiita.com/xorphitus/items/f26ec8fbe17c317d3994

4 .jshintrc をプロジェクトルートなどに置く

jshint foo.js

としたとき、foo.jsのあるディレクトリを含めて階層を上って最初に見つかった.jshintrcが使われるらしい。

JSHint will start looking for this file in the same directory as the file that's being linted. If not found, it will move one level up the directory tree all the way up to the filesystem root. (Note that if the input comes from stdin, JSHint doesn't attempt to find a configuration file)

http://www.jshint.com/docs/

5 jshint2.vim(https://github.com/Shutnik/jshint2.vim)を入れる

NeoBundle 'Shutnik/jshint2.vim'

6 jshint2.vimの設定

設定例

augroup jshint2
  autocmd! jshint2
  autocmd FileType javascript call s:jshint2_settings()
augroup END

function! s:jshint2_settings()
    nnoremap <buffer> ,jh :JSHint<Space>
    vnoremap <buffer> ,jh :JSHint<Space>
endfunction

" 保存時にlintする
let g:jshint2_save = 1

7 使う

ファイル全体をlintする ロケーションリストに表示される

:JSHint

指定範囲をlintする

:'<,'>JSHint

エラー001、警告002、情報003は出さない

:JSHint -E001 -W002 -I003

例えば、警告106は変数名を小文字スネークケース(foo_bar_baz)にするだけで出るので、他の警告やエラーの可読性を大きく落とすことがある。
そんな時は:JSHint -E106とするか、:JSHint camelcase:falseとすれば警告を抑制できる。(永続的に抑制するには、.jshintrcの"camelcase"をtrueにする)

エラー、警告、情報の番号とメッセージの一覧
https://code.google.com/p/rialab/source/browse/trunk/websnippet/jshint-2.1.4.js#5834