Compare commits

...

9 Commits

Author SHA1 Message Date
Bram Moolenaar
a1d5c154db patch 8.0.1396: memory leak when CTRL-G in search command line fails
Problem:    Memory leak when CTRL-G in search command line fails.
Solution:   Move restore_last_search_pattern to after "if".
2017-12-16 19:05:22 +01:00
Bram Moolenaar
200d0e36bc patch 8.0.1395: it is not easy to see if a colorscheme is well written
Problem:    It is not easy to see if a colorscheme is well written.
Solution:   Add a script that checks for common mistakes. (Christian Brabandt)
2017-12-16 18:53:35 +01:00
Bram Moolenaar
7e1652c63c patch 8.0.1394: cannot intercept a yank command
Problem:    Cannot intercept a yank command.
Solution:   Add the TextYankPost autocommand event. (Philippe Vaucher et al.,
            closes #2333)
2017-12-16 18:27:02 +01:00
Bram Moolenaar
6621605eb9 patch 8.0.1393: too much highlighting with 'hlsearch' and 'incsearch' set
Problem:    Too much highlighting with 'hlsearch' and 'incsearch' set.
Solution:   Do not highlight matches when the pattern matches everything.
2017-12-16 16:33:44 +01:00
Bram Moolenaar
8b42328cef patch 8.0.1392: build fails with --with-features=huge --disable-channel
Problem:    Build fails with --with-features=huge --disable-channel.
Solution:   Don't enable the terminal feature when the channel feature is
            missing. (Dominique Pelle, closes #2453)
2017-12-16 14:37:06 +01:00
Bram Moolenaar
b29d328eb4 patch 8.0.1391: encoding empty string to JSON sometimes gives "null"
Problem:    Encoding empty string to JSON sometimes gives "null".
Solution:   Handle NULL string as empty string. (closes #2446)
2017-12-15 21:25:01 +01:00
Bram Moolenaar
4697399e8c move netrw back to the previous version 2017-12-14 19:56:46 +01:00
Bram Moolenaar
7f88b65f6c patch 8.0.1390: DirectX scrolling can be slow, vertical positioning is off
Problem:    DirectX scrolling can be slow, vertical positioning is off.
Solution:   Make scroll slightly faster when using "scrlines:1". Fix y
            position of displayed text. Fix DirectX with non-utf8 encoding.
            (Ken Takata, closes #2440)
2017-12-14 13:15:19 +01:00
Bram Moolenaar
a6d4849c71 patch 8.0.1389: getqflist() items are missing if not set
Problem:    getqflist() items are missing if not set, that makes it more
            difficult to handle the values.
Solution:   When a value is not available return zero or another invalid
            value. (Yegappan Lakshmanan, closes #2430)
2017-12-12 22:45:31 +01:00
29 changed files with 1183 additions and 961 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -1,7 +1,7 @@
" netrwSettings.vim: makes netrw settings simpler
" Date: Nov 09, 2016
" Date: Dec 30, 2014
" Maintainer: Charles E Campbell <drchipNOSPAM at campbellfamily dot biz>
" Version: 16
" Version: 15
" Copyright: Copyright (C) 1999-2007 Charles E. Campbell {{{1
" Permission is hereby granted to use and distribute this code,
" with or without modifications, provided that this copyright
@@ -19,7 +19,7 @@
if exists("g:loaded_netrwSettings") || &cp
finish
endif
let g:loaded_netrwSettings = "v16"
let g:loaded_netrwSettings = "v15"
if v:version < 700
echohl WarningMsg
echo "***warning*** this version of netrwSettings needs vim 7.0"
@@ -154,13 +154,9 @@ fun! netrwSettings#NetrwSettings()
put = 'let g:netrw_list_hide = '.g:netrw_list_hide
put = 'let g:netrw_liststyle = '.g:netrw_liststyle
put = 'let g:netrw_localcopycmd = '.g:netrw_localcopycmd
put = 'let g:netrw_localcopycmdopt = '.g:netrw_localcopycmdopt
put = 'let g:netrw_localmkdir = '.g:netrw_localmkdir
put = 'let g:netrw_localmkdiropt = '.g:netrw_localmkdiropt
put = 'let g:netrw_localmovecmd = '.g:netrw_localmovecmd
put = 'let g:netrw_localmovecmdopt = '.g:netrw_localmovecmdopt
put = 'let g:netrw_localrmdir = '.g:netrw_localrmdir
put = 'let g:netrw_localrmdiropt = '.g:netrw_localrmdiropt
put = 'let g:netrw_maxfilenamelen = '.g:netrw_maxfilenamelen
put = 'let g:netrw_menu = '.g:netrw_menu
put = 'let g:netrw_mousemaps = '.g:netrw_mousemaps

View File

@@ -64,6 +64,7 @@ Search for "highlight_init".
If you think you have a color scheme that is good enough to be used by others,
please check the following items:
- Source the check_colors.vim script to check for common mistakes.
- Does it work in a color terminal as well as in the GUI?
- Is "g:colors_name" set to a meaningful value? In case of doubt you can do
it this way:

View File

@@ -0,0 +1,136 @@
" This script tests a color scheme for some errors. Load the scheme and source
" this script. e.g. :e colors/desert.vim | :so test_colors.vim
" Will output possible errors.
let s:save_cpo= &cpo
set cpo&vim
func! Test_check_colors()
call cursor(1,1)
let err={}
" 1) Check g:colors_name is existing
if !search('\<\%(g:\)\?colors_name\>', 'cnW')
let err['colors_name'] = 'g:colors_name not set'
else
let err['colors_name'] = 'OK'
endif
" 2) Check for some well-defined highlighting groups
" Some items, check several groups, e.g. Diff, Spell
let hi_groups = ['ColorColumn', 'Diff', 'ErrorMsg', 'Folded',
\ 'FoldColumn', 'IncSearch', 'LineNr', 'ModeMsg', 'MoreMsg', 'NonText',
\ 'Normal', 'Pmenu', 'Todo', 'Search', 'Spell', 'StatusLine', 'TabLine',
\ 'Title', 'Visual', 'WarningMsg', 'WildMenu']
let groups={}
for group in hi_groups
if search('\c@suppress\s\+'.group, 'cnW')
" skip check, if the script contains a line like
" @suppress Visual:
let groups[group] = 'Ignoring '.group
continue
endif
if !search('hi\%[ghlight] \+'.group, 'cnW')
let groups[group] = 'No highlight definition for '.group
continue
endif
if !search('hi\%[ghlight] \+'.group. '.*fg=', 'cnW')
let groups[group] = 'Missing foreground color for '.group
continue
endif
if search('hi\%[ghlight] \+'.group. '.*guibg=', 'cnW') &&
\ !search('hi\%[ghlight] \+'.group. '.*ctermbg=', 'cnW')
let groups[group] = 'Missing bg terminal color for '.group
continue
endif
call search('hi\%[ghlight] \+'.group, 'cW')
" only check in the current line
if !search('guifg', 'cnW', line('.')) || !search('ctermfg', 'cnW', line('.'))
" do not check for background colors, they could be intentionally left out
let groups[group] = 'Missing fg definition for '.group
endif
call cursor(1,1)
endfor
let err['highlight'] = groups
" 3) Check, that it does not set background highlighting
" Doesn't ':hi Normal ctermfg=253 ctermfg=233' also set the background sometimes?
let bg_set='\(set\?\|setl\(ocal\)\?\) .*\(background\|bg\)=\(dark\|light\)'
let bg_let='let \%([&]\%([lg]:\)\?\)\%(background\|bg\)\s*=\s*\([''"]\?\)\w\+\1'
let bg_pat='\%('.bg_set. '\|'.bg_let.'\)'
let line=search(bg_pat, 'cnW')
if search(bg_pat, 'cnW')
exe line
if search('hi \U\w\+\s\+\S', 'cbnW')
let err['background'] = 'Should not set background option after :hi statement'
endif
else
let err['background'] = 'OK'
endif
call cursor(1,1)
" 4) Check, that t_Co is checked
let pat = '[&]t_Co\s*[<>=]=\?\s*\d\+'
if !search(pat, 'ncW')
let err['t_Co'] = 'Does not check terminal for capable colors'
endif
" 5) Initializes correctly, e.g. should have a section like
" hi clear
" if exists("syntax_on")
" syntax reset
" endif
let pat='hi\%[ghlight]\s*clear\n\s*if\s*exists(\([''"]\)syntax_on\1)\n\s*syn\%[tax]\s*reset\n\s*endif'
if !search(pat, 'cnW')
let err['init'] = 'No initialization'
endif
" 6) Does not use :syn on
if search('syn\%[tax]\s\+on', 'cnW')
let err['background'] = 'Should not issue :syn on'
endif
" 7) Does not define filetype specfic groups like vimCommand, htmlTag,
let hi_groups = ['vim', 'html', 'python', 'sh', 'ruby']
for group in hi_groups
let pat='\Chi\%[ghlight]\s*\zs'.group.'\w\+\>'
if search(pat, 'cnW')
let line = search(pat, 'cW')
let err['filetype'] = get(err, 'filetype', 'Should not define: ') . matchstr(getline('.'), pat). ' '
endif
call cursor(1,1)
endfor
let g:err = err
" print Result
call Result(err)
endfu
fu! Result(err)
let do_roups = 0
echohl Title|echomsg "---------------"|echohl Normal
for key in sort(keys(a:err))
if key is# 'highlight'
let do_groups = 1
continue
else
if a:err[key] !~ 'OK'
echohl Title
endif
echomsg printf("%15s: %s", key, a:err[key])
echohl Normal
endif
endfor
echohl Title|echomsg "---------------"|echohl Normal
if do_groups
echohl Title | echomsg "Groups" | echohl Normal
for v1 in sort(keys(a:err['highlight']))
echomsg printf("%25s: %s", v1, a:err['highlight'][v1])
endfor
endif
endfu
call Test_check_colors()
let &cpo = s:save_cpo
unlet s:save_cpo

View File

@@ -330,6 +330,7 @@ Name triggered by ~
|TextChanged| after a change was made to the text in Normal mode
|TextChangedI| after a change was made to the text in Insert mode
|TextYankPost| after text is yanked or deleted
|ColorScheme| after loading a color scheme
@@ -956,6 +957,26 @@ TextChangedI After a change was made to the text in the
current buffer in Insert mode.
Not triggered when the popup menu is visible.
Otherwise the same as TextChanged.
|TextYankPost|
TextYankPost After text has been yanked or deleted in the
current buffer. The following values of
|v:event| can be used to determine the operation
that triggered this autocmd:
operator The operation performed.
regcontents Text that was stored in the
register, as a list of lines,
like with: >
getreg(r, 1, 1)
< regname Name of the |register| or
empty string for the unnamed
register.
regtype Type of the register, see
|getregtype()|.
Not triggered when |quote_| is used nor when
called recursively.
It is not allowed to change the buffer text,
see |textlock|.
*User*
User Never executed automatically. To be used for
autocommands that are only executed with

View File

@@ -1554,6 +1554,12 @@ v:errors Errors found by assert functions, such as |assert_true()|.
< If v:errors is set to anything but a list it is made an empty
list by the assert function.
*v:event* *event-variable*
v:event Dictionary containing information about the current
|autocommand|. The dictionary is emptied when the |autocommand|
finishes, please refer to |dict-identity| for how to get an
independent copy of it.
*v:exception* *exception-variable*
v:exception The value of the exception most recently caught and not
finished. See also |v:throwpoint| and |throw-variables|.
@@ -4687,7 +4693,7 @@ getqflist([{what}]) *getqflist()*
winid get the quickfix |window-ID|
all all of the above quickfix properties
Non-string items in {what} are ignored. To get the value of a
particular item, set it to one.
particular item, set it to zero.
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.
@@ -4697,17 +4703,21 @@ getqflist([{what}]) *getqflist()*
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.
The returned dictionary contains the following entries:
context context information stored with |setqflist()|
id quickfix list ID |quickfix-ID|
idx index of the current entry in the list
items quickfix list entries
nr quickfix list number
size number of entries in the quickfix list
title quickfix list title text
context context information stored with |setqflist()|.
If not present, set to "".
id quickfix list ID |quickfix-ID|. If not
present, set to 0.
idx index of the current entry in the list. If not
present, set to 0.
items quickfix list entries. If not present, set to
an empty list.
nr quickfix list number. If not present, set to 0
size number of entries in the quickfix list. If not
present, set to 0.
title quickfix list title text. If not present, set
to "".
winid quickfix |window-ID|. If not present, set to 0
Examples: >

View File

@@ -20,7 +20,7 @@
if &cp || exists("g:loaded_netrwPlugin")
finish
endif
let g:loaded_netrwPlugin = "v162"
let g:loaded_netrwPlugin = "v156"
let s:keepcpo = &cpo
set cpo&vim
"DechoRemOn
@@ -42,8 +42,8 @@ augroup END
" Network Browsing Reading Writing: {{{2
augroup Network
au!
au BufReadCmd file://* call netrw#FileUrlEdit(expand("<amatch>"))
au BufReadCmd ftp://*,rcp://*,scp://*,http://*,https://*,dav://*,davs://*,rsync://*,sftp://* exe "sil doau BufReadPre ".fnameescape(expand("<amatch>"))|call netrw#Nread(2,expand("<amatch>"))|exe "sil doau BufReadPost ".fnameescape(expand("<amatch>"))
au BufReadCmd file://* call netrw#FileUrlRead(expand("<amatch>"))
au BufReadCmd ftp://*,rcp://*,scp://*,http://*,file://*,https://*,dav://*,davs://*,rsync://*,sftp://* exe "sil doau BufReadPre ".fnameescape(expand("<amatch>"))|call netrw#Nread(2,expand("<amatch>"))|exe "sil doau BufReadPost ".fnameescape(expand("<amatch>"))
au FileReadCmd ftp://*,rcp://*,scp://*,http://*,file://*,https://*,dav://*,davs://*,rsync://*,sftp://* exe "sil doau FileReadPre ".fnameescape(expand("<amatch>"))|call netrw#Nread(1,expand("<amatch>"))|exe "sil doau FileReadPost ".fnameescape(expand("<amatch>"))
au BufWriteCmd ftp://*,rcp://*,scp://*,http://*,file://*,dav://*,davs://*,rsync://*,sftp://* exe "sil doau BufWritePre ".fnameescape(expand("<amatch>"))|exe 'Nwrite '.fnameescape(expand("<amatch>"))|exe "sil doau BufWritePost ".fnameescape(expand("<amatch>"))
au FileWriteCmd ftp://*,rcp://*,scp://*,http://*,file://*,dav://*,davs://*,rsync://*,sftp://* exe "sil doau FileWritePre ".fnameescape(expand("<amatch>"))|exe "'[,']".'Nwrite '.fnameescape(expand("<amatch>"))|exe "sil doau FileWritePost ".fnameescape(expand("<amatch>"))
@@ -59,7 +59,7 @@ com! -count=1 -nargs=* Nread let s:svpos= winsaveview()<bar>call netrw#NetRead(
com! -range=% -nargs=* Nwrite let s:svpos= winsaveview()<bar><line1>,<line2>call netrw#NetWrite(<f-args>)<bar>call winrestview(s:svpos)
com! -nargs=* NetUserPass call NetUserPass(<f-args>)
com! -nargs=* Nsource let s:svpos= winsaveview()<bar>call netrw#NetSource(<f-args>)<bar>call winrestview(s:svpos)
com! -nargs=? Ntree call netrw#SetTreetop(1,<q-args>)
com! -nargs=? Ntree call netrw#SetTreetop(<q-args>)
" Commands: :Explore, :Sexplore, Hexplore, Vexplore, Lexplore {{{2
com! -nargs=* -bar -bang -count=0 -complete=dir Explore call netrw#Explore(<count>,0,0+<bang>0,<q-args>)
@@ -81,7 +81,7 @@ if !exists("g:netrw_nogx")
if !hasmapto('<Plug>NetrwBrowseX')
nmap <unique> gx <Plug>NetrwBrowseX
endif
nno <silent> <Plug>NetrwBrowseX :call netrw#BrowseX(netrw#GX(),netrw#CheckIfRemote(netrw#GX()))<cr>
nno <silent> <Plug>NetrwBrowseX :call netrw#BrowseX(expand((exists("g:netrw_gx")? g:netrw_gx : '<cfile>')),netrw#CheckIfRemote())<cr>
endif
if maparg('gx','v') == ""
if !hasmapto('<Plug>NetrwBrowseXVis')
@@ -129,15 +129,19 @@ fun! s:LocalBrowse(dirname)
elseif isdirectory(a:dirname)
" call Decho("(LocalBrowse) dirname<".a:dirname."> ft=".&ft." (isdirectory, not amiga)")
" call Dredir("LocalBrowse ft last set: ","verbose set ft")
" call Decho("(s:LocalBrowse) COMBAK#23: buf#".bufnr("%")." file<".expand("%")."> line#".line(".")." col#".col("."))
sil! call netrw#LocalBrowseCheck(a:dirname)
" call Decho("(s:LocalBrowse) COMBAK#24: buf#".bufnr("%")." file<".expand("%")."> line#".line(".")." col#".col("."))
if exists("w:netrw_bannercnt") && line('.') < w:netrw_bannercnt
exe w:netrw_bannercnt
" call Decho("(s:LocalBrowse) COMBAK#25: buf#".bufnr("%")." file<".expand("%")."> line#".line(".")." col#".col("."))
endif
else
" not a directory, ignore it
" call Decho("(LocalBrowse) dirname<".a:dirname."> not a directory, ignoring...")
endif
" call Decho("(s:LocalBrowse) COMBAK#26: buf#".bufnr("%")." file<".expand("%")."> line#".line(".")." col#".col("."))
" call Dret("s:LocalBrowse")
endfun

View File

@@ -34,10 +34,11 @@ Contents:
11. Building with Ruby support
12. Building with Tcl support
13. Building with Terminal support
14. Windows 3.1
15. MS-DOS
14. Building with DirectX (DirectWrite) support
15. Windows 3.1
16. MS-DOS
16. Installing after building from sources
17. Installing after building from sources
The currently recommended way (that means it has been verified to work) is
@@ -787,25 +788,59 @@ E.g. When using MSVC:
nmake -f Make_mvc.mak TERMINAL=yes
Or when using MinGW (as one line):
Or when using MinGW:
mingw32-make -f Make_ming.mak TERMINAL=yes
14. Windows 3.1x
14. Building with DirectX (DirectWrite) support
===============================================
Vim with DirectX (DirectWrite) support can be built with either MSVC or MinGW.
This requires dwrite_2.h and some other header files which come with Windows
SDK 8.1 or later (or MinGW-w64), if you want to enable color emoji support.
This also requires MBYTE=yes which is enabled by default.
A) Using MSVC
If you use MSVC 2013 or later, Windows SDK 8.1 or later is used by default.
You just need to specify DIRECTX=yes:
nmake -f Make_mvc.mak DIRECTX=yes
If you use MSVC 2012 or earlier, the required header files are not available
by default. However, you can use the header files from newer SDKs with older
compilers. E.g.:
set "INCLUDE=%INCLUDE%;C:\Program Files (x86)\Windows Kits\8.1\Include\um"
nmake -f Make_mvc.mak DIRECTX=yes
If you don't need color emoji support, only dwrite.h is required. You can use
older compilers (e.g. VC2010) without Windows SDK 8.1. E.g.:
nmake -f Make_mvc.mak DIRECTX=yes COLOR_EMOJI=no
B) Using MinGW-w64
Just set DIRECTX to yes:
mingw32-make -f Make_ming.mak DIRECTX=yes
15. Windows 3.1x
================
The Windows 3.1x support was removed in patch 7.4.1364.
15. MS-DOS
16. MS-DOS
==========
The MS-DOS support was removed in patch 7.4.1399. Only very old Vim versions
work on MS-DOS because of the limited amount of memory available.
16. Installing after building from sources
17. Installing after building from sources
==========================================
[provided by Michael Soyka, updated by Ken Takata]

View File

@@ -588,7 +588,7 @@ endif
ifeq ($(DIRECTX),yes)
# Only allow DirectWrite for a GUI build.
ifeq (yes, $(GUI))
DEFINES += -DFEAT_DIRECTX -DDYNAMIC_DIRECTX
DEFINES += -DFEAT_DIRECTX -DDYNAMIC_DIRECTX -DFEAT_DIRECTX_COLOR_EMOJI
endif
endif

View File

@@ -25,12 +25,15 @@
#
# GUI interface: GUI=yes (default is no)
#
# GUI with DirectWrite(DirectX): DIRECTX=yes
# (default is no, requires GUI=yes)
# GUI with DirectWrite (DirectX): DIRECTX=yes
# (default is no, requires GUI=yes and MBYTE=yes)
#
# Color emoji support: COLOR_EMOJI=yes
# (default is yes if DIRECTX=yes, requires WinSDK 8.1 or later.)
#
# OLE interface: OLE=yes (usually with GUI=yes)
#
# Multibyte support: MBYTE=yes (default is no)
# Multibyte support: MBYTE=yes (default is yes for NORMAL, BIG, HUGE)
#
# IME support: IME=yes (requires GUI=yes)
# DYNAMIC_IME=[yes or no] (to load the imm32.dll dynamically, default
@@ -419,9 +422,12 @@ NBDEBUG_SRC = nbdebug.c
NETBEANS_LIB = WSock32.lib
!endif
# DirectWrite(DirectX)
# DirectWrite (DirectX)
!if "$(DIRECTX)" == "yes"
DIRECTX_DEFS = -DFEAT_DIRECTX -DDYNAMIC_DIRECTX
!if "$(COLOR_EMOJI)" != "no"
DIRECTX_DEFS = $(DIRECTX_DEFS) -DFEAT_DIRECTX_COLOR_EMOJI
!endif
DIRECTX_INCL = gui_dwrite.h
DIRECTX_OBJ = $(OUTDIR)\gui_dwrite.obj
!endif

2
src/auto/configure vendored
View File

@@ -7514,7 +7514,7 @@ $as_echo "defaulting to no" >&6; }
$as_echo "no" >&6; }
fi
fi
if test "$enable_terminal" = "yes"; then
if test "$enable_terminal" = "yes" -a "$enable_channel" = "yes"; then
$as_echo "#define FEAT_TERMINAL 1" >>confdefs.h
TERM_SRC="libvterm/src/encoding.c libvterm/src/keyboard.c libvterm/src/mouse.c libvterm/src/parser.c libvterm/src/pen.c libvterm/src/screen.c libvterm/src/state.c libvterm/src/unicode.c libvterm/src/vterm.c"

View File

@@ -2059,7 +2059,7 @@ else
AC_MSG_RESULT(no)
fi
fi
if test "$enable_terminal" = "yes"; then
if test "$enable_terminal" = "yes" -a "$enable_channel" = "yes"; then
AC_DEFINE(FEAT_TERMINAL)
TERM_SRC="libvterm/src/encoding.c libvterm/src/keyboard.c libvterm/src/mouse.c libvterm/src/parser.c libvterm/src/pen.c libvterm/src/screen.c libvterm/src/state.c libvterm/src/unicode.c libvterm/src/vterm.c"
AC_SUBST(TERM_SRC)

View File

@@ -47,6 +47,16 @@ dict_alloc(void)
return d;
}
dict_T *
dict_alloc_lock(int lock)
{
dict_T *d = dict_alloc();
if (d != NULL)
d->dv_lock = lock;
return d;
}
/*
* Allocate an empty dict for a return value.
* Returns OK or FAIL.
@@ -54,13 +64,12 @@ dict_alloc(void)
int
rettv_dict_alloc(typval_T *rettv)
{
dict_T *d = dict_alloc();
dict_T *d = dict_alloc_lock(0);
if (d == NULL)
return FAIL;
rettv_dict_set(rettv, d);
rettv->v_lock = 0;
return OK;
}
@@ -80,7 +89,7 @@ rettv_dict_set(typval_T *rettv, dict_T *d)
* Free a Dictionary, including all non-container items it contains.
* Ignores the reference count.
*/
static void
void
dict_free_contents(dict_T *d)
{
int todo;
@@ -102,6 +111,8 @@ dict_free_contents(dict_T *d)
--todo;
}
}
/* The hashtab is still locked, it has to be re-initialized anyway */
hash_clear(&d->dv_hashtab);
}
@@ -846,4 +857,23 @@ dict_list(typval_T *argvars, typval_T *rettv, int what)
}
}
/*
* Make each item in the dict readonly (not the value of the item).
*/
void
dict_set_items_ro(dict_T *di)
{
int todo = (int)di->dv_hashtab.ht_used;
hashitem_T *hi;
/* Set readonly */
for (hi = di->dv_hashtab.ht_array; todo > 0 ; ++hi)
{
if (HASHITEM_EMPTY(hi))
continue;
--todo;
HI2DI(hi)->di_flags |= DI_FLAGS_RO | DI_FLAGS_FIX;
}
}
#endif /* defined(FEAT_EVAL) */

View File

@@ -192,6 +192,7 @@ static struct vimvar
{VV_NAME("termu7resp", VAR_STRING), VV_RO},
{VV_NAME("termstyleresp", VAR_STRING), VV_RO},
{VV_NAME("termblinkresp", VAR_STRING), VV_RO},
{VV_NAME("event", VAR_DICT), VV_RO},
};
/* shorthand */
@@ -319,8 +320,9 @@ eval_init(void)
set_vim_var_nr(VV_SEARCHFORWARD, 1L);
set_vim_var_nr(VV_HLSEARCH, 1L);
set_vim_var_dict(VV_COMPLETED_ITEM, dict_alloc());
set_vim_var_dict(VV_COMPLETED_ITEM, dict_alloc_lock(VAR_FIXED));
set_vim_var_list(VV_ERRORS, list_alloc());
set_vim_var_dict(VV_EVENT, dict_alloc_lock(VAR_FIXED));
set_vim_var_nr(VV_FALSE, VVAL_FALSE);
set_vim_var_nr(VV_TRUE, VVAL_TRUE);
@@ -6632,6 +6634,16 @@ get_vim_var_list(int idx)
return vimvars[idx].vv_list;
}
/*
* Get Dict v: variable value. Caller must take care of reference count when
* needed.
*/
dict_T *
get_vim_var_dict(int idx)
{
return vimvars[idx].vv_dict;
}
/*
* Set v:char to character "c".
*/
@@ -6706,25 +6718,13 @@ set_vim_var_list(int idx, list_T *val)
void
set_vim_var_dict(int idx, dict_T *val)
{
int todo;
hashitem_T *hi;
clear_tv(&vimvars[idx].vv_di.di_tv);
vimvars[idx].vv_type = VAR_DICT;
vimvars[idx].vv_dict = val;
if (val != NULL)
{
++val->dv_refcount;
/* Set readonly */
todo = (int)val->dv_hashtab.ht_used;
for (hi = val->dv_hashtab.ht_array; todo > 0 ; ++hi)
{
if (HASHITEM_EMPTY(hi))
continue;
--todo;
HI2DI(hi)->di_flags |= DI_FLAGS_RO | DI_FLAGS_FIX;
}
dict_set_items_ro(val);
}
}

View File

@@ -172,6 +172,22 @@ abandon_cmdline(void)
redraw_cmdline = TRUE;
}
/*
* Guess that the pattern matches everything. Only finds specific cases, such
* as a trailing \|, which can happen while typing a pattern.
*/
static int
empty_pattern(char_u *p)
{
int n = STRLEN(p);
/* remove trailing \v and the like */
while (n >= 2 && p[n - 2] == '\\'
&& vim_strchr((char_u *)"mMvVcCZ", p[n - 1]) != NULL)
n -= 2;
return n == 0 || (n >= 2 && p[n - 2] == '\\' && p[n - 1] == '|');
}
/*
* getcmdline() - accept a command line starting with firstc.
*
@@ -1794,11 +1810,11 @@ getcmdline(
# endif
old_botline = curwin->w_botline;
update_screen(NOT_VALID);
restore_last_search_pattern();
redrawcmdline();
}
else
vim_beep(BO_ERROR);
restore_last_search_pattern();
goto cmdline_not_changed;
}
break;
@@ -2023,6 +2039,11 @@ cmdline_changed:
else
end_pos = curwin->w_cursor; /* shutup gcc 4 */
/* Disable 'hlsearch' highlighting if the pattern matches
* everything. Avoids a flash when typing "foo\|". */
if (empty_pattern(ccline.cmdbuff))
SET_NO_HLSEARCH(TRUE);
validate_cursor();
/* May redraw the status line to show the cursor position. */
if (p_ru && curwin->w_status_height > 0)

View File

@@ -6478,6 +6478,7 @@ buf_modname(
/*
* Like fgets(), but if the file line is too long, it is truncated and the
* rest of the line is thrown away. Returns TRUE for end-of-file.
* If the line is truncated then buf[size - 2] will not be NUL.
*/
int
vim_fgets(char_u *buf, int size, FILE *fp)
@@ -7856,6 +7857,7 @@ static struct event_name
{"WinEnter", EVENT_WINENTER},
{"WinLeave", EVENT_WINLEAVE},
{"VimResized", EVENT_VIMRESIZED},
{"TextYankPost", EVENT_TEXTYANKPOST},
{NULL, (event_T)0}
};
@@ -9399,6 +9401,15 @@ has_funcundefined(void)
return (first_autopat[(int)EVENT_FUNCUNDEFINED] != NULL);
}
/*
* Return TRUE when there is a TextYankPost autocommand defined.
*/
int
has_textyankpost(void)
{
return (first_autopat[(int)EVENT_TEXTYANKPOST] != NULL);
}
/*
* Execute autocommands for "event" and file name "fname".
* Return TRUE if some commands were executed.

View File

@@ -38,7 +38,11 @@
# define _Outptr_
#endif
#include <dwrite_2.h>
#ifdef FEAT_DIRECTX_COLOR_EMOJI
# include <dwrite_2.h>
#else
# include <dwrite.h>
#endif
#include "gui_dwrite.h"
@@ -284,7 +288,9 @@ struct DWriteContext {
ID2D1SolidColorBrush *mBrush;
IDWriteFactory *mDWriteFactory;
#ifdef FEAT_DIRECTX_COLOR_EMOJI
IDWriteFactory2 *mDWriteFactory2;
#endif
IDWriteGdiInterop *mGdiInterop;
IDWriteRenderingParams *mRenderingParams;
@@ -481,6 +487,7 @@ public:
AdjustedGlyphRun adjustedGlyphRun(glyphRun, context->cellWidth,
context->offsetX);
#ifdef FEAT_DIRECTX_COLOR_EMOJI
if (pDWC_->mDWriteFactory2 != NULL)
{
IDWriteColorGlyphRunEnumerator *enumerator = NULL;
@@ -517,6 +524,7 @@ public:
return S_OK;
}
}
#endif
// Draw by IDWriteFactory (without color emoji)
pDWC_->mRT->DrawGlyphRun(
@@ -589,7 +597,9 @@ DWriteContext::DWriteContext() :
mGDIRT(NULL),
mBrush(NULL),
mDWriteFactory(NULL),
#ifdef FEAT_DIRECTX_COLOR_EMOJI
mDWriteFactory2(NULL),
#endif
mGdiInterop(NULL),
mRenderingParams(NULL),
mFontCache(8),
@@ -618,6 +628,7 @@ DWriteContext::DWriteContext() :
mDWriteFactory);
}
#ifdef FEAT_DIRECTX_COLOR_EMOJI
if (SUCCEEDED(hr))
{
DWriteCreateFactory(
@@ -626,6 +637,7 @@ DWriteContext::DWriteContext() :
reinterpret_cast<IUnknown**>(&mDWriteFactory2));
_RPT1(_CRT_WARN, "IDWriteFactory2: %s\n", SUCCEEDED(hr) ? "available" : "not available");
}
#endif
if (SUCCEEDED(hr))
{
@@ -647,7 +659,9 @@ DWriteContext::~DWriteContext()
SafeRelease(&mRenderingParams);
SafeRelease(&mGdiInterop);
SafeRelease(&mDWriteFactory);
#ifdef FEAT_DIRECTX_COLOR_EMOJI
SafeRelease(&mDWriteFactory2);
#endif
SafeRelease(&mBrush);
SafeRelease(&mGDIRT);
SafeRelease(&mRT);
@@ -995,7 +1009,7 @@ DWriteContext::DrawText(const WCHAR *text, int len,
TextRenderer renderer(this);
TextRendererContext context = { color, FLOAT(cellWidth), 0.0f };
textLayout->Draw(&context, &renderer, FLOAT(x), FLOAT(y));
textLayout->Draw(&context, &renderer, FLOAT(x), FLOAT(y) - 0.5f);
}
SafeRelease(&textLayout);

View File

@@ -30,11 +30,14 @@
#endif
#if defined(FEAT_DIRECTX)
# ifndef FEAT_MBYTE
# error FEAT_MBYTE is required for FEAT_DIRECTX.
# endif
static DWriteContext *s_dwc = NULL;
static int s_directx_enabled = 0;
static int s_directx_load_attempted = 0;
static int s_directx_scrlines = 0;
# define IS_ENABLE_DIRECTX() (s_directx_enabled && s_dwc != NULL)
# define IS_ENABLE_DIRECTX() (s_directx_enabled && s_dwc != NULL && enc_utf8)
static int directx_enabled(void);
static void directx_binddc(void);
#endif
@@ -47,7 +50,7 @@ static int gui_mswin_get_menu_height(int fix_window);
int
gui_mch_set_rendering_options(char_u *s)
{
#ifdef FEAT_DIRECTX
# ifdef FEAT_DIRECTX
char_u *p, *q;
int dx_enable = 0;
@@ -159,9 +162,9 @@ gui_mch_set_rendering_options(char_u *s)
s_directx_scrlines = dx_scrlines;
return OK;
#else
# else
return FAIL;
#endif
# endif
}
#endif
@@ -3140,7 +3143,8 @@ gui_mch_delete_lines(
{
if (s_directx_scrlines > 0 && s_directx_scrlines <= num_lines)
{
RedrawWindow(s_textArea, &rc, NULL, RDW_INVALIDATE);
gui_redraw(rc.left, rc.top,
rc.right - rc.left + 1, rc.bottom - rc.top + 1);
use_redraw = 1;
}
else
@@ -3152,9 +3156,9 @@ gui_mch_delete_lines(
intel_gpu_workaround();
ScrollWindowEx(s_textArea, 0, -num_lines * gui.char_height,
&rc, &rc, NULL, NULL, get_scroll_flags());
UpdateWindow(s_textArea);
}
UpdateWindow(s_textArea);
/* This seems to be required to avoid the cursor disappearing when
* scrolling such that the cursor ends up in the top-left character on
* the screen... But why? (Webb) */
@@ -3190,7 +3194,8 @@ gui_mch_insert_lines(
{
if (s_directx_scrlines > 0 && s_directx_scrlines <= num_lines)
{
RedrawWindow(s_textArea, &rc, NULL, RDW_INVALIDATE);
gui_redraw(rc.left, rc.top,
rc.right - rc.left + 1, rc.bottom - rc.top + 1);
use_redraw = 1;
}
else
@@ -3204,10 +3209,9 @@ gui_mch_insert_lines(
* off-screen. How do we avoid it when it's not needed? */
ScrollWindowEx(s_textArea, 0, num_lines * gui.char_height,
&rc, &rc, NULL, NULL, get_scroll_flags());
UpdateWindow(s_textArea);
}
UpdateWindow(s_textArea);
gui_clear_block(row, gui.scroll_region_left,
row + num_lines - 1, gui.scroll_region_right);
}
@@ -6401,13 +6405,13 @@ gui_mch_draw_string(
if (text[n] >= 0x80)
break;
#if defined(FEAT_DIRECTX)
# if defined(FEAT_DIRECTX)
/* Quick hack to enable DirectWrite. To use DirectWrite (antialias), it is
* required that unicode drawing routine, currently. So this forces it
* enabled. */
if (enc_utf8 && IS_ENABLE_DIRECTX())
if (IS_ENABLE_DIRECTX())
n = 0; /* Keep n < len, to enter block for unicode. */
#endif
# endif
/* Check if the Unicode buffer exists and is big enough. Create it
* with the same length as the multi-byte string, the number of wide
@@ -6480,7 +6484,7 @@ gui_mch_draw_string(
i += utf_ptr2len_len(text + i, len - i);
++clen;
}
#if defined(FEAT_DIRECTX)
# if defined(FEAT_DIRECTX)
if (IS_ENABLE_DIRECTX())
{
/* Add one to "cells" for italics. */
@@ -6490,7 +6494,7 @@ gui_mch_draw_string(
foptions, pcliprect, unicodepdy);
}
else
#endif
# endif
ExtTextOutW(s_hdc, TEXT_X(col), TEXT_Y(row),
foptions, pcliprect, unicodebuf, wlen, unicodepdy);
len = cells; /* used for underlining */

View File

@@ -92,7 +92,7 @@ write_string(garray_T *gap, char_u *str)
char_u numbuf[NUMBUFLEN];
if (res == NULL)
ga_concat(gap, (char_u *)"null");
ga_concat(gap, (char_u *)"\"\"");
else
{
#if defined(FEAT_MBYTE) && defined(USE_ICONV)
@@ -237,7 +237,7 @@ json_encode_item(garray_T *gap, typval_T *val, int copyID, int options)
case VAR_LIST:
l = val->vval.v_list;
if (l == NULL)
ga_concat(gap, (char_u *)"null");
ga_concat(gap, (char_u *)"[]");
else
{
if (l->lv_copyID == copyID)
@@ -272,7 +272,7 @@ json_encode_item(garray_T *gap, typval_T *val, int copyID, int options)
case VAR_DICT:
d = val->vval.v_dict;
if (d == NULL)
ga_concat(gap, (char_u *)"null");
ga_concat(gap, (char_u *)"{}");
else
{
if (d->dv_copyID == copyID)

View File

@@ -1645,6 +1645,63 @@ shift_delete_registers()
y_regs[1].y_array = NULL; /* set register one to empty */
}
static void
yank_do_autocmd(oparg_T *oap, yankreg_T *reg)
{
static int recursive = FALSE;
dict_T *v_event;
list_T *list;
int n;
char_u buf[NUMBUFLEN + 2];
long reglen = 0;
if (recursive)
return;
v_event = get_vim_var_dict(VV_EVENT);
list = list_alloc();
for (n = 0; n < reg->y_size; n++)
list_append_string(list, reg->y_array[n], -1);
list->lv_lock = VAR_FIXED;
dict_add_list(v_event, "regcontents", list);
buf[0] = (char_u)oap->regname;
buf[1] = NUL;
dict_add_nr_str(v_event, "regname", 0, buf);
buf[0] = get_op_char(oap->op_type);
buf[1] = get_extra_op_char(oap->op_type);
buf[2] = NUL;
dict_add_nr_str(v_event, "operator", 0, buf);
buf[0] = NUL;
buf[1] = NUL;
switch (get_reg_type(oap->regname, &reglen))
{
case MLINE: buf[0] = 'V'; break;
case MCHAR: buf[0] = 'v'; break;
case MBLOCK:
vim_snprintf((char *)buf, sizeof(buf), "%c%ld", Ctrl_V,
reglen + 1);
break;
}
dict_add_nr_str(v_event, "regtype", 0, buf);
/* Lock the dictionary and its keys */
dict_set_items_ro(v_event);
recursive = TRUE;
textlock++;
apply_autocmds(EVENT_TEXTYANKPOST, NULL, NULL, FALSE, curbuf);
textlock--;
recursive = FALSE;
/* Empty the dictionary, v:event is still valid */
dict_free_contents(v_event);
hash_init(&v_event->dv_hashtab);
}
/*
* Handle a delete operation.
*
@@ -1798,6 +1855,11 @@ op_delete(oparg_T *oap)
return FAIL;
}
}
#ifdef FEAT_AUTOCMD
if (did_yank && has_textyankpost())
yank_do_autocmd(oap, y_current);
#endif
}
/*
@@ -3270,6 +3332,11 @@ op_yank(oparg_T *oap, int deleting, int mess)
# endif
#endif
#ifdef FEAT_AUTOCMD
if (!deleting && has_textyankpost())
yank_do_autocmd(oap, y_current);
#endif
return OK;
fail: /* free the allocated lines */

View File

@@ -1,7 +1,9 @@
/* dict.c */
dict_T *dict_alloc(void);
dict_T *dict_alloc_lock(int lock);
int rettv_dict_alloc(typval_T *rettv);
void rettv_dict_set(typval_T *rettv, dict_T *d);
void dict_free_contents(dict_T *d);
void dict_unref(dict_T *d);
int dict_free_nonref(int copyID);
void dict_free_items(int copyID);
@@ -23,4 +25,5 @@ void dict_extend(dict_T *d1, dict_T *d2, char_u *action);
dictitem_T *dict_lookup(hashitem_T *hi);
int dict_equal(dict_T *d1, dict_T *d2, int ic, int recursive);
void dict_list(typval_T *argvars, typval_T *rettv, int what);
void dict_set_items_ro(dict_T *di);
/* vim: set ft=c : */

View File

@@ -64,6 +64,7 @@ void set_vim_var_nr(int idx, varnumber_T val);
varnumber_T get_vim_var_nr(int idx);
char_u *get_vim_var_str(int idx);
list_T *get_vim_var_list(int idx);
dict_T * get_vim_var_dict(int idx);
void set_vim_var_char(int c);
void set_vcount(long count, long count1, int set_prevcount);
void set_vim_var_string(int idx, char_u *val, int len);

View File

@@ -51,6 +51,7 @@ int has_textchangedI(void);
int has_insertcharpre(void);
int has_cmdundefined(void);
int has_funcundefined(void);
int has_textyankpost(void);
void block_autocmds(void);
void unblock_autocmds(void);
int is_autocmd_blocked(void);

View File

@@ -4863,70 +4863,24 @@ qf_get_properties(win_T *wp, dict_T *what, dict_T *retdict)
if (wp != NULL)
qi = GET_LOC_LIST(wp);
/* List is not present or is empty */
if (qi == NULL || qi->qf_listcount == 0)
{
/* If querying for the size of the list, return 0 */
if (((di = dict_find(what, (char_u *)"nr", -1)) != NULL)
&& (di->di_tv.v_type == VAR_STRING)
&& (STRCMP(di->di_tv.vval.v_string, "$") == 0))
return dict_add_nr_str(retdict, "nr", 0, NULL);
return FAIL;
}
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)
return FAIL;
}
}
else if ((di->di_tv.v_type == VAR_STRING)
&& (STRCMP(di->di_tv.vval.v_string, "$") == 0))
/* Get the last quickfix list number */
qf_idx = qi->qf_listcount - 1;
else
return FAIL;
flags |= QF_GETLIST_NR;
}
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 specifed by 'nr' */
if (di->di_tv.vval.v_number != 0)
{
qf_idx = qf_id2nr(qi, di->di_tv.vval.v_number);
if (qf_idx == -1)
return FAIL; /* List not found */
}
flags |= QF_GETLIST_ID;
}
else
return FAIL;
}
if (dict_find(what, (char_u *)"all", -1) != NULL)
flags |= QF_GETLIST_ALL;
if (dict_find(what, (char_u *)"title", -1) != NULL)
flags |= QF_GETLIST_TITLE;
if (dict_find(what, (char_u *)"nr", -1) != NULL)
flags |= QF_GETLIST_NR;
if (dict_find(what, (char_u *)"winid", -1) != NULL)
flags |= QF_GETLIST_WINID;
if (dict_find(what, (char_u *)"context", -1) != NULL)
flags |= QF_GETLIST_CONTEXT;
if (dict_find(what, (char_u *)"id", -1) != NULL)
flags |= QF_GETLIST_ID;
if (dict_find(what, (char_u *)"items", -1) != NULL)
flags |= QF_GETLIST_ITEMS;
@@ -4936,6 +4890,77 @@ qf_get_properties(win_T *wp, dict_T *what, dict_T *retdict)
if (dict_find(what, (char_u *)"size", -1) != NULL)
flags |= QF_GETLIST_SIZE;
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)
&& (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;
}
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 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;
}
else
qf_idx = -1;
}
}
/* 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", 0L, 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);
return status;
}
if (flags & QF_GETLIST_TITLE)
{
char_u *t;

View File

@@ -1124,3 +1124,42 @@ func Test_Filter_noshelltemp()
let &shelltemp = shelltemp
bwipe!
endfunc
func Test_TextYankPost()
enew!
call setline(1, ['foo'])
let g:event = []
au TextYankPost * let g:event = copy(v:event)
call assert_equal({}, v:event)
call assert_fails('let v:event = {}', 'E46:')
call assert_fails('let v:event.mykey = 0', 'E742:')
norm "ayiw
call assert_equal(
\{'regcontents': ['foo'], 'regname': 'a', 'operator': 'y', 'regtype': 'v'},
\g:event)
norm y_
call assert_equal(
\{'regcontents': ['foo'], 'regname': '', 'operator': 'y', 'regtype': 'V'},
\g:event)
call feedkeys("\<C-V>y", 'x')
call assert_equal(
\{'regcontents': ['f'], 'regname': '', 'operator': 'y', 'regtype': "\x161"},
\g:event)
norm "xciwbar
call assert_equal(
\{'regcontents': ['foo'], 'regname': 'x', 'operator': 'c', 'regtype': 'v'},
\g:event)
norm "bdiw
call assert_equal(
\{'regcontents': ['bar'], 'regname': 'b', 'operator': 'd', 'regtype': 'v'},
\g:event)
call assert_equal({}, v:event)
au! TextYankPost
unlet g:event
bwipe!
endfunc

View File

@@ -103,6 +103,10 @@ func Test_json_encode()
call assert_fails('echo json_encode(function("tr"))', 'E474:')
call assert_fails('echo json_encode([function("tr")])', 'E474:')
call assert_equal('{"a":""}', json_encode({'a': test_null_string()}))
call assert_equal('{"a":[]}', json_encode({"a": test_null_list()}))
call assert_equal('{"a":{}}', json_encode({"a": test_null_dict()}))
silent! let res = json_encode(function("tr"))
call assert_equal("", res)
endfunc

View File

@@ -1833,8 +1833,8 @@ func Xproperty_tests(cchar)
call assert_equal(-1, s)
call assert_equal({}, g:Xgetlist({'abc':1}))
call assert_equal({}, g:Xgetlist({'nr':99, 'title':1}))
call assert_equal({}, g:Xgetlist({'nr':[], 'title':1}))
call assert_equal('', g:Xgetlist({'nr':99, 'title':1}).title)
call assert_equal('', g:Xgetlist({'nr':[], 'title':1}).title)
if a:cchar == 'l'
call assert_equal({}, getloclist(99, {'title': 1}))
@@ -1870,7 +1870,7 @@ func Xproperty_tests(cchar)
call assert_equal([1, 2], getloclist(w2_id, {'context':1}).context)
only
call setloclist(0, [], 'f')
call assert_equal({}, getloclist(0, {'context':1}))
call assert_equal('', getloclist(0, {'context':1}).context)
endif
" Test for changing the context of previous quickfix lists
@@ -2383,8 +2383,8 @@ func XsizeTests(cchar)
call g:Xsetlist([], 'f')
call assert_equal(0, g:Xgetlist({'nr':'$'}).nr)
call assert_equal(1, len(g:Xgetlist({'nr':'$', 'all':1})))
call assert_equal(0, len(g:Xgetlist({'nr':0})))
call assert_equal('', g:Xgetlist({'nr':'$', 'all':1}).title)
call assert_equal(0, g:Xgetlist({'nr':0}).nr)
Xexpr "File1:10:Line1"
Xexpr "File2:20:Line2"
@@ -2754,7 +2754,7 @@ func Xqfid_tests(cchar)
call s:setup_commands(a:cchar)
call g:Xsetlist([], 'f')
call assert_equal({}, g:Xgetlist({'id':0}))
call assert_equal(0, g:Xgetlist({'id':0}).id)
Xexpr ''
let start_id = g:Xgetlist({'id' : 0}).id
Xexpr '' | Xexpr ''
@@ -2762,10 +2762,10 @@ func Xqfid_tests(cchar)
call assert_equal(start_id, g:Xgetlist({'id':0, 'nr':1}).id)
call assert_equal(start_id + 1, g:Xgetlist({'id':0, 'nr':0}).id)
call assert_equal(start_id + 2, g:Xgetlist({'id':0, 'nr':'$'}).id)
call assert_equal({}, g:Xgetlist({'id':0, 'nr':99}))
call assert_equal(0, g:Xgetlist({'id':0, 'nr':99}).id)
call assert_equal(2, g:Xgetlist({'id':start_id + 1, 'nr':0}).nr)
call assert_equal({}, g:Xgetlist({'id':99, 'nr':0}))
call assert_equal({}, g:Xgetlist({'id':"abc", 'nr':0}))
call assert_equal(0, g:Xgetlist({'id':99, 'nr':0}).id)
call assert_equal(0, g:Xgetlist({'id':"abc", 'nr':0}).id)
call g:Xsetlist([], 'a', {'id':start_id, 'context':[1,2]})
call assert_equal([1,2], g:Xgetlist({'nr':1, 'context':1}).context)
@@ -2776,7 +2776,7 @@ func Xqfid_tests(cchar)
let qfid = g:Xgetlist({'id':0, 'nr':0})
call g:Xsetlist([], 'f')
call assert_equal({}, g:Xgetlist({'id':qfid, 'nr':0}))
call assert_equal(0, g:Xgetlist({'id':qfid, 'nr':0}).id)
endfunc
func Test_qf_id()
@@ -2880,3 +2880,62 @@ func Test_qfjump()
call Xqfjump_tests('c')
call Xqfjump_tests('l')
endfunc
" Tests for the getqflist() and getloclist() functions when the list is not
" present or is empty
func Xgetlist_empty_tests(cchar)
call s:setup_commands(a:cchar)
" Empty quickfix stack
call g:Xsetlist([], 'f')
call assert_equal('', g:Xgetlist({'context' : 0}).context)
call assert_equal(0, g:Xgetlist({'id' : 0}).id)
call assert_equal(0, g:Xgetlist({'idx' : 0}).idx)
call assert_equal([], g:Xgetlist({'items' : 0}).items)
call assert_equal(0, g:Xgetlist({'nr' : 0}).nr)
call assert_equal(0, g:Xgetlist({'size' : 0}).size)
call assert_equal('', g:Xgetlist({'title' : 0}).title)
call assert_equal(0, g:Xgetlist({'winid' : 0}).winid)
call assert_equal({'context' : '', 'id' : 0, 'idx' : 0, 'items' : [], 'nr' : 0, 'size' : 0, 'title' : '', 'winid' : 0}, g:Xgetlist({'all' : 0}))
" Empty quickfix list
Xexpr ""
call assert_equal('', g:Xgetlist({'context' : 0}).context)
call assert_notequal(0, g:Xgetlist({'id' : 0}).id)
call assert_equal(0, g:Xgetlist({'idx' : 0}).idx)
call assert_equal([], g:Xgetlist({'items' : 0}).items)
call assert_notequal(0, g:Xgetlist({'nr' : 0}).nr)
call assert_equal(0, g:Xgetlist({'size' : 0}).size)
call assert_notequal('', g:Xgetlist({'title' : 0}).title)
call assert_equal(0, g:Xgetlist({'winid' : 0}).winid)
let qfid = g:Xgetlist({'id' : 0}).id
call g:Xsetlist([], 'f')
" Non-existing quickfix identifier
call assert_equal('', g:Xgetlist({'id' : qfid, 'context' : 0}).context)
call assert_equal(0, g:Xgetlist({'id' : qfid}).id)
call assert_equal(0, g:Xgetlist({'id' : qfid, 'idx' : 0}).idx)
call assert_equal([], g:Xgetlist({'id' : qfid, 'items' : 0}).items)
call assert_equal(0, g:Xgetlist({'id' : qfid, 'nr' : 0}).nr)
call assert_equal(0, g:Xgetlist({'id' : qfid, 'size' : 0}).size)
call assert_equal('', g:Xgetlist({'id' : qfid, 'title' : 0}).title)
call assert_equal(0, g:Xgetlist({'id' : qfid, 'winid' : 0}).winid)
call assert_equal({'context' : '', 'id' : 0, 'idx' : 0, 'items' : [], 'nr' : 0, 'size' : 0, 'title' : '', 'winid' : 0}, g:Xgetlist({'id' : qfid, 'all' : 0}))
" Non-existing quickfix list number
call assert_equal('', g:Xgetlist({'nr' : 5, 'context' : 0}).context)
call assert_equal(0, g:Xgetlist({'nr' : 5}).nr)
call assert_equal(0, g:Xgetlist({'nr' : 5, 'idx' : 0}).idx)
call assert_equal([], g:Xgetlist({'nr' : 5, 'items' : 0}).items)
call assert_equal(0, g:Xgetlist({'nr' : 5, 'id' : 0}).id)
call assert_equal(0, g:Xgetlist({'nr' : 5, 'size' : 0}).size)
call assert_equal('', g:Xgetlist({'nr' : 5, 'title' : 0}).title)
call assert_equal(0, g:Xgetlist({'nr' : 5, 'winid' : 0}).winid)
call assert_equal({'context' : '', 'id' : 0, 'idx' : 0, 'items' : [], 'nr' : 0, 'size' : 0, 'title' : '', 'winid' : 0}, g:Xgetlist({'nr' : 5, 'all' : 0}))
endfunc
func Test_getqflist()
call Xgetlist_empty_tests('c')
call Xgetlist_empty_tests('l')
endfunc

View File

@@ -771,6 +771,22 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
1396,
/**/
1395,
/**/
1394,
/**/
1393,
/**/
1392,
/**/
1391,
/**/
1390,
/**/
1389,
/**/
1388,
/**/

View File

@@ -1339,6 +1339,7 @@ enum auto_event
EVENT_TEXTCHANGEDI, /* text was modified in Insert mode*/
EVENT_CMDUNDEFINED, /* command undefined */
EVENT_OPTIONSET, /* option was set */
EVENT_TEXTYANKPOST, /* after some text was yanked */
NUM_EVENTS /* MUST be the last one */
};
@@ -1988,7 +1989,8 @@ typedef int sock_T;
#define VV_TERMU7RESP 83
#define VV_TERMSTYLERESP 84
#define VV_TERMBLINKRESP 85
#define VV_LEN 86 /* number of v: vars */
#define VV_EVENT 86
#define VV_LEN 87 /* number of v: vars */
/* used for v_number in VAR_SPECIAL */
#define VVAL_FALSE 0L