Merge remote-tracking branch 'vim/master'

This commit is contained in:
Kazuki Sakamoto
2017-09-11 22:00:48 -07:00
29 changed files with 788 additions and 321 deletions
+5
View File
@@ -830,6 +830,11 @@ Also see |`=|.
Note: these are typed literally, they are not special keys!
<cword> is replaced with the word under the cursor (like |star|)
<cWORD> is replaced with the WORD under the cursor (see |WORD|)
<cexpr> is replaced with the word under the cursor, including more
to form a C expression. E.g., when the cursor is on "arg"
of "ptr->arg" then the result is "ptr->arg"; when the
cursor is on "]" of "list[idx]" then the result is
"list[idx]". This is used for |v:beval_text|.
<cfile> is replaced with the path name under the cursor (like what
|gf| uses)
<afile> When executing autocommands, is replaced with the file name
+20 -17
View File
@@ -1,4 +1,4 @@
*eval.txt* For Vim version 8.0. Last change: 2017 Aug 13
*eval.txt* For Vim version 8.0. Last change: 2017 Sep 11
VIM REFERENCE MANUAL by Bram Moolenaar
@@ -1449,7 +1449,7 @@ v:beval_text The text under or after the mouse pointer. Usually a word as
but a dot and "->" before the position is included. When on a
']' the text before it is used, including the matching '[' and
word before it. When on a Visual area within one line the
highlighted text is used.
highlighted text is used. Also see |<cexpr>|.
Only valid while evaluating the 'balloonexpr' option.
*v:beval_winnr* *beval_winnr-variable*
@@ -3301,7 +3301,7 @@ count({comp}, {expr} [, {ic} [, {start}]]) *count()*
When {ic} is given and it's |TRUE| then case is ignored.
When {comp} is a string then the number of not overlapping
occurences of {expr} is returned.
occurrences of {expr} is returned.
*cscope_connection()*
@@ -3467,7 +3467,7 @@ escape({string}, {chars}) *escape()*
:echo escape('c:\program files\vim', ' \')
< results in: >
c:\\program\ files\\vim
< Also see |shellescape()|.
< Also see |shellescape()| and |fnameescape()|.
*eval()*
eval({string}) Evaluate {string} and return the result. Especially useful to
@@ -3887,7 +3887,7 @@ float2nr({expr}) *float2nr()*
When the value of {expr} is out of range for a |Number| the
result is truncated to 0x7fffffff or -0x7fffffff (or when
64-bit Number support is enabled, 0x7fffffffffffffff or
-0x7fffffffffffffff. NaN results in -0x80000000 (or when
-0x7fffffffffffffff). NaN results in -0x80000000 (or when
64-bit Number support is enabled, -0x8000000000000000).
Examples: >
echo float2nr(3.95)
@@ -4657,12 +4657,12 @@ getqflist([{what}]) *getqflist()*
If "nr" is not present then the current quickfix list is used.
If both "nr" and a non-zero "id" are specified, then the list
specified by "id" is used.
To get the number of lists in the quickfix stack, set 'nr' to
'$' in {what}. The 'nr' value in the returned dictionary
To get the number of lists in the quickfix stack, set "nr" to
"$" in {what}. The "nr" value in the returned dictionary
contains the quickfix stack size.
When 'text' is specified, all the other items are ignored. The
returned dictionary contains the entry 'items' with the list
of entries.
When "lines" is specified, all the other items except "efm"
are ignored. The returned dictionary contains the entry
"items" with the list of entries.
In case of error processing {what}, an empty dictionary is
returned.
@@ -6967,6 +6967,7 @@ setline({lnum}, {text}) *setline()*
:for [n, l] in [[5, 'aaa'], [6, 'bbb'], [7, 'ccc']]
: call setline(n, l)
:endfor
< Note: The '[ and '] marks are not set.
setloclist({nr}, {list}[, {action}[, {what}]]) *setloclist()*
@@ -7164,16 +7165,17 @@ setreg({regname}, {value} [, {options}])
:call setreg('a', "1\n2\n3", 'b5')
< This example shows using the functions to save and restore a
register (note: you may not reliably restore register value
without using the third argument to |getreg()| as without it
newlines are represented as newlines AND Nul bytes are
represented as newlines as well, see |NL-used-for-Nul|). >
register: >
:let var_a = getreg('a', 1, 1)
:let var_amode = getregtype('a')
....
:call setreg('a', var_a, var_amode)
< Note: you may not reliably restore register value
without using the third argument to |getreg()| as without it
newlines are represented as newlines AND Nul bytes are
represented as newlines as well, see |NL-used-for-Nul|.
< You can also change the type of a register by appending
You can also change the type of a register by appending
nothing: >
:call setreg('a', '', 'al')
@@ -8145,7 +8147,7 @@ term_start({cmd}, {options}) *term_start()*
are supported:
all timeout options
"stoponexit"
"out_cb", "err_cb"
"callback", "out_cb", "err_cb"
"exit_cb", "close_cb"
"in_io", "in_top", "in_bot", "in_name", "in_buf"
"out_io", "out_name", "out_buf", "out_modifiable", "out_msg"
@@ -8165,6 +8167,7 @@ term_start({cmd}, {options}) *term_start()*
"curwin" use the current window, do not split the
window; fails if the current buffer
cannot be |abandon|ed
"hidden" do not open a window
"term_finish" What to do when the job is finished:
"close": close any windows
"open": open window if needed
@@ -8562,7 +8565,7 @@ win_getid([{win} [, {tab}]]) *win_getid()*
Get the |window-ID| for the specified window.
When {win} is missing use the current window.
With {win} this is the window number. The top window has
number 1.
number 1. Use `win_getid(winnr())` for the current window.
Without {tab} use the current tab, otherwise the tab with
number {tab}. The first tab has number one.
Return zero if the window cannot be found.
+2
View File
@@ -1415,6 +1415,8 @@ The valid escape sequences are
<line1> The starting line of the command range.
*<line2>*
<line2> The final line of the command range.
*<range>*
<range> The number of items in the command range: 0, 1 or 2
*<count>*
<count> Any count supplied (as described for the '-range'
and '-count' attributes).
+12
View File
@@ -44,6 +44,18 @@ From inside Vim an easy way to run a command and handle the output is with the
The 'errorformat' option should be set to match the error messages from your
compiler (see |errorformat| below).
*quickfix-ID*
Each quickfix list has a unique identifier called the quickfix ID and this
number will not change within a Vim session. The getqflist() function can be
used to get the identifier assigned to a list.
*quickfix-ID*
Each quickfix list has a unique identifier called the quickfix ID and this
number will not change within a Vim session. The getqflist() function can be
used to get the identifier assigned to a list. There is also a quickfix list
number which may change whenever more than ten lists are added to a quickfix
stack.
*location-list* *E776*
A location list is a window-local quickfix list. You get one after commands
like `:lvimgrep`, `:lgrep`, `:lhelpgrep`, `:lmake`, etc., which create a
+95 -22
View File
@@ -1,4 +1,4 @@
*terminal.txt* For Vim version 8.0. Last change: 2017 Aug 29
*terminal.txt* For Vim version 8.0. Last change: 2017 Sep 10
VIM REFERENCE MANUAL by Bram Moolenaar
@@ -30,11 +30,11 @@ This feature is for running a terminal emulator in a Vim window. A job can be
started connected to the terminal emulator. For example, to run a shell: >
:term bash
Or to run a debugger: >
:term gdb vim
Or to run build command: >
:term make myprogram
The job runs asynchronously from Vim, the window will be updated to show
output from the job, also while editing in any other window.
output from the job, also while editing in another window.
Typing ~
@@ -109,7 +109,8 @@ Syntax ~
If [range] is given the specified lines are used as
input for the job. It will not be possible to type
keys in the terminal window.
keys in the terminal window. For MS-Windows see the
++eof argument below.
Two comma separated numbers are used as "rows,cols".
E.g. `:24,80gdb` opens a terminal with 24 rows and 80
@@ -133,14 +134,15 @@ Syntax ~
height.
++cols={width} Use {width} for the terminal window
width.
++eof={text} when using [range], text to send after
the last line was written. The default
is to send CTRL-D. A CR is appended.
++eof={text} when using [range]: text to send after
the last line was written. Cannot
contain white space. A CR is
appended. For MS-Windows the default
is to send CTRL-D.
E.g. for a shell use "++eof=exit" and
for Python "++eof=exit()". Special
codes can be used like with `:map`,
e.g. "<C-Z>" for CTRL-Z.
{only on MS-Windows}
If you want to use more options use the |term_start()|
function.
@@ -303,33 +305,104 @@ term_scrape() inspect terminal screen
3. Debugging *terminal-debug*
The Terminal debugging plugin can be used to debug a program with gdb and view
the source code in a Vim window.
the source code in a Vim window. Since this is completely contained inside
Vim this also works remotely over an ssh connection.
Starting ~
Load the plugin with this command: >
packadd termdebug
< *:Termdebug*
To start debugging use `:TermDebug` folowed by the command name, for example: >
:TermDebug vim
This opens two windows:
- A terminal window in which "gdb vim" is executed. Here you can directly
interact with gdb.
- A terminal window for the executed program. When "run" is used in gdb the
program I/O will happen in this window, so that it does not interfere with
controlling gdb.
The current window is used to show the source code. When gdb jumps to a
source file location this window will display the code, if possible. Values
of variables can be inspected, breakpoints set and cleared, etc.
gdb window A terminal window in which "gdb vim" is executed. Here you
can directly interact with gdb. The buffer name is "!gdb".
program window A terminal window for the executed program. When "run" is
used in gdb the program I/O will happen in this window, so
that it does not interfere with controlling gdb. The buffer
name is "gdb program".
When the debugger ends the two opened windows are closed.
The current window is used to show the source code. When gdb pauses the
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.
Focus the terminal of the executed program to interact with it. This works
the same as any command running in a terminal window.
When the debugger ends, typically by typing "quit" in the gdb window, the two
opened windows are closed.
Stepping through code ~
Put focus on the gdb window to type commands there. Some common ones are:
- CTRL-C interrupt the program
- next execute the current line and stop at the next line
- step execute the current line and stop at the next statement, entering
functions
- finish execute until leaving the current function
- where show the stack
- frame N go to the Nth stack frame
- continue continue execution
In the window showing the source code some commands can used to control gdb:
:Break set a breakpoint at the current line; a sign will be displayed
:Delete delete a 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
Inspecting variables ~
:Evaluate evaluate the expression under the cursor
K same
:Evaluate {expr} evaluate {expr}
:'<,'>Evaluate evaluate the Visually selected text
This is similar to using "print" in the gdb window.
Other commands ~
:Gdb jump to the gdb window
:Program jump to the window with the running program
Communication ~
There is another, hidden, buffer, which is used for Vim to communicate with
gdb. The buffer name is "gdb communication". Do not delete this buffer, it
will break the debugger.
Customizing ~
g:debugger The debugger command. Default "gdb".
To change the name of the gdb command, set the "termdebugger" variable before
invoking `:Termdebug`: >
let termdebugger = "mygdb"
Only debuggers fully compatible with gdb will work. Vim uses the GDB/MI
interface.
The color of the signs can be adjusted with these highlight groups:
- debugPC the current position
- debugBreakpoint a breakpoint
The defaults are, when 'background' is "light":
hi debugPC term=reverse ctermbg=lightblue guibg=lightblue
hi debugBreakpoint term=reverse ctermbg=red guibg=red
When 'background' is "dark":
hi debugPC term=reverse ctermbg=darkblue guibg=darkblue
hi debugBreakpoint term=reverse ctermbg=red guibg=red
TODO
vim:tw=78:ts=8:ft=help:norl:
+201 -36
View File
@@ -20,18 +20,26 @@
command -nargs=* -complete=file Termdebug call s:StartDebug(<q-args>)
" Name of the gdb command, defaults to "gdb".
if !exists('debugger')
let debugger = 'gdb'
if !exists('termdebugger')
let termdebugger = 'gdb'
endif
" Sign used to highlight the line where the program has stopped.
" There can be only one.
sign define debugPC linehl=debugPC
if &background == 'light'
hi debugPC term=reverse ctermbg=lightblue guibg=lightblue
else
hi debugPC term=reverse ctermbg=darkblue guibg=darkblue
endif
let s:pc_id = 12
let s:break_id = 13
" Sign used to indicate a breakpoint.
" Can be used multiple times.
sign define debugBreakpoint text=>> texthl=debugBreakpoint
if &background == 'light'
hi default debugPC term=reverse ctermbg=lightblue guibg=lightblue
else
hi default debugPC term=reverse ctermbg=darkblue guibg=darkblue
endif
hi default debugBreakpoint term=reverse ctermbg=red guibg=red
func s:StartDebug(cmd)
let s:startwin = win_getid(winnr())
@@ -46,6 +54,7 @@ func s:StartDebug(cmd)
return
endif
let pty = job_info(term_getjob(s:ptybuf))['tty_out']
let s:ptywin = win_getid(winnr())
" Create a hidden terminal window to communicate with gdb
let s:commbuf = term_start('NONE', {
@@ -61,7 +70,7 @@ func s:StartDebug(cmd)
let commpty = job_info(term_getjob(s:commbuf))['tty_out']
" Open a terminal window to run the debugger.
let cmd = [g:debugger, '-tty', pty, a:cmd]
let cmd = [g:termdebugger, '-tty', pty, a:cmd]
echomsg 'executing "' . join(cmd) . '"'
let gdbbuf = term_start(cmd, {
\ 'exit_cb': function('s:EndDebug'),
@@ -73,15 +82,30 @@ func s:StartDebug(cmd)
exe 'bwipe! ' . s:commbuf
return
endif
let s:gdbwin = win_getid(winnr())
" Connect gdb to the communication pty, using the GDB/MI interface
call term_sendkeys(gdbbuf, 'new-ui mi ' . commpty . "\r")
" Install debugger commands in the text window.
call win_gotoid(s:startwin)
call s:InstallCommands()
call win_gotoid(s:gdbwin)
let s:breakpoints = {}
endfunc
func s:EndDebug(job, status)
exe 'bwipe! ' . s:ptybuf
exe 'bwipe! ' . s:commbuf
call setwinvar(s:startwin, '&signcolumn', s:startsigncolumn)
let curwinid = win_getid(winnr())
call win_gotoid(s:startwin)
let &signcolumn = s:startsigncolumn
call s:DeleteCommands()
call win_gotoid(curwinid)
endfunc
" Handle a message received from gdb on the GDB/MI interface.
@@ -95,34 +119,175 @@ func s:CommOutput(chan, msg)
endif
if msg != ''
if msg =~ '^\*\(stopped\|running\)'
let wid = win_getid(winnr())
if win_gotoid(s:startwin)
if msg =~ '^\*stopped'
" TODO: proper parsing
let fname = substitute(msg, '.*fullname="\([^"]*\)".*', '\1', '')
let lnum = substitute(msg, '.*line="\([^"]*\)".*', '\1', '')
if lnum =~ '^[0-9]*$'
if expand('%:h') != fname
if &modified
" TODO: find existing window
exe 'split ' . fnameescape(fname)
let s:startwin = win_getid(winnr())
else
exe 'edit ' . fnameescape(fname)
endif
endif
exe lnum
exe 'sign place ' . s:pc_id . ' line=' . lnum . ' name=debugPC file=' . fnameescape(fname)
setlocal signcolumn=yes
endif
else
exe 'sign unplace ' . s:pc_id
endif
call win_gotoid(wid)
endif
call s:HandleCursor(msg)
elseif msg =~ '^\^done,bkpt=' || msg =~ '^=breakpoint-created,'
call s:HandleNewBreakpoint(msg)
elseif msg =~ '^=breakpoint-deleted,'
call s:HandleBreakpointDelete(msg)
elseif msg =~ '^\^done,value='
call s:HandleEvaluate(msg)
elseif msg =~ '^\^error,msg='
call s:HandleError(msg)
endif
endif
endfor
endfunc
" Install commands in the current window to control the debugger.
func s:InstallCommands()
command Break call s:SetBreakpoint()
command Delete call s:DeleteBreakpoint()
command Step call s:SendCommand('-exec-step')
command Over call s:SendCommand('-exec-next')
command Finish call s:SendCommand('-exec-finish')
command Continue call s:SendCommand('-exec-continue')
command -range -nargs=* Evaluate call s:Evaluate(<range>, <q-args>)
command Gdb call win_gotoid(s:gdbwin)
command Program call win_gotoid(s:ptywin)
" TODO: can the K mapping be restored?
nnoremap K :Evaluate<CR>
endfunc
" Delete installed debugger commands in the current window.
func s:DeleteCommands()
delcommand Break
delcommand Delete
delcommand Step
delcommand Over
delcommand Finish
delcommand Continue
delcommand Evaluate
delcommand Gdb
delcommand Program
nunmap K
sign undefine debugPC
sign undefine debugBreakpoint
exe 'sign unplace ' . s:pc_id
for key in keys(s:breakpoints)
exe 'sign unplace ' . (s:break_id + key)
endfor
unlet s:breakpoints
endfunc
" :Break - Set a breakpoint at the cursor position.
func s:SetBreakpoint()
call term_sendkeys(s:commbuf, '-break-insert --source '
\ . fnameescape(expand('%:p')) . ' --line ' . line('.') . "\r")
endfunc
" :Delete - Delete a breakpoint at the cursor position.
func s:DeleteBreakpoint()
let fname = fnameescape(expand('%:p'))
let lnum = line('.')
for [key, val] in items(s:breakpoints)
if val['fname'] == fname && val['lnum'] == lnum
call term_sendkeys(s:commbuf, '-break-delete ' . key . "\r")
" Assume this always wors, the reply is simply "^done".
exe 'sign unplace ' . (s:break_id + key)
unlet s:breakpoints[key]
break
endif
endfor
endfunc
" :Next, :Continue, etc - send a command to gdb
func s:SendCommand(cmd)
call term_sendkeys(s:commbuf, a:cmd . "\r")
endfunc
" :Evaluate - evaluate what is under the cursor
func s:Evaluate(range, arg)
if a:arg != ''
let expr = a:arg
elseif a:range == 2
let pos = getcurpos()
let reg = getreg('v', 1, 1)
let regt = getregtype('v')
normal! gv"vy
let expr = @v
call setpos('.', pos)
call setreg('v', reg, regt)
else
let expr = expand('<cexpr>')
endif
call term_sendkeys(s:commbuf, '-data-evaluate-expression "' . expr . "\"\r")
let s:evalexpr = expr
endfunc
" Handle the result of data-evaluate-expression
func s:HandleEvaluate(msg)
echomsg '"' . s:evalexpr . '": ' . substitute(a:msg, '.*value="\(.*\)"', '\1', '')
endfunc
" Handle an error.
func s:HandleError(msg)
echoerr substitute(a:msg, '.*msg="\(.*\)"', '\1', '')
endfunc
" Handle stopping and running message from gdb.
" Will update the sign that shows the current position.
func s:HandleCursor(msg)
let wid = win_getid(winnr())
if win_gotoid(s:startwin)
if a:msg =~ '^\*stopped'
let fname = substitute(a:msg, '.*fullname="\([^"]*\)".*', '\1', '')
let lnum = substitute(a:msg, '.*line="\([^"]*\)".*', '\1', '')
if lnum =~ '^[0-9]*$'
if expand('%:h') != fname
if &modified
" TODO: find existing window
exe 'split ' . fnameescape(fname)
let s:startwin = win_getid(winnr())
else
exe 'edit ' . fnameescape(fname)
endif
endif
exe lnum
exe 'sign place ' . s:pc_id . ' line=' . lnum . ' name=debugPC file=' . fnameescape(fname)
setlocal signcolumn=yes
endif
else
exe 'sign unplace ' . s:pc_id
endif
call win_gotoid(wid)
endif
endfunc
" Handle setting a breakpoint
" Will update the sign that shows the breakpoint
func s:HandleNewBreakpoint(msg)
let nr = substitute(a:msg, '.*number="\([0-9]\)*\".*', '\1', '') + 0
if nr == 0
return
endif
if has_key(s:breakpoints, nr)
let entry = s:breakpoints[nr]
else
let entry = {}
let s:breakpoints[nr] = entry
endif
let fname = substitute(a:msg, '.*fullname="\([^"]*\)".*', '\1', '')
let lnum = substitute(a:msg, '.*line="\([^"]*\)".*', '\1', '')
exe 'sign place ' . (s:break_id + nr) . ' line=' . lnum . ' name=debugBreakpoint file=' . fnameescape(fname)
let entry['fname'] = fname
let entry['lnum'] = lnum
endfunc
" Handle deleting a breakpoint
" Will remove the sign that shows the breakpoint
func s:HandleBreakpointDelete(msg)
let nr = substitute(a:msg, '.*id="\([0-9]*\)\".*', '\1', '') + 0
if nr == 0
return
endif
exe 'sign unplace ' . (s:break_id + nr)
unlet s:breakpoints[nr]
endfunc
+1
View File
@@ -2282,6 +2282,7 @@ test_arglist \
test_taglist \
test_tcl \
test_terminal \
test_terminal_fail \
test_textobjects \
test_timers \
test_true_false \
+24 -13
View File
@@ -2951,14 +2951,27 @@ channel_close_in(channel_T *channel)
ch_close_part(channel, PART_IN);
}
static void
remove_from_writeque(writeq_T *wq, writeq_T *entry)
{
ga_clear(&entry->wq_ga);
wq->wq_next = entry->wq_next;
if (wq->wq_next == NULL)
wq->wq_prev = NULL;
else
wq->wq_next->wq_prev = NULL;
vim_free(entry);
}
/*
* Clear the read buffer on "channel"/"part".
*/
static void
channel_clear_one(channel_T *channel, ch_part_T part)
{
jsonq_T *json_head = &channel->ch_part[part].ch_json_head;
cbq_T *cb_head = &channel->ch_part[part].ch_cb_head;
chanpart_T *ch_part = &channel->ch_part[part];
jsonq_T *json_head = &ch_part->ch_json_head;
cbq_T *cb_head = &ch_part->ch_cb_head;
while (channel_peek(channel, part) != NULL)
vim_free(channel_get(channel, part));
@@ -2978,10 +2991,13 @@ channel_clear_one(channel_T *channel, ch_part_T part)
remove_json_node(json_head, json_head->jq_next);
}
free_callback(channel->ch_part[part].ch_callback,
channel->ch_part[part].ch_partial);
channel->ch_part[part].ch_callback = NULL;
channel->ch_part[part].ch_partial = NULL;
free_callback(ch_part->ch_callback, ch_part->ch_partial);
ch_part->ch_callback = NULL;
ch_part->ch_partial = NULL;
while (ch_part->ch_writeque.wq_next != NULL)
remove_from_writeque(&ch_part->ch_writeque,
ch_part->ch_writeque.wq_next);
}
/*
@@ -2996,7 +3012,7 @@ channel_clear(channel_T *channel)
channel_clear_one(channel, PART_SOCK);
channel_clear_one(channel, PART_OUT);
channel_clear_one(channel, PART_ERR);
/* there is no callback or queue for PART_IN */
channel_clear_one(channel, PART_IN);
free_callback(channel->ch_callback, channel->ch_partial);
channel->ch_callback = NULL;
channel->ch_partial = NULL;
@@ -3744,12 +3760,7 @@ channel_send(
if (entry != NULL)
{
/* Remove the entry from the write queue. */
ga_clear(&entry->wq_ga);
wq->wq_next = entry->wq_next;
if (wq->wq_next == NULL)
wq->wq_prev = NULL;
else
wq->wq_next->wq_prev = NULL;
remove_from_writeque(wq, entry);
continue;
}
if (did_use_queue)
+6 -1
View File
@@ -4833,7 +4833,7 @@ get_qf_loc_list(int is_qf, win_T *wp, typval_T *what_arg, typval_T *rettv)
dict_T *d = what_arg->vval.v_dict;
if (d != NULL)
get_errorlist_properties(wp, d, rettv->vval.v_dict);
qf_get_properties(wp, d, rettv->vval.v_dict);
}
else
EMSG(_(e_dictreq));
@@ -8659,7 +8659,10 @@ remote_common(typval_T *argvars, typval_T *rettv, int expr)
# endif
{
if (r != NULL)
{
EMSG(r); /* sending worked but evaluation failed */
vim_free(r);
}
else
EMSG2(_("E241: Unable to send to %s"), server_name);
return;
@@ -8719,6 +8722,8 @@ f_remote_foreground(typval_T *argvars UNUSED, typval_T *rettv UNUSED)
argvars[1].v_type = VAR_STRING;
argvars[1].vval.v_string = vim_strsave((char_u *)"foreground()");
argvars[2].v_type = VAR_UNKNOWN;
rettv->v_type = VAR_STRING;
rettv->vval.v_string = NULL;
remote_common(argvars, rettv, TRUE);
vim_free(argvars[1].vval.v_string);
# endif
+38 -18
View File
@@ -6348,7 +6348,8 @@ ex_command(exarg_T *eap)
{
++p;
end = skiptowhite(p);
if (uc_scan_attr(p, end - p, &argt, &def, &flags, &compl, &compl_arg, &addr_type_arg)
if (uc_scan_attr(p, end - p, &argt, &def, &flags, &compl,
&compl_arg, &addr_type_arg)
== FAIL)
return;
p = skipwhite(end);
@@ -6389,7 +6390,7 @@ ex_command(exarg_T *eap)
}
else
uc_add_command(name, end - name, p, argt, def, flags, compl, compl_arg,
addr_type_arg, eap->forceit);
addr_type_arg, eap->forceit);
}
/*
@@ -6609,8 +6610,18 @@ uc_check_code(
char_u *p = code + 1;
size_t l = len - 2;
int quote = 0;
enum { ct_ARGS, ct_BANG, ct_COUNT, ct_LINE1, ct_LINE2, ct_MODS,
ct_REGISTER, ct_LT, ct_NONE } type = ct_NONE;
enum {
ct_ARGS,
ct_BANG,
ct_COUNT,
ct_LINE1,
ct_LINE2,
ct_RANGE,
ct_MODS,
ct_REGISTER,
ct_LT,
ct_NONE
} type = ct_NONE;
if ((vim_strchr((char_u *)"qQfF", *p) != NULL) && p[1] == '-')
{
@@ -6632,6 +6643,8 @@ uc_check_code(
type = ct_LINE1;
else if (STRNICMP(p, "line2>", l) == 0)
type = ct_LINE2;
else if (STRNICMP(p, "range>", l) == 0)
type = ct_RANGE;
else if (STRNICMP(p, "lt>", l) == 0)
type = ct_LT;
else if (STRNICMP(p, "reg>", l) == 0 || STRNICMP(p, "register>", l) == 0)
@@ -6733,11 +6746,13 @@ uc_check_code(
case ct_LINE1:
case ct_LINE2:
case ct_RANGE:
case ct_COUNT:
{
char num_buf[20];
long num = (type == ct_LINE1) ? eap->line1 :
(type == ct_LINE2) ? eap->line2 :
(type == ct_RANGE) ? eap->addr_count :
(eap->addr_count > 0) ? eap->line2 : cmd->uc_def;
size_t num_len;
@@ -10662,31 +10677,33 @@ find_cmdline_var(char_u *src, int *usedlen)
"%",
#define SPEC_PERC 0
"#",
#define SPEC_HASH 1
#define SPEC_HASH (SPEC_PERC + 1)
"<cword>", /* cursor word */
#define SPEC_CWORD 2
#define SPEC_CWORD (SPEC_HASH + 1)
"<cWORD>", /* cursor WORD */
#define SPEC_CCWORD 3
#define SPEC_CCWORD (SPEC_CWORD + 1)
"<cexpr>", /* expr under cursor */
#define SPEC_CEXPR (SPEC_CCWORD + 1)
"<cfile>", /* cursor path name */
#define SPEC_CFILE 4
#define SPEC_CFILE (SPEC_CEXPR + 1)
"<sfile>", /* ":so" file name */
#define SPEC_SFILE 5
#define SPEC_SFILE (SPEC_CFILE + 1)
"<slnum>", /* ":so" file line number */
#define SPEC_SLNUM 6
#define SPEC_SLNUM (SPEC_SFILE + 1)
#ifdef FEAT_AUTOCMD
"<afile>", /* autocommand file name */
# define SPEC_AFILE 7
# define SPEC_AFILE (SPEC_SLNUM + 1)
"<abuf>", /* autocommand buffer number */
# define SPEC_ABUF 8
# define SPEC_ABUF (SPEC_AFILE + 1)
"<amatch>", /* autocommand match name */
# define SPEC_AMATCH 9
# define SPEC_AMATCH (SPEC_ABUF + 1)
#endif
#ifdef FEAT_CLIENTSERVER
"<client>"
# ifdef FEAT_AUTOCMD
# define SPEC_CLIENT 10
# define SPEC_CLIENT (SPEC_AMATCH + 1)
# else
# define SPEC_CLIENT 7
# define SPEC_CLIENT (SPEC_SLNUM + 1)
# endif
#endif
};
@@ -10774,10 +10791,13 @@ eval_vars(
/*
* word or WORD under cursor
*/
if (spec_idx == SPEC_CWORD || spec_idx == SPEC_CCWORD)
if (spec_idx == SPEC_CWORD || spec_idx == SPEC_CCWORD
|| spec_idx == SPEC_CEXPR)
{
resultlen = find_ident_under_cursor(&result, spec_idx == SPEC_CWORD ?
(FIND_IDENT|FIND_STRING) : FIND_STRING);
resultlen = find_ident_under_cursor(&result,
spec_idx == SPEC_CWORD ? (FIND_IDENT | FIND_STRING)
: spec_idx == SPEC_CEXPR ? (FIND_IDENT | FIND_STRING | FIND_EVAL)
: FIND_STRING);
if (resultlen == 0)
{
*errormsg = (char_u *)"";
+3 -11
View File
@@ -1177,23 +1177,15 @@ drawBalloon(BalloonEval *beval)
int x_offset = EVAL_OFFSET_X;
int y_offset = EVAL_OFFSET_Y;
PangoLayout *layout;
# if GTK_CHECK_VERSION(3,22,2)
GdkRectangle rect;
GdkMonitor * const mon = gdk_display_get_monitor_at_window(
gtk_widget_get_display(beval->balloonShell),
gtk_widget_get_window(beval->balloonShell));
gdk_monitor_get_geometry(mon, &rect);
screen_w = rect.width;
screen_h = rect.height;
# else
# if !GTK_CHECK_VERSION(3,22,2)
GdkScreen *screen;
screen = gtk_widget_get_screen(beval->target);
gtk_window_set_screen(GTK_WINDOW(beval->balloonShell), screen);
screen_w = gdk_screen_get_width(screen);
screen_h = gdk_screen_get_height(screen);
# endif
gui_gtk_get_screen_size_of_win(beval->balloonShell,
&screen_w, &screen_h);
# if !GTK_CHECK_VERSION(3,0,0)
gtk_widget_ensure_style(beval->balloonShell);
gtk_widget_ensure_style(beval->balloonLabel);
+25 -21
View File
@@ -4941,6 +4941,29 @@ gui_mch_set_shellsize(int width, int height,
gui_mch_update();
}
void
gui_gtk_get_screen_size_of_win(GtkWidget *wid, int *width, int *height)
{
#if GTK_CHECK_VERSION(3,22,0)
GdkDisplay *dpy = gtk_widget_get_display(wid);
GdkWindow *win = gtk_widget_get_window(wid);
GdkMonitor *monitor = gdk_display_get_monitor_at_window(dpy, win);
GdkRectangle geometry;
gdk_monitor_get_geometry(monitor, &geometry);
*width = geometry.width;
*height = geometry.height;
#else
GdkScreen* screen;
if (wid != NULL && gtk_widget_has_screen(wid))
screen = gtk_widget_get_screen(wid);
else
screen = gdk_screen_get_default();
*width = gdk_screen_get_width(screen);
*height = gdk_screen_get_height(screen);
#endif
}
/*
* The screen size is used to make sure the initial window doesn't get bigger
@@ -4950,30 +4973,11 @@ gui_mch_set_shellsize(int width, int height,
void
gui_mch_get_screen_dimensions(int *screen_w, int *screen_h)
{
#if GTK_CHECK_VERSION(3,22,2)
GdkRectangle rect;
GdkMonitor * const mon = gdk_display_get_monitor_at_window(
gtk_widget_get_display(gui.mainwin),
gtk_widget_get_window(gui.mainwin));
gdk_monitor_get_geometry(mon, &rect);
gui_gtk_get_screen_size_of_win(gui.mainwin, screen_w, screen_h);
*screen_w = rect.width;
/* Subtract 'guiheadroom' from the height to allow some room for the
* window manager (task list and window title bar). */
*screen_h = rect.height - p_ghr;
#else
GdkScreen* screen;
if (gui.mainwin != NULL && gtk_widget_has_screen(gui.mainwin))
screen = gtk_widget_get_screen(gui.mainwin);
else
screen = gdk_screen_get_default();
*screen_w = gdk_screen_get_width(screen);
/* Subtract 'guiheadroom' from the height to allow some room for the
* window manager (task list and window title bar). */
*screen_h = gdk_screen_get_height(screen) - p_ghr;
#endif
*screen_h -= p_ghr;
/*
* FIXME: dirty trick: Because the gui_get_base_height() doesn't include
+1
View File
@@ -421,6 +421,7 @@ serverSendToVim(
{
LookupName(dpy, loosename ? loosename : name,
/*DELETE=*/TRUE, NULL);
vim_free(loosename);
continue;
}
}
+1 -2
View File
@@ -4887,8 +4887,7 @@ im_preedit_window_set_position(void)
if (preedit_window == NULL)
return;
sw = gdk_screen_get_width(gtk_widget_get_screen(preedit_window));
sh = gdk_screen_get_height(gtk_widget_get_screen(preedit_window));
gui_gtk_get_screen_size_of_win(preedit_window, &sw, &sh);
#if GTK_CHECK_VERSION(3,0,0)
gdk_window_get_origin(gtk_widget_get_window(gui.drawarea), &x, &y);
#else
-24
View File
@@ -3355,9 +3355,6 @@ reset_VIsual(void)
}
}
#if defined(FEAT_BEVAL)
static int find_is_eval_item(char_u *ptr, int *colp, int *nbp, int dir);
/*
* Check for a balloon-eval special item to include when searching for an
* identifier. When "dir" is BACKWARD "ptr[-1]" must be valid!
@@ -3396,7 +3393,6 @@ find_is_eval_item(
}
return FALSE;
}
#endif
/*
* Find the identifier under or to the right of the cursor.
@@ -3446,9 +3442,7 @@ find_ident_at_pos(
int prev_class;
int prevcol;
#endif
#if defined(FEAT_BEVAL)
int bn = 0; /* bracket nesting */
#endif
/*
* if i == 0: try to find an identifier
@@ -3466,11 +3460,9 @@ find_ident_at_pos(
{
while (ptr[col] != NUL)
{
# if defined(FEAT_BEVAL)
/* Stop at a ']' to evaluate "a[x]". */
if ((find_type & FIND_EVAL) && ptr[col] == ']')
break;
# endif
this_class = mb_get_class(ptr + col);
if (this_class != 0 && (i == 1 || this_class != 1))
break;
@@ -3481,16 +3473,12 @@ find_ident_at_pos(
#endif
while (ptr[col] != NUL
&& (i == 0 ? !vim_iswordc(ptr[col]) : VIM_ISWHITE(ptr[col]))
# if defined(FEAT_BEVAL)
&& (!(find_type & FIND_EVAL) || ptr[col] != ']')
# endif
)
++col;
#if defined(FEAT_BEVAL)
/* When starting on a ']' count it, so that we include the '['. */
bn = ptr[col] == ']';
#endif
/*
* 2. Back up to start of identifier/string.
@@ -3499,11 +3487,9 @@ find_ident_at_pos(
if (has_mbyte)
{
/* Remember class of character under cursor. */
# if defined(FEAT_BEVAL)
if ((find_type & FIND_EVAL) && ptr[col] == ']')
this_class = mb_get_class((char_u *)"a");
else
# endif
this_class = mb_get_class(ptr + col);
while (col > 0 && this_class != 0)
{
@@ -3513,12 +3499,10 @@ find_ident_at_pos(
&& (i == 0
|| prev_class == 0
|| (find_type & FIND_IDENT))
# if defined(FEAT_BEVAL)
&& (!(find_type & FIND_EVAL)
|| prevcol == 0
|| !find_is_eval_item(ptr + prevcol, &prevcol,
&bn, BACKWARD))
# endif
)
break;
col = prevcol;
@@ -3540,12 +3524,10 @@ find_ident_at_pos(
: (!VIM_ISWHITE(ptr[col - 1])
&& (!(find_type & FIND_IDENT)
|| !vim_iswordc(ptr[col - 1]))))
#if defined(FEAT_BEVAL)
|| ((find_type & FIND_EVAL)
&& col > 1
&& find_is_eval_item(ptr + col - 1, &col,
&bn, BACKWARD))
#endif
))
--col;
@@ -3577,10 +3559,8 @@ find_ident_at_pos(
/*
* 3. Find the end if the identifier/string.
*/
#if defined(FEAT_BEVAL)
bn = 0;
startcol -= col;
#endif
col = 0;
#ifdef FEAT_MBYTE
if (has_mbyte)
@@ -3590,11 +3570,9 @@ find_ident_at_pos(
while (ptr[col] != NUL
&& ((i == 0 ? mb_get_class(ptr + col) == this_class
: mb_get_class(ptr + col) != 0)
# if defined(FEAT_BEVAL)
|| ((find_type & FIND_EVAL)
&& col <= (int)startcol
&& find_is_eval_item(ptr + col, &col, &bn, FORWARD))
# endif
))
col += (*mb_ptr2len)(ptr + col);
}
@@ -3602,11 +3580,9 @@ find_ident_at_pos(
#endif
while ((i == 0 ? vim_iswordc(ptr[col])
: (ptr[col] != NUL && !VIM_ISWHITE(ptr[col])))
# if defined(FEAT_BEVAL)
|| ((find_type & FIND_EVAL)
&& col <= (int)startcol
&& find_is_eval_item(ptr + col, &col, &bn, FORWARD))
# endif
)
{
++col;
+1
View File
@@ -25,6 +25,7 @@ int gui_mch_maximized(void);
void gui_mch_unmaximize(void);
void gui_mch_newfont(void);
void gui_mch_set_shellsize(int width, int height, int min_width, int min_height, int base_width, int base_height, int direction);
void gui_gtk_get_screen_size_of_win(GtkWidget *win, int *width, int *height);
void gui_mch_get_screen_dimensions(int *screen_w, int *screen_h);
void gui_mch_settitle(char_u *title, char_u *icon);
void gui_mch_enable_menu(int showit);
+1 -1
View File
@@ -22,7 +22,7 @@ void ex_cnext(exarg_T *eap);
void ex_cfile(exarg_T *eap);
void ex_vimgrep(exarg_T *eap);
int get_errorlist(qf_info_T *qi, win_T *wp, int qf_idx, list_T *list);
int get_errorlist_properties(win_T *wp, dict_T *what, dict_T *retdict);
int qf_get_properties(win_T *wp, dict_T *what, dict_T *retdict);
int set_errorlist(win_T *wp, list_T *list, int action, char_u *title, dict_T *what);
int set_ref_in_quickfix(int copyID);
void ex_cbuffer(exarg_T *eap);
+30 -11
View File
@@ -4690,13 +4690,28 @@ qf_get_list_from_lines(dict_T *what, dictitem_T *di, dict_T *retdict)
return status;
}
/*
* Return the quickfix/location list number with the given identifier.
* Returns -1 if list is not found.
*/
static int
qf_id2nr(qf_info_T *qi, int_u qfid)
{
int qf_idx;
for (qf_idx = 0; qf_idx < qi->qf_listcount; qf_idx++)
if (qi->qf_lists[qf_idx].qf_id == qfid)
return qf_idx;
return -1;
}
/*
* 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
get_errorlist_properties(win_T *wp, dict_T *what, dict_T *retdict)
qf_get_properties(win_T *wp, dict_T *what, dict_T *retdict)
{
qf_info_T *qi = &ql_info;
int status = OK;
@@ -4752,12 +4767,8 @@ get_errorlist_properties(win_T *wp, dict_T *what, dict_T *retdict)
/* For zero, use the current list or the list specifed by 'nr' */
if (di->di_tv.vval.v_number != 0)
{
for (qf_idx = 0; qf_idx < qi->qf_listcount; qf_idx++)
{
if (qi->qf_lists[qf_idx].qf_id == di->di_tv.vval.v_number)
break;
}
if (qf_idx == qi->qf_listcount)
qf_idx = qf_id2nr(qi, di->di_tv.vval.v_number);
if (qf_idx == -1)
return FAIL; /* List not found */
}
flags |= QF_GETLIST_ID;
@@ -5024,10 +5035,8 @@ qf_set_properties(qf_info_T *qi, dict_T *what, int action, char_u *title)
/* Use the quickfix/location list with the specified id */
if (di->di_tv.v_type == VAR_NUMBER)
{
for (qf_idx = 0; qf_idx < qi->qf_listcount; qf_idx++)
if (qi->qf_lists[qf_idx].qf_id == di->di_tv.vval.v_number)
break;
if (qf_idx == qi->qf_listcount)
qf_idx = qf_id2nr(qi, di->di_tv.vval.v_number);
if (qf_idx == -1)
return FAIL; /* List not found */
}
else
@@ -5062,6 +5071,16 @@ qf_set_properties(qf_info_T *qi, dict_T *what, int action, char_u *title)
retval = qf_add_entries(qi, qf_idx, di->di_tv.vval.v_list,
title_save, action == ' ' ? 'a' : action);
if (action == 'r')
{
/*
* When replacing the quickfix list entries using
* qf_add_entries(), the title is set with a ':' prefix.
* Restore the title with the saved title.
*/
vim_free(qi->qf_lists[qf_idx].qf_title);
qi->qf_lists[qf_idx].qf_title = vim_strsave(title_save);
}
vim_free(title_save);
}
}
+14
View File
@@ -3139,6 +3139,7 @@ win_line(
#endif
#ifdef FEAT_TERMINAL
int get_term_attr = FALSE;
int term_attr = 0; /* background for terminal window */
#endif
/* draw_state: items that are drawn in sequence: */
@@ -3256,6 +3257,7 @@ win_line(
{
extra_check = TRUE;
get_term_attr = TRUE;
term_attr = term_get_attr(wp->w_buffer, lnum, -1);
}
#endif
@@ -5056,6 +5058,9 @@ win_line(
else if ((
# ifdef FEAT_DIFF
diff_hlf != (hlf_T)0 ||
# endif
# ifdef FEAT_TERMINAL
term_attr != 0 ||
# endif
line_attr != 0
) && (
@@ -5090,6 +5095,15 @@ win_line(
HL_ATTR(HLF_CUL));
}
}
# endif
# ifdef FEAT_TERMINAL
if (term_attr != 0)
{
char_attr = term_attr;
if (wp->w_p_cul && lnum == wp->w_cursor.lnum)
char_attr = hl_combine_attr(char_attr,
HL_ATTR(HLF_CUL));
}
# endif
}
#endif
+98 -89
View File
@@ -7364,7 +7364,6 @@ do_highlight(
int attr;
int id;
int idx;
struct hl_group *item;
struct hl_group item_before;
int dodefault = FALSE;
int doclear = FALSE;
@@ -7380,6 +7379,9 @@ do_highlight(
#else
# define is_menu_group 0
# define is_tooltip_group 0
#endif
#if defined(FEAT_GUI) || defined(FEAT_TERMGUICOLORS)
int did_highlight_changed = FALSE;
#endif
/*
@@ -7461,13 +7463,12 @@ do_highlight(
}
from_id = syn_check_group(from_start, (int)(from_end - from_start));
item = &HL_TABLE()[from_id - 1];
if (STRNCMP(to_start, "NONE", 4) == 0)
to_id = 0;
else
to_id = syn_check_group(to_start, (int)(to_end - to_start));
if (from_id > 0 && (!init || item->sg_set == 0))
if (from_id > 0 && (!init || HL_TABLE()[from_id - 1].sg_set == 0))
{
/*
* Don't allow a link when there already is some highlighting
@@ -7479,19 +7480,19 @@ do_highlight(
if (sourcing_name == NULL && !dodefault)
EMSG(_("E414: group has settings, highlight link ignored"));
}
else if (item->sg_link != to_id
else if (HL_TABLE()[from_id - 1].sg_link != to_id
#ifdef FEAT_EVAL
|| item->sg_scriptID != current_SID
|| HL_TABLE()[from_id - 1].sg_scriptID != current_SID
#endif
|| item->sg_cleared)
|| HL_TABLE()[from_id - 1].sg_cleared)
{
if (!init)
item->sg_set |= SG_LINK;
item->sg_link = to_id;
HL_TABLE()[from_id - 1].sg_set |= SG_LINK;
HL_TABLE()[from_id - 1].sg_link = to_id;
#ifdef FEAT_EVAL
item->sg_scriptID = current_SID;
HL_TABLE()[from_id - 1].sg_scriptID = current_SID;
#endif
item->sg_cleared = FALSE;
HL_TABLE()[from_id - 1].sg_cleared = FALSE;
redraw_all_later(SOME_VALID);
/* Only call highlight_changed() once after multiple changes. */
@@ -7569,8 +7570,9 @@ do_highlight(
#if defined(FEAT_GUI) || defined(FEAT_TERMGUICOLORS)
if (USE_24BIT)
highlight_gui_started();
else
#endif
highlight_changed();
highlight_changed();
redraw_later_clear();
return;
}
@@ -7585,23 +7587,22 @@ do_highlight(
if (id == 0) /* failed (out of memory) */
return;
idx = id - 1; /* index is ID minus one */
item = &HL_TABLE()[idx];
/* Return if "default" was used and the group already has settings. */
if (dodefault && hl_has_settings(idx, TRUE))
return;
/* Make a copy so we can check if any attribute actually changed. */
item_before = *item;
item_before = HL_TABLE()[idx];
if (STRCMP(item->sg_name_u, "NORMAL") == 0)
if (STRCMP(HL_TABLE()[idx].sg_name_u, "NORMAL") == 0)
is_normal_group = TRUE;
#ifdef FEAT_GUI_X11
else if (STRCMP(item->sg_name_u, "MENU") == 0)
else if (STRCMP(HL_TABLE()[idx].sg_name_u, "MENU") == 0)
is_menu_group = TRUE;
else if (STRCMP(item->sg_name_u, "SCROLLBAR") == 0)
else if (STRCMP(HL_TABLE()[idx].sg_name_u, "SCROLLBAR") == 0)
is_scrollbar_group = TRUE;
else if (STRCMP(item->sg_name_u, "TOOLTIP") == 0)
else if (STRCMP(HL_TABLE()[idx].sg_name_u, "TOOLTIP") == 0)
is_tooltip_group = TRUE;
#endif
@@ -7610,7 +7611,7 @@ do_highlight(
{
highlight_clear(idx);
if (!doclear)
item->sg_set = 0;
HL_TABLE()[idx].sg_set = 0;
}
if (!doclear)
@@ -7641,10 +7642,10 @@ do_highlight(
if (STRCMP(key, "NONE") == 0)
{
if (!init || item->sg_set == 0)
if (!init || HL_TABLE()[idx].sg_set == 0)
{
if (!init)
item->sg_set |= SG_TERM+SG_CTERM+SG_GUI;
HL_TABLE()[idx].sg_set |= SG_TERM+SG_CTERM+SG_GUI;
highlight_clear(idx);
}
continue;
@@ -7731,31 +7732,31 @@ do_highlight(
break;
if (*key == 'T')
{
if (!init || !(item->sg_set & SG_TERM))
if (!init || !(HL_TABLE()[idx].sg_set & SG_TERM))
{
if (!init)
item->sg_set |= SG_TERM;
item->sg_term = attr;
HL_TABLE()[idx].sg_set |= SG_TERM;
HL_TABLE()[idx].sg_term = attr;
}
}
else if (*key == 'C')
{
if (!init || !(item->sg_set & SG_CTERM))
if (!init || !(HL_TABLE()[idx].sg_set & SG_CTERM))
{
if (!init)
item->sg_set |= SG_CTERM;
item->sg_cterm = attr;
item->sg_cterm_bold = FALSE;
HL_TABLE()[idx].sg_set |= SG_CTERM;
HL_TABLE()[idx].sg_cterm = attr;
HL_TABLE()[idx].sg_cterm_bold = FALSE;
}
}
#if defined(FEAT_GUI) || defined(FEAT_EVAL)
else
{
if (!init || !(item->sg_set & SG_GUI))
if (!init || !(HL_TABLE()[idx].sg_set & SG_GUI))
{
if (!init)
item->sg_set |= SG_GUI;
item->sg_gui = attr;
HL_TABLE()[idx].sg_set |= SG_GUI;
HL_TABLE()[idx].sg_gui = attr;
}
}
#endif
@@ -7764,74 +7765,74 @@ do_highlight(
{
/* in non-GUI fonts are simply ignored */
#ifdef FEAT_GUI
if (item->sg_font_name != NULL
&& STRCMP(item->sg_font_name, arg) == 0)
if (HL_TABLE()[idx].sg_font_name != NULL
&& STRCMP(HL_TABLE()[idx].sg_font_name, arg) == 0)
{
/* Font name didn't change, ignore. */
}
else if (!gui.shell_created)
{
/* GUI not started yet, always accept the name. */
vim_free(item->sg_font_name);
item->sg_font_name = vim_strsave(arg);
vim_free(HL_TABLE()[idx].sg_font_name);
HL_TABLE()[idx].sg_font_name = vim_strsave(arg);
}
else
{
GuiFont temp_sg_font = item->sg_font;
GuiFont temp_sg_font = HL_TABLE()[idx].sg_font;
# ifdef FEAT_XFONTSET
GuiFontset temp_sg_fontset = item->sg_fontset;
GuiFontset temp_sg_fontset = HL_TABLE()[idx].sg_fontset;
# endif
/* First, save the current font/fontset.
* Then try to allocate the font/fontset.
* If the allocation fails, item->sg_font OR
* If the allocation fails, HL_TABLE()[idx].sg_font OR
* sg_fontset will be set to NOFONT or NOFONTSET respectively.
*/
item->sg_font = NOFONT;
HL_TABLE()[idx].sg_font = NOFONT;
# ifdef FEAT_XFONTSET
item->sg_fontset = NOFONTSET;
HL_TABLE()[idx].sg_fontset = NOFONTSET;
# endif
hl_do_font(idx, arg, is_normal_group, is_menu_group,
is_tooltip_group, FALSE);
# ifdef FEAT_XFONTSET
if (item->sg_fontset != NOFONTSET)
if (HL_TABLE()[idx].sg_fontset != NOFONTSET)
{
/* New fontset was accepted. Free the old one, if there
* was one. */
gui_mch_free_fontset(temp_sg_fontset);
vim_free(item->sg_font_name);
item->sg_font_name = vim_strsave(arg);
vim_free(HL_TABLE()[idx].sg_font_name);
HL_TABLE()[idx].sg_font_name = vim_strsave(arg);
}
else
item->sg_fontset = temp_sg_fontset;
HL_TABLE()[idx].sg_fontset = temp_sg_fontset;
# endif
if (item->sg_font != NOFONT)
if (HL_TABLE()[idx].sg_font != NOFONT)
{
/* New font was accepted. Free the old one, if there was
* one. */
gui_mch_free_font(temp_sg_font);
vim_free(item->sg_font_name);
item->sg_font_name = vim_strsave(arg);
vim_free(HL_TABLE()[idx].sg_font_name);
HL_TABLE()[idx].sg_font_name = vim_strsave(arg);
}
else
item->sg_font = temp_sg_font;
HL_TABLE()[idx].sg_font = temp_sg_font;
}
#endif
}
else if (STRCMP(key, "CTERMFG") == 0 || STRCMP(key, "CTERMBG") == 0)
{
if (!init || !(item->sg_set & SG_CTERM))
if (!init || !(HL_TABLE()[idx].sg_set & SG_CTERM))
{
if (!init)
item->sg_set |= SG_CTERM;
HL_TABLE()[idx].sg_set |= SG_CTERM;
/* When setting the foreground color, and previously the "bold"
* flag was set for a light color, reset it now */
if (key[5] == 'F' && item->sg_cterm_bold)
if (key[5] == 'F' && HL_TABLE()[idx].sg_cterm_bold)
{
item->sg_cterm &= ~HL_BOLD;
item->sg_cterm_bold = FALSE;
HL_TABLE()[idx].sg_cterm &= ~HL_BOLD;
HL_TABLE()[idx].sg_cterm_bold = FALSE;
}
if (VIM_ISDIGIT(*arg))
@@ -7888,22 +7889,22 @@ do_highlight(
* colors (on some terminals, e.g. "linux") */
if (bold == TRUE)
{
item->sg_cterm |= HL_BOLD;
item->sg_cterm_bold = TRUE;
HL_TABLE()[idx].sg_cterm |= HL_BOLD;
HL_TABLE()[idx].sg_cterm_bold = TRUE;
}
else if (bold == FALSE)
item->sg_cterm &= ~HL_BOLD;
HL_TABLE()[idx].sg_cterm &= ~HL_BOLD;
}
/* Add one to the argument, to avoid zero. Zero is used for
* "NONE", then "color" is -1. */
if (key[5] == 'F')
{
item->sg_cterm_fg = color + 1;
HL_TABLE()[idx].sg_cterm_fg = color + 1;
if (is_normal_group)
{
cterm_normal_fg_color = color + 1;
cterm_normal_fg_bold = (item->sg_cterm & HL_BOLD);
cterm_normal_fg_bold = (HL_TABLE()[idx].sg_cterm & HL_BOLD);
#ifdef FEAT_GUI
/* Don't do this if the GUI is used. */
if (!gui.in_use && !gui.starting)
@@ -7917,7 +7918,7 @@ do_highlight(
}
else
{
item->sg_cterm_bg = color + 1;
HL_TABLE()[idx].sg_cterm_bg = color + 1;
if (is_normal_group)
{
cterm_normal_bg_color = color + 1;
@@ -7957,23 +7958,23 @@ do_highlight(
else if (STRCMP(key, "GUIFG") == 0)
{
#if defined(FEAT_GUI) || defined(FEAT_EVAL)
if (!init || !(item->sg_set & SG_GUI))
if (!init || !(HL_TABLE()[idx].sg_set & SG_GUI))
{
if (!init)
item->sg_set |= SG_GUI;
HL_TABLE()[idx].sg_set |= SG_GUI;
# if defined(FEAT_GUI) || defined(FEAT_TERMGUICOLORS)
/* In GUI guifg colors are only used when recognized */
i = color_name2handle(arg);
if (i != INVALCOLOR || STRCMP(arg, "NONE") == 0 || !USE_24BIT)
{
item->sg_gui_fg = i;
HL_TABLE()[idx].sg_gui_fg = i;
# endif
vim_free(item->sg_gui_fg_name);
vim_free(HL_TABLE()[idx].sg_gui_fg_name);
if (STRCMP(arg, "NONE") != 0)
item->sg_gui_fg_name = vim_strsave(arg);
HL_TABLE()[idx].sg_gui_fg_name = vim_strsave(arg);
else
item->sg_gui_fg_name = NULL;
HL_TABLE()[idx].sg_gui_fg_name = NULL;
# if defined(FEAT_GUI) || defined(FEAT_TERMGUICOLORS)
# ifdef FEAT_GUI_X11
if (is_menu_group)
@@ -7994,23 +7995,23 @@ do_highlight(
else if (STRCMP(key, "GUIBG") == 0)
{
#if defined(FEAT_GUI) || defined(FEAT_EVAL)
if (!init || !(item->sg_set & SG_GUI))
if (!init || !(HL_TABLE()[idx].sg_set & SG_GUI))
{
if (!init)
item->sg_set |= SG_GUI;
HL_TABLE()[idx].sg_set |= SG_GUI;
# if defined(FEAT_GUI) || defined(FEAT_TERMGUICOLORS)
/* In GUI guifg colors are only used when recognized */
i = color_name2handle(arg);
if (i != INVALCOLOR || STRCMP(arg, "NONE") == 0 || !USE_24BIT)
{
item->sg_gui_bg = i;
HL_TABLE()[idx].sg_gui_bg = i;
# endif
vim_free(item->sg_gui_bg_name);
vim_free(HL_TABLE()[idx].sg_gui_bg_name);
if (STRCMP(arg, "NONE") != 0)
item->sg_gui_bg_name = vim_strsave(arg);
HL_TABLE()[idx].sg_gui_bg_name = vim_strsave(arg);
else
item->sg_gui_bg_name = NULL;
HL_TABLE()[idx].sg_gui_bg_name = NULL;
# if defined(FEAT_GUI) || defined(FEAT_TERMGUICOLORS)
# ifdef FEAT_GUI_X11
if (is_menu_group)
@@ -8031,22 +8032,22 @@ do_highlight(
else if (STRCMP(key, "GUISP") == 0)
{
#if defined(FEAT_GUI) || defined(FEAT_EVAL)
if (!init || !(item->sg_set & SG_GUI))
if (!init || !(HL_TABLE()[idx].sg_set & SG_GUI))
{
if (!init)
item->sg_set |= SG_GUI;
HL_TABLE()[idx].sg_set |= SG_GUI;
# ifdef FEAT_GUI
i = color_name2handle(arg);
if (i != INVALCOLOR || STRCMP(arg, "NONE") == 0 || !gui.in_use)
{
item->sg_gui_sp = i;
HL_TABLE()[idx].sg_gui_sp = i;
# endif
vim_free(item->sg_gui_sp_name);
vim_free(HL_TABLE()[idx].sg_gui_sp_name);
if (STRCMP(arg, "NONE") != 0)
item->sg_gui_sp_name = vim_strsave(arg);
HL_TABLE()[idx].sg_gui_sp_name = vim_strsave(arg);
else
item->sg_gui_sp_name = NULL;
HL_TABLE()[idx].sg_gui_sp_name = NULL;
# ifdef FEAT_GUI
}
# endif
@@ -8059,7 +8060,7 @@ do_highlight(
char_u *tname;
if (!init)
item->sg_set |= SG_TERM;
HL_TABLE()[idx].sg_set |= SG_TERM;
/*
* The "start" and "stop" arguments can be a literal escape
@@ -8126,13 +8127,13 @@ do_highlight(
p = vim_strsave(buf);
if (key[2] == 'A')
{
vim_free(item->sg_start);
item->sg_start = p;
vim_free(HL_TABLE()[idx].sg_start);
HL_TABLE()[idx].sg_start = p;
}
else
{
vim_free(item->sg_stop);
item->sg_stop = p;
vim_free(HL_TABLE()[idx].sg_stop);
HL_TABLE()[idx].sg_stop = p;
}
}
else
@@ -8141,13 +8142,13 @@ do_highlight(
error = TRUE;
break;
}
item->sg_cleared = FALSE;
HL_TABLE()[idx].sg_cleared = FALSE;
/*
* When highlighting has been given for a group, don't link it.
*/
if (!init || !(item->sg_set & SG_LINK))
item->sg_link = 0;
if (!init || !(HL_TABLE()[idx].sg_set & SG_LINK))
HL_TABLE()[idx].sg_link = 0;
/*
* Continue with next argument.
@@ -8164,10 +8165,10 @@ do_highlight(
{
if (is_normal_group)
{
item->sg_term_attr = 0;
item->sg_cterm_attr = 0;
HL_TABLE()[idx].sg_term_attr = 0;
HL_TABLE()[idx].sg_cterm_attr = 0;
#ifdef FEAT_GUI
item->sg_gui_attr = 0;
HL_TABLE()[idx].sg_gui_attr = 0;
/*
* Need to update all groups, because they might be using "bg"
* and/or "fg", which have been changed now.
@@ -8175,7 +8176,11 @@ do_highlight(
#endif
#if defined(FEAT_GUI) || defined(FEAT_TERMGUICOLORS)
if (USE_24BIT)
{
highlight_gui_started();
did_highlight_changed = TRUE;
redraw_all_later(NOT_VALID);
}
#endif
}
#ifdef FEAT_GUI_X11
@@ -8202,7 +8207,7 @@ do_highlight(
else
set_hl_attr(idx);
#ifdef FEAT_EVAL
item->sg_scriptID = current_SID;
HL_TABLE()[idx].sg_scriptID = current_SID;
#endif
}
@@ -8211,7 +8216,11 @@ do_highlight(
/* Only call highlight_changed() once, after a sequence of highlight
* commands, and only if an attribute actually changed. */
if (memcmp(item, &item_before, sizeof(item_before)) != 0)
if (memcmp(&HL_TABLE()[idx], &item_before, sizeof(item_before)) != 0
#if defined(FEAT_GUI) || defined(FEAT_TERMGUICOLORS)
&& !did_highlight_changed
#endif
)
{
redraw_all_later(NOT_VALID);
need_highlight_changed = TRUE;
+2 -2
View File
@@ -4572,12 +4572,12 @@ check_termcode(
/* Detect terminals that set $TERM to something like
* "xterm-256colors" but are not fully xterm
* compatible. */
# ifdef MACOS
/* Mac Terminal.app sends 1;95;0 */
if (version == 95
&& STRNCMP(tp + extra - 2, "1;95;0c", 7) == 0)
is_not_xterm = TRUE;
# endif
/* Gnome terminal sends 1;3801;0, 1;4402;0 or 1;2501;0.
* xfce4-terminal sends 1;2802;0.
* screen sends 83;40500;0
+89 -24
View File
@@ -39,6 +39,7 @@
*
* TODO:
* - patch to use GUI or cterm colors for vterm. Yasuhiro, #2067
* - patch to add tmap, jakalope (Jacob Askeland) #2073
* - Redirecting output does not work on MS-Windows.
* - implement term_setsize()
* - add test for giving error for invalid 'termsize' value.
@@ -84,6 +85,7 @@ typedef struct {
typedef struct sb_line_S {
int sb_cols; /* can differ per line */
cellattr_T *sb_cells; /* allocated */
cellattr_T sb_fill_attr; /* for short line */
} sb_line_T;
/* typedef term_T in structs.h */
@@ -126,6 +128,7 @@ struct terminal_S {
garray_T tl_scrollback;
int tl_scrollback_scrolled;
cellattr_T tl_default_color;
VTermPos tl_cursor_pos;
int tl_cursor_visible;
@@ -393,6 +396,7 @@ term_start(typval_T *argvar, jobopt_T *opt, int forceit)
vim_snprintf((char *)p, len, "!%s (%d)", cmd, i);
if (buflist_findname(p) == NULL)
{
vim_free(curbuf->b_ffname);
curbuf->b_ffname = p;
break;
}
@@ -552,6 +556,7 @@ ex_terminal(exarg_T *eap)
argvar[1].v_type = VAR_UNKNOWN;
term_start(argvar, &opt, eap->forceit);
vim_free(tofree);
vim_free(opt.jo_eof_chars);
}
/*
@@ -944,6 +949,28 @@ add_scrollback_line_to_buffer(term_T *term, char_u *text, int len)
}
}
static void
cell2cellattr(const VTermScreenCell *cell, cellattr_T *attr)
{
attr->width = cell->width;
attr->attrs = cell->attrs;
attr->fg = cell->fg;
attr->bg = cell->bg;
}
static int
equal_celattr(cellattr_T *a, cellattr_T *b)
{
/* Comparing the colors should be sufficient. */
return a->fg.red == b->fg.red
&& a->fg.green == b->fg.green
&& a->fg.blue == b->fg.blue
&& a->bg.red == b->bg.red
&& a->bg.green == b->bg.green
&& a->bg.blue == b->bg.blue;
}
/*
* Add the current lines of the terminal to scrollback and to the buffer.
* Called after the job has ended and when switching to Terminal-Normal mode.
@@ -956,21 +983,30 @@ move_terminal_to_buffer(term_T *term)
int lines_skipped = 0;
VTermPos pos;
VTermScreenCell cell;
cellattr_T fill_attr, new_fill_attr;
cellattr_T *p;
VTermScreen *screen;
if (term->tl_vterm == NULL)
return;
screen = vterm_obtain_screen(term->tl_vterm);
fill_attr = new_fill_attr = term->tl_default_color;
for (pos.row = 0; pos.row < term->tl_rows; ++pos.row)
{
len = 0;
for (pos.col = 0; pos.col < term->tl_cols; ++pos.col)
if (vterm_screen_get_cell(screen, pos, &cell) != 0
&& cell.chars[0] != NUL)
{
len = pos.col + 1;
new_fill_attr = term->tl_default_color;
}
else
/* Assume the last attr is the filler attr. */
cell2cellattr(&cell, &new_fill_attr);
if (len == 0)
if (len == 0 && equal_celattr(&new_fill_attr, &fill_attr))
++lines_skipped;
else
{
@@ -985,14 +1021,19 @@ move_terminal_to_buffer(term_T *term)
line->sb_cols = 0;
line->sb_cells = NULL;
line->sb_fill_attr = fill_attr;
++term->tl_scrollback.ga_len;
add_scrollback_line_to_buffer(term, (char_u *)"", 0);
}
}
p = (cellattr_T *)alloc((int)sizeof(cellattr_T) * len);
if (p != NULL && ga_grow(&term->tl_scrollback, 1) == OK)
if (len == 0)
p = NULL;
else
p = (cellattr_T *)alloc((int)sizeof(cellattr_T) * len);
if ((p != NULL || len == 0)
&& ga_grow(&term->tl_scrollback, 1) == OK)
{
garray_T ga;
int width;
@@ -1014,10 +1055,7 @@ move_terminal_to_buffer(term_T *term)
{
width = cell.width;
p[pos.col].width = cell.width;
p[pos.col].attrs = cell.attrs;
p[pos.col].fg = cell.fg;
p[pos.col].bg = cell.bg;
cell2cellattr(&cell, &p[pos.col]);
if (ga_grow(&ga, MB_MAXBYTES) == OK)
{
@@ -1032,6 +1070,8 @@ move_terminal_to_buffer(term_T *term)
}
line->sb_cols = len;
line->sb_cells = p;
line->sb_fill_attr = new_fill_attr;
fill_attr = new_fill_attr;
++term->tl_scrollback.ga_len;
if (ga_grow(&ga, 1) == FAIL)
@@ -1048,6 +1088,10 @@ move_terminal_to_buffer(term_T *term)
}
}
/* Obtain the current background color. */
vterm_state_get_default_colors(vterm_obtain_state(term->tl_vterm),
&term->tl_default_color.fg, &term->tl_default_color.bg);
FOR_ALL_WINDOWS(wp)
{
if (wp->w_buffer == term->tl_buffer)
@@ -2004,11 +2048,14 @@ handle_pushline(int cols, const VTermScreenCell *cells, void *user)
int col;
sb_line_T *line;
garray_T ga;
cellattr_T fill_attr = term->tl_default_color;
/* do not store empty cells at the end */
for (i = 0; i < cols; ++i)
if (cells[i].chars[0] != 0)
len = i + 1;
else
cell2cellattr(&cells[i], &fill_attr);
ga_init2(&ga, 1, 100);
if (len > 0)
@@ -2025,10 +2072,7 @@ handle_pushline(int cols, const VTermScreenCell *cells, void *user)
for (i = 0; (c = cells[col].chars[i]) > 0 || i == 0; ++i)
ga.ga_len += utf_char2bytes(c == NUL ? ' ' : c,
(char_u *)ga.ga_data + ga.ga_len);
p[col].width = cells[col].width;
p[col].attrs = cells[col].attrs;
p[col].fg = cells[col].fg;
p[col].bg = cells[col].bg;
cell2cellattr(&cells[col], &p[col]);
}
}
if (ga_grow(&ga, 1) == FAIL)
@@ -2044,6 +2088,7 @@ handle_pushline(int cols, const VTermScreenCell *cells, void *user)
+ term->tl_scrollback.ga_len;
line->sb_cols = len;
line->sb_cells = p;
line->sb_fill_attr = fill_attr;
++term->tl_scrollback.ga_len;
++term->tl_scrollback_scrolled;
}
@@ -2320,6 +2365,7 @@ term_change_in_curbuf(void)
/*
* Get the screen attribute for a position in the buffer.
* Use a negative "col" to get the filler background color.
*/
int
term_get_attr(buf_T *buf, linenr_T lnum, int col)
@@ -2329,11 +2375,15 @@ term_get_attr(buf_T *buf, linenr_T lnum, int col)
cellattr_T *cellattr;
if (lnum > term->tl_scrollback.ga_len)
return 0;
line = (sb_line_T *)term->tl_scrollback.ga_data + lnum - 1;
if (col >= line->sb_cols)
return 0;
cellattr = line->sb_cells + col;
cellattr = &term->tl_default_color;
else
{
line = (sb_line_T *)term->tl_scrollback.ga_data + lnum - 1;
if (col < 0 || col >= line->sb_cols)
cellattr = &line->sb_fill_attr;
else
cellattr = line->sb_cells + col;
}
return cell2attr(cellattr->attrs, cellattr->fg, cellattr->bg);
}
@@ -2346,6 +2396,8 @@ create_vterm(term_T *term, int rows, int cols)
VTerm *vterm;
VTermScreen *screen;
VTermValue value;
VTermColor *fg, *bg;
int fgval, bgval;
vterm = vterm_new(rows, cols);
term->tl_vterm = vterm;
@@ -2356,14 +2408,23 @@ create_vterm(term_T *term, int rows, int cols)
/* Vterm uses a default black background. Set it to white when
* 'background' is "light". */
vim_memset(&term->tl_default_color.attrs, 0, sizeof(VTermScreenCellAttrs));
term->tl_default_color.width = 1;
fg = &term->tl_default_color.fg;
bg = &term->tl_default_color.bg;
if (*p_bg == 'l')
{
VTermColor fg, bg;
fg.red = fg.green = fg.blue = 0;
bg.red = bg.green = bg.blue = 255;
vterm_state_set_default_colors(vterm_obtain_state(vterm), &fg, &bg);
fgval = 0;
bgval = 255;
}
else
{
fgval = 255;
bgval = 0;
}
fg->red = fg->green = fg->blue = fgval;
bg->red = bg->green = bg->blue = bgval;
vterm_state_set_default_colors(vterm_obtain_state(vterm), fg, bg);
/* Required to initialize most things. */
vterm_screen_reset(screen, 1 /* hard */);
@@ -3101,6 +3162,7 @@ term_and_job_init(
jobopt_T *opt)
{
WCHAR *cmd_wchar = NULL;
WCHAR *cwd_wchar = NULL;
channel_T *channel = NULL;
job_T *job = NULL;
DWORD error;
@@ -3128,6 +3190,8 @@ term_and_job_init(
cmd_wchar = enc_to_utf16(cmd, NULL);
if (cmd_wchar == NULL)
return FAIL;
if (opt->jo_cwd != NULL)
cwd_wchar = enc_to_utf16(opt->jo_cwd, NULL);
job = job_alloc();
if (job == NULL)
@@ -3154,7 +3218,7 @@ term_and_job_init(
WINPTY_SPAWN_FLAG_EXIT_AFTER_SHUTDOWN,
NULL,
cmd_wchar,
NULL,
cwd_wchar,
NULL,
&winpty_err);
if (spawn_config == NULL)
@@ -3205,6 +3269,7 @@ term_and_job_init(
winpty_spawn_config_free(spawn_config);
vim_free(cmd_wchar);
vim_free(cwd_wchar);
create_vterm(term, term->tl_rows, term->tl_cols);
@@ -3228,8 +3293,8 @@ term_and_job_init(
failed:
if (argvar->v_type == VAR_LIST)
vim_free(ga.ga_data);
if (cmd_wchar != NULL)
vim_free(cmd_wchar);
vim_free(cmd_wchar);
vim_free(cwd_wchar);
if (spawn_config != NULL)
winpty_spawn_config_free(spawn_config);
if (channel != NULL)
+1
View File
@@ -194,6 +194,7 @@ NEW_TESTS = test_arabic.res \
test_system.res \
test_tcl.res \
test_terminal.res \
test_terminal_fail.res \
test_textobjects.res \
test_undo.res \
test_usercommands.res \
+2 -1
View File
@@ -35,7 +35,8 @@ func Test_client_server()
endif
" Takes a short while for the server to be active.
call WaitFor('serverlist() =~ "' . name . '"')
" When using valgrind it takes much longer.
call WaitFor('serverlist() =~ "' . name . '"', 5000)
call assert_match(name, serverlist())
call remote_foreground(name)
+16 -4
View File
@@ -389,10 +389,22 @@ func! Test_normal10_expand()
call setline(1, ['1', 'ifooar,,cbar'])
2
norm! $
let a=expand('<cword>')
let b=expand('<cWORD>')
call assert_equal('cbar', a)
call assert_equal('ifooar,,cbar', b)
call assert_equal('cbar', expand('<cword>'))
call assert_equal('ifooar,,cbar', expand('<cWORD>'))
call setline(1, ['prx = list[idx];'])
1
let expected = ['', 'prx', 'prx', 'prx',
\ 'list', 'list', 'list', 'list', 'list', 'list', 'list',
\ 'idx', 'idx', 'idx', 'idx',
\ 'list[idx]',
\ '];',
\ ]
for i in range(1, 16)
exe 'norm ' . i . '|'
call assert_equal(expected[i], expand('<cexpr>'), 'i == ' . i)
endfor
" clean up
bw!
endfunc
+24 -2
View File
@@ -487,6 +487,19 @@ func s:test_xhelpgrep(cchar)
" This wipes out the buffer, make sure that doesn't cause trouble.
Xclose
if a:cchar == 'l'
" When a help window is present, running :lhelpgrep should reuse the
" help window and not the current window
new | only
call g:Xsetlist([], 'f')
help index.txt
wincmd w
lhelpgrep quickfix
call assert_equal(1, winnr())
call assert_notequal([], getloclist(1))
call assert_equal([], getloclist(2))
endif
new | only
" Search for non existing help string
@@ -1684,6 +1697,10 @@ func HistoryTest(cchar)
call assert_equal(' error list 1 of 3; 1 ' . common, res[0])
call assert_equal(' error list 2 of 3; 2 ' . common, res[1])
call assert_equal('> error list 3 of 3; 3 ' . common, res[2])
call g:Xsetlist([], 'f')
let l = split(execute(a:cchar . 'hist'), "\n")
call assert_equal('No entries', l[0])
endfunc
func Test_history()
@@ -1862,6 +1879,11 @@ func Xproperty_tests(cchar)
let l = g:Xgetlist({'items':1})
call assert_equal(0, len(l.items))
call g:Xsetlist([], 'r', {'title' : 'TestTitle'})
call g:Xsetlist([], 'r', {'items' : [{'filename' : 'F1', 'lnum' : 10, 'text' : 'L10'}]})
call g:Xsetlist([], 'r', {'items' : [{'filename' : 'F1', 'lnum' : 10, 'text' : 'L10'}]})
call assert_equal('TestTitle', g:Xgetlist({'title' : 1}).title)
" The following used to crash Vim with address sanitizer
call g:Xsetlist([], 'f')
call g:Xsetlist([], 'a', {'items' : [{'filename':'F1', 'lnum':10}]})
@@ -1904,10 +1926,10 @@ func Xproperty_tests(cchar)
call g:Xsetlist([], 'r', l2)
let newl1=g:Xgetlist({'nr':1,'all':1})
let newl2=g:Xgetlist({'nr':2,'all':1})
call assert_equal(':Fruits', newl1.title)
call assert_equal('Fruits', newl1.title)
call assert_equal(['Fruits'], newl1.context)
call assert_equal('Line20', newl1.items[0].text)
call assert_equal(':Colors', newl2.title)
call assert_equal('Colors', newl2.title)
call assert_equal(['Colors'], newl2.context)
call assert_equal('Line10', newl2.items[0].text)
call g:Xsetlist([], 'f')
+15 -22
View File
@@ -104,6 +104,15 @@ func! s:Nasty_exit_cb(job, st)
let g:buf = 0
endfunc
func Get_cat_123_cmd()
if has('win32')
return 'cmd /c "cls && color 2 && echo 123"'
else
call writefile(["\<Esc>[32m123"], 'Xtext')
return "cat Xtext"
endif
endfunc
func Test_terminal_nasty_cb()
let cmd = Get_cat_123_cmd()
let g:buf = term_start(cmd, {'exit_cb': function('s:Nasty_exit_cb')})
@@ -143,15 +152,6 @@ func Check_123(buf)
call assert_equal('123', l)
endfunc
func Get_cat_123_cmd()
if has('win32')
return 'cmd /c "cls && color 2 && echo 123"'
else
call writefile(["\<Esc>[32m123"], 'Xtext')
return "cat Xtext"
endif
endfunc
func Test_terminal_scrape_123()
let cmd = Get_cat_123_cmd()
let buf = term_start(cmd)
@@ -197,7 +197,7 @@ func Test_terminal_scrape_multibyte()
let g:line = 1
endif
call WaitFor('term_scrape(g:buf, g:line)[0].chars == "l"')
call WaitFor('len(term_scrape(g:buf, g:line)) >= 7 && term_scrape(g:buf, g:line)[0].chars == "l"')
let l = term_scrape(g:buf, g:line)
call assert_true(len(l) >= 7)
call assert_equal('l', l[0].chars)
@@ -393,18 +393,16 @@ func Test_finish_open_close()
call assert_equal(2, winnr('$'))
call assert_equal(4, winheight(0))
bwipe
endfunc
func Test_terminal_cwd()
if !has('unix')
if !executable('pwd')
return
endif
call mkdir('Xdir')
let buf = term_start('pwd', {'cwd': 'Xdir'})
sleep 100m
call term_wait(buf)
call assert_equal(getcwd() . '/Xdir', getline(1))
call WaitFor('"Xdir" == fnamemodify(getline(1), ":t")')
call assert_equal('Xdir', fnamemodify(getline(1), ":t"))
exe buf . 'bwipe'
call delete('Xdir', 'rf')
@@ -609,18 +607,13 @@ func Test_terminal_redir_file()
call term_wait(buf)
call WaitFor('len(readfile("Xfile")) > 0')
call assert_match('123', readfile('Xfile')[0])
let g:job = term_getjob(buf)
call WaitFor('job_status(g:job) == "dead"')
call delete('Xfile')
bwipe
endif
if has('unix')
let buf = term_start('xyzabc', {'err_io': 'file', 'err_name': 'Xfile'})
call term_wait(buf)
call WaitFor('len(readfile("Xfile")) > 0')
call assert_match('executing job failed', readfile('Xfile')[0])
call delete('Xfile')
bwipe
call writefile(['one line'], 'Xfile')
let buf = term_start('cat', {'in_io': 'file', 'in_name': 'Xfile'})
call term_wait(buf)
+21
View File
@@ -0,0 +1,21 @@
" This test is in a separate file, because it usually causes reports for memory
" leaks under valgrind. That is because when fork/exec fails memory is not
" freed. Since the process exists right away it's not a real leak.
if !has('terminal')
finish
endif
source shared.vim
func Test_terminal_redir_fails()
if has('unix')
let buf = term_start('xyzabc', {'err_io': 'file', 'err_name': 'Xfile'})
call term_wait(buf)
call WaitFor('len(readfile("Xfile")) > 0')
call assert_match('executing job failed', readfile('Xfile')[0])
call WaitFor('!&modified')
call delete('Xfile')
bwipe
endif
endfunc
+40
View File
@@ -784,6 +784,46 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
1097,
/**/
1096,
/**/
1095,
/**/
1094,
/**/
1093,
/**/
1092,
/**/
1091,
/**/
1090,
/**/
1089,
/**/
1088,
/**/
1087,
/**/
1086,
/**/
1085,
/**/
1084,
/**/
1083,
/**/
1082,
/**/
1081,
/**/
1080,
/**/
1079,
/**/
1078,
/**/
1077,
/**/