Merge remote-tracking branch 'vim/master'

This commit is contained in:
Kazuki Sakamoto
2018-07-02 23:15:52 -07:00
41 changed files with 1405 additions and 282 deletions
+2
View File
@@ -412,6 +412,8 @@ SRC_DOS = \
src/msvc2008.bat \
src/msvc2010.bat \
src/msvc2015.bat \
src/msys32.bat \
src/msys64.bat \
src/dimm.idl \
src/dlldata.c \
src/dosinst.c \
+3 -4
View File
@@ -127,7 +127,7 @@ Vim evaluation and command execution, and others.
rules. Example: >
:lua t = {math.pi, false, say = 'hi'}
:echo luaeval('vim.list(t)')
:" [3.141593, 0], 'say' is ignored
:" [3.141593, v:false], 'say' is ignored
<
vim.dict([arg]) Returns an empty dictionary or, if "arg" is a
Lua table, returns a dict d such that d[k] =
@@ -141,8 +141,7 @@ Vim evaluation and command execution, and others.
:" {'say': 'hi'}, numeric keys ignored
<
vim.funcref({name}) Returns a Funcref to function {name} (see
|Funcref|). It is equivalent to Vim's
"function". NOT IMPLEMENTED YET
|Funcref|). It is equivalent to Vim's function().
vim.buffer([arg]) If "arg" is a number, returns buffer with
number "arg" in the buffer list or, if "arg"
@@ -166,7 +165,7 @@ Vim evaluation and command execution, and others.
or window, respectively. Examples: >
:lua l = vim.list()
:lua print(type(l), vim.type(l))
:" userdata list
:" list
<
vim.command({cmd}) Executes the vim (ex-mode) command {cmd}.
Examples: >
+112 -32
View File
@@ -22,23 +22,24 @@ any faster, but you can edit files larger than 2 Gbyte.
Contents:
1. Microsoft Visual C++
2. Using MinGW
3. Cygwin
4. Borland
5. Cross compiling for Win32 from a Linux machine
6. Building with Python support
7. Building with Python3 support
8. Building with Racket or MzScheme support
9. Building with Lua support
10. Building with Perl support
11. Building with Ruby support
12. Building with Tcl support
13. Building with Terminal support
14. Building with DirectX (DirectWrite) support
15. Windows 3.1
16. MS-DOS
2. Using MSYS2 with MinGW
3. Using MinGW
4. Cygwin
5. Borland
6. Cross compiling for Win32 from a Linux machine
7. Building with Python support
8. Building with Python3 support
9. Building with Racket or MzScheme support
10. Building with Lua support
11. Building with Perl support
12. Building with Ruby support
13. Building with Tcl support
14. Building with Terminal support
15. Building with DirectX (DirectWrite) support
16. Windows 3.1
17. MS-DOS
17. Installing after building from sources
18. Installing after building from sources
The currently recommended way (that means it has been verified to work) is
@@ -261,8 +262,87 @@ Instructions for integrating the Platform SDK into VC Express:
http://msdn.microsoft.com/vstudio/express/visualc/usingpsdk/default.aspx
2. MSYS2 with MinGW
===================
2. MinGW
2.1. Setup the basic msys2 environment
Go to the official page of MSYS2: https://www.msys2.org
Download an installer:
* msys2-x86_64-YYYYMMDD.exe for 64-bit Windows
(Even if you want to build 32-bit Vim)
* msys2-i686-YYYYMMDD.exe for 32-bit Windows
Execute the installer and follow the instructions to update basic packages.
At the end keep the checkbox checked to run msys2 now. If needed, you can
open the window from the start menu, MSYS2 64 bit / MSYS2 MSYS
Execute:
$ pacman -Syu
And restart MSYS2 window (select "MSYS2 MSYS" icon from the Start Menu).
Then execute:
$ pacman -Su
If pacman complains that `catgets` and `libcatgets` conflict with another
package, select `y` to remove them.
2.2. Install additional packages for building Vim
The following package groups are required for building Vim:
* base-devel
* mingw-w64-i686-toolchain (for building 32-bit Vim)
* mingw-w64-x86_64-toolchain (for building 64-bit Vim)
Use the following command to install them:
$ pacman -S base-devel mingw-w64-i686-toolchain mingw-w64-x86_64-toolchain
Or you can use the `pacboy` command to avoid long package names:
$ pacboy -S base-devel: toolchain:m
(See `pacboy help` for the help.)
2.3. Keep the build environment up-to-date
After you have installed the build environment, you may want to keep it
up-to-date (E.g. always use the latest GCC).
In that case, you just need to execute the command:
$ pacman -Syu
# Build Vim
Select one of the following icon from the Start Menu:
* MSYS2 MinGW 32-bit (To build 32-bit versions of Vim)
* MSYS2 MinGW 64-bit (To build 64-bit versions of Vim)
Go to the source directory of Vim, then execute the make command. E.g.:
make -f Make_ming.mak
make -f Make_ming.mak GUI=no
make -f Make_ming.mak GUI=no DEBUG=yes
NOTE: you can't execute the vim.exe in the MSYS console, open a normal Windows
console for that. You need to set $PATH to be able to build there, e.g.:
set PATH=c:\msys64\mingw32\bin;c:\msys64\usr\bin;%PATH%
This command is in msys32.bat. Or or the 64 bit compiler use msys64.bat:
set PATH=c:\msys64\mingw64\bin;c:\msys64\usr\bin;%PATH%
If you have msys64 in another location you will need to adjust the paths for
that.
3. MinGW
========
(written by Ron Aaron: <ronaharon@yahoo.com>)
@@ -344,7 +424,7 @@ If you want National Language Support, read the file src/po/README_mingw.txt.
You need to uncomment lines in Make_ming.mak to have NLS defined.
3. Cygwin
4. Cygwin
=========
Use Make_cyg.mak with Cygwin's GCC. See
@@ -356,14 +436,14 @@ running on Unix), while with Make_cyg.mak you get a Windows application (like
with the other makefiles).
4. Borland
5. Borland
===========
Use Make_bc5.mak with Borland C++ 5.x. See
http://users.skynet.be/antoine.mechelynck/vim/compile.htm
5. Cross compiling for Win32 from a Linux machine
6. Cross compiling for Win32 from a Linux machine
=================================================
[Update of 1) needs to be verified]
@@ -383,7 +463,7 @@ your Linux (or other unix) box. To do this, you need to follow a few steps:
Now you have created the Windows binary from your Linux box! Have fun...
6. Building with Python support
7. Building with Python support
===============================
For building with MSVC 2008 the "Windows Installer" from www.python.org
@@ -435,7 +515,7 @@ And if you use msys2 to build python support (as one line):
You will end up with a Python-enabled, Win32 version. Enjoy!
7. Building with Python3 support
8. Building with Python3 support
================================
For building with MSVC 2008 the "Windows Installer" from www.python.org
@@ -466,7 +546,7 @@ When using msys2 and link with Python3 bundled with msys2 (as one line):
(This is for 64-bit builds. For 32-bit builds, replace mingw64 with mingw32.)
8. Building with Racket or MzScheme support
9. Building with Racket or MzScheme support
========================================
1) Building with Racket support (newest)
@@ -556,7 +636,7 @@ After a successful build, these dlls can be freely removed, leaving them in
9. Building with Lua support
10. Building with Lua support
============================
Vim with Lua support can be built with either MSVC or MinGW (or maybe Cygwin).
@@ -611,7 +691,7 @@ Or when using Cygwin (as one line) (untested):
LUA=/cygdrive/c/projects/lua53 DYNAMIC_LUA=yes LUA_VER=53
10. Building with Perl support
11. Building with Perl support
==============================
Vim with Perl support can be built with either MSVC or MinGW (or Cygwin).
@@ -637,7 +717,7 @@ Or when using MinGW (as one line):
PERL=C:/Perl DYNAMIC_PERL=yes PERL_VER=522
11. Building with Ruby support
12. Building with Ruby support
==============================
Vim with Ruby support can be built with either MSVC or MinGW (or Cygwin).
@@ -745,7 +825,7 @@ Ruby 2.1 or later. (Default is 0x501.)
12. Building with Tcl support
13. Building with Tcl support
=============================
Vim with Tcl support can be built with either MSVC or MinGW (or Cygwin).
@@ -777,7 +857,7 @@ Or when using MinGW (as one line):
TCL=C:/Tcl86 DYNAMIC_TCL=yes TCL_VER=86 TCL_VER_LONG=8.6
13. Building with Terminal support
14. Building with Terminal support
==================================
Vim with Terminal support can be built with either MSVC, MinGW or Cygwin.
@@ -793,7 +873,7 @@ Or when using MinGW:
mingw32-make -f Make_ming.mak TERMINAL=yes
14. Building with DirectX (DirectWrite) support
15. Building with DirectX (DirectWrite) support
===============================================
Vim with DirectX (DirectWrite) support can be built with either MSVC or MinGW.
@@ -827,20 +907,20 @@ Just set DIRECTX to yes:
mingw32-make -f Make_ming.mak DIRECTX=yes
15. Windows 3.1x
16. Windows 3.1x
================
The Windows 3.1x support was removed in patch 7.4.1364.
16. MS-DOS
17. MS-DOS
==========
The MS-DOS support was removed in patch 7.4.1399. Only very old Vim versions
work on MS-DOS because of the limited amount of memory available.
17. Installing after building from sources
18. Installing after building from sources
==========================================
[provided by Michael Soyka, updated by Ken Takata]
+3 -2
View File
@@ -75,9 +75,10 @@ POSTSCRIPT=no
# Set to yes to enable OLE support.
OLE=no
# Set the default $(WINVER) to make it work with WinXP.
# Set the default $(WINVER). Use 0x0501 to make it work with WinXP.
ifndef WINVER
WINVER = 0x0501
# WINVER = 0x0501
WINVER = 0x0600
endif
# Set to yes to enable Cscope support.
+2 -1
View File
@@ -2136,7 +2136,7 @@ test1 \
test52 test59 \
test64 test69 \
test70 test72 \
test85 test86 test87 test88 \
test86 test87 test88 \
test94 test95 test99 test108:
cd testdir; rm -f $@.out; $(MAKE) -f Makefile $@.out VIMPROG=../$(VIMTESTTARGET) $(GUI_TESTARG) SCRIPTSOURCE=../$(SCRIPTSOURCE)
@@ -2305,6 +2305,7 @@ test_arglist \
test_syn_attr \
test_syntax \
test_system \
test_tab \
test_tabline \
test_tabpage \
test_tagcase \
+3 -3
View File
@@ -9387,7 +9387,7 @@ ins_bs(
if (p_sta && in_indent)
want_vcol = (want_vcol / curbuf->b_p_sw) * curbuf->b_p_sw;
else
want_vcol = tabstop_start(want_vcol, curbuf->b_p_sts,
want_vcol = tabstop_start(want_vcol, get_sts_value(),
curbuf->b_p_vsts_array);
#else
want_vcol = (want_vcol / ts) * ts;
@@ -10236,9 +10236,9 @@ ins_tab(void)
temp = (int)curbuf->b_p_sw;
temp -= get_nolist_virtcol() % temp;
}
else if (tabstop_count(curbuf->b_p_vsts_array) > 0 || curbuf->b_p_sts > 0)
else if (tabstop_count(curbuf->b_p_vsts_array) > 0 || curbuf->b_p_sts != 0)
/* use 'softtabstop' when set */
temp = tabstop_padding(get_nolist_virtcol(), curbuf->b_p_sts,
temp = tabstop_padding(get_nolist_virtcol(), get_sts_value(),
curbuf->b_p_vsts_array);
else /* otherwise use 'tabstop' */
temp = tabstop_padding(get_nolist_virtcol(), curbuf->b_p_ts,
+1 -1
View File
@@ -6628,7 +6628,7 @@ f_has(typval_T *argvars, typval_T *rettv)
#endif
#ifdef FEAT_VTP
else if (STRICMP(name, "vcon") == 0)
n = has_vtp_working();
n = is_term_win32() && has_vtp_working();
#endif
#ifdef FEAT_NETBEANS_INTG
else if (STRICMP(name, "netbeans_enabled") == 0)
+15 -5
View File
@@ -398,6 +398,7 @@ ex_sort(exarg_T *eap)
colnr_T end_col;
int sort_what = 0;
int format_found = 0;
int change_occurred = FALSE; // Buffer contents changed.
/* Sorting one line is really quick! */
if (count <= 1)
@@ -616,12 +617,19 @@ ex_sort(exarg_T *eap)
lnum = eap->line2;
for (i = 0; i < count; ++i)
{
s = ml_get(nrs[eap->forceit ? count - i - 1 : i].lnum);
linenr_T get_lnum = nrs[eap->forceit ? count - i - 1 : i].lnum;
// If the original line number of the line being placed is not the same
// as "lnum" (accounting for offset), we know that the buffer changed.
if (get_lnum + ((linenr_T)count - 1) != lnum)
change_occurred = TRUE;
s = ml_get(get_lnum);
if (!unique || i == 0
|| (sort_ic ? STRICMP(s, sortbuf1) : STRCMP(s, sortbuf1)) != 0)
{
/* Copy the line into a buffer, it may become invalid in
* ml_append(). And it's needed for "unique". */
// Copy the line into a buffer, it may become invalid in
// ml_append(). And it's needed for "unique".
STRCPY(sortbuf1, s);
if (ml_append(lnum++, sortbuf1, (colnr_T)0, FALSE) == FAIL)
break;
@@ -644,7 +652,9 @@ ex_sort(exarg_T *eap)
mark_adjust(eap->line2 - deleted, eap->line2, (long)MAXLNUM, -deleted);
else if (deleted < 0)
mark_adjust(eap->line2, MAXLNUM, -deleted, 0L);
changed_lines(eap->line1, 0, eap->line2 + 1, -deleted);
if (change_occurred || deleted != 0)
changed_lines(eap->line1, 0, eap->line2 + 1, -deleted);
curwin->w_cursor.lnum = eap->line1;
beginline(BL_WHITE | BL_FIX);
@@ -856,7 +866,6 @@ ex_retab(exarg_T *eap)
{
set_string_option_direct((char_u *)"vts", -1, new_ts_str,
OPT_FREE|OPT_LOCAL, 0);
vim_free(new_ts_str);
curbuf->b_p_vts_array = new_vts_array;
vim_free(old_vts_ary);
}
@@ -867,6 +876,7 @@ ex_retab(exarg_T *eap)
curbuf->b_p_ts = tabstop_first(new_vts_array);
vim_free(new_vts_array);
}
vim_free(new_ts_str);
}
#else
curbuf->b_p_ts = new_ts;
+1 -1
View File
@@ -1419,7 +1419,7 @@ check_due_timer(void)
bevalexpr_due_set = FALSE;
if (balloonEval == NULL)
{
balloonEval = (BalloonEval *)alloc(sizeof(BalloonEval));
balloonEval = (BalloonEval *)alloc_clear(sizeof(BalloonEval));
balloonEvalForTerm = TRUE;
}
if (balloonEval != NULL)
+5
View File
@@ -745,7 +745,12 @@ gui_init(void)
/* Always create the Balloon Evaluation area, but disable it when
* 'ballooneval' is off. */
if (balloonEval != NULL)
{
# ifdef FEAT_VARTABS
vim_free(balloonEval->vts);
# endif
vim_free(balloonEval);
}
balloonEvalForTerm = FALSE;
# ifdef FEAT_GUI_GTK
balloonEval = gui_mch_create_beval_area(gui.drawarea, NULL,
+1 -10
View File
@@ -111,28 +111,19 @@ gui_mch_create_beval_area(
return NULL;
}
beval = (BalloonEval *)alloc(sizeof(BalloonEval));
beval = (BalloonEval *)alloc_clear(sizeof(BalloonEval));
if (beval != NULL)
{
#ifdef FEAT_GUI_GTK
beval->target = GTK_WIDGET(target);
beval->balloonShell = NULL;
beval->timerID = 0;
#else
beval->target = (Widget)target;
beval->balloonShell = NULL;
beval->timerID = (XtIntervalId)NULL;
beval->appContext = XtWidgetToApplicationContext((Widget)target);
#endif
beval->showState = ShS_NEUTRAL;
beval->x = 0;
beval->y = 0;
beval->msg = mesg;
beval->msgCB = mesgCB;
beval->clientData = clientData;
#ifdef FEAT_VARTABS
beval->vts = NULL;
#endif
/*
* Set up event handler which will keep its eyes on the pointer,
+1 -8
View File
@@ -8922,28 +8922,21 @@ gui_mch_create_beval_area(
return NULL;
}
beval = (BalloonEval *)alloc(sizeof(BalloonEval));
beval = (BalloonEval *)alloc_clear(sizeof(BalloonEval));
if (beval != NULL)
{
beval->target = s_textArea;
beval->balloon = NULL;
beval->showState = ShS_NEUTRAL;
beval->x = 0;
beval->y = 0;
beval->msg = mesg;
beval->msgCB = mesgCB;
beval->clientData = clientData;
#ifdef FEAT_VARTABS
beval->vts = NULL;
#endif
InitCommonControls();
cur_beval = beval;
if (p_beval)
gui_mch_enable_beval_area(beval);
}
return beval;
}
+238 -27
View File
@@ -28,10 +28,16 @@ typedef buf_T *luaV_Buffer;
typedef win_T *luaV_Window;
typedef dict_T *luaV_Dict;
typedef list_T *luaV_List;
typedef struct {
typval_T tv; // funcref
typval_T args;
dict_T *self; // selfdict
} luaV_Funcref;
typedef void (*msgfunc_T)(char_u *);
static const char LUAVIM_DICT[] = "dict";
static const char LUAVIM_LIST[] = "list";
static const char LUAVIM_FUNCREF[] = "funcref";
static const char LUAVIM_BUFFER[] = "buffer";
static const char LUAVIM_WINDOW[] = "window";
static const char LUAVIM_FREE[] = "luaV_free";
@@ -55,9 +61,15 @@ static const char LUAVIM_SETREF[] = "luaV_setref";
if (sandbox) luaL_error((L), "not allowed in sandbox")
#define luaV_msg(L) luaV_msgfunc((L), (msgfunc_T) msg)
#define luaV_emsg(L) luaV_msgfunc((L), (msgfunc_T) emsg)
#define luaV_checktypval(L, a, v, msg) \
do { \
if (luaV_totypval(L, a, v) == FAIL) \
luaL_error(L, msg ": cannot convert value"); \
} while (0)
static luaV_List *luaV_pushlist (lua_State *L, list_T *lis);
static luaV_Dict *luaV_pushdict (lua_State *L, dict_T *dic);
static luaV_List *luaV_pushlist(lua_State *L, list_T *lis);
static luaV_Dict *luaV_pushdict(lua_State *L, dict_T *dic);
static luaV_Funcref *luaV_pushfuncref(lua_State *L, typval_T *tv);
#if LUA_VERSION_NUM <= 501
#define luaV_openlib(L, l, n) luaL_openlib(L, NULL, l, n)
@@ -506,16 +518,25 @@ luaV_pushtypval(lua_State *L, typval_T *tv)
else
lua_pushnil(L);
break;
case VAR_FUNC:
luaV_pushfuncref(L, tv);
break;
default:
lua_pushnil(L);
}
}
/* converts lua value at 'pos' to typval 'tv' */
static void
luaV_totypval (lua_State *L, int pos, typval_T *tv)
/*
* Converts lua value at 'pos' to typval 'tv'.
* Returns OK or FAIL.
*/
static int
luaV_totypval(lua_State *L, int pos, typval_T *tv)
{
switch(lua_type(L, pos)) {
int status = OK;
switch (lua_type(L, pos))
{
case LUA_TBOOLEAN:
tv->v_type = VAR_SPECIAL;
tv->vval.v_number = (varnumber_T) lua_toboolean(L, pos);
@@ -533,8 +554,10 @@ luaV_totypval (lua_State *L, int pos, typval_T *tv)
tv->vval.v_number = (varnumber_T) lua_tointeger(L, pos);
#endif
break;
case LUA_TUSERDATA: {
case LUA_TUSERDATA:
{
void *p = lua_touserdata(L, pos);
if (lua_getmetatable(L, pos)) /* has metatable? */
{
/* check list */
@@ -545,7 +568,7 @@ luaV_totypval (lua_State *L, int pos, typval_T *tv)
tv->vval.v_list = *((luaV_List *) p);
++tv->vval.v_list->lv_refcount;
lua_pop(L, 2); /* MTs */
return;
break;
}
/* check dict */
luaV_getfield(L, LUAVIM_DICT);
@@ -555,16 +578,27 @@ luaV_totypval (lua_State *L, int pos, typval_T *tv)
tv->vval.v_dict = *((luaV_Dict *) p);
++tv->vval.v_dict->dv_refcount;
lua_pop(L, 3); /* MTs */
return;
break;
}
lua_pop(L, 3); /* MTs */
/* check funcref */
luaV_getfield(L, LUAVIM_FUNCREF);
if (lua_rawequal(L, -1, -4))
{
luaV_Funcref *f = (luaV_Funcref *) p;
copy_tv(&f->tv, tv);
lua_pop(L, 4); /* MTs */
break;
}
lua_pop(L, 4); /* MTs */
}
break;
}
/* FALLTHROUGH */
default:
tv->v_type = VAR_NUMBER;
tv->vval.v_number = 0;
status = FAIL;
}
return status;
}
/* similar to luaL_addlstring, but replaces \0 with \n if toline and
@@ -646,7 +680,7 @@ luaV_msgfunc(lua_State *L, msgfunc_T mf)
#define luaV_pushtype(typ,tname,luatyp) \
static luatyp * \
luaV_push##tname (lua_State *L, typ *obj) \
luaV_push##tname(lua_State *L, typ *obj) \
{ \
luatyp *o = NULL; \
if (obj == NULL) \
@@ -766,7 +800,7 @@ luaV_list_newindex (lua_State *L)
else
{
typval_T v;
luaV_totypval(L, 3, &v);
luaV_checktypval(L, 3, &v, "setting list item");
clear_tv(&li->li_tv);
copy_tv(&v, &li->li_tv);
clear_tv(&v);
@@ -783,11 +817,11 @@ luaV_list_add (lua_State *L)
if (l->lv_lock)
luaL_error(L, "list is locked");
lua_settop(L, 2);
luaV_totypval(L, 2, &v);
luaV_checktypval(L, 2, &v, "adding list item");
if (list_append_tv(l, &v) == FAIL)
{
clear_tv(&v);
luaL_error(L, "Failed to add item to list");
luaL_error(L, "failed to add item to list");
}
clear_tv(&v);
lua_settop(L, 1);
@@ -811,11 +845,11 @@ luaV_list_insert (lua_State *L)
luaL_error(L, "invalid position");
}
lua_settop(L, 2);
luaV_totypval(L, 2, &v);
luaV_checktypval(L, 2, &v, "inserting list item");
if (list_insert_tv(l, &v, li) == FAIL)
{
clear_tv(&v);
luaL_error(L, "Failed to add item to list");
luaL_error(L, "failed to add item to list");
}
clear_tv(&v);
lua_settop(L, 1);
@@ -894,26 +928,43 @@ luaV_dict_call (lua_State *L)
}
static int
luaV_dict_index (lua_State *L)
luaV_dict_index(lua_State *L)
{
dict_T *d = luaV_unbox(L, luaV_Dict, 1);
char_u *key = (char_u *) luaL_checkstring(L, 2);
dictitem_T *di = dict_find(d, key, -1);
if (di == NULL)
lua_pushnil(L);
else
{
luaV_pushtypval(L, &di->di_tv);
if (di->di_tv.v_type == VAR_FUNC) /* funcref? */
{
luaV_Funcref *f = (luaV_Funcref *) lua_touserdata(L, -1);
f->self = d; /* keep "self" reference */
d->dv_refcount++;
}
}
return 1;
}
static int
luaV_dict_newindex (lua_State *L)
luaV_dict_newindex(lua_State *L)
{
dict_T *d = luaV_unbox(L, luaV_Dict, 1);
char_u *key = (char_u *) luaL_checkstring(L, 2);
dictitem_T *di;
typval_T v;
if (d->dv_lock)
luaL_error(L, "dict is locked");
if (key != NULL && *key == NUL)
luaL_error(L, "empty key");
if (!lua_isnil(L, 3)) { /* read value? */
luaV_checktypval(L, 3, &v, "setting dict item");
if (d->dv_scope == VAR_DEF_SCOPE && v.v_type == VAR_FUNC)
luaL_error(L, "cannot assign funcref to builtin scope");
}
di = dict_find(d, key, -1);
if (di == NULL) /* non-existing key? */
{
@@ -934,9 +985,8 @@ luaV_dict_newindex (lua_State *L)
hash_remove(&d->dv_hashtab, hi);
dictitem_free(di);
}
else {
typval_T v;
luaV_totypval(L, 3, &v);
else
{
copy_tv(&v, &di->di_tv);
clear_tv(&v);
}
@@ -953,6 +1003,92 @@ static const luaL_Reg luaV_Dict_mt[] = {
};
/* ======= Funcref type ======= */
static luaV_Funcref *
luaV_newfuncref(lua_State *L, char_u *name)
{
luaV_Funcref *f = (luaV_Funcref *)lua_newuserdata(L, sizeof(luaV_Funcref));
if (name != NULL)
{
func_ref(name); /* as in copy_tv */
f->tv.vval.v_string = vim_strsave(name);
}
f->tv.v_type = VAR_FUNC;
f->args.v_type = VAR_LIST;
f->self = NULL;
luaV_getfield(L, LUAVIM_FUNCREF);
lua_setmetatable(L, -2);
return f;
}
static luaV_Funcref *
luaV_pushfuncref(lua_State *L, typval_T *tv)
{
luaV_Funcref *f = luaV_newfuncref(L, NULL);
copy_tv(tv, &f->tv);
clear_tv(tv);
return f;
}
luaV_type_tostring(funcref, LUAVIM_FUNCREF)
static int
luaV_funcref_gc(lua_State *L)
{
luaV_Funcref *f = (luaV_Funcref *) lua_touserdata(L, 1);
func_unref(f->tv.vval.v_string);
vim_free(f->tv.vval.v_string);
dict_unref(f->self);
return 0;
}
/* equivalent to string(funcref) */
static int
luaV_funcref_len(lua_State *L)
{
luaV_Funcref *f = (luaV_Funcref *) lua_touserdata(L, 1);
lua_pushstring(L, (const char *) f->tv.vval.v_string);
return 1;
}
static int
luaV_funcref_call(lua_State *L)
{
luaV_Funcref *f = (luaV_Funcref *) lua_touserdata(L, 1);
int i, n = lua_gettop(L) - 1; /* #args */
int status;
typval_T v, rettv;
f->args.vval.v_list = list_alloc();
rettv.v_type = VAR_UNKNOWN; /* as in clear_tv */
for (i = 0; i < n; i++) {
luaV_checktypval(L, i + 2, &v, "calling funcref");
list_append_tv(f->args.vval.v_list, &v);
}
status = func_call(f->tv.vval.v_string, &f->args, NULL, f->self, &rettv);
if (status == OK)
luaV_pushtypval(L, &rettv);
clear_tv(&f->args);
clear_tv(&rettv);
if (status != OK)
luaL_error(L, "cannot call funcref");
return 1;
}
static const luaL_Reg luaV_Funcref_mt[] = {
{"__tostring", luaV_funcref_tostring},
{"__gc", luaV_funcref_gc},
{"__len", luaV_funcref_len},
{"__call", luaV_funcref_call},
{NULL, NULL}
};
/* ======= Buffer type ======= */
luaV_newtype(buf_T, buffer, luaV_Buffer, LUAVIM_BUFFER)
@@ -1033,7 +1169,8 @@ luaV_buffer_newindex(lua_State *L)
curbuf = buf;
luaL_error(L, "cannot delete line");
}
else {
else
{
deleted_lines_mark(n, 1L);
if (b == curwin->w_buffer) /* fix cursor in current window? */
{
@@ -1371,22 +1508,84 @@ luaV_line(lua_State *L)
static int
luaV_list(lua_State *L)
{
list_T *l = list_alloc();
list_T *l;
int initarg = !lua_isnoneornil(L, 1);
if (initarg && lua_type(L, 1) != LUA_TTABLE)
luaL_error(L, "table expected, got %s", luaL_typename(L, 1));
l = list_alloc();
if (l == NULL)
lua_pushnil(L);
else
{
luaV_newlist(L, l);
if (initarg) { /* traverse table to init dict */
int notnil, i = 0;
typval_T v;
do {
lua_rawgeti(L, 1, ++i);
notnil = !lua_isnil(L, -1);
if (notnil) {
luaV_checktypval(L, -1, &v, "vim.list");
list_append_tv(l, &v);
}
lua_pop(L, 1); /* value */
} while (notnil);
}
}
return 1;
}
static int
luaV_dict(lua_State *L)
{
dict_T *d = dict_alloc();
dict_T *d;
int initarg = !lua_isnoneornil(L, 1);
if (initarg && lua_type(L, 1) != LUA_TTABLE)
luaL_error(L, "table expected, got %s", luaL_typename(L, 1));
d = dict_alloc();
if (d == NULL)
lua_pushnil(L);
else
{
luaV_newdict(L, d);
if (initarg) /* traverse table to init dict */
{
lua_pushnil(L);
while (lua_next(L, 1))
{
char_u *key;
dictitem_T *di;
typval_T v;
lua_pushvalue(L, -2); /* dup key in case it's a number */
key = (char_u *) lua_tostring(L, -1);
if (key != NULL && *key == NUL)
luaL_error(L, "table has empty key");
luaV_checktypval(L, -2, &v, "vim.dict"); /* value */
di = dictitem_alloc(key);
if (di == NULL || dict_add(d, di) == FAIL) {
vim_free(di);
lua_pushnil(L);
return 1;
}
copy_tv(&v, &di->di_tv);
clear_tv(&v);
lua_pop(L, 2); /* key copy and value */
}
}
}
return 1;
}
static int
luaV_funcref(lua_State *L)
{
const char *name = luaL_checkstring(L, 1);
/* note: not checking if function exists (needs function_exists) */
if (name == NULL || *name == NUL || VIM_ISDIGIT(*name))
luaL_error(L, "invalid function name: %s", name);
luaV_newfuncref(L, (char_u *) name);
return 1;
}
@@ -1402,7 +1601,8 @@ luaV_buffer(lua_State *L)
FOR_ALL_BUFFERS(buf)
if (buf->b_fnum == n) break;
}
else { /* by name */
else // by name
{
size_t l;
const char *s = lua_tolstring(L, 1, &l);
FOR_ALL_BUFFERS(buf)
@@ -1472,6 +1672,12 @@ luaV_type(lua_State *L)
lua_pushstring(L, "dict");
return 1;
}
luaV_getfield(L, LUAVIM_FUNCREF);
if (lua_rawequal(L, -1, 2))
{
lua_pushstring(L, "funcref");
return 1;
}
luaV_getfield(L, LUAVIM_BUFFER);
if (lua_rawequal(L, -1, 2))
{
@@ -1497,6 +1703,7 @@ static const luaL_Reg luaV_module[] = {
{"line", luaV_line},
{"list", luaV_list},
{"dict", luaV_dict},
{"funcref", luaV_funcref},
{"buffer", luaV_buffer},
{"window", luaV_window},
{"open", luaV_open},
@@ -1537,7 +1744,8 @@ luaV_luaeval (lua_State *L)
luaV_emsg(L);
return 0;
}
luaV_totypval(L, -1, rettv);
if (luaV_totypval(L, -1, rettv) == FAIL)
EMSG("luaeval: cannot convert value");
return 0;
}
@@ -1612,6 +1820,9 @@ luaopen_vim(lua_State *L)
luaV_newmetatable(L, LUAVIM_DICT);
lua_pushvalue(L, 1);
luaV_openlib(L, luaV_Dict_mt, 1);
luaV_newmetatable(L, LUAVIM_FUNCREF);
lua_pushvalue(L, 1);
luaV_openlib(L, luaV_Funcref_mt, 1);
luaV_newmetatable(L, LUAVIM_BUFFER);
lua_pushvalue(L, 1); /* cache table */
luaV_openlib(L, luaV_Buffer_mt, 1);
+2 -2
View File
@@ -14,9 +14,9 @@
*/
/*
* PCHAR(lp, c) - put character 'c' at position 'lp'
* PBYTE(lp, c) - put byte 'c' at position 'lp'
*/
#define PCHAR(lp, c) (*(ml_get_buf(curbuf, (lp).lnum, TRUE) + (lp).col) = (c))
#define PBYTE(lp, c) (*(ml_get_buf(curbuf, (lp).lnum, TRUE) + (lp).col) = (c))
/*
* Position comparisons
+18
View File
@@ -399,6 +399,20 @@ smsg_attr(int attr, char_u *s, ...)
return msg_attr(IObuff, attr);
}
int
# ifdef __BORLANDC__
_RTLENTRYF
# endif
smsg_attr_keep(int attr, char_u *s, ...)
{
va_list arglist;
va_start(arglist, s);
vim_vsnprintf((char *)IObuff, IOSIZE, (char *)s, arglist);
va_end(arglist);
return msg_attr_keep(IObuff, attr, TRUE);
}
#endif
/*
@@ -982,7 +996,11 @@ ex_messages(exarg_T *eap)
{
s = mch_getenv((char_u *)"LANG");
if (s != NULL && *s != NUL)
// The next comment is extracted by xgettext and put in po file for
// translators to read.
msg_attr((char_u *)
// Translator: Please replace the name and email address
// with the appropriate text for your translation.
_("Messages maintainer: Bram Moolenaar <Bram@vim.org>"),
HL_ATTR(HLF_T));
}
+2 -2
View File
@@ -3387,8 +3387,8 @@ same_directory(char_u *f1, char_u *f2)
&& pathcmp((char *)ffname, (char *)f2, (int)(t1 - ffname)) == 0);
}
#if defined(FEAT_SESSION) || defined(MSWIN) || defined(FEAT_GUI_MAC) \
|| defined(FEAT_GUI_GTK) \
#if defined(FEAT_SESSION) || defined(FEAT_AUTOCHDIR) \
|| defined(MSWIN) || defined(FEAT_GUI_MAC) || defined(FEAT_GUI_GTK) \
|| defined(FEAT_SUN_WORKSHOP) || defined(FEAT_NETBEANS_INTG) \
|| defined(PROTO)
/*
Executable
+6
View File
@@ -0,0 +1,6 @@
@echo off
rem To be used on MS-Windows for Msys2 with the 32 bit MinGW compiler.
rem Adjust the "c:\msys64" part to match your installation.
@echo on
set PATH=c:\msys64\mingw32\bin;c:\msys64\usr\bin;%PATH%
Executable
+6
View File
@@ -0,0 +1,6 @@
@echo off
rem To be used on MS-Windows for Msys2 with the 64 bit MinGW compiler.
rem Adjust the "c:\msys64" part to match your installation.
@echo on
set PATH=c:\msys64\mingw64\bin;c:\msys64\usr\bin;%PATH%
+34 -14
View File
@@ -2146,6 +2146,25 @@ mb_adjust_opend(oparg_T *oap)
#endif
#if defined(FEAT_VISUALEXTRA) || defined(PROTO)
# ifdef FEAT_MBYTE
/*
* Replace the character under the cursor with "c".
* This takes care of multi-byte characters.
*/
static void
replace_character(int c)
{
int n = State;
State = REPLACE;
ins_char(c);
State = n;
/* Backup to the replaced character. */
dec_cursor();
}
# endif
/*
* Replace a whole area with one character.
*/
@@ -2331,12 +2350,7 @@ op_replace(oparg_T *oap, int c)
* with a multi-byte and the other way around. */
if (curwin->w_cursor.lnum == oap->end.lnum)
oap->end.col += (*mb_char2len)(c) - (*mb_char2len)(n);
n = State;
State = REPLACE;
ins_char(c);
State = n;
/* Backup to the replaced character. */
dec_cursor();
replace_character(c);
}
else
#endif
@@ -2358,7 +2372,7 @@ op_replace(oparg_T *oap, int c)
getvpos(&oap->end, end_vcol);
}
#endif
PCHAR(curwin->w_cursor, c);
PBYTE(curwin->w_cursor, c);
}
}
#ifdef FEAT_VIRTUALEDIT
@@ -2377,9 +2391,14 @@ op_replace(oparg_T *oap, int c)
curwin->w_cursor.col -= (virtcols + 1);
for (; virtcols >= 0; virtcols--)
{
PCHAR(curwin->w_cursor, c);
if (inc(&curwin->w_cursor) == -1)
break;
#ifdef FEAT_MBYTE
if ((*mb_char2len)(c) > 1)
replace_character(c);
else
#endif
PBYTE(curwin->w_cursor, c);
if (inc(&curwin->w_cursor) == -1)
break;
}
}
#endif
@@ -2619,7 +2638,7 @@ swapchar(int op_type, pos_T *pos)
}
else
#endif
PCHAR(*pos, nc);
PBYTE(*pos, nc);
return TRUE;
}
return FALSE;
@@ -3551,9 +3570,10 @@ do_put(
return;
}
/* Autocommands may be executed when saving lines for undo, which may make
* y_array invalid. Start undo now to avoid that. */
u_save(curwin->w_cursor.lnum, curwin->w_cursor.lnum + 1);
/* Autocommands may be executed when saving lines for undo. This might
* make "y_array" invalid, so we start undo now to avoid that. */
if (u_save(curwin->w_cursor.lnum, curwin->w_cursor.lnum + 1) == FAIL)
goto end;
if (insert_string != NULL)
{
+9 -4
View File
@@ -8990,10 +8990,13 @@ set_bool_option(
# endif
highlight_gui_started();
# ifdef FEAT_VTP
control_console_color_rgb();
/* reset t_Co */
if (is_term_win32())
{
control_console_color_rgb();
set_termname(T_NAME);
init_highlight(TRUE, FALSE);
}
# endif
}
#endif
@@ -13083,7 +13086,7 @@ tabstop_start(colnr_T col, int ts, int *vts)
tabstop_fromto(
colnr_T start_col,
colnr_T end_col,
int ts,
int ts_arg,
int *vts,
int *ntabs,
int *nspcs)
@@ -13093,12 +13096,14 @@ tabstop_fromto(
int padding = 0;
int tabcount;
int t;
int ts = ts_arg == 0 ? curbuf->b_p_ts : ts_arg;
if (vts == NULL || vts[0] == 0)
{
int tabs = 0;
int initspc = ts - (start_col % ts);
int initspc = 0;
initspc = ts - (start_col % ts);
if (spaces >= initspc)
{
spaces -= initspc;
@@ -13227,7 +13232,7 @@ get_sw_value(buf_T *buf)
/*
* Return the effective softtabstop value for the current buffer, using the
* 'tabstop' value when 'softtabstop' is negative.
* 'shiftwidth' value when 'softtabstop' is negative.
*/
long
get_sts_value(void)
+6
View File
@@ -115,6 +115,12 @@ _RTLENTRYF
# endif
smsg_attr(int, char_u *, ...);
int
# ifdef __BORLANDC__
_RTLENTRYF
# endif
smsg_attr_keep(int, char_u *, ...);
int
# ifdef __BORLANDC__
_RTLENTRYF
+9 -4
View File
@@ -4757,13 +4757,13 @@ win_line(
n_extra = win_lbr_chartabsize(wp, line, p, (colnr_T)vcol,
NULL) - 1;
if (c == TAB && n_extra + col > wp->w_width)
#ifdef FEAT_VARTABS
# ifdef FEAT_VARTABS
n_extra = tabstop_padding(vcol, wp->w_buffer->b_p_ts,
wp->w_buffer->b_p_vts_array) - 1;
#else
wp->w_buffer->b_p_vts_array) - 1;
# else
n_extra = (int)wp->w_buffer->b_p_ts
- vcol % (int)wp->w_buffer->b_p_ts - 1;
#endif
# endif
# ifdef FEAT_MBYTE
c_extra = mb_off > 0 ? MB_FILLER_CHAR : ' ';
@@ -4906,6 +4906,11 @@ win_line(
p_extra_free = p;
for (i = 0; i < tab_len; i++)
{
if (*p == NUL)
{
tab_len = i;
break;
}
#ifdef FEAT_MBYTE
mb_char2bytes(lcs_tab2, p);
p += mb_char2len(lcs_tab2);
+1
View File
@@ -1345,6 +1345,7 @@ typedef struct
garray_T uf_lines; /* function lines */
#ifdef FEAT_PROFILE
int uf_profiling; /* TRUE when func is being profiled */
int uf_prof_initialized;
/* profiling the function as a whole */
int uf_tm_count; /* nr of calls */
proftime_T uf_tm_total; /* time spent in function + children */
+18 -3
View File
@@ -2595,7 +2595,6 @@ findtag_end:
}
static garray_T tag_fnames = GA_EMPTY;
static void found_tagfile_cb(char_u *fname, void *cookie);
/*
* Callback function for finding all "tags" and "tags-??" files in
@@ -2605,8 +2604,15 @@ static void found_tagfile_cb(char_u *fname, void *cookie);
found_tagfile_cb(char_u *fname, void *cookie UNUSED)
{
if (ga_grow(&tag_fnames, 1) == OK)
((char_u **)(tag_fnames.ga_data))[tag_fnames.ga_len++] =
vim_strsave(fname);
{
char_u *tag_fname = vim_strsave(fname);
#ifdef BACKSLASH_IN_FILENAME
slash_adjust(tag_fname);
#endif
simplify_filename(tag_fname);
((char_u **)(tag_fnames.ga_data))[tag_fnames.ga_len++] = tag_fname;
}
}
#if defined(EXITFREE) || defined(PROTO)
@@ -2638,6 +2644,7 @@ get_tagfname(
{
char_u *fname = NULL;
char_u *r_ptr;
int i;
if (first)
vim_memset(tnp, 0, sizeof(tagname_T));
@@ -2679,6 +2686,14 @@ get_tagfname(
++tnp->tn_hf_idx;
STRCPY(buf, p_hf);
STRCPY(gettail(buf), "tags");
#ifdef BACKSLASH_IN_FILENAME
slash_adjust(buf);
#endif
simplify_filename(buf);
for (i = 0; i < tag_fnames.ga_len; ++i)
if (STRCMP(buf, ((char_u **)(tag_fnames.ga_data))[i]) == 0)
return FAIL; // avoid duplicate file names
}
else
vim_strncpy(buf, ((char_u **)(tag_fnames.ga_data))[
+5
View File
@@ -4696,6 +4696,11 @@ check_termcode(
&& STRNCMP(tp + extra - 2, "0;115;0c", 8) == 0)
is_not_xterm = TRUE;
// Xterm first responded to this request at patch level
// 95, so assume anything below 95 is not xterm.
if (version < 95)
is_not_xterm = TRUE;
/* Only request the cursor style if t_SH and t_RS are
* set. Only supported properly by xterm since version
* 279 (otherwise it returns 0x18).
-1
View File
@@ -36,7 +36,6 @@ SCRIPTS_ALL = \
SCRIPTS_MORE1 = \
test11.out \
test52.out \
test85.out \
test86.out \
test87.out
-1
View File
@@ -14,7 +14,6 @@ include Make_all.mak
# test10 'errorformat' is different
# test11 "cat" doesn't work properly
# test52 only for Win32
# test85 no Lua interface
# test86, 87 no Python interface
SCRIPTS = $(SCRIPTS_ALL) $(SCRIPTS_MORE4)
+3 -8
View File
@@ -93,7 +93,6 @@ SCRIPT = test1.out test3.out \
#
# test72: bug - Vim hangs at :rename (while rename works well otherwise)
# test78: bug - Vim dies at :recover Xtest
# test85: no Lua interface
# test89: bug - findfile() does not work on VMS (just in the current directory)
# test102: Just ODS-5 supports space and special chars in the filename.
# On ODS-2 tests fail.
@@ -119,9 +118,9 @@ SCRIPT_SPELL = test59.out
SCRIPT_MZSCH = test70.out
.ENDIF
.IFDEF HAVE_ODS5
SCRIPT_ODS5 = test102.out
.ENDIF
.IFDEF HAVE_ODS5
SCRIPT_ODS5 = test102.out
.ENDIF
.IFDEF HAVE_GZIP
SCRIPT_GZIP = test11.out
@@ -131,10 +130,6 @@ SCRIPT_GZIP = test11.out
SCRIPT_GDIFF = test47.out
.ENDIF
.IFDEF HAVE_LUA
SCRIPT_LUA = test85.out
.ENDIF
.IFDEF HAVE_PYTHON
SCRIPT_PYTHON = test86.out test87.out
.ENDIF
-86
View File
@@ -1,86 +0,0 @@
Test for Lua interface and luaeval() function
STARTTEST
:so small.vim
:set belloff=all
:so lua.vim
:set nocompatible viminfo+=nviminfo
:lua l = vim.list():add"item0":add"dictionary with list OK":add"item2"
:lua h = vim.dict(); h.list = l
:call garbagecollect()
/^1
:" change buffer contents
:lua curbuf = vim.buffer()
:lua curline = vim.eval"line('.')"
:lua curbuf[curline] = "1 changed line 1"
:" scalar test
:let tmp_string = luaeval('"string"')
:let tmp_1000 = luaeval('1000')
:if printf("%s%.0f", tmp_string, tmp_1000) == "string1000"
:let scalar_res = "OK"
:else
:let scalar_res = "FAILED"
:endif
:call append(search("^1"), "scalar test " . scalar_res)
:" dictionary containing a list
:let tmp = luaeval("h").list[1]
:/^2/put =tmp
:" circular list (at the same time test lists containing lists)
:lua l[2] = l
:let l2 = luaeval("h").list
:if l2[2] == l2
:let res = "OK"
:else
:let res = "FAILED"
:endif
:call setline(search("^3"), "circular test " . res)
:let l = []
:lua l = vim.eval("l")
:lua l:add(123)
:lua l:add("abc")
:lua l:add(vim.eval("[1, 2, 3]"))
:lua l:add(vim.eval("{'a':1, 'b':2, 'c':3}"))
:lua l:insert(123)
:lua l:insert("abc")
:lua l:insert(vim.eval("[1, 2, 3]"))
:lua l:insert(vim.eval("{'a':1, 'b':2, 'c':3}"))
:lua l[0] = l[0]
:lua l[1] = l[1]
:lua l[2] = l[2]
:lua l[3] = l[3]
:lua l[0] = 123
:lua l[1] = "abc"
:lua l[2] = vim.eval("[1, 2, 3]")
:lua l[3] = vim.eval("{'a':1, 'b':2, 'c':3}")
:lua l[3] = nil
:lua l[2] = nil
:lua l[1] = nil
:lua l[0] = nil
:lua l = nil
:$put =string(l)
:let d = {}
:lua d = vim.eval("d")
:lua d[0] = 123
:lua d[1] = "abc"
:lua d[2] = vim.eval("[1, 2, 3]")
:lua d[3] = vim.eval("{'a':1, 'b':2, 'c':3}")
:lua d[4] = d[0]
:lua d[5] = d[1]
:lua d[6] = d[2]
:lua d[7] = d[3]
:lua d[3] = nil
:lua d[2] = nil
:lua d[1] = nil
:lua d[0] = nil
:lua d = nil
:$put =string(d)
:?^1?,$w! test.out
:qa!
ENDTEST
1 line 1
2 line 2
3 line 3
+547 -9
View File
@@ -1,22 +1,560 @@
" Tests for Lua.
" TODO: move tests from test85.in here.
if !has('lua')
finish
endif
func Test_luado()
new
call setline(1, ['one', 'two', 'three'])
luado vim.command("%d_")
bwipe!
" Check switching to another buffer does not trigger ml_get error.
" Check that switching to another buffer does not trigger ml_get error.
func Test_command_new_no_ml_get_error()
new
let wincount = winnr('$')
call setline(1, ['one', 'two', 'three'])
luado vim.command("new")
call assert_equal(wincount + 1, winnr('$'))
bwipe!
%bwipe!
endfunc
" Test vim.command()
func Test_command()
new
call setline(1, ['one', 'two', 'three'])
luado vim.command("1,2d_")
call assert_equal(['three'], getline(1, '$'))
bwipe!
endfunc
" Test vim.eval()
func Test_eval()
" lua.eval with a number
lua v = vim.eval('123')
call assert_equal('number', luaeval('vim.type(v)'))
call assert_equal(123.0, luaeval('v'))
" lua.eval with a string
lua v = vim.eval('"abc"')
call assert_equal('string', luaeval('vim.type(v)'))
call assert_equal('abc', luaeval('v'))
" lua.eval with a list
lua v = vim.eval("['a']")
call assert_equal('list', luaeval('vim.type(v)'))
call assert_equal(['a'], luaeval('v'))
" lua.eval with a dict
lua v = vim.eval("{'a':'b'}")
call assert_equal('dict', luaeval('vim.type(v)'))
call assert_equal({'a':'b'}, luaeval('v'))
call assert_fails('lua v = vim.eval(nil)',
\ "[string \"vim chunk\"]:1: bad argument #1 to 'eval' (string expected, got nil)")
call assert_fails('lua v = vim.eval(true)',
\ "[string \"vim chunk\"]:1: bad argument #1 to 'eval' (string expected, got boolean)")
call assert_fails('lua v = vim.eval({})',
\ "[string \"vim chunk\"]:1: bad argument #1 to 'eval' (string expected, got table)")
call assert_fails('lua v = vim.eval(print)',
\ "[string \"vim chunk\"]:1: bad argument #1 to 'eval' (string expected, got function)")
call assert_fails('lua v = vim.eval(vim.buffer())',
\ "[string \"vim chunk\"]:1: bad argument #1 to 'eval' (string expected, got userdata)")
lua v = nil
endfunc
" Test vim.window()
func Test_window()
e Xfoo2
new Xfoo1
" Window 1 (top window) contains Xfoo1
" Window 2 (bottom window) contains Xfoo2
call assert_equal('Xfoo1', luaeval('vim.window(1):buffer().name'))
call assert_equal('Xfoo2', luaeval('vim.window(2):buffer().name'))
" Window 3 does not exist so vim.window(3) should return nil
call assert_equal('nil', luaeval('tostring(vim.window(3))'))
%bwipe!
endfunc
" Test vim.window().height
func Test_window_height()
new
lua vim.window().height = 2
call assert_equal(2, winheight(0))
lua vim.window().height = vim.window().height + 1
call assert_equal(3, winheight(0))
bwipe!
endfunc
" Test vim.window().width
func Test_window_width()
vert new
lua vim.window().width = 2
call assert_equal(2, winwidth(0))
lua vim.window().width = vim.window().width + 1
call assert_equal(3, winwidth(0))
bwipe!
endfunc
" Test vim.window().line and vim.window.col
func Test_window_line_col()
new
call setline(1, ['line1', 'line2', 'line3'])
lua vim.window().line = 2
lua vim.window().col = 4
call assert_equal([0, 2, 4, 0], getpos('.'))
lua vim.window().line = vim.window().line + 1
lua vim.window().col = vim.window().col - 1
call assert_equal([0, 3, 3, 0], getpos('.'))
call assert_fails('lua vim.window().line = 10',
\ '[string "vim chunk"]:1: line out of range')
bwipe!
endfunc
" Test setting the current window
func Test_window_set_current()
new Xfoo1
lua w1 = vim.window()
new Xfoo2
lua w2 = vim.window()
call assert_equal('Xfoo2', bufname('%'))
lua w1()
call assert_equal('Xfoo1', bufname('%'))
lua w2()
call assert_equal('Xfoo2', bufname('%'))
lua w1, w2 = nil
%bwipe!
endfunc
" Test vim.window().buffer
func Test_window_buffer()
new Xfoo1
lua w1 = vim.window()
lua b1 = w1.buffer()
new Xfoo2
lua w2 = vim.window()
lua b2 = w2.buffer()
lua b1()
call assert_equal('Xfoo1', bufname('%'))
lua b2()
call assert_equal('Xfoo2', bufname('%'))
lua b1, b2, w1, w2 = nil
%bwipe!
endfunc
" Test vim.window():previous() and vim.window():next()
func Test_window_next_previous()
new Xfoo1
new Xfoo2
new Xfoo3
wincmd j
call assert_equal('Xfoo2', luaeval('vim.window().buffer().name'))
call assert_equal('Xfoo1', luaeval('vim.window():next():buffer().name'))
call assert_equal('Xfoo3', luaeval('vim.window():previous():buffer().name'))
%bwipe!
endfunc
" Test vim.window():isvalid()
func Test_window_isvalid()
new Xfoo
lua w = vim.window()
call assert_true(luaeval('w:isvalid()'))
" FIXME: how to test the case when isvalid() returns v:false?
" isvalid() gives errors when the window is deleted. Is it a bug?
lua w = nil
bwipe!
endfunc
" Test vim.buffer() with and without argument
func Test_buffer()
new Xfoo1
let bn1 = bufnr('%')
new Xfoo2
let bn2 = bufnr('%')
" Test vim.buffer() without argument.
call assert_equal('Xfoo2', luaeval("vim.buffer().name"))
" Test vim.buffer() with string argument.
call assert_equal('Xfoo1', luaeval("vim.buffer('Xfoo1').name"))
call assert_equal('Xfoo2', luaeval("vim.buffer('Xfoo2').name"))
" Test vim.buffer() with integer argument.
call assert_equal('Xfoo1', luaeval("vim.buffer(" . bn1 . ").name"))
call assert_equal('Xfoo2', luaeval("vim.buffer(" . bn2 . ").name"))
lua bn1, bn2 = nil
%bwipe!
endfunc
" Test vim.buffer().name and vim.buffer().fname
func Test_buffer_name()
new
" FIXME: for an unnamed buffer, I would expect
" vim.buffer().name to give an empty string, but
" it returns 0. Is it a bug?
" so this assert_equal is commented out.
" call assert_equal('', luaeval('vim.buffer().name'))
bwipe!
new Xfoo
call assert_equal('Xfoo', luaeval('vim.buffer().name'))
call assert_equal(expand('%:p'), luaeval('vim.buffer().fname'))
bwipe!
endfunc
" Test vim.buffer().number
func Test_buffer_number()
" All numbers in Lua are floating points number (no integers).
call assert_equal(bufnr('%'), float2nr(luaeval('vim.buffer().number')))
endfunc
" Test inserting lines in buffer.
func Test_buffer_insert()
new
lua vim.buffer()[1] = '3'
lua vim.buffer():insert('1', 0)
lua vim.buffer():insert('2', 1)
lua vim.buffer():insert('4', 10)
call assert_equal(['1', '2', '3', '4'], getline(1, '$'))
bwipe!
endfunc
" Test deleting line in buffer
func Test_buffer_delete()
new
call setline(1, ['1', '2', '3'])
lua vim.buffer()[2] = nil
call assert_equal(['1', '3'], getline(1, '$'))
call assert_fails('lua vim.buffer()[3] = nil',
\ '[string "vim chunk"]:1: invalid line number')
bwipe!
endfunc
" Test #vim.buffer() i.e. number of lines in buffer
func Test_buffer_number_lines()
new
call setline(1, ['a', 'b', 'c'])
call assert_equal(3.0, luaeval('#vim.buffer()'))
bwipe!
endfunc
" Test vim.buffer():next() and vim.buffer():previous()
" Note that these functions get the next or previous buffers
" but do not switch buffer.
func Test_buffer_next_previous()
new Xfoo1
new Xfoo2
new Xfoo3
b Xfoo2
lua bn = vim.buffer():next()
lua bp = vim.buffer():previous()
call assert_equal('Xfoo2', luaeval('vim.buffer().name'))
call assert_equal('Xfoo1', luaeval('bp.name'))
call assert_equal('Xfoo3', luaeval('bn.name'))
call assert_equal('Xfoo2', bufname('%'))
lua bn()
call assert_equal('Xfoo3', luaeval('vim.buffer().name'))
call assert_equal('Xfoo3', bufname('%'))
lua bp()
call assert_equal('Xfoo1', luaeval('vim.buffer().name'))
call assert_equal('Xfoo1', bufname('%'))
lua bn, bp = nil
%bwipe!
endfunc
" Test vim.buffer():isvalid()
func Test_buffer_isvalid()
new Xfoo
lua b = vim.buffer()
call assert_true(luaeval('b:isvalid()'))
" FIXME: how to test the case when isvalid() returns v:false?
" isvalid() gives errors when the buffer is wiped. Is it a bug?
lua b = nil
bwipe!
endfunc
func Test_list()
call assert_equal([], luaeval('vim.list()'))
let l = []
lua l = vim.eval('l')
lua l:add(123)
lua l:add('abc')
lua l:add(true)
lua l:add(false)
lua l:add(vim.eval("[1, 2, 3]"))
lua l:add(vim.eval("{'a':1, 'b':2, 'c':3}"))
call assert_equal([123.0, 'abc', v:true, v:false, [1, 2, 3], {'a': 1, 'b': 2, 'c': 3}], l)
call assert_equal(6.0, luaeval('#l'))
call assert_match('^list: \%(0x\)\?\x\+$', luaeval('tostring(l)'))
lua l[0] = 124
lua l[4] = nil
lua l:insert('first')
lua l:insert('xx', 3)
call assert_equal(['first', 124.0, 'abc', 'xx', v:true, v:false, {'a': 1, 'b': 2, 'c': 3}], l)
lockvar 1 l
call assert_fails('lua l:add("x")', '[string "vim chunk"]:1: list is locked')
lua l = nil
endfunc
func Test_list_table()
" See :help lua-vim
" Non-numeric keys should not be used to initialize the list
" so say = 'hi' should be ignored.
lua t = {3.14, 'hello', false, true, say = 'hi'}
call assert_equal([3.14, 'hello', v:false, v:true], luaeval('vim.list(t)'))
lua t = nil
call assert_fails('lua vim.list(1)', '[string "vim chunk"]:1: table expected, got number')
call assert_fails('lua vim.list("x")', '[string "vim chunk"]:1: table expected, got string')
call assert_fails('lua vim.list(print)', '[string "vim chunk"]:1: table expected, got function')
call assert_fails('lua vim.list(true)', '[string "vim chunk"]:1: table expected, got boolean')
endfunc
" Test l() i.e. iterator on list
func Test_list_iter()
lua l = vim.list():add('foo'):add('bar')
lua str = ''
lua for v in l() do str = str .. v end
call assert_equal('foobar', luaeval('str'))
lua str, l = nil
endfunc
func Test_recursive_list()
lua l = vim.list():add(1):add(2)
lua l = l:add(l)
call assert_equal(1.0, luaeval('l[0]'))
call assert_equal(2.0, luaeval('l[1]'))
call assert_equal(1.0, luaeval('l[2][0]'))
call assert_equal(2.0, luaeval('l[2][1]'))
call assert_equal(1.0, luaeval('l[2][2][0]'))
call assert_equal(2.0, luaeval('l[2][2][1]'))
call assert_equal('[1.0, 2.0, [...]]', string(luaeval('l')))
call assert_match('^list: \%(0x\)\?\x\+$', luaeval('tostring(l)'))
call assert_equal(luaeval('tostring(l)'), luaeval('tostring(l[2])'))
call assert_equal(luaeval('l'), luaeval('l[2]'))
call assert_equal(luaeval('l'), luaeval('l[2][2]'))
lua l = nil
endfunc
func Test_dict()
call assert_equal({}, luaeval('vim.dict()'))
let d = {}
lua d = vim.eval('d')
lua d[0] = 123
lua d[1] = "abc"
lua d[2] = true
lua d[3] = false
lua d[4] = vim.eval("[1, 2, 3]")
lua d[5] = vim.eval("{'a':1, 'b':2, 'c':3}")
call assert_equal({'0':123.0, '1':'abc', '2':v:true, '3':v:false, '4': [1, 2, 3], '5': {'a':1, 'b':2, 'c':3}}, d)
call assert_equal(6.0, luaeval('#d'))
call assert_match('^dict: \%(0x\)\?\x\+$', luaeval('tostring(d)'))
call assert_equal('abc', luaeval('d[1]'))
lua d[0] = 124
lua d[4] = nil
call assert_equal({'0':124.0, '1':'abc', '2':v:true, '3':v:false, '5': {'a':1, 'b':2, 'c':3}}, d)
lockvar 1 d
call assert_fails('lua d[6] = 1', '[string "vim chunk"]:1: dict is locked')
lua d = nil
endfunc
func Test_dict_table()
lua t = {key1 = 'x', key2 = 3.14, key3 = true, key4 = false}
call assert_equal({'key1': 'x', 'key2': 3.14, 'key3': v:true, 'key4': v:false},
\ luaeval('vim.dict(t)'))
" Same example as in :help lua-vim.
lua t = {math.pi, false, say = 'hi'}
" FIXME: commented out as it currently does not work as documented:
" Expected {'say': 'hi'}
" but got {'1': 3.141593, '2': v:false, 'say': 'hi'}
" Is the documentation or the code wrong?
"call assert_equal({'say' : 'hi'}, luaeval('vim.dict(t)'))
lua t = nil
call assert_fails('lua vim.dict(1)', '[string "vim chunk"]:1: table expected, got number')
call assert_fails('lua vim.dict("x")', '[string "vim chunk"]:1: table expected, got string')
call assert_fails('lua vim.dict(print)', '[string "vim chunk"]:1: table expected, got function')
call assert_fails('lua vim.dict(true)', '[string "vim chunk"]:1: table expected, got boolean')
endfunc
" Test d() i.e. iterator on dictionary
func Test_dict_iter()
let d = {'a': 1, 'b':2}
lua d = vim.eval('d')
lua str = ''
lua for k,v in d() do str = str .. k ..':' .. v .. ',' end
call assert_equal('a:1,b:2,', luaeval('str'))
lua str, d = nil
endfunc
func Test_funcref()
function I(x)
return a:x
endfunction
let R = function('I')
lua i1 = vim.funcref"I"
lua i2 = vim.eval"R"
lua msg = "funcref|test|" .. (#i2(i1) == #i1(i2) and "OK" or "FAIL")
lua msg = vim.funcref"tr"(msg, "|", " ")
call assert_equal("funcref test OK", luaeval('msg'))
" dict funcref
function Mylen() dict
return len(self.data)
endfunction
let l = [0, 1, 2, 3]
let mydict = {'data': l}
lua d = vim.eval"mydict"
lua d.len = vim.funcref"Mylen" -- assign d as 'self'
lua res = (d.len() == vim.funcref"len"(vim.eval"l")) and "OK" or "FAIL"
call assert_equal("OK", luaeval('res'))
lua i1, i2, msg, d, res = nil
endfunc
" Test vim.type()
func Test_type()
" The following values are identical to Lua's type function.
call assert_equal('string', luaeval('vim.type("foo")'))
call assert_equal('number', luaeval('vim.type(1)'))
call assert_equal('number', luaeval('vim.type(1.2)'))
call assert_equal('function', luaeval('vim.type(print)'))
call assert_equal('table', luaeval('vim.type({})'))
call assert_equal('boolean', luaeval('vim.type(true)'))
call assert_equal('boolean', luaeval('vim.type(false)'))
call assert_equal('nil', luaeval('vim.type(nil)'))
" The following values are specific to Vim.
call assert_equal('window', luaeval('vim.type(vim.window())'))
call assert_equal('buffer', luaeval('vim.type(vim.buffer())'))
call assert_equal('list', luaeval('vim.type(vim.list())'))
call assert_equal('dict', luaeval('vim.type(vim.dict())'))
call assert_equal('funcref', luaeval('vim.type(vim.funcref("Test_type"))'))
endfunc
" Test vim.open()
func Test_open()
call assert_notmatch('XOpen', execute('ls'))
" Open a buffer XOpen1, but do not jump to it.
lua b = vim.open('XOpen1')
call assert_equal('XOpen1', luaeval('b.name'))
call assert_equal('', bufname('%'))
call assert_match('XOpen1', execute('ls'))
call assert_notequal('XOpen2', bufname('%'))
" Open a buffer XOpen2 and jump to it.
lua b = vim.open('XOpen2')()
call assert_equal('XOpen2', luaeval('b.name'))
call assert_equal('XOpen2', bufname('%'))
lua b = nil
%bwipe!
endfunc
" Test vim.line()
func Test_line()
new
call setline(1, ['first line', 'second line'])
1
call assert_equal('first line', luaeval('vim.line()'))
2
call assert_equal('second line', luaeval('vim.line()'))
bwipe!
endfunc
" Test vim.beep()
func Test_beep()
call assert_beeps('lua vim.beep()')
endfunc
" Test errors in luaeval()
func Test_luaeval_error()
" Compile error
call assert_fails("call luaeval('-nil')",
\ '[string "luaeval"]:1: attempt to perform arithmetic on a nil value')
call assert_fails("call luaeval(']')",
\ "[string \"luaeval\"]:1: unexpected symbol near ']'")
endfunc
" Test :luafile foo.lua
func Test_luafile()
call delete('Xlua_file')
call writefile(["str = 'hello'", "num = 123.0" ], 'Xlua_file')
call setfperm('Xlua_file', 'r-xr-xr-x')
luafile Xlua_file
call assert_equal('hello', luaeval('str'))
call assert_equal(123.0, luaeval('num'))
lua str, num = nil
call delete('Xlua_file')
endfunc
" Test :luafile %
func Test_luafile_percent()
new Xlua_file
append
str, num = 'foo', 321.0
print(string.format('str=%s, num=%d', str, num))
.
w!
luafile %
let msg = split(execute('message'), "\n")[-1]
call assert_equal('str=foo, num=321', msg)
lua str, num = nil
call delete('Xlua_file')
bwipe!
endfunc
" Test :luafile with syntax error
func Test_luafile_error()
new Xlua_file
call writefile(['nil = 0' ], 'Xlua_file')
call setfperm('Xlua_file', 'r-xr-xr-x')
call assert_fails('luafile Xlua_file', "Xlua_file:1: unexpected symbol near 'nil'")
call delete('Xlua_file')
bwipe!
endfunc
+1 -1
View File
@@ -39,7 +39,7 @@ function Test_messages()
endtry
endfunction
" Patch 7.4.1696 defined the "clearmode()" command for clearing the mode
" Patch 7.4.1696 defined the "clearmode()" function for clearing the mode
" indicator (e.g., "-- INSERT --") when ":stopinsert" is invoked. Message
" output could then be disturbed when 'cmdheight' was greater than one.
" This test ensures that the bugfix for this issue remains in place.
+85 -15
View File
@@ -5,6 +5,8 @@ endif
func Test_profile_func()
let lines = [
\ 'profile start Xprofile_func.log',
\ 'profile func Foo*"',
\ "func! Foo1()",
\ "endfunc",
\ "func! Foo2()",
@@ -33,9 +35,7 @@ func Test_profile_func()
call writefile(lines, 'Xprofile_func.vim')
call system(v:progpath
\ . ' -es -u NONE -U NONE -i NONE --noplugin'
\ . ' -c "profile start Xprofile_func.log"'
\ . ' -c "profile func Foo*"'
\ . ' -es --clean'
\ . ' -c "so Xprofile_func.vim"'
\ . ' -c "qall!"')
call assert_equal(0, v:shell_error)
@@ -97,7 +97,7 @@ func Test_profile_file()
call writefile(lines, 'Xprofile_file.vim')
call system(v:progpath
\ . ' -es -u NONE -U NONE -i NONE --noplugin'
\ . ' -es --clean'
\ . ' -c "profile start Xprofile_file.log"'
\ . ' -c "profile file Xprofile_file.vim"'
\ . ' -c "so Xprofile_file.vim"'
@@ -152,17 +152,17 @@ func Test_profile_file_with_cont()
let lines = readfile('Xprofile_file.log')
call assert_equal(11, len(lines))
call assert_match('^SCRIPT .*Xprofile_file.vim$', lines[0])
call assert_equal('Sourced 1 time', lines[1])
call assert_match('^Total time:\s\+\d\+\.\d\+$', lines[2])
call assert_match('^ Self time:\s\+\d\+\.\d\+$', lines[3])
call assert_equal('', lines[4])
call assert_equal('count total (s) self (s)', lines[5])
call assert_match(' 1 0.\d\+ echo "hello', lines[6])
call assert_equal(' \ world"', lines[7])
call assert_match(' 1 0.\d\+ echo "foo ', lines[8])
call assert_equal(' \bar"', lines[9])
call assert_equal('', lines[10])
call assert_match('^SCRIPT .*Xprofile_file.vim$', lines[0])
call assert_equal('Sourced 1 time', lines[1])
call assert_match('^Total time:\s\+\d\+\.\d\+$', lines[2])
call assert_match('^ Self time:\s\+\d\+\.\d\+$', lines[3])
call assert_equal('', lines[4])
call assert_equal('count total (s) self (s)', lines[5])
call assert_match(' 1 0.\d\+ echo "hello', lines[6])
call assert_equal(' \ world"', lines[7])
call assert_match(' 1 0.\d\+ echo "foo ', lines[8])
call assert_equal(' \bar"', lines[9])
call assert_equal('', lines[10])
call delete('Xprofile_file.vim')
call delete('Xprofile_file.log')
@@ -222,3 +222,73 @@ func Test_profile_truncate_mbyte()
call delete('Xprofile_file.vim')
call delete('Xprofile_file.log')
endfunc
func Test_profdel_func()
let lines = [
\ 'profile start Xprofile_file.log',
\ 'func! Foo1()',
\ 'endfunc',
\ 'func! Foo2()',
\ 'endfunc',
\ 'func! Foo3()',
\ 'endfunc',
\ '',
\ 'profile func Foo1',
\ 'profile func Foo2',
\ 'call Foo1()',
\ 'call Foo2()',
\ '',
\ 'profile func Foo3',
\ 'profdel func Foo2',
\ 'profdel func Foo3',
\ 'call Foo1()',
\ 'call Foo2()',
\ 'call Foo3()' ]
call writefile(lines, 'Xprofile_file.vim')
call system(v:progpath . ' -es --clean -c "so Xprofile_file.vim" -c q')
call assert_equal(0, v:shell_error)
let lines = readfile('Xprofile_file.log')
call assert_equal(24, len(lines))
" Check that:
" - Foo1() is called twice (profdel not invoked)
" - Foo2() is called once (profdel invoked after it was called)
" - Foo3() is not called (profdel invoked before it was called)
call assert_equal('FUNCTION Foo1()', lines[0])
call assert_equal('Called 2 times', lines[1])
call assert_equal('FUNCTION Foo2()', lines[7])
call assert_equal('Called 1 time', lines[8])
call assert_equal('FUNCTIONS SORTED ON TOTAL TIME', lines[14])
call assert_equal('FUNCTIONS SORTED ON SELF TIME', lines[19])
call delete('Xprofile_file.vim')
call delete('Xprofile_file.log')
endfunc
func Test_profdel_star()
" Foo() is invoked once before and once after 'profdel *'.
" So profiling should report it only once.
let lines = [
\ 'profile start Xprofile_file.log',
\ 'func! Foo()',
\ 'endfunc',
\ 'profile func Foo',
\ 'call Foo()',
\ 'profdel *',
\ 'call Foo()' ]
call writefile(lines, 'Xprofile_file.vim')
call system(v:progpath . ' -es --clean -c "so Xprofile_file.vim" -c q')
call assert_equal(0, v:shell_error)
let lines = readfile('Xprofile_file.log')
call assert_equal(15, len(lines))
call assert_equal('FUNCTION Foo()', lines[0])
call assert_equal('Called 1 time', lines[1])
call assert_equal('FUNCTIONS SORTED ON TOTAL TIME', lines[7])
call assert_equal('FUNCTIONS SORTED ON SELF TIME', lines[11])
call delete('Xprofile_file.vim')
call delete('Xprofile_file.log')
endfunc
+46
View File
@@ -1,3 +1,4 @@
" Tests for put commands, e.g. ":put", "p", "gp", "P", "gP", etc.
func Test_put_block()
if !has('multi_byte')
@@ -58,3 +59,48 @@ func Test_put_expr()
call assert_equal(['A1','A2','A3','4A','5A','6A'], getline(1,'$'))
bw!
endfunc
func Test_put_fails_when_nomodifiable()
new
setlocal nomodifiable
normal! yy
call assert_fails(':put', 'E21')
call assert_fails(':put!', 'E21')
call assert_fails(':normal! p', 'E21')
call assert_fails(':normal! gp', 'E21')
call assert_fails(':normal! P', 'E21')
call assert_fails(':normal! gP', 'E21')
if has('mouse')
set mouse=n
call assert_fails('execute "normal! \<MiddleMouse>"', 'E21')
set mouse&
endif
bwipeout!
endfunc
" A bug was discovered where the Normal mode put commands (e.g., "p") would
" output duplicate error messages when invoked in a non-modifiable buffer.
func Test_put_p_errmsg_nodup()
new
setlocal nomodifiable
normal! yy
func Capture_p_error()
redir => s:p_err
normal! p
redir END
endfunc
silent! call Capture_p_error()
" Error message output within a function should be three lines (the function
" name, the line number, and the error message).
call assert_equal(3, count(s:p_err, "\n"))
delfunction Capture_p_error
bwipeout!
endfunc
+47 -8
View File
@@ -1,13 +1,13 @@
" Test sort()
" Tests for the "sort()" function and for the ":sort" command.
:func Compare1(a, b) abort
func Compare1(a, b) abort
call sort(range(3), 'Compare2')
return a:a - a:b
:endfunc
endfunc
:func Compare2(a, b) abort
func Compare2(a, b) abort
return a:a - a:b
:endfunc
endfunc
func Test_sort_strings()
" numbers compared as strings
@@ -45,7 +45,7 @@ func Test_sort_default()
call assert_fails('call sort([3.3, 1, "2"], 3)', "E474")
endfunc
" Tests for the :sort command
" Tests for the ":sort" command.
func Test_sort_cmd()
let tests = [
\ {
@@ -1167,15 +1167,54 @@ func Test_sort_cmd()
\ '1.234',
\ '123.456'
\ ]
\ }
\ },
\ {
\ 'name' : 'alphabetical, sorted input',
\ 'cmd' : 'sort',
\ 'input' : [
\ 'a',
\ 'b',
\ 'c',
\ ],
\ 'expected' : [
\ 'a',
\ 'b',
\ 'c',
\ ]
\ },
\ {
\ 'name' : 'alphabetical, sorted input, unique at end',
\ 'cmd' : 'sort u',
\ 'input' : [
\ 'aa',
\ 'bb',
\ 'cc',
\ 'cc',
\ ],
\ 'expected' : [
\ 'aa',
\ 'bb',
\ 'cc',
\ ]
\ },
\ ]
for t in tests
enew!
call append(0, t.input)
$delete _
exe t.cmd
setlocal nomodified
execute t.cmd
call assert_equal(t.expected, getline(1, '$'), t.name)
" Previously, the ":sort" command would set 'modified' even if the buffer
" contents did not change. Here, we check that this problem is fixed.
if t.input == t.expected
call assert_false(&modified, t.name . ': &mod is not correct')
else
call assert_true(&modified, t.name . ': &mod is not correct')
endif
endfor
call assert_fails('sort no', 'E474')
+36
View File
@@ -1,3 +1,4 @@
" Various tests for inserting a Tab.
" Tests for "r<Tab>" with 'smarttab' and 'expandtab' set/not set.
" Also test that dv_ works correctly
@@ -43,3 +44,38 @@ func Test_smarttab()
enew!
set expandtab& smartindent& copyindent& ts& sw& sts&
endfunc
func Test_softtabstop()
new
set sts=0 sw=0
exe "normal ix\<Tab>x\<Esc>"
call assert_equal("x\tx", getline(1))
call setline(1, '')
set sts=4
exe "normal ix\<Tab>x\<Esc>"
call assert_equal("x x", getline(1))
call setline(1, '')
set sts=-1 sw=4
exe "normal ix\<Tab>x\<Esc>"
call assert_equal("x x", getline(1))
call setline(1, 'x ')
set sts=0 sw=0 backspace=start
exe "normal A\<BS>x\<Esc>"
call assert_equal("x x", getline(1))
call setline(1, 'x ')
set sts=4
exe "normal A\<BS>x\<Esc>"
call assert_equal("x x", getline(1))
call setline(1, 'x ')
set sts=-1 sw=4
exe "normal A\<BS>x\<Esc>"
call assert_equal("x x", getline(1))
set sts=0 sw=0 backspace&
bwipe!
endfunc
+24 -1
View File
@@ -1,4 +1,4 @@
" test 'taglist' function and :tags command
" test taglist(), tagfiles() functions and :tags command
func Test_taglist()
call writefile([
@@ -61,3 +61,26 @@ func Test_tags_too_long()
call assert_fails('tag ' . repeat('x', 1020), 'E426')
tags
endfunc
func Test_tagfiles()
call assert_equal([], tagfiles())
call writefile(["FFoo\tXfoo\t1"], 'Xtags1')
call writefile(["FBar\tXbar\t1"], 'Xtags2')
set tags=Xtags1,Xtags2
call assert_equal(['Xtags1', 'Xtags2'], tagfiles())
help
let tf = tagfiles()
call assert_equal(1, len(tf))
call assert_equal(fnamemodify(expand('$VIMRUNTIME/doc/tags'), ':p:gs?\\?/?'),
\ fnamemodify(tf[0], ':p:gs?\\?/?'))
helpclose
call assert_equal(['Xtags1', 'Xtags2'], tagfiles())
set tags&
call assert_equal([], tagfiles())
call delete('Xtags1')
call delete('Xtags2')
bd
endfunc
+22 -6
View File
@@ -262,21 +262,37 @@ func! Test_vartabs_breakindent()
endfunc
func! Test_vartabs_linebreak()
if winwidth(0) < 80
if winwidth(0) < 40
return
endif
new
70vnew
40vnew
%d
setl linebreak vartabstop=10,15,20,40
setl linebreak vartabstop=10,20,30,40
call setline(1, "\tx\tx\tx\tx")
let lines = ScreenLines([1, 2], winwidth(0))
let expect = [' x x x ',
\ ' x ']
let expect = [' x ',
\ 'x x ',
\ 'x ']
let lines = ScreenLines([1, 3], winwidth(0))
call s:compare_lines(expect, lines)
setl list listchars=tab:>-
let expect = ['>---------x>------------------ ',
\ 'x>------------------x>------------------',
\ 'x ']
let lines = ScreenLines([1, 3], winwidth(0))
call s:compare_lines(expect, lines)
setl linebreak vartabstop=40
let expect = ['>---------------------------------------',
\ 'x>--------------------------------------',
\ 'x>--------------------------------------',
\ 'x>--------------------------------------',
\ 'x ']
let lines = ScreenLines([1, 5], winwidth(0))
call s:compare_lines(expect, lines)
" cleanup
bw!
bw!
set nolist listchars&vim
endfunc
+16
View File
@@ -42,6 +42,22 @@ func Test_paste_end_of_line()
set virtualedit=
endfunc
func Test_replace_end_of_line()
new
set virtualedit=all
call setline(1, range(20))
exe "normal! gg2jv10lr-"
call assert_equal(["1", "-----------", "3"], getline(2,4))
if has('multi_byte')
call setline(1, range(20))
exe "normal! gg2jv10lr\<c-k>hh"
call assert_equal(["1", "───────────", "3"], getline(2,4))
endif
bwipe!
set virtualedit=
endfunc
func Test_edit_CTRL_G()
new
set virtualedit=insert
+1 -1
View File
@@ -2968,7 +2968,7 @@ u_undo_end(
}
#endif
smsg((char_u *)_("%ld %s; %s #%ld %s"),
smsg_attr_keep(0, (char_u *)_("%ld %s; %s #%ld %s"),
u_oldcount < 0 ? -u_oldcount : u_oldcount,
_(msgstr),
did_undo ? _("before") : _("after"),
+30 -22
View File
@@ -293,10 +293,6 @@ get_lambda_tv(char_u **arg, typval_T *rettv, int evaluate)
fp->uf_scoped = NULL;
#ifdef FEAT_PROFILE
fp->uf_tml_count = NULL;
fp->uf_tml_total = NULL;
fp->uf_tml_self = NULL;
fp->uf_profiling = FALSE;
if (prof_def_func())
func_do_profile(fp);
#endif
@@ -706,6 +702,7 @@ call_user_func(
#ifdef FEAT_PROFILE
proftime_T wait_start;
proftime_T call_start;
int started_profiling = FALSE;
#endif
/* If depth of calling is getting too high, don't execute the function */
@@ -921,7 +918,10 @@ call_user_func(
if (do_profiling == PROF_YES)
{
if (!fp->uf_profiling && has_profiling(FALSE, fp->uf_name, NULL))
{
started_profiling = TRUE;
func_do_profile(fp);
}
if (fp->uf_profiling
|| (fc->caller != NULL && fc->caller->func->uf_profiling))
{
@@ -965,6 +965,9 @@ call_user_func(
profile_add(&fc->caller->func->uf_tm_children, &call_start);
profile_add(&fc->caller->func->uf_tml_children, &call_start);
}
if (started_profiling)
// make a ":profdel func" stop profiling the function
fp->uf_profiling = FALSE;
}
#endif
@@ -2522,23 +2525,28 @@ func_do_profile(ufunc_T *fp)
{
int len = fp->uf_lines.ga_len;
if (len == 0)
len = 1; /* avoid getting error for allocating zero bytes */
fp->uf_tm_count = 0;
profile_zero(&fp->uf_tm_self);
profile_zero(&fp->uf_tm_total);
if (fp->uf_tml_count == NULL)
fp->uf_tml_count = (int *)alloc_clear((unsigned) (sizeof(int) * len));
if (fp->uf_tml_total == NULL)
fp->uf_tml_total = (proftime_T *)alloc_clear((unsigned)
(sizeof(proftime_T) * len));
if (fp->uf_tml_self == NULL)
fp->uf_tml_self = (proftime_T *)alloc_clear((unsigned)
(sizeof(proftime_T) * len));
fp->uf_tml_idx = -1;
if (fp->uf_tml_count == NULL || fp->uf_tml_total == NULL
|| fp->uf_tml_self == NULL)
return; /* out of memory */
if (!fp->uf_prof_initialized)
{
if (len == 0)
len = 1; /* avoid getting error for allocating zero bytes */
fp->uf_tm_count = 0;
profile_zero(&fp->uf_tm_self);
profile_zero(&fp->uf_tm_total);
if (fp->uf_tml_count == NULL)
fp->uf_tml_count = (int *)alloc_clear(
(unsigned)(sizeof(int) * len));
if (fp->uf_tml_total == NULL)
fp->uf_tml_total = (proftime_T *)alloc_clear(
(unsigned)(sizeof(proftime_T) * len));
if (fp->uf_tml_self == NULL)
fp->uf_tml_self = (proftime_T *)alloc_clear(
(unsigned)(sizeof(proftime_T) * len));
fp->uf_tml_idx = -1;
if (fp->uf_tml_count == NULL || fp->uf_tml_total == NULL
|| fp->uf_tml_self == NULL)
return; /* out of memory */
fp->uf_prof_initialized = TRUE;
}
fp->uf_profiling = TRUE;
}
@@ -2568,7 +2576,7 @@ func_dump_profile(FILE *fd)
{
--todo;
fp = HI2UF(hi);
if (fp->uf_profiling)
if (fp->uf_prof_initialized)
{
if (sorttab != NULL)
sorttab[st_len++] = fp;
+44
View File
@@ -804,6 +804,50 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
139,
/**/
138,
/**/
137,
/**/
136,
/**/
135,
/**/
134,
/**/
133,
/**/
132,
/**/
131,
/**/
130,
/**/
129,
/**/
128,
/**/
127,
/**/
126,
/**/
125,
/**/
124,
/**/
123,
/**/
122,
/**/
121,
/**/
120,
/**/
119,
/**/
118,
/**/
117,
/**/