Compare commits

...

20 Commits

Author SHA1 Message Date
Bram Moolenaar
14944c04bd patch 8.2.1663: options window entries cannot be translated
Problem:    Options window entries cannot be translated.
Solution:   Use AddOption() for all explanations. (closes #6800)
2020-09-11 20:51:26 +02:00
Bram Moolenaar
0e655111e9 patch 8.2.1662: :mksession does not restore shared terminal buffer properly
Problem:    :mksession does not restore shared terminal buffer properly.
Solution:   Keep a hashtab with terminal buffers. (Rob Pilling, closes #6930)
2020-09-11 20:36:36 +02:00
Bram Moolenaar
c6a67c92bc patch 8.2.1661: cannot connect to 127.0.0.1 for host with only IPv6 addresses
Problem:    Cannot connect to 127.0.0.1 for host with only IPv6 addresses.
Solution:   pass AI_V4MAPPED flag to getaddrinfo. (Filipe Brandenburger,
            closes #6931)
2020-09-11 19:28:19 +02:00
Bram Moolenaar
c0c71e9d98 patch 8.2.1660: assert functions require passing expected as first argument
Problem:    Assert functions require passing expected result as the first
            argument, which isn't obvious.
Solution:   Use a method, as in "runtest()->assert_equal(expected)".
2020-09-11 19:09:48 +02:00
Bram Moolenaar
96fdf4348a patch 8.2.1659: spellfile code not completely tested
Problem:    Spellfile code not completely tested.
Solution:   Add a few more test cases. (Yegappan Lakshmanan, closes #6929)
2020-09-11 18:11:50 +02:00
Bram Moolenaar
a810db3f17 patch 8.2.1658: expand('<stack>') has trailing ".."
Problem:    Expand('<stack>') has trailing "..".
Solution:   Remove the "..". (closes #6927)
2020-09-11 17:59:23 +02:00
Bram Moolenaar
8b848cafb0 patch 8.2.1657: Vim9: no proper error for nested ":def!"
Problem:    Vim9: no proper error for nested ":def!".
Solution:   Check for "!". (closes #6920)
2020-09-10 22:28:01 +02:00
Bram Moolenaar
dfa3d5524e patch 8.2.1656: Vim9: callstack wrong if :def function calls :def function
Problem:    Vim9: callstack wrong if :def function calls :def function.
Solution:   Set the line number before calling. (closes #6914)
2020-09-10 22:05:08 +02:00
Bram Moolenaar
895a7a472d patch 8.2.1655: cannot build with Strawberry Perl 5.32.0
Problem:    Cannot build with Strawberry Perl 5.32.0.
Solution:   Use Perl_sv_2pvbyte_flags. (closes #6921)
2020-09-10 21:36:11 +02:00
Bram Moolenaar
ad9ec5e799 patch 8.2.1654: when job writes to hidden buffer current window is wrong
Problem:    When job writes to hidden buffer current window has display
            errors.  (Johnny McArthur)
Solution:   Use aucmd_prepbuf() instead of switch_to_win_for_buf().
            (closes #6925)
2020-09-10 21:25:45 +02:00
Bram Moolenaar
4f25b1aba0 patch 8.2.1653: expand('<stack>') does not include the final line number
Problem:    Expand('<stack>') does not include the final line number.
Solution:   Add the line nuber. (closes #6927)
2020-09-10 19:25:05 +02:00
Bram Moolenaar
a953b5cf4f patch 8.2.1652: cannot translate lines in the options window
Problem:    Cannot translate lines in the options window.
Solution:   Use the AddOption() function to split descriptions where indicated
            by a line break. (issue #6800)
2020-09-10 14:25:25 +02:00
Bram Moolenaar
64e2db6dc6 patch 8.2.1651: spellfile code not completely tested
Problem:    Spellfile code not completely tested.
Solution:   Add a few more test cases. (Yegappan Lakshmanan, closes #6918)
2020-09-09 22:43:19 +02:00
Bram Moolenaar
c1ec0422e4 patch 8.2.1650: Vim9: result of && and || expression is not bool in script
Problem:    Vim9: result of && and || expression cannot be assigned to a bool
            at the script level.
Solution:   Add the VAR_BOOL_OK flag.  Convert to bool when needed.
2020-09-09 22:27:58 +02:00
Bram Moolenaar
3e4cc9671c patch 8.2.1649: GTK3: using old file chooser
Problem:    GTK3: using old file chooser.
Solution:   Use native file chooser on GTK 3.20 and above. (Yogeshwar
            Velingker, closes #6909)
2020-09-09 20:58:55 +02:00
Bram Moolenaar
a62372be1f patch 8.2.1648: Amiga: no common build file for Amiga (-like) systems
Problem:    Amiga: no common build file for Amiga (-like) systems.
Solution:   Turn Make_morph.mak into Make_ami.mak. (Ola Söder, closes #6805)
2020-09-09 20:41:40 +02:00
Bram Moolenaar
4ed124cc6c patch 8.2.1647: Vim9: result of expression with && and || is not a bool
Problem:    Vim9: result of expression with && and || cannot be assigned to a
            bool variable.
Solution:   Add the TTFLAG_BOOL_OK flag and convert the value if needed.
2020-09-09 20:03:46 +02:00
Bram Moolenaar
33e3346322 patch 8.2.1646: Amiga: Unnecessary #include
Problem:    Amiga: Unnecessary #include.
Solution:   Remove the #include. (Ola Söder, closes #6908)
2020-09-09 19:25:09 +02:00
Bram Moolenaar
81a4cf469a patch 8.2.1645: GTK3: icons become broken images when resized
Problem:    GTK3: icons become broken images when resized.
Solution:   Use gtk_image_new_from_icon_name(). (closes #6916)
            Fix compiler warnings.
2020-09-09 19:05:13 +02:00
Bram Moolenaar
ba7c0d7b4c patch 8.2.1644: Vim9: cannot assign 1 and 0 to bool at script level
Problem:    Vim9: cannot assign 1 and 0 to bool at script level.
Solution:   Add the TTFLAG_BOOL_OK flag to the type. Fix name of test
            function.
2020-09-09 18:54:42 +02:00
40 changed files with 1482 additions and 961 deletions

View File

@@ -623,7 +623,7 @@ SRC_AMI = \
README_amisrc.txt.info \
src.info \
src/INSTALLami.txt \
src/Make_morph.mak \
src/Make_ami.mak \
src/os_amiga.c \
src/os_amiga.h \
src/proto/os_amiga.pro \

File diff suppressed because it is too large Load Diff

View File

@@ -1,4 +1,4 @@
INSTALLami.txt - Installation of Vim from source on Amiga
INSTALLami.txt - Installation of Vim from source on Amiga and MorphOS
This file contains instructions for compiling Vim. If you already have an
executable version of Vim, you don't need this.
@@ -7,28 +7,13 @@ The file "feature.h" can be edited to match your preferences. You can skip
this, then you will get the default behavior as is documented, which should
be fine for most people.
Summary:
make -f Make_manx.mak Manx C
make -f Make_sas.mak Lattice/SAS C
make -f Make_dice.mak DICE
make -f Make_ami.mak gcc
make -f Make_ami.mak CC=vc vbcc
The Manx compiler is preferred, it was used to produce the Amiga executable
and has been tested most. You should not get any errors or warnings.
Please note that currently only gcc has been tested. VBCC would need its own
CFLAGS, but should otherwise work out of the box. For cross-compiling, UNM
can be used to override uname and thereby set the target. An example is shown
below:
The SAS compiler can be used. Older versions (6.0 to 6.3) don't work with the
optimizer switched on. This seems to be fixed with 6.5 or 6.56, but this has
not been tested much. Also disable optimizing when the compiler runs out of
memory or crashes the system (yes, that happens; did I say the Manx compiler
is preferred?).
The DICE makefile has been reported to work by one person only.
You will have to set the "VIM" environment variable to the location of the
documentation files.
MorphOS
Use the Make_morph.mak Makefile:
make -f Make_morph.mak
make -f Make_ami.mak CC=ppc-morphos-gcc UNM=MorphOS

201
src/Make_ami.mak Normal file
View File

@@ -0,0 +1,201 @@
#
# Makefile for AROS, AmigaOS4 and MorphOS.
#
BIN = vim
CC ?= gcc
LD = $(CC)
UNM ?= $(shell uname)
DEBUG ?= no
BUILD ?= huge
CFLAGS = -c -O3
# Common compiler flags
CFLAGS += \
-DNO_ARP \
-DUSE_TMPNAM \
-DHAVE_STDARG_H \
-DHAVE_TGETENT \
-DHAVE_TERMCAP \
-DNEW_SHELLSIZE \
-I proto \
-Wno-attributes \
-Wextra
# Vim 'huge' build
ifeq ($(BUILD),huge)
CFLAGS += \
-DFEAT_BROWSE \
-DFEAT_MOUSE \
-DFEAT_HUGE
else
# Vim 'big' build
ifeq ($(BUILD),big)
CFLAGS += \
-DFEAT_BROWSE \
-DFEAT_MOUSE \
-DFEAT_BIG
else
# Vim 'normal' build
ifeq ($(BUILD),normal)
CFLAGS +=\
-DFEAT_BROWSE \
-DFEAT_MOUSE \
-DFEAT_NORMAL
else
# Vim 'small' build
ifeq ($(BUILD),small)
CFLAGS += -DFEAT_SMALL
else
# Vim 'tiny' build
ifeq ($(BUILD),tiny)
CFLAGS += -DFEAT_TINY
endif
endif
endif
endif
endif
# OS specific compiler flags
ifeq ($(UNM),AmigaOS)
LDFLAGS = -mcrt=clib2 -lauto -lm -lnet
CFLAGS += -DHAVE_FSYNC -D__USE_INLINE__ -mcrt=clib2
else
ifeq ($(UNM),AROS)
LDFLAGS = -DHAVE_FSYNC -ldebug
else
ifeq ($(UNM),MorphOS)
LDFLAGS = -ldebug -noixemul
endif
endif
endif
# Patch level used for Amiga style version string
ifdef PATCHLEVEL
CFLAGS += -DPATCHLEVEL=\"$(PATCHLEVEL)\"
endif
# Common sources
SRC += \
arabic.c \
arglist.c \
autocmd.c \
beval.c \
blob.c \
blowfish.c \
buffer.c \
bufwrite.c \
change.c \
charset.c \
cindent.c \
clientserver.c \
clipboard.c \
cmdhist.c \
cmdexpand.c \
crypt.c \
crypt_zip.c \
debugger.c \
dict.c \
diff.c \
digraph.c \
drawline.c \
drawscreen.c \
edit.c \
eval.c \
evalbuffer.c \
evalfunc.c \
evalvars.c \
evalwindow.c \
ex_cmds.c \
ex_cmds2.c \
ex_docmd.c \
ex_eval.c \
ex_getln.c \
fileio.c \
filepath.c \
findfile.c \
fold.c \
getchar.c \
hardcopy.c \
hashtab.c \
help.c \
highlight.c \
if_cscope.c \
indent.c \
insexpand.c \
json.c \
list.c \
locale.c \
main.c \
mark.c \
map.c \
match.c \
mbyte.c \
memfile.c \
memline.c \
menu.c \
message.c \
misc1.c \
misc2.c \
mouse.c \
move.c \
normal.c \
ops.c \
option.c \
optionstr.c \
os_amiga.c \
popupmenu.c \
popupwin.c \
quickfix.c \
regexp.c \
register.c \
screen.c \
scriptfile.c \
search.c \
session.c \
sha256.c \
sign.c \
spell.c \
spellfile.c \
spellsuggest.c \
syntax.c \
tag.c \
term.c \
termlib.c \
testing.c \
textformat.c \
textobject.c \
textprop.c \
time.c \
typval.c \
ui.c \
undo.c \
usercmd.c \
userfunc.c \
version.c \
viminfo.c \
vim9compile.c \
vim9execute.c \
vim9script.c \
vim9type.c \
window.c \
xdiff/xdiffi.c \
xdiff/xemit.c \
xdiff/xhistogram.c \
xdiff/xpatience.c \
xdiff/xprepare.c \
xdiff/xutils.c
OBJ = $(SRC:.c=.o)
# Build everything - Ignoring header dependencies.
$(BIN): $(OBJ)
${LD} -o $(BIN) $(OBJ) $(LDFLAGS)
# Clean up
.PHONY: clean
clean:
$(RM) -fv $(OBJ) $(BIN)

View File

@@ -1,132 +0,0 @@
#
# Makefile for VIM, using MorphOS SDK (gcc 2.95.3)
#
CFLAGS = -c \
-pipe \
-O2 \
-Wall \
\
-DNO_ARP \
-DUSE_TMPNAM \
\
-I proto \
\
-noixemul
PRG = Vim
LIBS = -noixemul -s
CC = gcc
LD = gcc
OBJDUMP = objdump
RM = rm
.c.o:
${CC} ${CFLAGS} $< -o $@
SRC = arabic.c \
arglist.c \
autocmd.c \
blowfish.c \
buffer.c \
bufwrite.c \
change.c \
charset.c \
cindent.c \
clientserver.c \
clipboard.c \
cmdexpand.c \
cmdhist.c \
crypt.c \
crypt_zip.c \
debugger.c \
dict.c \
diff.c \
digraph.c \
drawline.c \
drawscreen.c \
edit.c \
eval.c \
evalbuffer.c \
evalfunc.c \
evalvars.c \
evalwindow.c \
ex_cmds.c \
ex_cmds2.c \
ex_docmd.c \
ex_eval.c \
ex_getln.c \
fileio.c \
filepath.c \
findfile.c \
fold.c \
getchar.c \
gui_xim.c \
hardcopy.c \
hashtab.c \
help.c \
highlight.c \
indent.c \
insexpand.c \
json.c \
list.c \
locale.c \
main.c \
map.c \
mark.c \
match.c \
mbyte.c \
memfile.c \
memline.c \
menu.c \
message.c \
misc1.c \
misc2.c \
mouse.c \
move.c \
normal.c \
ops.c \
option.c \
optionstr.c \
os_amiga.c \
popupmenu.c \
profiler.c \
quickfix.c \
regexp.c \
register.c \
scriptfile.c \
screen.c \
search.c \
session.c \
sha256.c \
sign.c \
spell.c \
spellfile.c \
spellsuggest.c \
syntax.c \
tag.c \
term.c \
testing.c \
textformat.c \
textobject.c \
textprop.c \
time.c \
typval.c \
ui.c \
undo.c \
usercmd.c \
userfunc.c \
version.c \
viminfo.c \
window.c \
OBJ = $(SRC:.c=.o)
$(PRG): $(OBJ)
${LD} -o $(PRG) $(OBJ) $(LIBS)
dump: $(PRG)
$(OBJDUMP) --reloc --disassemble-all $(PRG) > $(PRG).s
clean:
$(RM) -fv $(OBJ) $(PRG) $(PRG).s

View File

@@ -977,8 +977,8 @@ channel_open(
CLEAR_FIELD(hints);
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
# ifdef AI_ADDRCONFIG
hints.ai_flags = AI_ADDRCONFIG;
# if defined(AI_ADDRCONFIG) && defined(AI_V4MAPPED)
hints.ai_flags = AI_ADDRCONFIG | AI_V4MAPPED;
# endif
// Set port number manually in order to prevent name resolution services
// from being invoked in the environment where AI_NUMERICSERV is not
@@ -2619,9 +2619,7 @@ invoke_one_time_callback(
static void
append_to_buffer(buf_T *buffer, char_u *msg, channel_T *channel, ch_part_T part)
{
bufref_T save_curbuf = {NULL, 0, 0};
win_T *save_curwin = NULL;
tabpage_T *save_curtab = NULL;
aco_save_T aco;
linenr_T lnum = buffer->b_ml.ml_line_count;
int save_write_to = buffer->b_write_to_channel;
chanpart_T *ch_part = &channel->ch_part[part];
@@ -2647,12 +2645,13 @@ append_to_buffer(buf_T *buffer, char_u *msg, channel_T *channel, ch_part_T part)
}
// Append to the buffer
ch_log(channel, "appending line %d to buffer", (int)lnum + 1 - empty);
ch_log(channel, "appending line %d to buffer %s",
(int)lnum + 1 - empty, buffer->b_fname);
buffer->b_p_ma = TRUE;
// Save curbuf/curwin/curtab and make "buffer" the current buffer.
switch_to_win_for_buf(buffer, &save_curwin, &save_curtab, &save_curbuf);
// set curbuf to be our buf, temporarily
aucmd_prepbuf(&aco, buffer);
u_sync(TRUE);
// ignore undo failure, undo is not very useful here
@@ -2668,8 +2667,8 @@ append_to_buffer(buf_T *buffer, char_u *msg, channel_T *channel, ch_part_T part)
ml_append(lnum, msg, 0, FALSE);
appended_lines_mark(lnum, 1L);
// Restore curbuf/curwin/curtab
restore_win_for_buf(save_curwin, save_curtab, &save_curbuf);
// reset notion of buffer
aucmd_restbuf(&aco);
if (ch_part->ch_nomodifiable)
buffer->b_p_ma = FALSE;
@@ -2693,9 +2692,10 @@ append_to_buffer(buf_T *buffer, char_u *msg, channel_T *channel, ch_part_T part)
// down. If the topline is outdated update it now.
if (move_cursor || wp->w_topline > buffer->b_ml.ml_line_count)
{
win_T *save_curwin = curwin;
if (move_cursor)
++wp->w_cursor.lnum;
save_curwin = curwin;
curwin = wp;
curbuf = curwin->w_buffer;
scroll_cursor_bot(0, FALSE);

View File

@@ -105,7 +105,7 @@ do_debug(char_u *cmd)
vim_free(debug_newval);
debug_newval = NULL;
}
sname = estack_sfile(FALSE);
sname = estack_sfile(ESTACK_NONE);
if (sname != NULL)
msg((char *)sname);
vim_free(sname);
@@ -344,7 +344,7 @@ do_checkbacktracelevel(void)
}
else
{
char_u *sname = estack_sfile(FALSE);
char_u *sname = estack_sfile(ESTACK_NONE);
int max = get_maxbacktrace_level(sname);
if (debug_backtrace_level > max)
@@ -365,7 +365,7 @@ do_showbacktrace(char_u *cmd)
int i = 0;
int max;
sname = estack_sfile(FALSE);
sname = estack_sfile(ESTACK_NONE);
max = get_maxbacktrace_level(sname);
if (sname != NULL)
{

View File

@@ -256,4 +256,6 @@ EXTERN char e_assert_fails_fourth_argument[]
INIT(= N_("E1115: assert_fails() fourth argument must be a number"));
EXTERN char e_assert_fails_fifth_argument[]
INIT(= N_("E1116: assert_fails() fifth argument must be a string"));
EXTERN char e_cannot_use_bang_with_nested_def[]
INIT(= N_("E1117: Cannot use ! with nested :def"));
#endif

View File

@@ -2356,6 +2356,9 @@ eval2(char_u **arg, typval_T *rettv, evalarg_T *evalarg)
clear_evalarg(&local_evalarg, NULL);
else
evalarg->eval_flags = orig_flags;
// Resulting value can be assigned to a bool.
rettv->v_lock |= VAR_BOOL_OK;
}
return OK;
@@ -2451,6 +2454,7 @@ eval3(char_u **arg, typval_T *rettv, evalarg_T *evalarg)
*arg = skipwhite_and_linebreak(*arg + 2, evalarg_used);
evalarg_used->eval_flags = result ? orig_flags
: orig_flags & ~EVAL_EVALUATE;
CLEAR_FIELD(var2);
if (eval4(arg, &var2, evalarg_used) == FAIL)
return FAIL;
@@ -2487,6 +2491,9 @@ eval3(char_u **arg, typval_T *rettv, evalarg_T *evalarg)
clear_evalarg(&local_evalarg, NULL);
else
evalarg->eval_flags = orig_flags;
// Resulting value can be assigned to a bool.
rettv->v_lock |= VAR_BOOL_OK;
}
return OK;

View File

@@ -778,7 +778,7 @@ ex_let(exarg_T *eap)
evalarg_T evalarg;
int len = 1;
rettv.v_type = VAR_UNKNOWN;
CLEAR_FIELD(rettv);
i = FAIL;
if (has_assign || concat)
{
@@ -2935,10 +2935,12 @@ set_var(
set_var_const(
char_u *name,
type_T *type,
typval_T *tv,
typval_T *tv_arg,
int copy, // make copy of value in "tv"
int flags) // LET_IS_CONST and/or LET_NO_COMMAND
{
typval_T *tv = tv_arg;
typval_T bool_tv;
dictitem_T *di;
char_u *varname;
hashtab_T *ht;
@@ -2971,6 +2973,15 @@ set_var_const(
&& var_wrong_func_name(name, di == NULL))
return;
if (need_convert_to_bool(type, tv))
{
// Destination is a bool and the value is not, but it can be converted.
CLEAR_FIELD(bool_tv);
bool_tv.v_type = VAR_BOOL;
bool_tv.vval.v_number = tv2bool(tv) ? VVAL_TRUE : VVAL_FALSE;
tv = &bool_tv;
}
if (di != NULL)
{
if ((di->di_flags & DI_FLAGS_RELOAD) == 0)
@@ -2989,7 +3000,7 @@ set_var_const(
return;
}
// check the type
// check the type and adjust to bool if needed
if (check_script_var_type(&di->di_tv, tv, name) == FAIL)
return;
}

View File

@@ -8389,6 +8389,7 @@ find_cmdline_var(char_u *src, int *usedlen)
* '<cexpr>' to C-expression under the cursor
* '<cfile>' to path name under the cursor
* '<sfile>' to sourced file name
* '<stack>' to call stack
* '<slnum>' to sourced file line number
* '<afile>' to file name for autocommand
* '<abuf>' to buffer number for autocommand
@@ -8606,7 +8607,8 @@ eval_vars(
case SPEC_SFILE: // file name for ":so" command
case SPEC_STACK: // call stack
result = estack_sfile(spec_idx == SPEC_SFILE);
result = estack_sfile(spec_idx == SPEC_SFILE
? ESTACK_SFILE : ESTACK_STACK);
if (result == NULL)
{
*errormsg = spec_idx == SPEC_SFILE

View File

@@ -290,7 +290,7 @@ cause_errthrow(
// Get the source name and lnum now, it may change before
// reaching do_errthrow().
elem->sfile = estack_sfile(FALSE);
elem->sfile = estack_sfile(ESTACK_NONE);
elem->slnum = SOURCING_LNUM;
}
}
@@ -549,7 +549,7 @@ throw_exception(void *value, except_type_T type, char_u *cmdname)
}
else
{
excp->throw_name = estack_sfile(FALSE);
excp->throw_name = estack_sfile(ESTACK_NONE);
if (excp->throw_name == NULL)
excp->throw_name = vim_strsave((char_u *)"");
if (excp->throw_name == NULL)

View File

@@ -1199,7 +1199,11 @@ gui_mch_browse(int saving UNUSED,
char_u *filter)
{
#ifdef USE_FILE_CHOOSER
GtkWidget *fc;
# if GTK_CHECK_VERSION(3,20,0)
GtkFileChooserNative *fc;
# else
GtkWidget *fc;
# endif
#endif
char_u dirbuf[MAXPATHL];
guint log_handler;
@@ -1226,18 +1230,27 @@ gui_mch_browse(int saving UNUSED,
#ifdef USE_FILE_CHOOSER
// We create the dialog each time, so that the button text can be "Open"
// or "Save" according to the action.
fc = gtk_file_chooser_dialog_new((const gchar *)title,
# if GTK_CHECK_VERSION(3,20,0)
fc = gtk_file_chooser_native_new(
# else
fc = gtk_file_chooser_dialog_new(
# endif
(const gchar *)title,
GTK_WINDOW(gui.mainwin),
saving ? GTK_FILE_CHOOSER_ACTION_SAVE
: GTK_FILE_CHOOSER_ACTION_OPEN,
# if GTK_CHECK_VERSION(3,10,0)
# if GTK_CHECK_VERSION(3,20,0)
saving ? _("_Save") : _("_Open"), _("_Cancel"));
# else
# if GTK_CHECK_VERSION(3,10,0)
_("_Cancel"), GTK_RESPONSE_CANCEL,
saving ? _("_Save") : _("_Open"), GTK_RESPONSE_ACCEPT,
# else
# else
GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
saving ? GTK_STOCK_SAVE : GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
# endif
# endif
NULL);
# endif
gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(fc),
(const gchar *)dirbuf);
@@ -1263,7 +1276,7 @@ gui_mch_browse(int saving UNUSED,
gtk_file_filter_add_pattern(gfilter, (gchar *)patt);
if (*p == '\n')
{
gtk_file_chooser_add_filter((GtkFileChooser *)fc,
gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(fc),
gfilter);
if (*(p + 1) != NUL)
gfilter = gtk_file_filter_new();
@@ -1284,7 +1297,11 @@ gui_mch_browse(int saving UNUSED,
gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER(fc), (char *)dflt);
gui.browse_fname = NULL;
# if GTK_CHECK_VERSION(3,20,0)
if (gtk_native_dialog_run(GTK_NATIVE_DIALOG(fc)) == GTK_RESPONSE_ACCEPT)
# else
if (gtk_dialog_run(GTK_DIALOG(fc)) == GTK_RESPONSE_ACCEPT)
#endif
{
char *filename;
@@ -1292,7 +1309,11 @@ gui_mch_browse(int saving UNUSED,
gui.browse_fname = (char_u *)g_strdup(filename);
g_free(filename);
}
# if GTK_CHECK_VERSION(3,20,0)
g_object_unref(fc);
# else
gtk_widget_destroy(GTK_WIDGET(fc));
# endif
#else // !USE_FILE_CHOOSER

View File

@@ -2555,7 +2555,8 @@ mainwin_realize(GtkWidget *widget UNUSED, gpointer data UNUSED)
gtk_window_set_icon_list(GTK_WINDOW(gui.mainwin), icons);
g_list_foreach(icons, (GFunc)&g_object_unref, NULL);
// TODO: is this type cast OK?
g_list_foreach(icons, (GFunc)(void *)&g_object_unref, NULL);
g_list_free(icons);
}
@@ -3092,8 +3093,8 @@ icon_size_changed_foreach(GtkWidget *widget, gpointer user_data)
const gchar *icon_name;
gtk_image_get_icon_name(image, &icon_name, NULL);
gtk_image_set_from_icon_name(image, icon_name, icon_size);
image = (GtkImage *)gtk_image_new_from_icon_name(
icon_name, icon_size);
}
# else
// User-defined icons are stored in a GtkIconSet
@@ -4967,7 +4968,8 @@ ascii_glyph_table_init(void)
}
}
g_list_foreach(item_list, (GFunc)&pango_item_free, NULL);
// TODO: is this type cast OK?
g_list_foreach(item_list, (GFunc)(void *)&pango_item_free, NULL);
g_list_free(item_list);
pango_attr_list_unref(attr_list);
}

View File

@@ -81,7 +81,7 @@ hash_clear(hashtab_T *ht)
vim_free(ht->ht_array);
}
#if defined(FEAT_SPELL) || defined(PROTO)
#if defined(FEAT_SPELL) || defined(FEAT_TERMINAL) || defined(PROTO)
/*
* Free the array of a hash table and all the keys it contains. The keys must
* have been allocated. "off" is the offset from the start of the allocate

View File

@@ -241,6 +241,9 @@ typedef int perl_key;
# else
# define Perl_sv_2pv dll_Perl_sv_2pv
# endif
# if (PERL_REVISION == 5) && (PERL_VERSION >= 32)
# define Perl_sv_2pvbyte_flags dll_Perl_sv_2pvbyte_flags
# endif
# define Perl_sv_2pvbyte dll_Perl_sv_2pvbyte
# define Perl_sv_bless dll_Perl_sv_bless
# if (PERL_REVISION == 5) && (PERL_VERSION >= 8)
@@ -397,6 +400,9 @@ static char* (*Perl_sv_2pv_nolen)(pTHX_ SV*);
static char* (*Perl_sv_2pv)(pTHX_ SV*, STRLEN*);
# endif
static char* (*Perl_sv_2pvbyte)(pTHX_ SV*, STRLEN*);
# if (PERL_REVISION == 5) && (PERL_VERSION >= 32)
static char* (*Perl_sv_2pvbyte_flags)(pTHX_ SV*, STRLEN*, I32);
# endif
static SV* (*Perl_sv_bless)(pTHX_ SV*, HV*);
# if (PERL_REVISION == 5) && (PERL_VERSION >= 8)
static void (*Perl_sv_catpvn_flags)(pTHX_ SV* , const char*, STRLEN, I32);
@@ -553,6 +559,9 @@ static struct {
{"Perl_sv_2pv", (PERL_PROC*)&Perl_sv_2pv},
# endif
{"Perl_sv_2pvbyte", (PERL_PROC*)&Perl_sv_2pvbyte},
# if (PERL_REVISION == 5) && (PERL_VERSION >= 32)
{"Perl_sv_2pvbyte_flags", (PERL_PROC*)&Perl_sv_2pvbyte_flags},
# endif
# ifdef PERL589_OR_LATER
{"Perl_sv_2iv_flags", (PERL_PROC*)&Perl_sv_2iv_flags},
{"Perl_newXS_flags", (PERL_PROC*)&Perl_newXS_flags},

View File

@@ -461,7 +461,7 @@ get_emsg_source(void)
if (SOURCING_NAME != NULL && other_sourcing_name())
{
char_u *sname = estack_sfile(FALSE);
char_u *sname = estack_sfile(ESTACK_NONE);
char_u *tofree = sname;
if (sname == NULL)

View File

@@ -4,7 +4,7 @@ estack_T *estack_push(etype_T type, char_u *name, long lnum);
estack_T *estack_push_ufunc(ufunc_T *ufunc, long lnum);
int estack_top_is_ufunc(ufunc_T *ufunc, long lnum);
estack_T *estack_pop(void);
char_u *estack_sfile(int is_sfile);
char_u *estack_sfile(estack_arg_T which);
void ex_runtime(exarg_T *eap);
int do_in_path(char_u *path, char_u *name, int flags, void (*callback)(char_u *fname, void *ck), void *cookie);
int do_in_runtimepath(char_u *name, int flags, void (*callback)(char_u *fname, void *ck), void *cookie);

View File

@@ -2,7 +2,7 @@
void init_job_options(jobopt_T *opt);
buf_T *term_start(typval_T *argvar, char **argv, jobopt_T *opt, int flags);
void ex_terminal(exarg_T *eap);
int term_write_session(FILE *fd, win_T *wp);
int term_write_session(FILE *fd, win_T *wp, hashtab_T *terminal_bufs);
int term_should_restore(buf_T *buf);
void free_terminal(buf_T *buf);
void free_unused_terminals(void);

View File

@@ -6,6 +6,7 @@ type_T *get_dict_type(type_T *member_type, garray_T *type_gap);
type_T *alloc_func_type(type_T *ret_type, int argcount, garray_T *type_gap);
type_T *get_func_type(type_T *ret_type, int argcount, garray_T *type_gap);
int func_type_add_arg_types(type_T *functype, int argcount, garray_T *type_gap);
int need_convert_to_bool(type_T *type, typval_T *tv);
type_T *typval2type(typval_T *tv, garray_T *type_gap);
type_T *typval2type_vimvar(typval_T *tv, garray_T *type_gap);
int check_typval_type(type_T *expected, typval_T *actual_tv, int argidx);

View File

@@ -111,10 +111,10 @@ estack_pop(void)
/*
* Get the current value for <sfile> in allocated memory.
* "is_sfile" is TRUE for <sfile> itself.
* "which" is ESTACK_SFILE for <sfile> and ESTACK_STACK for <stack>.
*/
char_u *
estack_sfile(int is_sfile UNUSED)
estack_sfile(estack_arg_T which UNUSED)
{
estack_T *entry;
#ifdef FEAT_EVAL
@@ -127,7 +127,7 @@ estack_sfile(int is_sfile UNUSED)
entry = ((estack_T *)exestack.ga_data) + exestack.ga_len - 1;
#ifdef FEAT_EVAL
if (is_sfile && entry->es_type != ETYPE_UFUNC)
if (which == ESTACK_SFILE && entry->es_type != ETYPE_UFUNC)
#endif
{
if (entry->es_name == NULL)
@@ -144,6 +144,9 @@ estack_sfile(int is_sfile UNUSED)
entry = ((estack_T *)exestack.ga_data) + idx;
if (entry->es_name != NULL)
{
long lnum = 0;
char *dots;
len = STRLEN(entry->es_name) + 15;
type_name = "";
if (entry->es_type != last_type)
@@ -159,15 +162,20 @@ estack_sfile(int is_sfile UNUSED)
len += STRLEN(type_name);
if (ga_grow(&ga, (int)len) == FAIL)
break;
if (idx == exestack.ga_len - 1 || entry->es_lnum == 0)
// For the bottom entry: do not add the line number, it is used
// in <slnum>. Also leave it out when the number is not set.
vim_snprintf((char *)ga.ga_data + ga.ga_len, len, "%s%s%s",
type_name, entry->es_name,
idx == exestack.ga_len - 1 ? "" : "..");
if (idx == exestack.ga_len - 1)
lnum = which == ESTACK_STACK ? SOURCING_LNUM : 0;
else
vim_snprintf((char *)ga.ga_data + ga.ga_len, len, "%s%s[%ld]..",
type_name, entry->es_name, entry->es_lnum);
lnum = entry->es_lnum;
dots = idx == exestack.ga_len - 1 ? "" : "..";
if (lnum == 0)
// For the bottom entry of <sfile>: do not add the line number,
// it is used in <slnum>. Also leave it out when the number is
// not set.
vim_snprintf((char *)ga.ga_data + ga.ga_len, len, "%s%s%s",
type_name, entry->es_name, dots);
else
vim_snprintf((char *)ga.ga_data + ga.ga_len, len, "%s%s[%ld]%s",
type_name, entry->es_name, lnum, dots);
ga.ga_len += (int)STRLEN((char *)ga.ga_data + ga.ga_len);
}
}

View File

@@ -305,8 +305,12 @@ put_view(
win_T *wp,
int add_edit, // add ":edit" command to view
unsigned *flagp, // vop_flags or ssop_flags
int current_arg_idx) // current argument index of the window, use
// -1 if unknown
int current_arg_idx // current argument index of the window, use
// -1 if unknown
#ifdef FEAT_TERMINAL
, hashtab_T *terminal_bufs
#endif
)
{
win_T *save_curwin;
int f;
@@ -349,7 +353,7 @@ put_view(
# ifdef FEAT_TERMINAL
if (bt_terminal(wp->w_buffer))
{
if (term_write_session(fd, wp) == FAIL)
if (term_write_session(fd, wp, terminal_bufs) == FAIL)
return FAIL;
}
else
@@ -588,6 +592,12 @@ makeopens(
frame_T *tab_topframe;
int cur_arg_idx = 0;
int next_arg_idx = 0;
int ret = FAIL;
#ifdef FEAT_TERMINAL
hashtab_T terminal_bufs;
hash_init(&terminal_bufs);
#endif
if (ssop_flags & SSOP_BUFFERS)
only_save_windows = FALSE; // Save ALL buffers
@@ -596,25 +606,25 @@ makeopens(
// sessionable variables.
#ifdef FEAT_EVAL
if (put_line(fd, "let v:this_session=expand(\"<sfile>:p\")") == FAIL)
return FAIL;
goto fail;
if (ssop_flags & SSOP_GLOBALS)
if (store_session_globals(fd) == FAIL)
return FAIL;
goto fail;
#endif
// Close all windows and tabs but one.
if (put_line(fd, "silent only") == FAIL)
return FAIL;
goto fail;
if ((ssop_flags & SSOP_TABPAGES)
&& put_line(fd, "silent tabonly") == FAIL)
return FAIL;
goto fail;
// Now a :cd command to the session directory or the current directory
if (ssop_flags & SSOP_SESDIR)
{
if (put_line(fd, "exe \"cd \" . escape(expand(\"<sfile>:p:h\"), ' ')")
== FAIL)
return FAIL;
goto fail;
}
else if (ssop_flags & SSOP_CURDIR)
{
@@ -625,7 +635,7 @@ makeopens(
|| put_eol(fd) == FAIL)
{
vim_free(sname);
return FAIL;
goto fail;
}
vim_free(sname);
}
@@ -633,27 +643,27 @@ makeopens(
// If there is an empty, unnamed buffer we will wipe it out later.
// Remember the buffer number.
if (put_line(fd, "if expand('%') == '' && !&modified && line('$') <= 1 && getline(1) == ''") == FAIL)
return FAIL;
goto fail;
if (put_line(fd, " let s:wipebuf = bufnr('%')") == FAIL)
return FAIL;
goto fail;
if (put_line(fd, "endif") == FAIL)
return FAIL;
goto fail;
// Now save the current files, current buffer first.
if (put_line(fd, "set shortmess=aoO") == FAIL)
return FAIL;
goto fail;
// the global argument list
if (ses_arglist(fd, "argglobal", &global_alist.al_ga,
!(ssop_flags & SSOP_CURDIR), &ssop_flags) == FAIL)
return FAIL;
goto fail;
if (ssop_flags & SSOP_RESIZE)
{
// Note: after the restore we still check it worked!
if (fprintf(fd, "set lines=%ld columns=%ld" , Rows, Columns) < 0
|| put_eol(fd) == FAIL)
return FAIL;
goto fail;
}
#ifdef FEAT_GUI
@@ -665,7 +675,7 @@ makeopens(
{
// Note: after the restore we still check it worked!
if (fprintf(fd, "winpos %d %d", x, y) < 0 || put_eol(fd) == FAIL)
return FAIL;
goto fail;
}
}
#endif
@@ -677,7 +687,7 @@ makeopens(
if (p_stal == 1 && first_tabpage->tp_next != NULL)
{
if (put_line(fd, "set stal=2") == FAIL)
return FAIL;
goto fail;
restore_stal = TRUE;
}
@@ -695,9 +705,9 @@ makeopens(
// later local options won't be copied to the new tabs.
FOR_ALL_TABPAGES(tp)
if (tp->tp_next != NULL && put_line(fd, "tabnew") == FAIL)
return FAIL;
goto fail;
if (first_tabpage->tp_next != NULL && put_line(fd, "tabrewind") == FAIL)
return FAIL;
goto fail;
}
for (tabnr = 1; ; ++tabnr)
{
@@ -739,13 +749,13 @@ makeopens(
)
{
if (need_tabnext && put_line(fd, "tabnext") == FAIL)
return FAIL;
goto fail;
need_tabnext = FALSE;
if (fputs("edit ", fd) < 0
|| ses_fname(fd, wp->w_buffer, &ssop_flags, TRUE)
== FAIL)
return FAIL;
goto fail;
if (!wp->w_arg_idx_invalid)
edited_win = wp;
break;
@@ -754,17 +764,17 @@ makeopens(
// If no file got edited create an empty tab page.
if (need_tabnext && put_line(fd, "tabnext") == FAIL)
return FAIL;
goto fail;
// Save current window layout.
if (put_line(fd, "set splitbelow splitright") == FAIL)
return FAIL;
goto fail;
if (ses_win_rec(fd, tab_topframe) == FAIL)
return FAIL;
goto fail;
if (!p_sb && put_line(fd, "set nosplitbelow") == FAIL)
return FAIL;
goto fail;
if (!p_spr && put_line(fd, "set nosplitright") == FAIL)
return FAIL;
goto fail;
// Check if window sizes can be restored (no windows omitted).
// Remember the window number of the current window after restoring.
@@ -781,7 +791,7 @@ makeopens(
// Go to the first window.
if (put_line(fd, "wincmd t") == FAIL)
return FAIL;
goto fail;
// If more than one window, see if sizes can be restored.
// First set 'winheight' and 'winwidth' to 1 to avoid the windows being
@@ -794,9 +804,9 @@ makeopens(
|| put_line(fd, "set winheight=1") == FAIL
|| put_line(fd, "set winminwidth=0") == FAIL
|| put_line(fd, "set winwidth=1") == FAIL)
return FAIL;
goto fail;
if (nr > 1 && ses_winsizes(fd, restore_size, tab_firstwin) == FAIL)
return FAIL;
goto fail;
// Restore the tab-local working directory if specified
// Do this before the windows, so that the window-local directory can
@@ -806,7 +816,7 @@ makeopens(
if (fputs("tcd ", fd) < 0
|| ses_put_fname(fd, tp->tp_localdir, &ssop_flags) == FAIL
|| put_eol(fd) == FAIL)
return FAIL;
goto fail;
did_lcd = TRUE;
}
@@ -815,11 +825,14 @@ makeopens(
{
if (!ses_do_win(wp))
continue;
if (put_view(fd, wp, wp != edited_win, &ssop_flags,
cur_arg_idx) == FAIL)
return FAIL;
if (put_view(fd, wp, wp != edited_win, &ssop_flags, cur_arg_idx
#ifdef FEAT_TERMINAL
, &terminal_bufs
#endif
) == FAIL)
goto fail;
if (nr > 1 && put_line(fd, "wincmd w") == FAIL)
return FAIL;
goto fail;
next_arg_idx = wp->w_arg_idx;
}
@@ -831,12 +844,12 @@ makeopens(
// Restore cursor to the current window if it's not the first one.
if (cnr > 1 && (fprintf(fd, "%dwincmd w", cnr) < 0
|| put_eol(fd) == FAIL))
return FAIL;
goto fail;
// Restore window sizes again after jumping around in windows, because
// the current window has a minimum size while others may not.
if (nr > 1 && ses_winsizes(fd, restore_size, tab_firstwin) == FAIL)
return FAIL;
goto fail;
// Don't continue in another tab page when doing only the current one
// or when at the last tab page.
@@ -848,10 +861,10 @@ makeopens(
{
if (fprintf(fd, "tabnext %d", tabpage_index(curtab)) < 0
|| put_eol(fd) == FAIL)
return FAIL;
goto fail;
}
if (restore_stal && put_line(fd, "set stal=1") == FAIL)
return FAIL;
goto fail;
// Now put the remaining buffers into the buffer list.
// This is near the end, so that when 'hidden' is set we don't create extra
@@ -872,38 +885,43 @@ makeopens(
if (fprintf(fd, "badd +%ld ", buf->b_wininfo == NULL ? 1L
: buf->b_wininfo->wi_fpos.lnum) < 0
|| ses_fname(fd, buf, &ssop_flags, TRUE) == FAIL)
return FAIL;
goto fail;
}
}
// Wipe out an empty unnamed buffer we started in.
if (put_line(fd, "if exists('s:wipebuf') && len(win_findbuf(s:wipebuf)) == 0")
== FAIL)
return FAIL;
goto fail;
if (put_line(fd, " silent exe 'bwipe ' . s:wipebuf") == FAIL)
return FAIL;
goto fail;
if (put_line(fd, "endif") == FAIL)
return FAIL;
goto fail;
if (put_line(fd, "unlet! s:wipebuf") == FAIL)
return FAIL;
goto fail;
// Re-apply 'winheight', 'winwidth' and 'shortmess'.
if (fprintf(fd, "set winheight=%ld winwidth=%ld shortmess=%s",
p_wh, p_wiw, p_shm) < 0 || put_eol(fd) == FAIL)
return FAIL;
goto fail;
// Re-apply 'winminheight' and 'winminwidth'.
if (fprintf(fd, "set winminheight=%ld winminwidth=%ld",
p_wmh, p_wmw) < 0 || put_eol(fd) == FAIL)
return FAIL;
goto fail;
// Lastly, execute the x.vim file if it exists.
if (put_line(fd, "let s:sx = expand(\"<sfile>:p:r\").\"x.vim\"") == FAIL
|| put_line(fd, "if filereadable(s:sx)") == FAIL
|| put_line(fd, " exe \"source \" . fnameescape(s:sx)") == FAIL
|| put_line(fd, "endif") == FAIL)
return FAIL;
goto fail;
return OK;
ret = OK;
fail:
#ifdef FEAT_TERMINAL
hash_clear_all(&terminal_bufs, 0);
#endif
return ret;
}
/*
@@ -1084,6 +1102,11 @@ ex_mkrc(exarg_T *eap)
char_u *viewFile = NULL;
unsigned *flagp;
#endif
#ifdef FEAT_TERMINAL
hashtab_T terminal_bufs;
hash_init(&terminal_bufs);
#endif
if (eap->cmdidx == CMD_mksession || eap->cmdidx == CMD_mkview)
{
@@ -1240,8 +1263,11 @@ ex_mkrc(exarg_T *eap)
}
else
{
failed |= (put_view(fd, curwin, !using_vdir, flagp,
-1) == FAIL);
failed |= (put_view(fd, curwin, !using_vdir, flagp, -1
#ifdef FEAT_TERMINAL
, &terminal_bufs
#endif
) == FAIL);
}
if (put_line(fd, "let &so = s:so_save | let &siso = s:siso_save")
== FAIL)

View File

@@ -1381,7 +1381,7 @@ struct type_S {
typedef struct
{
vartype_T v_type;
char v_lock; // see below: VAR_LOCKED, VAR_FIXED
char v_lock; // see below: VAR_LOCKED, VAR_FIXED, VAR_BOOL_OK
union
{
varnumber_T v_number; // number value
@@ -1406,8 +1406,9 @@ typedef struct
// allowed to mask existing functions
// Values for "v_lock".
#define VAR_LOCKED 1 // locked with lock(), can use unlock()
#define VAR_FIXED 2 // locked forever
#define VAR_LOCKED 1 // locked with lock(), can use unlock()
#define VAR_FIXED 2 // locked forever
#define VAR_BOOL_OK 4 // can be convered to bool
/*
* Structure to hold an item of a list: an internal variable without a name.

View File

@@ -935,9 +935,30 @@ theend:
* Return FAIL if writing fails.
*/
int
term_write_session(FILE *fd, win_T *wp)
term_write_session(FILE *fd, win_T *wp, hashtab_T *terminal_bufs)
{
term_T *term = wp->w_buffer->b_term;
const int bufnr = wp->w_buffer->b_fnum;
term_T *term = wp->w_buffer->b_term;
if (wp->w_buffer->b_nwindows > 1)
{
// There are multiple views into this terminal buffer. We don't want to
// create the terminal multiple times. If it's the first time, create,
// otherwise link to the first buffer.
char id_as_str[NUMBUFLEN];
hashitem_T *entry;
vim_snprintf(id_as_str, sizeof(id_as_str), "%d", bufnr);
entry = hash_find(terminal_bufs, (char_u *)id_as_str);
if (!HASHITEM_EMPTY(entry))
{
// we've already opened this terminal buffer
if (fprintf(fd, "execute 'buffer ' . s:term_buf_%d", bufnr) < 0)
return FAIL;
return put_eol(fd);
}
}
// Create the terminal and run the command. This is not without
// risk, but let's assume the user only creates a session when this
@@ -951,6 +972,19 @@ term_write_session(FILE *fd, win_T *wp)
#endif
if (term->tl_command != NULL && fputs((char *)term->tl_command, fd) < 0)
return FAIL;
if (put_eol(fd) != OK)
return FAIL;
if (fprintf(fd, "let s:term_buf_%d = bufnr()", bufnr) < 0)
return FAIL;
if (wp->w_buffer->b_nwindows > 1)
{
char *hash_key = alloc(NUMBUFLEN);
vim_snprintf(hash_key, NUMBUFLEN, "%d", bufnr);
hash_add(terminal_bufs, (char_u *)hash_key);
}
return put_eol(fd);
}

View File

@@ -39,9 +39,9 @@ endfunc
func Test_expand_sfile_and_stack()
call assert_match('test_expand_func\.vim$', s:sfile)
let expected = 'script .*testdir/runtest.vim\[\d\+\]\.\.function RunTheTest\[\d\+\]\.\.Test_expand_sfile_and_stack$'
call assert_match(expected , expand('<sfile>'))
call assert_match(expected , expand('<stack>'))
let expected = 'script .*testdir/runtest.vim\[\d\+\]\.\.function RunTheTest\[\d\+\]\.\.Test_expand_sfile_and_stack'
call assert_match(expected .. '$', expand('<sfile>'))
call assert_match(expected .. '\[4\]' , expand('<stack>'))
" Call in script-local function
call assert_match('script .*testdir/runtest.vim\[\d\+\]\.\.function RunTheTest\[\d\+\]\.\.Test_expand_sfile_and_stack\[7\]\.\.<SNR>\d\+_expand_sfile$', s:expand_sfile())
@@ -53,11 +53,12 @@ func Test_expand_sfile_and_stack()
" Use <stack> from sourced script.
let lines =<< trim END
" comment here
let g:stack_value = expand('<stack>')
END
call writefile(lines, 'Xstack')
source Xstack
call assert_match('\<Xstack$', g:stack_value)
call assert_match('\<Xstack\[2\]$', g:stack_value)
call delete('Xstack')
endfunc

View File

@@ -455,6 +455,32 @@ func Test_mksession_terminal_restore_other()
call delete('Xtest_mks.out')
endfunc
func Test_mksession_terminal_shared_windows()
terminal
let term_buf = bufnr()
new
execute "buffer" term_buf
mksession! Xtest_mks.out
let lines = readfile('Xtest_mks.out')
let found_creation = 0
let found_use = 0
for line in lines
if line =~ '^terminal'
let found_creation = 1
call assert_match('terminal ++curwin ++cols=\d\+ ++rows=\d\+', line)
elseif line =~ "^execute 'buffer ' . s:term_buf_" . term_buf . "$"
let found_use = 1
endif
endfor
call assert_true(found_creation && found_use)
call StopShellInTerminal(term_buf)
call delete('Xtest_mks.out')
endfunc
endif " has('terminal')
" Test :mkview with a file argument.

View File

@@ -112,6 +112,7 @@ foobar/?
set spelllang=
call assert_fails("call spellbadword('maxch')", 'E756:')
call assert_fails("spelldump", 'E756:')
call delete('Xwords.spl')
call delete('Xwords')

View File

@@ -179,6 +179,11 @@ func Spellfile_Test(content, emsg)
" Add the spell file header and version (VIMspell2)
let v = 0z56494D7370656C6C32 + a:content
call writefile(v, splfile, 'b')
" 'encoding' is set before each test to clear the previously loaded suggest
" file from memory.
set encoding=utf-8
set runtimepath=./Xtest
set spelllang=Xtest
if a:emsg != ''
@@ -299,6 +304,12 @@ func Test_spellfile_format_error()
" SN_SOFO: missing sofoto
call Spellfile_Test(0z0600000000050001610000, 'E759:')
" SN_SOFO: empty sofofrom and sofoto
call Spellfile_Test(0z06000000000400000000FF000000000000000000000000, '')
" SN_SOFO: multi-byte characters in sofofrom and sofoto
call Spellfile_Test(0z0600000000080002CF810002CF82FF000000000000000000000000, '')
" SN_COMPOUND: compmax is less than 2
call Spellfile_Test(0z08000000000101, 'E759:')
@@ -308,6 +319,12 @@ func Test_spellfile_format_error()
" SN_COMPOUND: missing compoptions
call Spellfile_Test(0z080000000005040101, 'E758:')
" SN_COMPOUND: missing comppattern
call Spellfile_Test(0z08000000000704010100000001, 'E758:')
" SN_COMPOUND: incorrect comppatlen
call Spellfile_Test(0z080000000007040101000000020165, 'E758:')
" SN_INFO: missing info
call Spellfile_Test(0z0F0000000005040101, '')
@@ -317,6 +334,12 @@ func Test_spellfile_format_error()
" SN_MAP: missing midword
call Spellfile_Test(0z0700000000040102, '')
" SN_MAP: empty map string
call Spellfile_Test(0z070000000000FF000000000000000000000000, '')
" SN_MAP: duplicate multibyte character
call Spellfile_Test(0z070000000004DC81DC81, 'E783:')
" SN_SYLLABLE: missing SYLLABLE item
call Spellfile_Test(0z0900000000040102, '')
@@ -333,12 +356,21 @@ func Test_spellfile_format_error()
" LWORDTREE: missing tree node value
call Spellfile_Test(0zFF0000000402, 'E758:')
" LWORDTREE: incorrect sibling node count
call Spellfile_Test(0zFF00000001040000000000000000, 'E759:')
" KWORDTREE: missing tree node
call Spellfile_Test(0zFF0000000000000004, 'E758:')
" PREFIXTREE: missing tree node
call Spellfile_Test(0zFF000000000000000000000004, 'E758:')
" PREFIXTREE: incorrect prefcondnr
call Spellfile_Test(0zFF000000000000000000000002010200000020, 'E759:')
" PREFIXTREE: invalid nodeidx
call Spellfile_Test(0zFF00000000000000000000000201010000, 'E759:')
let &rtp = save_rtp
call delete('Xtest', 'rf')
endfunc
@@ -506,6 +538,14 @@ func Test_wordlist_dic()
let output = execute('mkspell! -ascii Xwordlist.spl Xwordlist.dic')
call assert_match('Ignored 1 words with non-ASCII characters', output)
" keep case of a word
let lines =<< trim [END]
example/=
[END]
call writefile(lines, 'Xwordlist.dic')
let output = execute('mkspell! Xwordlist.spl Xwordlist.dic')
call assert_match('Compressed keep-case:', output)
call delete('Xwordlist.spl')
call delete('Xwordlist.dic')
endfunc
@@ -513,8 +553,14 @@ endfunc
" Test for the :mkspell command
func Test_mkspell()
call assert_fails('mkspell Xtest_us.spl', 'E751:')
call assert_fails('mkspell Xtest.spl abc', 'E484:')
call assert_fails('mkspell a b c d e f g h i j k', 'E754:')
" create a .aff file but not the .dic file
call writefile([], 'Xtest.aff')
call assert_fails('mkspell Xtest.spl Xtest', 'E484:')
call delete('Xtest.aff')
call writefile([], 'Xtest.spl')
call writefile([], 'Xtest.dic')
call assert_fails('mkspell Xtest.spl Xtest.dic', 'E13:')
@@ -706,6 +752,43 @@ func Test_aff_file_format_error()
let output = execute('mkspell! Xtest.spl Xtest')
call assert_match('Illegal flag in Xtest.aff line 2: L', output)
" missing character in UPP entry. The character table is used only in a
" non-utf8 encoding
call writefile(['FOL abc', 'LOW abc', 'UPP A'], 'Xtest.aff')
let save_encoding = &encoding
set encoding=cp949
call assert_fails('mkspell! Xtest.spl Xtest', 'E761:')
let &encoding = save_encoding
" character range doesn't match between FOL and LOW entries
call writefile(["FOL \u0102bc", 'LOW abc', 'UPP ABC'], 'Xtest.aff')
let save_encoding = &encoding
set encoding=cp949
call assert_fails('mkspell! Xtest.spl Xtest', 'E762:')
let &encoding = save_encoding
" character range doesn't match between FOL and UPP entries
call writefile(["FOL \u0102bc", "LOW \u0102bc", 'UPP ABC'], 'Xtest.aff')
let save_encoding = &encoding
set encoding=cp949
call assert_fails('mkspell! Xtest.spl Xtest', 'E762:')
let &encoding = save_encoding
" additional characters in LOW and UPP entries
call writefile(["FOL ab", "LOW abc", 'UPP ABC'], 'Xtest.aff')
let save_encoding = &encoding
set encoding=cp949
call assert_fails('mkspell! Xtest.spl Xtest', 'E761:')
let &encoding = save_encoding
" missing UPP entry
call writefile(["FOL abc", "LOW abc"], 'Xtest.aff')
let save_encoding = &encoding
set encoding=cp949
let output = execute('mkspell! Xtest.spl Xtest')
call assert_match('Missing FOL/LOW/UPP line in Xtest.aff', output)
let &encoding = save_encoding
" duplicate word in the .dic file
call writefile(['2', 'good', 'good', 'good'], 'Xtest.dic')
call writefile(['NAME vim'], 'Xtest.aff')
@@ -713,6 +796,20 @@ func Test_aff_file_format_error()
call assert_match('First duplicate word in Xtest.dic line 3: good', output)
call assert_match('2 duplicate word(s) in Xtest.dic', output)
" use multiple .aff files with different values for COMPOUNDWORDMAX and
" MIDWORD (number and string)
call writefile(['1', 'world'], 'Xtest_US.dic')
call writefile(['1', 'world'], 'Xtest_CA.dic')
call writefile(["COMPOUNDWORDMAX 3", "MIDWORD '-"], 'Xtest_US.aff')
call writefile(["COMPOUNDWORDMAX 4", "MIDWORD '="], 'Xtest_CA.aff')
let output = execute('mkspell! Xtest.spl Xtest_US Xtest_CA')
call assert_match('COMPOUNDWORDMAX value differs from what is used in another .aff file', output)
call assert_match('MIDWORD value differs from what is used in another .aff file', output)
call delete('Xtest_US.dic')
call delete('Xtest_CA.dic')
call delete('Xtest_US.aff')
call delete('Xtest_CA.aff')
call delete('Xtest.dic')
call delete('Xtest.aff')
call delete('Xtest.spl')

View File

@@ -1199,6 +1199,29 @@ def Test_disassemble_invert_bool()
assert_equal(true, InvertBool())
enddef
def ReturnBool(): bool
let var: bool = "no" && [] || 123
return var
enddef
def Test_disassemble_return_bool()
let instr = execute('disassemble ReturnBool')
assert_match('ReturnBool\_s*' ..
'let var: bool = "no" && \[\] || 123\_s*' ..
'0 PUSHS "no"\_s*' ..
'1 JUMP_AND_KEEP_IF_FALSE -> 3\_s*' ..
'2 NEWLIST size 0\_s*' ..
'3 JUMP_AND_KEEP_IF_TRUE -> 5\_s*' ..
'4 PUSHNR 123\_s*' ..
'5 2BOOL (!!val)\_s*' ..
'\d STORE $0\_s*' ..
'return var\_s*' ..
'\d LOAD $0\_s*' ..
'\d RETURN',
instr)
assert_equal(true, InvertBool())
enddef
def Test_disassemble_compare()
let cases = [
['true == isFalse', 'COMPAREBOOL =='],

View File

@@ -2382,7 +2382,7 @@ func Test_expr_fails()
call CheckDefFailure(["CallMe ('yes')"], 'E476:', 1)
call CheckScriptFailure(["CallMe ('yes')"], 'E492:', 1)
call CheckScriptAndDefFailure(["CallMe2('yes','no')"], 'E1069:', 1)
call CheckDefAndScriptFailure(["CallMe2('yes','no')"], 'E1069:', 1)
call CheckDefFailure(["CallMe2('yes' , 'no')"], 'E1068:', 1)
call CheckDefFailure(["v:nosuch += 3"], 'E1001:', 1)

File diff suppressed because it is too large Load Diff

View File

@@ -39,17 +39,50 @@ let g:alist = [7]
let g:astring = 'text'
let g:anumber = 123
def Test_assignment()
def Test_assignment_bool()
let bool1: bool = true
assert_equal(v:true, bool1)
let bool2: bool = false
assert_equal(v:false, bool2)
let bool3: bool = 0
assert_equal(0, bool3)
assert_equal(false, bool3)
let bool4: bool = 1
assert_equal(1, bool4)
assert_equal(true, bool4)
let bool5: bool = 'yes' && 'no'
assert_equal(true, bool5)
let bool6: bool = [] && 99
assert_equal(false, bool6)
let bool7: bool = [] || #{a: 1} && 99
assert_equal(true, bool7)
let lines =<< trim END
vim9script
def GetFlag(): bool
let flag: bool = 1
return flag
enddef
let flag: bool = GetFlag()
assert_equal(true, flag)
flag = 0
assert_equal(false, flag)
flag = 1
assert_equal(true, flag)
flag = 99 || 123
assert_equal(true, flag)
flag = 'yes' && []
assert_equal(false, flag)
END
CheckScriptSuccess(lines)
CheckDefAndScriptFailure(['let x: bool = 2'], 'E1012:')
CheckDefAndScriptFailure(['let x: bool = -1'], 'E1012:')
CheckDefAndScriptFailure(['let x: bool = [1]'], 'E1012:')
CheckDefAndScriptFailure(['let x: bool = {}'], 'E1012:')
CheckDefAndScriptFailure(['let x: bool = "x"'], 'E1012:')
enddef
def Test_assignment()
CheckDefFailure(['let x:string'], 'E1069:')
CheckDefFailure(['let x:string = "x"'], 'E1069:')
CheckDefFailure(['let a:string = "x"'], 'E1069:')
@@ -164,8 +197,7 @@ def Test_assignment()
assert_equal('xxx', &t_TI)
&t_TI = save_TI
END
CheckDefSuccess(lines)
CheckScriptSuccess(['vim9script'] + lines)
CheckDefAndScriptSuccess(lines)
CheckDefFailure(['&t_TI = 123'], 'E1012:')
CheckScriptFailure(['vim9script', '&t_TI = 123'], 'E928:')

View File

@@ -48,7 +48,7 @@ enddef
" Check that a command fails both when used in a :def function and when used
" in Vim9 script.
def CheckScriptAndDefFailure(lines: list<string>, error: string, lnum = -3)
def CheckDefAndScriptFailure(lines: list<string>, error: string, lnum = -3)
CheckDefFailure(lines, error, lnum)
CheckScriptFailure(['vim9script'] + lines, error, lnum + 1)
enddef

View File

@@ -22,7 +22,7 @@
prepare_assert_error(garray_T *gap)
{
char buf[NUMBUFLEN];
char_u *sname = estack_sfile(FALSE);
char_u *sname = estack_sfile(ESTACK_NONE);
ga_init2(gap, 1, 100);
if (sname != NULL)

View File

@@ -9,10 +9,6 @@
#include "vim.h"
#ifdef AMIGA
# include <time.h> // for time()
#endif
/*
* Vim originated from Stevie version 3.6 (Fish disk 217) by GRWalter (Fred)
* It has been changed beyond recognition since then.
@@ -754,6 +750,46 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
1663,
/**/
1662,
/**/
1661,
/**/
1660,
/**/
1659,
/**/
1658,
/**/
1657,
/**/
1656,
/**/
1655,
/**/
1654,
/**/
1653,
/**/
1652,
/**/
1651,
/**/
1650,
/**/
1649,
/**/
1648,
/**/
1647,
/**/
1646,
/**/
1645,
/**/
1644,
/**/
1643,
/**/

View File

@@ -2097,8 +2097,7 @@ typedef struct stat stat_T;
# define USE_PRINTF_FORMAT_ATTRIBUTE
#endif
typedef enum
{
typedef enum {
ASSERT_EQUAL,
ASSERT_NOTEQUAL,
ASSERT_MATCH,
@@ -2128,6 +2127,13 @@ typedef enum {
USEPOPUP_HIDDEN // use info popup initially hidden
} use_popup_T;
// Argument for estack_sfile().
typedef enum {
ESTACK_NONE,
ESTACK_SFILE,
ESTACK_STACK
} estack_arg_T;
// Flags for assignment functions.
#define LET_IS_CONST 1 // ":const"
#define LET_NO_COMMAND 2 // "var = expr" without ":let" or ":const"

View File

@@ -729,6 +729,15 @@ need_type(
cctx_T *cctx,
int silent)
{
if (expected == &t_bool && actual != &t_bool
&& (actual->tt_flags & TTFLAG_BOOL_OK))
{
// Using "0", "1" or the result of an expression with "&&" or "||" as a
// boolean is OK but requires a conversion.
generate_2BOOL(cctx, FALSE);
return OK;
}
if (check_type(expected, actual, FALSE, 0) == OK)
return OK;
if (actual->tt_type != VAR_ANY
@@ -3926,6 +3935,8 @@ compile_and_or(
{
garray_T *instr = &cctx->ctx_instr;
garray_T end_ga;
garray_T *stack = &cctx->ctx_type_stack;
type_T **typep;
/*
* Repeat until there is no following "||" or "&&"
@@ -3985,6 +3996,20 @@ compile_and_or(
isn->isn_arg.jump.jump_where = instr->ga_len;
}
ga_clear(&end_ga);
// The resulting type can be used as a bool.
typep = ((type_T **)stack->ga_data) + stack->ga_len - 1;
if (*typep != &t_bool)
{
type_T *type = alloc_type(cctx->ctx_type_list);
if (type != NULL)
{
*type = **typep;
type->tt_flags |= TTFLAG_BOOL_OK;
*typep = type;
}
}
}
return OK;
@@ -4295,6 +4320,12 @@ compile_nested_function(exarg_T *eap, cctx_T *cctx)
ufunc_T *ufunc;
int r;
if (*name_start == '!')
{
emsg(_(e_cannot_use_bang_with_nested_def));
return NULL;
}
// Only g:Func() can use a namespace.
if (name_start[1] == ':' && !is_global)
{

View File

@@ -1665,6 +1665,7 @@ call_def_function(
// call a :def function
case ISN_DCALL:
SOURCING_LNUM = iptr->isn_lnum;
if (call_dfunc(iptr->isn_arg.dfunc.cdf_idx,
iptr->isn_arg.dfunc.cdf_argcount,
&ectx) == FAIL)

View File

@@ -557,6 +557,7 @@ vim9_declare_scriptvar(exarg_T *eap, char_u *arg)
/*
* Check if the type of script variable "dest" allows assigning "value".
* If needed convert "value" to a bool.
*/
int
check_script_var_type(typval_T *dest, typval_T *value, char_u *name)
@@ -575,12 +576,24 @@ check_script_var_type(typval_T *dest, typval_T *value, char_u *name)
if (sv->sv_tv == dest)
{
int ret;
if (sv->sv_const)
{
semsg(_(e_readonlyvar), name);
return FAIL;
}
return check_typval_type(sv->sv_type, value, 0);
ret = check_typval_type(sv->sv_type, value, 0);
if (ret == OK && need_convert_to_bool(sv->sv_type, value))
{
int val = tv2bool(value);
clear_tv(value);
value->v_type = VAR_BOOL;
value->v_lock = 0;
value->vval.v_number = val ? VVAL_TRUE : VVAL_FALSE;
}
return ret;
}
}
iemsg("check_script_var_type(): not found");

View File

@@ -199,16 +199,16 @@ func_type_add_arg_types(
* Get a type_T for a typval_T.
* "type_list" is used to temporarily create types in.
*/
type_T *
typval2type(typval_T *tv, garray_T *type_gap)
static type_T *
typval2type_int(typval_T *tv, garray_T *type_gap)
{
type_T *actual;
type_T *type;
type_T *member_type;
if (tv->v_type == VAR_NUMBER)
return &t_number;
if (tv->v_type == VAR_BOOL)
return &t_bool; // not used
return &t_bool;
if (tv->v_type == VAR_STRING)
return &t_string;
@@ -276,13 +276,53 @@ typval2type(typval_T *tv, garray_T *type_gap)
}
}
actual = alloc_type(type_gap);
if (actual == NULL)
type = alloc_type(type_gap);
if (type == NULL)
return NULL;
actual->tt_type = tv->v_type;
actual->tt_member = &t_any;
type->tt_type = tv->v_type;
type->tt_member = &t_any;
return actual;
return type;
}
/*
* Return TRUE if "tv" is not a bool but should be converted to bool.
*/
int
need_convert_to_bool(type_T *type, typval_T *tv)
{
return type != NULL && type == &t_bool && tv->v_type != VAR_BOOL
&& ((tv->v_lock & VAR_BOOL_OK)
|| (tv->v_type == VAR_NUMBER
&& (tv->vval.v_number == 0 || tv->vval.v_number == 1)));
}
/*
* Get a type_T for a typval_T and handle VAR_BOOL_OK.
* "type_list" is used to temporarily create types in.
*/
type_T *
typval2type(typval_T *tv, garray_T *type_gap)
{
type_T *type = typval2type_int(tv, type_gap);
if (type != NULL && type != &t_bool
&& ((tv->v_type == VAR_NUMBER
&& (tv->vval.v_number == 0 || tv->vval.v_number == 1))
|| (tv->v_lock & VAR_BOOL_OK)))
{
type_T *newtype = alloc_type(type_gap);
// Number 0 and 1 and expression with "&&" or "||" can also be used
// for bool.
if (newtype != NULL)
{
*newtype = *type;
newtype->tt_flags = TTFLAG_BOOL_OK;
type = newtype;
}
}
return type;
}
/*
@@ -359,7 +399,7 @@ check_type(type_T *expected, type_T *actual, int give_msg, int argidx)
{
if (expected->tt_type != actual->tt_type)
{
if (expected->tt_type == VAR_BOOL && actual->tt_type == VAR_NUMBER
if (expected->tt_type == VAR_BOOL
&& (actual->tt_flags & TTFLAG_BOOL_OK))
// Using number 0 or 1 for bool is OK.
return OK;