3
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

お前の.vimrcを見せろ

Last updated at Posted at 2021-12-02

 これは UEC Advent Calendar 2021 12月3日参加の記事です。本当はD言語について何かしら書こうと思ってたんですけど、課題が過大なので手っ取り早く書けそうなやつにしました。許してね。
 また、この記事はエッセイみたいなものです。電通大生にとって技術的に有益な話が今更あるわけではなく、ただこんな感じだよーっていうのを見てほしいだけです。ただ、もしこれがきっかけに有志が集まったらvimrc読書会をやってみたいとも思っています。

はじめに(Vimあんま知らない人向け)

Vim について

 Vimはテキストエディタの一種です。テキストエディタというとEmacsとかVisual Studio CodeとかAtomあたりが有名でしょうか。コンパイラやリンカやデバッガなんかもくっついてるIDE(Integrated Development Environment, 統合開発環境)と違って、ただテキストファイルを編集するためだけに存在する潔いソフトウェアです。その歴史は結構古く、元々はviという1976年に制作されたテキストエディタに遡ります。viは多くのUNIX系システムに搭載され、その後継であるVimは現在も多くの利用者を抱えています。同じような立ち位置のEmacsとはライバル関係にあり、どのエディタを使っているかという話題は宗教戦争に繋がる恐れがあるので注意しましょう。
 近年の主流と言えばVSCodeやAtomですが、Vimにはそれらとは違う大きな特徴が一つあります。一つはGUIを必要とせずCUI上で動作すること。なんか知らんけどXが入ってないコンピュータとか遠くのサーバにSSHで入ってるときとかに重宝するわけです。そしてもう一つは「モード」と呼ばれる概念と特殊なキーバインドです。

モード

 VimはCUIで動くため大仰なインタフェースは存在しません。更にマウスのような機器は使わず、なんなら矢印キーの使用を邪道と言う過激派もいます。したがって最低限のキーだけでテキスト編集を行う必要があり、そのためにモードという機能が備わっています。ユーザはその瞬間のやりたいことに合わせてモードを操作するわけです。
 具体的には、大きく分けて以下のモードが存在します。

モード 説明
ノーマル モードの変更、カーソルの移動、テキストのヤング&ペースト・削除などを行う
挿入 テキストを入力する
ビジュアル テキストを選択する
コマンドライン コマンドを実行してファイル開閉、検索、置換などを行う

 他にも色々あったり上のモードも更に細分化されたりしますがだいたいこんな感じ。普段は基本的にノーマルモードにいて、ここを中心として必要に応じてモードを切り替えることが多いです。
 各モードに対してキーバインドが割り振られており、これのせいで初心者殺しとか色々言われたりします。初めて使う人が何事もなくテキストを編集するのはまず間違いなく無理なので、仕方ないっちゃ仕方ないですが。

.vimrcについて

 .vimrcはVimにおけるconfigファイル的なものです("rc"は"Run Command"の略。.bashrcとか.cshrcとか、UNIX系では.*rcというのがよくあるネーミング)。VimにはVim scriptという組み込みのスクリプト言語があり、これで記述することでVimの挙動を設定できます。

ぼくの.vimrc

 というわけで、僕の.vimrcを下に張っつけときます。そんなに面白いものでもないですが。

"plugin by vim-plug
call plug#begin()
    Plug 'scrooloose/nerdtree'
    Plug 'scrooloose/syntastic'
    Plug 'Shougo/neocomplete'
    Plug 'tokorom/vim-review'
    Plug 'vim-airline/vim-airline'
    Plug 'vim-airline/vim-airline-themes'
    Plug 'mattn/emmet-vim'
call plug#end()

"syntastic setup
set statusline+=%#warningmsg#
set statusline+=%{SyntasticStatuslineFlag()}
set statusline+=%*

let g:syntastic_always_populate_loc_list=1
let g:syntastic_auto_loc_list=1
let g:syntastic_check_on_open=1
let g:syntastic_check_on_wq=0

let g:vim_review#include_filetypes=['c',"python","sh","java"]
"end

"neocomplete setup
let g:neocomplete#enable_at_startup=1
let g:neocomplete#max_list=25
inoremap <expr><C-l> neocomplete#complete_common_string()
"end

"powerline setup
set t_Co=256

let g:airline_powerline_fonts = 1
let g:airline#extensions#tabline#enabled = 1
let g:airline#extensions#tabline#buffer_idx_mode = 1
let g:airline#extensions#whitespace#mixed_indent_algo = 1
let g:airline_theme = 'dark'
if !exists('g:airline_symbols')
    let g:airline_symbols = {}
endif

" unicode symbols
let g:airline_left_sep = '»'
let g:airline_left_sep = '▶'
let g:airline_right_sep = '«'
let g:airline_right_sep = '◀'
let g:airline_symbols.crypt = '🔒'
let g:airline_symbols.linenr = '☰'
let g:airline_symbols.linenr = '␊'
let g:airline_symbols.linenr = '␤'
let g:airline_symbols.linenr = '¶'
let g:airline_symbols.maxlinenr = ''
let g:airline_symbols.maxlinenr = '㏑'
let g:airline_symbols.branch = '⎇'
let g:airline_symbols.paste = 'ρ'
let g:airline_symbols.paste = 'Þ'
let g:airline_symbols.paste = '∥'
let g:airline_symbols.spell = 'Ꞩ'
let g:airline_symbols.notexists = '∄'
let g:airline_symbols.whitespace = 'Ξ'
"end

"my funcs

command! -nargs=+ Atcoder call SetAtcoder(<f-args>)

function SetAtcoder(...)
    if a:0 == 1
        if a:1 == 'd'
            so $HOME/.vim/atcoder/setup/d.vim
        elseif a:1 == 'ds'
            so $HOME/.vim/atcoder/setup/simpled.vim
        elseif a:1 == 'cpp'
            so $HOME/.vim/atcoder/setup/cpp.vim
        else
            echo "Atcoder: file type '" . a:1 . "' not found."
        endif
    elseif a:0 == 2
        if a:2 == 'old'
            if a:1 == 'd'
                so $HOME/.vim/atcoder/setup/d_2.071_0.vim
            else
                echo "Atcoder: file type '" . a:1 . " " . a:2 . "' not found."
            endif
        else
            echo "Atcoder: file type '" . a:1 . " " . a:2 . "' not found."
        endif
    else
        echo "Atcoder: too many arguments."
    endif
endfunction

command! -nargs=? LaTeXreport call SetLatexreport(<f-args>)

function SetLatexreport(...)
    if a:0 == 0
        so $HOME/.vim/latexreport/setup/default.vim
    endif

endfunction

command! LaTeXpdf call SaveAndConvertLaTeXtoPDF()

function SaveAndConvertLaTeXtoPDF()
    write
    !lpreport "%:r"
endfunction

command! ReplacePanctuations call ReplaceJapanesePancuationsTraditionalToAcademic()

function ReplaceJapanesePancuationsTraditionalToAcademic()
    %s/。/./g
    %s/、/,/g
endfunction

"end

"basic settings

set encoding=utf-8
set number
set showmatch
set hlsearch
set synmaxcol=400
set tabstop=4
set softtabstop=4
set wildmode=list:longest
set expandtab
set shiftwidth=4
set autoindent
set cindent
set wildmenu
set history=5000
set laststatus=2
set timeoutlen=500
syntax on
filetype plugin on

let mapleader="\<Space>"

inoremap (<CR> ()<LEFT><CR><ESC><S-o>
inoremap {<CR> {}<LEFT><CR><ESC><S-o>
inoremap ( ()<LEFT>
inoremap { {}<LEFT>
inoremap [ []<LEFT>
inoremap ' ''<LEFT>
inoremap " ""<LEFT>
inoremap '<CR> '
inoremap "<CR> "
inoremap <<CR> <><LEFT>
inoremap ;<Leader><Leader> <ESC>A;
inoremap /*<CR> /**/<LEFT><LEFT>
inoremap $$ $$<LEFT>


nnoremap sh <C-h>
nnoremap sj <C-j>
nnoremap sk <C-k>
nnoremap sl <C-l>
nnoremap sw <C-w>

 順番に見ていきましょう。

プラグイン関連

"plugin by vim-plug
call plug#begin()
    Plug 'scrooloose/nerdtree'
    Plug 'scrooloose/syntastic'
    Plug 'Shougo/neocomplete'
    Plug 'tokorom/vim-review'
    Plug 'vim-airline/vim-airline'
    Plug 'vim-airline/vim-airline-themes'
    Plug 'mattn/emmet-vim'
call plug#end()

"syntastic setup
set statusline+=%#warningmsg#
set statusline+=%{SyntasticStatuslineFlag()}
set statusline+=%*

let g:syntastic_always_populate_loc_list=1
let g:syntastic_auto_loc_list=1
let g:syntastic_check_on_open=1
let g:syntastic_check_on_wq=0

let g:vim_review#include_filetypes=['c',"python","sh","java"]
"end

"neocomplete setup
let g:neocomplete#enable_at_startup=1
let g:neocomplete#max_list=25
inoremap <expr><C-l> neocomplete#complete_common_string()
"end

 実は僕はvim-plug派です。巷ではdein.vimが多数派なんじゃないですかね、知らんけど。dein.vimはShougoさんというVimプラグイン界のLv.255みたいな方が作成したプラグインマネージャで、たくさんプラグインを入れてもあんまり起動速度が落ちないらしいです。ただちょっと煩雑で、Vimガチ勢でもないしテキトーに使いたい僕は、軽く書くだけでよさそうなvim-plugを採用しています。
 ちなみにVim 8.0から標準でもプラグイン管理機能がついています。使ったことはありません。

 導入してるプラグインはこんな感じです。

プラグイン 説明
nerdtree Vim内でファイルブラウズができる
syntastic シンタックスチェッカー
neocomplete 入力補完
vim-review RE:Viewという技術書執筆ツールのサポート
vim-airline PowerLineでVimをイケてる見た目にする(後述)
emmet-vim HTMLやCSSの入力補助 コンリテ課題がクソすぎて入れた

 ちなみに現在neocompleteの開発は停止され、代わって元々nvim用だった(Vim 8以降はVimにも対応)deoplete.nvimが開発されています。面倒だから移行してないだけです。

vim-airlineまわり

"powerline setup
set t_Co=256

let g:airline_powerline_fonts = 1
let g:airline#extensions#tabline#enabled = 1
let g:airline#extensions#tabline#buffer_idx_mode = 1
let g:airline#extensions#whitespace#mixed_indent_algo = 1
let g:airline_theme = 'dark'
if !exists('g:airline_symbols')
    let g:airline_symbols = {}
endif

" unicode symbols
let g:airline_left_sep = '»'
let g:airline_left_sep = '▶'
let g:airline_right_sep = '«'
let g:airline_right_sep = '◀'
let g:airline_symbols.crypt = '🔒'
let g:airline_symbols.linenr = '☰'
let g:airline_symbols.linenr = '␊'
let g:airline_symbols.linenr = '␤'
let g:airline_symbols.linenr = '¶'
let g:airline_symbols.maxlinenr = ''
let g:airline_symbols.maxlinenr = '㏑'
let g:airline_symbols.branch = '⎇'
let g:airline_symbols.paste = 'ρ'
let g:airline_symbols.paste = 'Þ'
let g:airline_symbols.paste = '∥'
let g:airline_symbols.spell = 'Ꞩ'
let g:airline_symbols.notexists = '∄'
let g:airline_symbols.whitespace = 'Ξ'
"end

 vim-airlineとは、Poweline(ターミナルのプロンプトをリッチにしてGitのブランチ管理とかできるツール)を用いてVimをイカした見た目にできるプラグインです。この辺の経緯はこちらに詳しく書きました。
 これを使うとファイル編集のとき画面が賑やかになって楽しいです。ちょっとだけね。

ユーザ定義コマンド

 ここまではありものを寄せ集めて便利機能を追加しただけでしたが、ここからはお手製です。

"my funcs

command! -nargs=+ Atcoder call SetAtcoder(<f-args>)

function SetAtcoder(...)
    if a:0 == 1
        if a:1 == 'd'
            so $HOME/.vim/atcoder/setup/d.vim
        elseif a:1 == 'ds'
            so $HOME/.vim/atcoder/setup/simpled.vim
        elseif a:1 == 'cpp'
            so $HOME/.vim/atcoder/setup/cpp.vim
        else
            echo "Atcoder: file type '" . a:1 . "' not found."
        endif
    elseif a:0 == 2
        if a:2 == 'old'
            if a:1 == 'd'
                so $HOME/.vim/atcoder/setup/d_2.071_0.vim
            else
                echo "Atcoder: file type '" . a:1 . " " . a:2 . "' not found."
            endif
        else
            echo "Atcoder: file type '" . a:1 . " " . a:2 . "' not found."
        endif
    else
        echo "Atcoder: too many arguments."
    endif
endfunction

 前半部では競プロ関係のコマンド定義をしています。あたかも競プロといえばAtCoderみたいな書き方をしていて殺されそうですが、AtCoder以外やったことないし何なら最近はAtCoderもやってないので許してください。
 僕は~/.vim/にシステムファイル以外も色々突っ込んでしまっています。~/.vim/atcoder/setup/にAtCoder用のテンプレートが色々と入っていて、実際に使う時はエディタからコマンドラインモードで:Atcoder dのように実行するとD言語用のテンプレートが展開されます。
 以前のAtCoderはdmd v2.071までしか対応していなくて不便でした。import std;が使えなかったり、UFCSが効かなくて同名のdeprecatedなpropertyが呼ばれたり......


command! -nargs=? LaTeXreport call SetLatexreport(<f-args>)

function SetLatexreport(...)
    if a:0 == 0
        so $HOME/.vim/latexreport/setup/default.vim
    endif

endfunction

command! LaTeXpdf call SaveAndConvertLaTeXtoPDF()

function SaveAndConvertLaTeXtoPDF()
    write
    !lpreport "%:r"
endfunction

command! ReplacePanctuations call ReplaceJapanesePancuationsTraditionalToAcademic()

function ReplaceJapanesePancuationsTraditionalToAcademic()
    %s/。/./g
    %s/、/,/g
endfunction

"end

 後半部は $\LaTeX$ 用のコマンドです。えぇ、はい。基礎科学実験Aのために作りました。:LaTeXreportでテンプレートを展開して、:LaTeXpdfで今編集中のファイルからpdfを出力できるようになっています。あとは適当に:!evince hoge.pdf &とかで開けばOKです。

基本設定

"basic settings

set encoding=utf-8
set number
set showmatch
set hlsearch
set synmaxcol=400
set tabstop=4
set softtabstop=4
set wildmode=list:longest
set expandtab
set shiftwidth=4
set autoindent
set cindent
set wildmenu
set history=5000
set laststatus=2
set timeoutlen=500
syntax on
filetype plugin on

 この辺はみなさん思い思いの設定にしていると思います。set numberで行番号表示とか。
 僕は4タブ派なのでset tabstop=4としています。これも宗教戦争の火種なので注意ですね。あと、set expandtabとしておくとTabキー押下時に挿入されるのがタブ文字ではなくtabstop分の空白文字になります。
 インデント関係はどうするのが正解なんでしょうか?普段はとりあえずautoindentと、C言語系文法の言語を書くことが多いのでcindentをオンにしています。smartindentはよくわかんなかった(小並感)。

キーバインド

let mapleader="\<Space>"

inoremap (<CR> ()<LEFT><CR><ESC><S-o>
inoremap {<CR> {}<LEFT><CR><ESC><S-o>
inoremap ( ()<LEFT>
inoremap { {}<LEFT>
inoremap [ []<LEFT>
inoremap ' ''<LEFT>
inoremap " ""<LEFT>
inoremap '<CR> '
inoremap "<CR> "
inoremap <<CR> <><LEFT>
inoremap ;<Leader><Leader> <ESC>A;
inoremap /*<CR> /**/<LEFT><LEFT>
inoremap $$ $$<LEFT>


nnoremap sh <C-h>
nnoremap sj <C-j>
nnoremap sk <C-k>
nnoremap sl <C-l>
nnoremap sw <C-w>

 これが一番悩ましい部分でしょう。例えばHTMLなら<と打った時点ですぐに<>として欲しいけど、そうすると他の言語で不便。'''としたいけど$\LaTeX$で数式を書く時に不便。カッコの内側からでも;<Leader>で行末にセミコロンをつけたいけど、そうするとforeach(i; ...)とかの時に困る。
 あとはLeaderをどのキーに割り振るかも難しいところです。僕はスペースキーに振っていますが、結構使いづらくて困っています。いいアイデアがあったら教えてください。

おわりに

 (もし存在したら)電通大Vimmerで集まってvimrc読書会やりませんか?興味のある方はTwitterに連絡していただけると幸いです。

3
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?