To: vim_dev@googlegroups.com Subject: Patch 8.1.1056 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ------------ Patch 8.1.1056 Problem: No eval function for Ruby. Solution: Add rubyeval(). (Ozaki Kiichi, closes #4152) Files: runtime/doc/eval.txt, runtime/doc/if_ruby.txt, src/evalfunc.c, src/if_ruby.c, src/proto/if_ruby.pro, src/testdir/test_ruby.vim *** ../vim-8.1.1055/runtime/doc/eval.txt 2019-03-23 14:23:02.134361686 +0100 --- runtime/doc/eval.txt 2019-03-26 22:40:42.456751899 +0100 *************** *** 2486,2499 **** remote_send({server}, {string} [, {idvar}]) String send key sequence remote_startserver({name}) none become server {name} ! String send key sequence ! remove({list}, {idx} [, {end}]) any remove items {idx}-{end} from {list} remove({dict}, {key}) any remove entry {key} from {dict} rename({from}, {to}) Number rename (move) file from {from} to {to} repeat({expr}, {count}) String repeat {expr} {count} times resolve({filename}) String get filename a shortcut points to reverse({list}) List reverse {list} in-place round({expr}) Float round off {expr} screenattr({row}, {col}) Number attribute at screen position screenchar({row}, {col}) Number character at screen position screencol() Number current cursor column --- 2511,2527 ---- remote_send({server}, {string} [, {idvar}]) String send key sequence remote_startserver({name}) none become server {name} ! remove({list}, {idx} [, {end}]) any/List ! remove items {idx}-{end} from {list} ! remove({blob}, {idx} [, {end}]) Number/Blob ! remove bytes {idx}-{end} from {blob} remove({dict}, {key}) any remove entry {key} from {dict} rename({from}, {to}) Number rename (move) file from {from} to {to} repeat({expr}, {count}) String repeat {expr} {count} times resolve({filename}) String get filename a shortcut points to reverse({list}) List reverse {list} in-place round({expr}) Float round off {expr} + rubyeval({expr}) any evaluate |Ruby| expression screenattr({row}, {col}) Number attribute at screen position screenchar({row}, {col}) Number character at screen position screencol() Number current cursor column *************** *** 7379,7384 **** --- 7433,7449 ---- < -5.0 {only available when compiled with the |+float| feature} + rubyeval({expr}) *rubyeval()* + Evaluate Ruby expression {expr} and return its result + converted to Vim data structures. + Numbers, floats and strings are returned as they are (strings + are copied though). + Arrays are represented as Vim |List| type. + Hashes are represented as Vim |Dictionary| type. + Other objects are represented as strings resulted from their + "Object#to_s" method. + {only available when compiled with the |+ruby| feature} + screenattr({row}, {col}) *screenattr()* Like |screenchar()|, but return the attribute. This is a rather arbitrary number that can only be used to compare to the *** ../vim-8.1.1055/runtime/doc/if_ruby.txt 2019-01-12 22:47:01.256088105 +0100 --- runtime/doc/if_ruby.txt 2019-03-26 22:40:42.456751899 +0100 *************** *** 11,17 **** 3. Vim::Buffer objects |ruby-buffer| 4. Vim::Window objects |ruby-window| 5. Global variables |ruby-globals| ! 6. Dynamic loading |ruby-dynamic| {Vi does not have any of these commands} *E266* *E267* *E268* *E269* *E270* *E271* *E272* *E273* --- 11,18 ---- 3. Vim::Buffer objects |ruby-buffer| 4. Vim::Window objects |ruby-window| 5. Global variables |ruby-globals| ! 6. rubyeval() Vim function |ruby-rubyeval| ! 7. Dynamic loading |ruby-dynamic| {Vi does not have any of these commands} *E266* *E267* *E268* *E269* *E270* *E271* *E272* *E273* *************** *** 112,118 **** *ruby-blob* Vim::blob({arg}) ! Return Blob literal string from {arg}. *ruby-set_option* Vim::set_option({arg}) --- 113,119 ---- *ruby-blob* Vim::blob({arg}) ! Return |Blob| literal string from {arg}. *ruby-set_option* Vim::set_option({arg}) *************** *** 198,204 **** $curbuf The current buffer object. ============================================================================== ! 6. Dynamic loading *ruby-dynamic* On MS-Windows and Unix the Ruby library can be loaded dynamically. The |:version| output then includes |+ruby/dyn|. --- 199,214 ---- $curbuf The current buffer object. ============================================================================== ! 6. rubyeval() Vim function *ruby-rubyeval* ! ! To facilitate bi-directional interface, you can use |rubyeval()| function to ! evaluate Ruby expressions and pass their values to Vim script. ! ! The Ruby value "true", "false" and "nil" are converted to v:true, v:false and ! v:null, respectively. ! ! ============================================================================== ! 7. Dynamic loading *ruby-dynamic* On MS-Windows and Unix the Ruby library can be loaded dynamically. The |:version| output then includes |+ruby/dyn|. *** ../vim-8.1.1055/src/evalfunc.c 2019-03-23 14:23:02.138361658 +0100 --- src/evalfunc.c 2019-03-26 22:40:42.456751899 +0100 *************** *** 338,343 **** --- 338,346 ---- #ifdef FEAT_FLOAT static void f_round(typval_T *argvars, typval_T *rettv); #endif + #ifdef FEAT_RUBY + static void f_rubyeval(typval_T *argvars, typval_T *rettv); + #endif static void f_screenattr(typval_T *argvars, typval_T *rettv); static void f_screenchar(typval_T *argvars, typval_T *rettv); static void f_screencol(typval_T *argvars, typval_T *rettv); *************** *** 829,834 **** --- 832,840 ---- #ifdef FEAT_FLOAT {"round", 1, 1, f_round}, #endif + #ifdef FEAT_RUBY + {"rubyeval", 1, 1, f_rubyeval}, + #endif {"screenattr", 2, 2, f_screenattr}, {"screenchar", 2, 2, f_screenchar}, {"screencol", 0, 0, f_screencol}, *************** *** 10351,10356 **** --- 10357,10377 ---- } #endif + #ifdef FEAT_RUBY + /* + * "rubyeval()" function + */ + static void + f_rubyeval(typval_T *argvars, typval_T *rettv) + { + char_u *str; + char_u buf[NUMBUFLEN]; + + str = tv_get_string_buf(&argvars[0], buf); + do_rubyeval(str, rettv); + } + #endif + /* * "screenattr()" function */ *** ../vim-8.1.1055/src/if_ruby.c 2019-02-23 14:22:59.567653374 +0100 --- src/if_ruby.c 2019-03-26 22:40:42.456751899 +0100 *************** *** 205,210 **** --- 205,211 ---- static void error_print(int); static void ruby_io_init(void); static void ruby_vim_init(void); + static int ruby_convert_to_vim_value(VALUE val, typval_T *rettv); #if defined(RUBY19_OR_LATER) || defined(RUBY_INIT_STACK) # if defined(__ia64) && !defined(ruby_init_stack) *************** *** 259,264 **** --- 260,266 ---- # endif # define rb_global_variable dll_rb_global_variable # define rb_hash_aset dll_rb_hash_aset + # define rb_hash_foreach dll_rb_hash_foreach # define rb_hash_new dll_rb_hash_new # define rb_inspect dll_rb_inspect # define rb_int2inum dll_rb_int2inum *************** *** 275,280 **** --- 277,283 ---- # endif # define rb_num2uint dll_rb_num2uint # endif + # define rb_num2dbl dll_rb_num2dbl # define rb_lastline_get dll_rb_lastline_get # define rb_lastline_set dll_rb_lastline_set # define rb_protect dll_rb_protect *************** *** 409,414 **** --- 412,418 ---- # endif static void (*dll_rb_global_variable) (VALUE*); static VALUE (*dll_rb_hash_aset) (VALUE, VALUE, VALUE); + static VALUE (*dll_rb_hash_foreach) (VALUE, int (*)(VALUE, VALUE, VALUE), VALUE); static VALUE (*dll_rb_hash_new) (void); static VALUE (*dll_rb_inspect) (VALUE); static VALUE (*dll_rb_int2inum) (long); *************** *** 418,423 **** --- 422,428 ---- static long (*dll_rb_num2int) (VALUE); static unsigned long (*dll_rb_num2uint) (VALUE); # endif + static double (*dll_rb_num2dbl) (VALUE); static VALUE (*dll_rb_lastline_get) (void); static void (*dll_rb_lastline_set) (VALUE); static VALUE (*dll_rb_protect) (VALUE (*)(VALUE), VALUE, int*); *************** *** 501,542 **** # if defined(RUBY19_OR_LATER) && !defined(PROTO) # if defined(DYNAMIC_RUBY_VER) && DYNAMIC_RUBY_VER >= 22 ! long rb_num2long_stub(VALUE x) # else ! SIGNED_VALUE rb_num2long_stub(VALUE x) # endif { return dll_rb_num2long(x); } # if defined(DYNAMIC_RUBY_VER) && DYNAMIC_RUBY_VER >= 26 ! VALUE rb_int2big_stub(intptr_t x) # else ! VALUE rb_int2big_stub(SIGNED_VALUE x) # endif { return dll_rb_int2big(x); } # if defined(DYNAMIC_RUBY_VER) && DYNAMIC_RUBY_VER >= 19 \ && VIM_SIZEOF_INT < VIM_SIZEOF_LONG ! long rb_fix2int_stub(VALUE x) { return dll_rb_fix2int(x); } ! long rb_num2int_stub(VALUE x) { return dll_rb_num2int(x); } # endif # if defined(DYNAMIC_RUBY_VER) && DYNAMIC_RUBY_VER >= 20 ! VALUE rb_float_new_in_heap(double d) { return dll_rb_float_new(d); } # if defined(DYNAMIC_RUBY_VER) && DYNAMIC_RUBY_VER >= 22 ! unsigned long rb_num2ulong(VALUE x) # else ! VALUE rb_num2ulong(VALUE x) # endif { return (long)RSHIFT((SIGNED_VALUE)(x),1); --- 506,555 ---- # if defined(RUBY19_OR_LATER) && !defined(PROTO) # if defined(DYNAMIC_RUBY_VER) && DYNAMIC_RUBY_VER >= 22 ! long ! rb_num2long_stub(VALUE x) # else ! SIGNED_VALUE ! rb_num2long_stub(VALUE x) # endif { return dll_rb_num2long(x); } # if defined(DYNAMIC_RUBY_VER) && DYNAMIC_RUBY_VER >= 26 ! VALUE ! rb_int2big_stub(intptr_t x) # else ! VALUE ! rb_int2big_stub(SIGNED_VALUE x) # endif { return dll_rb_int2big(x); } # if defined(DYNAMIC_RUBY_VER) && DYNAMIC_RUBY_VER >= 19 \ && VIM_SIZEOF_INT < VIM_SIZEOF_LONG ! long ! rb_fix2int_stub(VALUE x) { return dll_rb_fix2int(x); } ! long ! rb_num2int_stub(VALUE x) { return dll_rb_num2int(x); } # endif # if defined(DYNAMIC_RUBY_VER) && DYNAMIC_RUBY_VER >= 20 ! VALUE rb_float_new_in_heap(double d) { return dll_rb_float_new(d); } # if defined(DYNAMIC_RUBY_VER) && DYNAMIC_RUBY_VER >= 22 ! unsigned long ! rb_num2ulong(VALUE x) # else ! VALUE ! rb_num2ulong(VALUE x) # endif { return (long)RSHIFT((SIGNED_VALUE)(x),1); *************** *** 547,558 **** /* Do not generate a prototype here, VALUE isn't always defined. */ # if defined(USE_RGENGC) && USE_RGENGC && !defined(PROTO) # if defined(DYNAMIC_RUBY_VER) && DYNAMIC_RUBY_VER == 21 ! void rb_gc_writebarrier_unprotect_promoted_stub(VALUE obj) { dll_rb_gc_writebarrier_unprotect_promoted(obj); } # else ! void rb_gc_writebarrier_unprotect_stub(VALUE obj) { dll_rb_gc_writebarrier_unprotect(obj); } --- 560,573 ---- /* Do not generate a prototype here, VALUE isn't always defined. */ # if defined(USE_RGENGC) && USE_RGENGC && !defined(PROTO) # if defined(DYNAMIC_RUBY_VER) && DYNAMIC_RUBY_VER == 21 ! void ! rb_gc_writebarrier_unprotect_promoted_stub(VALUE obj) { dll_rb_gc_writebarrier_unprotect_promoted(obj); } # else ! void ! rb_gc_writebarrier_unprotect_stub(VALUE obj) { dll_rb_gc_writebarrier_unprotect(obj); } *************** *** 560,566 **** # endif # if defined(DYNAMIC_RUBY_VER) && DYNAMIC_RUBY_VER >= 26 ! void rb_ary_detransient_stub(VALUE x) { dll_rb_ary_detransient(x); } --- 575,582 ---- # endif # if defined(DYNAMIC_RUBY_VER) && DYNAMIC_RUBY_VER >= 26 ! void ! rb_ary_detransient_stub(VALUE x) { dll_rb_ary_detransient(x); } *************** *** 629,634 **** --- 645,651 ---- # endif {"rb_global_variable", (RUBY_PROC*)&dll_rb_global_variable}, {"rb_hash_aset", (RUBY_PROC*)&dll_rb_hash_aset}, + {"rb_hash_foreach", (RUBY_PROC*)&dll_rb_hash_foreach}, {"rb_hash_new", (RUBY_PROC*)&dll_rb_hash_new}, {"rb_inspect", (RUBY_PROC*)&dll_rb_inspect}, {"rb_int2inum", (RUBY_PROC*)&dll_rb_int2inum}, *************** *** 638,643 **** --- 655,661 ---- {"rb_num2int", (RUBY_PROC*)&dll_rb_num2int}, {"rb_num2uint", (RUBY_PROC*)&dll_rb_num2uint}, # endif + {"rb_num2dbl", (RUBY_PROC*)&dll_rb_num2dbl}, {"rb_lastline_get", (RUBY_PROC*)&dll_rb_lastline_get}, {"rb_lastline_set", (RUBY_PROC*)&dll_rb_lastline_set}, {"rb_protect", (RUBY_PROC*)&dll_rb_protect}, *************** *** 789,795 **** #endif } ! void ex_ruby(exarg_T *eap) { int state; char *script = NULL; --- 807,814 ---- #endif } ! void ! ex_ruby(exarg_T *eap) { int state; char *script = NULL; *************** *** 860,866 **** return rb_eval_string_protect(str, state); } ! void ex_rubydo(exarg_T *eap) { int state; linenr_T i; --- 879,886 ---- return rb_eval_string_protect(str, state); } ! void ! ex_rubydo(exarg_T *eap) { int state; linenr_T i; *************** *** 906,918 **** } } ! static VALUE rb_load_wrap(VALUE file_to_load) { rb_load(file_to_load, 0); return Qnil; } ! void ex_rubyfile(exarg_T *eap) { int state; --- 926,940 ---- } } ! static VALUE ! rb_load_wrap(VALUE file_to_load) { rb_load(file_to_load, 0); return Qnil; } ! void ! ex_rubyfile(exarg_T *eap) { int state; *************** *** 925,931 **** } } ! void ruby_buffer_free(buf_T *buf) { if (buf->b_ruby_ref) { --- 947,954 ---- } } ! void ! ruby_buffer_free(buf_T *buf) { if (buf->b_ruby_ref) { *************** *** 934,940 **** } } ! void ruby_window_free(win_T *win) { if (win->w_ruby_ref) { --- 957,964 ---- } } ! void ! ruby_window_free(win_T *win) { if (win->w_ruby_ref) { *************** *** 943,949 **** } } ! static int ensure_ruby_initialized(void) { if (!ruby_initialized) { --- 967,974 ---- } } ! static int ! ensure_ruby_initialized(void) { if (!ruby_initialized) { *************** *** 993,999 **** return ruby_initialized; } ! static void error_print(int state) { #if !defined(DYNAMIC_RUBY) && !defined(RUBY19_OR_LATER) RUBYEXTERN VALUE ruby_errinfo; --- 1018,1025 ---- return ruby_initialized; } ! static void ! error_print(int state) { #if !defined(DYNAMIC_RUBY) && !defined(RUBY19_OR_LATER) RUBYEXTERN VALUE ruby_errinfo; *************** *** 1018,1083 **** switch (state) { ! case TAG_RETURN: ! emsg(_("E267: unexpected return")); ! break; ! case TAG_NEXT: ! emsg(_("E268: unexpected next")); ! break; ! case TAG_BREAK: ! emsg(_("E269: unexpected break")); ! break; ! case TAG_REDO: ! emsg(_("E270: unexpected redo")); ! break; ! case TAG_RETRY: ! emsg(_("E271: retry outside of rescue clause")); ! break; ! case TAG_RAISE: ! case TAG_FATAL: #ifdef RUBY19_OR_LATER ! error = rb_errinfo(); #else ! error = ruby_errinfo; #endif ! eclass = CLASS_OF(error); ! einfo = rb_obj_as_string(error); ! if (eclass == rb_eRuntimeError && RSTRING_LEN(einfo) == 0) ! { ! emsg(_("E272: unhandled exception")); ! } ! else ! { ! VALUE epath; ! char *p; ! epath = rb_class_path(eclass); ! vim_snprintf(buff, BUFSIZ, "%s: %s", ! RSTRING_PTR(epath), RSTRING_PTR(einfo)); ! p = strchr(buff, '\n'); ! if (p) *p = '\0'; ! emsg(buff); ! } ! attr = syn_name2attr((char_u *)"Error"); # ifdef RUBY21_OR_LATER ! bt = rb_funcallv(error, rb_intern("backtrace"), 0, 0); ! for (i = 0; i < RARRAY_LEN(bt); i++) ! msg_attr(RSTRING_PTR(RARRAY_AREF(bt, i)), attr); # else ! bt = rb_funcall2(error, rb_intern("backtrace"), 0, 0); ! for (i = 0; i < RARRAY_LEN(bt); i++) ! msg_attr(RSTRING_PTR(RARRAY_PTR(bt)[i]), attr); ! # endif ! break; ! default: ! vim_snprintf(buff, BUFSIZ, _("E273: unknown longjmp status %d"), state); ! emsg(buff); ! break; } } ! static VALUE vim_message(VALUE self UNUSED, VALUE str) { char *buff, *p; --- 1044,1110 ---- switch (state) { ! case TAG_RETURN: ! emsg(_("E267: unexpected return")); ! break; ! case TAG_NEXT: ! emsg(_("E268: unexpected next")); ! break; ! case TAG_BREAK: ! emsg(_("E269: unexpected break")); ! break; ! case TAG_REDO: ! emsg(_("E270: unexpected redo")); ! break; ! case TAG_RETRY: ! emsg(_("E271: retry outside of rescue clause")); ! break; ! case TAG_RAISE: ! case TAG_FATAL: #ifdef RUBY19_OR_LATER ! error = rb_errinfo(); #else ! error = ruby_errinfo; #endif ! eclass = CLASS_OF(error); ! einfo = rb_obj_as_string(error); ! if (eclass == rb_eRuntimeError && RSTRING_LEN(einfo) == 0) ! { ! emsg(_("E272: unhandled exception")); ! } ! else ! { ! VALUE epath; ! char *p; ! epath = rb_class_path(eclass); ! vim_snprintf(buff, BUFSIZ, "%s: %s", ! RSTRING_PTR(epath), RSTRING_PTR(einfo)); ! p = strchr(buff, '\n'); ! if (p) *p = '\0'; ! emsg(buff); ! } ! attr = syn_name2attr((char_u *)"Error"); # ifdef RUBY21_OR_LATER ! bt = rb_funcallv(error, rb_intern("backtrace"), 0, 0); ! for (i = 0; i < RARRAY_LEN(bt); i++) ! msg_attr(RSTRING_PTR(RARRAY_AREF(bt, i)), attr); # else ! bt = rb_funcall2(error, rb_intern("backtrace"), 0, 0); ! for (i = 0; i < RARRAY_LEN(bt); i++) ! msg_attr(RSTRING_PTR(RARRAY_PTR(bt)[i]), attr); ! # endif ! break; ! default: ! vim_snprintf(buff, BUFSIZ, _("E273: unknown longjmp status %d"), state); ! emsg(buff); ! break; } } ! static VALUE ! vim_message(VALUE self UNUSED, VALUE str) { char *buff, *p; *************** *** 1098,1118 **** return Qnil; } ! static VALUE vim_set_option(VALUE self UNUSED, VALUE str) { do_set((char_u *)StringValuePtr(str), 0); update_screen(NOT_VALID); return Qnil; } ! static VALUE vim_command(VALUE self UNUSED, VALUE str) { do_cmdline_cmd((char_u *)StringValuePtr(str)); return Qnil; } #ifdef FEAT_EVAL ! static VALUE vim_to_ruby(typval_T *tv) { VALUE result = Qnil; --- 1125,1148 ---- return Qnil; } ! static VALUE ! vim_set_option(VALUE self UNUSED, VALUE str) { do_set((char_u *)StringValuePtr(str), 0); update_screen(NOT_VALID); return Qnil; } ! static VALUE ! vim_command(VALUE self UNUSED, VALUE str) { do_cmdline_cmd((char_u *)StringValuePtr(str)); return Qnil; } #ifdef FEAT_EVAL ! static VALUE ! vim_to_ruby(typval_T *tv) { VALUE result = Qnil; *************** *** 1188,1194 **** } #endif ! static VALUE vim_evaluate(VALUE self UNUSED, VALUE str) { #ifdef FEAT_EVAL typval_T *tv; --- 1218,1225 ---- } #endif ! static VALUE ! vim_evaluate(VALUE self UNUSED, VALUE str) { #ifdef FEAT_EVAL typval_T *tv; *************** *** 1221,1233 **** # endif }; ! static size_t buffer_dsize(const void *buf UNUSED) { return sizeof(buf_T); } #endif ! static VALUE buffer_new(buf_T *buf) { if (buf->b_ruby_ref) { --- 1252,1266 ---- # endif }; ! static size_t ! buffer_dsize(const void *buf UNUSED) { return sizeof(buf_T); } #endif ! static VALUE ! buffer_new(buf_T *buf) { if (buf->b_ruby_ref) { *************** *** 1246,1252 **** } } ! static buf_T *get_buf(VALUE obj) { buf_T *buf; --- 1279,1286 ---- } } ! static buf_T * ! get_buf(VALUE obj) { buf_T *buf; *************** *** 1260,1266 **** return buf; } ! static VALUE vim_blob(VALUE self UNUSED, VALUE str) { VALUE result = rb_str_new("0z", 2); char buf[4]; --- 1294,1301 ---- return buf; } ! static VALUE ! vim_blob(VALUE self UNUSED, VALUE str) { VALUE result = rb_str_new("0z", 2); char buf[4]; *************** *** 1273,1284 **** return result; } ! static VALUE buffer_s_current(void) { return buffer_new(curbuf); } ! static VALUE buffer_s_count(void) { buf_T *b; int n = 0; --- 1308,1321 ---- return result; } ! static VALUE ! buffer_s_current(void) { return buffer_new(curbuf); } ! static VALUE ! buffer_s_count(void) { buf_T *b; int n = 0; *************** *** 1294,1300 **** return INT2NUM(n); } ! static VALUE buffer_s_aref(VALUE self UNUSED, VALUE num) { buf_T *b; int n = NUM2INT(num); --- 1331,1338 ---- return INT2NUM(n); } ! static VALUE ! buffer_s_aref(VALUE self UNUSED, VALUE num) { buf_T *b; int n = NUM2INT(num); *************** *** 1314,1348 **** return Qnil; } ! static VALUE buffer_name(VALUE self) { buf_T *buf = get_buf(self); return buf->b_ffname ? rb_str_new2((char *)buf->b_ffname) : Qnil; } ! static VALUE buffer_number(VALUE self) { buf_T *buf = get_buf(self); return INT2NUM(buf->b_fnum); } ! static VALUE buffer_count(VALUE self) { buf_T *buf = get_buf(self); return INT2NUM(buf->b_ml.ml_line_count); } ! static VALUE get_buffer_line(buf_T *buf, linenr_T n) { if (n <= 0 || n > buf->b_ml.ml_line_count) rb_raise(rb_eIndexError, "line number %ld out of range", (long)n); return vim_str2rb_enc_str((char *)ml_get_buf(buf, n, FALSE)); } ! static VALUE buffer_aref(VALUE self, VALUE num) { buf_T *buf = get_buf(self); --- 1352,1391 ---- return Qnil; } ! static VALUE ! buffer_name(VALUE self) { buf_T *buf = get_buf(self); return buf->b_ffname ? rb_str_new2((char *)buf->b_ffname) : Qnil; } ! static VALUE ! buffer_number(VALUE self) { buf_T *buf = get_buf(self); return INT2NUM(buf->b_fnum); } ! static VALUE ! buffer_count(VALUE self) { buf_T *buf = get_buf(self); return INT2NUM(buf->b_ml.ml_line_count); } ! static VALUE ! get_buffer_line(buf_T *buf, linenr_T n) { if (n <= 0 || n > buf->b_ml.ml_line_count) rb_raise(rb_eIndexError, "line number %ld out of range", (long)n); return vim_str2rb_enc_str((char *)ml_get_buf(buf, n, FALSE)); } ! static VALUE ! buffer_aref(VALUE self, VALUE num) { buf_T *buf = get_buf(self); *************** *** 1351,1357 **** return Qnil; /* For stop warning */ } ! static VALUE set_buffer_line(buf_T *buf, linenr_T n, VALUE str) { char *line = StringValuePtr(str); aco_save_T aco; --- 1394,1401 ---- return Qnil; /* For stop warning */ } ! static VALUE ! set_buffer_line(buf_T *buf, linenr_T n, VALUE str) { char *line = StringValuePtr(str); aco_save_T aco; *************** *** 1383,1389 **** return str; } ! static VALUE buffer_aset(VALUE self, VALUE num, VALUE str) { buf_T *buf = get_buf(self); --- 1427,1434 ---- return str; } ! static VALUE ! buffer_aset(VALUE self, VALUE num, VALUE str) { buf_T *buf = get_buf(self); *************** *** 1392,1398 **** return str; } ! static VALUE buffer_delete(VALUE self, VALUE num) { buf_T *buf = get_buf(self); long n = NUM2LONG(num); --- 1437,1444 ---- return str; } ! static VALUE ! buffer_delete(VALUE self, VALUE num) { buf_T *buf = get_buf(self); long n = NUM2LONG(num); *************** *** 1427,1433 **** return Qnil; } ! static VALUE buffer_append(VALUE self, VALUE num, VALUE str) { buf_T *buf = get_buf(self); char *line = StringValuePtr(str); --- 1473,1480 ---- return Qnil; } ! static VALUE ! buffer_append(VALUE self, VALUE num, VALUE str) { buf_T *buf = get_buf(self); char *line = StringValuePtr(str); *************** *** 1479,1491 **** # endif }; ! static size_t window_dsize(const void *win UNUSED) { return sizeof(win_T); } #endif ! static VALUE window_new(win_T *win) { if (win->w_ruby_ref) { --- 1526,1540 ---- # endif }; ! static size_t ! window_dsize(const void *win UNUSED) { return sizeof(win_T); } #endif ! static VALUE ! window_new(win_T *win) { if (win->w_ruby_ref) { *************** *** 1504,1510 **** } } ! static win_T *get_win(VALUE obj) { win_T *win; --- 1553,1560 ---- } } ! static win_T * ! get_win(VALUE obj) { win_T *win; *************** *** 1518,1524 **** return win; } ! static VALUE window_s_current(void) { return window_new(curwin); } --- 1568,1575 ---- return win; } ! static VALUE ! window_s_current(void) { return window_new(curwin); } *************** *** 1527,1550 **** * Added line manipulation functions * SegPhault - 03/07/05 */ ! static VALUE line_s_current(void) { return get_buffer_line(curbuf, curwin->w_cursor.lnum); } ! static VALUE set_current_line(VALUE self UNUSED, VALUE str) { return set_buffer_line(curbuf, curwin->w_cursor.lnum, str); } ! static VALUE current_line_number(void) { return INT2FIX((int)curwin->w_cursor.lnum); } ! ! ! static VALUE window_s_count(void) { win_T *w; int n = 0; --- 1578,1603 ---- * Added line manipulation functions * SegPhault - 03/07/05 */ ! static VALUE ! line_s_current(void) { return get_buffer_line(curbuf, curwin->w_cursor.lnum); } ! static VALUE ! set_current_line(VALUE self UNUSED, VALUE str) { return set_buffer_line(curbuf, curwin->w_cursor.lnum, str); } ! static VALUE ! current_line_number(void) { return INT2FIX((int)curwin->w_cursor.lnum); } ! static VALUE ! window_s_count(void) { win_T *w; int n = 0; *************** *** 1554,1560 **** return INT2NUM(n); } ! static VALUE window_s_aref(VALUE self UNUSED, VALUE num) { win_T *w; int n = NUM2INT(num); --- 1607,1614 ---- return INT2NUM(n); } ! static VALUE ! window_s_aref(VALUE self UNUSED, VALUE num) { win_T *w; int n = NUM2INT(num); *************** *** 1565,1585 **** return Qnil; } ! static VALUE window_buffer(VALUE self) { win_T *win = get_win(self); return buffer_new(win->w_buffer); } ! static VALUE window_height(VALUE self) { win_T *win = get_win(self); return INT2NUM(win->w_height); } ! static VALUE window_set_height(VALUE self, VALUE height) { win_T *win = get_win(self); win_T *savewin = curwin; --- 1619,1642 ---- return Qnil; } ! static VALUE ! window_buffer(VALUE self) { win_T *win = get_win(self); return buffer_new(win->w_buffer); } ! static VALUE ! window_height(VALUE self) { win_T *win = get_win(self); return INT2NUM(win->w_height); } ! static VALUE ! window_set_height(VALUE self, VALUE height) { win_T *win = get_win(self); win_T *savewin = curwin; *************** *** 1590,1601 **** return height; } ! static VALUE window_width(VALUE self UNUSED) { return INT2NUM(get_win(self)->w_width); } ! static VALUE window_set_width(VALUE self UNUSED, VALUE width) { win_T *win = get_win(self); win_T *savewin = curwin; --- 1647,1660 ---- return height; } ! static VALUE ! window_width(VALUE self UNUSED) { return INT2NUM(get_win(self)->w_width); } ! static VALUE ! window_set_width(VALUE self UNUSED, VALUE width) { win_T *win = get_win(self); win_T *savewin = curwin; *************** *** 1606,1619 **** return width; } ! static VALUE window_cursor(VALUE self) { win_T *win = get_win(self); return rb_assoc_new(INT2NUM(win->w_cursor.lnum), INT2NUM(win->w_cursor.col)); } ! static VALUE window_set_cursor(VALUE self, VALUE pos) { VALUE lnum, col; win_T *win = get_win(self); --- 1665,1680 ---- return width; } ! static VALUE ! window_cursor(VALUE self) { win_T *win = get_win(self); return rb_assoc_new(INT2NUM(win->w_cursor.lnum), INT2NUM(win->w_cursor.col)); } ! static VALUE ! window_set_cursor(VALUE self, VALUE pos) { VALUE lnum, col; win_T *win = get_win(self); *************** *** 1631,1642 **** return Qnil; } ! static VALUE f_nop(VALUE self UNUSED) { return Qnil; } ! static VALUE f_p(int argc, VALUE *argv, VALUE self UNUSED) { int i; VALUE str = rb_str_new("", 0); --- 1692,1705 ---- return Qnil; } ! static VALUE ! f_nop(VALUE self UNUSED) { return Qnil; } ! static VALUE ! f_p(int argc, VALUE *argv, VALUE self UNUSED) { int i; VALUE str = rb_str_new("", 0); *************** *** 1656,1662 **** return ret; } ! static void ruby_io_init(void) { #ifndef DYNAMIC_RUBY RUBYEXTERN VALUE rb_stdout; --- 1719,1726 ---- return ret; } ! static void ! ruby_io_init(void) { #ifndef DYNAMIC_RUBY RUBYEXTERN VALUE rb_stdout; *************** *** 1672,1678 **** rb_define_global_function("p", f_p, -1); } ! static void ruby_vim_init(void) { objtbl = rb_hash_new(); rb_global_variable(&objtbl); --- 1736,1743 ---- rb_define_global_function("p", f_p, -1); } ! static void ! ruby_vim_init(void) { objtbl = rb_hash_new(); rb_global_variable(&objtbl); *************** *** 1736,1743 **** rb_define_virtual_variable("$curwin", window_s_current, 0); } ! void vim_ruby_init(void *stack_start) { /* should get machine stack start address early in main function */ ruby_stack_start = stack_start; } --- 1801,1939 ---- rb_define_virtual_variable("$curwin", window_s_current, 0); } ! void ! vim_ruby_init(void *stack_start) { /* should get machine stack start address early in main function */ ruby_stack_start = stack_start; } + + static int + convert_hash2dict(VALUE key, VALUE val, VALUE arg) + { + dict_T *d = (dict_T *)arg; + dictitem_T *di; + + di = dictitem_alloc((char_u *)RSTRING_PTR(RSTRING(rb_obj_as_string(key)))); + if (di == NULL || ruby_convert_to_vim_value(val, &di->di_tv) != OK + || dict_add(d, di) != OK) + { + d->dv_hashtab.ht_error = TRUE; + return ST_STOP; + } + return ST_CONTINUE; + } + + static int + ruby_convert_to_vim_value(VALUE val, typval_T *rettv) + { + switch (TYPE(val)) + { + case T_NIL: + rettv->v_type = VAR_SPECIAL; + rettv->vval.v_number = VVAL_NULL; + break; + case T_TRUE: + rettv->v_type = VAR_SPECIAL; + rettv->vval.v_number = VVAL_TRUE; + break; + case T_FALSE: + rettv->v_type = VAR_SPECIAL; + rettv->vval.v_number = VVAL_FALSE; + break; + case T_BIGNUM: + case T_FIXNUM: + rettv->v_type = VAR_NUMBER; + rettv->vval.v_number = (varnumber_T)NUM2LONG(val); + break; + #ifdef FEAT_FLOAT + case T_FLOAT: + rettv->v_type = VAR_FLOAT; + rettv->vval.v_float = (float_T)NUM2DBL(val); + break; + #endif + default: + val = rb_obj_as_string(val); + // FALLTHROUGH + case T_STRING: + { + VALUE str = (VALUE)RSTRING(val); + + rettv->v_type = VAR_STRING; + rettv->vval.v_string = vim_strnsave((char_u *)RSTRING_PTR(str), + (int)RSTRING_LEN(str)); + } + break; + case T_ARRAY: + { + list_T *l; + long i; + typval_T v; + + l = list_alloc(); + if (l == NULL) + return FAIL; + + for (i = 0; i < RARRAY_LEN(val); ++i) + { + if (ruby_convert_to_vim_value((VALUE)RARRAY_PTR(val)[i], + &v) != OK) + { + list_unref(l); + return FAIL; + } + list_append_tv(l, &v); + clear_tv(&v); + } + + rettv->v_type = VAR_LIST; + rettv->vval.v_list = l; + ++l->lv_refcount; + } + break; + case T_HASH: + { + dict_T *d; + + d = dict_alloc(); + if (d == NULL) + return FAIL; + + rb_hash_foreach(val, convert_hash2dict, (VALUE)d); + if (d->dv_hashtab.ht_error) + { + dict_unref(d); + return FAIL; + } + + rettv->v_type = VAR_DICT; + rettv->vval.v_dict = d; + ++d->dv_refcount; + } + break; + } + return OK; + } + + void + do_rubyeval(char_u *str, typval_T *rettv) + { + int retval = FAIL; + + if (ensure_ruby_initialized()) + { + int state; + VALUE obj; + + obj = rb_eval_string_protect((const char *)str, &state); + if (state) + error_print(state); + else + retval = ruby_convert_to_vim_value(obj, rettv); + } + if (retval == FAIL) + { + rettv->v_type = VAR_NUMBER; + rettv->vval.v_number = 0; + } + } *** ../vim-8.1.1055/src/proto/if_ruby.pro 2018-05-17 13:52:41.000000000 +0200 --- src/proto/if_ruby.pro 2019-03-26 22:40:42.456751899 +0100 *************** *** 7,10 **** --- 7,11 ---- void ruby_buffer_free(buf_T *buf); void ruby_window_free(win_T *win); void vim_ruby_init(void *stack_start); + void do_rubyeval(char_u *str, typval_T *rettv); /* vim: set ft=c : */ *** ../vim-8.1.1055/src/testdir/test_ruby.vim 2019-02-23 14:22:59.567653374 +0100 --- src/testdir/test_ruby.vim 2019-03-26 22:40:42.456751899 +0100 *************** *** 4,16 **** finish end - " Helper function as there is no builtin rubyeval() function similar - " to perleval, luaevel() or pyeval(). - func RubyEval(ruby_expr) - let s = split(execute('ruby print ' . a:ruby_expr), "\n") - return (len(s) == 0) ? '' : s[-1] - endfunc - func Test_ruby_change_buffer() call setline(line('$'), ['1 line 1']) ruby Vim.command("normal /^1\n") --- 4,9 ---- *************** *** 49,60 **** normal gg rubydo $curwin.cursor = [1, 5] call assert_equal([1, 6], [line('.'), col('.')]) ! call assert_equal('[1, 5]', RubyEval('$curwin.cursor')) " Check that movement after setting cursor position keeps current column. normal j call assert_equal([2, 6], [line('.'), col('.')]) ! call assert_equal('[2, 5]', RubyEval('$curwin.cursor')) call assert_fails('ruby $curwin.cursor = [1]', \ 'ArgumentError: array length must be 2') --- 42,53 ---- normal gg rubydo $curwin.cursor = [1, 5] call assert_equal([1, 6], [line('.'), col('.')]) ! call assert_equal([1, 5], rubyeval('$curwin.cursor')) " Check that movement after setting cursor position keeps current column. normal j call assert_equal([2, 6], [line('.'), col('.')]) ! call assert_equal([2, 5], rubyeval('$curwin.cursor')) call assert_fails('ruby $curwin.cursor = [1]', \ 'ArgumentError: array length must be 2') *************** *** 65,89 **** func Test_buffer_count() new call setline(1, ['one', 'two', 'three']) ! call assert_equal('3', RubyEval('$curbuf.count')) ! call assert_equal('3', RubyEval('$curbuf.length')) bwipe! endfunc " Test buffer.name (buffer name) func Test_buffer_name() new Xfoo ! call assert_equal(expand('%:p'), RubyEval('$curbuf.name')) bwipe ! call assert_equal('', RubyEval('$curbuf.name')) endfunc " Test buffer.number (number of the buffer). func Test_buffer_number() new ! call assert_equal(string(bufnr('%')), RubyEval('$curbuf.number')) new ! call assert_equal(string(bufnr('%')), RubyEval('$curbuf.number')) %bwipe endfunc --- 58,82 ---- func Test_buffer_count() new call setline(1, ['one', 'two', 'three']) ! call assert_equal(3, rubyeval('$curbuf.count')) ! call assert_equal(3, rubyeval('$curbuf.length')) bwipe! endfunc " Test buffer.name (buffer name) func Test_buffer_name() new Xfoo ! call assert_equal(expand('%:p'), rubyeval('$curbuf.name')) bwipe ! call assert_equal(v:null, rubyeval('$curbuf.name')) endfunc " Test buffer.number (number of the buffer). func Test_buffer_number() new ! call assert_equal(bufnr('%'), rubyeval('$curbuf.number')) new ! call assert_equal(bufnr('%'), rubyeval('$curbuf.number')) %bwipe endfunc *************** *** 124,130 **** new call setline(1, ['one', 'two', 'three']) 2 ! call assert_equal('two', RubyEval('$curbuf.line')) ruby $curbuf.line = 'TWO' call assert_equal(['one', 'TWO', 'three'], getline(1, '$')) --- 117,123 ---- new call setline(1, ['one', 'two', 'three']) 2 ! call assert_equal('two', rubyeval('$curbuf.line')) ruby $curbuf.line = 'TWO' call assert_equal(['one', 'TWO', 'three'], getline(1, '$')) *************** *** 137,143 **** new call setline(1, ['one', 'two', 'three']) 2 ! call assert_equal('2', RubyEval('$curbuf.line_number')) bwipe! endfunc --- 130,136 ---- new call setline(1, ['one', 'two', 'three']) 2 ! call assert_equal(2, rubyeval('$curbuf.line_number')) bwipe! endfunc *************** *** 145,152 **** func Test_buffer_get() new call setline(1, ['one', 'two']) ! call assert_equal('one', RubyEval('$curbuf[1]')) ! call assert_equal('two', RubyEval('$curbuf[2]')) call assert_fails('ruby $curbuf[0]', \ 'IndexError: line number 0 out of range') --- 138,145 ---- func Test_buffer_get() new call setline(1, ['one', 'two']) ! call assert_equal('one', rubyeval('$curbuf[1]')) ! call assert_equal('two', rubyeval('$curbuf[2]')) call assert_fails('ruby $curbuf[0]', \ 'IndexError: line number 0 out of range') *************** *** 178,184 **** call assert_equal(2, winheight(0)) " Test getting window height ! call assert_equal('2', RubyEval('$curwin.height')) bwipe endfunc --- 171,177 ---- call assert_equal(2, winheight(0)) " Test getting window height ! call assert_equal(2, rubyeval('$curwin.height')) bwipe endfunc *************** *** 192,198 **** call assert_equal(2, winwidth(0)) " Test getting window width ! call assert_equal('2', RubyEval('$curwin.width')) bwipe endfunc --- 185,191 ---- call assert_equal(2, winwidth(0)) " Test getting window width ! call assert_equal(2, rubyeval('$curwin.width')) bwipe endfunc *************** *** 207,216 **** ruby $b1 = $curwin.buffer ruby $w1 = $curwin ! call assert_equal(RubyEval('$b1'), RubyEval('$w1.buffer')) ! call assert_equal(RubyEval('$b2'), RubyEval('$w2.buffer')) ! call assert_equal(string(bufnr('Xfoo1')), RubyEval('$w1.buffer.number')) ! call assert_equal(string(bufnr('Xfoo2')), RubyEval('$w2.buffer.number')) ruby $b1, $w1, $b2, $w2 = nil %bwipe --- 200,209 ---- ruby $b1 = $curwin.buffer ruby $w1 = $curwin ! call assert_equal(rubyeval('$b1'), rubyeval('$w1.buffer')) ! call assert_equal(rubyeval('$b2'), rubyeval('$w2.buffer')) ! call assert_equal(bufnr('Xfoo1'), rubyeval('$w1.buffer.number')) ! call assert_equal(bufnr('Xfoo2'), rubyeval('$w2.buffer.number')) ruby $b1, $w1, $b2, $w2 = nil %bwipe *************** *** 218,225 **** " Test Vim::Window.current (get current window object) func Test_Vim_window_current() ! let cw = RubyEval('$curwin') ! call assert_equal(cw, RubyEval('Vim::Window.current')) call assert_match('^#$', cw) endfunc --- 211,218 ---- " Test Vim::Window.current (get current window object) func Test_Vim_window_current() ! let cw = rubyeval('$curwin') ! call assert_equal(cw, rubyeval('Vim::Window.current')) call assert_match('^#$', cw) endfunc *************** *** 228,254 **** new Xfoo1 new Xfoo2 split ! call assert_equal('4', RubyEval('Vim::Window.count')) %bwipe ! call assert_equal('1', RubyEval('Vim::Window.count')) endfunc " Test Vim::Window[n] (get window object of window n) func Test_Vim_window_get() new Xfoo1 new Xfoo2 ! call assert_match('Xfoo2$', RubyEval('Vim::Window[0].buffer.name')) wincmd j ! call assert_match('Xfoo1$', RubyEval('Vim::Window[1].buffer.name')) wincmd j ! call assert_equal('', RubyEval('Vim::Window[2].buffer.name')) %bwipe endfunc " Test Vim::Buffer.current (return the buffer object of current buffer) func Test_Vim_buffer_current() ! let cb = RubyEval('$curbuf') ! call assert_equal(cb, RubyEval('Vim::Buffer.current')) call assert_match('^#$', cb) endfunc --- 221,247 ---- new Xfoo1 new Xfoo2 split ! call assert_equal(4, rubyeval('Vim::Window.count')) %bwipe ! call assert_equal(1, rubyeval('Vim::Window.count')) endfunc " Test Vim::Window[n] (get window object of window n) func Test_Vim_window_get() new Xfoo1 new Xfoo2 ! call assert_match('Xfoo2$', rubyeval('Vim::Window[0].buffer.name')) wincmd j ! call assert_match('Xfoo1$', rubyeval('Vim::Window[1].buffer.name')) wincmd j ! call assert_equal(v:null, rubyeval('Vim::Window[2].buffer.name')) %bwipe endfunc " Test Vim::Buffer.current (return the buffer object of current buffer) func Test_Vim_buffer_current() ! let cb = rubyeval('$curbuf') ! call assert_equal(cb, rubyeval('Vim::Buffer.current')) call assert_match('^#$', cb) endfunc *************** *** 256,264 **** func Test_Vim_buffer_count() new Xfoo1 new Xfoo2 ! call assert_equal('3', RubyEval('Vim::Buffer.count')) %bwipe ! call assert_equal('1', RubyEval('Vim::Buffer.count')) endfunc " Test Vim::buffer[n] (return the buffer object of buffer number n) --- 249,257 ---- func Test_Vim_buffer_count() new Xfoo1 new Xfoo2 ! call assert_equal(3, rubyeval('Vim::Buffer.count')) %bwipe ! call assert_equal(1, rubyeval('Vim::Buffer.count')) endfunc " Test Vim::buffer[n] (return the buffer object of buffer number n) *************** *** 267,275 **** new Xfoo2 " Index of Vim::Buffer[n] goes from 0 to the number of buffers. ! call assert_equal('', RubyEval('Vim::Buffer[0].name')) ! call assert_match('Xfoo1$', RubyEval('Vim::Buffer[1].name')) ! call assert_match('Xfoo2$', RubyEval('Vim::Buffer[2].name')) call assert_fails('ruby print Vim::Buffer[3].name', \ "NoMethodError: undefined method `name' for nil:NilClass") %bwipe --- 260,268 ---- new Xfoo2 " Index of Vim::Buffer[n] goes from 0 to the number of buffers. ! call assert_equal(v:null, rubyeval('Vim::Buffer[0].name')) ! call assert_match('Xfoo1$', rubyeval('Vim::Buffer[1].name')) ! call assert_match('Xfoo2$', rubyeval('Vim::Buffer[2].name')) call assert_fails('ruby print Vim::Buffer[3].name', \ "NoMethodError: undefined method `name' for nil:NilClass") %bwipe *************** *** 295,337 **** endfunc func Test_Vim_evaluate() ! call assert_equal('123', RubyEval('Vim::evaluate("123")')) " Vim::evaluate("123").class gives Integer or Fixnum depending " on versions of Ruby. ! call assert_match('^Integer\|Fixnum$', RubyEval('Vim::evaluate("123").class')) ! call assert_equal('1.23', RubyEval('Vim::evaluate("1.23")')) ! call assert_equal('Float', RubyEval('Vim::evaluate("1.23").class')) ! call assert_equal('foo', RubyEval('Vim::evaluate("\"foo\"")')) ! call assert_equal('String', RubyEval('Vim::evaluate("\"foo\"").class')) ! call assert_equal('["\x01\xAB"]', RubyEval('Vim::evaluate("0z01ab").unpack("M")')) ! call assert_equal('String', RubyEval('Vim::evaluate("0z01ab").class')) ! call assert_equal('[1, 2]', RubyEval('Vim::evaluate("[1, 2]")')) ! call assert_equal('Array', RubyEval('Vim::evaluate("[1, 2]").class')) ! call assert_equal('{"1"=>2}', RubyEval('Vim::evaluate("{1:2}")')) ! call assert_equal('Hash', RubyEval('Vim::evaluate("{1:2}").class')) ! call assert_equal('', RubyEval('Vim::evaluate("v:null")')) ! call assert_equal('NilClass', RubyEval('Vim::evaluate("v:null").class')) ! call assert_equal('', RubyEval('Vim::evaluate("v:none")')) ! call assert_equal('NilClass', RubyEval('Vim::evaluate("v:none").class')) ! call assert_equal('true', RubyEval('Vim::evaluate("v:true")')) ! call assert_equal('TrueClass', RubyEval('Vim::evaluate("v:true").class')) ! call assert_equal('false', RubyEval('Vim::evaluate("v:false")')) ! call assert_equal('FalseClass',RubyEval('Vim::evaluate("v:false").class')) endfunc func Test_Vim_blob() ! call assert_equal('0z', RubyEval('Vim::blob("")')) ! call assert_equal('0z31326162', RubyEval('Vim::blob("12ab")')) ! call assert_equal('0z00010203', RubyEval('Vim::blob("\x00\x01\x02\x03")')) ! call assert_equal('0z8081FEFF', RubyEval('Vim::blob("\x80\x81\xfe\xff")')) endfunc func Test_Vim_evaluate_list() --- 288,330 ---- endfunc func Test_Vim_evaluate() ! call assert_equal(123, rubyeval('Vim::evaluate("123")')) " Vim::evaluate("123").class gives Integer or Fixnum depending " on versions of Ruby. ! call assert_match('^Integer\|Fixnum$', rubyeval('Vim::evaluate("123").class')) ! call assert_equal(1.23, rubyeval('Vim::evaluate("1.23")')) ! call assert_equal('Float', rubyeval('Vim::evaluate("1.23").class')) ! call assert_equal('foo', rubyeval('Vim::evaluate("\"foo\"")')) ! call assert_equal('String', rubyeval('Vim::evaluate("\"foo\"").class')) ! call assert_equal(["\x01\xAB"], rubyeval('Vim::evaluate("0z01ab").unpack("M")')) ! call assert_equal('String', rubyeval('Vim::evaluate("0z01ab").class')) ! call assert_equal([1, 2], rubyeval('Vim::evaluate("[1, 2]")')) ! call assert_equal('Array', rubyeval('Vim::evaluate("[1, 2]").class')) ! call assert_equal({'1': 2}, rubyeval('Vim::evaluate("{1:2}")')) ! call assert_equal('Hash', rubyeval('Vim::evaluate("{1:2}").class')) ! call assert_equal(v:null, rubyeval('Vim::evaluate("v:null")')) ! call assert_equal('NilClass', rubyeval('Vim::evaluate("v:null").class')) ! call assert_equal(v:null, rubyeval('Vim::evaluate("v:none")')) ! call assert_equal('NilClass', rubyeval('Vim::evaluate("v:none").class')) ! call assert_equal(v:true, rubyeval('Vim::evaluate("v:true")')) ! call assert_equal('TrueClass', rubyeval('Vim::evaluate("v:true").class')) ! call assert_equal(v:false, rubyeval('Vim::evaluate("v:false")')) ! call assert_equal('FalseClass',rubyeval('Vim::evaluate("v:false").class')) endfunc func Test_Vim_blob() ! call assert_equal('0z', rubyeval('Vim::blob("")')) ! call assert_equal('0z31326162', rubyeval('Vim::blob("12ab")')) ! call assert_equal('0z00010203', rubyeval('Vim::blob("\x00\x01\x02\x03")')) ! call assert_equal('0z8081FEFF', rubyeval('Vim::blob("\x80\x81\xfe\xff")')) endfunc func Test_Vim_evaluate_list() *************** *** 364,372 **** endfunc func Test_print() ! ruby print "Hello World!" ! let messages = split(execute('message'), "\n") ! call assert_equal('Hello World!', messages[-1]) endfunc func Test_p() --- 357,378 ---- endfunc func Test_print() ! func RubyPrint(expr) ! return trim(execute('ruby print ' . a:expr)) ! endfunc ! ! call assert_equal('123', RubyPrint('123')) ! call assert_equal('1.23', RubyPrint('1.23')) ! call assert_equal('Hello World!', RubyPrint('"Hello World!"')) ! call assert_equal('[1, 2]', RubyPrint('[1, 2]')) ! call assert_equal('{"k1"=>"v1", "k2"=>"v2"}', RubyPrint('({"k1" => "v1", "k2" => "v2"})')) ! call assert_equal('true', RubyPrint('true')) ! call assert_equal('false', RubyPrint('false')) ! call assert_equal('', RubyPrint('nil')) ! call assert_match('Vim', RubyPrint('Vim')) ! call assert_match('Module', RubyPrint('Vim.class')) ! ! delfunc RubyPrint endfunc func Test_p() *************** *** 376,388 **** " Check return values of p method ! call assert_equal('123', RubyEval('p(123)')) ! call assert_equal('[1, 2, 3]', RubyEval('p(1, 2, 3)')) " Avoid the "message maintainer" line. let $LANG = '' messages clear ! call assert_equal('true', RubyEval('p() == nil')) let messages = split(execute('message'), "\n") call assert_equal(0, len(messages)) --- 382,394 ---- " Check return values of p method ! call assert_equal(123, rubyeval('p(123)')) ! call assert_equal([1, 2, 3], rubyeval('p(1, 2, 3)')) " Avoid the "message maintainer" line. let $LANG = '' messages clear ! call assert_equal(v:true, rubyeval('p() == nil')) let messages = split(execute('message'), "\n") call assert_equal(0, len(messages)) *** ../vim-8.1.1055/src/version.c 2019-03-26 22:46:01.885928372 +0100 --- src/version.c 2019-03-26 22:49:08.868304682 +0100 *************** *** 777,778 **** --- 777,780 ---- { /* Add new patch number below this line */ + /**/ + 1056, /**/ -- hundred-and-one symptoms of being an internet addict: 128. You can access the Net -- via your portable and cellular phone. /// Bram Moolenaar -- Bram@Moolenaar.net -- http://www.Moolenaar.net \\\ /// sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\ \\\ an exciting new programming language -- http://www.Zimbu.org /// \\\ help me help AIDS victims -- http://ICCF-Holland.org ///