changeset 13575:4df23d9bad47 v8.0.1660

patch 8.0.1660: the terminal API "drop" command doesn't support options commit https://github.com/vim/vim/commit/333b80acf3a44e462456e6d5730e47ffa449c83d Author: Bram Moolenaar <Bram@vim.org> Date: Wed Apr 4 22:57:29 2018 +0200 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.
author Christian Brabandt <cb@256bit.org>
date Wed, 04 Apr 2018 23:00:07 +0200
parents 73c69063091f
children 8e08ded3a3e6
files runtime/doc/terminal.txt src/eval.c src/ex_cmds.h src/ex_docmd.c src/fileio.c src/misc2.c src/proto/ex_docmd.pro src/terminal.c src/testdir/test_terminal.vim src/version.c
diffstat 10 files changed, 216 insertions(+), 33 deletions(-) [+]
line wrap: on
line diff
--- a/runtime/doc/terminal.txt
+++ b/runtime/doc/terminal.txt
@@ -25,7 +25,7 @@ 1. Basic use			|terminal-use|
       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 @@ On Unix a pty is used to make it possibl
 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 @@ Currently supported commands:
 <		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"}]
 
--- a/src/eval.c
+++ b/src/eval.c
@@ -6590,7 +6590,7 @@ set_cmdarg(exarg_T *eap, char_u *oldarg)
 	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 @@ set_cmdarg(exarg_T *eap, char_u *oldarg)
 
     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",
--- a/src/ex_cmds.h
+++ b/src/ex_cmds.h
@@ -1778,7 +1778,7 @@ struct exarg
     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 */
--- a/src/ex_docmd.c
+++ b/src/ex_docmd.c
@@ -5308,6 +5308,18 @@ skip_cmd_arg(
     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 @@ getargopt(exarg_T *eap)
 #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 @@ getargopt(exarg_T *eap)
     {
 	/* 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
--- a/src/fileio.c
+++ b/src/fileio.c
@@ -2779,22 +2779,22 @@ readfile_linenr(
     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)
-#endif
-						 + 15));
+		+ (unsigned)STRLEN(buf->b_p_fenc)
+#endif
+	    );
     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);
-#endif
-    eap->force_ff = 7;
+    sprintf((char *)eap->cmd, "e");
+#endif
+    eap->force_ff = *buf->b_p_ff;
 
     eap->force_bin = buf->b_p_bin ? FORCE_BIN : FORCE_NOBIN;
     eap->read_edit = FALSE;
--- a/src/misc2.c
+++ b/src/misc2.c
@@ -3161,7 +3161,7 @@ get_fileformat_force(
     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)
--- a/src/proto/ex_docmd.pro
+++ b/src/proto/ex_docmd.pro
@@ -12,6 +12,7 @@ char_u *skip_range(char_u *cmd, int *ctx
 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);
--- 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 @@ init_default_colors(term_T *term)
 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 @@ handle_drop_command(listitem_T *item)
 	}
     }
 
-    /* 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);
 }
 
 /*
--- a/src/testdir/test_terminal.vim
+++ b/src/testdir/test_terminal.vim
@@ -1049,17 +1049,14 @@ func Test_terminal_dumpdiff_options()
   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 @@ func Test_terminal_api_drop_newwin()
   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')
--- a/src/version.c
+++ b/src/version.c
@@ -763,6 +763,8 @@ static char *(features[]) =
 static int included_patches[] =
 {   /* Add new patch number below this line */
 /**/
+    1660,
+/**/
     1659,
 /**/
     1658,