mirror of
https://github.com/macvim-dev/macvim.git
synced 2026-06-11 15:37:29 +02:00
Merge remote-tracking branch 'vim/master'
This commit is contained in:
+34
-3
@@ -1,4 +1,4 @@
|
||||
*develop.txt* For Vim version 8.0. Last change: 2017 Jul 31
|
||||
*develop.txt* For Vim version 8.0. Last change: 2018 Apr 17
|
||||
|
||||
|
||||
VIM REFERENCE MANUAL by Bram Moolenaar
|
||||
@@ -185,9 +185,40 @@ The basic steps to make changes to the code:
|
||||
C COMPILER *style-compiler*
|
||||
|
||||
The minimal C compiler version supported is C89, also known as ANSI C.
|
||||
Later standards don't add much and C89 is the widest supported.
|
||||
Later standards, such as C99, are not widely supported, or at least not 100%
|
||||
supported. Therefore we use only some of the C99 features and disallow some
|
||||
(at least for now).
|
||||
|
||||
One restriction that this implies: no // comments, only /* comments */.
|
||||
Please don't make changes everywhere to use the C99 features, it causes merge
|
||||
problems for existing patches. Only use them for new and changed code.
|
||||
|
||||
Comments ~
|
||||
|
||||
Traditionally Vim uses /* comments */. We intend to keep it that way,
|
||||
especially for file and function headers. For new code or lines of code that
|
||||
change, it is allowed to use // comments. Especially when it comes after
|
||||
code:
|
||||
int some_var; // single line comment useful here
|
||||
|
||||
Enums ~
|
||||
|
||||
The last item in an enum may have a trailing comma. C89 didn't allow this.
|
||||
|
||||
Types ~
|
||||
|
||||
"long long" is allowed and can be expected to be 64 bits. Use %lld in printf
|
||||
formats. Also "long long unsigned" with %llu.
|
||||
|
||||
Not to be used ~
|
||||
|
||||
These C99 features are not to be used, because not enough compilers support
|
||||
them:
|
||||
- Declaration after Statements (MSVC 2012 does not support it). All
|
||||
declarations need to be at the start of the block.
|
||||
- Variable length arrays (even in C11 this is an optional feature).
|
||||
- _Bool and _Complex types.
|
||||
- "inline" (it's hardly ever needed, let the optimizer do its work)
|
||||
- flexible array members: Not supported by HP-UX C compiler (John Marriott)
|
||||
|
||||
|
||||
USE OF COMMON FUNCTIONS *style-functions*
|
||||
|
||||
+16
-8
@@ -8124,15 +8124,23 @@ A jump table for the options with a short description can be found at |Q_op|.
|
||||
'termsize' 'tms' string (default "")
|
||||
local to window
|
||||
{not in Vi}
|
||||
Size of the |terminal| window. Format: {rows}x{columns}.
|
||||
Size of the |terminal| window. Format: {rows}x{columns} or
|
||||
{rows}*{columns}.
|
||||
- When empty the terminal gets the size from the window.
|
||||
- When set (e.g., "24x80") the terminal size is not adjusted to the
|
||||
window size. If the window is smaller only the top-left part is
|
||||
displayed.
|
||||
When rows is zero then use the height of the window.
|
||||
When columns is zero then use the width of the window.
|
||||
For example: "30x0" uses 30 rows with the current window width.
|
||||
Using "0x0" is the same as empty.
|
||||
- When set with a "x" (e.g., "24x80") the terminal size is not
|
||||
adjusted to the window size. If the window is smaller only the
|
||||
top-left part is displayed.
|
||||
- When set with a "*" (e.g., "10*50") the terminal size follows the
|
||||
window size, but will not be smaller than the specified rows and/or
|
||||
columns.
|
||||
- When rows is zero then use the height of the window.
|
||||
- When columns is zero then use the width of the window.
|
||||
- Using "0x0" or "0*0" is the same as empty.
|
||||
|
||||
Examples:
|
||||
"30x0" uses 30 rows and the current window width.
|
||||
"20*0" uses at least 20 rows and the current window width.
|
||||
"0*40" uses the current window height and at least 40 columns.
|
||||
Note that the command running in the terminal window may still change
|
||||
the size of the terminal. In that case the Vim window will be
|
||||
adjusted to that size, if possible.
|
||||
|
||||
+33
-16
@@ -623,7 +623,8 @@ Starting ~
|
||||
Load the plugin with this command: >
|
||||
packadd termdebug
|
||||
< *:Termdebug*
|
||||
To start debugging use `:Termdebug` followed by the command name, for example: >
|
||||
To start debugging use `:Termdebug` or `:TermdebugCommand`` followed by the
|
||||
command name, for example: >
|
||||
:Termdebug vim
|
||||
|
||||
This opens two windows:
|
||||
@@ -641,7 +642,8 @@ source file location will be displayed, if possible. A sign is used to
|
||||
highlight the current position, using highlight group debugPC.
|
||||
|
||||
If the buffer in the current window is modified, another window will be opened
|
||||
to display the current gdb position.
|
||||
to display the current gdb position. You can use `:Winbar` to add a window
|
||||
toolbar there.
|
||||
|
||||
Focus the terminal of the executed program to interact with it. This works
|
||||
the same as any command running in a terminal window.
|
||||
@@ -650,12 +652,25 @@ When the debugger ends, typically by typing "quit" in the gdb window, the two
|
||||
opened windows are closed.
|
||||
|
||||
Only one debugger can be active at a time.
|
||||
*:TermdebugCommand*
|
||||
If you want to give specific commands to the command being debugged, you can
|
||||
use the `:TermdebugCommand` command followed by the command name and
|
||||
additional parameters. >
|
||||
:TermdebugCommand vim --clean -c ':set nu'
|
||||
|
||||
To attach gdb to an already running executable, or use a core file, pass extra
|
||||
Both the `:Termdebug` and `:TermdebugCommand` support an optional "!" bang
|
||||
argument to start the command right away, without pausing at the gdb window
|
||||
(and cursor will be in the debugged window). For example: >
|
||||
:TermdebugCommand! vim --clean
|
||||
|
||||
To attach gdb to an already running executable or use a core file, pass extra
|
||||
arguments. E.g.: >
|
||||
:Termdebug vim core
|
||||
:Termdebug vim 98343
|
||||
|
||||
If no argument is given, you'll end up in a gdb window, in which you need to
|
||||
specify which command to run using e.g. the gdb `file` command.
|
||||
|
||||
|
||||
Example session ~
|
||||
*termdebug-example*
|
||||
@@ -728,18 +743,20 @@ Put focus on the gdb window to type commands there. Some common ones are:
|
||||
- frame N go to the Nth stack frame
|
||||
- continue continue execution
|
||||
|
||||
In the window showing the source code these commands can be used to control gdb:
|
||||
*:Run* *:Arguments*
|
||||
In the window showing the source code these commands can be used to control
|
||||
gdb:
|
||||
`:Run` [args] run the program with [args] or the previous arguments
|
||||
`:Arguments` {args} set arguments for the next `:Run`
|
||||
|
||||
`:Break` set a breakpoint at the current line; a sign will be displayed
|
||||
`:Clear` delete the breakpoint at the current line
|
||||
*:Break* set a breakpoint at the current line; a sign will be displayed
|
||||
*:Clear* delete the breakpoint at the current line
|
||||
|
||||
`:Step` execute the gdb "step" command
|
||||
`:Over` execute the gdb "next" command (`:Next` is a Vim command)
|
||||
`:Finish` execute the gdb "finish" command
|
||||
`:Continue` execute the gdb "continue" command
|
||||
`:Stop` interrupt the program
|
||||
*:Step* execute the gdb "step" command
|
||||
*:Over* execute the gdb "next" command (`:Next` is a Vim command)
|
||||
*:Finish* execute the gdb "finish" command
|
||||
*:Continue* execute the gdb "continue" command
|
||||
*:Stop* interrupt the program
|
||||
|
||||
If 'mouse' is set the plugin adds a window toolbar with these entries:
|
||||
Step `:Step`
|
||||
@@ -750,7 +767,7 @@ If 'mouse' is set the plugin adds a window toolbar with these entries:
|
||||
Eval `:Evaluate`
|
||||
This way you can use the mouse to perform the most common commands. You need
|
||||
to have the 'mouse' option set to enable mouse clicks.
|
||||
|
||||
*:Winbar*
|
||||
You can add the window toolbar in other windows you open with: >
|
||||
:Winbar
|
||||
|
||||
@@ -761,7 +778,7 @@ abandoned.
|
||||
|
||||
|
||||
Inspecting variables ~
|
||||
*termdebug-variables*
|
||||
*termdebug-variables* *:Evaluate*
|
||||
`:Evaluate` evaluate the expression under the cursor
|
||||
`K` same
|
||||
`:Evaluate` {expr} evaluate {expr}
|
||||
@@ -773,9 +790,9 @@ You can usually shorten `:Evaluate` to `:Ev`.
|
||||
|
||||
Other commands ~
|
||||
*termdebug-commands*
|
||||
:Gdb jump to the gdb window
|
||||
:Program jump to the window with the running program
|
||||
:Source jump to the window with the source code, create it if there
|
||||
*:Gdb* jump to the gdb window
|
||||
*:Program* jump to the window with the running program
|
||||
*:Source* jump to the window with the source code, create it if there
|
||||
isn't one
|
||||
|
||||
|
||||
|
||||
+30
-3
@@ -25,7 +25,8 @@ endif
|
||||
|
||||
" The command that starts debugging, e.g. ":Termdebug vim".
|
||||
" To end type "quit" in the gdb window.
|
||||
command -nargs=* -complete=file Termdebug call s:StartDebug(<f-args>)
|
||||
command -nargs=* -complete=file -bang Termdebug call s:StartDebug(<bang>0, <f-args>)
|
||||
command -nargs=+ -complete=file -bang TermdebugCommand call s:StartDebugCommand(<bang>0, <f-args>)
|
||||
|
||||
" Name of the gdb command, defaults to "gdb".
|
||||
if !exists('termdebugger')
|
||||
@@ -43,7 +44,17 @@ else
|
||||
endif
|
||||
hi default debugBreakpoint term=reverse ctermbg=red guibg=red
|
||||
|
||||
func s:StartDebug(...)
|
||||
func s:StartDebug(bang, ...)
|
||||
" First argument is the command to debug, second core file or process ID.
|
||||
call s:StartDebug_internal({'gdb_args': a:000, 'bang': a:bang})
|
||||
endfunc
|
||||
|
||||
func s:StartDebugCommand(bang, ...)
|
||||
" First argument is the command to debug, rest are run arguments.
|
||||
call s:StartDebug_internal({'gdb_args': [a:1], 'proc_args': a:000[1:], 'bang': a:bang})
|
||||
endfunc
|
||||
|
||||
func s:StartDebug_internal(dict)
|
||||
if exists('s:gdbwin')
|
||||
echoerr 'Terminal debugger already running'
|
||||
return
|
||||
@@ -95,7 +106,10 @@ func s:StartDebug(...)
|
||||
|
||||
" Open a terminal window to run the debugger.
|
||||
" Add -quiet to avoid the intro message causing a hit-enter prompt.
|
||||
let cmd = [g:termdebugger, '-quiet', '-tty', pty] + a:000
|
||||
let gdb_args = get(a:dict, 'gdb_args', [])
|
||||
let proc_args = get(a:dict, 'proc_args', [])
|
||||
|
||||
let cmd = [g:termdebugger, '-quiet', '-tty', pty] + gdb_args
|
||||
echomsg 'executing "' . join(cmd) . '"'
|
||||
let s:gdbbuf = term_start(cmd, {
|
||||
\ 'exit_cb': function('s:EndDebug'),
|
||||
@@ -109,6 +123,11 @@ func s:StartDebug(...)
|
||||
endif
|
||||
let s:gdbwin = win_getid(winnr())
|
||||
|
||||
" Set arguments to be run
|
||||
if len(proc_args)
|
||||
call term_sendkeys(s:gdbbuf, 'set args ' . join(proc_args) . "\r")
|
||||
endif
|
||||
|
||||
" Connect gdb to the communication pty, using the GDB/MI interface
|
||||
call term_sendkeys(s:gdbbuf, 'new-ui mi ' . commpty . "\r")
|
||||
|
||||
@@ -182,6 +201,14 @@ func s:StartDebug(...)
|
||||
au BufRead * call s:BufRead()
|
||||
au BufUnload * call s:BufUnloaded()
|
||||
augroup END
|
||||
|
||||
" Run the command if the bang attribute was given
|
||||
" and got to the window
|
||||
if get(a:dict, 'bang', 0)
|
||||
call s:SendCommand('-exec-run')
|
||||
call win_gotoid(s:ptywin)
|
||||
endif
|
||||
|
||||
endfunc
|
||||
|
||||
func s:EndDebug(job, status)
|
||||
|
||||
Vendored
+30
@@ -4177,6 +4177,36 @@ $as_echo "#define HAVE_SYS_WAIT_H 1" >>confdefs.h
|
||||
fi
|
||||
|
||||
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if the compiler can handle Vim code" >&5
|
||||
$as_echo_n "checking if the compiler can handle Vim code... " >&6; }
|
||||
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
|
||||
/* end confdefs.h. */
|
||||
#include <stdio.h>
|
||||
int
|
||||
main ()
|
||||
{
|
||||
|
||||
enum {
|
||||
one, // one comment
|
||||
two, // two comments
|
||||
three, // three comments
|
||||
};
|
||||
long long int a = 1;
|
||||
long long unsigned b = 2;
|
||||
printf("a %lld and a %llu", a, b);
|
||||
|
||||
;
|
||||
return 0;
|
||||
}
|
||||
_ACEOF
|
||||
if ac_fn_c_try_compile "$LINENO"; then :
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
|
||||
$as_echo "yes" >&6; }
|
||||
else
|
||||
as_fn_error $? "compiler does not work properly - see auto/config.log" "$LINENO" 5
|
||||
fi
|
||||
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
|
||||
|
||||
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking --enable-fail-if-missing argument" >&5
|
||||
$as_echo_n "checking --enable-fail-if-missing argument... " >&6; }
|
||||
|
||||
+16
-1
@@ -417,6 +417,8 @@ buf_hashtab_remove(buf_T *buf)
|
||||
hash_remove(&buf_hashtab, hi);
|
||||
}
|
||||
|
||||
static char *e_buflocked = N_("E937: Attempt to delete a buffer that is in use");
|
||||
|
||||
/*
|
||||
* Close the link to a buffer.
|
||||
* "action" is used when there is no longer a window for the buffer.
|
||||
@@ -476,8 +478,15 @@ close_buffer(
|
||||
if (term_job_running(buf->b_term))
|
||||
{
|
||||
if (wipe_buf || unload_buf)
|
||||
{
|
||||
if (buf->b_locked)
|
||||
{
|
||||
EMSG(_(e_buflocked));
|
||||
return;
|
||||
}
|
||||
/* Wiping out or unloading a terminal buffer kills the job. */
|
||||
free_terminal(buf);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* The job keeps running, hide the buffer. */
|
||||
@@ -499,7 +508,7 @@ close_buffer(
|
||||
* halfway a command that relies on it). Unloading is allowed. */
|
||||
if (buf->b_locked > 0 && (del_buf || wipe_buf))
|
||||
{
|
||||
EMSG(_("E937: Attempt to delete a buffer that is in use"));
|
||||
EMSG(_(e_buflocked));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1360,6 +1369,12 @@ do_buffer(
|
||||
int forward;
|
||||
bufref_T bufref;
|
||||
|
||||
if (buf->b_locked)
|
||||
{
|
||||
EMSG(_(e_buflocked));
|
||||
return FAIL;
|
||||
}
|
||||
|
||||
set_bufref(&bufref, buf);
|
||||
|
||||
/* When unloading or deleting a buffer that's already unloaded and
|
||||
|
||||
@@ -29,6 +29,25 @@ dnl in autoconf needs it, where it uses STDC_HEADERS.
|
||||
AC_HEADER_STDC
|
||||
AC_HEADER_SYS_WAIT
|
||||
|
||||
dnl Check that the C99 features that Vim uses are supported:
|
||||
dnl - // commands
|
||||
dnl - comma after last enum item
|
||||
dnl - "long long int" and "long long unsigned"
|
||||
dnl - flexible array member
|
||||
AC_MSG_CHECKING(if the compiler can handle Vim code)
|
||||
AC_TRY_COMPILE([#include <stdio.h>], [
|
||||
enum {
|
||||
one, // one comment
|
||||
two, // two comments
|
||||
three, // three comments
|
||||
};
|
||||
long long int a = 1;
|
||||
long long unsigned b = 2;
|
||||
printf("a %lld and a %llu", a, b);
|
||||
],
|
||||
AC_MSG_RESULT(yes),
|
||||
AC_MSG_ERROR([compiler does not work properly - see auto/config.log]))
|
||||
|
||||
dnl Check for the flag that fails if stuff are missing.
|
||||
|
||||
AC_MSG_CHECKING(--enable-fail-if-missing argument)
|
||||
|
||||
+13
-1
@@ -3665,7 +3665,9 @@ ins_compl_set_original_text(char_u *str)
|
||||
{
|
||||
char_u *p;
|
||||
|
||||
/* Replace the original text entry. */
|
||||
/* Replace the original text entry.
|
||||
* The ORIGINAL_TEXT flag is either at the first item or might possibly be
|
||||
* at the last item for backward completion */
|
||||
if (compl_first_match->cp_flags & ORIGINAL_TEXT) /* safety check */
|
||||
{
|
||||
p = vim_strsave(str);
|
||||
@@ -3675,6 +3677,16 @@ ins_compl_set_original_text(char_u *str)
|
||||
compl_first_match->cp_str = p;
|
||||
}
|
||||
}
|
||||
else if (compl_first_match->cp_prev != NULL
|
||||
&& (compl_first_match->cp_prev->cp_flags & ORIGINAL_TEXT))
|
||||
{
|
||||
p = vim_strsave(str);
|
||||
if (p != NULL)
|
||||
{
|
||||
vim_free(compl_first_match->cp_prev->cp_str);
|
||||
compl_first_match->cp_prev->cp_str = p;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
+23
-3
@@ -3894,10 +3894,30 @@ static int APP_BOTH;
|
||||
static void
|
||||
add_pack_plugin(char_u *fname, void *cookie)
|
||||
{
|
||||
if (cookie != &APP_LOAD && strstr((char *)p_rtp, (char *)fname) == NULL)
|
||||
/* directory is not yet in 'runtimepath', add it */
|
||||
if (add_pack_dir_to_rtp(fname) == FAIL)
|
||||
if (cookie != &APP_LOAD)
|
||||
{
|
||||
char_u *buf = alloc(MAXPATHL);
|
||||
char_u *p;
|
||||
int found = FALSE;
|
||||
|
||||
if (buf == NULL)
|
||||
return;
|
||||
p = p_rtp;
|
||||
while (*p != NUL)
|
||||
{
|
||||
copy_option_part(&p, buf, MAXPATHL, ",");
|
||||
if (pathcmp((char *)buf, (char *)fname, -1) == 0)
|
||||
{
|
||||
found = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
vim_free(buf);
|
||||
if (!found)
|
||||
/* directory is not yet in 'runtimepath', add it */
|
||||
if (add_pack_dir_to_rtp(fname) == FAIL)
|
||||
return;
|
||||
}
|
||||
|
||||
if (cookie != &APP_ADD_DIR)
|
||||
load_pack_plugin(fname);
|
||||
|
||||
+6
-6
@@ -1119,7 +1119,7 @@ main_loop(
|
||||
int cmdwin, /* TRUE when working in the command-line window */
|
||||
int noexmode) /* TRUE when return on entering Ex mode */
|
||||
{
|
||||
oparg_T oa; /* operator arguments */
|
||||
oparg_T oa; /* operator arguments */
|
||||
volatile int previous_got_int = FALSE; /* "got_int" was TRUE */
|
||||
#ifdef FEAT_CONCEAL
|
||||
/* these are static to avoid a compiler warning */
|
||||
@@ -1458,11 +1458,6 @@ getout_preserve_modified(int exitval)
|
||||
void
|
||||
getout(int exitval)
|
||||
{
|
||||
tabpage_T *tp;
|
||||
tabpage_T *next_tp;
|
||||
buf_T *buf;
|
||||
win_T *wp;
|
||||
|
||||
exiting = TRUE;
|
||||
#if defined(FEAT_JOB_CHANNEL)
|
||||
ch_log(NULL, "Exiting...");
|
||||
@@ -1491,6 +1486,11 @@ getout(int exitval)
|
||||
|
||||
if (v_dying <= 1)
|
||||
{
|
||||
tabpage_T *tp;
|
||||
tabpage_T *next_tp;
|
||||
buf_T *buf;
|
||||
win_T *wp;
|
||||
|
||||
/* Trigger BufWinLeave for all windows, but only once per buffer. */
|
||||
for (tp = first_tabpage; tp != NULL; tp = next_tp)
|
||||
{
|
||||
|
||||
@@ -1707,8 +1707,6 @@ str2special(
|
||||
{
|
||||
c = TO_SPECIAL(str[1], str[2]);
|
||||
str += 2;
|
||||
if (c == KS_ZERO) /* display <Nul> as ^@ or <Nul> */
|
||||
c = NUL;
|
||||
}
|
||||
if (IS_SPECIAL(c) || modifiers) /* special key */
|
||||
special = TRUE;
|
||||
|
||||
+3
-1
@@ -7587,7 +7587,9 @@ did_set_string_option(
|
||||
if (*curwin->w_p_tms != NUL)
|
||||
{
|
||||
p = skipdigits(curwin->w_p_tms);
|
||||
if (p == curwin->w_p_tms || *p != 'x' || *skipdigits(p + 1) != NUL)
|
||||
if (p == curwin->w_p_tms
|
||||
|| (*p != 'x' && *p != '*')
|
||||
|| *skipdigits(p + 1) != NUL)
|
||||
errmsg = e_invarg;
|
||||
}
|
||||
}
|
||||
|
||||
+201
-129
@@ -1183,7 +1183,8 @@ qf_init_ext(
|
||||
fields.errmsglen = CMDBUFFSIZE + 1;
|
||||
fields.errmsg = alloc_id(fields.errmsglen, aid_qf_errmsg);
|
||||
fields.pattern = alloc_id(CMDBUFFSIZE + 1, aid_qf_pattern);
|
||||
if (fields.namebuf == NULL || fields.errmsg == NULL || fields.pattern == NULL)
|
||||
if (fields.namebuf == NULL || fields.errmsg == NULL
|
||||
|| fields.pattern == NULL)
|
||||
goto qf_init_end;
|
||||
|
||||
if (efile != NULL && (state.fd = mch_fopen((char *)efile, "r")) == NULL)
|
||||
@@ -1817,7 +1818,6 @@ qf_push_dir(char_u *dirbuf, struct dir_stack_T **stackptr, int is_file_stack)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* pop dirbuf from the directory stack and return previous directory or NULL if
|
||||
* stack is empty
|
||||
@@ -4948,7 +4948,8 @@ enum {
|
||||
};
|
||||
|
||||
/*
|
||||
* Parse text from 'di' and return the quickfix list items
|
||||
* Parse text from 'di' and return the quickfix list items.
|
||||
* Existing quickfix lists are not modified.
|
||||
*/
|
||||
static int
|
||||
qf_get_list_from_lines(dict_T *what, dictitem_T *di, dict_T *retdict)
|
||||
@@ -5017,25 +5018,13 @@ qf_winid(qf_info_T *qi)
|
||||
}
|
||||
|
||||
/*
|
||||
* Return quickfix/location list details (title) as a
|
||||
* dictionary. 'what' contains the details to return. If 'list_idx' is -1,
|
||||
* then current list is used. Otherwise the specified list is used.
|
||||
* Convert the keys in 'what' to quickfix list property flags.
|
||||
*/
|
||||
int
|
||||
qf_get_properties(win_T *wp, dict_T *what, dict_T *retdict)
|
||||
static int
|
||||
qf_getprop_keys2flags(dict_T *what)
|
||||
{
|
||||
qf_info_T *qi = &ql_info;
|
||||
int status = OK;
|
||||
int qf_idx;
|
||||
dictitem_T *di;
|
||||
int flags = QF_GETLIST_NONE;
|
||||
|
||||
if ((di = dict_find(what, (char_u *)"lines", -1)) != NULL)
|
||||
return qf_get_list_from_lines(what, di, retdict);
|
||||
|
||||
if (wp != NULL)
|
||||
qi = GET_LOC_LIST(wp);
|
||||
|
||||
if (dict_find(what, (char_u *)"all", -1) != NULL)
|
||||
flags |= QF_GETLIST_ALL;
|
||||
|
||||
@@ -5066,140 +5055,223 @@ qf_get_properties(win_T *wp, dict_T *what, dict_T *retdict)
|
||||
if (dict_find(what, (char_u *)"changedtick", -1) != NULL)
|
||||
flags |= QF_GETLIST_TICK;
|
||||
|
||||
if (qi != NULL && qi->qf_listcount != 0)
|
||||
{
|
||||
qf_idx = qi->qf_curlist; /* default is the current list */
|
||||
if ((di = dict_find(what, (char_u *)"nr", -1)) != NULL)
|
||||
{
|
||||
/* Use the specified quickfix/location list */
|
||||
if (di->di_tv.v_type == VAR_NUMBER)
|
||||
{
|
||||
/* for zero use the current list */
|
||||
if (di->di_tv.vval.v_number != 0)
|
||||
{
|
||||
qf_idx = di->di_tv.vval.v_number - 1;
|
||||
if (qf_idx < 0 || qf_idx >= qi->qf_listcount)
|
||||
qf_idx = -1;
|
||||
}
|
||||
}
|
||||
else if (di->di_tv.v_type == VAR_STRING
|
||||
&& di->di_tv.vval.v_string != NULL
|
||||
&& STRCMP(di->di_tv.vval.v_string, "$") == 0)
|
||||
/* Get the last quickfix list number */
|
||||
qf_idx = qi->qf_listcount - 1;
|
||||
else
|
||||
qf_idx = -1;
|
||||
flags |= QF_GETLIST_NR;
|
||||
}
|
||||
return flags;
|
||||
}
|
||||
|
||||
if ((di = dict_find(what, (char_u *)"id", -1)) != NULL)
|
||||
/*
|
||||
* Return the quickfix list index based on 'nr' or 'id' in 'what'.
|
||||
* If 'nr' and 'id' are not present in 'what' then return the current
|
||||
* quickfix list index.
|
||||
* If 'nr' is zero then return the current quickfix list index.
|
||||
* If 'nr' is '$' then return the last quickfix list index.
|
||||
* If 'id' is present then return the index of the quickfix list with that id.
|
||||
* If 'id' is zero then return the quickfix list index specified by 'nr'.
|
||||
* Return -1, if quickfix list is not present or if the stack is empty.
|
||||
*/
|
||||
static int
|
||||
qf_getprop_qfidx(qf_info_T *qi, dict_T *what)
|
||||
{
|
||||
int qf_idx;
|
||||
dictitem_T *di;
|
||||
|
||||
qf_idx = qi->qf_curlist; /* default is the current list */
|
||||
if ((di = dict_find(what, (char_u *)"nr", -1)) != NULL)
|
||||
{
|
||||
/* Use the specified quickfix/location list */
|
||||
if (di->di_tv.v_type == VAR_NUMBER)
|
||||
{
|
||||
/* Look for a list with the specified id */
|
||||
if (di->di_tv.v_type == VAR_NUMBER)
|
||||
/* for zero use the current list */
|
||||
if (di->di_tv.vval.v_number != 0)
|
||||
{
|
||||
/*
|
||||
* For zero, use the current list or the list specifed by 'nr'
|
||||
*/
|
||||
if (di->di_tv.vval.v_number != 0)
|
||||
qf_idx = qf_id2nr(qi, di->di_tv.vval.v_number);
|
||||
flags |= QF_GETLIST_ID;
|
||||
qf_idx = di->di_tv.vval.v_number - 1;
|
||||
if (qf_idx < 0 || qf_idx >= qi->qf_listcount)
|
||||
qf_idx = -1;
|
||||
}
|
||||
else
|
||||
qf_idx = -1;
|
||||
}
|
||||
else if (di->di_tv.v_type == VAR_STRING
|
||||
&& di->di_tv.vval.v_string != NULL
|
||||
&& STRCMP(di->di_tv.vval.v_string, "$") == 0)
|
||||
/* Get the last quickfix list number */
|
||||
qf_idx = qi->qf_listcount - 1;
|
||||
else
|
||||
qf_idx = -1;
|
||||
}
|
||||
|
||||
if ((di = dict_find(what, (char_u *)"id", -1)) != NULL)
|
||||
{
|
||||
/* Look for a list with the specified id */
|
||||
if (di->di_tv.v_type == VAR_NUMBER)
|
||||
{
|
||||
/*
|
||||
* For zero, use the current list or the list specified by 'nr'
|
||||
*/
|
||||
if (di->di_tv.vval.v_number != 0)
|
||||
qf_idx = qf_id2nr(qi, di->di_tv.vval.v_number);
|
||||
}
|
||||
else
|
||||
qf_idx = -1;
|
||||
}
|
||||
|
||||
return qf_idx;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return default values for quickfix list properties in retdict.
|
||||
*/
|
||||
static int
|
||||
qf_getprop_defaults(qf_info_T *qi, int flags, dict_T *retdict)
|
||||
{
|
||||
int status = OK;
|
||||
|
||||
if (flags & QF_GETLIST_TITLE)
|
||||
status = dict_add_nr_str(retdict, "title", 0L, (char_u *)"");
|
||||
if ((status == OK) && (flags & QF_GETLIST_ITEMS))
|
||||
{
|
||||
list_T *l = list_alloc();
|
||||
if (l != NULL)
|
||||
status = dict_add_list(retdict, "items", l);
|
||||
else
|
||||
status = FAIL;
|
||||
}
|
||||
if ((status == OK) && (flags & QF_GETLIST_NR))
|
||||
status = dict_add_nr_str(retdict, "nr", 0L, NULL);
|
||||
if ((status == OK) && (flags & QF_GETLIST_WINID))
|
||||
status = dict_add_nr_str(retdict, "winid", qf_winid(qi), NULL);
|
||||
if ((status == OK) && (flags & QF_GETLIST_CONTEXT))
|
||||
status = dict_add_nr_str(retdict, "context", 0L, (char_u *)"");
|
||||
if ((status == OK) && (flags & QF_GETLIST_ID))
|
||||
status = dict_add_nr_str(retdict, "id", 0L, NULL);
|
||||
if ((status == OK) && (flags & QF_GETLIST_IDX))
|
||||
status = dict_add_nr_str(retdict, "idx", 0L, NULL);
|
||||
if ((status == OK) && (flags & QF_GETLIST_SIZE))
|
||||
status = dict_add_nr_str(retdict, "size", 0L, NULL);
|
||||
if ((status == OK) && (flags & QF_GETLIST_TICK))
|
||||
status = dict_add_nr_str(retdict, "changedtick", 0L, NULL);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return the quickfix list title as 'title' in retdict
|
||||
*/
|
||||
static int
|
||||
qf_getprop_title(qf_info_T *qi, int qf_idx, dict_T *retdict)
|
||||
{
|
||||
char_u *t;
|
||||
|
||||
t = qi->qf_lists[qf_idx].qf_title;
|
||||
if (t == NULL)
|
||||
t = (char_u *)"";
|
||||
return dict_add_nr_str(retdict, "title", 0L, t);
|
||||
}
|
||||
|
||||
/*
|
||||
* Return the quickfix list items/entries as 'items' in retdict
|
||||
*/
|
||||
static int
|
||||
qf_getprop_items(qf_info_T *qi, int qf_idx, dict_T *retdict)
|
||||
{
|
||||
int status = OK;
|
||||
list_T *l = list_alloc();
|
||||
if (l != NULL)
|
||||
{
|
||||
(void)get_errorlist(qi, NULL, qf_idx, l);
|
||||
dict_add_list(retdict, "items", l);
|
||||
}
|
||||
else
|
||||
status = FAIL;
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return the quickfix list context (if any) as 'context' in retdict.
|
||||
*/
|
||||
static int
|
||||
qf_getprop_ctx(qf_info_T *qi, int qf_idx, dict_T *retdict)
|
||||
{
|
||||
int status;
|
||||
dictitem_T *di;
|
||||
|
||||
if (qi->qf_lists[qf_idx].qf_ctx != NULL)
|
||||
{
|
||||
di = dictitem_alloc((char_u *)"context");
|
||||
if (di != NULL)
|
||||
{
|
||||
copy_tv(qi->qf_lists[qf_idx].qf_ctx, &di->di_tv);
|
||||
status = dict_add(retdict, di);
|
||||
if (status == FAIL)
|
||||
dictitem_free(di);
|
||||
}
|
||||
else
|
||||
status = FAIL;
|
||||
}
|
||||
else
|
||||
status = dict_add_nr_str(retdict, "context", 0L, (char_u *)"");
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return the quickfix list index as 'idx' in retdict
|
||||
*/
|
||||
static int
|
||||
qf_getprop_idx(qf_info_T *qi, int qf_idx, dict_T *retdict)
|
||||
{
|
||||
int idx = qi->qf_lists[qf_idx].qf_index;
|
||||
if (qi->qf_lists[qf_idx].qf_count == 0)
|
||||
/* For empty lists, qf_index is set to 1 */
|
||||
idx = 0;
|
||||
return dict_add_nr_str(retdict, "idx", idx, NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Return quickfix/location list details (title) as a
|
||||
* dictionary. 'what' contains the details to return. If 'list_idx' is -1,
|
||||
* then current list is used. Otherwise the specified list is used.
|
||||
*/
|
||||
int
|
||||
qf_get_properties(win_T *wp, dict_T *what, dict_T *retdict)
|
||||
{
|
||||
qf_info_T *qi = &ql_info;
|
||||
int status = OK;
|
||||
int qf_idx;
|
||||
dictitem_T *di;
|
||||
int flags = QF_GETLIST_NONE;
|
||||
|
||||
if ((di = dict_find(what, (char_u *)"lines", -1)) != NULL)
|
||||
return qf_get_list_from_lines(what, di, retdict);
|
||||
|
||||
if (wp != NULL)
|
||||
qi = GET_LOC_LIST(wp);
|
||||
|
||||
flags = qf_getprop_keys2flags(what);
|
||||
|
||||
if (qi != NULL && qi->qf_listcount != 0)
|
||||
qf_idx = qf_getprop_qfidx(qi, what);
|
||||
|
||||
/* List is not present or is empty */
|
||||
if (qi == NULL || qi->qf_listcount == 0 || qf_idx == -1)
|
||||
{
|
||||
if (flags & QF_GETLIST_TITLE)
|
||||
status = dict_add_nr_str(retdict, "title", 0L, (char_u *)"");
|
||||
if ((status == OK) && (flags & QF_GETLIST_ITEMS))
|
||||
{
|
||||
list_T *l = list_alloc();
|
||||
if (l != NULL)
|
||||
status = dict_add_list(retdict, "items", l);
|
||||
else
|
||||
status = FAIL;
|
||||
}
|
||||
if ((status == OK) && (flags & QF_GETLIST_NR))
|
||||
status = dict_add_nr_str(retdict, "nr", 0L, NULL);
|
||||
if ((status == OK) && (flags & QF_GETLIST_WINID))
|
||||
status = dict_add_nr_str(retdict, "winid", qf_winid(qi), NULL);
|
||||
if ((status == OK) && (flags & QF_GETLIST_CONTEXT))
|
||||
status = dict_add_nr_str(retdict, "context", 0L, (char_u *)"");
|
||||
if ((status == OK) && (flags & QF_GETLIST_ID))
|
||||
status = dict_add_nr_str(retdict, "id", 0L, NULL);
|
||||
if ((status == OK) && (flags & QF_GETLIST_IDX))
|
||||
status = dict_add_nr_str(retdict, "idx", 0L, NULL);
|
||||
if ((status == OK) && (flags & QF_GETLIST_SIZE))
|
||||
status = dict_add_nr_str(retdict, "size", 0L, NULL);
|
||||
if ((status == OK) && (flags & QF_GETLIST_TICK))
|
||||
status = dict_add_nr_str(retdict, "changedtick", 0L, NULL);
|
||||
|
||||
return status;
|
||||
}
|
||||
return qf_getprop_defaults(qi, flags, retdict);
|
||||
|
||||
if (flags & QF_GETLIST_TITLE)
|
||||
{
|
||||
char_u *t;
|
||||
t = qi->qf_lists[qf_idx].qf_title;
|
||||
if (t == NULL)
|
||||
t = (char_u *)"";
|
||||
status = dict_add_nr_str(retdict, "title", 0L, t);
|
||||
}
|
||||
status = qf_getprop_title(qi, qf_idx, retdict);
|
||||
if ((status == OK) && (flags & QF_GETLIST_NR))
|
||||
status = dict_add_nr_str(retdict, "nr", qf_idx + 1, NULL);
|
||||
if ((status == OK) && (flags & QF_GETLIST_WINID))
|
||||
status = dict_add_nr_str(retdict, "winid", qf_winid(qi), NULL);
|
||||
if ((status == OK) && (flags & QF_GETLIST_ITEMS))
|
||||
{
|
||||
list_T *l = list_alloc();
|
||||
if (l != NULL)
|
||||
{
|
||||
(void)get_errorlist(qi, NULL, qf_idx, l);
|
||||
dict_add_list(retdict, "items", l);
|
||||
}
|
||||
else
|
||||
status = FAIL;
|
||||
}
|
||||
|
||||
status = qf_getprop_items(qi, qf_idx, retdict);
|
||||
if ((status == OK) && (flags & QF_GETLIST_CONTEXT))
|
||||
{
|
||||
if (qi->qf_lists[qf_idx].qf_ctx != NULL)
|
||||
{
|
||||
di = dictitem_alloc((char_u *)"context");
|
||||
if (di != NULL)
|
||||
{
|
||||
copy_tv(qi->qf_lists[qf_idx].qf_ctx, &di->di_tv);
|
||||
status = dict_add(retdict, di);
|
||||
if (status == FAIL)
|
||||
dictitem_free(di);
|
||||
}
|
||||
else
|
||||
status = FAIL;
|
||||
}
|
||||
else
|
||||
status = dict_add_nr_str(retdict, "context", 0L, (char_u *)"");
|
||||
}
|
||||
|
||||
status = qf_getprop_ctx(qi, qf_idx, retdict);
|
||||
if ((status == OK) && (flags & QF_GETLIST_ID))
|
||||
status = dict_add_nr_str(retdict, "id", qi->qf_lists[qf_idx].qf_id,
|
||||
NULL);
|
||||
|
||||
if ((status == OK) && (flags & QF_GETLIST_IDX))
|
||||
{
|
||||
int idx = qi->qf_lists[qf_idx].qf_index;
|
||||
if (qi->qf_lists[qf_idx].qf_count == 0)
|
||||
/* For empty lists, qf_index is set to 1 */
|
||||
idx = 0;
|
||||
status = dict_add_nr_str(retdict, "idx", idx, NULL);
|
||||
}
|
||||
|
||||
status = qf_getprop_idx(qi, qf_idx, retdict);
|
||||
if ((status == OK) && (flags & QF_GETLIST_SIZE))
|
||||
status = dict_add_nr_str(retdict, "size",
|
||||
qi->qf_lists[qf_idx].qf_count, NULL);
|
||||
|
||||
if ((status == OK) && (flags & QF_GETLIST_TICK))
|
||||
status = dict_add_nr_str(retdict, "changedtick",
|
||||
qi->qf_lists[qf_idx].qf_changedtick, NULL);
|
||||
@@ -5609,7 +5681,7 @@ mark_quickfix_ctx(qf_info_T *qi, int copyID)
|
||||
|
||||
/*
|
||||
* Mark the context of the quickfix list and the location lists (if present) as
|
||||
* "in use". So that garabage collection doesn't free the context.
|
||||
* "in use". So that garbage collection doesn't free the context.
|
||||
*/
|
||||
int
|
||||
set_ref_in_quickfix(int copyID)
|
||||
|
||||
+27
-27
@@ -827,9 +827,9 @@ struct msglist
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
ET_USER, /* exception caused by ":throw" command */
|
||||
ET_ERROR, /* error exception */
|
||||
ET_INTERRUPT /* interrupt exception triggered by Ctrl-C */
|
||||
ET_USER, // exception caused by ":throw" command
|
||||
ET_ERROR, // error exception
|
||||
ET_INTERRUPT, // interrupt exception triggered by Ctrl-C
|
||||
} except_type_T;
|
||||
|
||||
/*
|
||||
@@ -1190,16 +1190,16 @@ typedef struct channel_S channel_T;
|
||||
typedef enum
|
||||
{
|
||||
VAR_UNKNOWN = 0,
|
||||
VAR_NUMBER, /* "v_number" is used */
|
||||
VAR_STRING, /* "v_string" is used */
|
||||
VAR_FUNC, /* "v_string" is function name */
|
||||
VAR_PARTIAL, /* "v_partial" is used */
|
||||
VAR_LIST, /* "v_list" is used */
|
||||
VAR_DICT, /* "v_dict" is used */
|
||||
VAR_FLOAT, /* "v_float" is used */
|
||||
VAR_SPECIAL, /* "v_number" is used */
|
||||
VAR_JOB, /* "v_job" is used */
|
||||
VAR_CHANNEL /* "v_channel" is used */
|
||||
VAR_NUMBER, // "v_number" is used
|
||||
VAR_STRING, // "v_string" is used
|
||||
VAR_FUNC, // "v_string" is function name
|
||||
VAR_PARTIAL, // "v_partial" is used
|
||||
VAR_LIST, // "v_list" is used
|
||||
VAR_DICT, // "v_dict" is used
|
||||
VAR_FLOAT, // "v_float" is used
|
||||
VAR_SPECIAL, // "v_number" is used
|
||||
VAR_JOB, // "v_job" is used
|
||||
VAR_CHANNEL, // "v_channel" is used
|
||||
} vartype_T;
|
||||
|
||||
/*
|
||||
@@ -1456,8 +1456,8 @@ typedef enum
|
||||
{
|
||||
JOB_FAILED,
|
||||
JOB_STARTED,
|
||||
JOB_ENDED, /* detected job done */
|
||||
JOB_FINISHED /* job done and cleanup done */
|
||||
JOB_ENDED, // detected job done
|
||||
JOB_FINISHED, // job done and cleanup done
|
||||
} jobstatus_T;
|
||||
|
||||
/*
|
||||
@@ -1531,11 +1531,11 @@ typedef enum
|
||||
MODE_NL = 0,
|
||||
MODE_RAW,
|
||||
MODE_JSON,
|
||||
MODE_JS
|
||||
MODE_JS,
|
||||
} ch_mode_T;
|
||||
|
||||
typedef enum {
|
||||
JIO_PIPE, /* default */
|
||||
JIO_PIPE, // default
|
||||
JIO_NULL,
|
||||
JIO_FILE,
|
||||
JIO_BUFFER,
|
||||
@@ -1557,7 +1557,7 @@ typedef enum {
|
||||
PART_IN,
|
||||
# define CH_IN_FD CH_PART_FD(PART_IN)
|
||||
#endif
|
||||
PART_COUNT
|
||||
PART_COUNT,
|
||||
} ch_part_T;
|
||||
|
||||
#define INVALID_FD (-1)
|
||||
@@ -3271,15 +3271,15 @@ typedef struct {
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
TYPE_UNKNOWN = 0
|
||||
, TYPE_EQUAL /* == */
|
||||
, TYPE_NEQUAL /* != */
|
||||
, TYPE_GREATER /* > */
|
||||
, TYPE_GEQUAL /* >= */
|
||||
, TYPE_SMALLER /* < */
|
||||
, TYPE_SEQUAL /* <= */
|
||||
, TYPE_MATCH /* =~ */
|
||||
, TYPE_NOMATCH /* !~ */
|
||||
TYPE_UNKNOWN = 0,
|
||||
TYPE_EQUAL, // ==
|
||||
TYPE_NEQUAL, // !=
|
||||
TYPE_GREATER, // >
|
||||
TYPE_GEQUAL, // >=
|
||||
TYPE_SMALLER, // <
|
||||
TYPE_SEQUAL, // <=
|
||||
TYPE_MATCH, // =~
|
||||
TYPE_NOMATCH, // !~
|
||||
} exptype_T;
|
||||
|
||||
/*
|
||||
|
||||
+72
-45
@@ -42,26 +42,23 @@
|
||||
* redirection. Probably in call to channel_set_pipes().
|
||||
* - Win32: Redirecting output does not work, Test_terminal_redir_file()
|
||||
* is disabled.
|
||||
* - Copy text in the vterm to the Vim buffer once in a while, so that
|
||||
* completion works.
|
||||
* - When starting terminal window with shell in terminal, then using :gui to
|
||||
* switch to GUI, shell stops working. Scrollback seems wrong, command
|
||||
* running in shell is still running.
|
||||
* - in GUI vertical split causes problems. Cursor is flickering. (Hirohito
|
||||
* Higashi, 2017 Sep 19)
|
||||
* - after resizing windows overlap. (Boris Staletic, #2164)
|
||||
* - cursor blinks in terminal on widows with a timer. (xtal8, #2142)
|
||||
* - Termdebug does not work when Vim build with mzscheme. gdb hangs.
|
||||
* - After executing a shell command the status line isn't redraw.
|
||||
* - add test for giving error for invalid 'termsize' value.
|
||||
* - support minimal size when 'termsize' is "rows*cols".
|
||||
* - support minimal size when 'termsize' is empty?
|
||||
* - GUI: when using tabs, focus in terminal, click on tab does not work.
|
||||
* - handle_moverect() scrolls one line at a time. Postpone scrolling, count
|
||||
* the number of lines, until a redraw happens. Then if scrolling many lines
|
||||
* a redraw is faster.
|
||||
* - Copy text in the vterm to the Vim buffer once in a while, so that
|
||||
* completion works.
|
||||
* - Redrawing is slow with Athena and Motif. Also other GUI? (Ramel Eshed)
|
||||
* - For the GUI fill termios with default values, perhaps like pangoterm:
|
||||
* http://bazaar.launchpad.net/~leonerd/pangoterm/trunk/view/head:/main.c#L134
|
||||
* - When 'encoding' is not utf-8, or the job is using another encoding, setup
|
||||
* conversions.
|
||||
* - Termdebug does not work when Vim build with mzscheme: gdb hangs just after
|
||||
* "run". Everything else works, including communication channel. Not
|
||||
* initializing mzscheme avoid the problem, thus it's not some #ifdef.
|
||||
*/
|
||||
|
||||
#include "vim.h"
|
||||
@@ -133,9 +130,6 @@ struct terminal_S {
|
||||
/* last known vterm size */
|
||||
int tl_rows;
|
||||
int tl_cols;
|
||||
/* vterm size does not follow window size */
|
||||
int tl_rows_fixed;
|
||||
int tl_cols_fixed;
|
||||
|
||||
char_u *tl_title; /* NULL or allocated */
|
||||
char_u *tl_status_text; /* NULL or allocated */
|
||||
@@ -207,9 +201,38 @@ static int desired_cursor_blink = -1;
|
||||
* 1. Generic code for all systems.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Parse 'termsize' and set "rows" and "cols" for the terminal size in the
|
||||
* current window.
|
||||
* Sets "rows" and/or "cols" to zero when it should follow the window size.
|
||||
* Return TRUE if the size is the minimum size: "24*80".
|
||||
*/
|
||||
static int
|
||||
parse_termsize(win_T *wp, int *rows, int *cols)
|
||||
{
|
||||
int minsize = FALSE;
|
||||
|
||||
*rows = 0;
|
||||
*cols = 0;
|
||||
|
||||
if (*wp->w_p_tms != NUL)
|
||||
{
|
||||
char_u *p = vim_strchr(wp->w_p_tms, 'x');
|
||||
|
||||
/* Syntax of value was already checked when it's set. */
|
||||
if (p == NULL)
|
||||
{
|
||||
minsize = TRUE;
|
||||
p = vim_strchr(wp->w_p_tms, '*');
|
||||
}
|
||||
*rows = atoi((char *)wp->w_p_tms);
|
||||
*cols = atoi((char *)p + 1);
|
||||
}
|
||||
return minsize;
|
||||
}
|
||||
|
||||
/*
|
||||
* Determine the terminal size from 'termsize' and the current window.
|
||||
* Assumes term->tl_rows and term->tl_cols are zero.
|
||||
*/
|
||||
static void
|
||||
set_term_and_win_size(term_T *term)
|
||||
@@ -224,27 +247,21 @@ set_term_and_win_size(term_T *term)
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
if (*curwin->w_p_tms != NUL)
|
||||
if (parse_termsize(curwin, &term->tl_rows, &term->tl_cols))
|
||||
{
|
||||
char_u *p = vim_strchr(curwin->w_p_tms, 'x') + 1;
|
||||
|
||||
term->tl_rows = atoi((char *)curwin->w_p_tms);
|
||||
term->tl_cols = atoi((char *)p);
|
||||
if (term->tl_rows != 0)
|
||||
term->tl_rows = MAX(term->tl_rows, curwin->w_height);
|
||||
if (term->tl_cols != 0)
|
||||
term->tl_cols = MAX(term->tl_cols, curwin->w_width);
|
||||
}
|
||||
if (term->tl_rows == 0)
|
||||
term->tl_rows = curwin->w_height;
|
||||
else
|
||||
{
|
||||
win_setheight_win(term->tl_rows, curwin);
|
||||
term->tl_rows_fixed = TRUE;
|
||||
}
|
||||
if (term->tl_cols == 0)
|
||||
term->tl_cols = curwin->w_width;
|
||||
else
|
||||
{
|
||||
win_setwidth_win(term->tl_cols, curwin);
|
||||
term->tl_cols_fixed = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -2858,6 +2875,10 @@ term_update_window(win_T *wp)
|
||||
VTermScreen *screen;
|
||||
VTermState *state;
|
||||
VTermPos pos;
|
||||
int rows, cols;
|
||||
int newrows, newcols;
|
||||
int minsize;
|
||||
win_T *twp;
|
||||
|
||||
if (term == NULL || term->tl_vterm == NULL || term->tl_normal_mode)
|
||||
return FAIL;
|
||||
@@ -2876,31 +2897,32 @@ term_update_window(win_T *wp)
|
||||
* If the window was resized a redraw will be triggered and we get here.
|
||||
* Adjust the size of the vterm unless 'termsize' specifies a fixed size.
|
||||
*/
|
||||
if ((!term->tl_rows_fixed && term->tl_rows != wp->w_height)
|
||||
|| (!term->tl_cols_fixed && term->tl_cols != wp->w_width))
|
||||
{
|
||||
int rows = term->tl_rows_fixed ? term->tl_rows : wp->w_height;
|
||||
int cols = term->tl_cols_fixed ? term->tl_cols : wp->w_width;
|
||||
win_T *twp;
|
||||
minsize = parse_termsize(wp, &rows, &cols);
|
||||
|
||||
FOR_ALL_WINDOWS(twp)
|
||||
newrows = 99999;
|
||||
newcols = 99999;
|
||||
FOR_ALL_WINDOWS(twp)
|
||||
{
|
||||
/* When more than one window shows the same terminal, use the
|
||||
* smallest size. */
|
||||
if (twp->w_buffer == term->tl_buffer)
|
||||
{
|
||||
/* When more than one window shows the same terminal, use the
|
||||
* smallest size. */
|
||||
if (twp->w_buffer == term->tl_buffer)
|
||||
{
|
||||
if (!term->tl_rows_fixed && rows > twp->w_height)
|
||||
rows = twp->w_height;
|
||||
if (!term->tl_cols_fixed && cols > twp->w_width)
|
||||
cols = twp->w_width;
|
||||
}
|
||||
newrows = MIN(newrows, twp->w_height);
|
||||
newcols = MIN(newcols, twp->w_width);
|
||||
}
|
||||
}
|
||||
newrows = rows == 0 ? newrows : minsize ? MAX(rows, newrows) : rows;
|
||||
newcols = cols == 0 ? newcols : minsize ? MAX(cols, newcols) : cols;
|
||||
|
||||
if (term->tl_rows != newrows || term->tl_cols != newcols)
|
||||
{
|
||||
|
||||
|
||||
term->tl_vterm_size_changed = TRUE;
|
||||
vterm_set_size(vterm, rows, cols);
|
||||
vterm_set_size(vterm, newrows, newcols);
|
||||
ch_log(term->tl_job->jv_channel, "Resizing terminal to %d lines",
|
||||
rows);
|
||||
term_report_winsize(term, rows, cols);
|
||||
newrows);
|
||||
term_report_winsize(term, newrows, newcols);
|
||||
}
|
||||
|
||||
/* The cursor may have been moved when resizing. */
|
||||
@@ -3419,6 +3441,10 @@ parse_osc(const char *command, size_t cmdlen, void *user)
|
||||
{
|
||||
char_u *cmd = get_tv_string(&item->li_tv);
|
||||
|
||||
/* Make sure an invoked command doesn't delete the buffer (and the
|
||||
* terminal) under our fingers. */
|
||||
++term->tl_buffer->b_locked;
|
||||
|
||||
item = item->li_next;
|
||||
if (item == NULL)
|
||||
ch_log(channel, "Missing argument for %s", cmd);
|
||||
@@ -3428,6 +3454,7 @@ parse_osc(const char *command, size_t cmdlen, void *user)
|
||||
handle_call_command(term, channel, item);
|
||||
else
|
||||
ch_log(channel, "Invalid command received: %s", cmd);
|
||||
--term->tl_buffer->b_locked;
|
||||
}
|
||||
}
|
||||
else
|
||||
|
||||
@@ -57,7 +57,12 @@ func RunVimInTerminal(arguments, options)
|
||||
" Add -v to have gvim run in the terminal (if possible)
|
||||
let cmd .= ' -v ' . a:arguments
|
||||
let buf = term_start(cmd, {'curwin': 1, 'term_rows': rows, 'term_cols': cols})
|
||||
call assert_equal([rows, cols], term_getsize(buf))
|
||||
if &termsize == ''
|
||||
call assert_equal([rows, cols], term_getsize(buf))
|
||||
else
|
||||
let rows = term_getsize(buf)[0]
|
||||
let cols = term_getsize(buf)[1]
|
||||
endif
|
||||
|
||||
" Wait for "All" of the ruler in the status line to be shown.
|
||||
" This can be quite slow (e.g. when using valgrind).
|
||||
|
||||
@@ -119,7 +119,9 @@ func Test_autocmd_bufunload_avoiding_SEGV_01()
|
||||
exe 'autocmd BufUnload <buffer> ' . (lastbuf + 1) . 'bwipeout!'
|
||||
augroup END
|
||||
|
||||
call assert_fails('edit bb.txt', 'E937:')
|
||||
" Todo: check for E937 generated first
|
||||
" call assert_fails('edit bb.txt', 'E937:')
|
||||
call assert_fails('edit bb.txt', 'E517:')
|
||||
|
||||
autocmd! test_autocmd_bufunload
|
||||
augroup! test_autocmd_bufunload
|
||||
@@ -316,7 +318,7 @@ func Test_three_windows()
|
||||
e Xtestje2
|
||||
sp Xtestje1
|
||||
call assert_fails('e', 'E937:')
|
||||
call assert_equal('Xtestje2', expand('%'))
|
||||
call assert_equal('Xtestje1', expand('%'))
|
||||
|
||||
" Test changing buffers in a BufWipeout autocommand. If this goes wrong
|
||||
" there are ml_line errors and/or a Crash.
|
||||
@@ -338,7 +340,6 @@ func Test_three_windows()
|
||||
|
||||
au!
|
||||
enew
|
||||
bwipe! Xtestje1
|
||||
call delete('Xtestje1')
|
||||
call delete('Xtestje2')
|
||||
call delete('Xtestje3')
|
||||
@@ -1181,7 +1182,9 @@ endfunc
|
||||
func Test_nocatch_wipe_all_buffers()
|
||||
" Real nasty autocommand: wipe all buffers on any event.
|
||||
au * * bwipe *
|
||||
call assert_fails('next x', 'E93')
|
||||
" Get E93 first?
|
||||
" call assert_fails('next x', 'E93:')
|
||||
call assert_fails('next x', 'E517:')
|
||||
bwipe
|
||||
au!
|
||||
endfunc
|
||||
|
||||
@@ -40,6 +40,15 @@ func Test_packadd()
|
||||
call assert_match('/testdir/Xdir/pack/mine/opt/mytest\($\|,\)', &rtp)
|
||||
call assert_match('/testdir/Xdir/pack/mine/opt/mytest/after$', &rtp)
|
||||
|
||||
" NOTE: '/.../opt/myte' forwardly matches with '/.../opt/mytest'
|
||||
call mkdir(fnamemodify(s:plugdir, ':h') . '/myte', 'p')
|
||||
let rtp = &rtp
|
||||
packadd myte
|
||||
|
||||
" Check the path of 'myte' is added
|
||||
call assert_true(len(&rtp) > len(rtp))
|
||||
call assert_match('/testdir/Xdir/pack/mine/opt/myte\($\|,\)', &rtp)
|
||||
|
||||
" Check exception
|
||||
call assert_fails("packadd directorynotfound", 'E919:')
|
||||
call assert_fails("packadd", 'E471:')
|
||||
|
||||
@@ -814,5 +814,24 @@ func Test_popup_command()
|
||||
call delete('Xtest')
|
||||
endfunc
|
||||
|
||||
func Test_popup_complete_backwards()
|
||||
new
|
||||
call setline(1, ['Post', 'Port', 'Po'])
|
||||
let expected=['Post', 'Port', 'Port']
|
||||
call cursor(3,2)
|
||||
call feedkeys("A\<C-X>". repeat("\<C-P>", 3). "rt\<cr>", 'tx')
|
||||
call assert_equal(expected, getline(1,'$'))
|
||||
bwipe!
|
||||
endfunc
|
||||
|
||||
func Test_popup_complete_backwards_ctrl_p()
|
||||
new
|
||||
call setline(1, ['Post', 'Port', 'Po'])
|
||||
let expected=['Post', 'Port', 'Port']
|
||||
call cursor(3,2)
|
||||
call feedkeys("A\<C-P>\<C-N>rt\<cr>", 'tx')
|
||||
call assert_equal(expected, getline(1,'$'))
|
||||
bwipe!
|
||||
endfunc
|
||||
|
||||
" vim: shiftwidth=2 sts=2 expandtab
|
||||
|
||||
@@ -1297,6 +1297,30 @@ func Test_terminal_api_call_fails()
|
||||
call delete('Xlog')
|
||||
endfunc
|
||||
|
||||
let s:caught_e937 = 0
|
||||
|
||||
func Tapi_Delete(bufnum, arg)
|
||||
try
|
||||
execute 'bdelete!' a:bufnum
|
||||
catch /E937:/
|
||||
let s:caught_e937 = 1
|
||||
endtry
|
||||
endfunc
|
||||
|
||||
func Test_terminal_api_call_fail_delete()
|
||||
if !CanRunVimInTerminal()
|
||||
return
|
||||
endif
|
||||
|
||||
call WriteApiCall('Tapi_Delete')
|
||||
let buf = RunVimInTerminal('-S Xscript', {})
|
||||
call WaitFor({-> s:caught_e937 == 1})
|
||||
|
||||
call StopVimInTerminal(buf)
|
||||
call delete('Xscript')
|
||||
call ch_logfile('', '')
|
||||
endfunc
|
||||
|
||||
func Test_terminal_ansicolors_default()
|
||||
let colors = [
|
||||
\ '#000000', '#e00000',
|
||||
@@ -1366,3 +1390,102 @@ func Test_terminal_ansicolors_func()
|
||||
call term_wait(buf)
|
||||
exe buf . 'bwipe'
|
||||
endfunc
|
||||
|
||||
func Test_terminal_termsize_option_fixed()
|
||||
if !CanRunVimInTerminal()
|
||||
return
|
||||
endif
|
||||
set termsize=6x40
|
||||
let text = []
|
||||
for n in range(10)
|
||||
call add(text, repeat(n, 50))
|
||||
endfor
|
||||
call writefile(text, 'Xwinsize')
|
||||
let buf = RunVimInTerminal('Xwinsize', {})
|
||||
let win = bufwinid(buf)
|
||||
call assert_equal([6, 40], term_getsize(buf))
|
||||
call assert_equal(6, winheight(win))
|
||||
call assert_equal(40, winwidth(win))
|
||||
|
||||
" resizing the window doesn't resize the terminal.
|
||||
resize 10
|
||||
vertical resize 60
|
||||
call assert_equal([6, 40], term_getsize(buf))
|
||||
call assert_equal(10, winheight(win))
|
||||
call assert_equal(60, winwidth(win))
|
||||
|
||||
call StopVimInTerminal(buf)
|
||||
call delete('Xwinsize')
|
||||
|
||||
call assert_fails('set termsize=40', 'E474')
|
||||
call assert_fails('set termsize=10+40', 'E474')
|
||||
call assert_fails('set termsize=abc', 'E474')
|
||||
|
||||
set termsize=
|
||||
endfunc
|
||||
|
||||
func Test_terminal_termsize_option_zero()
|
||||
set termsize=0x0
|
||||
let buf = Run_shell_in_terminal({})
|
||||
let win = bufwinid(buf)
|
||||
call assert_equal([winheight(win), winwidth(win)], term_getsize(buf))
|
||||
call Stop_shell_in_terminal(buf)
|
||||
call term_wait(buf)
|
||||
exe buf . 'bwipe'
|
||||
|
||||
set termsize=7x0
|
||||
let buf = Run_shell_in_terminal({})
|
||||
let win = bufwinid(buf)
|
||||
call assert_equal([7, winwidth(win)], term_getsize(buf))
|
||||
call Stop_shell_in_terminal(buf)
|
||||
call term_wait(buf)
|
||||
exe buf . 'bwipe'
|
||||
|
||||
set termsize=0x33
|
||||
let buf = Run_shell_in_terminal({})
|
||||
let win = bufwinid(buf)
|
||||
call assert_equal([winheight(win), 33], term_getsize(buf))
|
||||
call Stop_shell_in_terminal(buf)
|
||||
call term_wait(buf)
|
||||
exe buf . 'bwipe'
|
||||
|
||||
set termsize=
|
||||
endfunc
|
||||
|
||||
func Test_terminal_termsize_mininmum()
|
||||
set termsize=10*50
|
||||
vsplit
|
||||
let buf = Run_shell_in_terminal({})
|
||||
let win = bufwinid(buf)
|
||||
call assert_inrange(10, 1000, winheight(win))
|
||||
call assert_inrange(50, 1000, winwidth(win))
|
||||
call assert_equal([winheight(win), winwidth(win)], term_getsize(buf))
|
||||
|
||||
resize 15
|
||||
vertical resize 60
|
||||
redraw
|
||||
call assert_equal([15, 60], term_getsize(buf))
|
||||
call assert_equal(15, winheight(win))
|
||||
call assert_equal(60, winwidth(win))
|
||||
|
||||
resize 7
|
||||
vertical resize 30
|
||||
redraw
|
||||
call assert_equal([10, 50], term_getsize(buf))
|
||||
call assert_equal(7, winheight(win))
|
||||
call assert_equal(30, winwidth(win))
|
||||
|
||||
call Stop_shell_in_terminal(buf)
|
||||
call term_wait(buf)
|
||||
exe buf . 'bwipe'
|
||||
|
||||
set termsize=0*0
|
||||
let buf = Run_shell_in_terminal({})
|
||||
let win = bufwinid(buf)
|
||||
call assert_equal([winheight(win), winwidth(win)], term_getsize(buf))
|
||||
call Stop_shell_in_terminal(buf)
|
||||
call term_wait(buf)
|
||||
exe buf . 'bwipe'
|
||||
|
||||
set termsize=
|
||||
endfunc
|
||||
|
||||
@@ -777,6 +777,36 @@ static char *(features[]) =
|
||||
|
||||
static int included_patches[] =
|
||||
{ /* Add new patch number below this line */
|
||||
/**/
|
||||
1735,
|
||||
/**/
|
||||
1734,
|
||||
/**/
|
||||
1733,
|
||||
/**/
|
||||
1732,
|
||||
/**/
|
||||
1731,
|
||||
/**/
|
||||
1730,
|
||||
/**/
|
||||
1729,
|
||||
/**/
|
||||
1728,
|
||||
/**/
|
||||
1727,
|
||||
/**/
|
||||
1726,
|
||||
/**/
|
||||
1725,
|
||||
/**/
|
||||
1724,
|
||||
/**/
|
||||
1723,
|
||||
/**/
|
||||
1722,
|
||||
/**/
|
||||
1721,
|
||||
/**/
|
||||
1720,
|
||||
/**/
|
||||
|
||||
Reference in New Issue
Block a user