diff options
author | Justin M. Keyes <justinkz@gmail.com> | 2016-07-10 14:16:12 -0400 |
---|---|---|
committer | Justin M. Keyes <justinkz@gmail.com> | 2016-07-10 14:16:12 -0400 |
commit | c7d84c5550a1ffa27c1b1c199fabbdb9247e5117 (patch) | |
tree | 2f99bfeb2482c63d01b9380982129dd0aca7468c | |
parent | 5573e1a350dd2df65e21ed48c14cf89f5e9c0e7a (diff) | |
parent | d3981fee217c2ac56b7659179df06ddced2377ca (diff) | |
download | rneovim-c7d84c5550a1ffa27c1b1c199fabbdb9247e5117.tar.gz rneovim-c7d84c5550a1ffa27c1b1c199fabbdb9247e5117.tar.bz2 rneovim-c7d84c5550a1ffa27c1b1c199fabbdb9247e5117.zip |
Merge #4980 'Support legacy `:ruby` commands'.
-rwxr-xr-x | .ci/install.sh | 3 | ||||
-rw-r--r-- | runtime/autoload/health.vim | 35 | ||||
-rw-r--r-- | runtime/autoload/provider/ruby.vim | 50 | ||||
-rw-r--r-- | runtime/autoload/provider/script_host.rb | 8 | ||||
-rw-r--r-- | runtime/doc/if_ruby.txt | 185 | ||||
-rw-r--r-- | runtime/doc/provider.txt | 19 | ||||
-rw-r--r-- | runtime/doc/vim_diff.txt | 3 | ||||
-rw-r--r-- | src/nvim/eval.c | 8 | ||||
-rw-r--r-- | src/nvim/ex_cmds.lua | 6 | ||||
-rw-r--r-- | src/nvim/ex_cmds2.c | 15 | ||||
-rw-r--r-- | test/functional/provider/ruby_spec.lua | 96 |
11 files changed, 412 insertions, 16 deletions
diff --git a/.ci/install.sh b/.ci/install.sh index cb2362a70e..93c9a930ac 100755 --- a/.ci/install.sh +++ b/.ci/install.sh @@ -29,3 +29,6 @@ if [[ "${TRAVIS_OS_NAME}" == osx ]]; then else CC=cc pip3.3 -q install --user --upgrade neovim fi + +echo "Install neovim RubyGem." +gem install --no-document --version ">= 0.2.0" neovim diff --git a/runtime/autoload/health.vim b/runtime/autoload/health.vim index dc362577a6..0a698e6492 100644 --- a/runtime/autoload/health.vim +++ b/runtime/autoload/health.vim @@ -404,6 +404,39 @@ function! s:diagnose_python(version) abort endfunction +function! s:diagnose_ruby() abort + echo 'Checking: Ruby' + let ruby_vers = systemlist('ruby -v')[0] + let ruby_prog = provider#ruby#Detect() + let notes = [] + + if empty(ruby_prog) + let ruby_prog = 'not found' + let prog_vers = 'not found' + call add(notes, 'Suggestion: Install the neovim RubyGem using ' . + \ '`gem install neovim`.') + else + silent let prog_vers = systemlist(ruby_prog . ' --version')[0] + + if v:shell_error + let prog_vers = 'outdated' + call add(notes, 'Suggestion: Install the latest neovim RubyGem using ' . + \ '`gem install neovim`.') + elseif s:version_cmp(prog_vers, "0.2.0") == -1 + let prog_vers .= ' (outdated)' + call add(notes, 'Suggestion: Install the latest neovim RubyGem using ' . + \ '`gem install neovim`.') + endif + endif + + echo ' Ruby Version: ' . ruby_vers + echo ' Host Executable: ' . ruby_prog + echo ' Host Version: ' . prog_vers + + call s:echo_notes(notes) +endfunction + + function! health#check(bang) abort redir => report try @@ -411,6 +444,8 @@ function! health#check(bang) abort silent echo '' silent call s:diagnose_python(3) silent echo '' + silent call s:diagnose_ruby() + silent echo '' silent call s:diagnose_manifest() silent echo '' finally diff --git a/runtime/autoload/provider/ruby.vim b/runtime/autoload/provider/ruby.vim index aad8c09d28..e9130b98c1 100644 --- a/runtime/autoload/provider/ruby.vim +++ b/runtime/autoload/provider/ruby.vim @@ -1,12 +1,18 @@ " The Ruby provider helper -if exists('s:loaded_ruby_provider') +if exists('g:loaded_ruby_provider') finish endif +let g:loaded_ruby_provider = 1 -let s:loaded_ruby_provider = 1 +function! provider#ruby#Detect() abort + return exepath('neovim-ruby-host') +endfunction + +function! provider#ruby#Prog() + return s:prog +endfunction function! provider#ruby#Require(host) abort - " Collect registered Ruby plugins into args let args = [] let ruby_plugins = remote#host#PluginsForHost(a:host.name) @@ -16,19 +22,43 @@ function! provider#ruby#Require(host) abort try let channel_id = rpcstart(provider#ruby#Prog(), args) - - if rpcrequest(channel_id, 'poll') == 'ok' + if rpcrequest(channel_id, 'poll') ==# 'ok' return channel_id endif catch echomsg v:throwpoint echomsg v:exception endtry - - throw remote#host#LoadErrorForHost(a:host.orig_name, - \ '$NVIM_RUBY_LOG_FILE') + throw remote#host#LoadErrorForHost(a:host.orig_name, '$NVIM_RUBY_LOG_FILE') endfunction -function! provider#ruby#Prog() abort - return 'neovim-ruby-host' +function! provider#ruby#Call(method, args) + if s:err != '' + echoerr s:err + return + endif + + if !exists('s:host') + try + let s:host = remote#host#Require('legacy-ruby-provider') + catch + let s:err = v:exception + echohl WarningMsg + echomsg v:exception + echohl None + return + endtry + endif + return call('rpcrequest', insert(insert(a:args, 'ruby_'.a:method), s:host)) endfunction + +let s:err = '' +let s:prog = provider#ruby#Detect() +let s:plugin_path = expand('<sfile>:p:h') . '/script_host.rb' + +if empty(s:prog) + let s:err = 'Cannot find the neovim RubyGem. Try :CheckHealth' +endif + +call remote#host#RegisterClone('legacy-ruby-provider', 'ruby') +call remote#host#RegisterPlugin('legacy-ruby-provider', s:plugin_path, []) diff --git a/runtime/autoload/provider/script_host.rb b/runtime/autoload/provider/script_host.rb new file mode 100644 index 0000000000..1dade766c7 --- /dev/null +++ b/runtime/autoload/provider/script_host.rb @@ -0,0 +1,8 @@ +begin + require "neovim/ruby_provider" +rescue LoadError + warn( + "Your neovim RubyGem is missing or out of date. " + + "Install the latest version using `gem install neovim`." + ) +end diff --git a/runtime/doc/if_ruby.txt b/runtime/doc/if_ruby.txt new file mode 100644 index 0000000000..fdd63501ea --- /dev/null +++ b/runtime/doc/if_ruby.txt @@ -0,0 +1,185 @@ +*if_ruby.txt* + + + VIM REFERENCE MANUAL by Shugo Maeda + +The Ruby Interface to Vim *ruby* *Ruby* + + +1. Commands |ruby-commands| +2. The VIM module |ruby-vim| +3. VIM::Buffer objects |ruby-buffer| +4. VIM::Window objects |ruby-window| +5. Global variables |ruby-globals| + + *E266* *E267* *E268* *E269* *E270* *E271* *E272* *E273* + +The home page for ruby is http://www.ruby-lang.org/. You can find links for +downloading Ruby there. + +============================================================================== +1. Commands *ruby-commands* + + *:ruby* *:rub* +:rub[y] {cmd} Execute Ruby command {cmd}. A command to try it out: > + :ruby print "Hello" + +:rub[y] << {endpattern} +{script} +{endpattern} + Execute Ruby script {script}. + {endpattern} must NOT be preceded by any white space. + If {endpattern} is omitted, it defaults to a dot '.' + like for the |:append| and |:insert| commands. This + form of the |:ruby| command is mainly useful for + including ruby code in vim scripts. + Note: This command doesn't work when the Ruby feature + wasn't compiled in. To avoid errors, see + |script-here|. + +Example Vim script: > + + function! RedGem() + ruby << EOF + class Garnet + def initialize(s) + @buffer = VIM::Buffer.current + vimputs(s) + end + def vimputs(s) + @buffer.append(@buffer.count,s) + end + end + gem = Garnet.new("pretty") + EOF + endfunction +< + + *:rubydo* *:rubyd* *E265* +:[range]rubyd[o] {cmd} Evaluate Ruby command {cmd} for each line in the + [range], with $_ being set to the text of each line in + turn, without a trailing <EOL>. Setting $_ will change + the text, but note that it is not possible to add or + delete lines using this command. + The default for [range] is the whole file: "1,$". + + *:rubyfile* *:rubyf* +:rubyf[ile] {file} Execute the Ruby script in {file}. This is the same as + ":ruby load 'file'", but allows file name completion. + +Executing Ruby commands is not possible in the |sandbox|. + +============================================================================== +2. The VIM module *ruby-vim* + +Ruby code gets all of its access to vim via the "VIM" module. + +Overview > + print "Hello" # displays a message + VIM.command(cmd) # execute an Ex command + num = VIM::Window.count # gets the number of windows + w = VIM::Window[n] # gets window "n" + cw = VIM::Window.current # gets the current window + num = VIM::Buffer.count # gets the number of buffers + b = VIM::Buffer[n] # gets buffer "n" + cb = VIM::Buffer.current # gets the current buffer + w.height = lines # sets the window height + w.cursor = [row, col] # sets the window cursor position + pos = w.cursor # gets an array [row, col] + name = b.name # gets the buffer file name + line = b[n] # gets a line from the buffer + num = b.count # gets the number of lines + b[n] = str # sets a line in the buffer + b.delete(n) # deletes a line + b.append(n, str) # appends a line after n + line = VIM::Buffer.current.line # gets the current line + num = VIM::Buffer.current.line_number # gets the current line number + VIM::Buffer.current.line = "test" # sets the current line number +< + +Module Functions: + + *ruby-message* +VIM::message({msg}) + Displays the message {msg}. + + *ruby-set_option* +VIM::set_option({arg}) + Sets a vim option. {arg} can be any argument that the ":set" command + accepts. Note that this means that no spaces are allowed in the + argument! See |:set|. + + *ruby-command* +VIM::command({cmd}) + Executes Ex command {cmd}. + + *ruby-evaluate* +VIM::evaluate({expr}) + Evaluates {expr} using the vim internal expression evaluator (see + |expression|). Returns the expression result as a string. + A |List| is turned into a string by joining the items and inserting + line breaks. + +============================================================================== +3. VIM::Buffer objects *ruby-buffer* + +VIM::Buffer objects represent vim buffers. + +Class Methods: + +current Returns the current buffer object. +count Returns the number of buffers. +self[{n}] Returns the buffer object for the number {n}. The first number + is 0. + +Methods: + +name Returns the name of the buffer. +number Returns the number of the buffer. +count Returns the number of lines. +length Returns the number of lines. +self[{n}] Returns a line from the buffer. {n} is the line number. +self[{n}] = {str} + Sets a line in the buffer. {n} is the line number. +delete({n}) Deletes a line from the buffer. {n} is the line number. +append({n}, {str}) + Appends a line after the line {n}. +line Returns the current line of the buffer if the buffer is + active. +line = {str} Sets the current line of the buffer if the buffer is active. +line_number Returns the number of the current line if the buffer is + active. + +============================================================================== +4. VIM::Window objects *ruby-window* + +VIM::Window objects represent vim windows. + +Class Methods: + +current Returns the current window object. +count Returns the number of windows. +self[{n}] Returns the window object for the number {n}. The first number + is 0. + +Methods: + +buffer Returns the buffer displayed in the window. +height Returns the height of the window. +height = {n} Sets the window height to {n}. +width Returns the width of the window. +width = {n} Sets the window width to {n}. +cursor Returns a [row, col] array for the cursor position. +cursor = [{row}, {col}] + Sets the cursor position to {row} and {col}. + +============================================================================== +5. Global variables *ruby-globals* + +There are two global variables. + +$curwin The current window object. +$curbuf The current buffer object. + +============================================================================== + vim:tw=78:ts=8:ft=help:norl: diff --git a/runtime/doc/provider.txt b/runtime/doc/provider.txt index db5c61879c..7380fb9346 100644 --- a/runtime/doc/provider.txt +++ b/runtime/doc/provider.txt @@ -88,6 +88,25 @@ the |:CheckHealth| command to diagnose your setup. save to a file or copy to the clipboard. ============================================================================== +Ruby integration *provider-ruby* + +Nvim supports the Vim legacy |ruby-vim| interface via external Ruby +interpreters connected via |RPC|. + + +RUBY QUICKSTART ~ + +To use Vim Ruby plugins with Nvim, just install the latest `neovim` RubyGem: > + $ gem install neovim + + +RUBY PROVIDER CONFIGURATION ~ + *g:loaded_ruby_provider* +To disable Ruby support: > + let g:loaded_ruby_provider = 1 + + +============================================================================== Clipboard integration *provider-clipboard* *clipboard* Nvim has no direct connection to the system clipboard. Instead it is diff --git a/runtime/doc/vim_diff.txt b/runtime/doc/vim_diff.txt index e536ea873a..a5b1cbf9b1 100644 --- a/runtime/doc/vim_diff.txt +++ b/runtime/doc/vim_diff.txt @@ -202,13 +202,12 @@ Additional differences: ============================================================================== 5. Missing legacy features *nvim-features-missing* - *if_ruby* *if_lua* *if_perl* *if_mzscheme* *if_tcl* + *if_lua* *if_perl* *if_mzscheme* *if_tcl* These legacy Vim features may be implemented in the future, but they are not planned for the current milestone. - vim.bindeval() (new feature in Vim 7.4 Python interface) -- |if_ruby| - |if_lua| - |if_perl| - |if_mzscheme| diff --git a/src/nvim/eval.c b/src/nvim/eval.c index 55fa974797..47d44b148a 100644 --- a/src/nvim/eval.c +++ b/src/nvim/eval.c @@ -22344,7 +22344,10 @@ bool eval_has_provider(char *name) } \ } - static int has_clipboard = -1, has_python = -1, has_python3 = -1; + static int has_clipboard = -1; + static int has_python = -1; + static int has_python3 = -1; + static int has_ruby = -1; if (!strcmp(name, "clipboard")) { check_provider(clipboard); @@ -22355,6 +22358,9 @@ bool eval_has_provider(char *name) } else if (!strcmp(name, "python")) { check_provider(python); return has_python; + } else if (!strcmp(name, "ruby")) { + check_provider(ruby); + return has_ruby; } return false; diff --git a/src/nvim/ex_cmds.lua b/src/nvim/ex_cmds.lua index 76191d5a56..3f5d9b3244 100644 --- a/src/nvim/ex_cmds.lua +++ b/src/nvim/ex_cmds.lua @@ -2170,19 +2170,19 @@ return { command='ruby', flags=bit.bor(RANGE, EXTRA, NEEDARG, CMDWIN), addr_type=ADDR_LINES, - func='ex_script_ni', + func='ex_ruby', }, { command='rubydo', flags=bit.bor(RANGE, DFLALL, EXTRA, NEEDARG, CMDWIN), addr_type=ADDR_LINES, - func='ex_ni', + func='ex_rubydo', }, { command='rubyfile', flags=bit.bor(RANGE, FILE1, NEEDARG, CMDWIN), addr_type=ADDR_LINES, - func='ex_ni', + func='ex_rubyfile', }, { command='rviminfo', diff --git a/src/nvim/ex_cmds2.c b/src/nvim/ex_cmds2.c index b56b1cf013..6d24ba91f2 100644 --- a/src/nvim/ex_cmds2.c +++ b/src/nvim/ex_cmds2.c @@ -897,6 +897,21 @@ void ex_pydo(exarg_T *eap) script_host_do_range("python", eap); } +void ex_ruby(exarg_T *eap) +{ + script_host_execute("ruby", eap); +} + +void ex_rubyfile(exarg_T *eap) +{ + script_host_execute_file("ruby", eap); +} + +void ex_rubydo(exarg_T *eap) +{ + script_host_do_range("ruby", eap); +} + void ex_python3(exarg_T *eap) { script_host_execute("python3", eap); diff --git a/test/functional/provider/ruby_spec.lua b/test/functional/provider/ruby_spec.lua new file mode 100644 index 0000000000..7b0e17688d --- /dev/null +++ b/test/functional/provider/ruby_spec.lua @@ -0,0 +1,96 @@ +local helpers = require('test.functional.helpers')(after_each) + +local eq = helpers.eq +local feed = helpers.feed +local clear = helpers.clear +local funcs = helpers.funcs +local meths = helpers.meths +local insert = helpers.insert +local expect = helpers.expect +local command = helpers.command +local write_file = helpers.write_file +local curbufmeths = helpers.curbufmeths + +do + clear() + command('let g:prog = provider#ruby#Detect()') + local prog = meths.get_var('prog') + + if prog == '' then + pending( + "Cannot find the neovim RubyGem. Try :CheckHealth", + function() end) + return + end +end + +before_each(function() + clear() +end) + +describe('ruby feature test', function() + it('works', function() + eq(1, funcs.has('ruby')) + end) +end) + +describe(':ruby command', function() + it('evaluates ruby', function() + command('ruby VIM.command("let g:set_by_ruby = [100, 0]")') + eq({100, 0}, meths.get_var('set_by_ruby')) + end) + + it('supports nesting', function() + command([[ruby VIM.command('ruby VIM.command("let set_by_nested_ruby = 555")')]]) + eq(555, meths.get_var('set_by_nested_ruby')) + end) +end) + +describe(':rubyfile command', function() + it('evaluates a ruby file', function() + local fname = 'rubyfile.rb' + write_file(fname, 'VIM.command("let set_by_rubyfile = 123")') + command('rubyfile rubyfile.rb') + eq(123, meths.get_var('set_by_rubyfile')) + os.remove(fname) + end) +end) + +describe(':rubydo command', function() + it('exposes the $_ variable for modifying lines', function() + insert('abc\ndef\nghi\njkl') + expect([[ + abc + def + ghi + jkl]]) + + feed('ggjvj:rubydo $_.upcase!<CR>') + expect([[ + abc + DEF + GHI + jkl]]) + end) + + it('operates on all lines when not given a range', function() + insert('abc\ndef\nghi\njkl') + expect([[ + abc + def + ghi + jkl]]) + + feed(':rubydo $_.upcase!<CR>') + expect([[ + ABC + DEF + GHI + JKL]]) + end) + + it('does not modify the buffer if no changes are made', function() + command('normal :rubydo 42') + eq(false, curbufmeths.get_option('modified')) + end) +end) |