Visual Studio プラグイン ViEmu をいじってみる
辺りを見渡してもあまりいない Vi 使い。通称「Vimmer」
仕事上、Visual Studio を使用することもあり、そろそろ GVim + ctags コンビも辛くなってきたので ViEmu を購入してみた。
http://www.viemu.com/
Eclipse や Netbeans のViライクなプラグインにはどうも慣れなかったけど ViEmu はなんとかいけそう。
というわけで ViEmu の初期設定ファイル .viemurc を晒してみる。
set hlsearch set ignorecase set incsearch set nowrapscan set noterse set smartcase nnoremap Y y$ vnoremap Y y$ nnoremap p gp vnoremap p gp nnoremap P gP vnoremap P gP nnoremap n nzz nnoremap N Nzz nnoremap * *zz nnoremap # #zz nnoremap g* g*zz nnoremap g# g#zz nnoremap <C-T> <C-&>zz nnoremap k gk nnoremap j gj vnoremap k gk vnoremap j gj nnoremap h <backspace> nnoremap l <space> nnoremap <Left> <backspace> nnoremap <Right> <space> cnoremap <C-v> <C-R>+ inoremap <C-v> <C-R>+ inoremap <C-g> <Delete> nnoremap <C-[> :noh<CR> nnoremap <ESC> :noh<CR> nnoremap <C-Q> :close<CR> vnoremap / y/<C-R>/<CR> vnoremap < <gv vnoremap > >gv "---------------------------------------- " コマンドモード用 "---------------------------------------- cnoremap <C-d> <Right> cnoremap <C-s> <Left> cnoremap <C-a> <Home> cnoremap <C-f> <End> cnoremap <M-c> \\C cnoremap <M-w> <Home>\\<<End>\\> cnoremap <C-j> <Enter>
[既知な制約事項]
whichwrap の設定はできないのでこれで代用。
nnoremap h <backspace> nnoremap l <space> nnoremap <Left> <backspace> nnoremap <Right> <space>
std::map - insert 時の無駄な find を防ぐ
std::map 使用時に、
「挿入させたいキーが既に登録されているかチェックしたい」
ってことがよくある。
そんな時は insert の戻り値を使用する。
std::map<int, char> hige; hige.insert(1, 'a'); ... std::map<int, char>::_Pairib pib = hige.insert(1, 'b'); if (!pib.second) { // キーが重複している }
[説明]
_Pairib のデータ構造を覗いてみる。
// _Pairib = _Pair + i(terator) + b(ool) typedef pair<iterator, bool> _Pairib; _Pairib::iterator // insert 時のキーの iterator が格納 _Pairib::bool // 新規登録ができたら true となる
というわけで、_Pairib::bool でキーが重複しているかがチェックできる。
find を用いても可能だが、insert 時も find しているので冗長になってしまう。
iterator = hige.find(1); // ここで find if (iterator == hige.end()) { // キーが重複している } hige.insert(1, 'b'); // キー重複チェックする為、ここでも find
因みに、あるキーのデータを(登録|データの変更)したいだけなら [](インデクサ)を用いた方が可読性は高い。
hige[1] = 'b';
insert を用いると以下になる。
hige.insert(std::make_pair(1, map<int, char>::mapped_type())).first->second = 'b';
std::map - erase 時の iterator の無効化を防ぐ
std::map を使用していると、
「ある条件を満たし(た|てない)要素を削除したい」
ってことがよくある。
そんな時はこんな感じにしてみる。
std::map<int, bool> hige; std::map<int, bool>::iterator it = hige.begin(); while (it != hige.end()) { if (it->second == true) { // ここがポイント hige.erase(it++); } else { ++it; } }
[説明]
std::map は要素を変更した場合に、以前まで保持していた iterator は無効になってしまう。
erase の戻り値も void なので何も期待できない。
だったら erase に渡す前の iterator を保持しちゃう。
std::map<int, bool>::iterator tmp = it; ++it; hige.erase(tmp);
これだと長いので後置インクリメントを使用する。
hige.erase(it++);
後置インクリメントはオブジェクトのコピーが erase の引数になるので、iterator は無効化されない。
これは erase の時点で iterator が無効になるのでエラーになる。
hige.erase(it); it++;