Vimにはtextmateちっくなsnippet補完を実現するためのプラグインがいくつかあります。
neocomplcache-snippets-complete, snipMate, UltiSnipなどなど。
私が利用しているのは、neocomplcache-snippets-completeなので、それを利用する時の流れについての話です。
neocomplecacheを使っていると、補完が統合されるので、neocomplecacheユーザーは大体これに落ち着くと思います。
ちょっと調べたところだと、UltiSnipはかなり高機能っぽいのですが、pythonインターフェースが必要で、ちょっと複雑過ぎるかもしれません。
読み込みのルール
現在のneocomplecacheは、内部でvimのバッファが持っているファイルタイプとは別に、
独自のファイルタイプ情報を持っています。
最近になって(8月後半ぐらい)、NeoComplCacheSetFileTypeというコマンドが追加され、
neocomplecacheがどのfiletypeで補完を行うかを、vim本体のfiletypeとは独立して設定できるようになりました。
また、neocomplecacheでは複合ファイルタイプに対応しているので、
ruby.railsというファイルタイプを指定すれば、rubyというファイルタイプについての補完設定と、
railsというファイルタイプについての補完設定が動作するようになります。
一方で、railsで開発をしているとvim-railsというプラグインを使っていることが多いと思いますが、
そのプラグインがrailsで宣言的に記述するようなメソッド名をハイライトしてくれます。
しかし、vimのfiletypeをruby.railsにすると、そのハイライトが消えてしまいます。
ソースを読んだところ、filetypeがrubyじゃないと駄目みたいで、そういう仕様のようです。
なので、railsで書いている場合は出来れば複合ファイルタイプは使いたくない。
で、以前ならば、snippetを全部、ruby用のファイルに書くという手段が取れたのですが、
rails外でコード書いてる時にrailsのsnippetは必要無いわけで、どうもスマートではない。
そこで、NeoComplCacheSetFileTypeが活用できます。
設定例
vim-railsは、railsっぽいファイルを開くとb:rails_rootというバッファ変数を定義します。
この変数の有無でrailsかどうかを容易に判別できるので、これを利用します。
autocmd BufEnter * if exists("b:rails_root") | NeoComplCacheSetFileType ruby.rails | endif
autocmd BufEnter * if (expand("%") =~ "_spec\.rb$") || (expand("%") =~ "^spec.*\.rb$") | NeoComplCacheSetFileType ruby.rspec | endif
こんな感じで書いておけば、railsの時だけ、neocomplecacheのみrubyとrailsの両方の補完設定を活用できます。
下のrspec向けの設定は、ファイルパスでrspecかどうかを判断しています。
これで、ruby.snipに定義してあるsnippetも、rails.snipに定義してあるsnippetも、
望む通りの環境で利用することができます。
let g:neocomplcache_snippets_dir = $HOME . '/.vim/snippets'
nnoremap <Space>se :<C-U>NeoComplCacheEditSnippets<CR>
後はこんな感じで、snippetの格納場所を設定し、snippet編集用のコマンドをさっと呼べるようにしておけば、確認するのも楽です。
" SuperTab like snippets behavior.
imap <expr><TAB> neocomplcache#sources#snippets_complete#expandable() ? "\<Plug>(neocomplcache_snippets_expand)" : pumvisible() ? "\<C-n>" : "\<TAB>"
今のところ、snippetの展開については、neocomplecacheの設定例にあるようにこんな感じにしてます。
後は、私のsnippetについて張っておきます。
書式についてはマニュアルを参照してください。
railsのsnipはデフォルトで定義されているものがあるのですが、
どうも貧弱な感じなので、一旦削除して書き換えているものがあります。
一部、snipMateやUltiSnipを参考にパクってきてるものもあります。
rspec周りはコピペベースで、まだちょっと適当なのでご了承ください。
snippet encutf
abbr # coding: utf-8
# coding: utf-8
alias encutf magic
snippet class
abbr class end
class ${1:name}
${2}
end
snippet mod
abbr module end
module ${1:name}
${2}
end
snippet defi
abbr def initialize(...
def initialize${1:(${2:args\})}
${3}
end
snippet unless
abbr unless end
unless ${1:condition}
${2}
end
snippet ife
abbr if else end
if ${1:condition}
${2}
else
${3}
end
snippet ifei
abbr if elsif end
if ${1:condition}
${2}
elsif ${3:condition}
${4}
end
snippet case
abbr case when end
case ${1:var}
when ${2:expr}
${3}
end
alias case sw
snippet inj
abbr inject(n) do end
inject(${1:initial}) do |${2:acc}, ${3:val}|
${4}
end
snippet injp
abbr inject(n, &:method)
inject(${1:initial}, &:${2:method})
snippet eacho
abbr each_with_object(obj) do end
each_with_object(${1:memoobj}) do |${2:val}, ${3:memoobj}|
${4}
end
snippet map
abbr map do end
map do |${1:var}|
${2}
end
snippet mapp
abbr map(&:method)
map(&:${1:method})
snippet sortby
abbr sort_by(&:method)
sort_by(&:${1:method})
alias sortby sort_by
snippet sortbydo
abbr sort_by do end
sort_by do |${1:var}|
${2}
end
snippet begin
abbr begin rescue end
begin
${1:# TODO}
rescue
${2:# TODO}
end
snippet sc
abbr scope :method, lambda
prev_word '^'
scope :${1}, lambda { ${2} }
snippet dsc
abbr default_scope lambda
prev_word '^'
default_scope lambda { ${1} }
snippet bff
abbr before_filter
prev_word '^'
before_filter :${1:method}
delete hm
snippet hm
abbr has_many :objects
prev_word '^'
has_many :${1:objects}
alias hm has_m
snippet hmo
abbr has_many with options
prev_word '^'
has_many :${1:objects}${2:, class_name: "${3\}", foreign_key: "${4:reference\}_id"}
snippet hmt
abbr has_many :objects, :through
prev_word '^'
has_many :${1:objects}, through: ${2:relation}
delete ho
snippet ho
abbr has_one :object
prev_word '^'
has_one :${1:object}
alias ho has_o
delete bt
snippet bt
abbr belongs_to :object
prev_word '^'
belongs_to :${1:object}
alias bt bel
snippet bto
abbr belongs_to with options
prev_word '^'
belongs_to :${1:object}${2:, class_name: "${3\}", foreign_key: "${4:reference\}_id"}
delete logd
snippet logd
abbr logger.debug
logger.debug(${1})
delete logi
snippet logi
abbr logger.info
logger.info(${1})
delete logw
snippet logw
abbr logger.warn
logger.warn(${1})
delete loge
snippet loge
abbr logger.error
logger.error(${1})
delete logf
snippet logf
abbr logger.fatal
logger.fatal(${1})
snippet fla
abbr flash[...]
prev_word '^'
flash[:${1:notice}] = "${2:Successfully created...}"
alias fla flash
snippet rep
abbr redirect_to (path)
redirect_to ${1:model}_path${2:(${3:params\})}
delete va
snippet va
abbr validates_associated
validates_associated :${1:attr}
delete vb
snippet vb
abbr validates_acceptance_of
validates_acceptance_of :${1:attr}
delete vc
snippet vc
abbr validates_confirmation_of
validates_confirmation_of :${1:attr}
delete ve
snippet ve
abbr validates_exclusion_of
validates_exclusion_of :${1:attr}, in: ${2:%w( ${3:mov avi\} )}
delete vf
snippet vf
abbr validates_format_of
validates_format_of :${1:attr}, with: /${2:regexp}/
delete vi
snippet vi
abbr validates_inclusion_of
validates_inclusion_of :${1:attr}, in: ${2:%w( ${3:mov avi\} )}
delete vl
snippet vl
abbr validates_length_of
validates_length_of :${1:attr}, within: ${2:3..20}
delete vn
snippet vn
abbr validates_numericality_of
validates_numericality_of :${1:attr}
snippet vng
abbr validates_numericality_of greater_than: n
validates_numericality_of :${1:attr}, greater_than: ${2:num}
snippet vnl
abbr validates_numericality_of less_than: n
validates_numericality_of :${1:attr}, less_than: ${2:num}
delete vp
snippet vp
abbr validates_presence_of
validates_presence_of :${1:attr}
delete vu
snippet vu
abbr validates_uniqueness_of
validates_uniqueness_of :${1:attr}
snippet aln
abbr allow_nil
allow_nil: ${1:true}
delete ra
snippet ra
abbr render :action
render action: ${1}
delete rc
snippet rc
abbr render :controller
render controller: ${1}
delete rf
snippet rf
abbr render :file
render file: ${1}
delete ri
snippet ri
abbr render :inline
render inline: ${1}
delete rj
snippet rj
abbr render :json
render json: ${1}
delete rl
snippet rl
abbr render :layout
render layout: ${1}
delete rp
snippet rp
abbr render :partial
render partial: ${1}
delete rt
snippet rt
abbr render :text
render text: ${1}
delete rx
snippet rx
abbr render :xml
render xml: ${1}
delete id
delete object
delete partial
delete action
snippet action
abbr action: name
action: ${1}
snippet tzn
abbr Time.zone.now
Time.zone.now
snippet res
abbr resources
prev_word '^'
resources :${1:resources}
alias res resources
delete rst
snippet rst
abbr respond_to
prev_word '^'
respond_to do |format|
format.html${1: { ${2\} \}}
format.json { render json: ${3} }
end
snippet befs
abbr before_save
prev_word '^'
before_save :${1:method}
snippet befc
abbr before_create
prev_word '^'
before_create :${1:method}
snippet befu
abbr before_update
prev_word '^'
before_update :${1:method}
snippet befv
abbr before_validation
prev_word '^'
before_validation :${1:method}
snippet befvc
abbr before_validation_on_create
prev_word '^'
before_validation_on_create :${1:method}
snippet befvu
abbr before_validation_on_update
prev_word '^'
before_validation_on_update :${1:method}
snippet befd
abbr before_destroy
prev_word '^'
before_destroy :${1:method}
snippet afts
abbr after_save
prev_word '^'
after_save :${1:method}
snippet aftc
abbr after_create
prev_word '^'
after_create :${1:method}
snippet aftu
abbr after_update
prev_word '^'
after_update :${1:method}
snippet aftv
abbr after_validation
prev_word '^'
after_validation :${1:method}
snippet aftvc
abbr after_validation_on_create
prev_word '^'
after_validation_on_create :${1:method}
snippet aftvu
abbr after_validation_on_update
prev_word '^'
after_validation_on_update :${1:method}
snippet aftd
abbr after_destroy
prev_word '^'
after_destroy :${1:method}
snippet try
abbr try(:method)
try(:${1:method})
snippet desc
abbr describe end
prev_word '^'
describe "${1:name}" do
${2}
end
snippet desch
abbr spec_helper describe
require 'spec_helper'
describe ${1:`Snippet_RubySpecNameFromFilename()`} do
${2}
end
snippet desccon
describe "${1:GET|POST|PUT|DELETE} ${2:/some/path}${3}" do
${4}
end
snippet bef
before do
${1}
end
alias bef before
snippet befa
before(:all) do
${1}
end
alias befa beforeall
snippet aft
after do
${1}
end
alias aft after
snippet afta
after(:all) do
${1}
end
alias afta afterall
snippet con
context "${1}" do
${2}
end
alias con context
snippet cona
abbr context after callback
context "after #${1:save!}" do
before do
subject.$1
end
${2}
end
snippet subjc
subject { ${1:FactoryGirl.create(:${2:name\})} }
snippet subjb
subject { ${1:FactoryGirl.build(:${2:name\})} }
snippet it
it "${1}" do
${2}
end
snippet itb
abbr it {}
it { ${1} }
snippet its
it "should ${1:work correctly}" do
${2}
end
snippet is
it { should ${1} }
snippet isn
it { should_not ${1} }
snippet sh
should == ${1:value}
${2}
snippet shn
should_not == ${1:value}
${2}
snippet shs
should satisfy { |${1:obj}| ${2} }
${3}
snippet shp
should be_${1:predicate}
alias shp shbe
snippet shh
should have(${1:num}).${2:things}
${3}
snippet she
should eq(${1:value})
${3}
snippet shne
should_not eq(${1:value})
${2}
snippet shnredt
response.should_not redirect_to(${1:url})
${2}
snippet shbw
should be_within(${1:tolerance}).of(${2:result})
${3}
snippet shnbw
should_not be_within(${1:tolerance}).of(${2:result})
${4}
snippet shhal
should have_at_least(${1:num}).${2:things}
${3}
snippet shhi
should have(${1:n}).records
${2}
snippet shns
should_not satisfy { |${1:obj}| ${2} }
${3}
snippet shbko
should be_a_kind_of(${1:class})
${2}
snippet shnbko
should_not be_a_kind_of(${1:klass})
${2}
snippet shnbe
.should_not be_${1:predicate}
snippet shre
should raise_error(${1:error})
${2}
snippet shnre
should_not raise_error(${1:error})
${2}
alias shre shraise
snippet shc
expect {
${1}
}.should change(${2:described_class}, :${3:count}).by(${4:1})
alias shc exshc
snippet shnc
expect {
${1}
}.should_not change(${2:target}, :${3:method})
snippet shrt
should respond_to(:${1:sym})
${2}
snippet shnrt
should_not respond_to(:${1:sym})
${2}
snippet shr
should_receive(:${1:message})${2}
${3}
snippet shnr
should_not_receive(:${1:message})${2}
${3}
snippet wia
with(${1:args})
${2}
snippet shm
should match(/${1:regexp}/)
${2}
snippet shnm
should_not match(/${1:regexp}/)
${2}
snippet shredt
response.should redirect_to(${1:url})
${2}
snippet shbr
response.should be_redirect
${1}
snippet shnbr
response.should_not be_redirect
${1}
snippet shbs
response.should be_success
${1}
snippet shnbs
response.should_not be_success
${1}
snippet shtemp
response.should render_template(:${1:template})
${2}
snippet shbio
should be_instance_of(${1:class})
${2}
snippet shnbio
should_not be_instance_of(${1:klass})
${2}
snippet sc
abbr shared_context do end
shared_context "${1:condition}" do
${2}
end
alias sc shared_context
snippet scm
abbr shared_context with metadata
shared_context "${1:condition}", :${2:key} => ${3:value} do
${4}
end
snippet inc
abbr include_context
include_context "${1}"
alias inc include_context
snippet se
abbr shared_examples do end
shared_examples "${1:do something}" do
${2}
end
alias se shared_examples
snippet sed
shared_examples "${1:}" do
describe "as $1" do
${2}
end
end
snippet ibl
abbr it_behaves_like
it_behaves_like '${1}'
alias ibl it_behaves
snippet ine
abbr include_examples
include_examples "${1}"
alias ine include_examples
snippet let
abbr let {}
let(:${1}) { ${2} }
snippet let!
abbr let! {}
let!(:${1}) { ${2} }
snippet letf
let(:${1:model}) do
FactoryGirl.create(:${2:$1})
end
snippet atl
at_least(${1:n}).times
snippet atm
at_most(${1:n}).times
snippet on
once
snippet tw
twice
snippet ber
be_redirect
snippet ex
exactly(${1:n}).times
alias ex exact
snippet annot
any_number_of_times
snippet shham
${1:target}.should have_at_most(${2:num}).${3:things}
${4}
snippet ant
and_throw(${1:sym})
snippet any
and_yield(${1:values})
snippet mat
RSpec::Matchers.define :${1:matcher_name} do
match do |model|
# return Boolean
${2}
end
end
alias mat matcher
snippet anr
and_return(${1:value})
snippet anrb
and_return { ${1} }
snippet anra
and_raise(${1:exception})
snippet st
stub(:${1:method}).and_returns(${2:return})
alias st stub
snippet sm
stub_model(${1:model}, {${2}})
snippet mm
mock_model(${1:model})${2}
snippet moc
${1:var} = mock("${2:mock_name}"${3:, :null_object => true})
${4}
snippet facb
FactoryGirl.build(:${1})
snippet fac
FactoryGirl(:${1}, ${2})
snippet facc
FactoryGirl.create(:${1})
snippet facs
sequence(:${1}) {|n| "${2}#{n}"}
snippet facn
FactoryGirl.next(:${1:sequence-name})
snippet faca
f.${1:model} {|a| a.association(:${2:$1})}
snippet facd
FactoryGirl.define do
${1}
end
snippet facf
factory ${1:name} do
${2}
end