これは 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に連絡していただけると幸いです。