xref: /vim-8.2.3635/runtime/ftplugin/ruby.vim (revision 4d8f4761)
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*4d8f4761SBram Moolenaar" Last Change:		2020 Feb 13
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 =
272ed639abSBram 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	\ ':' .
312ed639abSBram Moolenaar        \ '}\|\%(^\|[^.\:@$=]\)\@<=\<end\:\@!\>' .
322ed639abSBram Moolenaar        \ ',^=begin\>:^=end\>,' .
332ed639abSBram Moolenaar	\ ',\[:\],(:)'
3460a795aaSBram Moolenaar
3560a795aaSBram Moolenaar  let b:match_skip =
3660a795aaSBram Moolenaar	\ "synIDattr(synID(line('.'),col('.'),0),'name') =~ '" .
372ed639abSBram Moolenaar	\ "\\<ruby\\%(String\\|.\+Delimiter\\|Character\\|.\+Escape\\|" .
382ed639abSBram Moolenaar        \ "Regexp\\|Interpolation\\|Comment\\|Documentation\\|" .
392ed639abSBram Moolenaar	\ "ConditionalModifier\\|RepeatModifier\\|RescueModifier\\|OptionalDo\\|" .
402ed639abSBram Moolenaar	\ "MethodName\\|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{,}"
65d09091d4SBram 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'), ',')
902ed639abSBram 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{,}) )
115*4d8f4761SBram Moolenaar    elseif executable('ruby') && !empty($HOME)
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
137d09091d4SBram 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"
140d09091d4SBram Moolenaar
141d09091d4SBram Moolenaarif get(g:, 'ruby_recommended_style', 1)
142d09091d4SBram Moolenaar  setlocal shiftwidth=2 softtabstop=2 expandtab
143d09091d4SBram Moolenaar  let b:undo_ftplugin .= ' | setl sw< sts< et<'
144d09091d4SBram Moolenaarendif
145d09091d4SBram Moolenaar
146d09091d4SBram Moolenaar" To activate, :set ballooneval
147d09091d4SBram Moolenaarif exists('+balloonexpr') && get(g:, 'ruby_balloonexpr')
148d09091d4SBram Moolenaar  setlocal balloonexpr=RubyBalloonexpr()
149d09091d4SBram Moolenaar  let b:undo_ftplugin .= "| setl bexpr="
150d09091d4SBram 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))
1552ed639abSBram Moolenaar    exe a:mode.'map' '<buffer>' a:flags a:map
15689bcfda6SBram Moolenaar    let b:undo_ftplugin .= '|sil! '.a:mode.'unmap <buffer> '.from
15789bcfda6SBram Moolenaar  endif
15889bcfda6SBram Moolenaarendfunction
15989bcfda6SBram Moolenaar
160d09091d4SBram Moolenaarcmap <buffer><script><expr> <Plug><ctag> substitute(RubyCursorTag(),'^$',"\022\027",'')
16189bcfda6SBram Moolenaarcmap <buffer><script><expr> <Plug><cfile> substitute(RubyCursorFile(),'^$',"\022\006",'')
162d09091d4SBram 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
168d09091d4SBram Moolenaar  nnoremap <silent> <buffer> [m :<C-U>call <SID>searchsyn('\<def\>',['rubyDefine'],'b','n')<CR>
169d09091d4SBram Moolenaar  nnoremap <silent> <buffer> ]m :<C-U>call <SID>searchsyn('\<def\>',['rubyDefine'],'','n')<CR>
170d09091d4SBram Moolenaar  nnoremap <silent> <buffer> [M :<C-U>call <SID>searchsyn('\<end\>',['rubyDefine'],'b','n')<CR>
171d09091d4SBram Moolenaar  nnoremap <silent> <buffer> ]M :<C-U>call <SID>searchsyn('\<end\>',['rubyDefine'],'','n')<CR>
172d09091d4SBram Moolenaar  xnoremap <silent> <buffer> [m :<C-U>call <SID>searchsyn('\<def\>',['rubyDefine'],'b','v')<CR>
173d09091d4SBram Moolenaar  xnoremap <silent> <buffer> ]m :<C-U>call <SID>searchsyn('\<def\>',['rubyDefine'],'','v')<CR>
174d09091d4SBram Moolenaar  xnoremap <silent> <buffer> [M :<C-U>call <SID>searchsyn('\<end\>',['rubyDefine'],'b','v')<CR>
175d09091d4SBram Moolenaar  xnoremap <silent> <buffer> ]M :<C-U>call <SID>searchsyn('\<end\>',['rubyDefine'],'','v')<CR>
17679166c43SBram Moolenaar
177d09091d4SBram Moolenaar  nnoremap <silent> <buffer> [[ :<C-U>call <SID>searchsyn('\<\%(class\<Bar>module\)\>',['rubyModule','rubyClass'],'b','n')<CR>
178d09091d4SBram Moolenaar  nnoremap <silent> <buffer> ]] :<C-U>call <SID>searchsyn('\<\%(class\<Bar>module\)\>',['rubyModule','rubyClass'],'','n')<CR>
179d09091d4SBram Moolenaar  nnoremap <silent> <buffer> [] :<C-U>call <SID>searchsyn('\<end\>',['rubyModule','rubyClass'],'b','n')<CR>
180d09091d4SBram Moolenaar  nnoremap <silent> <buffer> ][ :<C-U>call <SID>searchsyn('\<end\>',['rubyModule','rubyClass'],'','n')<CR>
181d09091d4SBram Moolenaar  xnoremap <silent> <buffer> [[ :<C-U>call <SID>searchsyn('\<\%(class\<Bar>module\)\>',['rubyModule','rubyClass'],'b','v')<CR>
182d09091d4SBram Moolenaar  xnoremap <silent> <buffer> ]] :<C-U>call <SID>searchsyn('\<\%(class\<Bar>module\)\>',['rubyModule','rubyClass'],'','v')<CR>
183d09091d4SBram Moolenaar  xnoremap <silent> <buffer> [] :<C-U>call <SID>searchsyn('\<end\>',['rubyModule','rubyClass'],'b','v')<CR>
184d09091d4SBram 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' : ''
213d09091d4SBram Moolenaar  call s:map('n', '<silent>', '<C-]>       <SID>:exe  v:count1."tag <Plug><ctag>"<SID>tagzv<CR>')
214d09091d4SBram Moolenaar  call s:map('n', '<silent>', 'g<C-]>      <SID>:exe         "tjump <Plug><ctag>"<SID>tagzv<CR>')
215d09091d4SBram Moolenaar  call s:map('n', '<silent>', 'g]          <SID>:exe       "tselect <Plug><ctag>"<SID>tagzv<CR>')
216d09091d4SBram Moolenaar  call s:map('n', '<silent>', '<C-W>]      <SID>:exe v:count1."stag <Plug><ctag>"<SID>tagzv<CR>')
217d09091d4SBram Moolenaar  call s:map('n', '<silent>', '<C-W><C-]>  <SID>:exe v:count1."stag <Plug><ctag>"<SID>tagzv<CR>')
218d09091d4SBram Moolenaar  call s:map('n', '<silent>', '<C-W>g<C-]> <SID>:exe        "stjump <Plug><ctag>"<SID>tagzv<CR>')
219d09091d4SBram Moolenaar  call s:map('n', '<silent>', '<C-W>g]     <SID>:exe      "stselect <Plug><ctag>"<SID>tagzv<CR>')
220d09091d4SBram Moolenaar  call s:map('n', '<silent>', '<C-W>}      <SID>:exe v:count1."ptag <Plug><ctag>"<CR>')
221d09091d4SBram 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
293d09091d4SBram 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)
299d09091d4SBram 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
309d09091d4SBram Moolenaarfunction! s:synid() abort
310d09091d4SBram Moolenaar  return synID(line('.'),col('.'),0)
31179166c43SBram Moolenaarendfunction
312756ec0f3SBram Moolenaar
31389bcfda6SBram Moolenaarfunction! s:wrap_i(back,forward) abort
3142ed639abSBram Moolenaar  execute 'norm! k'
3152ed639abSBram Moolenaar  execute 'norm '.a:forward
316ec7944aaSBram Moolenaar  let line = line('.')
317ec7944aaSBram Moolenaar  execute 'norm '.a:back
318ec7944aaSBram Moolenaar  if line('.') == line - 1
319ec7944aaSBram Moolenaar    return s:wrap_a(a:back,a:forward)
320ec7944aaSBram Moolenaar  endif
3212ed639abSBram Moolenaar  execute 'norm! jV'
3222ed639abSBram Moolenaar  execute 'norm '.a:forward
3232ed639abSBram Moolenaar  execute 'norm! k'
324ec7944aaSBram Moolenaarendfunction
325ec7944aaSBram Moolenaar
32689bcfda6SBram Moolenaarfunction! s:wrap_a(back,forward) abort
327ec7944aaSBram Moolenaar  execute 'norm '.a:forward
328ec7944aaSBram Moolenaar  if line('.') < line('$') && getline(line('.')+1) ==# ''
329ec7944aaSBram Moolenaar    let after = 1
330ec7944aaSBram Moolenaar  endif
331ec7944aaSBram Moolenaar  execute 'norm '.a:back
332ec7944aaSBram Moolenaar  while getline(line('.')-1) =~# '^\s*#' && line('.')
333ec7944aaSBram Moolenaar    -
334ec7944aaSBram Moolenaar  endwhile
335ec7944aaSBram Moolenaar  if exists('after')
3362ed639abSBram Moolenaar    execute 'norm! V'
3372ed639abSBram Moolenaar    execute 'norm '.a:forward
3382ed639abSBram Moolenaar    execute 'norm! j'
339ec7944aaSBram Moolenaar  elseif line('.') > 1 && getline(line('.')-1) =~# '^\s*$'
3402ed639abSBram Moolenaar    execute 'norm! kV'
3412ed639abSBram Moolenaar    execute 'norm '.a:forward
342ec7944aaSBram Moolenaar  else
3432ed639abSBram Moolenaar    execute 'norm! V'
3442ed639abSBram Moolenaar    execute 'norm '.a:forward
345ec7944aaSBram Moolenaar  endif
346ec7944aaSBram Moolenaarendfunction
347ec7944aaSBram Moolenaar
34889bcfda6SBram Moolenaarfunction! RubyCursorIdentifier() abort
3491d68952aSBram Moolenaar  let asciicode    = '\%(\w\|[]})\"'."'".']\)\@<!\%(?\%(\\M-\\C-\|\\C-\\M-\|\\M-\\c\|\\c\\M-\|\\c\|\\C-\|\\M-\)\=\%(\\\o\{1,3}\|\\x\x\{1,2}\|\\\=\S\)\)'
3501d68952aSBram Moolenaar  let number       = '\%(\%(\w\|[]})\"'."'".']\s*\)\@<!-\)\=\%(\<[[:digit:]_]\+\%(\.[[:digit:]_]\+\)\=\%([Ee][[:digit:]_]\+\)\=\>\|\<0[xXbBoOdD][[:xdigit:]_]\+\>\)\|'.asciicode
3511d68952aSBram Moolenaar  let operator     = '\%(\[\]\|<<\|<=>\|[!<>]=\=\|===\=\|[!=]\~\|>>\|\*\*\|\.\.\.\=\|=>\|[~^&|*/%+-]\)'
35289bcfda6SBram Moolenaar  let method       = '\%(\.[_a-zA-Z]\w*\s*=>\@!\|\<[_a-zA-Z]\w*\>[?!]\=\)'
3531d68952aSBram Moolenaar  let global       = '$\%([!$&"'."'".'*+,./:;<=>?@\`~]\|-\=\w\+\>\)'
3541d68952aSBram Moolenaar  let symbolizable = '\%(\%(@@\=\)\w\+\>\|'.global.'\|'.method.'\|'.operator.'\)'
3551d68952aSBram Moolenaar  let pattern      = '\C\s*\%('.number.'\|\%(:\@<!:\)\='.symbolizable.'\)'
3561d68952aSBram Moolenaar  let [lnum, col]  = searchpos(pattern,'bcn',line('.'))
3571d68952aSBram Moolenaar  let raw          = matchstr(getline('.')[col-1 : ],pattern)
35889bcfda6SBram Moolenaar  let stripped     = substitute(substitute(raw,'\s\+=$','=',''),'^\s*[:.]\=','','')
3591d68952aSBram Moolenaar  return stripped == '' ? expand("<cword>") : stripped
3601d68952aSBram Moolenaarendfunction
3611d68952aSBram Moolenaar
362d09091d4SBram Moolenaarfunction! RubyCursorTag() abort
363d09091d4SBram Moolenaar  return substitute(RubyCursorIdentifier(), '^[$@]*', '', '')
364d09091d4SBram Moolenaarendfunction
365d09091d4SBram Moolenaar
36689bcfda6SBram Moolenaarfunction! RubyCursorFile() abort
36789bcfda6SBram Moolenaar  let isfname = &isfname
36889bcfda6SBram Moolenaar  try
36989bcfda6SBram Moolenaar    set isfname+=:
37089bcfda6SBram Moolenaar    let cfile = expand('<cfile>')
37189bcfda6SBram Moolenaar  finally
37289bcfda6SBram Moolenaar    let isfname = &isfname
37389bcfda6SBram Moolenaar  endtry
37489bcfda6SBram Moolenaar  let pre = matchstr(strpart(getline('.'), 0, col('.')-1), '.*\f\@<!')
37589bcfda6SBram Moolenaar  let post = matchstr(strpart(getline('.'), col('.')), '\f\@!.*')
376d09091d4SBram Moolenaar  if s:synid() ==# hlID('rubyConstant')
37789bcfda6SBram Moolenaar    let cfile = substitute(cfile,'\.\w\+[?!=]\=$','','')
378d09091d4SBram Moolenaar    let cfile = substitute(cfile,'^::','','')
37989bcfda6SBram Moolenaar    let cfile = substitute(cfile,'::','/','g')
38089bcfda6SBram Moolenaar    let cfile = substitute(cfile,'\(\u\+\)\(\u\l\)','\1_\2', 'g')
38189bcfda6SBram Moolenaar    let cfile = substitute(cfile,'\(\l\|\d\)\(\u\)','\1_\2', 'g')
38289bcfda6SBram Moolenaar    return tolower(cfile) . '.rb'
38389bcfda6SBram Moolenaar  elseif getline('.') =~# '^\s*require_relative\s*\(["'']\).*\1\s*$'
3842ed639abSBram Moolenaar    let cfile = expand('%:p:h') . '/' . matchstr(getline('.'),'\(["'']\)\zs.\{-\}\ze\1')
3852ed639abSBram Moolenaar    let cfile .= cfile !~# '\.rb$' ? '.rb' : ''
38689bcfda6SBram Moolenaar  elseif getline('.') =~# '^\s*\%(require[( ]\|load[( ]\|autoload[( ]:\w\+,\)\s*\%(::\)\=File\.expand_path(\(["'']\)\.\./.*\1,\s*__FILE__)\s*$'
38789bcfda6SBram Moolenaar    let target = matchstr(getline('.'),'\(["'']\)\.\.\zs/.\{-\}\ze\1')
3882ed639abSBram Moolenaar    let cfile = expand('%:p:h') . target
3892ed639abSBram Moolenaar    let cfile .= cfile !~# '\.rb$' ? '.rb' : ''
390ec7944aaSBram Moolenaar  elseif getline('.') =~# '^\s*\%(require \|load \|autoload :\w\+,\)\s*\(["'']\).*\1\s*$'
3912ed639abSBram Moolenaar    let cfile = matchstr(getline('.'),'\(["'']\)\zs.\{-\}\ze\1')
3922ed639abSBram Moolenaar    let cfile .= cfile !~# '\.rb$' ? '.rb' : ''
39389bcfda6SBram Moolenaar  elseif pre.post =~# '\<File.expand_path[( ].*[''"]\{2\}, *__FILE__\>' && cfile =~# '^\.\.'
39489bcfda6SBram Moolenaar    let cfile = expand('%:p:h') . strpart(cfile, 2)
395ec7944aaSBram Moolenaar  else
39689bcfda6SBram Moolenaar    return substitute(cfile, '\C\v^(.*):(\d+)%(:in)=$', '+\2 \1', '')
397ec7944aaSBram Moolenaar  endif
39889bcfda6SBram Moolenaar  let cwdpat = '^\M' . substitute(getcwd(), '[\/]', '\\[\\/]', 'g').'\ze\[\/]'
39989bcfda6SBram Moolenaar  let cfile = substitute(cfile, cwdpat, '.', '')
40089bcfda6SBram Moolenaar  if fnameescape(cfile) !=# cfile
40189bcfda6SBram Moolenaar    return '+ '.fnameescape(cfile)
402ec7944aaSBram Moolenaar  else
40389bcfda6SBram Moolenaar    return cfile
404ec7944aaSBram Moolenaar  endif
405ec7944aaSBram Moolenaarendfunction
406ec7944aaSBram Moolenaar
40760a795aaSBram Moolenaar"
40860a795aaSBram Moolenaar" Instructions for enabling "matchit" support:
40960a795aaSBram Moolenaar"
41060a795aaSBram Moolenaar" 1. Look for the latest "matchit" plugin at
41160a795aaSBram Moolenaar"
41260a795aaSBram Moolenaar"         http://www.vim.org/scripts/script.php?script_id=39
41360a795aaSBram Moolenaar"
41460a795aaSBram Moolenaar"    It is also packaged with Vim, in the $VIMRUNTIME/macros directory.
41560a795aaSBram Moolenaar"
41660a795aaSBram Moolenaar" 2. Copy "matchit.txt" into a "doc" directory (e.g. $HOME/.vim/doc).
41760a795aaSBram Moolenaar"
41860a795aaSBram Moolenaar" 3. Copy "matchit.vim" into a "plugin" directory (e.g. $HOME/.vim/plugin).
41960a795aaSBram Moolenaar"
42060a795aaSBram Moolenaar" 4. Ensure this file (ftplugin/ruby.vim) is installed.
42160a795aaSBram Moolenaar"
42260a795aaSBram Moolenaar" 5. Ensure you have this line in your $HOME/.vimrc:
42360a795aaSBram Moolenaar"         filetype plugin on
42460a795aaSBram Moolenaar"
42560a795aaSBram Moolenaar" 6. Restart Vim and create the matchit documentation:
42660a795aaSBram Moolenaar"
42760a795aaSBram Moolenaar"         :helptags ~/.vim/doc
42860a795aaSBram Moolenaar"
42960a795aaSBram Moolenaar"    Now you can do ":help matchit", and you should be able to use "%" on Ruby
43060a795aaSBram Moolenaar"    keywords.  Try ":echo b:match_words" to be sure.
43160a795aaSBram Moolenaar"
43260a795aaSBram Moolenaar" Thanks to Mark J. Reed for the instructions.  See ":help vimrc" for the
43360a795aaSBram Moolenaar" locations of plugin directories, etc., as there are several options, and it
43460a795aaSBram Moolenaar" differs on Windows.  Email [email protected] if you need help.
43560a795aaSBram Moolenaar"
43660a795aaSBram Moolenaar
437446cb837SBram Moolenaar" vim: nowrap sw=2 sts=2 ts=8:
438