Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
brammool committed Apr 4, 2018
1 parent 1f8495c commit 333b80a
Show file tree
Hide file tree
Showing 10 changed files with 214 additions and 31 deletions.
20 changes: 17 additions & 3 deletions runtime/doc/terminal.txt
Expand Up @@ -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|
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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"}]
Expand Down
6 changes: 4 additions & 2 deletions src/eval.c
Expand Up @@ -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;
Expand All @@ -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",
Expand Down
2 changes: 1 addition & 1 deletion src/ex_cmds.h
Expand Up @@ -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 */
Expand Down
22 changes: 14 additions & 8 deletions src/ex_docmd.c
Expand Up @@ -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.
Expand Down Expand Up @@ -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)
Expand All @@ -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
Expand Down
14 changes: 7 additions & 7 deletions src/fileio.c
Expand Up @@ -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;
Expand Down
2 changes: 1 addition & 1 deletion src/misc2.c
Expand Up @@ -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)
Expand Down
1 change: 1 addition & 0 deletions src/proto/ex_docmd.pro
Expand Up @@ -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);
Expand Down
59 changes: 55 additions & 4 deletions src/terminal.c
Expand Up @@ -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
Expand Down Expand Up @@ -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)
Expand All @@ -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);
}

/*
Expand Down
117 changes: 112 additions & 5 deletions src/testdir/test_terminal.vim
Expand Up @@ -1049,24 +1049,131 @@ 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')
let buf = RunVimInTerminal('-S Xscript', {})
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')
Expand Down
2 changes: 2 additions & 0 deletions src/version.c
Expand Up @@ -762,6 +762,8 @@ static char *(features[]) =

static int included_patches[] =
{ /* Add new patch number below this line */
/**/
1660,
/**/
1659,
/**/
Expand Down

0 comments on commit 333b80a

Please sign in to comment.