Visual Studio プラグイン ViEmu をいじってみる

辺りを見渡してもあまりいない Vi 使い。通称「Vimmer
仕事上、Visual Studio を使用することもあり、そろそろ GVim + ctags コンビも辛くなってきたので ViEmu を購入してみた。
http://www.viemu.com/
EclipseNetbeans の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>

[既知な制約事項]

  • 複数キーリマップには設定ファイルは対応していない
  • レジスタ1つしかなく、指定しても同一レジスタに保存される

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';


参考リンク
http://d.hatena.ne.jp/yamadila/20081113/1226547302

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++;