xref: /vim-8.2.3635/runtime/ftplugin/ruby.vim (revision d09091d4)
1071d4279SBram Moolenaar" Vim filetype plugin
2071d4279SBram Moolenaar" Language:		Ruby
3ec7944aaSBram Moolenaar" Maintainer:		Tim Pope <[email protected]>
4ec7944aaSBram Moolenaar" URL:			https://github.com/vim-ruby/vim-ruby
5c6249bb2SBram Moolenaar" Release Coordinator:	Doug Kearns <[email protected]>
6*d09091d4SBram Moolenaar" Last Change:		2019 Jan 06
7071d4279SBram Moolenaar
8071d4279SBram Moolenaarif (exists("b:did_ftplugin"))
9071d4279SBram Moolenaar  finish
10071d4279SBram Moolenaarendif
11071d4279SBram Moolenaarlet b:did_ftplugin = 1
12071d4279SBram Moolenaar
1360a795aaSBram Moolenaarlet s:cpo_save = &cpo
1460a795aaSBram Moolenaarset cpo&vim
1560a795aaSBram Moolenaar
16756ec0f3SBram Moolenaarif has("gui_running") && !has("gui_win32")
17ec7944aaSBram Moolenaar  setlocal keywordprg=ri\ -T\ -f\ bs
18756ec0f3SBram Moolenaarelse
19756ec0f3SBram Moolenaar  setlocal keywordprg=ri
20756ec0f3SBram Moolenaarendif
21756ec0f3SBram Moolenaar
2260a795aaSBram Moolenaar" Matchit support
2360a795aaSBram Moolenaarif exists("loaded_matchit") && !exists("b:match_words")
2460a795aaSBram Moolenaar  let b:match_ignorecase = 0
2560a795aaSBram Moolenaar
2660a795aaSBram Moolenaar  let b:match_words =
2779166c43SBram Moolenaar	\ '\<\%(if\|unless\|case\|while\|until\|for\|do\|class\|module\|def\|begin\)\>=\@!' .
2860a795aaSBram Moolenaar	\ ':' .
2979166c43SBram Moolenaar	\ '\<\%(else\|elsif\|ensure\|when\|rescue\|break\|redo\|next\|retry\)\>' .
3060a795aaSBram Moolenaar	\ ':' .
3189bcfda6SBram Moolenaar        \ '\%(^\|[^.\:@$]\)\@<=\<end\:\@!\>' .
3291170f8aSBram Moolenaar	\ ',{:},\[:\],(:)'
3360a795aaSBram Moolenaar
3460a795aaSBram Moolenaar  let b:match_skip =
3560a795aaSBram Moolenaar	\ "synIDattr(synID(line('.'),col('.'),0),'name') =~ '" .
3679166c43SBram Moolenaar	\ "\\<ruby\\%(String\\|StringDelimiter\\|ASCIICode\\|Escape\\|" .
3789bcfda6SBram Moolenaar        \ "Regexp\\|RegexpDelimiter\\|" .
3879166c43SBram Moolenaar	\ "Interpolation\\|NoInterpolation\\|Comment\\|Documentation\\|" .
3979166c43SBram Moolenaar	\ "ConditionalModifier\\|RepeatModifier\\|OptionalDo\\|" .
4079166c43SBram Moolenaar	\ "Function\\|BlockArgument\\|KeywordAsMethod\\|ClassVariable\\|" .
4179166c43SBram Moolenaar	\ "InstanceVariable\\|GlobalVariable\\|Symbol\\)\\>'"
4260a795aaSBram Moolenaarendif
4360a795aaSBram Moolenaar
4460a795aaSBram Moolenaarsetlocal formatoptions-=t formatoptions+=croql
4560a795aaSBram Moolenaar
46ec7944aaSBram Moolenaarsetlocal include=^\\s*\\<\\(load\\>\\\|require\\>\\\|autoload\\s*:\\=[\"']\\=\\h\\w*[\"']\\=,\\)
4760a795aaSBram Moolenaarsetlocal suffixesadd=.rb
48c6249bb2SBram Moolenaar
49756ec0f3SBram Moolenaarif exists("&ofu") && has("ruby")
509e54a0e7SBram Moolenaar  setlocal omnifunc=rubycomplete#Complete
51c6249bb2SBram Moolenaarendif
5260a795aaSBram Moolenaar
5360a795aaSBram Moolenaar" TODO:
5460a795aaSBram Moolenaar"setlocal define=^\\s*def
5560a795aaSBram Moolenaar
5660a795aaSBram Moolenaarsetlocal comments=:#
5760a795aaSBram Moolenaarsetlocal commentstring=#\ %s
5860a795aaSBram Moolenaar
59ec7944aaSBram Moolenaarif !exists('g:ruby_version_paths')
60ec7944aaSBram Moolenaar  let g:ruby_version_paths = {}
6160a795aaSBram Moolenaarendif
62ec7944aaSBram Moolenaar
6389bcfda6SBram Moolenaarfunction! s:query_path(root) abort
64ec7944aaSBram Moolenaar  let code = "print $:.join %q{,}"
65*d09091d4SBram Moolenaar  if &shell =~# 'sh' && empty(&shellxquote)
6689bcfda6SBram Moolenaar    let prefix = 'env PATH='.shellescape($PATH).' '
6760a795aaSBram Moolenaar  else
68ec7944aaSBram Moolenaar    let prefix = ''
69ec7944aaSBram Moolenaar  endif
70ec7944aaSBram Moolenaar  if &shellxquote == "'"
7189bcfda6SBram Moolenaar    let path_check = prefix.'ruby --disable-gems -e "' . code . '"'
72ec7944aaSBram Moolenaar  else
7389bcfda6SBram Moolenaar    let path_check = prefix."ruby --disable-gems -e '" . code . "'"
74ec7944aaSBram Moolenaar  endif
75ec7944aaSBram Moolenaar
76ec7944aaSBram Moolenaar  let cd = haslocaldir() ? 'lcd' : 'cd'
7789bcfda6SBram Moolenaar  let cwd = fnameescape(getcwd())
78ec7944aaSBram Moolenaar  try
79ec7944aaSBram Moolenaar    exe cd fnameescape(a:root)
80ec7944aaSBram Moolenaar    let path = split(system(path_check),',')
8189bcfda6SBram Moolenaar    exe cd cwd
82ec7944aaSBram Moolenaar    return path
83ec7944aaSBram Moolenaar  finally
8489bcfda6SBram Moolenaar    exe cd cwd
85ec7944aaSBram Moolenaar  endtry
86ec7944aaSBram Moolenaarendfunction
87ec7944aaSBram Moolenaar
8889bcfda6SBram Moolenaarfunction! s:build_path(path) abort
89ec7944aaSBram Moolenaar  let path = join(map(copy(a:path), 'v:val ==# "." ? "" : v:val'), ',')
90ec7944aaSBram Moolenaar  if &g:path !~# '\v^\.%(,/%(usr|emx)/include)=,,$'
91ec7944aaSBram Moolenaar    let path = substitute(&g:path,',,$',',','') . ',' . path
92ec7944aaSBram Moolenaar  endif
93ec7944aaSBram Moolenaar  return path
94ec7944aaSBram Moolenaarendfunction
95ec7944aaSBram Moolenaar
96ec7944aaSBram Moolenaarif !exists('b:ruby_version') && !exists('g:ruby_path') && isdirectory(expand('%:p:h'))
97ec7944aaSBram Moolenaar  let s:version_file = findfile('.ruby-version', '.;')
9889bcfda6SBram Moolenaar  if !empty(s:version_file) && filereadable(s:version_file)
99ec7944aaSBram Moolenaar    let b:ruby_version = get(readfile(s:version_file, '', 1), '')
100ec7944aaSBram Moolenaar    if !has_key(g:ruby_version_paths, b:ruby_version)
101ec7944aaSBram Moolenaar      let g:ruby_version_paths[b:ruby_version] = s:query_path(fnamemodify(s:version_file, ':p:h'))
102ec7944aaSBram Moolenaar    endif
10360a795aaSBram Moolenaar  endif
10460a795aaSBram Moolenaarendif
10560a795aaSBram Moolenaar
106ec7944aaSBram Moolenaarif exists("g:ruby_path")
107ec7944aaSBram Moolenaar  let s:ruby_path = type(g:ruby_path) == type([]) ? join(g:ruby_path, ',') : g:ruby_path
108ec7944aaSBram Moolenaarelseif has_key(g:ruby_version_paths, get(b:, 'ruby_version', ''))
109ec7944aaSBram Moolenaar  let s:ruby_paths = g:ruby_version_paths[b:ruby_version]
110ec7944aaSBram Moolenaar  let s:ruby_path = s:build_path(s:ruby_paths)
111ec7944aaSBram Moolenaarelse
112ec7944aaSBram Moolenaar  if !exists('g:ruby_default_path')
113ec7944aaSBram Moolenaar    if has("ruby") && has("win32")
114ec7944aaSBram Moolenaar      ruby ::VIM::command( 'let g:ruby_default_path = split("%s",",")' % $:.join(%q{,}) )
115ec7944aaSBram Moolenaar    elseif executable('ruby')
116ec7944aaSBram Moolenaar      let g:ruby_default_path = s:query_path($HOME)
117ec7944aaSBram Moolenaar    else
118ec7944aaSBram Moolenaar      let g:ruby_default_path = map(split($RUBYLIB,':'), 'v:val ==# "." ? "" : v:val')
119ec7944aaSBram Moolenaar    endif
120ec7944aaSBram Moolenaar  endif
121ec7944aaSBram Moolenaar  let s:ruby_paths = g:ruby_default_path
122ec7944aaSBram Moolenaar  let s:ruby_path = s:build_path(s:ruby_paths)
123ec7944aaSBram Moolenaarendif
124ec7944aaSBram Moolenaar
125ec7944aaSBram Moolenaarif stridx(&l:path, s:ruby_path) == -1
1261d68952aSBram Moolenaar  let &l:path = s:ruby_path
127ec7944aaSBram Moolenaarendif
128ec7944aaSBram Moolenaarif exists('s:ruby_paths') && stridx(&l:tags, join(map(copy(s:ruby_paths),'v:val."/tags"'),',')) == -1
129ec7944aaSBram Moolenaar  let &l:tags = &tags . ',' . join(map(copy(s:ruby_paths),'v:val."/tags"'),',')
130ec7944aaSBram Moolenaarendif
13160a795aaSBram Moolenaar
13289bcfda6SBram Moolenaarif (has("gui_win32") || has("gui_gtk")) && !exists("b:browsefilter")
13360a795aaSBram Moolenaar  let b:browsefilter = "Ruby Source Files (*.rb)\t*.rb\n" .
13460a795aaSBram Moolenaar                     \ "All Files (*.*)\t*.*\n"
13560a795aaSBram Moolenaarendif
13660a795aaSBram Moolenaar
137*d09091d4SBram Moolenaarlet b:undo_ftplugin = "setl inc= sua= path= tags= fo< com< cms< kp="
13879166c43SBram Moolenaar      \."| unlet! b:browsefilter b:match_ignorecase b:match_words b:match_skip"
13979166c43SBram Moolenaar      \."| if exists('&ofu') && has('ruby') | setl ofu< | endif"
140*d09091d4SBram Moolenaar
141*d09091d4SBram Moolenaarif get(g:, 'ruby_recommended_style', 1)
142*d09091d4SBram Moolenaar  setlocal shiftwidth=2 softtabstop=2 expandtab
143*d09091d4SBram Moolenaar  let b:undo_ftplugin .= ' | setl sw< sts< et<'
144*d09091d4SBram Moolenaarendif
145*d09091d4SBram Moolenaar
146*d09091d4SBram Moolenaar" To activate, :set ballooneval
147*d09091d4SBram Moolenaarif exists('+balloonexpr') && get(g:, 'ruby_balloonexpr')
148*d09091d4SBram Moolenaar  setlocal balloonexpr=RubyBalloonexpr()
149*d09091d4SBram Moolenaar  let b:undo_ftplugin .= "| setl bexpr="
150*d09091d4SBram Moolenaarendif
15179166c43SBram Moolenaar
15289bcfda6SBram Moolenaarfunction! s:map(mode, flags, map) abort
15389bcfda6SBram Moolenaar  let from = matchstr(a:map, '\S\+')
15489bcfda6SBram Moolenaar  if empty(mapcheck(from, a:mode))
155*d09091d4SBram Moolenaar    exe a:mode.'map' '<buffer>' a:map
15689bcfda6SBram Moolenaar    let b:undo_ftplugin .= '|sil! '.a:mode.'unmap <buffer> '.from
15789bcfda6SBram Moolenaar  endif
15889bcfda6SBram Moolenaarendfunction
15989bcfda6SBram Moolenaar
160*d09091d4SBram Moolenaarcmap <buffer><script><expr> <Plug><ctag> substitute(RubyCursorTag(),'^$',"\022\027",'')
16189bcfda6SBram Moolenaarcmap <buffer><script><expr> <Plug><cfile> substitute(RubyCursorFile(),'^$',"\022\006",'')
162*d09091d4SBram Moolenaarlet b:undo_ftplugin .= "| sil! cunmap <buffer> <Plug><ctag>| sil! cunmap <buffer> <Plug><cfile>"
16389bcfda6SBram Moolenaar
16479166c43SBram Moolenaarif !exists("g:no_plugin_maps") && !exists("g:no_ruby_maps")
16589bcfda6SBram Moolenaar  nmap <buffer><script> <SID>:  :<C-U>
16689bcfda6SBram Moolenaar  nmap <buffer><script> <SID>c: :<C-U><C-R>=v:count ? v:count : ''<CR>
16789bcfda6SBram Moolenaar
168*d09091d4SBram Moolenaar  nnoremap <silent> <buffer> [m :<C-U>call <SID>searchsyn('\<def\>',['rubyDefine'],'b','n')<CR>
169*d09091d4SBram Moolenaar  nnoremap <silent> <buffer> ]m :<C-U>call <SID>searchsyn('\<def\>',['rubyDefine'],'','n')<CR>
170*d09091d4SBram Moolenaar  nnoremap <silent> <buffer> [M :<C-U>call <SID>searchsyn('\<end\>',['rubyDefine'],'b','n')<CR>
171*d09091d4SBram Moolenaar  nnoremap <silent> <buffer> ]M :<C-U>call <SID>searchsyn('\<end\>',['rubyDefine'],'','n')<CR>
172*d09091d4SBram Moolenaar  xnoremap <silent> <buffer> [m :<C-U>call <SID>searchsyn('\<def\>',['rubyDefine'],'b','v')<CR>
173*d09091d4SBram Moolenaar  xnoremap <silent> <buffer> ]m :<C-U>call <SID>searchsyn('\<def\>',['rubyDefine'],'','v')<CR>
174*d09091d4SBram Moolenaar  xnoremap <silent> <buffer> [M :<C-U>call <SID>searchsyn('\<end\>',['rubyDefine'],'b','v')<CR>
175*d09091d4SBram Moolenaar  xnoremap <silent> <buffer> ]M :<C-U>call <SID>searchsyn('\<end\>',['rubyDefine'],'','v')<CR>
17679166c43SBram Moolenaar
177*d09091d4SBram Moolenaar  nnoremap <silent> <buffer> [[ :<C-U>call <SID>searchsyn('\<\%(class\<Bar>module\)\>',['rubyModule','rubyClass'],'b','n')<CR>
178*d09091d4SBram Moolenaar  nnoremap <silent> <buffer> ]] :<C-U>call <SID>searchsyn('\<\%(class\<Bar>module\)\>',['rubyModule','rubyClass'],'','n')<CR>
179*d09091d4SBram Moolenaar  nnoremap <silent> <buffer> [] :<C-U>call <SID>searchsyn('\<end\>',['rubyModule','rubyClass'],'b','n')<CR>
180*d09091d4SBram Moolenaar  nnoremap <silent> <buffer> ][ :<C-U>call <SID>searchsyn('\<end\>',['rubyModule','rubyClass'],'','n')<CR>
181*d09091d4SBram Moolenaar  xnoremap <silent> <buffer> [[ :<C-U>call <SID>searchsyn('\<\%(class\<Bar>module\)\>',['rubyModule','rubyClass'],'b','v')<CR>
182*d09091d4SBram Moolenaar  xnoremap <silent> <buffer> ]] :<C-U>call <SID>searchsyn('\<\%(class\<Bar>module\)\>',['rubyModule','rubyClass'],'','v')<CR>
183*d09091d4SBram Moolenaar  xnoremap <silent> <buffer> [] :<C-U>call <SID>searchsyn('\<end\>',['rubyModule','rubyClass'],'b','v')<CR>
184*d09091d4SBram Moolenaar  xnoremap <silent> <buffer> ][ :<C-U>call <SID>searchsyn('\<end\>',['rubyModule','rubyClass'],'','v')<CR>
18579166c43SBram Moolenaar
18679166c43SBram Moolenaar  let b:undo_ftplugin = b:undo_ftplugin
18779166c43SBram Moolenaar        \."| sil! exe 'unmap <buffer> [[' | sil! exe 'unmap <buffer> ]]' | sil! exe 'unmap <buffer> []' | sil! exe 'unmap <buffer> ]['"
18879166c43SBram Moolenaar        \."| sil! exe 'unmap <buffer> [m' | sil! exe 'unmap <buffer> ]m' | sil! exe 'unmap <buffer> [M' | sil! exe 'unmap <buffer> ]M'"
1891d68952aSBram Moolenaar
19089bcfda6SBram Moolenaar  if maparg('im','x') == '' && maparg('im','o') == '' && maparg('am','x') == '' && maparg('am','o') == ''
191ec7944aaSBram Moolenaar    onoremap <silent> <buffer> im :<C-U>call <SID>wrap_i('[m',']M')<CR>
192ec7944aaSBram Moolenaar    onoremap <silent> <buffer> am :<C-U>call <SID>wrap_a('[m',']M')<CR>
193ec7944aaSBram Moolenaar    xnoremap <silent> <buffer> im :<C-U>call <SID>wrap_i('[m',']M')<CR>
194ec7944aaSBram Moolenaar    xnoremap <silent> <buffer> am :<C-U>call <SID>wrap_a('[m',']M')<CR>
195ec7944aaSBram Moolenaar    let b:undo_ftplugin = b:undo_ftplugin
196ec7944aaSBram Moolenaar          \."| sil! exe 'ounmap <buffer> im' | sil! exe 'ounmap <buffer> am'"
197ec7944aaSBram Moolenaar          \."| sil! exe 'xunmap <buffer> im' | sil! exe 'xunmap <buffer> am'"
198ec7944aaSBram Moolenaar  endif
199ec7944aaSBram Moolenaar
20089bcfda6SBram Moolenaar  if maparg('iM','x') == '' && maparg('iM','o') == '' && maparg('aM','x') == '' && maparg('aM','o') == ''
201ec7944aaSBram Moolenaar    onoremap <silent> <buffer> iM :<C-U>call <SID>wrap_i('[[','][')<CR>
202ec7944aaSBram Moolenaar    onoremap <silent> <buffer> aM :<C-U>call <SID>wrap_a('[[','][')<CR>
203ec7944aaSBram Moolenaar    xnoremap <silent> <buffer> iM :<C-U>call <SID>wrap_i('[[','][')<CR>
204ec7944aaSBram Moolenaar    xnoremap <silent> <buffer> aM :<C-U>call <SID>wrap_a('[[','][')<CR>
205ec7944aaSBram Moolenaar    let b:undo_ftplugin = b:undo_ftplugin
206ec7944aaSBram Moolenaar          \."| sil! exe 'ounmap <buffer> iM' | sil! exe 'ounmap <buffer> aM'"
207ec7944aaSBram Moolenaar          \."| sil! exe 'xunmap <buffer> iM' | sil! exe 'xunmap <buffer> aM'"
208ec7944aaSBram Moolenaar  endif
209ec7944aaSBram Moolenaar
21089bcfda6SBram Moolenaar  call s:map('c', '', '<C-R><C-F> <Plug><cfile>')
211ec7944aaSBram Moolenaar
21289bcfda6SBram Moolenaar  cmap <buffer><script><expr> <SID>tagzv &foldopen =~# 'tag' ? '<Bar>norm! zv' : ''
213*d09091d4SBram Moolenaar  call s:map('n', '<silent>', '<C-]>       <SID>:exe  v:count1."tag <Plug><ctag>"<SID>tagzv<CR>')
214*d09091d4SBram Moolenaar  call s:map('n', '<silent>', 'g<C-]>      <SID>:exe         "tjump <Plug><ctag>"<SID>tagzv<CR>')
215*d09091d4SBram Moolenaar  call s:map('n', '<silent>', 'g]          <SID>:exe       "tselect <Plug><ctag>"<SID>tagzv<CR>')
216*d09091d4SBram Moolenaar  call s:map('n', '<silent>', '<C-W>]      <SID>:exe v:count1."stag <Plug><ctag>"<SID>tagzv<CR>')
217*d09091d4SBram Moolenaar  call s:map('n', '<silent>', '<C-W><C-]>  <SID>:exe v:count1."stag <Plug><ctag>"<SID>tagzv<CR>')
218*d09091d4SBram Moolenaar  call s:map('n', '<silent>', '<C-W>g<C-]> <SID>:exe        "stjump <Plug><ctag>"<SID>tagzv<CR>')
219*d09091d4SBram Moolenaar  call s:map('n', '<silent>', '<C-W>g]     <SID>:exe      "stselect <Plug><ctag>"<SID>tagzv<CR>')
220*d09091d4SBram Moolenaar  call s:map('n', '<silent>', '<C-W>}      <SID>:exe v:count1."ptag <Plug><ctag>"<CR>')
221*d09091d4SBram Moolenaar  call s:map('n', '<silent>', '<C-W>g}     <SID>:exe        "ptjump <Plug><ctag>"<CR>')
22289bcfda6SBram Moolenaar
22389bcfda6SBram Moolenaar  call s:map('n', '<silent>', 'gf           <SID>c:find <Plug><cfile><CR>')
22489bcfda6SBram Moolenaar  call s:map('n', '<silent>', '<C-W>f      <SID>c:sfind <Plug><cfile><CR>')
22589bcfda6SBram Moolenaar  call s:map('n', '<silent>', '<C-W><C-F>  <SID>c:sfind <Plug><cfile><CR>')
22689bcfda6SBram Moolenaar  call s:map('n', '<silent>', '<C-W>gf   <SID>c:tabfind <Plug><cfile><CR>')
22779166c43SBram Moolenaarendif
22860a795aaSBram Moolenaar
22960a795aaSBram Moolenaarlet &cpo = s:cpo_save
23060a795aaSBram Moolenaarunlet s:cpo_save
23160a795aaSBram Moolenaar
232756ec0f3SBram Moolenaarif exists("g:did_ruby_ftplugin_functions")
233756ec0f3SBram Moolenaar  finish
234756ec0f3SBram Moolenaarendif
235756ec0f3SBram Moolenaarlet g:did_ruby_ftplugin_functions = 1
236756ec0f3SBram Moolenaar
23789bcfda6SBram Moolenaarfunction! RubyBalloonexpr() abort
238756ec0f3SBram Moolenaar  if !exists('s:ri_found')
239756ec0f3SBram Moolenaar    let s:ri_found = executable('ri')
240756ec0f3SBram Moolenaar  endif
241756ec0f3SBram Moolenaar  if s:ri_found
242756ec0f3SBram Moolenaar    let line = getline(v:beval_lnum)
243756ec0f3SBram Moolenaar    let b = matchstr(strpart(line,0,v:beval_col),'\%(\w\|[:.]\)*$')
244756ec0f3SBram Moolenaar    let a = substitute(matchstr(strpart(line,v:beval_col),'^\w*\%([?!]\|\s*=\)\?'),'\s\+','','g')
245756ec0f3SBram Moolenaar    let str = b.a
246756ec0f3SBram Moolenaar    let before = strpart(line,0,v:beval_col-strlen(b))
247756ec0f3SBram Moolenaar    let after  = strpart(line,v:beval_col+strlen(a))
248756ec0f3SBram Moolenaar    if str =~ '^\.'
249756ec0f3SBram Moolenaar      let str = substitute(str,'^\.','#','g')
250756ec0f3SBram Moolenaar      if before =~ '\]\s*$'
251756ec0f3SBram Moolenaar        let str = 'Array'.str
252756ec0f3SBram Moolenaar      elseif before =~ '}\s*$'
253756ec0f3SBram Moolenaar        " False positives from blocks here
254756ec0f3SBram Moolenaar        let str = 'Hash'.str
255756ec0f3SBram Moolenaar      elseif before =~ "[\"'`]\\s*$" || before =~ '\$\d\+\s*$'
256756ec0f3SBram Moolenaar        let str = 'String'.str
257756ec0f3SBram Moolenaar      elseif before =~ '\$\d\+\.\d\+\s*$'
258756ec0f3SBram Moolenaar        let str = 'Float'.str
259756ec0f3SBram Moolenaar      elseif before =~ '\$\d\+\s*$'
260756ec0f3SBram Moolenaar        let str = 'Integer'.str
261756ec0f3SBram Moolenaar      elseif before =~ '/\s*$'
262756ec0f3SBram Moolenaar        let str = 'Regexp'.str
263756ec0f3SBram Moolenaar      else
264756ec0f3SBram Moolenaar        let str = substitute(str,'^#','.','')
265756ec0f3SBram Moolenaar      endif
266756ec0f3SBram Moolenaar    endif
267756ec0f3SBram Moolenaar    let str = substitute(str,'.*\.\s*to_f\s*\.\s*','Float#','')
268756ec0f3SBram Moolenaar    let str = substitute(str,'.*\.\s*to_i\%(nt\)\=\s*\.\s*','Integer#','')
269756ec0f3SBram Moolenaar    let str = substitute(str,'.*\.\s*to_s\%(tr\)\=\s*\.\s*','String#','')
270756ec0f3SBram Moolenaar    let str = substitute(str,'.*\.\s*to_sym\s*\.\s*','Symbol#','')
271756ec0f3SBram Moolenaar    let str = substitute(str,'.*\.\s*to_a\%(ry\)\=\s*\.\s*','Array#','')
272756ec0f3SBram Moolenaar    let str = substitute(str,'.*\.\s*to_proc\s*\.\s*','Proc#','')
273756ec0f3SBram Moolenaar    if str !~ '^\w'
274756ec0f3SBram Moolenaar      return ''
275756ec0f3SBram Moolenaar    endif
276ec7944aaSBram Moolenaar    silent! let res = substitute(system("ri -f rdoc -T \"".str.'"'),'\n$','','')
27779166c43SBram Moolenaar    if res =~ '^Nothing known about' || res =~ '^Bad argument:' || res =~ '^More than one method'
278756ec0f3SBram Moolenaar      return ''
279756ec0f3SBram Moolenaar    endif
280756ec0f3SBram Moolenaar    return res
281756ec0f3SBram Moolenaar  else
282756ec0f3SBram Moolenaar    return ""
283756ec0f3SBram Moolenaar  endif
284756ec0f3SBram Moolenaarendfunction
285756ec0f3SBram Moolenaar
28689bcfda6SBram Moolenaarfunction! s:searchsyn(pattern, syn, flags, mode) abort
28789bcfda6SBram Moolenaar  let cnt = v:count1
28879166c43SBram Moolenaar  norm! m'
2891d68952aSBram Moolenaar  if a:mode ==# 'v'
2901d68952aSBram Moolenaar    norm! gv
2911d68952aSBram Moolenaar  endif
29279166c43SBram Moolenaar  let i = 0
293*d09091d4SBram Moolenaar  call map(a:syn, 'hlID(v:val)')
29479166c43SBram Moolenaar  while i < cnt
29579166c43SBram Moolenaar    let i = i + 1
29679166c43SBram Moolenaar    let line = line('.')
29779166c43SBram Moolenaar    let col  = col('.')
29879166c43SBram Moolenaar    let pos = search(a:pattern,'W'.a:flags)
299*d09091d4SBram Moolenaar    while pos != 0 && index(a:syn, s:synid()) < 0
30079166c43SBram Moolenaar      let pos = search(a:pattern,'W'.a:flags)
30179166c43SBram Moolenaar    endwhile
30279166c43SBram Moolenaar    if pos == 0
30379166c43SBram Moolenaar      call cursor(line,col)
30479166c43SBram Moolenaar      return
30579166c43SBram Moolenaar    endif
30679166c43SBram Moolenaar  endwhile
30779166c43SBram Moolenaarendfunction
30879166c43SBram Moolenaar
309*d09091d4SBram Moolenaarfunction! s:synid() abort
310*d09091d4SBram Moolenaar  return synID(line('.'),col('.'),0)
31179166c43SBram Moolenaarendfunction
312756ec0f3SBram Moolenaar
31389bcfda6SBram Moolenaarfunction! s:wrap_i(back,forward) abort
314ec7944aaSBram Moolenaar  execute 'norm k'.a:forward
315ec7944aaSBram Moolenaar  let line = line('.')
316ec7944aaSBram Moolenaar  execute 'norm '.a:back
317ec7944aaSBram Moolenaar  if line('.') == line - 1
318ec7944aaSBram Moolenaar    return s:wrap_a(a:back,a:forward)
319ec7944aaSBram Moolenaar  endif
320ec7944aaSBram Moolenaar  execute 'norm jV'.a:forward.'k'
321ec7944aaSBram Moolenaarendfunction
322ec7944aaSBram Moolenaar
32389bcfda6SBram Moolenaarfunction! s:wrap_a(back,forward) abort
324ec7944aaSBram Moolenaar  execute 'norm '.a:forward
325ec7944aaSBram Moolenaar  if line('.') < line('$') && getline(line('.')+1) ==# ''
326ec7944aaSBram Moolenaar    let after = 1
327ec7944aaSBram Moolenaar  endif
328ec7944aaSBram Moolenaar  execute 'norm '.a:back
329ec7944aaSBram Moolenaar  while getline(line('.')-1) =~# '^\s*#' && line('.')
330ec7944aaSBram Moolenaar    -
331ec7944aaSBram Moolenaar  endwhile
332ec7944aaSBram Moolenaar  if exists('after')
333ec7944aaSBram Moolenaar    execute 'norm V'.a:forward.'j'
334ec7944aaSBram Moolenaar  elseif line('.') > 1 && getline(line('.')-1) =~# '^\s*$'
335ec7944aaSBram Moolenaar    execute 'norm kV'.a:forward
336ec7944aaSBram Moolenaar  else
337ec7944aaSBram Moolenaar    execute 'norm V'.a:forward
338ec7944aaSBram Moolenaar  endif
339ec7944aaSBram Moolenaarendfunction
340ec7944aaSBram Moolenaar
34189bcfda6SBram Moolenaarfunction! RubyCursorIdentifier() abort
3421d68952aSBram Moolenaar  let asciicode    = '\%(\w\|[]})\"'."'".']\)\@<!\%(?\%(\\M-\\C-\|\\C-\\M-\|\\M-\\c\|\\c\\M-\|\\c\|\\C-\|\\M-\)\=\%(\\\o\{1,3}\|\\x\x\{1,2}\|\\\=\S\)\)'
3431d68952aSBram Moolenaar  let number       = '\%(\%(\w\|[]})\"'."'".']\s*\)\@<!-\)\=\%(\<[[:digit:]_]\+\%(\.[[:digit:]_]\+\)\=\%([Ee][[:digit:]_]\+\)\=\>\|\<0[xXbBoOdD][[:xdigit:]_]\+\>\)\|'.asciicode
3441d68952aSBram Moolenaar  let operator     = '\%(\[\]\|<<\|<=>\|[!<>]=\=\|===\=\|[!=]\~\|>>\|\*\*\|\.\.\.\=\|=>\|[~^&|*/%+-]\)'
34589bcfda6SBram Moolenaar  let method       = '\%(\.[_a-zA-Z]\w*\s*=>\@!\|\<[_a-zA-Z]\w*\>[?!]\=\)'
3461d68952aSBram Moolenaar  let global       = '$\%([!$&"'."'".'*+,./:;<=>?@\`~]\|-\=\w\+\>\)'
3471d68952aSBram Moolenaar  let symbolizable = '\%(\%(@@\=\)\w\+\>\|'.global.'\|'.method.'\|'.operator.'\)'
3481d68952aSBram Moolenaar  let pattern      = '\C\s*\%('.number.'\|\%(:\@<!:\)\='.symbolizable.'\)'
3491d68952aSBram Moolenaar  let [lnum, col]  = searchpos(pattern,'bcn',line('.'))
3501d68952aSBram Moolenaar  let raw          = matchstr(getline('.')[col-1 : ],pattern)
35189bcfda6SBram Moolenaar  let stripped     = substitute(substitute(raw,'\s\+=$','=',''),'^\s*[:.]\=','','')
3521d68952aSBram Moolenaar  return stripped == '' ? expand("<cword>") : stripped
3531d68952aSBram Moolenaarendfunction
3541d68952aSBram Moolenaar
355*d09091d4SBram Moolenaarfunction! RubyCursorTag() abort
356*d09091d4SBram Moolenaar  return substitute(RubyCursorIdentifier(), '^[$@]*', '', '')
357*d09091d4SBram Moolenaarendfunction
358*d09091d4SBram Moolenaar
35989bcfda6SBram Moolenaarfunction! RubyCursorFile() abort
36089bcfda6SBram Moolenaar  let isfname = &isfname
36189bcfda6SBram Moolenaar  try
36289bcfda6SBram Moolenaar    set isfname+=:
36389bcfda6SBram Moolenaar    let cfile = expand('<cfile>')
36489bcfda6SBram Moolenaar  finally
36589bcfda6SBram Moolenaar    let isfname = &isfname
36689bcfda6SBram Moolenaar  endtry
36789bcfda6SBram Moolenaar  let pre = matchstr(strpart(getline('.'), 0, col('.')-1), '.*\f\@<!')
36889bcfda6SBram Moolenaar  let post = matchstr(strpart(getline('.'), col('.')), '\f\@!.*')
36989bcfda6SBram Moolenaar  let ext = getline('.') =~# '^\s*\%(require\%(_relative\)\=\|autoload\)\>' && cfile !~# '\.rb$' ? '.rb' : ''
370*d09091d4SBram Moolenaar  if s:synid() ==# hlID('rubyConstant')
37189bcfda6SBram Moolenaar    let cfile = substitute(cfile,'\.\w\+[?!=]\=$','','')
372*d09091d4SBram Moolenaar    let cfile = substitute(cfile,'^::','','')
37389bcfda6SBram Moolenaar    let cfile = substitute(cfile,'::','/','g')
37489bcfda6SBram Moolenaar    let cfile = substitute(cfile,'\(\u\+\)\(\u\l\)','\1_\2', 'g')
37589bcfda6SBram Moolenaar    let cfile = substitute(cfile,'\(\l\|\d\)\(\u\)','\1_\2', 'g')
37689bcfda6SBram Moolenaar    return tolower(cfile) . '.rb'
37789bcfda6SBram Moolenaar  elseif getline('.') =~# '^\s*require_relative\s*\(["'']\).*\1\s*$'
37889bcfda6SBram Moolenaar    let cfile = expand('%:p:h') . '/' . matchstr(getline('.'),'\(["'']\)\zs.\{-\}\ze\1') . ext
37989bcfda6SBram Moolenaar  elseif getline('.') =~# '^\s*\%(require[( ]\|load[( ]\|autoload[( ]:\w\+,\)\s*\%(::\)\=File\.expand_path(\(["'']\)\.\./.*\1,\s*__FILE__)\s*$'
38089bcfda6SBram Moolenaar    let target = matchstr(getline('.'),'\(["'']\)\.\.\zs/.\{-\}\ze\1')
38189bcfda6SBram Moolenaar    let cfile = expand('%:p:h') . target . ext
382ec7944aaSBram Moolenaar  elseif getline('.') =~# '^\s*\%(require \|load \|autoload :\w\+,\)\s*\(["'']\).*\1\s*$'
38389bcfda6SBram Moolenaar    let cfile = matchstr(getline('.'),'\(["'']\)\zs.\{-\}\ze\1') . ext
38489bcfda6SBram Moolenaar  elseif pre.post =~# '\<File.expand_path[( ].*[''"]\{2\}, *__FILE__\>' && cfile =~# '^\.\.'
38589bcfda6SBram Moolenaar    let cfile = expand('%:p:h') . strpart(cfile, 2)
386ec7944aaSBram Moolenaar  else
38789bcfda6SBram Moolenaar    return substitute(cfile, '\C\v^(.*):(\d+)%(:in)=$', '+\2 \1', '')
388ec7944aaSBram Moolenaar  endif
38989bcfda6SBram Moolenaar  let cwdpat = '^\M' . substitute(getcwd(), '[\/]', '\\[\\/]', 'g').'\ze\[\/]'
39089bcfda6SBram Moolenaar  let cfile = substitute(cfile, cwdpat, '.', '')
39189bcfda6SBram Moolenaar  if fnameescape(cfile) !=# cfile
39289bcfda6SBram Moolenaar    return '+ '.fnameescape(cfile)
393ec7944aaSBram Moolenaar  else
39489bcfda6SBram Moolenaar    return cfile
395ec7944aaSBram Moolenaar  endif
396ec7944aaSBram Moolenaarendfunction
397ec7944aaSBram Moolenaar
39860a795aaSBram Moolenaar"
39960a795aaSBram Moolenaar" Instructions for enabling "matchit" support:
40060a795aaSBram Moolenaar"
40160a795aaSBram Moolenaar" 1. Look for the latest "matchit" plugin at
40260a795aaSBram Moolenaar"
40360a795aaSBram Moolenaar"         http://www.vim.org/scripts/script.php?script_id=39
40460a795aaSBram Moolenaar"
40560a795aaSBram Moolenaar"    It is also packaged with Vim, in the $VIMRUNTIME/macros directory.
40660a795aaSBram Moolenaar"
40760a795aaSBram Moolenaar" 2. Copy "matchit.txt" into a "doc" directory (e.g. $HOME/.vim/doc).
40860a795aaSBram Moolenaar"
40960a795aaSBram Moolenaar" 3. Copy "matchit.vim" into a "plugin" directory (e.g. $HOME/.vim/plugin).
41060a795aaSBram Moolenaar"
41160a795aaSBram Moolenaar" 4. Ensure this file (ftplugin/ruby.vim) is installed.
41260a795aaSBram Moolenaar"
41360a795aaSBram Moolenaar" 5. Ensure you have this line in your $HOME/.vimrc:
41460a795aaSBram Moolenaar"         filetype plugin on
41560a795aaSBram Moolenaar"
41660a795aaSBram Moolenaar" 6. Restart Vim and create the matchit documentation:
41760a795aaSBram Moolenaar"
41860a795aaSBram Moolenaar"         :helptags ~/.vim/doc
41960a795aaSBram Moolenaar"
42060a795aaSBram Moolenaar"    Now you can do ":help matchit", and you should be able to use "%" on Ruby
42160a795aaSBram Moolenaar"    keywords.  Try ":echo b:match_words" to be sure.
42260a795aaSBram Moolenaar"
42360a795aaSBram Moolenaar" Thanks to Mark J. Reed for the instructions.  See ":help vimrc" for the
42460a795aaSBram Moolenaar" locations of plugin directories, etc., as there are several options, and it
42560a795aaSBram Moolenaar" differs on Windows.  Email [email protected] if you need help.
42660a795aaSBram Moolenaar"
42760a795aaSBram Moolenaar
428446cb837SBram Moolenaar" vim: nowrap sw=2 sts=2 ts=8:
429