mirror of
https://github.com/neovim/neovim.git
synced 2025-09-28 22:18:33 +00:00
Merge branch 'master' into hide-container-impl
This commit is contained in:
@@ -9,6 +9,8 @@ matrix:
|
|||||||
allow_failures:
|
allow_failures:
|
||||||
- configuration: MINGW_64-gcov
|
- configuration: MINGW_64-gcov
|
||||||
install: []
|
install: []
|
||||||
|
before_build:
|
||||||
|
- ps: Install-Product node 8
|
||||||
build_script:
|
build_script:
|
||||||
- call ci\build.bat
|
- call ci\build.bat
|
||||||
cache:
|
cache:
|
||||||
|
@@ -37,3 +37,15 @@ else
|
|||||||
# https://github.com/travis-ci/travis-ci/issues/8363
|
# https://github.com/travis-ci/travis-ci/issues/8363
|
||||||
pip3 -q install --user --upgrade pip || true
|
pip3 -q install --user --upgrade pip || true
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
if [[ "${TRAVIS_OS_NAME}" == linux ]]; then
|
||||||
|
echo "Install node (LTS)"
|
||||||
|
|
||||||
|
if [ ! -f ~/.nvm/nvm.sh ]; then
|
||||||
|
curl -o ~/.nvm/nvm.sh https://raw.githubusercontent.com/creationix/nvm/master/nvm.sh
|
||||||
|
fi
|
||||||
|
|
||||||
|
source ~/.nvm/nvm.sh
|
||||||
|
nvm install --lts
|
||||||
|
nvm use --lts
|
||||||
|
fi
|
||||||
|
@@ -37,6 +37,9 @@ set PATH=C:\Ruby24\bin;%PATH%
|
|||||||
cmd /c gem.cmd install neovim || goto :error
|
cmd /c gem.cmd install neovim || goto :error
|
||||||
where.exe neovim-ruby-host.bat || goto :error
|
where.exe neovim-ruby-host.bat || goto :error
|
||||||
|
|
||||||
|
cmd /c npm.cmd install -g neovim || goto :error
|
||||||
|
where.exe neovim-node-host.cmd || goto :error
|
||||||
|
|
||||||
mkdir .deps
|
mkdir .deps
|
||||||
cd .deps
|
cd .deps
|
||||||
cmake -G "MinGW Makefiles" -DCMAKE_BUILD_TYPE=RelWithDebInfo ..\third-party\ || goto :error
|
cmake -G "MinGW Makefiles" -DCMAKE_BUILD_TYPE=RelWithDebInfo ..\third-party\ || goto :error
|
||||||
|
@@ -23,3 +23,8 @@ CC=cc pip3 -q install --user --upgrade neovim || true
|
|||||||
|
|
||||||
echo "Install neovim RubyGem."
|
echo "Install neovim RubyGem."
|
||||||
gem install --no-document --version ">= 0.2.0" neovim
|
gem install --no-document --version ">= 0.2.0" neovim
|
||||||
|
|
||||||
|
if [[ "${TRAVIS_OS_NAME}" == linux ]]; then
|
||||||
|
echo "Install neovim npm package"
|
||||||
|
npm install -g neovim
|
||||||
|
fi
|
||||||
|
@@ -253,14 +253,18 @@ function! s:check_python(version) abort
|
|||||||
|
|
||||||
if !empty(pyenv)
|
if !empty(pyenv)
|
||||||
if empty(pyenv_root)
|
if empty(pyenv_root)
|
||||||
call health#report_warn(
|
call health#report_info(
|
||||||
\ 'pyenv was found, but $PYENV_ROOT is not set.',
|
\ 'pyenv was found, but $PYENV_ROOT is not set. `pyenv root` will be used.'
|
||||||
\ ['Did you follow the final install instructions?',
|
\ .' If you run into problems, try setting $PYENV_ROOT explicitly.'
|
||||||
\ 'If you use a shell "framework" like Prezto or Oh My Zsh, try without.',
|
|
||||||
\ 'Try a different shell (bash).']
|
|
||||||
\ )
|
\ )
|
||||||
|
let pyenv_root = s:trim(s:system([pyenv, 'root']))
|
||||||
|
endif
|
||||||
|
|
||||||
|
if !isdirectory(pyenv_root)
|
||||||
|
call health#report_error('Invalid pyenv root: '.pyenv_root)
|
||||||
else
|
else
|
||||||
call health#report_ok(printf('pyenv found: "%s"', pyenv))
|
call health#report_info(printf('pyenv: %s', pyenv))
|
||||||
|
call health#report_info(printf('pyenv root: %s', pyenv_root))
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
|
|
||||||
@@ -451,10 +455,11 @@ function! s:check_ruby() abort
|
|||||||
|
|
||||||
let host = provider#ruby#Detect()
|
let host = provider#ruby#Detect()
|
||||||
if empty(host)
|
if empty(host)
|
||||||
call health#report_warn('Missing "neovim" gem.',
|
call health#report_warn("`neovim-ruby-host` not found.",
|
||||||
\ ['Run in shell: gem install neovim',
|
\ ['Run `gem install neovim` to ensure the neovim RubyGem is installed.',
|
||||||
\ 'Is the gem bin directory in $PATH? Check `gem environment`.',
|
\ 'Run `gem environment` to ensure the gem bin directory is in $PATH.',
|
||||||
\ 'If you are using rvm/rbenv/chruby, try "rehashing".'])
|
\ 'If you are using rvm/rbenv/chruby, try "rehashing".',
|
||||||
|
\ 'See :help g:ruby_host_prog for non-standard gem installations.'])
|
||||||
return
|
return
|
||||||
endif
|
endif
|
||||||
call health#report_info('Host: '. host)
|
call health#report_info('Host: '. host)
|
||||||
@@ -488,7 +493,7 @@ function! s:check_ruby() abort
|
|||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
function! s:check_node() abort
|
function! s:check_node() abort
|
||||||
call health#report_start('Node provider (optional)')
|
call health#report_start('Node.js provider (optional)')
|
||||||
|
|
||||||
let loaded_var = 'g:loaded_node_provider'
|
let loaded_var = 'g:loaded_node_provider'
|
||||||
if exists(loaded_var) && !exists('*provider#node#Call')
|
if exists(loaded_var) && !exists('*provider#node#Call')
|
||||||
@@ -502,7 +507,16 @@ function! s:check_node() abort
|
|||||||
\ ['Install Node.js and verify that `node` and `npm` commands work.'])
|
\ ['Install Node.js and verify that `node` and `npm` commands work.'])
|
||||||
return
|
return
|
||||||
endif
|
endif
|
||||||
call health#report_info('Node: '. s:system('node -v'))
|
let node_v = get(split(s:system('node -v'), "\n"), 0, '')
|
||||||
|
call health#report_info('Node.js: '. node_v)
|
||||||
|
if !s:shell_error && s:version_cmp(node_v[1:], '6.0.0') < 0
|
||||||
|
call health#report_warn('Neovim node.js host does not support '.node_v)
|
||||||
|
" Skip further checks, they are nonsense if nodejs is too old.
|
||||||
|
return
|
||||||
|
endif
|
||||||
|
if !provider#node#can_inspect()
|
||||||
|
call health#report_warn('node.js on this system does not support --inspect-brk so $NVIM_NODE_HOST_DEBUG is ignored.')
|
||||||
|
endif
|
||||||
|
|
||||||
let host = provider#node#Detect()
|
let host = provider#node#Detect()
|
||||||
if empty(host)
|
if empty(host)
|
||||||
@@ -511,7 +525,7 @@ function! s:check_node() abort
|
|||||||
\ 'Is the npm bin directory in $PATH?'])
|
\ 'Is the npm bin directory in $PATH?'])
|
||||||
return
|
return
|
||||||
endif
|
endif
|
||||||
call health#report_info('Host: '. host)
|
call health#report_info('Neovim node.js host: '. host)
|
||||||
|
|
||||||
let latest_npm_cmd = has('win32') ? 'cmd /c npm info neovim --json' : 'npm info neovim --json'
|
let latest_npm_cmd = has('win32') ? 'cmd /c npm info neovim --json' : 'npm info neovim --json'
|
||||||
let latest_npm = s:system(split(latest_npm_cmd))
|
let latest_npm = s:system(split(latest_npm_cmd))
|
||||||
@@ -530,11 +544,11 @@ function! s:check_node() abort
|
|||||||
let latest_npm = get(get(pkg_data, 'dist-tags', {}), 'latest', 'unable to parse')
|
let latest_npm = get(get(pkg_data, 'dist-tags', {}), 'latest', 'unable to parse')
|
||||||
endif
|
endif
|
||||||
|
|
||||||
let current_npm_cmd = host .' --version'
|
let current_npm_cmd = ['node', host, '--version']
|
||||||
let current_npm = s:system(current_npm_cmd)
|
let current_npm = s:system(current_npm_cmd)
|
||||||
if s:shell_error
|
if s:shell_error
|
||||||
call health#report_error('Failed to run: '. current_npm_cmd,
|
call health#report_error('Failed to run: '. string(current_npm_cmd),
|
||||||
\ ['Report this issue with the output of: ', current_npm_cmd])
|
\ ['Report this issue with the output of: ', string(current_npm_cmd)])
|
||||||
return
|
return
|
||||||
endif
|
endif
|
||||||
|
|
||||||
@@ -544,7 +558,7 @@ function! s:check_node() abort
|
|||||||
\ current_npm, latest_npm),
|
\ current_npm, latest_npm),
|
||||||
\ ['Run in shell: npm update neovim'])
|
\ ['Run in shell: npm update neovim'])
|
||||||
else
|
else
|
||||||
call health#report_ok('Latest "neovim" npm is installed: '. current_npm)
|
call health#report_ok('Latest "neovim" npm package is installed: '. current_npm)
|
||||||
endif
|
endif
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
|
@@ -5,11 +5,56 @@ let g:loaded_node_provider = 1
|
|||||||
|
|
||||||
let s:job_opts = {'rpc': v:true, 'on_stderr': function('provider#stderr_collector')}
|
let s:job_opts = {'rpc': v:true, 'on_stderr': function('provider#stderr_collector')}
|
||||||
|
|
||||||
function! provider#node#Detect() abort
|
function! s:is_minimum_version(version, min_major, min_minor) abort
|
||||||
return has('win32') ? exepath('neovim-node-host.cmd') : exepath('neovim-node-host')
|
if empty(a:version)
|
||||||
|
let nodejs_version = get(split(system(['node', '-v']), "\n"), 0, '')
|
||||||
|
if v:shell_error || nodejs_version[0] !=# 'v'
|
||||||
|
return 0
|
||||||
|
endif
|
||||||
|
else
|
||||||
|
let nodejs_version = a:version
|
||||||
|
endif
|
||||||
|
" Remove surrounding junk. Example: 'v4.12.0' => '4.12.0'
|
||||||
|
let nodejs_version = matchstr(nodejs_version, '\(\d\.\?\)\+')
|
||||||
|
" [major, minor, patch]
|
||||||
|
let v_list = split(nodejs_version, '\.')
|
||||||
|
return len(v_list) == 3
|
||||||
|
\ && ((str2nr(v_list[0]) > str2nr(a:min_major))
|
||||||
|
\ || (str2nr(v_list[0]) == str2nr(a:min_major)
|
||||||
|
\ && str2nr(v_list[1]) >= str2nr(a:min_minor)))
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
function! provider#node#Prog()
|
" Support for --inspect-brk requires node 6.12+ or 7.6+ or 8+
|
||||||
|
" Return 1 if it is supported
|
||||||
|
" Return 0 otherwise
|
||||||
|
function! provider#node#can_inspect() abort
|
||||||
|
if !executable('node')
|
||||||
|
return 0
|
||||||
|
endif
|
||||||
|
let ver = get(split(system(['node', '-v']), "\n"), 0, '')
|
||||||
|
if v:shell_error || ver[0] !=# 'v'
|
||||||
|
return 0
|
||||||
|
endif
|
||||||
|
return (ver[1] ==# '6' && s:is_minimum_version(ver, 6, 12))
|
||||||
|
\ || s:is_minimum_version(ver, 7, 6)
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function! provider#node#Detect() abort
|
||||||
|
let global_modules = get(split(system('npm root -g'), "\n"), 0, '')
|
||||||
|
if v:shell_error || !isdirectory(global_modules)
|
||||||
|
return ''
|
||||||
|
endif
|
||||||
|
if !s:is_minimum_version(v:null, 6, 0)
|
||||||
|
return ''
|
||||||
|
endif
|
||||||
|
let entry_point = glob(global_modules . '/neovim/bin/cli.js')
|
||||||
|
if !filereadable(entry_point)
|
||||||
|
return ''
|
||||||
|
endif
|
||||||
|
return entry_point
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function! provider#node#Prog() abort
|
||||||
return s:prog
|
return s:prog
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
@@ -19,18 +64,14 @@ function! provider#node#Require(host) abort
|
|||||||
return
|
return
|
||||||
endif
|
endif
|
||||||
|
|
||||||
if has('win32')
|
let args = ['node']
|
||||||
let args = provider#node#Prog()
|
|
||||||
else
|
|
||||||
let args = ['node']
|
|
||||||
|
|
||||||
if !empty($NVIM_NODE_HOST_DEBUG)
|
if !empty($NVIM_NODE_HOST_DEBUG) && provider#node#can_inspect()
|
||||||
call add(args, '--inspect-brk')
|
call add(args, '--inspect-brk')
|
||||||
endif
|
|
||||||
|
|
||||||
call add(args , provider#node#Prog())
|
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
call add(args, provider#node#Prog())
|
||||||
|
|
||||||
try
|
try
|
||||||
let channel_id = jobstart(args, s:job_opts)
|
let channel_id = jobstart(args, s:job_opts)
|
||||||
if rpcrequest(channel_id, 'poll') ==# 'ok'
|
if rpcrequest(channel_id, 'poll') ==# 'ok'
|
||||||
@@ -49,7 +90,7 @@ function! provider#node#Require(host) abort
|
|||||||
throw remote#host#LoadErrorForHost(a:host.orig_name, '$NVIM_NODE_LOG_FILE')
|
throw remote#host#LoadErrorForHost(a:host.orig_name, '$NVIM_NODE_LOG_FILE')
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
function! provider#node#Call(method, args)
|
function! provider#node#Call(method, args) abort
|
||||||
if s:err != ''
|
if s:err != ''
|
||||||
echoerr s:err
|
echoerr s:err
|
||||||
return
|
return
|
||||||
|
@@ -11,11 +11,11 @@ let g:loaded_python_provider = 1
|
|||||||
|
|
||||||
let [s:prog, s:err] = provider#pythonx#Detect(2)
|
let [s:prog, s:err] = provider#pythonx#Detect(2)
|
||||||
|
|
||||||
function! provider#python#Prog()
|
function! provider#python#Prog() abort
|
||||||
return s:prog
|
return s:prog
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
function! provider#python#Error()
|
function! provider#python#Error() abort
|
||||||
return s:err
|
return s:err
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
@@ -29,7 +29,7 @@ endif
|
|||||||
call remote#host#RegisterClone('legacy-python-provider', 'python')
|
call remote#host#RegisterClone('legacy-python-provider', 'python')
|
||||||
call remote#host#RegisterPlugin('legacy-python-provider', 'script_host.py', [])
|
call remote#host#RegisterPlugin('legacy-python-provider', 'script_host.py', [])
|
||||||
|
|
||||||
function! provider#python#Call(method, args)
|
function! provider#python#Call(method, args) abort
|
||||||
if s:err != ''
|
if s:err != ''
|
||||||
return
|
return
|
||||||
endif
|
endif
|
||||||
|
@@ -11,11 +11,11 @@ let g:loaded_python3_provider = 1
|
|||||||
|
|
||||||
let [s:prog, s:err] = provider#pythonx#Detect(3)
|
let [s:prog, s:err] = provider#pythonx#Detect(3)
|
||||||
|
|
||||||
function! provider#python3#Prog()
|
function! provider#python3#Prog() abort
|
||||||
return s:prog
|
return s:prog
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
function! provider#python3#Error()
|
function! provider#python3#Error() abort
|
||||||
return s:err
|
return s:err
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
@@ -29,7 +29,7 @@ endif
|
|||||||
call remote#host#RegisterClone('legacy-python3-provider', 'python3')
|
call remote#host#RegisterClone('legacy-python3-provider', 'python3')
|
||||||
call remote#host#RegisterPlugin('legacy-python3-provider', 'script_host.py', [])
|
call remote#host#RegisterPlugin('legacy-python3-provider', 'script_host.py', [])
|
||||||
|
|
||||||
function! provider#python3#Call(method, args)
|
function! provider#python3#Call(method, args) abort
|
||||||
if s:err != ''
|
if s:err != ''
|
||||||
return
|
return
|
||||||
endif
|
endif
|
||||||
|
@@ -7,7 +7,7 @@ let g:loaded_ruby_provider = 1
|
|||||||
let s:stderr = {}
|
let s:stderr = {}
|
||||||
let s:job_opts = {'rpc': v:true}
|
let s:job_opts = {'rpc': v:true}
|
||||||
|
|
||||||
function! s:job_opts.on_stderr(chan_id, data, event)
|
function! s:job_opts.on_stderr(chan_id, data, event) abort
|
||||||
let stderr = get(s:stderr, a:chan_id, [''])
|
let stderr = get(s:stderr, a:chan_id, [''])
|
||||||
let last = remove(stderr, -1)
|
let last = remove(stderr, -1)
|
||||||
let a:data[0] = last.a:data[0]
|
let a:data[0] = last.a:data[0]
|
||||||
@@ -23,7 +23,7 @@ function! provider#ruby#Detect() abort
|
|||||||
end
|
end
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
function! provider#ruby#Prog()
|
function! provider#ruby#Prog() abort
|
||||||
return s:prog
|
return s:prog
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
@@ -50,7 +50,7 @@ function! provider#ruby#Require(host) abort
|
|||||||
throw remote#host#LoadErrorForHost(a:host.orig_name, '$NVIM_RUBY_LOG_FILE')
|
throw remote#host#LoadErrorForHost(a:host.orig_name, '$NVIM_RUBY_LOG_FILE')
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
function! provider#ruby#Call(method, args)
|
function! provider#ruby#Call(method, args) abort
|
||||||
if s:err != ''
|
if s:err != ''
|
||||||
echoerr s:err
|
echoerr s:err
|
||||||
return
|
return
|
||||||
|
@@ -6845,6 +6845,7 @@ setqflist({list} [, {action}[, {what}]]) *setqflist()*
|
|||||||
nr error number
|
nr error number
|
||||||
text description of the error
|
text description of the error
|
||||||
type single-character error type, 'E', 'W', etc.
|
type single-character error type, 'E', 'W', etc.
|
||||||
|
valid recognized error message
|
||||||
|
|
||||||
The "col", "vcol", "nr", "type" and "text" entries are
|
The "col", "vcol", "nr", "type" and "text" entries are
|
||||||
optional. Either "lnum" or "pattern" entry can be used to
|
optional. Either "lnum" or "pattern" entry can be used to
|
||||||
@@ -6854,21 +6855,26 @@ setqflist({list} [, {action}[, {what}]]) *setqflist()*
|
|||||||
item will not be handled as an error line.
|
item will not be handled as an error line.
|
||||||
If both "pattern" and "lnum" are present then "pattern" will
|
If both "pattern" and "lnum" are present then "pattern" will
|
||||||
be used.
|
be used.
|
||||||
|
If the "valid" entry is not supplied, then the valid flag is
|
||||||
|
set when "bufnr" is a valid buffer or "filename" exists.
|
||||||
If you supply an empty {list}, the quickfix list will be
|
If you supply an empty {list}, the quickfix list will be
|
||||||
cleared.
|
cleared.
|
||||||
Note that the list is not exactly the same as what
|
Note that the list is not exactly the same as what
|
||||||
|getqflist()| returns.
|
|getqflist()| returns.
|
||||||
|
|
||||||
*E927*
|
{action} values: *E927*
|
||||||
If {action} is set to 'a', then the items from {list} are
|
'a' The items from {list} are added to the existing
|
||||||
added to the existing quickfix list. If there is no existing
|
quickfix list. If there is no existing list, then a
|
||||||
list, then a new list is created.
|
new list is created.
|
||||||
|
|
||||||
If {action} is set to 'r', then the items from the current
|
'r' The items from the current quickfix list are replaced
|
||||||
quickfix list are replaced with the items from {list}. This
|
with the items from {list}. This can also be used to
|
||||||
can also be used to clear the list: >
|
clear the list: >
|
||||||
:call setqflist([], 'r')
|
:call setqflist([], 'r')
|
||||||
<
|
<
|
||||||
|
'f' All the quickfix lists in the quickfix stack are
|
||||||
|
freed.
|
||||||
|
|
||||||
If {action} is not present or is set to ' ', then a new list
|
If {action} is not present or is set to ' ', then a new list
|
||||||
is created.
|
is created.
|
||||||
|
|
||||||
|
@@ -3809,6 +3809,23 @@ A jump table for the options with a short description can be found at |Q_op|.
|
|||||||
This option cannot be set from a |modeline| or in the |sandbox|, for
|
This option cannot be set from a |modeline| or in the |sandbox|, for
|
||||||
security reasons.
|
security reasons.
|
||||||
|
|
||||||
|
*'makeencoding'* *'menc'*
|
||||||
|
'makeencoding' 'menc' string (default "")
|
||||||
|
global or local to buffer |global-local|
|
||||||
|
{only available when compiled with the |+multi_byte|
|
||||||
|
feature}
|
||||||
|
{not in Vi}
|
||||||
|
Encoding used for reading the output of external commands. When empty,
|
||||||
|
encoding is not converted.
|
||||||
|
This is used for `:make`, `:lmake`, `:grep`, `:lgrep`, `:grepadd`,
|
||||||
|
`:lgrepadd`, `:cfile`, `:cgetfile`, `:caddfile`, `:lfile`, `:lgetfile`,
|
||||||
|
and `:laddfile`.
|
||||||
|
|
||||||
|
This would be mostly useful when you use MS-Windows. If |+iconv| is
|
||||||
|
enabled and GNU libiconv is used, setting 'makeencoding' to "char" has
|
||||||
|
the same effect as setting to the system locale encoding. Example: >
|
||||||
|
:set makeencoding=char " system locale is used
|
||||||
|
<
|
||||||
*'makeprg'* *'mp'*
|
*'makeprg'* *'mp'*
|
||||||
'makeprg' 'mp' string (default "make")
|
'makeprg' 'mp' string (default "make")
|
||||||
global or local to buffer |global-local|
|
global or local to buffer |global-local|
|
||||||
|
@@ -165,6 +165,9 @@ processing a quickfix or location list command, it will be aborted.
|
|||||||
keep Vim running while compiling. If you give the
|
keep Vim running while compiling. If you give the
|
||||||
name of the errorfile, the 'errorfile' option will
|
name of the errorfile, the 'errorfile' option will
|
||||||
be set to [errorfile]. See |:cc| for [!].
|
be set to [errorfile]. See |:cc| for [!].
|
||||||
|
If the encoding of the error file differs from the
|
||||||
|
'encoding' option, you can use the 'makeencoding'
|
||||||
|
option to specify the encoding.
|
||||||
|
|
||||||
*:lf* *:lfile*
|
*:lf* *:lfile*
|
||||||
:lf[ile][!] [errorfile] Same as ":cfile", except the location list for the
|
:lf[ile][!] [errorfile] Same as ":cfile", except the location list for the
|
||||||
@@ -176,6 +179,9 @@ processing a quickfix or location list command, it will be aborted.
|
|||||||
:cg[etfile] [errorfile] *:cg* *:cgetfile*
|
:cg[etfile] [errorfile] *:cg* *:cgetfile*
|
||||||
Read the error file. Just like ":cfile" but don't
|
Read the error file. Just like ":cfile" but don't
|
||||||
jump to the first error.
|
jump to the first error.
|
||||||
|
If the encoding of the error file differs from the
|
||||||
|
'encoding' option, you can use the 'makeencoding'
|
||||||
|
option to specify the encoding.
|
||||||
|
|
||||||
|
|
||||||
:lg[etfile] [errorfile] *:lg* *:lgetfile*
|
:lg[etfile] [errorfile] *:lg* *:lgetfile*
|
||||||
@@ -186,6 +192,9 @@ processing a quickfix or location list command, it will be aborted.
|
|||||||
:caddf[ile] [errorfile] Read the error file and add the errors from the
|
:caddf[ile] [errorfile] Read the error file and add the errors from the
|
||||||
errorfile to the current quickfix list. If a quickfix
|
errorfile to the current quickfix list. If a quickfix
|
||||||
list is not present, then a new list is created.
|
list is not present, then a new list is created.
|
||||||
|
If the encoding of the error file differs from the
|
||||||
|
'encoding' option, you can use the 'makeencoding'
|
||||||
|
option to specify the encoding.
|
||||||
|
|
||||||
*:laddf* *:laddfile*
|
*:laddf* *:laddfile*
|
||||||
:laddf[ile] [errorfile] Same as ":caddfile", except the location list for the
|
:laddf[ile] [errorfile] Same as ":caddfile", except the location list for the
|
||||||
@@ -322,6 +331,7 @@ use this code: >
|
|||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
au QuickfixCmdPost make call QfMakeConv()
|
au QuickfixCmdPost make call QfMakeConv()
|
||||||
|
Another option is using 'makeencoding'.
|
||||||
|
|
||||||
EXECUTE A COMMAND IN ALL THE BUFFERS IN QUICKFIX OR LOCATION LIST:
|
EXECUTE A COMMAND IN ALL THE BUFFERS IN QUICKFIX OR LOCATION LIST:
|
||||||
*:cdo*
|
*:cdo*
|
||||||
@@ -586,6 +596,9 @@ lists, use ":cnewer 99" first.
|
|||||||
like |:cnext| and |:cprevious|, see above.
|
like |:cnext| and |:cprevious|, see above.
|
||||||
This command does not accept a comment, any "
|
This command does not accept a comment, any "
|
||||||
characters are considered part of the arguments.
|
characters are considered part of the arguments.
|
||||||
|
If the encoding of the program output differs from the
|
||||||
|
'encoding' option, you can use the 'makeencoding'
|
||||||
|
option to specify the encoding.
|
||||||
|
|
||||||
*:lmak* *:lmake*
|
*:lmak* *:lmake*
|
||||||
:lmak[e][!] [arguments]
|
:lmak[e][!] [arguments]
|
||||||
@@ -645,6 +658,7 @@ read the error messages: >
|
|||||||
au QuickfixCmdPost make call QfMakeConv()
|
au QuickfixCmdPost make call QfMakeConv()
|
||||||
|
|
||||||
(Example by Faque Cheng)
|
(Example by Faque Cheng)
|
||||||
|
Another option is using 'makeencoding'.
|
||||||
|
|
||||||
==============================================================================
|
==============================================================================
|
||||||
5. Using :vimgrep and :grep *grep* *lid*
|
5. Using :vimgrep and :grep *grep* *lid*
|
||||||
@@ -759,6 +773,9 @@ id-utils) in a similar way to its compiler integration (see |:make| above).
|
|||||||
When 'grepprg' is "internal" this works like
|
When 'grepprg' is "internal" this works like
|
||||||
|:vimgrep|. Note that the pattern needs to be
|
|:vimgrep|. Note that the pattern needs to be
|
||||||
enclosed in separator characters then.
|
enclosed in separator characters then.
|
||||||
|
If the encoding of the program output differs from the
|
||||||
|
'encoding' option, you can use the 'makeencoding'
|
||||||
|
option to specify the encoding.
|
||||||
|
|
||||||
*:lgr* *:lgrep*
|
*:lgr* *:lgrep*
|
||||||
:lgr[ep][!] [arguments] Same as ":grep", except the location list for the
|
:lgr[ep][!] [arguments] Same as ":grep", except the location list for the
|
||||||
@@ -783,6 +800,10 @@ id-utils) in a similar way to its compiler integration (see |:make| above).
|
|||||||
\ | catch /E480:/
|
\ | catch /E480:/
|
||||||
\ | endtry"
|
\ | endtry"
|
||||||
<
|
<
|
||||||
|
If the encoding of the program output differs from the
|
||||||
|
'encoding' option, you can use the 'makeencoding'
|
||||||
|
option to specify the encoding.
|
||||||
|
|
||||||
*:lgrepa* *:lgrepadd*
|
*:lgrepa* *:lgrepadd*
|
||||||
:lgrepa[dd][!] [arguments]
|
:lgrepa[dd][!] [arguments]
|
||||||
Same as ":grepadd", except the location list for the
|
Same as ":grepadd", except the location list for the
|
||||||
|
@@ -762,6 +762,7 @@ Short explanation of each option: *option-list*
|
|||||||
'loadplugins' 'lpl' load plugin scripts when starting up
|
'loadplugins' 'lpl' load plugin scripts when starting up
|
||||||
'magic' changes special characters in search patterns
|
'magic' changes special characters in search patterns
|
||||||
'makeef' 'mef' name of the errorfile for ":make"
|
'makeef' 'mef' name of the errorfile for ":make"
|
||||||
|
'makeencoding' 'menc' encoding of external make/grep commands
|
||||||
'makeprg' 'mp' program to use for the ":make" command
|
'makeprg' 'mp' program to use for the ":make" command
|
||||||
'matchpairs' 'mps' pairs of characters that "%" can match
|
'matchpairs' 'mps' pairs of characters that "%" can match
|
||||||
'matchtime' 'mat' tenths of a second to show matching paren
|
'matchtime' 'mat' tenths of a second to show matching paren
|
||||||
|
@@ -92,8 +92,11 @@ get_vim_sources() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
commit_message() {
|
commit_message() {
|
||||||
printf 'vim-patch:%s\n\n%s\n\n%s' "${vim_version}" \
|
if [[ -n "$vim_tag" ]]; then
|
||||||
"${vim_message}" "${vim_commit_url}"
|
printf '%s\n\n%s' "${vim_message}" "${vim_commit_url}"
|
||||||
|
else
|
||||||
|
printf 'vim-patch:%s\n\n%s\n\n%s' "$vim_version" "$vim_message" "$vim_commit_url"
|
||||||
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
find_git_remote() {
|
find_git_remote() {
|
||||||
@@ -108,22 +111,23 @@ assign_commit_details() {
|
|||||||
vim_tag="v${1}"
|
vim_tag="v${1}"
|
||||||
vim_commit=$(cd "${VIM_SOURCE_DIR}" \
|
vim_commit=$(cd "${VIM_SOURCE_DIR}" \
|
||||||
&& git log -1 --format="%H" "${vim_tag}")
|
&& git log -1 --format="%H" "${vim_tag}")
|
||||||
local strip_commit_line=true
|
local munge_commit_line=true
|
||||||
else
|
else
|
||||||
# Interpret parameter as commit hash.
|
# Interpret parameter as commit hash.
|
||||||
vim_version="${1:0:12}"
|
vim_version="${1:0:12}"
|
||||||
|
vim_tag=
|
||||||
vim_commit=$(cd "${VIM_SOURCE_DIR}" \
|
vim_commit=$(cd "${VIM_SOURCE_DIR}" \
|
||||||
&& git log -1 --format="%H" "${vim_version}")
|
&& git log -1 --format="%H" "${vim_version}")
|
||||||
local strip_commit_line=false
|
local munge_commit_line=false
|
||||||
fi
|
fi
|
||||||
|
|
||||||
vim_commit_url="https://github.com/vim/vim/commit/${vim_commit}"
|
vim_commit_url="https://github.com/vim/vim/commit/${vim_commit}"
|
||||||
vim_message="$(cd "${VIM_SOURCE_DIR}" \
|
vim_message="$(cd "${VIM_SOURCE_DIR}" \
|
||||||
&& git log -1 --pretty='format:%B' "${vim_commit}" \
|
&& git log -1 --pretty='format:%B' "${vim_commit}" \
|
||||||
| sed -e 's/\(#[0-9]*\)/vim\/vim\1/g')"
|
| sed -e 's/\(#[0-9]*\)/vim\/vim\1/g')"
|
||||||
if [[ ${strip_commit_line} == "true" ]]; then
|
if [[ ${munge_commit_line} == "true" ]]; then
|
||||||
# Remove first line of commit message.
|
# Remove first line of commit message.
|
||||||
vim_message="$(echo "${vim_message}" | sed -e '1d')"
|
vim_message="$(echo "${vim_message}" | sed -e '1s/^patch /vim-patch:/')"
|
||||||
fi
|
fi
|
||||||
patch_file="vim-${vim_version}.patch"
|
patch_file="vim-${vim_version}.patch"
|
||||||
}
|
}
|
||||||
@@ -286,9 +290,10 @@ submit_pr() {
|
|||||||
checked_out_branch="$(git rev-parse --abbrev-ref HEAD)"
|
checked_out_branch="$(git rev-parse --abbrev-ref HEAD)"
|
||||||
if [[ "${checked_out_branch}" != ${BRANCH_PREFIX}* ]]; then
|
if [[ "${checked_out_branch}" != ${BRANCH_PREFIX}* ]]; then
|
||||||
echo "✘ Current branch '${checked_out_branch}' doesn't seem to be a vim-patch branch."
|
echo "✘ Current branch '${checked_out_branch}' doesn't seem to be a vim-patch branch."
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
local git_remote
|
||||||
git_remote="$(find_git_remote)"
|
git_remote="$(find_git_remote)"
|
||||||
local pr_body
|
local pr_body
|
||||||
pr_body="$(git log --grep=vim-patch --reverse --format='#### %s%n%n%b%n' "${git_remote}"/master..HEAD)"
|
pr_body="$(git log --grep=vim-patch --reverse --format='#### %s%n%n%b%n' "${git_remote}"/master..HEAD)"
|
||||||
|
@@ -1,3 +1,7 @@
|
|||||||
# multiqueue.h pointer arithmetic is not accepted by asan
|
# multiqueue.h pointer arithmetic is not accepted by asan
|
||||||
fun:multiqueue_node_data
|
fun:multiqueue_node_data
|
||||||
fun:tv_dict_watcher_node_data
|
fun:tv_dict_watcher_node_data
|
||||||
|
|
||||||
|
# Allocation in loop_schedule_deferred() is freed by loop_deferred_event(), but
|
||||||
|
# this sometimes does not happen during teardown.
|
||||||
|
func:loop_schedule_deferred
|
||||||
|
@@ -1808,6 +1808,7 @@ void free_buf_options(buf_T *buf, int free_p_ff)
|
|||||||
buf->b_p_ul = NO_LOCAL_UNDOLEVEL;
|
buf->b_p_ul = NO_LOCAL_UNDOLEVEL;
|
||||||
clear_string_option(&buf->b_p_lw);
|
clear_string_option(&buf->b_p_lw);
|
||||||
clear_string_option(&buf->b_p_bkc);
|
clear_string_option(&buf->b_p_bkc);
|
||||||
|
clear_string_option(&buf->b_p_menc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@@ -637,6 +637,7 @@ struct file_buffer {
|
|||||||
uint32_t b_p_fex_flags; ///< flags for 'formatexpr'
|
uint32_t b_p_fex_flags; ///< flags for 'formatexpr'
|
||||||
char_u *b_p_kp; ///< 'keywordprg'
|
char_u *b_p_kp; ///< 'keywordprg'
|
||||||
int b_p_lisp; ///< 'lisp'
|
int b_p_lisp; ///< 'lisp'
|
||||||
|
char_u *b_p_menc; ///< 'makeencoding'
|
||||||
char_u *b_p_mps; ///< 'matchpairs'
|
char_u *b_p_mps; ///< 'matchpairs'
|
||||||
int b_p_ml; ///< 'modeline'
|
int b_p_ml; ///< 'modeline'
|
||||||
int b_p_ml_nobin; ///< b_p_ml saved for binary mode
|
int b_p_ml_nobin; ///< b_p_ml saved for binary mode
|
||||||
|
@@ -5183,6 +5183,8 @@ bool garbage_collect(bool testing)
|
|||||||
ABORTING(set_ref_list)(sub.additional_elements, copyID);
|
ABORTING(set_ref_list)(sub.additional_elements, copyID);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ABORTING(set_ref_in_quickfix)(copyID);
|
||||||
|
|
||||||
bool did_free = false;
|
bool did_free = false;
|
||||||
if (!abort) {
|
if (!abort) {
|
||||||
// 2. Free lists and dictionaries that are not referenced.
|
// 2. Free lists and dictionaries that are not referenced.
|
||||||
@@ -14611,7 +14613,8 @@ static void set_qf_ll_list(win_T *wp, typval_T *args, typval_T *rettv)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const char *const act = tv_get_string_chk(action_arg);
|
const char *const act = tv_get_string_chk(action_arg);
|
||||||
if ((*act == 'a' || *act == 'r' || *act == ' ') && act[1] == NUL) {
|
if ((*act == 'a' || *act == 'r' || *act == ' ' || *act == 'f')
|
||||||
|
&& act[1] == NUL) {
|
||||||
action = *act;
|
action = *act;
|
||||||
} else {
|
} else {
|
||||||
EMSG2(_(e_invact), act);
|
EMSG2(_(e_invact), act);
|
||||||
|
@@ -30,19 +30,22 @@ void loop_init(Loop *loop, void *data)
|
|||||||
uv_signal_init(&loop->uv, &loop->children_watcher);
|
uv_signal_init(&loop->uv, &loop->children_watcher);
|
||||||
uv_timer_init(&loop->uv, &loop->children_kill_timer);
|
uv_timer_init(&loop->uv, &loop->children_kill_timer);
|
||||||
uv_timer_init(&loop->uv, &loop->poll_timer);
|
uv_timer_init(&loop->uv, &loop->poll_timer);
|
||||||
|
loop->poll_timer.data = xmalloc(sizeof(bool)); // "timeout expired" flag
|
||||||
}
|
}
|
||||||
|
|
||||||
void loop_poll_events(Loop *loop, int ms)
|
/// @returns true if `ms` timeout was reached
|
||||||
|
bool loop_poll_events(Loop *loop, int ms)
|
||||||
{
|
{
|
||||||
if (loop->recursive++) {
|
if (loop->recursive++) {
|
||||||
abort(); // Should not re-enter uv_run
|
abort(); // Should not re-enter uv_run
|
||||||
}
|
}
|
||||||
|
|
||||||
uv_run_mode mode = UV_RUN_ONCE;
|
uv_run_mode mode = UV_RUN_ONCE;
|
||||||
|
bool timeout_expired = false;
|
||||||
|
|
||||||
if (ms > 0) {
|
if (ms > 0) {
|
||||||
// Use a repeating timeout of ms milliseconds to make sure
|
*((bool *)loop->poll_timer.data) = false; // reset "timeout expired" flag
|
||||||
// we do not block indefinitely for I/O.
|
// Dummy timer to ensure UV_RUN_ONCE does not block indefinitely for I/O.
|
||||||
uv_timer_start(&loop->poll_timer, timer_cb, (uint64_t)ms, (uint64_t)ms);
|
uv_timer_start(&loop->poll_timer, timer_cb, (uint64_t)ms, (uint64_t)ms);
|
||||||
} else if (ms == 0) {
|
} else if (ms == 0) {
|
||||||
// For ms == 0, do a non-blocking event poll.
|
// For ms == 0, do a non-blocking event poll.
|
||||||
@@ -52,11 +55,13 @@ void loop_poll_events(Loop *loop, int ms)
|
|||||||
uv_run(&loop->uv, mode);
|
uv_run(&loop->uv, mode);
|
||||||
|
|
||||||
if (ms > 0) {
|
if (ms > 0) {
|
||||||
|
timeout_expired = *((bool *)loop->poll_timer.data);
|
||||||
uv_timer_stop(&loop->poll_timer);
|
uv_timer_stop(&loop->poll_timer);
|
||||||
}
|
}
|
||||||
|
|
||||||
loop->recursive--; // Can re-enter uv_run now
|
loop->recursive--; // Can re-enter uv_run now
|
||||||
multiqueue_process_events(loop->fast_events);
|
multiqueue_process_events(loop->fast_events);
|
||||||
|
return timeout_expired;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Schedules an event from another thread.
|
/// Schedules an event from another thread.
|
||||||
@@ -111,7 +116,7 @@ bool loop_close(Loop *loop, bool wait)
|
|||||||
uv_mutex_destroy(&loop->mutex);
|
uv_mutex_destroy(&loop->mutex);
|
||||||
uv_close((uv_handle_t *)&loop->children_watcher, NULL);
|
uv_close((uv_handle_t *)&loop->children_watcher, NULL);
|
||||||
uv_close((uv_handle_t *)&loop->children_kill_timer, NULL);
|
uv_close((uv_handle_t *)&loop->children_kill_timer, NULL);
|
||||||
uv_close((uv_handle_t *)&loop->poll_timer, NULL);
|
uv_close((uv_handle_t *)&loop->poll_timer, timer_close_cb);
|
||||||
uv_close((uv_handle_t *)&loop->async, NULL);
|
uv_close((uv_handle_t *)&loop->async, NULL);
|
||||||
uint64_t start = wait ? os_hrtime() : 0;
|
uint64_t start = wait ? os_hrtime() : 0;
|
||||||
while (true) {
|
while (true) {
|
||||||
@@ -163,5 +168,11 @@ static void async_cb(uv_async_t *handle)
|
|||||||
|
|
||||||
static void timer_cb(uv_timer_t *handle)
|
static void timer_cb(uv_timer_t *handle)
|
||||||
{
|
{
|
||||||
|
bool *timeout_expired = handle->data;
|
||||||
|
*timeout_expired = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void timer_close_cb(uv_handle_t *handle)
|
||||||
|
{
|
||||||
|
xfree(handle->data);
|
||||||
|
}
|
||||||
|
@@ -1012,9 +1012,9 @@ static int cs_find_common(char *opt, char *pat, int forceit, int verbose,
|
|||||||
fclose(f);
|
fclose(f);
|
||||||
if (use_ll) /* Use location list */
|
if (use_ll) /* Use location list */
|
||||||
wp = curwin;
|
wp = curwin;
|
||||||
/* '-' starts a new error list */
|
// '-' starts a new error list
|
||||||
if (qf_init(wp, tmp, (char_u *)"%f%*\\t%l%*\\t%m",
|
if (qf_init(wp, tmp, (char_u *)"%f%*\\t%l%*\\t%m",
|
||||||
*qfpos == '-', cmdline) > 0) {
|
*qfpos == '-', cmdline, NULL) > 0) {
|
||||||
if (postponed_split != 0) {
|
if (postponed_split != 0) {
|
||||||
(void)win_split(postponed_split > 0 ? postponed_split : 0,
|
(void)win_split(postponed_split > 0 ? postponed_split : 0,
|
||||||
postponed_split_flags);
|
postponed_split_flags);
|
||||||
|
@@ -1369,7 +1369,7 @@ static void handle_quickfix(mparm_T *paramp)
|
|||||||
set_string_option_direct((char_u *)"ef", -1,
|
set_string_option_direct((char_u *)"ef", -1,
|
||||||
paramp->use_ef, OPT_FREE, SID_CARG);
|
paramp->use_ef, OPT_FREE, SID_CARG);
|
||||||
vim_snprintf((char *)IObuff, IOSIZE, "cfile %s", p_ef);
|
vim_snprintf((char *)IObuff, IOSIZE, "cfile %s", p_ef);
|
||||||
if (qf_init(NULL, p_ef, p_efm, true, IObuff) < 0) {
|
if (qf_init(NULL, p_ef, p_efm, true, IObuff, p_menc) < 0) {
|
||||||
ui_linefeed();
|
ui_linefeed();
|
||||||
mch_exit(3);
|
mch_exit(3);
|
||||||
}
|
}
|
||||||
|
@@ -2217,6 +2217,7 @@ void check_buf_options(buf_T *buf)
|
|||||||
check_string_option(&buf->b_p_tsr);
|
check_string_option(&buf->b_p_tsr);
|
||||||
check_string_option(&buf->b_p_lw);
|
check_string_option(&buf->b_p_lw);
|
||||||
check_string_option(&buf->b_p_bkc);
|
check_string_option(&buf->b_p_bkc);
|
||||||
|
check_string_option(&buf->b_p_menc);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -2635,8 +2636,8 @@ did_set_string_option (
|
|||||||
else if (varp == &p_ei) {
|
else if (varp == &p_ei) {
|
||||||
if (check_ei() == FAIL)
|
if (check_ei() == FAIL)
|
||||||
errmsg = e_invarg;
|
errmsg = e_invarg;
|
||||||
/* 'encoding' and 'fileencoding' */
|
// 'encoding', 'fileencoding' and 'makeencoding'
|
||||||
} else if (varp == &p_enc || gvarp == &p_fenc) {
|
} else if (varp == &p_enc || gvarp == &p_fenc || gvarp == &p_menc) {
|
||||||
if (gvarp == &p_fenc) {
|
if (gvarp == &p_fenc) {
|
||||||
if (!MODIFIABLE(curbuf) && opt_flags != OPT_GLOBAL) {
|
if (!MODIFIABLE(curbuf) && opt_flags != OPT_GLOBAL) {
|
||||||
errmsg = e_modifiable;
|
errmsg = e_modifiable;
|
||||||
@@ -5400,6 +5401,9 @@ void unset_global_local_option(char *name, void *from)
|
|||||||
case PV_LW:
|
case PV_LW:
|
||||||
clear_string_option(&buf->b_p_lw);
|
clear_string_option(&buf->b_p_lw);
|
||||||
break;
|
break;
|
||||||
|
case PV_MENC:
|
||||||
|
clear_string_option(&buf->b_p_menc);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -5433,6 +5437,7 @@ static char_u *get_varp_scope(vimoption_T *p, int opt_flags)
|
|||||||
case PV_UL: return (char_u *)&(curbuf->b_p_ul);
|
case PV_UL: return (char_u *)&(curbuf->b_p_ul);
|
||||||
case PV_LW: return (char_u *)&(curbuf->b_p_lw);
|
case PV_LW: return (char_u *)&(curbuf->b_p_lw);
|
||||||
case PV_BKC: return (char_u *)&(curbuf->b_p_bkc);
|
case PV_BKC: return (char_u *)&(curbuf->b_p_bkc);
|
||||||
|
case PV_MENC: return (char_u *)&(curbuf->b_p_menc);
|
||||||
}
|
}
|
||||||
return NULL; /* "cannot happen" */
|
return NULL; /* "cannot happen" */
|
||||||
}
|
}
|
||||||
@@ -5488,6 +5493,8 @@ static char_u *get_varp(vimoption_T *p)
|
|||||||
? (char_u *)&(curbuf->b_p_ul) : p->var;
|
? (char_u *)&(curbuf->b_p_ul) : p->var;
|
||||||
case PV_LW: return *curbuf->b_p_lw != NUL
|
case PV_LW: return *curbuf->b_p_lw != NUL
|
||||||
? (char_u *)&(curbuf->b_p_lw) : p->var;
|
? (char_u *)&(curbuf->b_p_lw) : p->var;
|
||||||
|
case PV_MENC: return *curbuf->b_p_menc != NUL
|
||||||
|
? (char_u *)&(curbuf->b_p_menc) : p->var;
|
||||||
|
|
||||||
case PV_ARAB: return (char_u *)&(curwin->w_p_arab);
|
case PV_ARAB: return (char_u *)&(curwin->w_p_arab);
|
||||||
case PV_LIST: return (char_u *)&(curwin->w_p_list);
|
case PV_LIST: return (char_u *)&(curwin->w_p_list);
|
||||||
@@ -5885,6 +5892,7 @@ void buf_copy_options(buf_T *buf, int flags)
|
|||||||
buf->b_p_qe = vim_strsave(p_qe);
|
buf->b_p_qe = vim_strsave(p_qe);
|
||||||
buf->b_p_udf = p_udf;
|
buf->b_p_udf = p_udf;
|
||||||
buf->b_p_lw = empty_option;
|
buf->b_p_lw = empty_option;
|
||||||
|
buf->b_p_menc = empty_option;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Don't copy the options set by ex_help(), use the saved values,
|
* Don't copy the options set by ex_help(), use the saved values,
|
||||||
|
@@ -489,6 +489,7 @@ EXTERN char_u *p_lcs; // 'listchars'
|
|||||||
EXTERN int p_lz; // 'lazyredraw'
|
EXTERN int p_lz; // 'lazyredraw'
|
||||||
EXTERN int p_lpl; // 'loadplugins'
|
EXTERN int p_lpl; // 'loadplugins'
|
||||||
EXTERN int p_magic; // 'magic'
|
EXTERN int p_magic; // 'magic'
|
||||||
|
EXTERN char_u *p_menc; // 'makeencoding'
|
||||||
EXTERN char_u *p_mef; // 'makeef'
|
EXTERN char_u *p_mef; // 'makeef'
|
||||||
EXTERN char_u *p_mp; // 'makeprg'
|
EXTERN char_u *p_mp; // 'makeprg'
|
||||||
EXTERN char_u *p_cc; // 'colorcolumn'
|
EXTERN char_u *p_cc; // 'colorcolumn'
|
||||||
@@ -736,6 +737,7 @@ enum {
|
|||||||
, BV_KP
|
, BV_KP
|
||||||
, BV_LISP
|
, BV_LISP
|
||||||
, BV_LW
|
, BV_LW
|
||||||
|
, BV_MENC
|
||||||
, BV_MA
|
, BV_MA
|
||||||
, BV_ML
|
, BV_ML
|
||||||
, BV_MOD
|
, BV_MOD
|
||||||
|
@@ -1456,6 +1456,13 @@ return {
|
|||||||
varname='p_mef',
|
varname='p_mef',
|
||||||
defaults={if_true={vi=""}}
|
defaults={if_true={vi=""}}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
full_name='makeencoding', abbreviation='menc',
|
||||||
|
type='string', scope={'global', 'buffer'},
|
||||||
|
vi_def=true,
|
||||||
|
varname='p_menc',
|
||||||
|
defaults={if_true={vi=""}}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
full_name='makeprg', abbreviation='mp',
|
full_name='makeprg', abbreviation='mp',
|
||||||
type='string', scope={'global', 'buffer'},
|
type='string', scope={'global', 'buffer'},
|
||||||
|
@@ -85,6 +85,7 @@ typedef struct qf_list_S {
|
|||||||
int qf_nonevalid; // TRUE if not a single valid entry found
|
int qf_nonevalid; // TRUE if not a single valid entry found
|
||||||
char_u *qf_title; // title derived from the command that created
|
char_u *qf_title; // title derived from the command that created
|
||||||
// the error list
|
// the error list
|
||||||
|
typval_T *qf_ctx; // context set by setqflist/setloclist
|
||||||
} qf_list_T;
|
} qf_list_T;
|
||||||
|
|
||||||
struct qf_info_S {
|
struct qf_info_S {
|
||||||
@@ -161,6 +162,7 @@ typedef struct {
|
|||||||
buf_T *buf;
|
buf_T *buf;
|
||||||
linenr_T buflnum;
|
linenr_T buflnum;
|
||||||
linenr_T lnumlast;
|
linenr_T lnumlast;
|
||||||
|
vimconv_T vc;
|
||||||
} qfstate_T;
|
} qfstate_T;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
@@ -194,19 +196,19 @@ typedef struct {
|
|||||||
static char_u *qf_last_bufname = NULL;
|
static char_u *qf_last_bufname = NULL;
|
||||||
static bufref_T qf_last_bufref = { NULL, 0, 0 };
|
static bufref_T qf_last_bufref = { NULL, 0, 0 };
|
||||||
|
|
||||||
/*
|
/// Read the errorfile "efile" into memory, line by line, building the error
|
||||||
* Read the errorfile "efile" into memory, line by line, building the error
|
/// list. Set the error list's title to qf_title.
|
||||||
* list. Set the error list's title to qf_title.
|
///
|
||||||
* Return -1 for error, number of errors for success.
|
/// @params wp If non-NULL, make a location list
|
||||||
*/
|
/// @params efile If non-NULL, errorfile to parse
|
||||||
int
|
/// @params errorformat 'errorformat' string used to parse the error lines
|
||||||
qf_init (
|
/// @params newlist If true, create a new error list
|
||||||
win_T *wp,
|
/// @params qf_title If non-NULL, title of the error list
|
||||||
char_u *efile,
|
/// @params enc If non-NULL, encoding used to parse errors
|
||||||
char_u *errorformat,
|
///
|
||||||
int newlist, /* TRUE: start a new error list */
|
/// @returns -1 for error, number of errors for success.
|
||||||
char_u *qf_title
|
int qf_init(win_T *wp, char_u *efile, char_u *errorformat, int newlist,
|
||||||
)
|
char_u *qf_title, char_u *enc)
|
||||||
{
|
{
|
||||||
qf_info_T *qi = &ql_info;
|
qf_info_T *qi = &ql_info;
|
||||||
|
|
||||||
@@ -215,8 +217,8 @@ qf_init (
|
|||||||
}
|
}
|
||||||
|
|
||||||
return qf_init_ext(qi, efile, curbuf, NULL, errorformat, newlist,
|
return qf_init_ext(qi, efile, curbuf, NULL, errorformat, newlist,
|
||||||
(linenr_T)0, (linenr_T)0,
|
(linenr_T)0, (linenr_T)0,
|
||||||
qf_title);
|
qf_title, enc);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Maximum number of bytes allowed per line while reading an errorfile.
|
// Maximum number of bytes allowed per line while reading an errorfile.
|
||||||
@@ -640,6 +642,22 @@ retry:
|
|||||||
} else {
|
} else {
|
||||||
state->linebuf = IObuff;
|
state->linebuf = IObuff;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Convert a line if it contains a non-ASCII character
|
||||||
|
if (state->vc.vc_type != CONV_NONE && has_non_ascii(state->linebuf)) {
|
||||||
|
char_u *line = string_convert(&state->vc, state->linebuf, &state->linelen);
|
||||||
|
if (line != NULL) {
|
||||||
|
if (state->linelen < IOSIZE) {
|
||||||
|
STRLCPY(state->linebuf, line, state->linelen + 1);
|
||||||
|
xfree(line);
|
||||||
|
} else {
|
||||||
|
xfree(state->growbuf);
|
||||||
|
state->linebuf = state->growbuf = line;
|
||||||
|
state->growbufsiz = state->linelen < LINE_MAXLEN
|
||||||
|
? state->linelen : LINE_MAXLEN;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
return QF_OK;
|
return QF_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -785,7 +803,7 @@ restofline:
|
|||||||
fields->type = *regmatch.startp[i];
|
fields->type = *regmatch.startp[i];
|
||||||
}
|
}
|
||||||
if (fmt_ptr->flags == '+' && !qi->qf_multiscan) { // %+
|
if (fmt_ptr->flags == '+' && !qi->qf_multiscan) { // %+
|
||||||
if (linelen > fields->errmsglen) {
|
if (linelen >= fields->errmsglen) {
|
||||||
// linelen + null terminator
|
// linelen + null terminator
|
||||||
fields->errmsg = xrealloc(fields->errmsg, linelen + 1);
|
fields->errmsg = xrealloc(fields->errmsg, linelen + 1);
|
||||||
fields->errmsglen = linelen + 1;
|
fields->errmsglen = linelen + 1;
|
||||||
@@ -796,7 +814,7 @@ restofline:
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
len = (size_t)(regmatch.endp[i] - regmatch.startp[i]);
|
len = (size_t)(regmatch.endp[i] - regmatch.startp[i]);
|
||||||
if (len > fields->errmsglen) {
|
if (len >= fields->errmsglen) {
|
||||||
// len + null terminator
|
// len + null terminator
|
||||||
fields->errmsg = xrealloc(fields->errmsg, len + 1);
|
fields->errmsg = xrealloc(fields->errmsg, len + 1);
|
||||||
fields->errmsglen = len + 1;
|
fields->errmsglen = len + 1;
|
||||||
@@ -873,7 +891,7 @@ restofline:
|
|||||||
fields->namebuf[0] = NUL; // no match found, remove file name
|
fields->namebuf[0] = NUL; // no match found, remove file name
|
||||||
fields->lnum = 0; // don't jump to this line
|
fields->lnum = 0; // don't jump to this line
|
||||||
fields->valid = false;
|
fields->valid = false;
|
||||||
if (linelen > fields->errmsglen) {
|
if (linelen >= fields->errmsglen) {
|
||||||
// linelen + null terminator
|
// linelen + null terminator
|
||||||
fields->errmsg = xrealloc(fields->errmsg, linelen + 1);
|
fields->errmsg = xrealloc(fields->errmsg, linelen + 1);
|
||||||
fields->errmsglen = linelen + 1;
|
fields->errmsglen = linelen + 1;
|
||||||
@@ -978,15 +996,15 @@ qf_init_ext(
|
|||||||
buf_T *buf,
|
buf_T *buf,
|
||||||
typval_T *tv,
|
typval_T *tv,
|
||||||
char_u *errorformat,
|
char_u *errorformat,
|
||||||
int newlist, /* TRUE: start a new error list */
|
int newlist, // TRUE: start a new error list
|
||||||
linenr_T lnumfirst, /* first line number to use */
|
linenr_T lnumfirst, // first line number to use
|
||||||
linenr_T lnumlast, /* last line number to use */
|
linenr_T lnumlast, // last line number to use
|
||||||
char_u *qf_title
|
char_u *qf_title,
|
||||||
|
char_u *enc
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
qfstate_T state = { NULL, 0, NULL, 0, NULL, NULL, NULL, NULL,
|
qfstate_T state;
|
||||||
NULL, NULL, 0, 0 };
|
qffields_T fields;
|
||||||
qffields_T fields = { NULL, NULL, 0, 0L, 0, false, NULL, 0, 0, 0 };
|
|
||||||
qfline_T *old_last = NULL;
|
qfline_T *old_last = NULL;
|
||||||
bool adding = false;
|
bool adding = false;
|
||||||
static efm_T *fmt_first = NULL;
|
static efm_T *fmt_first = NULL;
|
||||||
@@ -999,6 +1017,13 @@ qf_init_ext(
|
|||||||
xfree(qf_last_bufname);
|
xfree(qf_last_bufname);
|
||||||
qf_last_bufname = NULL;
|
qf_last_bufname = NULL;
|
||||||
|
|
||||||
|
memset(&state, 0, sizeof(state));
|
||||||
|
memset(&fields, 0, sizeof(fields));
|
||||||
|
state.vc.vc_type = CONV_NONE;
|
||||||
|
if (enc != NULL && *enc != NUL) {
|
||||||
|
convert_setup(&state.vc, enc, p_enc);
|
||||||
|
}
|
||||||
|
|
||||||
fields.namebuf = xmalloc(CMDBUFFSIZE + 1);
|
fields.namebuf = xmalloc(CMDBUFFSIZE + 1);
|
||||||
fields.errmsglen = CMDBUFFSIZE + 1;
|
fields.errmsglen = CMDBUFFSIZE + 1;
|
||||||
fields.errmsg = xmalloc(fields.errmsglen);
|
fields.errmsg = xmalloc(fields.errmsglen);
|
||||||
@@ -1150,6 +1175,10 @@ qf_init_end:
|
|||||||
|
|
||||||
qf_update_buffer(qi, old_last);
|
qf_update_buffer(qi, old_last);
|
||||||
|
|
||||||
|
if (state.vc.vc_type != CONV_NONE) {
|
||||||
|
convert_setup(&state.vc, NULL, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1384,6 +1413,13 @@ void copy_loclist(win_T *from, win_T *to)
|
|||||||
else
|
else
|
||||||
to_qfl->qf_title = NULL;
|
to_qfl->qf_title = NULL;
|
||||||
|
|
||||||
|
if (from_qfl->qf_ctx != NULL) {
|
||||||
|
to_qfl->qf_ctx = xcalloc(1, sizeof(typval_T));
|
||||||
|
tv_copy(from_qfl->qf_ctx, to_qfl->qf_ctx);
|
||||||
|
} else {
|
||||||
|
to_qfl->qf_ctx = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
if (from_qfl->qf_count) {
|
if (from_qfl->qf_count) {
|
||||||
qfline_T *from_qfp;
|
qfline_T *from_qfp;
|
||||||
qfline_T *prevp;
|
qfline_T *prevp;
|
||||||
@@ -2385,12 +2421,21 @@ static void qf_free(qf_info_T *qi, int idx)
|
|||||||
qi->qf_lists[idx].qf_start = NULL;
|
qi->qf_lists[idx].qf_start = NULL;
|
||||||
qi->qf_lists[idx].qf_ptr = NULL;
|
qi->qf_lists[idx].qf_ptr = NULL;
|
||||||
qi->qf_lists[idx].qf_title = NULL;
|
qi->qf_lists[idx].qf_title = NULL;
|
||||||
|
tv_free(qi->qf_lists[idx].qf_ctx);
|
||||||
|
qi->qf_lists[idx].qf_ctx = NULL;
|
||||||
qi->qf_lists[idx].qf_index = 0;
|
qi->qf_lists[idx].qf_index = 0;
|
||||||
|
qi->qf_lists[idx].qf_start = NULL;
|
||||||
|
qi->qf_lists[idx].qf_last = NULL;
|
||||||
|
qi->qf_lists[idx].qf_ptr = NULL;
|
||||||
|
qi->qf_lists[idx].qf_nonevalid = true;
|
||||||
|
|
||||||
qf_clean_dir_stack(&qi->qf_dir_stack);
|
qf_clean_dir_stack(&qi->qf_dir_stack);
|
||||||
qi->qf_directory = NULL;
|
qi->qf_directory = NULL;
|
||||||
qf_clean_dir_stack(&qi->qf_file_stack);
|
qf_clean_dir_stack(&qi->qf_file_stack);
|
||||||
qi->qf_currfile = NULL;
|
qi->qf_currfile = NULL;
|
||||||
|
qi->qf_multiline = false;
|
||||||
|
qi->qf_multiignore = false;
|
||||||
|
qi->qf_multiscan = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -3027,6 +3072,7 @@ void ex_make(exarg_T *eap)
|
|||||||
qf_info_T *qi = &ql_info;
|
qf_info_T *qi = &ql_info;
|
||||||
int res;
|
int res;
|
||||||
char_u *au_name = NULL;
|
char_u *au_name = NULL;
|
||||||
|
char_u *enc = (*curbuf->b_p_menc != NUL) ? curbuf->b_p_menc : p_menc;
|
||||||
|
|
||||||
/* Redirect ":grep" to ":vimgrep" if 'grepprg' is "internal". */
|
/* Redirect ":grep" to ":vimgrep" if 'grepprg' is "internal". */
|
||||||
if (grep_internal(eap->cmdidx)) {
|
if (grep_internal(eap->cmdidx)) {
|
||||||
@@ -3086,11 +3132,11 @@ void ex_make(exarg_T *eap)
|
|||||||
|
|
||||||
res = qf_init(wp, fname, (eap->cmdidx != CMD_make
|
res = qf_init(wp, fname, (eap->cmdidx != CMD_make
|
||||||
&& eap->cmdidx != CMD_lmake) ? p_gefm : p_efm,
|
&& eap->cmdidx != CMD_lmake) ? p_gefm : p_efm,
|
||||||
(eap->cmdidx != CMD_grepadd
|
(eap->cmdidx != CMD_grepadd && eap->cmdidx != CMD_lgrepadd),
|
||||||
&& eap->cmdidx != CMD_lgrepadd),
|
*eap->cmdlinep, enc);
|
||||||
*eap->cmdlinep);
|
if (wp != NULL) {
|
||||||
if (wp != NULL)
|
|
||||||
qi = GET_LOC_LIST(wp);
|
qi = GET_LOC_LIST(wp);
|
||||||
|
}
|
||||||
if (au_name != NULL) {
|
if (au_name != NULL) {
|
||||||
apply_autocmds(EVENT_QUICKFIXCMDPOST, au_name,
|
apply_autocmds(EVENT_QUICKFIXCMDPOST, au_name,
|
||||||
curbuf->b_fname, TRUE, curbuf);
|
curbuf->b_fname, TRUE, curbuf);
|
||||||
@@ -3432,19 +3478,18 @@ void ex_cfile(exarg_T *eap)
|
|||||||
if (*eap->arg != NUL)
|
if (*eap->arg != NUL)
|
||||||
set_string_option_direct((char_u *)"ef", -1, eap->arg, OPT_FREE, 0);
|
set_string_option_direct((char_u *)"ef", -1, eap->arg, OPT_FREE, 0);
|
||||||
|
|
||||||
/*
|
char_u *enc = (*curbuf->b_p_menc != NUL) ? curbuf->b_p_menc : p_menc;
|
||||||
* This function is used by the :cfile, :cgetfile and :caddfile
|
// This function is used by the :cfile, :cgetfile and :caddfile
|
||||||
* commands.
|
// commands.
|
||||||
* :cfile always creates a new quickfix list and jumps to the
|
// :cfile always creates a new quickfix list and jumps to the
|
||||||
* first error.
|
// first error.
|
||||||
* :cgetfile creates a new quickfix list but doesn't jump to the
|
// :cgetfile creates a new quickfix list but doesn't jump to the
|
||||||
* first error.
|
// first error.
|
||||||
* :caddfile adds to an existing quickfix list. If there is no
|
// :caddfile adds to an existing quickfix list. If there is no
|
||||||
* quickfix list then a new list is created.
|
// quickfix list then a new list is created.
|
||||||
*/
|
|
||||||
if (qf_init(wp, p_ef, p_efm, (eap->cmdidx != CMD_caddfile
|
if (qf_init(wp, p_ef, p_efm, (eap->cmdidx != CMD_caddfile
|
||||||
&& eap->cmdidx != CMD_laddfile),
|
&& eap->cmdidx != CMD_laddfile),
|
||||||
*eap->cmdlinep) > 0
|
*eap->cmdlinep, enc) > 0
|
||||||
&& (eap->cmdidx == CMD_cfile
|
&& (eap->cmdidx == CMD_cfile
|
||||||
|| eap->cmdidx == CMD_lfile)) {
|
|| eap->cmdidx == CMD_lfile)) {
|
||||||
if (au_name != NULL)
|
if (au_name != NULL)
|
||||||
@@ -4028,6 +4073,7 @@ enum {
|
|||||||
QF_GETLIST_ITEMS = 0x2,
|
QF_GETLIST_ITEMS = 0x2,
|
||||||
QF_GETLIST_NR = 0x4,
|
QF_GETLIST_NR = 0x4,
|
||||||
QF_GETLIST_WINID = 0x8,
|
QF_GETLIST_WINID = 0x8,
|
||||||
|
QF_GETLIST_CONTEXT = 0x10,
|
||||||
QF_GETLIST_ALL = 0xFF
|
QF_GETLIST_ALL = 0xFF
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -4078,6 +4124,10 @@ int get_errorlist_properties(win_T *wp, dict_T *what, dict_T *retdict)
|
|||||||
flags |= QF_GETLIST_WINID;
|
flags |= QF_GETLIST_WINID;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (tv_dict_find(what, S_LEN("context")) != NULL) {
|
||||||
|
flags |= QF_GETLIST_CONTEXT;
|
||||||
|
}
|
||||||
|
|
||||||
if (flags & QF_GETLIST_TITLE) {
|
if (flags & QF_GETLIST_TITLE) {
|
||||||
char_u *t = qi->qf_lists[qf_idx].qf_title;
|
char_u *t = qi->qf_lists[qf_idx].qf_title;
|
||||||
if (t == NULL) {
|
if (t == NULL) {
|
||||||
@@ -4095,6 +4145,20 @@ int get_errorlist_properties(win_T *wp, dict_T *what, dict_T *retdict)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((status == OK) && (flags & QF_GETLIST_CONTEXT)) {
|
||||||
|
if (qi->qf_lists[qf_idx].qf_ctx != NULL) {
|
||||||
|
di = tv_dict_item_alloc_len(S_LEN("context"));
|
||||||
|
if (di != NULL) {
|
||||||
|
tv_copy(qi->qf_lists[qf_idx].qf_ctx, &di->di_tv);
|
||||||
|
if (tv_dict_add(retdict, di) == FAIL) {
|
||||||
|
tv_dict_item_free(di);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
status = tv_dict_add_str(retdict, S_LEN("context"), "");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4158,6 +4222,11 @@ static int qf_add_entries(qf_info_T *qi, list_T *list, char_u *title,
|
|||||||
bufnum = 0;
|
bufnum = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If the 'valid' field is present it overrules the detected value.
|
||||||
|
if (tv_dict_find(d, "valid", -1) != NULL) {
|
||||||
|
valid = (int)tv_dict_get_number(d, "valid");
|
||||||
|
}
|
||||||
|
|
||||||
int status = qf_add_entry(qi,
|
int status = qf_add_entry(qi,
|
||||||
NULL, // dir
|
NULL, // dir
|
||||||
(char_u *)filename,
|
(char_u *)filename,
|
||||||
@@ -4213,7 +4282,10 @@ static int qf_set_properties(qf_info_T *qi, dict_T *what, int action)
|
|||||||
if ((di = tv_dict_find(what, S_LEN("nr"))) != NULL) {
|
if ((di = tv_dict_find(what, S_LEN("nr"))) != NULL) {
|
||||||
// Use the specified quickfix/location list
|
// Use the specified quickfix/location list
|
||||||
if (di->di_tv.v_type == VAR_NUMBER) {
|
if (di->di_tv.v_type == VAR_NUMBER) {
|
||||||
qf_idx = (int)di->di_tv.vval.v_number - 1;
|
// for zero use the current list
|
||||||
|
if (di->di_tv.vval.v_number != 0) {
|
||||||
|
qf_idx = (int)di->di_tv.vval.v_number - 1;
|
||||||
|
}
|
||||||
if (qf_idx < 0 || qf_idx >= qi->qf_listcount) {
|
if (qf_idx < 0 || qf_idx >= qi->qf_listcount) {
|
||||||
return FAIL;
|
return FAIL;
|
||||||
}
|
}
|
||||||
@@ -4240,9 +4312,75 @@ static int qf_set_properties(qf_info_T *qi, dict_T *what, int action)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((di = tv_dict_find(what, S_LEN("context"))) != NULL) {
|
||||||
|
tv_free(qi->qf_lists[qf_idx].qf_ctx);
|
||||||
|
|
||||||
|
typval_T *ctx = xcalloc(1, sizeof(typval_T));
|
||||||
|
tv_copy(&di->di_tv, ctx);
|
||||||
|
qi->qf_lists[qf_idx].qf_ctx = ctx;
|
||||||
|
}
|
||||||
|
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Find the non-location list window with the specified location list.
|
||||||
|
static win_T * find_win_with_ll(qf_info_T *qi)
|
||||||
|
{
|
||||||
|
FOR_ALL_WINDOWS_IN_TAB(wp, curtab) {
|
||||||
|
if ((wp->w_llist == qi) && !bt_quickfix(wp->w_buffer)) {
|
||||||
|
return wp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Free the entire quickfix/location list stack.
|
||||||
|
// If the quickfix/location list window is open, then clear it.
|
||||||
|
static void qf_free_stack(win_T *wp, qf_info_T *qi)
|
||||||
|
{
|
||||||
|
win_T *qfwin = qf_find_win(qi);
|
||||||
|
|
||||||
|
if (qfwin != NULL) {
|
||||||
|
// If the quickfix/location list window is open, then clear it
|
||||||
|
if (qi->qf_curlist < qi->qf_listcount) {
|
||||||
|
qf_free(qi, qi->qf_curlist);
|
||||||
|
}
|
||||||
|
qf_update_buffer(qi, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
win_T *llwin = NULL;
|
||||||
|
win_T *orig_wp = wp;
|
||||||
|
if (wp != NULL && IS_LL_WINDOW(wp)) {
|
||||||
|
// If in the location list window, then use the non-location list
|
||||||
|
// window with this location list (if present)
|
||||||
|
llwin = find_win_with_ll(qi);
|
||||||
|
if (llwin != NULL) {
|
||||||
|
wp = llwin;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
qf_free_all(wp);
|
||||||
|
if (wp == NULL) {
|
||||||
|
// quickfix list
|
||||||
|
qi->qf_curlist = 0;
|
||||||
|
qi->qf_listcount = 0;
|
||||||
|
} else if (IS_LL_WINDOW(orig_wp)) {
|
||||||
|
// If the location list window is open, then create a new empty location
|
||||||
|
// list
|
||||||
|
qf_info_T *new_ll = ll_new_list();
|
||||||
|
|
||||||
|
// first free the list reference in the location list window
|
||||||
|
ll_free_all(&orig_wp->w_llist_ref);
|
||||||
|
|
||||||
|
orig_wp->w_llist_ref = new_ll;
|
||||||
|
if (llwin != NULL) {
|
||||||
|
llwin->w_llist = new_ll;
|
||||||
|
new_ll->qf_refcount++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Populate the quickfix list with the items supplied in the list
|
// Populate the quickfix list with the items supplied in the list
|
||||||
// of dictionaries. "title" will be copied to w:quickfix_title
|
// of dictionaries. "title" will be copied to w:quickfix_title
|
||||||
// "action" is 'a' for add, 'r' for replace. Otherwise create a new list.
|
// "action" is 'a' for add, 'r' for replace. Otherwise create a new list.
|
||||||
@@ -4256,7 +4394,10 @@ int set_errorlist(win_T *wp, list_T *list, int action, char_u *title,
|
|||||||
qi = ll_get_or_alloc_list(wp);
|
qi = ll_get_or_alloc_list(wp);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (what != NULL) {
|
if (action == 'f') {
|
||||||
|
// Free the entire quickfix or location list stack
|
||||||
|
qf_free_stack(wp, qi);
|
||||||
|
} else if (what != NULL) {
|
||||||
retval = qf_set_properties(qi, what, action);
|
retval = qf_set_properties(qi, what, action);
|
||||||
} else {
|
} else {
|
||||||
retval = qf_add_entries(qi, list, title, action);
|
retval = qf_add_entries(qi, list, title, action);
|
||||||
@@ -4265,6 +4406,42 @@ int set_errorlist(win_T *wp, list_T *list, int action, char_u *title,
|
|||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool mark_quickfix_ctx(qf_info_T *qi, int copyID)
|
||||||
|
{
|
||||||
|
bool abort = false;
|
||||||
|
|
||||||
|
for (int i = 0; i < LISTCOUNT && !abort; i++) {
|
||||||
|
typval_T *ctx = qi->qf_lists[i].qf_ctx;
|
||||||
|
if (ctx != NULL && ctx->v_type != VAR_NUMBER
|
||||||
|
&& ctx->v_type != VAR_STRING && ctx->v_type != VAR_FLOAT) {
|
||||||
|
abort = set_ref_in_item(ctx, copyID, NULL, NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return abort;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Mark the context of the quickfix list and the location lists (if present) as
|
||||||
|
/// "in use". So that garabage collection doesn't free the context.
|
||||||
|
bool set_ref_in_quickfix(int copyID)
|
||||||
|
{
|
||||||
|
bool abort = mark_quickfix_ctx(&ql_info, copyID);
|
||||||
|
if (abort) {
|
||||||
|
return abort;
|
||||||
|
}
|
||||||
|
|
||||||
|
FOR_ALL_TAB_WINDOWS(tp, win) {
|
||||||
|
if (win->w_llist != NULL) {
|
||||||
|
abort = mark_quickfix_ctx(win->w_llist, copyID);
|
||||||
|
if (abort) {
|
||||||
|
return abort;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return abort;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ":[range]cbuffer [bufnr]" command.
|
* ":[range]cbuffer [bufnr]" command.
|
||||||
* ":[range]caddbuffer [bufnr]" command.
|
* ":[range]caddbuffer [bufnr]" command.
|
||||||
@@ -4342,7 +4519,7 @@ void ex_cbuffer(exarg_T *eap)
|
|||||||
if (qf_init_ext(qi, NULL, buf, NULL, p_efm,
|
if (qf_init_ext(qi, NULL, buf, NULL, p_efm,
|
||||||
(eap->cmdidx != CMD_caddbuffer
|
(eap->cmdidx != CMD_caddbuffer
|
||||||
&& eap->cmdidx != CMD_laddbuffer),
|
&& eap->cmdidx != CMD_laddbuffer),
|
||||||
eap->line1, eap->line2, qf_title) > 0) {
|
eap->line1, eap->line2, qf_title, NULL) > 0) {
|
||||||
if (au_name != NULL) {
|
if (au_name != NULL) {
|
||||||
apply_autocmds(EVENT_QUICKFIXCMDPOST, (char_u *)au_name,
|
apply_autocmds(EVENT_QUICKFIXCMDPOST, (char_u *)au_name,
|
||||||
curbuf->b_fname, true, curbuf);
|
curbuf->b_fname, true, curbuf);
|
||||||
@@ -4407,7 +4584,7 @@ void ex_cexpr(exarg_T *eap)
|
|||||||
if (qf_init_ext(qi, NULL, NULL, &tv, p_efm,
|
if (qf_init_ext(qi, NULL, NULL, &tv, p_efm,
|
||||||
(eap->cmdidx != CMD_caddexpr
|
(eap->cmdidx != CMD_caddexpr
|
||||||
&& eap->cmdidx != CMD_laddexpr),
|
&& eap->cmdidx != CMD_laddexpr),
|
||||||
(linenr_T)0, (linenr_T)0, *eap->cmdlinep) > 0) {
|
(linenr_T)0, (linenr_T)0, *eap->cmdlinep, NULL) > 0) {
|
||||||
if (au_name != NULL) {
|
if (au_name != NULL) {
|
||||||
apply_autocmds(EVENT_QUICKFIXCMDPOST, (char_u *)au_name,
|
apply_autocmds(EVENT_QUICKFIXCMDPOST, (char_u *)au_name,
|
||||||
curbuf->b_fname, true, curbuf);
|
curbuf->b_fname, true, curbuf);
|
||||||
@@ -4478,6 +4655,9 @@ void ex_helpgrep(exarg_T *eap)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Autocommands may change the list. Save it for later comparison
|
||||||
|
qf_info_T *save_qi = qi;
|
||||||
|
|
||||||
regmatch.regprog = vim_regcomp(eap->arg, RE_MAGIC + RE_STRING);
|
regmatch.regprog = vim_regcomp(eap->arg, RE_MAGIC + RE_STRING);
|
||||||
regmatch.rm_ic = FALSE;
|
regmatch.rm_ic = FALSE;
|
||||||
if (regmatch.regprog != NULL) {
|
if (regmatch.regprog != NULL) {
|
||||||
@@ -4590,10 +4770,11 @@ void ex_helpgrep(exarg_T *eap)
|
|||||||
|
|
||||||
if (au_name != NULL) {
|
if (au_name != NULL) {
|
||||||
apply_autocmds(EVENT_QUICKFIXCMDPOST, au_name,
|
apply_autocmds(EVENT_QUICKFIXCMDPOST, au_name,
|
||||||
curbuf->b_fname, TRUE, curbuf);
|
curbuf->b_fname, true, curbuf);
|
||||||
if (!new_qi && qi != &ql_info && qf_find_buf(qi) == NULL)
|
if (!new_qi && qi != save_qi && qf_find_buf(qi) == NULL) {
|
||||||
/* autocommands made "qi" invalid */
|
// autocommands made "qi" invalid
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Jump to first match. */
|
/* Jump to first match. */
|
||||||
|
@@ -65,6 +65,7 @@ NEW_TESTS ?= \
|
|||||||
test_increment_dbcs.res \
|
test_increment_dbcs.res \
|
||||||
test_lambda.res \
|
test_lambda.res \
|
||||||
test_langmap.res \
|
test_langmap.res \
|
||||||
|
test_makeencoding.res \
|
||||||
test_marks.res \
|
test_marks.res \
|
||||||
test_match.res \
|
test_match.res \
|
||||||
test_matchadd_conceal.res \
|
test_matchadd_conceal.res \
|
||||||
|
67
src/nvim/testdir/test_makeencoding.py
Normal file
67
src/nvim/testdir/test_makeencoding.py
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
#!/usr/bin/python
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
# Test program for :make, :grep and :cgetfile.
|
||||||
|
|
||||||
|
from __future__ import print_function, unicode_literals
|
||||||
|
import locale
|
||||||
|
import io
|
||||||
|
import sys
|
||||||
|
|
||||||
|
def set_output_encoding(enc=None):
|
||||||
|
"""Set the encoding of stdout and stderr
|
||||||
|
|
||||||
|
arguments:
|
||||||
|
enc -- Encoding name.
|
||||||
|
If omitted, locale.getpreferredencoding() is used.
|
||||||
|
"""
|
||||||
|
if enc is None:
|
||||||
|
enc = locale.getpreferredencoding()
|
||||||
|
|
||||||
|
def get_text_writer(fo, **kwargs):
|
||||||
|
kw = dict(kwargs)
|
||||||
|
kw.setdefault('errors', 'backslashreplace') # use \uXXXX style
|
||||||
|
kw.setdefault('closefd', False)
|
||||||
|
|
||||||
|
if sys.version_info[0] < 3:
|
||||||
|
# Work around for Python 2.x
|
||||||
|
# New line conversion isn't needed here. Done in somewhere else.
|
||||||
|
writer = io.open(fo.fileno(), mode='w', newline='', **kw)
|
||||||
|
write = writer.write # save the original write() function
|
||||||
|
enc = locale.getpreferredencoding()
|
||||||
|
def convwrite(s):
|
||||||
|
if isinstance(s, bytes):
|
||||||
|
write(s.decode(enc)) # convert to unistr
|
||||||
|
else:
|
||||||
|
write(s)
|
||||||
|
try:
|
||||||
|
writer.flush() # needed on Windows
|
||||||
|
except IOError:
|
||||||
|
pass
|
||||||
|
writer.write = convwrite
|
||||||
|
else:
|
||||||
|
writer = io.open(fo.fileno(), mode='w', **kw)
|
||||||
|
return writer
|
||||||
|
|
||||||
|
sys.stdout = get_text_writer(sys.stdout, encoding=enc)
|
||||||
|
sys.stderr = get_text_writer(sys.stderr, encoding=enc)
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
enc = 'utf-8'
|
||||||
|
if len(sys.argv) > 1:
|
||||||
|
enc = sys.argv[1]
|
||||||
|
set_output_encoding(enc)
|
||||||
|
|
||||||
|
message_tbl = {
|
||||||
|
'utf-8': 'ÀÈÌÒÙ こんにちは 你好',
|
||||||
|
'latin1': 'ÀÈÌÒÙ',
|
||||||
|
'cp932': 'こんにちは',
|
||||||
|
'cp936': '你好',
|
||||||
|
}
|
||||||
|
|
||||||
|
print('Xfoobar.c(10) : %s (%s)' % (message_tbl[enc], enc))
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
106
src/nvim/testdir/test_makeencoding.vim
Normal file
106
src/nvim/testdir/test_makeencoding.vim
Normal file
@@ -0,0 +1,106 @@
|
|||||||
|
" Tests for 'makeencoding'.
|
||||||
|
if !has('multi_byte')
|
||||||
|
finish
|
||||||
|
endif
|
||||||
|
|
||||||
|
source shared.vim
|
||||||
|
|
||||||
|
let s:python = PythonProg()
|
||||||
|
if s:python == ''
|
||||||
|
" Can't run this test.
|
||||||
|
finish
|
||||||
|
endif
|
||||||
|
|
||||||
|
let s:script = 'test_makeencoding.py'
|
||||||
|
|
||||||
|
let s:message_tbl = {
|
||||||
|
\ 'utf-8': 'ÀÈÌÒÙ こんにちは 你好',
|
||||||
|
\ 'latin1': 'ÀÈÌÒÙ',
|
||||||
|
\ 'cp932': 'こんにちは',
|
||||||
|
\ 'cp936': '你好',
|
||||||
|
\}
|
||||||
|
|
||||||
|
|
||||||
|
" Tests for :cgetfile and :lgetfile.
|
||||||
|
func Test_getfile()
|
||||||
|
set errorfile=Xerror.txt
|
||||||
|
set errorformat=%f(%l)\ :\ %m
|
||||||
|
|
||||||
|
" :cgetfile
|
||||||
|
for enc in keys(s:message_tbl)
|
||||||
|
let &makeencoding = enc
|
||||||
|
exec "silent !" . s:python . " " . s:script . " " . enc . " > " . &errorfile
|
||||||
|
cgetfile
|
||||||
|
copen
|
||||||
|
call assert_equal("Xfoobar.c|10| " . s:message_tbl[enc] . " (" . enc . ")",
|
||||||
|
\ getline('.'))
|
||||||
|
cclose
|
||||||
|
endfor
|
||||||
|
|
||||||
|
" :lgetfile
|
||||||
|
for enc in keys(s:message_tbl)
|
||||||
|
let &makeencoding = enc
|
||||||
|
exec "silent !" . s:python . " " . s:script . " " . enc . " > " . &errorfile
|
||||||
|
lgetfile
|
||||||
|
lopen
|
||||||
|
call assert_equal("Xfoobar.c|10| " . s:message_tbl[enc] . " (" . enc . ")",
|
||||||
|
\ getline('.'))
|
||||||
|
lclose
|
||||||
|
endfor
|
||||||
|
|
||||||
|
call delete(&errorfile)
|
||||||
|
endfunc
|
||||||
|
|
||||||
|
|
||||||
|
" Tests for :grep and :lgrep.
|
||||||
|
func Test_grep()
|
||||||
|
let &grepprg = s:python
|
||||||
|
set grepformat=%f(%l)\ :\ %m
|
||||||
|
|
||||||
|
" :grep
|
||||||
|
for enc in keys(s:message_tbl)
|
||||||
|
let &makeencoding = enc
|
||||||
|
exec "silent grep! " . s:script . " " . enc
|
||||||
|
copen
|
||||||
|
call assert_equal("Xfoobar.c|10| " . s:message_tbl[enc] . " (" . enc . ")",
|
||||||
|
\ getline('.'))
|
||||||
|
cclose
|
||||||
|
endfor
|
||||||
|
|
||||||
|
" :lgrep
|
||||||
|
for enc in keys(s:message_tbl)
|
||||||
|
let &makeencoding = enc
|
||||||
|
exec "silent lgrep! " . s:script . " " . enc
|
||||||
|
lopen
|
||||||
|
call assert_equal("Xfoobar.c|10| " . s:message_tbl[enc] . " (" . enc . ")",
|
||||||
|
\ getline('.'))
|
||||||
|
lclose
|
||||||
|
endfor
|
||||||
|
endfunc
|
||||||
|
|
||||||
|
|
||||||
|
" Tests for :make and :lmake.
|
||||||
|
func Test_make()
|
||||||
|
let &makeprg = s:python
|
||||||
|
set errorformat=%f(%l)\ :\ %m
|
||||||
|
|
||||||
|
" :make
|
||||||
|
for enc in keys(s:message_tbl)
|
||||||
|
let &makeencoding = enc
|
||||||
|
exec "silent make! " . s:script . " " . enc
|
||||||
|
copen
|
||||||
|
call assert_equal("Xfoobar.c|10| " . s:message_tbl[enc] . " (" . enc . ")",
|
||||||
|
\ getline('.'))
|
||||||
|
cclose
|
||||||
|
endfor
|
||||||
|
|
||||||
|
" :lmake
|
||||||
|
for enc in keys(s:message_tbl)
|
||||||
|
let &makeencoding = enc
|
||||||
|
exec "silent lmake! " . s:script . " " . enc
|
||||||
|
lopen
|
||||||
|
call assert_equal("Xfoobar.c|10| " . s:message_tbl[enc] . " (" . enc . ")",
|
||||||
|
\ getline('.'))
|
||||||
|
lclose
|
||||||
|
endfor
|
||||||
|
endfunc
|
@@ -24,19 +24,21 @@ func s:setup_commands(cchar)
|
|||||||
command! -nargs=* Xgetbuffer <mods>cgetbuffer <args>
|
command! -nargs=* Xgetbuffer <mods>cgetbuffer <args>
|
||||||
command! -nargs=* Xaddbuffer <mods>caddbuffer <args>
|
command! -nargs=* Xaddbuffer <mods>caddbuffer <args>
|
||||||
command! -nargs=* Xrewind <mods>crewind <args>
|
command! -nargs=* Xrewind <mods>crewind <args>
|
||||||
command! -nargs=* -bang Xnext <mods>cnext<bang> <args>
|
command! -count -nargs=* -bang Xnext <mods><count>cnext<bang> <args>
|
||||||
command! -nargs=* -bang Xprev <mods>cprev<bang> <args>
|
command! -count -nargs=* -bang Xprev <mods><count>cprev<bang> <args>
|
||||||
command! -nargs=* -bang Xfirst <mods>cfirst<bang> <args>
|
command! -nargs=* -bang Xfirst <mods>cfirst<bang> <args>
|
||||||
command! -nargs=* -bang Xlast <mods>clast<bang> <args>
|
command! -nargs=* -bang Xlast <mods>clast<bang> <args>
|
||||||
command! -nargs=* -bang Xnfile <mods>cnfile<bang> <args>
|
command! -nargs=* -bang Xnfile <mods>cnfile<bang> <args>
|
||||||
command! -nargs=* -bang Xpfile <mods>cpfile<bang> <args>
|
command! -nargs=* -bang Xpfile <mods>cpfile<bang> <args>
|
||||||
command! -nargs=* Xexpr <mods>cexpr <args>
|
command! -nargs=* Xexpr <mods>cexpr <args>
|
||||||
command! -nargs=* Xvimgrep <mods>vimgrep <args>
|
command! -range -nargs=* Xvimgrep <mods><count>vimgrep <args>
|
||||||
|
command! -nargs=* Xvimgrepadd <mods>vimgrepadd <args>
|
||||||
command! -nargs=* Xgrep <mods> grep <args>
|
command! -nargs=* Xgrep <mods> grep <args>
|
||||||
command! -nargs=* Xgrepadd <mods> grepadd <args>
|
command! -nargs=* Xgrepadd <mods> grepadd <args>
|
||||||
command! -nargs=* Xhelpgrep helpgrep <args>
|
command! -nargs=* Xhelpgrep helpgrep <args>
|
||||||
let g:Xgetlist = function('getqflist')
|
let g:Xgetlist = function('getqflist')
|
||||||
let g:Xsetlist = function('setqflist')
|
let g:Xsetlist = function('setqflist')
|
||||||
|
call setqflist([], 'f')
|
||||||
else
|
else
|
||||||
command! -nargs=* -bang Xlist <mods>llist<bang> <args>
|
command! -nargs=* -bang Xlist <mods>llist<bang> <args>
|
||||||
command! -nargs=* Xgetexpr <mods>lgetexpr <args>
|
command! -nargs=* Xgetexpr <mods>lgetexpr <args>
|
||||||
@@ -54,19 +56,21 @@ func s:setup_commands(cchar)
|
|||||||
command! -nargs=* Xgetbuffer <mods>lgetbuffer <args>
|
command! -nargs=* Xgetbuffer <mods>lgetbuffer <args>
|
||||||
command! -nargs=* Xaddbuffer <mods>laddbuffer <args>
|
command! -nargs=* Xaddbuffer <mods>laddbuffer <args>
|
||||||
command! -nargs=* Xrewind <mods>lrewind <args>
|
command! -nargs=* Xrewind <mods>lrewind <args>
|
||||||
command! -nargs=* -bang Xnext <mods>lnext<bang> <args>
|
command! -count -nargs=* -bang Xnext <mods><count>lnext<bang> <args>
|
||||||
command! -nargs=* -bang Xprev <mods>lprev<bang> <args>
|
command! -count -nargs=* -bang Xprev <mods><count>lprev<bang> <args>
|
||||||
command! -nargs=* -bang Xfirst <mods>lfirst<bang> <args>
|
command! -nargs=* -bang Xfirst <mods>lfirst<bang> <args>
|
||||||
command! -nargs=* -bang Xlast <mods>llast<bang> <args>
|
command! -nargs=* -bang Xlast <mods>llast<bang> <args>
|
||||||
command! -nargs=* -bang Xnfile <mods>lnfile<bang> <args>
|
command! -nargs=* -bang Xnfile <mods>lnfile<bang> <args>
|
||||||
command! -nargs=* -bang Xpfile <mods>lpfile<bang> <args>
|
command! -nargs=* -bang Xpfile <mods>lpfile<bang> <args>
|
||||||
command! -nargs=* Xexpr <mods>lexpr <args>
|
command! -nargs=* Xexpr <mods>lexpr <args>
|
||||||
command! -nargs=* Xvimgrep <mods>lvimgrep <args>
|
command! -range -nargs=* Xvimgrep <mods><count>lvimgrep <args>
|
||||||
|
command! -nargs=* Xvimgrepadd <mods>lvimgrepadd <args>
|
||||||
command! -nargs=* Xgrep <mods> lgrep <args>
|
command! -nargs=* Xgrep <mods> lgrep <args>
|
||||||
command! -nargs=* Xgrepadd <mods> lgrepadd <args>
|
command! -nargs=* Xgrepadd <mods> lgrepadd <args>
|
||||||
command! -nargs=* Xhelpgrep lhelpgrep <args>
|
command! -nargs=* Xhelpgrep lhelpgrep <args>
|
||||||
let g:Xgetlist = function('getloclist', [0])
|
let g:Xgetlist = function('getloclist', [0])
|
||||||
let g:Xsetlist = function('setloclist', [0])
|
let g:Xsetlist = function('setloclist', [0])
|
||||||
|
call setloclist(0, [], 'f')
|
||||||
endif
|
endif
|
||||||
endfunc
|
endfunc
|
||||||
|
|
||||||
@@ -74,6 +78,9 @@ endfunc
|
|||||||
func XlistTests(cchar)
|
func XlistTests(cchar)
|
||||||
call s:setup_commands(a:cchar)
|
call s:setup_commands(a:cchar)
|
||||||
|
|
||||||
|
if a:cchar == 'l'
|
||||||
|
call assert_fails('llist', 'E776:')
|
||||||
|
endif
|
||||||
" With an empty list, command should return error
|
" With an empty list, command should return error
|
||||||
Xgetexpr []
|
Xgetexpr []
|
||||||
silent! Xlist
|
silent! Xlist
|
||||||
@@ -85,49 +92,52 @@ func XlistTests(cchar)
|
|||||||
\ 'non-error 3', 'Xtestfile3:3:1:Line3']
|
\ 'non-error 3', 'Xtestfile3:3:1:Line3']
|
||||||
|
|
||||||
" List only valid entries
|
" List only valid entries
|
||||||
redir => result
|
let l = split(execute('Xlist', ''), "\n")
|
||||||
Xlist
|
|
||||||
redir END
|
|
||||||
let l = split(result, "\n")
|
|
||||||
call assert_equal([' 2 Xtestfile1:1 col 3: Line1',
|
call assert_equal([' 2 Xtestfile1:1 col 3: Line1',
|
||||||
\ ' 4 Xtestfile2:2 col 2: Line2',
|
\ ' 4 Xtestfile2:2 col 2: Line2',
|
||||||
\ ' 6 Xtestfile3:3 col 1: Line3'], l)
|
\ ' 6 Xtestfile3:3 col 1: Line3'], l)
|
||||||
|
|
||||||
" List all the entries
|
" List all the entries
|
||||||
redir => result
|
let l = split(execute('Xlist!', ''), "\n")
|
||||||
Xlist!
|
|
||||||
redir END
|
|
||||||
let l = split(result, "\n")
|
|
||||||
call assert_equal([' 1: non-error 1', ' 2 Xtestfile1:1 col 3: Line1',
|
call assert_equal([' 1: non-error 1', ' 2 Xtestfile1:1 col 3: Line1',
|
||||||
\ ' 3: non-error 2', ' 4 Xtestfile2:2 col 2: Line2',
|
\ ' 3: non-error 2', ' 4 Xtestfile2:2 col 2: Line2',
|
||||||
\ ' 5: non-error 3', ' 6 Xtestfile3:3 col 1: Line3'], l)
|
\ ' 5: non-error 3', ' 6 Xtestfile3:3 col 1: Line3'], l)
|
||||||
|
|
||||||
" List a range of errors
|
" List a range of errors
|
||||||
redir => result
|
let l = split(execute('Xlist 3,6', ''), "\n")
|
||||||
Xlist 3,6
|
|
||||||
redir END
|
|
||||||
let l = split(result, "\n")
|
|
||||||
call assert_equal([' 4 Xtestfile2:2 col 2: Line2',
|
call assert_equal([' 4 Xtestfile2:2 col 2: Line2',
|
||||||
\ ' 6 Xtestfile3:3 col 1: Line3'], l)
|
\ ' 6 Xtestfile3:3 col 1: Line3'], l)
|
||||||
|
|
||||||
redir => result
|
let l = split(execute('Xlist! 3,4', ''), "\n")
|
||||||
Xlist! 3,4
|
|
||||||
redir END
|
|
||||||
let l = split(result, "\n")
|
|
||||||
call assert_equal([' 3: non-error 2', ' 4 Xtestfile2:2 col 2: Line2'], l)
|
call assert_equal([' 3: non-error 2', ' 4 Xtestfile2:2 col 2: Line2'], l)
|
||||||
|
|
||||||
redir => result
|
let l = split(execute('Xlist -6,-4', ''), "\n")
|
||||||
Xlist -6,-4
|
|
||||||
redir END
|
|
||||||
let l = split(result, "\n")
|
|
||||||
call assert_equal([' 2 Xtestfile1:1 col 3: Line1'], l)
|
call assert_equal([' 2 Xtestfile1:1 col 3: Line1'], l)
|
||||||
|
|
||||||
redir => result
|
let l = split(execute('Xlist! -5,-3', ''), "\n")
|
||||||
Xlist! -5,-3
|
|
||||||
redir END
|
|
||||||
let l = split(result, "\n")
|
|
||||||
call assert_equal([' 2 Xtestfile1:1 col 3: Line1',
|
call assert_equal([' 2 Xtestfile1:1 col 3: Line1',
|
||||||
\ ' 3: non-error 2', ' 4 Xtestfile2:2 col 2: Line2'], l)
|
\ ' 3: non-error 2', ' 4 Xtestfile2:2 col 2: Line2'], l)
|
||||||
|
|
||||||
|
" Test for '+'
|
||||||
|
let l = split(execute('Xlist! +2', ''), "\n")
|
||||||
|
call assert_equal([' 2 Xtestfile1:1 col 3: Line1',
|
||||||
|
\ ' 3: non-error 2', ' 4 Xtestfile2:2 col 2: Line2'], l)
|
||||||
|
|
||||||
|
" Different types of errors
|
||||||
|
call g:Xsetlist([{'lnum':10,'col':5,'type':'W', 'text':'Warning','nr':11},
|
||||||
|
\ {'lnum':20,'col':10,'type':'e','text':'Error','nr':22},
|
||||||
|
\ {'lnum':30,'col':15,'type':'i','text':'Info','nr':33},
|
||||||
|
\ {'lnum':40,'col':20,'type':'x', 'text':'Other','nr':44},
|
||||||
|
\ {'lnum':50,'col':25,'type':"\<C-A>",'text':'one','nr':55}])
|
||||||
|
let l = split(execute('Xlist', ""), "\n")
|
||||||
|
call assert_equal([' 1:10 col 5 warning 11: Warning',
|
||||||
|
\ ' 2:20 col 10 error 22: Error',
|
||||||
|
\ ' 3:30 col 15 info 33: Info',
|
||||||
|
\ ' 4:40 col 20 x 44: Other',
|
||||||
|
\ ' 5:50 col 25 55: one'], l)
|
||||||
|
|
||||||
|
" Error cases
|
||||||
|
call assert_fails('Xlist abc', 'E488:')
|
||||||
endfunc
|
endfunc
|
||||||
|
|
||||||
func Test_clist()
|
func Test_clist()
|
||||||
@@ -141,6 +151,9 @@ endfunc
|
|||||||
func XageTests(cchar)
|
func XageTests(cchar)
|
||||||
call s:setup_commands(a:cchar)
|
call s:setup_commands(a:cchar)
|
||||||
|
|
||||||
|
let list = [{'bufnr': 1, 'lnum': 1}]
|
||||||
|
call g:Xsetlist(list)
|
||||||
|
|
||||||
" Jumping to a non existent list should return error
|
" Jumping to a non existent list should return error
|
||||||
silent! Xolder 99
|
silent! Xolder 99
|
||||||
call assert_true(v:errmsg ==# 'E380: At bottom of quickfix stack')
|
call assert_true(v:errmsg ==# 'E380: At bottom of quickfix stack')
|
||||||
@@ -174,11 +187,7 @@ func XageTests(cchar)
|
|||||||
endfunc
|
endfunc
|
||||||
|
|
||||||
func Test_cage()
|
func Test_cage()
|
||||||
let list = [{'bufnr': 1, 'lnum': 1}]
|
|
||||||
call setqflist(list)
|
|
||||||
call XageTests('c')
|
call XageTests('c')
|
||||||
|
|
||||||
call setloclist(0, list)
|
|
||||||
call XageTests('l')
|
call XageTests('l')
|
||||||
endfunc
|
endfunc
|
||||||
|
|
||||||
@@ -187,6 +196,11 @@ endfunc
|
|||||||
func XwindowTests(cchar)
|
func XwindowTests(cchar)
|
||||||
call s:setup_commands(a:cchar)
|
call s:setup_commands(a:cchar)
|
||||||
|
|
||||||
|
" Opening the location list window without any errors should fail
|
||||||
|
if a:cchar == 'l'
|
||||||
|
call assert_fails('lopen', 'E776:')
|
||||||
|
endif
|
||||||
|
|
||||||
" Create a list with no valid entries
|
" Create a list with no valid entries
|
||||||
Xgetexpr ['non-error 1', 'non-error 2', 'non-error 3']
|
Xgetexpr ['non-error 1', 'non-error 2', 'non-error 3']
|
||||||
|
|
||||||
@@ -227,6 +241,19 @@ func XwindowTests(cchar)
|
|||||||
" Calling cwindow should close the quickfix window with no valid errors
|
" Calling cwindow should close the quickfix window with no valid errors
|
||||||
Xwindow
|
Xwindow
|
||||||
call assert_true(winnr('$') == 1)
|
call assert_true(winnr('$') == 1)
|
||||||
|
|
||||||
|
if a:cchar == 'c'
|
||||||
|
" Opening the quickfix window in multiple tab pages should reuse the
|
||||||
|
" quickfix buffer
|
||||||
|
Xgetexpr ['Xtestfile1:1:3:Line1', 'Xtestfile2:2:2:Line2',
|
||||||
|
\ 'Xtestfile3:3:1:Line3']
|
||||||
|
Xopen
|
||||||
|
let qfbufnum = bufnr('%')
|
||||||
|
tabnew
|
||||||
|
Xopen
|
||||||
|
call assert_equal(qfbufnum, bufnr('%'))
|
||||||
|
new | only | tabonly
|
||||||
|
endif
|
||||||
endfunc
|
endfunc
|
||||||
|
|
||||||
func Test_cwindow()
|
func Test_cwindow()
|
||||||
@@ -316,6 +343,23 @@ func XbufferTests(cchar)
|
|||||||
\ l[3].lnum == 750 && l[3].col == 25 && l[3].text ==# 'Line 750')
|
\ l[3].lnum == 750 && l[3].col == 25 && l[3].text ==# 'Line 750')
|
||||||
enew!
|
enew!
|
||||||
|
|
||||||
|
" Check for invalid buffer
|
||||||
|
call assert_fails('Xbuffer 199', 'E474:')
|
||||||
|
|
||||||
|
" Check for unloaded buffer
|
||||||
|
edit Xtestfile1
|
||||||
|
let bnr = bufnr('%')
|
||||||
|
enew!
|
||||||
|
call assert_fails('Xbuffer ' . bnr, 'E681:')
|
||||||
|
|
||||||
|
" Check for invalid range
|
||||||
|
" Using Xbuffer will not run the range check in the cbuffer/lbuffer
|
||||||
|
" commands. So directly call the commands.
|
||||||
|
if (a:cchar == 'c')
|
||||||
|
call assert_fails('900,999cbuffer', 'E16:')
|
||||||
|
else
|
||||||
|
call assert_fails('900,999lbuffer', 'E16:')
|
||||||
|
endif
|
||||||
endfunc
|
endfunc
|
||||||
|
|
||||||
func Test_cbuffer()
|
func Test_cbuffer()
|
||||||
@@ -338,13 +382,22 @@ endfunc
|
|||||||
func Xtest_browse(cchar)
|
func Xtest_browse(cchar)
|
||||||
call s:setup_commands(a:cchar)
|
call s:setup_commands(a:cchar)
|
||||||
|
|
||||||
|
" Jumping to first or next location list entry without any error should
|
||||||
|
" result in failure
|
||||||
|
if a:cchar == 'l'
|
||||||
|
call assert_fails('lfirst', 'E776:')
|
||||||
|
call assert_fails('lnext', 'E776:')
|
||||||
|
endif
|
||||||
|
|
||||||
call s:create_test_file('Xqftestfile1')
|
call s:create_test_file('Xqftestfile1')
|
||||||
call s:create_test_file('Xqftestfile2')
|
call s:create_test_file('Xqftestfile2')
|
||||||
|
|
||||||
Xgetexpr ['Xqftestfile1:5:Line5',
|
Xgetexpr ['Xqftestfile1:5:Line5',
|
||||||
\ 'Xqftestfile1:6:Line6',
|
\ 'Xqftestfile1:6:Line6',
|
||||||
\ 'Xqftestfile2:10:Line10',
|
\ 'Xqftestfile2:10:Line10',
|
||||||
\ 'Xqftestfile2:11:Line11']
|
\ 'Xqftestfile2:11:Line11',
|
||||||
|
\ 'RegularLine1',
|
||||||
|
\ 'RegularLine2']
|
||||||
|
|
||||||
Xfirst
|
Xfirst
|
||||||
call assert_fails('Xprev', 'E553')
|
call assert_fails('Xprev', 'E553')
|
||||||
@@ -356,6 +409,7 @@ func Xtest_browse(cchar)
|
|||||||
call assert_equal('Xqftestfile1', bufname('%'))
|
call assert_equal('Xqftestfile1', bufname('%'))
|
||||||
call assert_equal(6, line('.'))
|
call assert_equal(6, line('.'))
|
||||||
Xlast
|
Xlast
|
||||||
|
Xprev
|
||||||
call assert_equal('Xqftestfile2', bufname('%'))
|
call assert_equal('Xqftestfile2', bufname('%'))
|
||||||
call assert_equal(11, line('.'))
|
call assert_equal(11, line('.'))
|
||||||
call assert_fails('Xnext', 'E553')
|
call assert_fails('Xnext', 'E553')
|
||||||
@@ -364,6 +418,16 @@ func Xtest_browse(cchar)
|
|||||||
call assert_equal('Xqftestfile1', bufname('%'))
|
call assert_equal('Xqftestfile1', bufname('%'))
|
||||||
call assert_equal(5, line('.'))
|
call assert_equal(5, line('.'))
|
||||||
|
|
||||||
|
10Xnext
|
||||||
|
call assert_equal('Xqftestfile2', bufname('%'))
|
||||||
|
call assert_equal(11, line('.'))
|
||||||
|
10Xprev
|
||||||
|
call assert_equal('Xqftestfile1', bufname('%'))
|
||||||
|
call assert_equal(5, line('.'))
|
||||||
|
|
||||||
|
Xexpr ""
|
||||||
|
call assert_fails('Xnext', 'E42:')
|
||||||
|
|
||||||
call delete('Xqftestfile1')
|
call delete('Xqftestfile1')
|
||||||
call delete('Xqftestfile2')
|
call delete('Xqftestfile2')
|
||||||
endfunc
|
endfunc
|
||||||
@@ -383,8 +447,32 @@ func s:test_xhelpgrep(cchar)
|
|||||||
let title_text = ':lhelpgrep quickfix'
|
let title_text = ':lhelpgrep quickfix'
|
||||||
endif
|
endif
|
||||||
call assert_true(w:quickfix_title =~ title_text, w:quickfix_title)
|
call assert_true(w:quickfix_title =~ title_text, w:quickfix_title)
|
||||||
|
|
||||||
|
" Jumping to a help topic should open the help window
|
||||||
|
only
|
||||||
|
Xnext
|
||||||
|
call assert_true(&buftype == 'help')
|
||||||
|
call assert_true(winnr('$') == 2)
|
||||||
|
" Jumping to the next match should reuse the help window
|
||||||
|
Xnext
|
||||||
|
call assert_true(&buftype == 'help')
|
||||||
|
call assert_true(winnr() == 1)
|
||||||
|
call assert_true(winnr('$') == 2)
|
||||||
|
" Jumping to the next match from the quickfix window should reuse the help
|
||||||
|
" window
|
||||||
|
Xopen
|
||||||
|
Xnext
|
||||||
|
call assert_true(&buftype == 'help')
|
||||||
|
call assert_true(winnr() == 1)
|
||||||
|
call assert_true(winnr('$') == 2)
|
||||||
|
|
||||||
" This wipes out the buffer, make sure that doesn't cause trouble.
|
" This wipes out the buffer, make sure that doesn't cause trouble.
|
||||||
Xclose
|
Xclose
|
||||||
|
|
||||||
|
new | only
|
||||||
|
|
||||||
|
" Search for non existing help string
|
||||||
|
call assert_fails('Xhelpgrep a1b2c3', 'E480:')
|
||||||
endfunc
|
endfunc
|
||||||
|
|
||||||
func Test_helpgrep()
|
func Test_helpgrep()
|
||||||
@@ -521,10 +609,7 @@ func Test_locationlist()
|
|||||||
lrewind
|
lrewind
|
||||||
enew
|
enew
|
||||||
lopen
|
lopen
|
||||||
lnext
|
4lnext
|
||||||
lnext
|
|
||||||
lnext
|
|
||||||
lnext
|
|
||||||
vert split
|
vert split
|
||||||
wincmd L
|
wincmd L
|
||||||
lopen
|
lopen
|
||||||
@@ -578,7 +663,7 @@ func Test_locationlist()
|
|||||||
wincmd n | only
|
wincmd n | only
|
||||||
|
|
||||||
augroup! testgroup
|
augroup! testgroup
|
||||||
endfunc
|
endfunc
|
||||||
|
|
||||||
func Test_locationlist_curwin_was_closed()
|
func Test_locationlist_curwin_was_closed()
|
||||||
augroup testgroup
|
augroup testgroup
|
||||||
@@ -597,7 +682,7 @@ func Test_locationlist_curwin_was_closed()
|
|||||||
call assert_fails('lrewind', 'E924:')
|
call assert_fails('lrewind', 'E924:')
|
||||||
|
|
||||||
augroup! testgroup
|
augroup! testgroup
|
||||||
endfunc
|
endfunc
|
||||||
|
|
||||||
func Test_locationlist_cross_tab_jump()
|
func Test_locationlist_cross_tab_jump()
|
||||||
call writefile(['loclistfoo'], 'loclistfoo')
|
call writefile(['loclistfoo'], 'loclistfoo')
|
||||||
@@ -734,7 +819,7 @@ func Test_efm1()
|
|||||||
call delete('Xerrorfile1')
|
call delete('Xerrorfile1')
|
||||||
call delete('Xerrorfile2')
|
call delete('Xerrorfile2')
|
||||||
call delete('Xtestfile')
|
call delete('Xtestfile')
|
||||||
endfunc
|
endfunc
|
||||||
|
|
||||||
" Test for quickfix directory stack support
|
" Test for quickfix directory stack support
|
||||||
func s:dir_stack_tests(cchar)
|
func s:dir_stack_tests(cchar)
|
||||||
@@ -893,30 +978,44 @@ func Test_efm2()
|
|||||||
call assert_equal(l[0].pattern, '^\VLine search text\$')
|
call assert_equal(l[0].pattern, '^\VLine search text\$')
|
||||||
call assert_equal(l[0].lnum, 0)
|
call assert_equal(l[0].lnum, 0)
|
||||||
|
|
||||||
|
let l = split(execute('clist', ''), "\n")
|
||||||
|
call assert_equal([' 1 Xtestfile:^\VLine search text\$: '], l)
|
||||||
|
|
||||||
" Test for %P, %Q and %t format specifiers
|
" Test for %P, %Q and %t format specifiers
|
||||||
let lines=["[Xtestfile1]",
|
let lines=["[Xtestfile1]",
|
||||||
\ "(1,17) error: ';' missing",
|
\ "(1,17) error: ';' missing",
|
||||||
\ "(21,2) warning: variable 'z' not defined",
|
\ "(21,2) warning: variable 'z' not defined",
|
||||||
\ "(67,3) error: end of file found before string ended",
|
\ "(67,3) error: end of file found before string ended",
|
||||||
|
\ "--",
|
||||||
\ "",
|
\ "",
|
||||||
\ "[Xtestfile2]",
|
\ "[Xtestfile2]",
|
||||||
|
\ "--",
|
||||||
\ "",
|
\ "",
|
||||||
\ "[Xtestfile3]",
|
\ "[Xtestfile3]",
|
||||||
\ "NEW compiler v1.1",
|
\ "NEW compiler v1.1",
|
||||||
\ "(2,2) warning: variable 'x' not defined",
|
\ "(2,2) warning: variable 'x' not defined",
|
||||||
\ "(67,3) warning: 's' already defined"
|
\ "(67,3) warning: 's' already defined",
|
||||||
|
\ "--"
|
||||||
\]
|
\]
|
||||||
set efm=%+P[%f],(%l\\,%c)%*[\ ]%t%*[^:]:\ %m,%-Q
|
set efm=%+P[%f]%r,(%l\\,%c)%*[\ ]%t%*[^:]:\ %m,%+Q--%r
|
||||||
|
" To exercise the push/pop file functionality in quickfix, the test files
|
||||||
|
" need to be created.
|
||||||
|
call writefile(['Line1'], 'Xtestfile1')
|
||||||
|
call writefile(['Line2'], 'Xtestfile2')
|
||||||
|
call writefile(['Line3'], 'Xtestfile3')
|
||||||
cexpr ""
|
cexpr ""
|
||||||
for l in lines
|
for l in lines
|
||||||
caddexpr l
|
caddexpr l
|
||||||
endfor
|
endfor
|
||||||
let l = getqflist()
|
let l = getqflist()
|
||||||
call assert_equal(9, len(l))
|
call assert_equal(12, len(l))
|
||||||
call assert_equal(21, l[2].lnum)
|
call assert_equal(21, l[2].lnum)
|
||||||
call assert_equal(2, l[2].col)
|
call assert_equal(2, l[2].col)
|
||||||
call assert_equal('w', l[2].type)
|
call assert_equal('w', l[2].type)
|
||||||
call assert_equal('e', l[3].type)
|
call assert_equal('e', l[3].type)
|
||||||
|
call delete('Xtestfile1')
|
||||||
|
call delete('Xtestfile2')
|
||||||
|
call delete('Xtestfile3')
|
||||||
|
|
||||||
" Tests for %E, %C and %Z format specifiers
|
" Tests for %E, %C and %Z format specifiers
|
||||||
let lines = ["Error 275",
|
let lines = ["Error 275",
|
||||||
@@ -968,6 +1067,25 @@ func Test_efm2()
|
|||||||
call assert_equal(1, l[4].valid)
|
call assert_equal(1, l[4].valid)
|
||||||
call assert_equal('unittests/dbfacadeTest.py', bufname(l[4].bufnr))
|
call assert_equal('unittests/dbfacadeTest.py', bufname(l[4].bufnr))
|
||||||
|
|
||||||
|
" The following sequence of commands used to crash Vim
|
||||||
|
set efm=%W%m
|
||||||
|
cgetexpr ['msg1']
|
||||||
|
let l = getqflist()
|
||||||
|
call assert_equal(1, len(l), string(l))
|
||||||
|
call assert_equal('msg1', l[0].text)
|
||||||
|
set efm=%C%m
|
||||||
|
lexpr 'msg2'
|
||||||
|
let l = getloclist(0)
|
||||||
|
call assert_equal(1, len(l), string(l))
|
||||||
|
call assert_equal('msg2', l[0].text)
|
||||||
|
lopen
|
||||||
|
call setqflist([], 'r')
|
||||||
|
caddbuf
|
||||||
|
let l = getqflist()
|
||||||
|
call assert_equal(1, len(l), string(l))
|
||||||
|
call assert_equal('|| msg2', l[0].text)
|
||||||
|
|
||||||
|
new | only
|
||||||
let &efm = save_efm
|
let &efm = save_efm
|
||||||
endfunc
|
endfunc
|
||||||
|
|
||||||
@@ -1064,6 +1182,32 @@ func SetXlistTests(cchar, bnum)
|
|||||||
call g:Xsetlist([])
|
call g:Xsetlist([])
|
||||||
let l = g:Xgetlist()
|
let l = g:Xgetlist()
|
||||||
call assert_equal(0, len(l))
|
call assert_equal(0, len(l))
|
||||||
|
|
||||||
|
" Tests for setting the 'valid' flag
|
||||||
|
call g:Xsetlist([{'bufnr':a:bnum, 'lnum':4, 'valid':0}])
|
||||||
|
Xwindow
|
||||||
|
call assert_equal(1, winnr('$'))
|
||||||
|
let l = g:Xgetlist()
|
||||||
|
call g:Xsetlist(l)
|
||||||
|
call assert_equal(0, g:Xgetlist()[0].valid)
|
||||||
|
call g:Xsetlist([{'text':'Text1', 'valid':1}])
|
||||||
|
Xwindow
|
||||||
|
call assert_equal(2, winnr('$'))
|
||||||
|
Xclose
|
||||||
|
let save_efm = &efm
|
||||||
|
set efm=%m
|
||||||
|
Xgetexpr 'TestMessage'
|
||||||
|
let l = g:Xgetlist()
|
||||||
|
call g:Xsetlist(l)
|
||||||
|
call assert_equal(1, g:Xgetlist()[0].valid)
|
||||||
|
let &efm = save_efm
|
||||||
|
|
||||||
|
" Error cases:
|
||||||
|
" Refer to a non-existing buffer and pass a non-dictionary type
|
||||||
|
call assert_fails("call g:Xsetlist([{'bufnr':998, 'lnum':4}," .
|
||||||
|
\ " {'bufnr':999, 'lnum':5}])", 'E92:')
|
||||||
|
call g:Xsetlist([[1, 2,3]])
|
||||||
|
call assert_equal(0, len(g:Xgetlist()))
|
||||||
endfunc
|
endfunc
|
||||||
|
|
||||||
func Test_setqflist()
|
func Test_setqflist()
|
||||||
@@ -1082,7 +1226,8 @@ func Xlist_empty_middle(cchar)
|
|||||||
call s:setup_commands(a:cchar)
|
call s:setup_commands(a:cchar)
|
||||||
|
|
||||||
" create three quickfix lists
|
" create three quickfix lists
|
||||||
Xvimgrep Test_ test_quickfix.vim
|
let @/ = 'Test_'
|
||||||
|
Xvimgrep // test_quickfix.vim
|
||||||
let testlen = len(g:Xgetlist())
|
let testlen = len(g:Xgetlist())
|
||||||
call assert_true(testlen > 0)
|
call assert_true(testlen > 0)
|
||||||
Xvimgrep empty test_quickfix.vim
|
Xvimgrep empty test_quickfix.vim
|
||||||
@@ -1290,18 +1435,18 @@ func Test_switchbuf()
|
|||||||
let winid = win_getid()
|
let winid = win_getid()
|
||||||
cfirst | cnext
|
cfirst | cnext
|
||||||
call assert_equal(winid, win_getid())
|
call assert_equal(winid, win_getid())
|
||||||
cnext | cnext
|
2cnext
|
||||||
call assert_equal(winid, win_getid())
|
call assert_equal(winid, win_getid())
|
||||||
cnext | cnext
|
2cnext
|
||||||
call assert_equal(winid, win_getid())
|
call assert_equal(winid, win_getid())
|
||||||
enew
|
enew
|
||||||
|
|
||||||
set switchbuf=useopen
|
set switchbuf=useopen
|
||||||
cfirst | cnext
|
cfirst | cnext
|
||||||
call assert_equal(file1_winid, win_getid())
|
call assert_equal(file1_winid, win_getid())
|
||||||
cnext | cnext
|
2cnext
|
||||||
call assert_equal(file2_winid, win_getid())
|
call assert_equal(file2_winid, win_getid())
|
||||||
cnext | cnext
|
2cnext
|
||||||
call assert_equal(file2_winid, win_getid())
|
call assert_equal(file2_winid, win_getid())
|
||||||
|
|
||||||
enew | only
|
enew | only
|
||||||
@@ -1311,9 +1456,9 @@ func Test_switchbuf()
|
|||||||
tabfirst
|
tabfirst
|
||||||
cfirst | cnext
|
cfirst | cnext
|
||||||
call assert_equal(2, tabpagenr())
|
call assert_equal(2, tabpagenr())
|
||||||
cnext | cnext
|
2cnext
|
||||||
call assert_equal(3, tabpagenr())
|
call assert_equal(3, tabpagenr())
|
||||||
cnext | cnext
|
2cnext
|
||||||
call assert_equal(3, tabpagenr())
|
call assert_equal(3, tabpagenr())
|
||||||
tabfirst | tabonly | enew
|
tabfirst | tabonly | enew
|
||||||
|
|
||||||
@@ -1351,11 +1496,25 @@ func Test_switchbuf()
|
|||||||
call assert_equal(2, winnr('$'))
|
call assert_equal(2, winnr('$'))
|
||||||
call assert_equal(1, bufwinnr('Xqftestfile3'))
|
call assert_equal(1, bufwinnr('Xqftestfile3'))
|
||||||
|
|
||||||
|
" If only quickfix window is open in the current tabpage, jumping to an
|
||||||
|
" entry with 'switchubf' set to 'usetab' should search in other tabpages.
|
||||||
enew | only
|
enew | only
|
||||||
|
set switchbuf=usetab
|
||||||
|
tabedit Xqftestfile1
|
||||||
|
tabedit Xqftestfile2
|
||||||
|
tabedit Xqftestfile3
|
||||||
|
tabfirst
|
||||||
|
copen | only
|
||||||
|
clast
|
||||||
|
call assert_equal(4, tabpagenr())
|
||||||
|
tabfirst | tabonly | enew | only
|
||||||
|
|
||||||
call delete('Xqftestfile1')
|
call delete('Xqftestfile1')
|
||||||
call delete('Xqftestfile2')
|
call delete('Xqftestfile2')
|
||||||
call delete('Xqftestfile3')
|
call delete('Xqftestfile3')
|
||||||
|
set switchbuf&vim
|
||||||
|
|
||||||
|
enew | only
|
||||||
endfunc
|
endfunc
|
||||||
|
|
||||||
func Xadjust_qflnum(cchar)
|
func Xadjust_qflnum(cchar)
|
||||||
@@ -1468,6 +1627,11 @@ endfunc
|
|||||||
func XbottomTests(cchar)
|
func XbottomTests(cchar)
|
||||||
call s:setup_commands(a:cchar)
|
call s:setup_commands(a:cchar)
|
||||||
|
|
||||||
|
" Calling lbottom without any errors should fail
|
||||||
|
if a:cchar == 'l'
|
||||||
|
call assert_fails('lbottom', 'E776:')
|
||||||
|
endif
|
||||||
|
|
||||||
call g:Xsetlist([{'filename': 'foo', 'lnum': 42}])
|
call g:Xsetlist([{'filename': 'foo', 'lnum': 42}])
|
||||||
Xopen
|
Xopen
|
||||||
let wid = win_getid()
|
let wid = win_getid()
|
||||||
@@ -1489,10 +1653,9 @@ endfunc
|
|||||||
func HistoryTest(cchar)
|
func HistoryTest(cchar)
|
||||||
call s:setup_commands(a:cchar)
|
call s:setup_commands(a:cchar)
|
||||||
|
|
||||||
call assert_fails(a:cchar . 'older 99', 'E380:')
|
|
||||||
" clear all lists after the first one, then replace the first one.
|
" clear all lists after the first one, then replace the first one.
|
||||||
call g:Xsetlist([])
|
call g:Xsetlist([])
|
||||||
Xolder
|
call assert_fails('Xolder 99', 'E380:')
|
||||||
let entry = {'filename': 'foo', 'lnum': 42}
|
let entry = {'filename': 'foo', 'lnum': 42}
|
||||||
call g:Xsetlist([entry], 'r')
|
call g:Xsetlist([entry], 'r')
|
||||||
call g:Xsetlist([entry, entry])
|
call g:Xsetlist([entry, entry])
|
||||||
@@ -1535,6 +1698,7 @@ func Xproperty_tests(cchar)
|
|||||||
call assert_fails('call g:Xsetlist([], "a", [])', 'E715:')
|
call assert_fails('call g:Xsetlist([], "a", [])', 'E715:')
|
||||||
|
|
||||||
" Set and get the title
|
" Set and get the title
|
||||||
|
call g:Xsetlist([])
|
||||||
Xopen
|
Xopen
|
||||||
wincmd p
|
wincmd p
|
||||||
call g:Xsetlist([{'filename':'foo', 'lnum':27}])
|
call g:Xsetlist([{'filename':'foo', 'lnum':27}])
|
||||||
@@ -1561,6 +1725,22 @@ func Xproperty_tests(cchar)
|
|||||||
call g:Xsetlist([], ' ', {'title' : 'N3'})
|
call g:Xsetlist([], ' ', {'title' : 'N3'})
|
||||||
call assert_equal('N2', g:Xgetlist({'nr':2, 'title':1}).title)
|
call assert_equal('N2', g:Xgetlist({'nr':2, 'title':1}).title)
|
||||||
|
|
||||||
|
" Changing the title of an earlier quickfix list
|
||||||
|
call g:Xsetlist([], ' ', {'title' : 'NewTitle', 'nr' : 2})
|
||||||
|
call assert_equal('NewTitle', g:Xgetlist({'nr':2, 'title':1}).title)
|
||||||
|
|
||||||
|
" Changing the title of an invalid quickfix list
|
||||||
|
call assert_equal(-1, g:Xsetlist([], ' ',
|
||||||
|
\ {'title' : 'SomeTitle', 'nr' : 99}))
|
||||||
|
call assert_equal(-1, g:Xsetlist([], ' ',
|
||||||
|
\ {'title' : 'SomeTitle', 'nr' : 'abc'}))
|
||||||
|
|
||||||
|
if a:cchar == 'c'
|
||||||
|
copen
|
||||||
|
call assert_equal({'winid':win_getid()}, getqflist({'winid':1}))
|
||||||
|
cclose
|
||||||
|
endif
|
||||||
|
|
||||||
" Invalid arguments
|
" Invalid arguments
|
||||||
call assert_fails('call g:Xgetlist([])', 'E715')
|
call assert_fails('call g:Xgetlist([])', 'E715')
|
||||||
call assert_fails('call g:Xsetlist([], "a", [])', 'E715')
|
call assert_fails('call g:Xsetlist([], "a", [])', 'E715')
|
||||||
@@ -1568,16 +1748,81 @@ func Xproperty_tests(cchar)
|
|||||||
call assert_equal(-1, s)
|
call assert_equal(-1, s)
|
||||||
|
|
||||||
call assert_equal({}, g:Xgetlist({'abc':1}))
|
call assert_equal({}, g:Xgetlist({'abc':1}))
|
||||||
|
call assert_equal({}, g:Xgetlist({'nr':99, 'title':1}))
|
||||||
|
call assert_equal({}, g:Xgetlist({'nr':[], 'title':1}))
|
||||||
|
|
||||||
if a:cchar == 'l'
|
if a:cchar == 'l'
|
||||||
call assert_equal({}, getloclist(99, {'title': 1}))
|
call assert_equal({}, getloclist(99, {'title': 1}))
|
||||||
endif
|
endif
|
||||||
endfunc
|
|
||||||
|
" Context related tests
|
||||||
|
call g:Xsetlist([], 'a', {'context':[1,2,3]})
|
||||||
|
call test_garbagecollect_now()
|
||||||
|
let d = g:Xgetlist({'context':1})
|
||||||
|
call assert_equal([1,2,3], d.context)
|
||||||
|
call g:Xsetlist([], 'a', {'context':{'color':'green'}})
|
||||||
|
let d = g:Xgetlist({'context':1})
|
||||||
|
call assert_equal({'color':'green'}, d.context)
|
||||||
|
call g:Xsetlist([], 'a', {'context':"Context info"})
|
||||||
|
let d = g:Xgetlist({'context':1})
|
||||||
|
call assert_equal("Context info", d.context)
|
||||||
|
call g:Xsetlist([], 'a', {'context':246})
|
||||||
|
let d = g:Xgetlist({'context':1})
|
||||||
|
call assert_equal(246, d.context)
|
||||||
|
if a:cchar == 'l'
|
||||||
|
" Test for copying context across two different location lists
|
||||||
|
new | only
|
||||||
|
let w1_id = win_getid()
|
||||||
|
let l = [1]
|
||||||
|
call setloclist(0, [], 'a', {'context':l})
|
||||||
|
new
|
||||||
|
let w2_id = win_getid()
|
||||||
|
call add(l, 2)
|
||||||
|
call assert_equal([1, 2], getloclist(w1_id, {'context':1}).context)
|
||||||
|
call assert_equal([1, 2], getloclist(w2_id, {'context':1}).context)
|
||||||
|
unlet! l
|
||||||
|
call assert_equal([1, 2], getloclist(w2_id, {'context':1}).context)
|
||||||
|
only
|
||||||
|
call setloclist(0, [], 'f')
|
||||||
|
call assert_equal({}, getloclist(0, {'context':1}))
|
||||||
|
endif
|
||||||
|
|
||||||
|
" Test for changing the context of previous quickfix lists
|
||||||
|
call g:Xsetlist([], 'f')
|
||||||
|
Xexpr "One"
|
||||||
|
Xexpr "Two"
|
||||||
|
Xexpr "Three"
|
||||||
|
call g:Xsetlist([], ' ', {'context' : [1], 'nr' : 1})
|
||||||
|
call g:Xsetlist([], ' ', {'context' : [2], 'nr' : 2})
|
||||||
|
" Also, check for setting the context using quickfix list number zero.
|
||||||
|
call g:Xsetlist([], ' ', {'context' : [3], 'nr' : 0})
|
||||||
|
call test_garbagecollect_now()
|
||||||
|
let l = g:Xgetlist({'nr' : 1, 'context' : 1})
|
||||||
|
call assert_equal([1], l.context)
|
||||||
|
let l = g:Xgetlist({'nr' : 2, 'context' : 1})
|
||||||
|
call assert_equal([2], l.context)
|
||||||
|
let l = g:Xgetlist({'nr' : 3, 'context' : 1})
|
||||||
|
call assert_equal([3], l.context)
|
||||||
|
|
||||||
|
" Test for changing the context through reference and for garbage
|
||||||
|
" collection of quickfix context
|
||||||
|
let l = ["red"]
|
||||||
|
call g:Xsetlist([], ' ', {'context' : l})
|
||||||
|
call add(l, "blue")
|
||||||
|
let x = g:Xgetlist({'context' : 1})
|
||||||
|
call add(x.context, "green")
|
||||||
|
call assert_equal(["red", "blue", "green"], l)
|
||||||
|
call assert_equal(["red", "blue", "green"], x.context)
|
||||||
|
unlet l
|
||||||
|
call test_garbagecollect_now()
|
||||||
|
let m = g:Xgetlist({'context' : 1})
|
||||||
|
call assert_equal(["red", "blue", "green"], m.context)
|
||||||
|
endfunc
|
||||||
|
|
||||||
func Test_qf_property()
|
func Test_qf_property()
|
||||||
call Xproperty_tests('c')
|
call Xproperty_tests('c')
|
||||||
call Xproperty_tests('l')
|
call Xproperty_tests('l')
|
||||||
endfunc
|
endfunc
|
||||||
|
|
||||||
" Tests for the QuickFixCmdPre/QuickFixCmdPost autocommands
|
" Tests for the QuickFixCmdPre/QuickFixCmdPost autocommands
|
||||||
func QfAutoCmdHandler(loc, cmd)
|
func QfAutoCmdHandler(loc, cmd)
|
||||||
@@ -1673,3 +1918,187 @@ func Test_dirstack_cleanup()
|
|||||||
caddbuffer
|
caddbuffer
|
||||||
let &efm = save_efm
|
let &efm = save_efm
|
||||||
endfunc
|
endfunc
|
||||||
|
|
||||||
|
" Tests for jumping to entries from the location list window and quickfix
|
||||||
|
" window
|
||||||
|
func Test_cwindow_jump()
|
||||||
|
set efm=%f%%%l%%%m
|
||||||
|
lgetexpr ["F1%10%Line 10", "F2%20%Line 20", "F3%30%Line 30"]
|
||||||
|
lopen | only
|
||||||
|
lfirst
|
||||||
|
call assert_true(winnr('$') == 2)
|
||||||
|
call assert_true(winnr() == 1)
|
||||||
|
" Location list for the new window should be set
|
||||||
|
call assert_true(getloclist(0)[2].text == 'Line 30')
|
||||||
|
|
||||||
|
" Open a scratch buffer
|
||||||
|
" Open a new window and create a location list
|
||||||
|
" Open the location list window and close the other window
|
||||||
|
" Jump to an entry.
|
||||||
|
" Should create a new window and jump to the entry. The scrtach buffer
|
||||||
|
" should not be used.
|
||||||
|
enew | only
|
||||||
|
set buftype=nofile
|
||||||
|
below new
|
||||||
|
lgetexpr ["F1%10%Line 10", "F2%20%Line 20", "F3%30%Line 30"]
|
||||||
|
lopen
|
||||||
|
2wincmd c
|
||||||
|
lnext
|
||||||
|
call assert_true(winnr('$') == 3)
|
||||||
|
call assert_true(winnr() == 2)
|
||||||
|
|
||||||
|
" Open two windows with two different location lists
|
||||||
|
" Open the location list window and close the previous window
|
||||||
|
" Jump to an entry in the location list window
|
||||||
|
" Should open the file in the first window and not set the location list.
|
||||||
|
enew | only
|
||||||
|
lgetexpr ["F1%5%Line 5"]
|
||||||
|
below new
|
||||||
|
lgetexpr ["F1%10%Line 10", "F2%20%Line 20", "F3%30%Line 30"]
|
||||||
|
lopen
|
||||||
|
2wincmd c
|
||||||
|
lnext
|
||||||
|
call assert_true(winnr() == 1)
|
||||||
|
call assert_true(getloclist(0)[0].text == 'Line 5')
|
||||||
|
|
||||||
|
enew | only
|
||||||
|
cgetexpr ["F1%10%Line 10", "F2%20%Line 20", "F3%30%Line 30"]
|
||||||
|
copen
|
||||||
|
cnext
|
||||||
|
call assert_true(winnr('$') == 2)
|
||||||
|
call assert_true(winnr() == 1)
|
||||||
|
|
||||||
|
enew | only
|
||||||
|
set efm&vim
|
||||||
|
endfunc
|
||||||
|
|
||||||
|
func XvimgrepTests(cchar)
|
||||||
|
call s:setup_commands(a:cchar)
|
||||||
|
|
||||||
|
call writefile(['Editor:VIM vim',
|
||||||
|
\ 'Editor:Emacs EmAcS',
|
||||||
|
\ 'Editor:Notepad NOTEPAD'], 'Xtestfile1')
|
||||||
|
call writefile(['Linux', 'MacOS', 'MS-Windows'], 'Xtestfile2')
|
||||||
|
|
||||||
|
" Error cases
|
||||||
|
call assert_fails('Xvimgrep /abc *', 'E682:')
|
||||||
|
|
||||||
|
let @/=''
|
||||||
|
call assert_fails('Xvimgrep // *', 'E35:')
|
||||||
|
|
||||||
|
call assert_fails('Xvimgrep abc', 'E683:')
|
||||||
|
call assert_fails('Xvimgrep a1b2c3 Xtestfile1', 'E480:')
|
||||||
|
call assert_fails('Xvimgrep pat Xa1b2c3', 'E480:')
|
||||||
|
|
||||||
|
Xexpr ""
|
||||||
|
Xvimgrepadd Notepad Xtestfile1
|
||||||
|
Xvimgrepadd MacOS Xtestfile2
|
||||||
|
let l = g:Xgetlist()
|
||||||
|
call assert_equal(2, len(l))
|
||||||
|
call assert_equal('Editor:Notepad NOTEPAD', l[0].text)
|
||||||
|
|
||||||
|
Xvimgrep #\cvim#g Xtestfile?
|
||||||
|
let l = g:Xgetlist()
|
||||||
|
call assert_equal(2, len(l))
|
||||||
|
call assert_equal(8, l[0].col)
|
||||||
|
call assert_equal(12, l[1].col)
|
||||||
|
|
||||||
|
1Xvimgrep ?Editor? Xtestfile*
|
||||||
|
let l = g:Xgetlist()
|
||||||
|
call assert_equal(1, len(l))
|
||||||
|
call assert_equal('Editor:VIM vim', l[0].text)
|
||||||
|
|
||||||
|
edit +3 Xtestfile2
|
||||||
|
Xvimgrep +\cemacs+j Xtestfile1
|
||||||
|
let l = g:Xgetlist()
|
||||||
|
call assert_equal('Xtestfile2', bufname(''))
|
||||||
|
call assert_equal('Editor:Emacs EmAcS', l[0].text)
|
||||||
|
|
||||||
|
call delete('Xtestfile1')
|
||||||
|
call delete('Xtestfile2')
|
||||||
|
endfunc
|
||||||
|
|
||||||
|
" Tests for the :vimgrep command
|
||||||
|
func Test_vimgrep()
|
||||||
|
call XvimgrepTests('c')
|
||||||
|
call XvimgrepTests('l')
|
||||||
|
endfunc
|
||||||
|
|
||||||
|
func XfreeTests(cchar)
|
||||||
|
call s:setup_commands(a:cchar)
|
||||||
|
|
||||||
|
enew | only
|
||||||
|
|
||||||
|
" Deleting the quickfix stack should work even When the current list is
|
||||||
|
" somewhere in the middle of the stack
|
||||||
|
Xexpr ['Xfile1:10:10:Line 10', 'Xfile1:15:15:Line 15']
|
||||||
|
Xexpr ['Xfile2:20:20:Line 20', 'Xfile2:25:25:Line 25']
|
||||||
|
Xexpr ['Xfile3:30:30:Line 30', 'Xfile3:35:35:Line 35']
|
||||||
|
Xolder
|
||||||
|
call g:Xsetlist([], 'f')
|
||||||
|
call assert_equal(0, len(g:Xgetlist()))
|
||||||
|
|
||||||
|
" After deleting the stack, adding a new list should create a stack with a
|
||||||
|
" single list.
|
||||||
|
Xexpr ['Xfile1:10:10:Line 10', 'Xfile1:15:15:Line 15']
|
||||||
|
call assert_equal(1, g:Xgetlist({'all':1}).nr)
|
||||||
|
|
||||||
|
" Deleting the stack from a quickfix window should update/clear the
|
||||||
|
" quickfix/location list window.
|
||||||
|
Xexpr ['Xfile1:10:10:Line 10', 'Xfile1:15:15:Line 15']
|
||||||
|
Xexpr ['Xfile2:20:20:Line 20', 'Xfile2:25:25:Line 25']
|
||||||
|
Xexpr ['Xfile3:30:30:Line 30', 'Xfile3:35:35:Line 35']
|
||||||
|
Xolder
|
||||||
|
Xwindow
|
||||||
|
call g:Xsetlist([], 'f')
|
||||||
|
call assert_equal(2, winnr('$'))
|
||||||
|
call assert_equal(1, line('$'))
|
||||||
|
Xclose
|
||||||
|
|
||||||
|
" Deleting the stack from a non-quickfix window should update/clear the
|
||||||
|
" quickfix/location list window.
|
||||||
|
Xexpr ['Xfile1:10:10:Line 10', 'Xfile1:15:15:Line 15']
|
||||||
|
Xexpr ['Xfile2:20:20:Line 20', 'Xfile2:25:25:Line 25']
|
||||||
|
Xexpr ['Xfile3:30:30:Line 30', 'Xfile3:35:35:Line 35']
|
||||||
|
Xolder
|
||||||
|
Xwindow
|
||||||
|
wincmd p
|
||||||
|
call g:Xsetlist([], 'f')
|
||||||
|
call assert_equal(0, len(g:Xgetlist()))
|
||||||
|
wincmd p
|
||||||
|
call assert_equal(2, winnr('$'))
|
||||||
|
call assert_equal(1, line('$'))
|
||||||
|
|
||||||
|
" After deleting the location list stack, if the location list window is
|
||||||
|
" opened, then a new location list should be created. So opening the
|
||||||
|
" location list window again should not create a new window.
|
||||||
|
if a:cchar == 'l'
|
||||||
|
lexpr ['Xfile1:10:10:Line 10', 'Xfile1:15:15:Line 15']
|
||||||
|
wincmd p
|
||||||
|
lopen
|
||||||
|
call assert_equal(2, winnr('$'))
|
||||||
|
endif
|
||||||
|
Xclose
|
||||||
|
endfunc
|
||||||
|
|
||||||
|
" Tests for the quickifx free functionality
|
||||||
|
func Test_qf_free()
|
||||||
|
call XfreeTests('c')
|
||||||
|
call XfreeTests('l')
|
||||||
|
endfunc
|
||||||
|
|
||||||
|
" Test for buffer overflow when parsing lines and adding new entries to
|
||||||
|
" the quickfix list.
|
||||||
|
func Test_bufoverflow()
|
||||||
|
set efm=%f:%l:%m
|
||||||
|
cgetexpr ['File1:100:' . repeat('x', 1025)]
|
||||||
|
|
||||||
|
set efm=%+GCompiler:\ %.%#,%f:%l:%m
|
||||||
|
cgetexpr ['Compiler: ' . repeat('a', 1015), 'File1:10:Hello World']
|
||||||
|
|
||||||
|
set efm=%DEntering\ directory\ %f,%f:%l:%m
|
||||||
|
cgetexpr ['Entering directory ' . repeat('a', 1006),
|
||||||
|
\ 'File1:10:Hello World']
|
||||||
|
set efm&vim
|
||||||
|
endfunc
|
||||||
|
|
||||||
|
@@ -70,7 +70,6 @@ typedef struct {
|
|||||||
UIBridgeData *bridge;
|
UIBridgeData *bridge;
|
||||||
Loop *loop;
|
Loop *loop;
|
||||||
bool stop;
|
bool stop;
|
||||||
uv_timer_t after_startup_timer;
|
|
||||||
unibi_var_t params[9];
|
unibi_var_t params[9];
|
||||||
char buf[OUTBUF_SIZE];
|
char buf[OUTBUF_SIZE];
|
||||||
size_t bufpos;
|
size_t bufpos;
|
||||||
@@ -291,18 +290,6 @@ static void terminfo_stop(UI *ui)
|
|||||||
unibi_destroy(data->ut);
|
unibi_destroy(data->ut);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void after_startup_timer_cb(uv_timer_t *handle)
|
|
||||||
FUNC_ATTR_NONNULL_ALL
|
|
||||||
{
|
|
||||||
UI *ui = handle->data;
|
|
||||||
TUIData *data = ui->data;
|
|
||||||
uv_timer_stop(&data->after_startup_timer);
|
|
||||||
|
|
||||||
// Emit this after Nvim startup, not during. This works around a tmux
|
|
||||||
// 2.3 bug(?) which caused slow drawing during startup. #7649
|
|
||||||
unibi_out_ext(ui, data->unibi_ext.enable_focus_reporting);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void tui_terminal_start(UI *ui)
|
static void tui_terminal_start(UI *ui)
|
||||||
{
|
{
|
||||||
TUIData *data = ui->data;
|
TUIData *data = ui->data;
|
||||||
@@ -312,8 +299,16 @@ static void tui_terminal_start(UI *ui)
|
|||||||
update_size(ui);
|
update_size(ui);
|
||||||
signal_watcher_start(&data->winch_handle, sigwinch_cb, SIGWINCH);
|
signal_watcher_start(&data->winch_handle, sigwinch_cb, SIGWINCH);
|
||||||
term_input_start(&data->input);
|
term_input_start(&data->input);
|
||||||
|
}
|
||||||
|
|
||||||
uv_timer_start(&data->after_startup_timer, after_startup_timer_cb, 500, 0);
|
static void tui_terminal_after_startup(UI *ui)
|
||||||
|
FUNC_ATTR_NONNULL_ALL
|
||||||
|
{
|
||||||
|
TUIData *data = ui->data;
|
||||||
|
|
||||||
|
// Emit this after Nvim startup, not during. This works around a tmux
|
||||||
|
// 2.3 bug(?) which caused slow drawing during startup. #7649
|
||||||
|
unibi_out_ext(ui, data->unibi_ext.enable_focus_reporting);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void tui_terminal_stop(UI *ui)
|
static void tui_terminal_stop(UI *ui)
|
||||||
@@ -347,8 +342,6 @@ static void tui_main(UIBridgeData *bridge, UI *ui)
|
|||||||
#ifdef UNIX
|
#ifdef UNIX
|
||||||
signal_watcher_start(&data->cont_handle, sigcont_cb, SIGCONT);
|
signal_watcher_start(&data->cont_handle, sigcont_cb, SIGCONT);
|
||||||
#endif
|
#endif
|
||||||
uv_timer_init(&data->loop->uv, &data->after_startup_timer);
|
|
||||||
data->after_startup_timer.data = ui;
|
|
||||||
|
|
||||||
#if TERMKEY_VERSION_MAJOR > 0 || TERMKEY_VERSION_MINOR > 18
|
#if TERMKEY_VERSION_MAJOR > 0 || TERMKEY_VERSION_MINOR > 18
|
||||||
data->input.tk_ti_hook_fn = tui_tk_ti_getstr;
|
data->input.tk_ti_hook_fn = tui_tk_ti_getstr;
|
||||||
@@ -363,11 +356,21 @@ static void tui_main(UIBridgeData *bridge, UI *ui)
|
|||||||
loop_schedule_deferred(&main_loop,
|
loop_schedule_deferred(&main_loop,
|
||||||
event_create(show_termcap_event, 1, data->ut));
|
event_create(show_termcap_event, 1, data->ut));
|
||||||
|
|
||||||
|
// "Active" loop: first ~100 ms of startup.
|
||||||
|
for (size_t ms = 0; ms < 100 && !data->stop;) {
|
||||||
|
ms += (loop_poll_events(&tui_loop, 20) ? 20 : 1);
|
||||||
|
}
|
||||||
|
if (!data->stop) {
|
||||||
|
tui_terminal_after_startup(ui);
|
||||||
|
// Tickle `main_loop` with a dummy event, else the initial "focus-gained"
|
||||||
|
// terminal response may not get processed until user hits a key.
|
||||||
|
loop_schedule_deferred(&main_loop, event_create(tui_dummy_event, 0));
|
||||||
|
}
|
||||||
|
// "Passive" (I/O-driven) loop: TUI thread "main loop".
|
||||||
while (!data->stop) {
|
while (!data->stop) {
|
||||||
loop_poll_events(&tui_loop, -1); // tui_loop.events is never processed
|
loop_poll_events(&tui_loop, -1); // tui_loop.events is never processed
|
||||||
}
|
}
|
||||||
|
|
||||||
uv_close((uv_handle_t *)&data->after_startup_timer, NULL);
|
|
||||||
ui_bridge_stopped(bridge);
|
ui_bridge_stopped(bridge);
|
||||||
term_input_destroy(&data->input);
|
term_input_destroy(&data->input);
|
||||||
signal_watcher_stop(&data->cont_handle);
|
signal_watcher_stop(&data->cont_handle);
|
||||||
@@ -379,6 +382,10 @@ static void tui_main(UIBridgeData *bridge, UI *ui)
|
|||||||
xfree(ui);
|
xfree(ui);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void tui_dummy_event(void **argv)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
static void tui_scheduler(Event event, void *d)
|
static void tui_scheduler(Event event, void *d)
|
||||||
{
|
{
|
||||||
UI *ui = d;
|
UI *ui = d;
|
||||||
@@ -1100,6 +1107,7 @@ static void suspend_event(void **argv)
|
|||||||
loop_poll_events(data->loop, -1);
|
loop_poll_events(data->loop, -1);
|
||||||
}
|
}
|
||||||
tui_terminal_start(ui);
|
tui_terminal_start(ui);
|
||||||
|
tui_terminal_after_startup(ui);
|
||||||
if (enable_mouse) {
|
if (enable_mouse) {
|
||||||
tui_mouse_on(ui);
|
tui_mouse_on(ui);
|
||||||
}
|
}
|
||||||
|
@@ -614,7 +614,7 @@ local function new_pipename()
|
|||||||
end
|
end
|
||||||
|
|
||||||
local function missing_provider(provider)
|
local function missing_provider(provider)
|
||||||
if provider == 'ruby' then
|
if provider == 'ruby' or provider == 'node' then
|
||||||
local prog = funcs['provider#' .. provider .. '#Detect']()
|
local prog = funcs['provider#' .. provider .. '#Detect']()
|
||||||
return prog == '' and (provider .. ' not detected') or false
|
return prog == '' and (provider .. ' not detected') or false
|
||||||
elseif provider == 'python' or provider == 'python3' then
|
elseif provider == 'python' or provider == 'python3' then
|
||||||
|
61
test/functional/provider/nodejs_spec.lua
Normal file
61
test/functional/provider/nodejs_spec.lua
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
local helpers = require('test.functional.helpers')(after_each)
|
||||||
|
local eq, clear = helpers.eq, helpers.clear
|
||||||
|
local missing_provider = helpers.missing_provider
|
||||||
|
local command = helpers.command
|
||||||
|
local write_file = helpers.write_file
|
||||||
|
local eval = helpers.eval
|
||||||
|
local retry = helpers.retry
|
||||||
|
|
||||||
|
do
|
||||||
|
clear()
|
||||||
|
if missing_provider('node') then
|
||||||
|
pending("Missing nodejs host, or nodejs version is too old.", function()end)
|
||||||
|
return
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
before_each(function()
|
||||||
|
clear()
|
||||||
|
command([[let $NODE_PATH = get(split(system('npm root -g'), "\n"), 0, '')]])
|
||||||
|
end)
|
||||||
|
|
||||||
|
describe('nodejs host', function()
|
||||||
|
teardown(function ()
|
||||||
|
os.remove('Xtest-nodejs-hello.js')
|
||||||
|
os.remove('Xtest-nodejs-hello-plugin.js')
|
||||||
|
end)
|
||||||
|
|
||||||
|
it('works', function()
|
||||||
|
local fname = 'Xtest-nodejs-hello.js'
|
||||||
|
write_file(fname, [[
|
||||||
|
const socket = process.env.NVIM_LISTEN_ADDRESS;
|
||||||
|
const neovim = require('neovim');
|
||||||
|
const nvim = neovim.attach({socket: socket});
|
||||||
|
nvim.command('let g:job_out = "hello"');
|
||||||
|
nvim.command('call jobstop(g:job_id)');
|
||||||
|
]])
|
||||||
|
command('let g:job_id = jobstart(["node", "'..fname..'"])')
|
||||||
|
retry(nil, 1000, function() eq('hello', eval('g:job_out')) end)
|
||||||
|
end)
|
||||||
|
it('plugin works', function()
|
||||||
|
local fname = 'Xtest-nodejs-hello-plugin.js'
|
||||||
|
write_file(fname, [[
|
||||||
|
const socket = process.env.NVIM_LISTEN_ADDRESS;
|
||||||
|
const neovim = require('neovim');
|
||||||
|
const nvim = neovim.attach({socket: socket});
|
||||||
|
|
||||||
|
class TestPlugin {
|
||||||
|
hello() {
|
||||||
|
this.nvim.command('let g:job_out = "hello-plugin"')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const PluginClass = neovim.Plugin(TestPlugin);
|
||||||
|
const plugin = new PluginClass(nvim);
|
||||||
|
plugin.hello();
|
||||||
|
nvim.command('call jobstop(g:job_id)');
|
||||||
|
]])
|
||||||
|
command('let g:job_id = jobstart(["node", "'..fname..'"])')
|
||||||
|
retry(nil, 1000, function() eq('hello-plugin', eval('g:job_out')) end)
|
||||||
|
end)
|
||||||
|
end)
|
@@ -15,9 +15,7 @@ local missing_provider = helpers.missing_provider
|
|||||||
do
|
do
|
||||||
clear()
|
clear()
|
||||||
if missing_provider('ruby') then
|
if missing_provider('ruby') then
|
||||||
pending(
|
pending("Missing neovim RubyGem.", function() end)
|
||||||
"Cannot find the neovim RubyGem. Try :checkhealth",
|
|
||||||
function() end)
|
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
4
third-party/CMakeLists.txt
vendored
4
third-party/CMakeLists.txt
vendored
@@ -103,8 +103,8 @@ set(LUA_SHA256 2640fc56a795f29d28ef15e13c34a47e223960b0240e8cb0a82d9b0738695333)
|
|||||||
set(LUAROCKS_URL https://github.com/luarocks/luarocks/archive/v2.4.2.tar.gz)
|
set(LUAROCKS_URL https://github.com/luarocks/luarocks/archive/v2.4.2.tar.gz)
|
||||||
set(LUAROCKS_SHA256 eef88c2429c715a7beb921e4b1ba571dddb7c74a250fbb0d3cc0d4be7a5865d9)
|
set(LUAROCKS_SHA256 eef88c2429c715a7beb921e4b1ba571dddb7c74a250fbb0d3cc0d4be7a5865d9)
|
||||||
|
|
||||||
set(UNIBILIUM_URL https://github.com/mauke/unibilium/archive/v1.2.0.tar.gz)
|
set(UNIBILIUM_URL https://github.com/mauke/unibilium/archive/v1.2.1.tar.gz)
|
||||||
set(UNIBILIUM_SHA256 623af1099515e673abfd3cae5f2fa808a09ca55dda1c65a7b5c9424eb304ead8)
|
set(UNIBILIUM_SHA256 6045b4f6adca7b1123284007675ca71f718f70942d3a93d8b9fa5bd442006ec1)
|
||||||
|
|
||||||
if(WIN32)
|
if(WIN32)
|
||||||
set(LIBTERMKEY_URL https://github.com/equalsraf/libtermkey/archive/tb-windows.zip)
|
set(LIBTERMKEY_URL https://github.com/equalsraf/libtermkey/archive/tb-windows.zip)
|
||||||
|
Reference in New Issue
Block a user