]> granicus.if.org Git - vim/commitdiff
patch 8.0.1660: the terminal API "drop" command doesn't support options v8.0.1660
authorBram Moolenaar <Bram@vim.org>
Wed, 4 Apr 2018 20:57:29 +0000 (22:57 +0200)
committerBram Moolenaar <Bram@vim.org>
Wed, 4 Apr 2018 20:57:29 +0000 (22:57 +0200)
Problem:    The terminal API "drop" command doesn't support options.
Solution:   Implement the options.

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

index 54c7e1f044bcf4cec5727f186a0d460d65eed42d..f575c82d1b2be98d4f603781941e253a6caa9b65 100644 (file)
@@ -25,7 +25,7 @@ If the result is "1" you have it.
       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 possible to run all kinds of commands.  You
 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"}]
 
index 2da56a47afb305b009eb96940d2b7ae95af71fa6..c965d64f2d479b4e4233508c1ef10701e1ab792c 100644 (file)
@@ -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",
index 41c7c80cb7b53a443cb921cb2f7d7d9ba33ff09a..48b025315734263dcff3570657204a58d9d0ea50 100644 (file)
@@ -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 */
index 3a6c7cfb15f45115dfcb7033e93dfb246afbac1d..b0130046e14e5f1fbb361e583c5dc76c32766c16 100644 (file)
@@ -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
index 05c3df50bc4e0cd6c7db776c0ccf15a3f1ec0a2f..e2fa3e22b6ad45a5902881d3010afbd9d5a4f708 100644 (file)
@@ -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)
+               + (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;
index cd1dcf054a7fbb822499c901e30aca569d201cd1..9127e669ae143bf6df413bcd8184a29900c838d5 100644 (file)
@@ -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)
index 3819531929088eed30430f6431ebfa3707e7ec1d..0eace6222f7ecfb30ccd6efc54efbc4bdda5889f 100644 (file)
@@ -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);
index b60799d7f1237cceb2f8dffbdbf0a9c3bd9c3451..32680620550fe5d85c31321f9284fd89dd46c1a2 100644 (file)
@@ -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);
 }
 
 /*
index eac54c1d68ef5158abf1ad7c0c64b552b891a64c..218b4ca6f610707f6fce61abf46299b596d03627 100644 (file)
@@ -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')
index cdd8b418de172c84ccbcf68120e50d5dd265ac30..2d566ca14f0ad933b09ec0de5191a0b7292313d1 100644 (file)
@@ -762,6 +762,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    1660,
 /**/
     1659,
 /**/