Merge #4980 'Support legacy :ruby commands'.

This commit is contained in:
Justin M. Keyes 2016-07-10 14:16:12 -04:00
commit c7d84c5550
11 changed files with 412 additions and 16 deletions

View File

@ -29,3 +29,6 @@ if [[ "${TRAVIS_OS_NAME}" == osx ]]; then
else else
CC=cc pip3.3 -q install --user --upgrade neovim CC=cc pip3.3 -q install --user --upgrade neovim
fi fi
echo "Install neovim RubyGem."
gem install --no-document --version ">= 0.2.0" neovim

View File

@ -404,6 +404,39 @@ function! s:diagnose_python(version) abort
endfunction 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 function! health#check(bang) abort
redir => report redir => report
try try
@ -411,6 +444,8 @@ function! health#check(bang) abort
silent echo '' silent echo ''
silent call s:diagnose_python(3) silent call s:diagnose_python(3)
silent echo '' silent echo ''
silent call s:diagnose_ruby()
silent echo ''
silent call s:diagnose_manifest() silent call s:diagnose_manifest()
silent echo '' silent echo ''
finally finally

View File

@ -1,12 +1,18 @@
" The Ruby provider helper " The Ruby provider helper
if exists('s:loaded_ruby_provider') if exists('g:loaded_ruby_provider')
finish finish
endif 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 function! provider#ruby#Require(host) abort
" Collect registered Ruby plugins into args
let args = [] let args = []
let ruby_plugins = remote#host#PluginsForHost(a:host.name) let ruby_plugins = remote#host#PluginsForHost(a:host.name)
@ -16,19 +22,43 @@ function! provider#ruby#Require(host) abort
try try
let channel_id = rpcstart(provider#ruby#Prog(), args) let channel_id = rpcstart(provider#ruby#Prog(), args)
if rpcrequest(channel_id, 'poll') ==# 'ok'
if rpcrequest(channel_id, 'poll') == 'ok'
return channel_id return channel_id
endif endif
catch catch
echomsg v:throwpoint echomsg v:throwpoint
echomsg v:exception echomsg v:exception
endtry 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 endfunction
function! provider#ruby#Prog() abort function! provider#ruby#Call(method, args)
return 'neovim-ruby-host' 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 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, [])

View File

@ -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

185
runtime/doc/if_ruby.txt Normal file
View File

@ -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:

View File

@ -87,6 +87,25 @@ the |:CheckHealth| command to diagnose your setup.
will be placed in a new buffer which can make it easier to will be placed in a new buffer which can make it easier to
save to a file or copy to the clipboard. 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* Clipboard integration *provider-clipboard* *clipboard*

View File

@ -202,13 +202,12 @@ Additional differences:
============================================================================== ==============================================================================
5. Missing legacy features *nvim-features-missing* 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 These legacy Vim features may be implemented in the future, but they are not
planned for the current milestone. planned for the current milestone.
- vim.bindeval() (new feature in Vim 7.4 Python interface) - vim.bindeval() (new feature in Vim 7.4 Python interface)
- |if_ruby|
- |if_lua| - |if_lua|
- |if_perl| - |if_perl|
- |if_mzscheme| - |if_mzscheme|

View File

@ -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")) { if (!strcmp(name, "clipboard")) {
check_provider(clipboard); check_provider(clipboard);
@ -22355,6 +22358,9 @@ bool eval_has_provider(char *name)
} else if (!strcmp(name, "python")) { } else if (!strcmp(name, "python")) {
check_provider(python); check_provider(python);
return has_python; return has_python;
} else if (!strcmp(name, "ruby")) {
check_provider(ruby);
return has_ruby;
} }
return false; return false;

View File

@ -2170,19 +2170,19 @@ return {
command='ruby', command='ruby',
flags=bit.bor(RANGE, EXTRA, NEEDARG, CMDWIN), flags=bit.bor(RANGE, EXTRA, NEEDARG, CMDWIN),
addr_type=ADDR_LINES, addr_type=ADDR_LINES,
func='ex_script_ni', func='ex_ruby',
}, },
{ {
command='rubydo', command='rubydo',
flags=bit.bor(RANGE, DFLALL, EXTRA, NEEDARG, CMDWIN), flags=bit.bor(RANGE, DFLALL, EXTRA, NEEDARG, CMDWIN),
addr_type=ADDR_LINES, addr_type=ADDR_LINES,
func='ex_ni', func='ex_rubydo',
}, },
{ {
command='rubyfile', command='rubyfile',
flags=bit.bor(RANGE, FILE1, NEEDARG, CMDWIN), flags=bit.bor(RANGE, FILE1, NEEDARG, CMDWIN),
addr_type=ADDR_LINES, addr_type=ADDR_LINES,
func='ex_ni', func='ex_rubyfile',
}, },
{ {
command='rviminfo', command='rviminfo',

View File

@ -897,6 +897,21 @@ void ex_pydo(exarg_T *eap)
script_host_do_range("python", 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) void ex_python3(exarg_T *eap)
{ {
script_host_execute("python3", eap); script_host_execute("python3", eap);

View File

@ -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)