patch 8.0.1660: the terminal API "drop" command doesn't support options
Problem: The terminal API "drop" command doesn't support options.
Solution: Implement the options.
diff --git a/runtime/doc/terminal.txt b/runtime/doc/terminal.txt
index 54c7e1f..f575c82 100644
--- a/runtime/doc/terminal.txt
+++ b/runtime/doc/terminal.txt
@@ -25,7 +25,7 @@
MS-Windows |terminal-ms-windows|
2. Terminal communication |terminal-communication|
Vim to job: term_sendkeys() |terminal-to-job|
- Job to Vim: JSON API |terminal-api|
+ Job to Vim: JSON API |terminal-api|
Using the client-server feature |terminal-client-server|
3. Remote testing |terminal-testing|
4. Diffing screen dumps |terminal-diff|
@@ -352,7 +352,7 @@
can even run Vim in the terminal! That's used for debugging, see below.
Environment variables are used to pass information to the running job:
- TERM name of the terminal, 'term'
+ TERM name of the terminal, from the 'term' option
ROWS number of rows in the terminal initially
LINES same as ROWS
COLUMNS number of columns in the terminal initially
@@ -443,11 +443,25 @@
< Output from `:echo` may be erased by a redraw, use `:echomsg`
to be able to see it with `:messages`.
- drop {filename}
+ drop {filename} [options]
Let Vim open a file, like the `:drop` command. If {filename}
is already open in a window, switch to that window. Otherwise
open a new window to edit {filename}.
+
+ [options] is only used when opening a new window. If present,
+ it must be a Dict. Similarly to |++opt|, These entries are recognized:
+ "ff" file format: "dos", "mac" or "unix"
+ "fileformat" idem
+ "enc" overrides 'fileencoding'
+ "encoding" idem
+ "bin" sets 'binary'
+ "binary" idem
+ "nobin" resets 'binary'
+ "nobinary" idem
+ "bad" specifies behavior for bad characters, see
+ |++bad|
+
Example in JSON: >
["drop", "path/file.txt", {"ff": "dos"}]
diff --git a/src/eval.c b/src/eval.c
index 2da56a4..c965d64 100644
--- a/src/eval.c
+++ b/src/eval.c
@@ -6590,7 +6590,7 @@
len += 7;
if (eap->force_ff != 0)
- len += (unsigned)STRLEN(eap->cmd + eap->force_ff) + 6;
+ len += 10; /* " ++ff=unix" */
# ifdef FEAT_MBYTE
if (eap->force_enc != 0)
len += (unsigned)STRLEN(eap->cmd + eap->force_enc) + 7;
@@ -6614,7 +6614,9 @@
if (eap->force_ff != 0)
sprintf((char *)newval + STRLEN(newval), " ++ff=%s",
- eap->cmd + eap->force_ff);
+ eap->force_ff == 'u' ? "unix"
+ : eap->force_ff == 'd' ? "dos"
+ : "mac");
#ifdef FEAT_MBYTE
if (eap->force_enc != 0)
sprintf((char *)newval + STRLEN(newval), " ++enc=%s",
diff --git a/src/ex_cmds.h b/src/ex_cmds.h
index 41c7c80..48b0253 100644
--- a/src/ex_cmds.h
+++ b/src/ex_cmds.h
@@ -1778,7 +1778,7 @@
int regname; /* register name (NUL if none) */
int force_bin; /* 0, FORCE_BIN or FORCE_NOBIN */
int read_edit; /* ++edit argument */
- int force_ff; /* ++ff= argument (index in cmd[]) */
+ int force_ff; /* ++ff= argument (first char of argument) */
#ifdef FEAT_MBYTE
int force_enc; /* ++enc= argument (index in cmd[]) */
int bad_char; /* BAD_KEEP, BAD_DROP or replacement byte */
diff --git a/src/ex_docmd.c b/src/ex_docmd.c
index 3a6c7cf..b013004 100644
--- a/src/ex_docmd.c
+++ b/src/ex_docmd.c
@@ -5308,6 +5308,18 @@
return p;
}
+ int
+get_bad_opt(char_u *p, exarg_T *eap)
+{
+ if (STRICMP(p, "keep") == 0)
+ eap->bad_char = BAD_KEEP;
+ else if (STRICMP(p, "drop") == 0)
+ eap->bad_char = BAD_DROP;
+ else if (MB_BYTE2LEN(*p) == 1 && p[1] == NUL)
+ eap->bad_char = *p;
+ return FAIL;
+}
+
/*
* Get "++opt=arg" argument.
* Return FAIL or OK.
@@ -5387,6 +5399,7 @@
#endif
if (check_ff_value(eap->cmd + eap->force_ff) == FAIL)
return FAIL;
+ eap->force_ff = eap->cmd[eap->force_ff];
#ifdef FEAT_MBYTE
}
else if (pp == &eap->force_enc)
@@ -5399,14 +5412,7 @@
{
/* Check ++bad= argument. Must be a single-byte character, "keep" or
* "drop". */
- p = eap->cmd + bad_char_idx;
- if (STRICMP(p, "keep") == 0)
- eap->bad_char = BAD_KEEP;
- else if (STRICMP(p, "drop") == 0)
- eap->bad_char = BAD_DROP;
- else if (MB_BYTE2LEN(*p) == 1 && p[1] == NUL)
- eap->bad_char = *p;
- else
+ if (get_bad_opt(eap->cmd + bad_char_idx, eap) == FAIL)
return FAIL;
}
#endif
diff --git a/src/fileio.c b/src/fileio.c
index 05c3df5..e2fa3e2 100644
--- a/src/fileio.c
+++ b/src/fileio.c
@@ -2779,22 +2779,22 @@
int
prep_exarg(exarg_T *eap, buf_T *buf)
{
- eap->cmd = alloc((unsigned)(STRLEN(buf->b_p_ff)
+ eap->cmd = alloc(15
#ifdef FEAT_MBYTE
- + STRLEN(buf->b_p_fenc)
+ + (unsigned)STRLEN(buf->b_p_fenc)
#endif
- + 15));
+ );
if (eap->cmd == NULL)
return FAIL;
#ifdef FEAT_MBYTE
- sprintf((char *)eap->cmd, "e ++ff=%s ++enc=%s", buf->b_p_ff, buf->b_p_fenc);
- eap->force_enc = 14 + (int)STRLEN(buf->b_p_ff);
+ sprintf((char *)eap->cmd, "e ++enc=%s", buf->b_p_fenc);
+ eap->force_enc = 8;
eap->bad_char = buf->b_bad_char;
#else
- sprintf((char *)eap->cmd, "e ++ff=%s", buf->b_p_ff);
+ sprintf((char *)eap->cmd, "e");
#endif
- eap->force_ff = 7;
+ eap->force_ff = *buf->b_p_ff;
eap->force_bin = buf->b_p_bin ? FORCE_BIN : FORCE_NOBIN;
eap->read_edit = FALSE;
diff --git a/src/misc2.c b/src/misc2.c
index cd1dcf0..9127e66 100644
--- a/src/misc2.c
+++ b/src/misc2.c
@@ -3161,7 +3161,7 @@
int c;
if (eap != NULL && eap->force_ff != 0)
- c = eap->cmd[eap->force_ff];
+ c = eap->force_ff;
else
{
if ((eap != NULL && eap->force_bin != 0)
diff --git a/src/proto/ex_docmd.pro b/src/proto/ex_docmd.pro
index 3819531..0eace62 100644
--- a/src/proto/ex_docmd.pro
+++ b/src/proto/ex_docmd.pro
@@ -12,6 +12,7 @@
void ex_ni(exarg_T *eap);
int expand_filename(exarg_T *eap, char_u **cmdlinep, char_u **errormsgp);
void separate_nextcmd(exarg_T *eap);
+int get_bad_opt(char_u *p, exarg_T *eap);
int ends_excmd(int c);
char_u *find_nextcmd(char_u *p);
char_u *check_nextcmd(char_u *p);
diff --git a/src/terminal.c b/src/terminal.c
index b60799d..3268062 100644
--- a/src/terminal.c
+++ b/src/terminal.c
@@ -38,7 +38,6 @@
* in tl_scrollback are no longer used.
*
* TODO:
- * - For the "drop" command accept another argument for options.
* - Add a way to set the 16 ANSI colors, to be used for 'termguicolors' and in
* the GUI.
* - Win32: Make terminal used for :!cmd in the GUI work better. Allow for
@@ -3152,10 +3151,12 @@
handle_drop_command(listitem_T *item)
{
char_u *fname = get_tv_string(&item->li_tv);
+ listitem_T *opt_item = item->li_next;
int bufnr;
win_T *wp;
tabpage_T *tp;
exarg_T ea;
+ char_u *tofree = NULL;
bufnr = buflist_add(fname, BLN_LISTED | BLN_NOOPT);
FOR_ALL_TAB_WINDOWS(tp, wp)
@@ -3168,10 +3169,60 @@
}
}
- /* open in new window, like ":sbuffer N" */
vim_memset(&ea, 0, sizeof(ea));
- ea.cmd = (char_u *)"sbuffer";
- goto_buffer(&ea, DOBUF_FIRST, FORWARD, bufnr);
+
+ if (opt_item != NULL && opt_item->li_tv.v_type == VAR_DICT
+ && opt_item->li_tv.vval.v_dict != NULL)
+ {
+ dict_T *dict = opt_item->li_tv.vval.v_dict;
+ char_u *p;
+
+ p = get_dict_string(dict, (char_u *)"ff", FALSE);
+ if (p == NULL)
+ p = get_dict_string(dict, (char_u *)"fileformat", FALSE);
+ if (p != NULL)
+ {
+ if (check_ff_value(p) == FAIL)
+ ch_log(NULL, "Invalid ff argument to drop: %s", p);
+ else
+ ea.force_ff = *p;
+ }
+ p = get_dict_string(dict, (char_u *)"enc", FALSE);
+ if (p == NULL)
+ p = get_dict_string(dict, (char_u *)"encoding", FALSE);
+ if (p != NULL)
+ {
+ ea.cmd = alloc((int)STRLEN(p) + 10);
+ if (ea.cmd != NULL)
+ {
+ sprintf((char *)ea.cmd, "sbuf ++enc=%s", p);
+ ea.force_enc = 11;
+ tofree = ea.cmd;
+ }
+ }
+
+ p = get_dict_string(dict, (char_u *)"bad", FALSE);
+ if (p != NULL)
+ get_bad_opt(p, &ea);
+
+ if (dict_find(dict, (char_u *)"bin", -1) != NULL)
+ ea.force_bin = FORCE_BIN;
+ if (dict_find(dict, (char_u *)"binary", -1) != NULL)
+ ea.force_bin = FORCE_BIN;
+ if (dict_find(dict, (char_u *)"nobin", -1) != NULL)
+ ea.force_bin = FORCE_NOBIN;
+ if (dict_find(dict, (char_u *)"nobinary", -1) != NULL)
+ ea.force_bin = FORCE_NOBIN;
+ }
+
+ /* open in new window, like ":split fname" */
+ if (ea.cmd == NULL)
+ ea.cmd = (char_u *)"split";
+ ea.arg = fname;
+ ea.cmdidx = CMD_split;
+ ex_splitview(&ea);
+
+ vim_free(tofree);
}
/*
diff --git a/src/testdir/test_terminal.vim b/src/testdir/test_terminal.vim
index eac54c1..218b4ca 100644
--- a/src/testdir/test_terminal.vim
+++ b/src/testdir/test_terminal.vim
@@ -1049,17 +1049,14 @@
set laststatus&
endfunc
-func Test_terminal_api_drop_newwin()
- if !CanRunVimInTerminal()
- return
- endif
+func Api_drop_common(options)
call assert_equal(1, winnr('$'))
" Use the title termcap entries to output the escape sequence.
call writefile([
\ 'set title',
\ 'exe "set t_ts=\<Esc>]51; t_fs=\x07"',
- \ 'let &titlestring = ''["drop","Xtextfile"]''',
+ \ 'let &titlestring = ''["drop","Xtextfile"' . a:options . ']''',
\ 'redraw',
\ "set t_ts=",
\ ], 'Xscript')
@@ -1067,6 +1064,116 @@
call WaitFor({-> bufnr('Xtextfile') > 0})
call assert_equal('Xtextfile', expand('%:t'))
call assert_true(winnr('$') >= 3)
+ return buf
+endfunc
+
+func Test_terminal_api_drop_newwin()
+ if !CanRunVimInTerminal()
+ return
+ endif
+ let buf = Api_drop_common('')
+ call assert_equal(0, &bin)
+ call assert_equal('', &fenc)
+
+ call StopVimInTerminal(buf)
+ call delete('Xscript')
+ bwipe Xtextfile
+endfunc
+
+func Test_terminal_api_drop_newwin_bin()
+ if !CanRunVimInTerminal()
+ return
+ endif
+ let buf = Api_drop_common(',{"bin":1}')
+ call assert_equal(1, &bin)
+
+ call StopVimInTerminal(buf)
+ call delete('Xscript')
+ bwipe Xtextfile
+endfunc
+
+func Test_terminal_api_drop_newwin_binary()
+ if !CanRunVimInTerminal()
+ return
+ endif
+ let buf = Api_drop_common(',{"binary":1}')
+ call assert_equal(1, &bin)
+
+ call StopVimInTerminal(buf)
+ call delete('Xscript')
+ bwipe Xtextfile
+endfunc
+
+func Test_terminal_api_drop_newwin_nobin()
+ if !CanRunVimInTerminal()
+ return
+ endif
+ set binary
+ let buf = Api_drop_common(',{"nobin":1}')
+ call assert_equal(0, &bin)
+
+ call StopVimInTerminal(buf)
+ call delete('Xscript')
+ bwipe Xtextfile
+ set nobinary
+endfunc
+
+func Test_terminal_api_drop_newwin_nobinary()
+ if !CanRunVimInTerminal()
+ return
+ endif
+ set binary
+ let buf = Api_drop_common(',{"nobinary":1}')
+ call assert_equal(0, &bin)
+
+ call StopVimInTerminal(buf)
+ call delete('Xscript')
+ bwipe Xtextfile
+ set nobinary
+endfunc
+
+func Test_terminal_api_drop_newwin_ff()
+ if !CanRunVimInTerminal()
+ return
+ endif
+ let buf = Api_drop_common(',{"ff":"dos"}')
+ call assert_equal("dos", &ff)
+
+ call StopVimInTerminal(buf)
+ call delete('Xscript')
+ bwipe Xtextfile
+endfunc
+
+func Test_terminal_api_drop_newwin_fileformat()
+ if !CanRunVimInTerminal()
+ return
+ endif
+ let buf = Api_drop_common(',{"fileformat":"dos"}')
+ call assert_equal("dos", &ff)
+
+ call StopVimInTerminal(buf)
+ call delete('Xscript')
+ bwipe Xtextfile
+endfunc
+
+func Test_terminal_api_drop_newwin_enc()
+ if !CanRunVimInTerminal()
+ return
+ endif
+ let buf = Api_drop_common(',{"enc":"utf-16"}')
+ call assert_equal("utf-16", &fenc)
+
+ call StopVimInTerminal(buf)
+ call delete('Xscript')
+ bwipe Xtextfile
+endfunc
+
+func Test_terminal_api_drop_newwin_encoding()
+ if !CanRunVimInTerminal()
+ return
+ endif
+ let buf = Api_drop_common(',{"encoding":"utf-16"}')
+ call assert_equal("utf-16", &fenc)
call StopVimInTerminal(buf)
call delete('Xscript')
diff --git a/src/version.c b/src/version.c
index cdd8b41..2d566ca 100644
--- a/src/version.c
+++ b/src/version.c
@@ -763,6 +763,8 @@
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
+ 1660,
+/**/
1659,
/**/
1658,