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
CC=cc pip3.3 -q install --user --upgrade neovim
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
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

View File

@ -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, [])

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

View File

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

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")) {
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;

View File

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

View File

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

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)