Module: VimClient
- Defined in:
- lib/vim_client.rb,
lib/vim_client/version.rb,
ext/vim_client/vim_client.c
Overview
This module provides methods for communicating with Vim, using it's +clientserver feature.
It provides a persistent connection to the X11 server for communicating with a Vim server, much like another running instance of Vim.
VimClient.send_keys is like using remote_send(), and VimClient.send_expr is like remote_expr().
This lets you avoid having to shell-out to Vim for each command you need to
send (using --remote-send
and --remote-expr
).
VimClient.send_keys2 would be like using remote_send() ending with a call to server2client() on the remote, then following that call with remote_read().
This allows you to send keys
, then evaluate an expression on the server
after those keys are processed and receive the result of that expression.
This may also be used to simply block until the sent keys have been processed.
Usage
Install the gem using:
gem install vim_client-ruby
Or, add it to your project's Gemfile.
gem 'vim_client-ruby'
Require VimClient:
require 'vim_client'
Then, be sure to set the name of your Vim server:
VimClient.server_name = 'vim_server1'
VimClient.timeout_sec = 30 # and optionally change the default timeout
If #server_name is not set, an Error will be raised.
Both #server_name and #timeout_sec may be updated at any time.
Character Encodings
Vim's default encoding is latin1 (ISO-8859-1)
. If compiled with the
+multi_byte feature, Vim supports many other encodings.
All returned strings from VimClient.send_expr and VimClient.send_keys2 will be set
to the encoding that is set on the Vim server. If the server is using
latin1
, then strings returned will be marked as ISO-8859-1
. If the
server is using utf-8
, then strings returned will be marked as UTF-8
.
No transcoding is performed on the strings returned from the server.
The strings are simply marked using the encoding reported by the server.
Vim handles all Unicode strings as UTF-8. This means if the server's encoding
is set to any Unicode encoding, the returned string will be in UTF-8. Vim
also expects that any command string being sent (as keys
or an expr
) will
be in UTF-8. Therefore, any string you send which is in a Vim supported
Unicode encoding will be transcoded to UTF-8 before being sent to the remote
server.
For other Vim supported encodings, Vim will be told which of it's supported encodings the sent string is using. If the string you send is using a different encoding than the 'encoding' set on the server, Vim will convert it and the response returned will be in the remote server's encoding.
For a list of Vim's supported encodings and their corresponding Ruby encoding names, see the source in ext/vim_client/misc.c. You can also view the specs to get a better idea of how this works.
Basically, as long as the keys
or expr
strings you're sending are in
an encoding supported by Vim, then you'll have no problems. Just remember
that the returned string will be in the server's encoding, and that this
will always be UTF-8 for Unicode strings.
Signals and Errors
If SIGINT is received while VimClient is waiting for a response from the server,
the wait loop will be aborted, the SIGINT handler that was present when we
entered the loop will be restored, and SIGINT will be re-raised to the calling
process group. If this signal is ignored, the process will continue and the calling
method (send_expr/send_keys2)
will return nil
.
If timeout_sec
expires while waiting for a response, TimeoutError will be raised,
which you may rescue.
In either case, be aware that any response received from the remote server for this request will be lost. Also, there is no way of knowing what state the server is in; especially in the case of a timeout. It could have reported an error and be waiting for an acknowledgement. In which case, the next sent command may simply hang as well. In such case, it may be best to simply stop your server and restart it before sending any further commands.
Defined Under Namespace
Classes: Error, Exception, ExprError, NoMemoryError, TimeoutError, XIOError
Constant Summary collapse
- VERSION =
'0.1.1'
Instance Attribute Summary collapse
-
#server_name ⇒ String
Sets the name of the remote Vim server to send messages to.
-
#timeout_sec ⇒ Integer
Sets the timeout in seconds to wait for a response.
Class Method Summary collapse
Instance Method Summary collapse
-
#send_expr(expr) ⇒ String, Nil
Evaluate an expression on the remote Vim server.
-
#send_keys(keys) ⇒ Nil
Send Keys to the remote Vim server.
-
#send_keys2(keys, expr = '""') ⇒ String, Nil
Send Keys to the remote server and wait for a reply.
Instance Attribute Details
#server_name ⇒ String
Sets the name of the remote Vim server to send messages to.
This may be changed at any time, as this value is read before each call to send_keys, send_keys2 and send_expr.
If no server name is specified, an Error will be raised.
|
# File 'lib/vim_client.rb', line 119
|
#timeout_sec ⇒ Integer
Sets the timeout in seconds to wait for a response.
This may be changed at any time, as this value is read before each call to send_keys2 and send_expr.
Defaults to 60 seconds if not specified.
|
# File 'lib/vim_client.rb', line 129
|
Class Method Details
.send_expr(expr) ⇒ Object
974 975 976 977 |
# File 'ext/vim_client/vim_client.c', line 974
static VALUE
send_expr(VALUE self, VALUE expr) {
return send2vim(expr, asExpr);
}
|
.send_keys(keys) ⇒ Object
969 970 971 972 |
# File 'ext/vim_client/vim_client.c', line 969
static VALUE
send_keys(VALUE self, VALUE keys) {
return send2vim(keys, asKeys);
}
|
.send_keys2(*args) ⇒ Object
979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 |
# File 'ext/vim_client/vim_client.c', line 979
static VALUE
send_keys2(int argc, VALUE *argv, VALUE self) {
VALUE keys, expr;
rb_scan_args(argc, argv, "11", &keys, &expr);
/* Create a callback string using the same encoding as keys.
* Note that concatination must be used, as opposed to printf (%)
* since we could be dealing with 16/32 bit encodings at this point.
*/
VALUE callback, close;
rb_encoding *enc = rb_enc_get(keys);
callback = rb_str_export_to_enc(rb_str_new2(
":call server2client(expand(\"<client>\"), "), enc);
close = rb_str_export_to_enc(rb_str_new2(")<cr>"), enc);
if (NIL_P(expr)) /* Return an empty string from the callback */
expr = rb_str_export_to_enc(rb_str_new2("\"\""), enc);
else if (enc != rb_enc_get(expr))
rb_raise(e_Error, "'keys' and 'expr' must use the same encoding");
/* Insert expr into the callback */
rb_str_append(callback, expr);
rb_str_append(callback, close);
/* Append the callback to the keys.
* rb_str_plus is used so we don't modify the user's 'keys' string */
keys = rb_str_plus(keys, callback);
return send2vim(keys, asKeys2);
}
|
Instance Method Details
#send_expr(expr) ⇒ String, Nil
Evaluate an expression on the remote Vim server.
This method is analogous to Vim's remote_expr() function.
If the expression results in a List (Array), Vim will return the items
separated by newlines using: join(list, "\n")
For example, to evaluate a simple expression:
ret = VimClient.send_expr('2+2')
# ret == '4'
To retrieve all lines in the current buffer:
ret = VimClient.send_expr('getline(1,"$")')
# ret == "line one\nline two\nline three"
The basic equivalent non-VimClient call for this method would be:
%x{ gvim --servername server_name --remote-expr 'getline(1,"$")' }
|
# File 'lib/vim_client.rb', line 262
|
#send_keys(keys) ⇒ Nil
Send Keys to the remote Vim server.
This method is analogous to Vim's remote_send() function.
The keys
string is sent to the remote server as input keys
and the method returns immediately. If you need this call to block
until the commands are processed, use send_keys2.
Note that if the commands sent result in an error on the server, it will not be reported and may cause subsequent commands to fail.
Use <cr>
to insert a carriage return. If omitted, the next call
to send_keys
will be appended. Each new line in keys
should
begin with a colon ( : )
. Commands may also be separated using
a pipe ( | )
.
For example, the following two commands are equivalent:
VimClient.send_keys(":e ++ff=dos #{ some_file } | setlocal ff=unix | w | bd<cr>")
VimClient.send_keys(":e ++ff=dos #{ some_file }<cr>:setlocal ff=unix<cr>:w | bd<cr>")
These two commands would be equivalent as well:
VimClient.send_keys(":e ++ff=dos #{ some_file } | setlocal ff=unix") # no `<cr>`
VimClient.send_keys(" | w | bd<cr>") # appends to the previously sent keys
The basic equivalent non-VimClient call for this method would be:
system('gvim', '--servername', 'server_name', '--remote-send',
":e ++ff=dos #{ some_file } | setlocal ff=unix | w | bd<cr>")
|
# File 'lib/vim_client.rb', line 139
|
#send_keys2(keys, expr = '""') ⇒ String, Nil
Send Keys to the remote server and wait for a reply.
This method is similar to send_keys, except that it adds a callback
to the end of the keys sent, then returns the result of expr
.
The keys
parameter follows the same rules as send_keys.
The expr
parameter follows the same rules as send_expr, except
that this expression must return a String; whereas send_expr will
automatically convert a List (Array) into a String.
For example, the following would be equivalent:
VimClient.send_expr('setline(1,["line one", "line two"])')
VimClient.send_expr('getline(1,"$")') # => "line one\nline two"
VimClient.send_keys2(
':call setline(1,["line one", "line two"])<cr>',
'join(getline(1,"$"), "\\n")'
) # => "line one\nline two"
If no expr
is given, then the expr
will simply return an empty string.
Note: While setline()
can be used with send_keys and send_keys2
(i.e. --remote-send
) to set the buffer text, any keycodes within
these command strings (including within string-literals) will be interpreted.
To understand this better, what this method actually does is append
a call to Vim's server2client() function.
It then waits for the reply, like calling remote_read().
# When you send the following:
VimClient.send_keys2(":sleep 1<cr>")
# What actually gets sent is:
# :sleep 1<cr>server2client(expand("<client>"), "")<cr>
# When sending:
VimClient.send_keys2(":sleep 1<cr>", "localtime()")
# This is sent:
# :sleep 1<cr>server2client(expand("<client>"), localtime())<cr>
The strings given for keys
and expr
must be in the same encoding
or an Error will be raised.
A call to send_keys2 may be preceded by other calls to send_keys, as keys sent asynchronously and added to the server's typeahead buffer.
As with send_keys, any error reported by the server will not be
reported. This includes any error evaluating the expr
given to
server2client(). However, since this call is waiting for a reply,
a TimeoutError would be raised.
The basic equivalent non-VimClient call for this method would be:
response = %x{
gvim -fes -u NONE +'call remote_send("server_name", \
'\\'':sleep 1 | call server2client(expand("<client>"), localtime())<cr>'\\'', "sid")' \
+'redir >> /dev/stdout | echo remote_read(sid) | redir END | q'
}
|
# File 'lib/vim_client.rb', line 183
|