mirror of
https://github.com/neovim/neovim.git
synced 2025-02-25 18:55:25 -06:00
Merge branch 'master' into colored-cmdline
This commit is contained in:
commit
fbe60af538
3
.gitignore
vendored
3
.gitignore
vendored
@ -17,6 +17,9 @@ tags
|
||||
/src/nvim/po/vim.pot
|
||||
/src/nvim/po/*.ck
|
||||
|
||||
# generated by tests with $NVIM_LOG_FILE set.
|
||||
/.nvimlog
|
||||
|
||||
# Files generated by scripts/vim-patch.sh
|
||||
/.vim-src/
|
||||
|
||||
|
@ -192,6 +192,16 @@ if(CMAKE_EXE_LINKER_FLAGS MATCHES "--sort-common" OR
|
||||
string(REGEX REPLACE "-Wl($| )" "" CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS}")
|
||||
endif()
|
||||
|
||||
check_c_source_compiles("
|
||||
#include <execinfo.h>
|
||||
int main(void)
|
||||
{
|
||||
void *trace[1];
|
||||
int trace_size = backtrace(trace, 1);
|
||||
return 0;
|
||||
}
|
||||
" HAVE_EXECINFO_BACKTRACE)
|
||||
|
||||
if(MSVC)
|
||||
# XXX: /W4 gives too many warnings. #3241
|
||||
add_definitions(/W3 -D_CRT_SECURE_NO_WARNINGS -D_CRT_NONSTDC_NO_DEPRECATE)
|
||||
@ -240,6 +250,14 @@ if(HAS_DIAG_COLOR_FLAG)
|
||||
add_definitions(-fdiagnostics-color=auto)
|
||||
endif()
|
||||
|
||||
if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
|
||||
if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS "4.8.5")
|
||||
# Array-bounds testing is broken in some GCC versions before 4.8.5.
|
||||
# https://gcc.gnu.org/bugzilla/show_bug.cgi?id=56273
|
||||
add_definitions(-Wno-array-bounds)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
option(TRAVIS_CI_BUILD "Travis/QuickBuild CI. Extra flags will be set." OFF)
|
||||
|
||||
if(TRAVIS_CI_BUILD)
|
||||
@ -316,7 +334,6 @@ main(void)
|
||||
return MSGPACK_OBJECT_FLOAT32;
|
||||
}
|
||||
" MSGPACK_HAS_FLOAT32)
|
||||
|
||||
if(MSGPACK_HAS_FLOAT32)
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DNVIM_MSGPACK_HAS_FLOAT32")
|
||||
endif()
|
||||
|
@ -27,6 +27,7 @@ Reporting problems
|
||||
- When reporting a crash, include a stacktrace.
|
||||
- [Bisect][git-bisect] to the cause of a regression, if you are able. This is _extremely_ helpful.
|
||||
- Check `$NVIM_LOG_FILE`, if it exists.
|
||||
- Include `cmake --system-information` for **build** issues.
|
||||
|
||||
Pull requests ("PRs")
|
||||
---------------------
|
||||
@ -94,8 +95,9 @@ and [AppVeyor].
|
||||
See [Building Neovim#running-tests][wiki-run-tests] to run tests locally.
|
||||
Passing locally doesn't guarantee passing the CI build, because of the
|
||||
different compilers and platforms tested against.
|
||||
- CI runs [ASan] and other analyzers. To run valgrind locally:
|
||||
`VALGRIND=1 make test`
|
||||
- CI runs [ASan] and other analyzers.
|
||||
- To run valgrind locally: `VALGRIND=1 make test`
|
||||
- To run Clang ASan/UBSan locally: `CC=clang make CMAKE_FLAGS="-DCLANG_ASAN_UBSAN=ON"`
|
||||
- The `lint` build ([#3174][3174]) checks modified lines _and their immediate
|
||||
neighbors_. This is to encourage incrementally updating the legacy style to
|
||||
meet our style guidelines.
|
||||
|
92
busted/outputHandlers/TAP.lua
Normal file
92
busted/outputHandlers/TAP.lua
Normal file
@ -0,0 +1,92 @@
|
||||
-- TODO(jkeyes): remove this and use the upstream version as soon as it is
|
||||
-- available in a release of busted.
|
||||
|
||||
local pretty = require 'pl.pretty'
|
||||
|
||||
return function(options)
|
||||
local busted = require 'busted'
|
||||
local handler = require 'busted.outputHandlers.base'()
|
||||
|
||||
local success = 'ok %u - %s'
|
||||
local failure = 'not ' .. success
|
||||
local skip = 'ok %u - # SKIP %s'
|
||||
local counter = 0
|
||||
|
||||
handler.suiteReset = function()
|
||||
counter = 0
|
||||
return nil, true
|
||||
end
|
||||
|
||||
handler.suiteEnd = function()
|
||||
print('1..' .. counter)
|
||||
io.flush()
|
||||
return nil, true
|
||||
end
|
||||
|
||||
local function showFailure(t)
|
||||
local message = t.message
|
||||
local trace = t.trace or {}
|
||||
|
||||
if message == nil then
|
||||
message = 'Nil error'
|
||||
elseif type(message) ~= 'string' then
|
||||
message = pretty.write(message)
|
||||
end
|
||||
|
||||
print(failure:format(counter, t.name))
|
||||
print('# ' .. t.element.trace.short_src .. ' @ ' .. t.element.trace.currentline)
|
||||
if t.randomseed then print('# Random seed: ' .. t.randomseed) end
|
||||
print('# Failure message: ' .. message:gsub('\n', '\n# '))
|
||||
if options.verbose and trace.traceback then
|
||||
print('# ' .. trace.traceback:gsub('^\n', '', 1):gsub('\n', '\n# '))
|
||||
end
|
||||
end
|
||||
|
||||
handler.testStart = function(element, parent)
|
||||
local trace = element.trace
|
||||
if options.verbose and trace and trace.short_src then
|
||||
local fileline = trace.short_src .. ' @ ' .. trace.currentline .. ': '
|
||||
local testName = fileline .. handler.getFullName(element)
|
||||
print('# ' .. testName)
|
||||
end
|
||||
io.flush()
|
||||
|
||||
return nil, true
|
||||
end
|
||||
|
||||
handler.testEnd = function(element, parent, status, trace)
|
||||
counter = counter + 1
|
||||
if status == 'success' then
|
||||
local t = handler.successes[#handler.successes]
|
||||
print(success:format(counter, t.name))
|
||||
elseif status == 'pending' then
|
||||
local t = handler.pendings[#handler.pendings]
|
||||
print(skip:format(counter, (t.message or t.name)))
|
||||
elseif status == 'failure' then
|
||||
showFailure(handler.failures[#handler.failures])
|
||||
elseif status == 'error' then
|
||||
showFailure(handler.errors[#handler.errors])
|
||||
end
|
||||
io.flush()
|
||||
|
||||
return nil, true
|
||||
end
|
||||
|
||||
handler.error = function(element, parent, message, debug)
|
||||
if element.descriptor ~= 'it' then
|
||||
counter = counter + 1
|
||||
showFailure(handler.errors[#handler.errors])
|
||||
end
|
||||
io.flush()
|
||||
|
||||
return nil, true
|
||||
end
|
||||
|
||||
busted.subscribe({ 'suite', 'reset' }, handler.suiteReset)
|
||||
busted.subscribe({ 'suite', 'end' }, handler.suiteEnd)
|
||||
busted.subscribe({ 'test', 'start' }, handler.testStart, { predicate = handler.cancelOnPending })
|
||||
busted.subscribe({ 'test', 'end' }, handler.testEnd, { predicate = handler.cancelOnPending })
|
||||
busted.subscribe({ 'error' }, handler.error)
|
||||
|
||||
return handler
|
||||
end
|
@ -1,3 +1,6 @@
|
||||
# Set LC_ALL to meet expectations of some locale-sensitive tests.
|
||||
set(ENV{LC_ALL} "en_US.UTF-8")
|
||||
|
||||
set(ENV{VIMRUNTIME} ${WORKING_DIR}/runtime)
|
||||
set(ENV{NVIM_RPLUGIN_MANIFEST} ${WORKING_DIR}/Xtest_rplugin_manifest)
|
||||
set(ENV{XDG_CONFIG_HOME} ${WORKING_DIR}/Xtest_xdg/config)
|
||||
|
@ -68,4 +68,6 @@
|
||||
#cmakedefine ORDER_BIG_ENDIAN
|
||||
#define ENDIAN_INCLUDE_FILE <@ENDIAN_INCLUDE_FILE@>
|
||||
|
||||
#cmakedefine HAVE_EXECINFO_BACKTRACE
|
||||
|
||||
#endif // AUTO_CONFIG_H
|
||||
|
@ -100,20 +100,6 @@ add_custom_target(
|
||||
${GENERATED_PACKAGE_TAGS}
|
||||
)
|
||||
|
||||
# Optional targets for nvim.desktop file and icon.
|
||||
find_program(XDG_MENU_PRG xdg-desktop-menu)
|
||||
find_program(XDG_ICON_PRG xdg-icon-resource)
|
||||
if(XDG_MENU_PRG)
|
||||
add_custom_target(desktop-file
|
||||
COMMAND xdg-desktop-menu install --novendor ${PROJECT_SOURCE_DIR}/runtime/nvim.desktop)
|
||||
# add_dependencies(runtime desktop-file)
|
||||
endif()
|
||||
if(XDG_ICON_PRG)
|
||||
add_custom_target(desktop-icon
|
||||
COMMAND xdg-icon-resource install --novendor --size 128 ${PROJECT_SOURCE_DIR}/runtime/nvim.png)
|
||||
# add_dependencies(runtime desktop-icon)
|
||||
endif()
|
||||
|
||||
# CMake is painful here. It will create the destination using the user's
|
||||
# current umask, and we don't want that. And we don't just want to install
|
||||
# the target directory, as it will mess with existing permissions. So this
|
||||
@ -128,6 +114,16 @@ install_helper(
|
||||
FILES ${GENERATED_SYN_VIM}
|
||||
DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/nvim/runtime/syntax/vim)
|
||||
|
||||
if(NOT APPLE)
|
||||
install_helper(
|
||||
FILES ${CMAKE_CURRENT_SOURCE_DIR}/nvim.desktop
|
||||
DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/applications)
|
||||
|
||||
install_helper(
|
||||
FILES ${CMAKE_CURRENT_SOURCE_DIR}/nvim.png
|
||||
DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/pixmaps)
|
||||
endif()
|
||||
|
||||
file(GLOB_RECURSE RUNTIME_PROGRAMS
|
||||
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
|
||||
*.awk *.sh *.bat)
|
||||
|
18
runtime/autoload/provider.vim
Normal file
18
runtime/autoload/provider.vim
Normal file
@ -0,0 +1,18 @@
|
||||
" Common functionality for providers
|
||||
|
||||
let s:stderr = {}
|
||||
|
||||
function! provider#stderr_collector(chan_id, data, event) dict
|
||||
let stderr = get(s:stderr, a:chan_id, [''])
|
||||
let stderr[-1] .= a:data[0]
|
||||
call extend(stderr, a:data[1:])
|
||||
let s:stderr[a:chan_id] = stderr
|
||||
endfunction
|
||||
|
||||
function! provider#clear_stderr(chan_id)
|
||||
silent! call delete(s:stderr, a:chan_id)
|
||||
endfunction
|
||||
|
||||
function! provider#get_stderr(chan_id)
|
||||
return get(s:stderr, a:chan_id, [])
|
||||
endfunction
|
@ -6,7 +6,7 @@ let s:paste = {}
|
||||
|
||||
" When caching is enabled, store the jobid of the xclip/xsel process keeping
|
||||
" ownership of the selection, so we know how long the cache is valid.
|
||||
let s:selection = { 'owner': 0, 'data': [] }
|
||||
let s:selection = { 'owner': 0, 'data': [], 'on_stderr': function('provider#stderr_collector') }
|
||||
|
||||
function! s:selection.on_exit(jobid, data, event) abort
|
||||
" At this point this nvim instance might already have launched
|
||||
@ -14,6 +14,13 @@ function! s:selection.on_exit(jobid, data, event) abort
|
||||
if self.owner == a:jobid
|
||||
let self.owner = 0
|
||||
endif
|
||||
if a:data != 0
|
||||
let stderr = provider#get_stderr(a:jobid)
|
||||
echohl WarningMsg
|
||||
echomsg 'clipboard: error invoking '.get(self.argv, 0, '?').': '.join(stderr)
|
||||
echohl None
|
||||
endif
|
||||
call provider#clear_stderr(a:jobid)
|
||||
endfunction
|
||||
|
||||
let s:selections = { '*': s:selection, '+': copy(s:selection)}
|
||||
@ -135,18 +142,19 @@ function! s:clipboard.set(lines, regtype, reg) abort
|
||||
end
|
||||
let selection.data = [a:lines, a:regtype]
|
||||
let argv = split(s:copy[a:reg], " ")
|
||||
let selection.argv = argv
|
||||
let selection.detach = s:cache_enabled
|
||||
let selection.cwd = "/"
|
||||
let jobid = jobstart(argv, selection)
|
||||
if jobid <= 0
|
||||
if jobid > 0
|
||||
call jobsend(jobid, a:lines)
|
||||
call jobclose(jobid, 'stdin')
|
||||
let selection.owner = jobid
|
||||
else
|
||||
echohl WarningMsg
|
||||
echo "clipboard: error when invoking provider"
|
||||
echomsg 'clipboard: failed to execute: '.(s:copy[a:reg])
|
||||
echohl None
|
||||
return 0
|
||||
endif
|
||||
call jobsend(jobid, a:lines)
|
||||
call jobclose(jobid, 'stdin')
|
||||
let selection.owner = jobid
|
||||
endfunction
|
||||
|
||||
function! provider#clipboard#Call(method, args) abort
|
||||
|
@ -5,17 +5,7 @@ endif
|
||||
|
||||
let s:loaded_pythonx_provider = 1
|
||||
|
||||
let s:stderr = {}
|
||||
let s:job_opts = {'rpc': v:true}
|
||||
|
||||
" TODO(bfredl): this logic is common and should be builtin
|
||||
function! s:job_opts.on_stderr(chan_id, data, event)
|
||||
let stderr = get(s:stderr, a:chan_id, [''])
|
||||
let last = remove(stderr, -1)
|
||||
let a:data[0] = last.a:data[0]
|
||||
call extend(stderr, a:data)
|
||||
let s:stderr[a:chan_id] = stderr
|
||||
endfunction
|
||||
let s:job_opts = {'rpc': v:true, 'on_stderr': function('provider#stderr_collector')}
|
||||
|
||||
function! provider#pythonx#Require(host) abort
|
||||
let ver = (a:host.orig_name ==# 'python') ? 2 : 3
|
||||
@ -38,9 +28,11 @@ function! provider#pythonx#Require(host) abort
|
||||
catch
|
||||
echomsg v:throwpoint
|
||||
echomsg v:exception
|
||||
for row in get(s:stderr, channel_id, [])
|
||||
for row in provider#get_stderr(channel_id)
|
||||
echomsg row
|
||||
endfor
|
||||
finally
|
||||
call provider#clear_stderr(channel_id)
|
||||
endtry
|
||||
throw remote#host#LoadErrorForHost(a:host.orig_name,
|
||||
\ '$NVIM_PYTHON_LOG_FILE')
|
||||
|
@ -15,30 +15,17 @@ function! tutor#SetupVim()
|
||||
endif
|
||||
endfunction
|
||||
|
||||
" Mappings: {{{1
|
||||
|
||||
function! s:CheckMaps()
|
||||
nmap
|
||||
" Loads metadata file, if available
|
||||
function! tutor#LoadMetadata()
|
||||
let b:tutor_metadata = json_decode(join(readfile(expand('%').'.json'), "\n"))
|
||||
endfunction
|
||||
|
||||
function! s:MapKeyWithRedirect(key, cmd)
|
||||
if maparg(a:key) !=# ''
|
||||
redir => l:keys
|
||||
silent call s:CheckMaps()
|
||||
redir END
|
||||
let l:key_list = split(l:keys, '\n')
|
||||
" Mappings: {{{1
|
||||
|
||||
let l:raw_map = filter(copy(l:key_list), "v:val =~# '\\* ".a:key."'")
|
||||
if len(l:raw_map) == 0
|
||||
exe "nnoremap <buffer> <expr> ".a:key." ".a:cmd
|
||||
return
|
||||
endif
|
||||
let l:map_data = split(l:raw_map[0], '\s*')
|
||||
|
||||
exe "nnoremap <buffer> <expr> ".l:map_data[0]." ".a:cmd
|
||||
else
|
||||
exe "nnoremap <buffer> <expr> ".a:key." ".a:cmd
|
||||
endif
|
||||
function! tutor#SetNormalMappings()
|
||||
nnoremap <silent> <buffer> <CR> :call tutor#FollowLink(0)<cr>
|
||||
nnoremap <silent> <buffer> <2-LeftMouse> :call tutor#MouseDoubleClick()<cr>
|
||||
nnoremap <buffer> >> :call tutor#InjectCommand()<cr>
|
||||
endfunction
|
||||
|
||||
function! tutor#MouseDoubleClick()
|
||||
@ -46,7 +33,7 @@ function! tutor#MouseDoubleClick()
|
||||
normal! zo
|
||||
else
|
||||
if match(getline('.'), '^#\{1,} ') > -1
|
||||
normal! zc
|
||||
silent normal! zc
|
||||
else
|
||||
call tutor#FollowLink(0)
|
||||
endif
|
||||
@ -59,114 +46,6 @@ function! tutor#InjectCommand()
|
||||
redraw | echohl WarningMsg | echon "tutor: ran" | echohl None | echon " " | echohl Statement | echon l:cmd
|
||||
endfunction
|
||||
|
||||
function! tutor#SetNormalMappings()
|
||||
call s:MapKeyWithRedirect('l', 'tutor#ForwardSkipConceal(v:count1)')
|
||||
call s:MapKeyWithRedirect('h', 'tutor#BackwardSkipConceal(v:count1)')
|
||||
call s:MapKeyWithRedirect('<right>', 'tutor#ForwardSkipConceal(v:count1)')
|
||||
call s:MapKeyWithRedirect('<left>', 'tutor#BackwardSkipConceal(v:count1)')
|
||||
|
||||
nnoremap <silent> <buffer> <CR> :call tutor#FollowLink(0)<cr>
|
||||
nnoremap <silent> <buffer> <2-LeftMouse> :call tutor#MouseDoubleClick()<cr>
|
||||
nnoremap <buffer> >> :call tutor#InjectCommand()<cr>
|
||||
endfunction
|
||||
|
||||
function! tutor#SetSampleTextMappings()
|
||||
noremap <silent> <buffer> A :if match(getline('.'), '^--->') > -1 \| call search('\s{\@=', 'Wc') \| startinsert \| else \| startinsert! \| endif<cr>
|
||||
noremap <silent> <buffer> $ :if match(getline('.'), '^--->') > -1 \| call search('.\s{\@=', 'Wc') \| else \| call search('$', 'Wc') \| endif<cr>
|
||||
onoremap <silent> <buffer> $ :if match(getline('.'), '^--->') > -1 \| call search('.\s{\@=', 'Wc') \| else \| call search('$', 'Wc') \| endif<cr>
|
||||
noremap <silent> <buffer> ^ :if match(getline('.'), '^--->') > -1 \| call search('\(--->\s\)\@<=.', 'bcW') \| else \| call search('^', 'bcW') \|endif<cr>
|
||||
onoremap <silent> <buffer> ^ :if match(getline('.'), '^--->') > -1 \| call search('\(--->\s\)\@<=.', 'bcW') \| else \| call search('^', 'bcW') \|endif<cr>
|
||||
nmap <silent> <buffer> 0 ^<esc>
|
||||
nmap <silent> <buffer> <Home> ^<esc>
|
||||
nmap <silent> <buffer> <End> $
|
||||
imap <silent> <buffer> <Home> <esc>^<esc>:startinsert<cr>
|
||||
imap <silent> <buffer> <End> <esc>$:startinsert<cr>
|
||||
noremap <silent> <buffer> I :exe "normal! 0" \| startinsert<cr>
|
||||
endfunction
|
||||
|
||||
" Navigation: {{{1
|
||||
|
||||
" taken from http://stackoverflow.com/a/24224578
|
||||
|
||||
function! tutor#ForwardSkipConceal(count)
|
||||
let cnt=a:count
|
||||
let mvcnt=0
|
||||
let c=col('.')
|
||||
let l=line('.')
|
||||
let lc=col('$')
|
||||
let line=getline('.')
|
||||
while cnt
|
||||
if c>=lc
|
||||
let mvcnt+=cnt
|
||||
break
|
||||
endif
|
||||
if stridx(&concealcursor, 'n')==-1
|
||||
let isconcealed=0
|
||||
else
|
||||
let [isconcealed, cchar, group] = synconcealed(l, c)
|
||||
endif
|
||||
if isconcealed
|
||||
let cnt-=strchars(cchar)
|
||||
let oldc=c
|
||||
let c+=1
|
||||
while c < lc
|
||||
let [isconcealed2, cchar2, group2] = synconcealed(l, c)
|
||||
if !isconcealed2 || cchar2 != cchar
|
||||
break
|
||||
endif
|
||||
let c+= 1
|
||||
endwhile
|
||||
let mvcnt+=strchars(line[oldc-1:c-2])
|
||||
else
|
||||
let cnt-=1
|
||||
let mvcnt+=1
|
||||
let c+=len(matchstr(line[c-1:], '.'))
|
||||
endif
|
||||
endwhile
|
||||
return mvcnt.'l'
|
||||
endfunction
|
||||
|
||||
function! tutor#BackwardSkipConceal(count)
|
||||
let cnt=a:count
|
||||
let mvcnt=0
|
||||
let c=col('.')
|
||||
let l=line('.')
|
||||
let lc=0
|
||||
let line=getline('.')
|
||||
while cnt
|
||||
if c<=1
|
||||
let mvcnt+=cnt
|
||||
break
|
||||
endif
|
||||
if stridx(&concealcursor, 'n')==-1 || c == 0
|
||||
let isconcealed=0
|
||||
else
|
||||
let [isconcealed, cchar, group]=synconcealed(l, c-1)
|
||||
endif
|
||||
if isconcealed
|
||||
let cnt-=strchars(cchar)
|
||||
let oldc=c
|
||||
let c-=1
|
||||
while c>1
|
||||
let [isconcealed2, cchar2, group2] = synconcealed(l, c-1)
|
||||
if !isconcealed2 || cchar2 != cchar
|
||||
break
|
||||
endif
|
||||
let c-=1
|
||||
endwhile
|
||||
let c = max([c, 1])
|
||||
let mvcnt+=strchars(line[c-1:oldc-2])
|
||||
else
|
||||
let cnt-=1
|
||||
let mvcnt+=1
|
||||
let c-=len(matchstr(line[:c-2], '.$'))
|
||||
endif
|
||||
endwhile
|
||||
return mvcnt.'h'
|
||||
endfunction
|
||||
|
||||
" Hypertext: {{{1
|
||||
|
||||
function! tutor#FollowLink(force)
|
||||
let l:stack_s = join(map(synstack(line('.'), col('.')), 'synIDattr(v:val, "name")'), '')
|
||||
if l:stack_s =~# 'tutorLink'
|
||||
@ -209,42 +88,40 @@ function! tutor#InfoText()
|
||||
return join(l:info_parts, " ")
|
||||
endfunction
|
||||
|
||||
" Marks {{{1
|
||||
function! tutor#PlaceXMarks()
|
||||
call cursor(1, 1)
|
||||
let b:tutor_sign_id = 1
|
||||
while search('^--->', 'W') > 0
|
||||
call tutor#CheckText(getline('.'))
|
||||
let b:tutor_sign_id+=1
|
||||
endwhile
|
||||
call cursor(1, 1)
|
||||
|
||||
" Marks: {{{1
|
||||
|
||||
function! tutor#ApplyMarks()
|
||||
hi! link tutorExpect Special
|
||||
if exists('b:tutor_metadata') && has_key(b:tutor_metadata, 'expect')
|
||||
let b:tutor_sign_id = 1
|
||||
for expct in keys(b:tutor_metadata['expect'])
|
||||
let lnum = eval(expct)
|
||||
call matchaddpos('tutorExpect', [lnum])
|
||||
call tutor#CheckLine(lnum)
|
||||
endfor
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! tutor#CheckText(text)
|
||||
if match(a:text, '{expect:ANYTHING}\s*$') == -1
|
||||
if match(getline('.'), '^--->\s*$') > -1
|
||||
exe "sign place ".b:tutor_sign_id." line=".line('.')." name=tutorbad buffer=".bufnr('%')
|
||||
else
|
||||
if match(getline('.'), '|expect:.\+|') == -1
|
||||
let l:cur_text = matchstr(a:text, '---> \zs.\{-}\ze {expect:')
|
||||
let l:expected_text = matchstr(a:text, '{expect:\zs.*\ze}\s*$')
|
||||
else
|
||||
let l:cur_text = matchstr(a:text, '---> \zs.\{-}\ze |expect:')
|
||||
let l:expected_text = matchstr(a:text, '|expect:\zs.*\ze|\s*$')
|
||||
endif
|
||||
if l:cur_text ==# l:expected_text
|
||||
exe "sign place ".b:tutor_sign_id." line=".line('.')." name=tutorok buffer=".bufnr('%')
|
||||
else
|
||||
exe "sign place ".b:tutor_sign_id." line=".line('.')." name=tutorbad buffer=".bufnr('%')
|
||||
endif
|
||||
function! tutor#ApplyMarksOnChanged()
|
||||
if exists('b:tutor_metadata') && has_key(b:tutor_metadata, 'expect')
|
||||
let lnum = line('.')
|
||||
if index(keys(b:tutor_metadata['expect']), string(lnum)) > -1
|
||||
call tutor#CheckLine(lnum)
|
||||
endif
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! tutor#OnTextChanged()
|
||||
let l:text = getline('.')
|
||||
if match(l:text, '^--->') > -1
|
||||
call tutor#CheckText(l:text)
|
||||
function! tutor#CheckLine(line)
|
||||
if exists('b:tutor_metadata') && has_key(b:tutor_metadata, 'expect')
|
||||
let bufn = bufnr('%')
|
||||
let ctext = getline(a:line)
|
||||
if b:tutor_metadata['expect'][string(a:line)] == -1 || ctext ==# b:tutor_metadata['expect'][string(a:line)]
|
||||
exe "sign place ".b:tutor_sign_id." line=".a:line." name=tutorok buffer=".bufn
|
||||
else
|
||||
exe "sign place ".b:tutor_sign_id." line=".a:line." name=tutorbad buffer=".bufn
|
||||
endif
|
||||
let b:tutor_sign_id+=1
|
||||
endif
|
||||
endfunction
|
||||
|
||||
|
@ -861,8 +861,7 @@ Exceptions:
|
||||
Substitute with an expression *sub-replace-expression*
|
||||
*sub-replace-\=* *s/\=*
|
||||
When the substitute string starts with "\=" the remainder is interpreted as an
|
||||
expression. This does not work recursively: a |substitute()| function inside
|
||||
the expression cannot use "\=" for the substitute string.
|
||||
expression.
|
||||
|
||||
The special meaning for characters as mentioned at |sub-replace-special| does
|
||||
not apply except for "<CR>". A <NL> character is used as a line break, you
|
||||
|
@ -143,7 +143,7 @@ a standard meaning:
|
||||
Two 2 Hook
|
||||
Nine 9 Horn
|
||||
|
||||
Equals = Cyrillic (= used as second char)
|
||||
Equals = Cyrillic (= used as second char)
|
||||
Asterisk * Greek
|
||||
Percent sign % Greek/Cyrillic special
|
||||
Plus + smalls: Arabic, capitals: Hebrew
|
||||
@ -922,6 +922,7 @@ char digraph hex dec official name ~
|
||||
† /- 2020 8224 DAGGER
|
||||
‡ /= 2021 8225 DOUBLE DAGGER
|
||||
‥ .. 2025 8229 TWO DOT LEADER
|
||||
… ,. 2026 8230 HORIZONTAL ELLIPSIS
|
||||
‰ %0 2030 8240 PER MILLE SIGN
|
||||
′ 1' 2032 8242 PRIME
|
||||
″ 2' 2033 8243 DOUBLE PRIME
|
||||
|
@ -4046,7 +4046,9 @@ getcompletion({pat}, {type} [, {filtered}]) *getcompletion()*
|
||||
locale locale names (as output of locale -a)
|
||||
mapping mapping name
|
||||
menu menus
|
||||
messages |:messages| suboptions
|
||||
option options
|
||||
packadd optional package |pack-add| names
|
||||
shellcmd Shell command
|
||||
sign |:sign| suboptions
|
||||
syntax syntax file names |'syntax'|
|
||||
@ -4273,7 +4275,8 @@ getqflist([{what}]) *getqflist()*
|
||||
If the optional {what} dictionary argument is supplied, then
|
||||
returns only the items listed in {what} as a dictionary. The
|
||||
following string items are supported in {what}:
|
||||
nr get information for this quickfix list
|
||||
nr get information for this quickfix list; zero
|
||||
means the current quickfix list
|
||||
title get the list title
|
||||
winid get the |window-ID| (if opened)
|
||||
all all of the above quickfix properties
|
||||
@ -5526,6 +5529,51 @@ max({expr}) Return the maximum value of all items in {expr}.
|
||||
items in {expr} cannot be used as a Number this results in
|
||||
an error. An empty |List| or |Dictionary| results in zero.
|
||||
|
||||
menu_get({path}, {modes}) *menu_get()*
|
||||
Returns a |List| of |Dictionaries| describing |menus| (defined
|
||||
by |:menu|, |:amenu|, etc.).
|
||||
{path} limits the result to a subtree of the menu hierarchy
|
||||
(empty string matches all menus). E.g. to get items in the
|
||||
"File" menu subtree: >
|
||||
:echo menu_get('File','')
|
||||
<
|
||||
{modes} is a string of zero or more modes (see |maparg()| or
|
||||
|creating-menus| for the list of modes). "a" means "all".
|
||||
|
||||
For example: >
|
||||
nnoremenu &Test.Test inormal
|
||||
inoremenu Test.Test insert
|
||||
vnoremenu Test.Test x
|
||||
echo menu_get("")
|
||||
<
|
||||
returns something like this:
|
||||
>
|
||||
[ {
|
||||
"hidden": 0,
|
||||
"name": "Test",
|
||||
"priority": 500,
|
||||
"shortcut": 84,
|
||||
"submenus": [ {
|
||||
"hidden": 0,
|
||||
"mappings": {
|
||||
i": {
|
||||
"enabled": 1,
|
||||
"noremap": 1,
|
||||
"rhs": "insert",
|
||||
"sid": 1,
|
||||
"silent": 0
|
||||
},
|
||||
n": { ... },
|
||||
s": { ... },
|
||||
v": { ... }
|
||||
},
|
||||
"name": "Test",
|
||||
"priority": 500,
|
||||
"shortcut": 0
|
||||
} ]
|
||||
} ]
|
||||
<
|
||||
|
||||
*min()*
|
||||
min({expr}) Return the minimum value of all items in {expr}.
|
||||
{expr} can be a list or a dictionary. For a dictionary,
|
||||
@ -5984,9 +6032,9 @@ range({expr} [, {max} [, {stride}]]) *range()*
|
||||
*readfile()*
|
||||
readfile({fname} [, {binary} [, {max}]])
|
||||
Read file {fname} and return a |List|, each line of the file
|
||||
as an item. Lines broken at NL characters. Macintosh files
|
||||
separated with CR will result in a single long line (unless a
|
||||
NL appears somewhere).
|
||||
as an item. Lines are broken at NL characters. Macintosh
|
||||
files separated with CR will result in a single long line
|
||||
(unless a NL appears somewhere).
|
||||
All NUL characters are replaced with a NL character.
|
||||
When {binary} contains "b" binary mode is used:
|
||||
- When the last line ends in a NL an extra empty list item is
|
||||
@ -6504,15 +6552,27 @@ serverlist() *serverlist()*
|
||||
nvim --cmd "echo serverlist()" --cmd "q"
|
||||
<
|
||||
serverstart([{address}]) *serverstart()*
|
||||
Opens a TCP socket (IPv4/IPv6), Unix domain socket (Unix),
|
||||
or named pipe (Windows) at {address} for clients to connect
|
||||
to and returns {address}.
|
||||
Opens a socket or named pipe at {address} and listens for
|
||||
|RPC| messages. Clients can send |API| commands to the address
|
||||
to control Nvim. Returns the address string.
|
||||
|
||||
If {address} contains `:`, a TCP socket is used. Everything in
|
||||
front of the last occurrence of `:` is the IP or hostname,
|
||||
everything after it the port. If the port is empty or `0`,
|
||||
a random port will be assigned.
|
||||
If {address} does not contain a colon ":" it is interpreted as
|
||||
a named pipe or Unix domain socket path.
|
||||
|
||||
Example: >
|
||||
if has('win32')
|
||||
call serverstart('\\.\pipe\nvim-pipe-1234')
|
||||
else
|
||||
call serverstart('nvim.sock')
|
||||
endif
|
||||
<
|
||||
If {address} contains a colon ":" it is interpreted as a TCP
|
||||
address where the last ":" separates the host and port.
|
||||
Assigns a random port if it is empty or 0. Supports IPv4/IPv6.
|
||||
|
||||
Example: >
|
||||
:call serverstart('::1:12345')
|
||||
<
|
||||
If no address is given, it is equivalent to: >
|
||||
:call serverstart(tempname())
|
||||
|
||||
@ -7291,6 +7351,9 @@ submatch({nr}[, {list}]) *submatch()* *E935*
|
||||
|substitute()| this list will always contain one or zero
|
||||
items, since there are no real line breaks.
|
||||
|
||||
When substitute() is used recursively only the submatches in
|
||||
the current (deepest) call can be obtained.
|
||||
|
||||
Example: >
|
||||
:s/\d\+/\=submatch(0) + 1/
|
||||
< This finds the first number in the line and adds one to it.
|
||||
|
@ -249,8 +249,7 @@ Vi "the original". Without further remarks this is the version
|
||||
of Vi that appeared in Sun OS 4.x. ":version" returns
|
||||
"Version 3.7, 6/7/85". Sometimes other versions are referred
|
||||
to. Only runs under Unix. Source code only available with a
|
||||
license. More information on Vi can be found through:
|
||||
http://vi-editor.org [doesn't currently work...]
|
||||
license.
|
||||
*Nvi*
|
||||
Nvi The "New" Vi. The version of Vi that comes with BSD 4.4 and FreeBSD.
|
||||
Very good compatibility with the original Vi, with a few extensions.
|
||||
|
@ -1202,6 +1202,7 @@ completion can be enabled:
|
||||
-complete=locale locale names (as output of locale -a)
|
||||
-complete=mapping mapping name
|
||||
-complete=menu menus
|
||||
-complete=messages |:messages| suboptions
|
||||
-complete=option options
|
||||
-complete=packadd optional package |pack-add| names
|
||||
-complete=shellcmd Shell command
|
||||
|
@ -6,6 +6,8 @@
|
||||
|
||||
Nvim *nvim* *nvim-intro*
|
||||
|
||||
Nvim is based on Vim by Bram Moolenaar.
|
||||
|
||||
If you are new to Vim see |help.txt|, or type ":Tutor".
|
||||
If you already use Vim see |nvim-from-vim| for a quickstart.
|
||||
|
||||
|
@ -2736,7 +2736,7 @@ A jump table for the options with a short description can be found at |Q_op|.
|
||||
'guicursor' 'gcr' string (default "n-v-c-sm:block,i-ci-ve:ver25,r-cr-o:hor20")
|
||||
global
|
||||
Configures the cursor style for each mode. Works in the GUI and many
|
||||
terminals. See |cursor-shape| for details.
|
||||
terminals. See |tui-cursor-shape|.
|
||||
|
||||
To disable cursor-styling, reset the option: >
|
||||
:set guicursor=
|
||||
|
@ -349,6 +349,9 @@ argument.
|
||||
*--api-info*
|
||||
--api-info Print msgpack-encoded |api-metadata| and exit.
|
||||
|
||||
*--headless*
|
||||
--headless Do not start the built-in UI.
|
||||
|
||||
==============================================================================
|
||||
2. Initialization *initialization* *startup*
|
||||
|
||||
|
@ -1,76 +1,62 @@
|
||||
*term.txt* Nvim
|
||||
|
||||
|
||||
VIM REFERENCE MANUAL by Bram Moolenaar
|
||||
NVIM REFERENCE MANUAL
|
||||
|
||||
|
||||
Terminal information
|
||||
|
||||
Vim uses information about the terminal you are using to fill the screen and
|
||||
recognize what keys you hit. If this information is not correct, the screen
|
||||
may be messed up or keys may not be recognized. The actions which have to be
|
||||
performed on the screen are accomplished by outputting a string of
|
||||
characters.
|
||||
Nvim (except in |--headless| mode) uses information about the terminal you are
|
||||
using to present a built-in UI. If that information is not correct, the
|
||||
screen may be messed up or keys may not be recognized.
|
||||
|
||||
Type <M-]> to see the table of contents.
|
||||
|
||||
==============================================================================
|
||||
Startup *startup-terminal*
|
||||
|
||||
When Vim is started a default terminal type is assumed. for MS-DOS this is
|
||||
the pc terminal, for Unix an ansi terminal.
|
||||
Nvim (except in |--headless| mode) guesses a terminal type when it starts.
|
||||
|$TERM| is the primary hint that determines the terminal type.
|
||||
|
||||
*terminfo* *E557* *E558* *E559*
|
||||
On Unix the terminfo database is used. There is no access to the terminfo
|
||||
settings with |:set|.
|
||||
The terminfo database is used if available.
|
||||
|
||||
The Unibilium library (used by Nvim to read terminfo) allows you to override
|
||||
an out-of-date system terminfo database with one in your $HOME/.terminfo/
|
||||
directory, in part or in whole.
|
||||
the system terminfo with one in $HOME/.terminfo/ directory, in part or in
|
||||
whole.
|
||||
|
||||
Building your own up-to-date terminfo database is usually as simple as running
|
||||
this as a non-superuser:
|
||||
Building your own terminfo is usually as simple as running this as
|
||||
a non-superuser:
|
||||
>
|
||||
wget http://invisible-island.net/datafiles/current/terminfo.src.gz
|
||||
curl -LO http://invisible-island.net/datafiles/current/terminfo.src.gz
|
||||
gunzip terminfo.src.gz
|
||||
tic terminfo.src
|
||||
<
|
||||
*TERM*
|
||||
If you experience terminal difficulties, first ensure that you have set the
|
||||
correct terminal type in your $TERM environment variable so that Nvim is
|
||||
pulling the correct entry from the terminfo database in the first place.
|
||||
*$TERM*
|
||||
The $TERM environment variable must match the terminal you are using!
|
||||
Otherwise Nvim cannot know what sequences your terminal expects, and weird
|
||||
or sub-optimal behavior will result (scrolling quirks, wrong colors, etc.).
|
||||
|
||||
Per the terminfo source file from ncurses:
|
||||
$TERM is also important because it is mirrored by SSH to the remote session,
|
||||
unlike other common client-end environment variables ($COLORTERM,
|
||||
$XTERM_VERSION, $VTE_VERSION, $KONSOLE_PROFILE_NAME, $TERM_PROGRAM, ...).
|
||||
|
||||
For these terminals Set $TERM to |builtin-terms|?
|
||||
For this terminal Set $TERM to |builtin-terms|?
|
||||
|
||||
iTerm.app "iterm" or "iTerm.app" Y
|
||||
anything libvte based "vte" or "vte-256color" Y
|
||||
(e.g. GNOME Terminal) ("gnome" and "gnome-256color" are
|
||||
available as aliases for these)
|
||||
(e.g. GNOME Terminal) (aliases: "gnome", "gnome-256color")
|
||||
tmux "tmux" or "tmux-256color" Y
|
||||
screen "screen" or "screen-256color" Y
|
||||
PuTTY "putty" or "putty-256color" Y
|
||||
Terminal.app "nsterm" N
|
||||
Linux virtual terminal "linux" or "linux-256color" Y
|
||||
|
||||
Describing any of these as "xterm" or "xterm-256colour" will not describe the
|
||||
terminal correctly to Nvim, and will cause various kinds of problematic
|
||||
behaviours.
|
||||
|
||||
Setting your $TERM environment variable to the correct value also avoids the
|
||||
problem that SSH does not mirror arbitrary client-end environment variables
|
||||
such as $COLORTERM, $XTERM_VERSION, $VTE_VERSION, $KONSOLE_PROFILE_NAME, and
|
||||
$TERM_PROGRAM to the server end, whereas it does send the $TERM environment
|
||||
variable.
|
||||
|
||||
See |terminfo| for dealing with out of date terminfo databases.
|
||||
|
||||
*builtin-terms* *builtin_terms*
|
||||
If a |terminfo| database is not available, or no entry for the terminal type is
|
||||
found in that database, Nvim will look up the terminal type in a compiled-in
|
||||
mini-database of terminfo entries for "xterm", "putty", "screen", "tmux",
|
||||
"rxvt", "iterm", "interix", "linux", "st", "vte", "gnome", and "ansi".
|
||||
found in that database, Nvim will use a compiled-in mini-database of terminfo
|
||||
entries for "xterm", "putty", "screen", "tmux", "rxvt", "iterm", "interix",
|
||||
"linux", "st", "vte", "gnome", and "ansi".
|
||||
|
||||
The lookup matches the initial portion of the terminal type, so (for example)
|
||||
"putty-256color" and "putty" will both be mapped to the built-in "putty"
|
||||
@ -87,8 +73,8 @@ supplying an external one with entries for the terminal type.
|
||||
|
||||
Settings depending on terminal *term-dependent-settings*
|
||||
|
||||
If you want to set options or mappings, depending on the terminal name, you
|
||||
can do this best in your init.vim. Example: >
|
||||
If you want to set terminal-dependent options or mappings, you can do this in
|
||||
your init.vim. Example: >
|
||||
|
||||
if $TERM =~ '^\(rxvt\|screen\|interix\|putty\)\(-.*\)\?$'
|
||||
set notermguicolors
|
||||
@ -127,62 +113,49 @@ variable, set by genuine Xterm, that it looks for is not automatically
|
||||
replicated over an SSH login session.
|
||||
|
||||
*256-color* *terminfo-colors* *termcap-colors*
|
||||
Nvim can make use of 256-colour terminals and tries to do so whereever it can.
|
||||
Nvim uses 256 colours by default, ignoring |terminfo| for most terminal types,
|
||||
including "linux" (whose virtual terminals have had 256-colour support since
|
||||
4.8) and anything claiming to be "xterm". Also when $COLORTERM or $TERM
|
||||
contain the string "256".
|
||||
|
||||
If the |terminfo| description of the terminal says that it supports fewer
|
||||
colours, Nvim will override this for many terminal types, including "linux"
|
||||
(whose virtual terminals have had 256-colour support since version 4.8) and
|
||||
anything (even if falsely) claiming to be "xterm". It will also set 256
|
||||
colours when the COLORTERM or TERM environment variables contain the string
|
||||
"256" somewhere.
|
||||
|
||||
Nvim similarly assumes that any terminal emulator that sets the COLORTERM
|
||||
environment variable at all, to anything, is capable of at least 16-colour
|
||||
operation; and it will override |terminfo| saying that it has fewer colours
|
||||
available.
|
||||
Nvim similarly assumes that any terminal emulator that sets $COLORTERM to any
|
||||
value, is capable of at least 16-colour operation.
|
||||
|
||||
*true-color* *xterm-true-color*
|
||||
Nvim supports using true (24-bit) colours in the terminal, on terminals that
|
||||
support it. It uses the same |terminfo| extensions that were proposed by
|
||||
Rüdiger Sonderfeld in 2013 for this: "setrgbf" and "setrgbb". If your
|
||||
terminfo definition specifies these, then nothing more is required.
|
||||
Nvim emits true (24-bit) colours in the terminal, if 'termguicolors' is set.
|
||||
|
||||
If your terminfo definition is missing them, then Nvim will decide whether to
|
||||
add them to your terminfo definition, using the ISO 8613-6:1994/ITU T.416:1993
|
||||
control sequences for setting RGB colours, but modified to use semicolons
|
||||
instead of colons unless the terminal is known to follow the standard.
|
||||
(Semicolons cause ambiguities that the standard avoided by specifying colons
|
||||
as a sub-parameter delimiter. A historical misunderstanding meant that many
|
||||
terminal emulators ended up using semicolons for many years, though.)
|
||||
It uses the "setrgbf" and "setrgbb" |terminfo| extensions (proposed by Rüdiger
|
||||
Sonderfeld in 2013). If your terminfo definition is missing them, then Nvim
|
||||
will decide whether to add them to your terminfo definition, using the ISO
|
||||
8613-6:1994/ITU T.416:1993 control sequences for setting RGB colours (but
|
||||
modified to use semicolons instead of colons unless the terminal is known to
|
||||
follow the standard).
|
||||
|
||||
A new convention, pioneered in 2016 by tmux, is the "Tc" terminfo extension.
|
||||
If your terminal's terminfo definition has this flag, Nvim will add
|
||||
constructed "setrgbf" and "setrgbb" capabilities as if they had been in the
|
||||
terminfo definition.
|
||||
Another convention, pioneered in 2016 by tmux, is the "Tc" terminfo extension.
|
||||
If terminfo has this flag, Nvim will add constructed "setrgbf" and "setrgbb"
|
||||
capabilities as if they had been in the terminfo definition.
|
||||
|
||||
If your terminal's terminfo definition does not (yet) have this flag, Nvim
|
||||
will fall back to looking at the TERM and other environment variables. It
|
||||
will add constructed "setrgbf" and "setrgbb" capabilities in the case of the
|
||||
the "rxvt", "linux", "st", "tmux", and "iterm" terminal types, or when
|
||||
Konsole, genuine Xterm, a libvte terminal emulator version 0.36 or later, or a
|
||||
terminal emulator that sets the COLORTERM environment variable to "truecolor"
|
||||
is detected.
|
||||
If terminfo does not (yet) have this flag, Nvim will fall back to $TERM and
|
||||
other environment variables. It will add constructed "setrgbf" and "setrgbb"
|
||||
capabilities in the case of the the "rxvt", "linux", "st", "tmux", and "iterm"
|
||||
terminal types, or when Konsole, genuine Xterm, a libvte terminal emulator
|
||||
version 0.36 or later, or a terminal emulator that sets the COLORTERM
|
||||
environment variable to "truecolor" is detected.
|
||||
|
||||
*xterm-resize*
|
||||
Nvim can resize the terminal display on some terminals that implement an
|
||||
extension pioneered by the dtterm program. |terminfo| does not have a flag
|
||||
for this extension. So Nvim simply assumes that (all) "dtterm", "xterm",
|
||||
"teraterm", "rxvt" terminal types, and Konsole, are capable of this.
|
||||
extension pioneered by dtterm. |terminfo| does not have a flag for this
|
||||
extension. So Nvim simply assumes that (all) "dtterm", "xterm", "teraterm",
|
||||
"rxvt" terminal types, and Konsole, are capable of this.
|
||||
|
||||
*cursor-shape* *terminfo-cursor-shape* *termcap-cursor-shape*
|
||||
*tui-cursor-shape*
|
||||
Nvim will adjust the shape of the cursor from a block to a line when in insert
|
||||
mode (or as specified by the 'guicursor' option), on terminals that support
|
||||
it. It uses the same |terminfo| extensions that were pioneered by tmux for
|
||||
this: "Ss" and "Se". If your terminfo definition specifies these, as some
|
||||
(such as those based upon "xterm+tmux") do, then nothing more is required.
|
||||
this: "Ss" and "Se".
|
||||
|
||||
If your terminfo definition is missing them, then Nvim will decide whether to
|
||||
add them to your terminfo definition, by looking at the TERM and other
|
||||
add them to your terminfo definition, by looking at $TERM and other
|
||||
environment variables. For the "rxvt", "putty", "linux", "screen",
|
||||
"teraterm", and "iterm" terminal types, or when Konsole, a libvte-based
|
||||
terminal emulator, or genuine Xterm are detected, it will add constructed
|
||||
@ -195,19 +168,14 @@ receives from Nvim into whatever control sequence is appropriate for the
|
||||
terminal that it is outputting to. It shares a common mechanism with Nvim, of
|
||||
using the "Ss" and "Se" capabilities from terminfo (for the output terminal)
|
||||
if they are present. Unlike Nvim, if they are not present in terminfo you
|
||||
will have to add them by setting the tmux "terminal-overrides" setting in
|
||||
$HOME/.tmux.conf .
|
||||
must add them by setting "terminal-overrides" in ~/.tmux.conf .
|
||||
|
||||
See the tmux(1) manual page for the details of how and what to do in the tmux
|
||||
configuration file. It will look something like: >
|
||||
|
||||
set -ga terminal-overrides '*:Ss=\E[%p1%d q:Se=\E[ q'
|
||||
set -ga terminal-overrides '*:Ss=\E[%p1%d q:Se=\E[ q'
|
||||
<or (alas!) for Konsole specifically, something more complex like: >
|
||||
set -ga terminal-overrides \
|
||||
'xterm*:\E]50;CursorShape=%?%p1%{3}%<%t%{0}%e%{1}%;%d\007'
|
||||
<but these are only rough examples that do not include all of the other stuff
|
||||
that occurs in that setting.
|
||||
|
||||
set -ga terminal-overrides 'xterm*:\E]50;CursorShape=%?%p1%{3}%<%t%{0}%e%{1}%;%d\007'
|
||||
<
|
||||
*cs7-problem*
|
||||
Note: If the terminal settings are changed after running Vim, you might have
|
||||
an illegal combination of settings. This has been reported on Solaris 2.5
|
||||
|
@ -79,8 +79,8 @@ Working intuitively and consistently is a major goal of Nvim. Examples:
|
||||
avoids features that cannot be provided on all platforms--instead that is
|
||||
delegated to external plugins/extensions.
|
||||
|
||||
- Test-only globals and functions such as test_autochdir(), test_settime(),
|
||||
etc., are not exposed (because they don't exist).
|
||||
- Vim's internal test functions (test_autochdir(), test_settime(), etc.) are
|
||||
not exposed (nor implemented); instead Nvim has a robust API.
|
||||
|
||||
ARCHITECTURE ~
|
||||
|
||||
@ -89,6 +89,9 @@ stability and allows those plugins to work without blocking the editor. Even
|
||||
"legacy" Python and Ruby plugins which use the old Vim interfaces (|if_py| and
|
||||
|if_ruby|) run out-of-process.
|
||||
|
||||
Platform and I/O facilities are built upon libuv. Nvim benefits from libuv
|
||||
features and bug fixes, and other projects benefit from improvements to libuv
|
||||
by Nvim developers.
|
||||
|
||||
FEATURES ~
|
||||
|
||||
@ -126,6 +129,7 @@ Commands:
|
||||
Functions:
|
||||
|dictwatcheradd()| notifies a callback whenever a |Dict| is modified
|
||||
|dictwatcherdel()|
|
||||
|menu_get()|
|
||||
|msgpackdump()|, |msgpackparse()| provide msgpack de/serialization
|
||||
|
||||
Events:
|
||||
|
@ -19,27 +19,30 @@ setlocal noundofile
|
||||
setlocal keywordprg=:help
|
||||
setlocal iskeyword=@,-,_
|
||||
|
||||
setlocal foldmethod=expr
|
||||
" The user will have to enable the folds himself, but we provide the foldexpr
|
||||
" function.
|
||||
setlocal foldmethod=manual
|
||||
setlocal foldexpr=tutor#TutorFolds()
|
||||
setlocal foldcolumn=1
|
||||
setlocal foldlevel=4
|
||||
setlocal nowrap
|
||||
|
||||
setlocal statusline=%{toupper(expand('%:t:r'))}\ tutorial%=
|
||||
setlocal statusline+=%{tutor#InfoText()}
|
||||
|
||||
" Load metadata if it exists: {{{1
|
||||
if filereadable(expand('%').'.json')
|
||||
call tutor#LoadMetadata()
|
||||
endif
|
||||
|
||||
" Mappings: {{{1
|
||||
|
||||
call tutor#SetNormalMappings()
|
||||
call tutor#SetSampleTextMappings()
|
||||
|
||||
" Checks: {{{1
|
||||
|
||||
sign define tutorok text=✓ texthl=tutorOK
|
||||
sign define tutorbad text=✗ texthl=tutorX
|
||||
|
||||
if !exists('g:tutor_debug') || g:tutor_debug == 0
|
||||
call tutor#PlaceXMarks()
|
||||
autocmd! TextChanged <buffer> call tutor#OnTextChanged()
|
||||
autocmd! TextChangedI <buffer> call tutor#OnTextChanged()
|
||||
if !exists('g:tutor_debug') || g:tutor_debug == 0
|
||||
call tutor#ApplyMarks()
|
||||
autocmd! TextChanged,TextChangedI <buffer> call tutor#ApplyMarksOnChanged()
|
||||
endif
|
||||
|
@ -31,26 +31,20 @@ syn keyword tutorMarks TODO NOTE IMPORTANT TIP ATTENTION EXERCISE
|
||||
syn keyword tutorMarks todo note tip attention exercise
|
||||
syn keyword tutorMarks Todo Note Tip Excersise
|
||||
|
||||
syn match tutorTextMark /\\\@<!--->/ conceal cchar=→
|
||||
syn region tutorSampleText start=/^\(--->\)\@=/ end=/$/ keepend contains=@SPELL
|
||||
syn match tutorSampleTextMark /^--->/ contained containedin=tutorSampleText conceal cchar=→
|
||||
syn match tutorSampleTextExpect /\}\@<! {expect:.\+}\s*$/ contained containedin=tutorSampleText conceal
|
||||
syn match tutorSampleTextExpect /|\@<! |expect:.\+|\s*$/ contained containedin=tutorSampleText conceal
|
||||
|
||||
syn region tutorCodeblock matchgroup=Delimiter start=/^\~\{3}.*$/ end=/^\~\{3}/
|
||||
|
||||
syn region tutorShell matchgroup=Delimiter start=/^\~\{3} sh\s*$/ end=/^\~\{3}/ keepend contains=@TUTORSHELL concealends
|
||||
syn region tutorShell matchgroup=Delimiter start=/^\~\{3} sh\s*$/ end=/^\~\{3}/ keepend contains=@TUTORSHELL
|
||||
syn match tutorShellPrompt /\(^\s*\)\@<=[$#]/ contained containedin=tutorShell
|
||||
|
||||
syn region tutorInlineCode matchgroup=Delimiter start=/\\\@<!`/ end=/\\\@<!\(`{\@!\|`\s\)/ concealends
|
||||
syn region tutorInlineCode matchgroup=Delimiter start=/\\\@<!`/ end=/\\\@<!\(`{\@!\|`\s\)/
|
||||
|
||||
syn region tutorCommand matchgroup=Delimiter start=/^\~\{3} cmd\( :\)\?\s*$/ end=/^\~\{3}/ keepend contains=@VIM concealends
|
||||
syn region tutorInlineCommand matchgroup=Delimiter start=/\\\@<!`\(.*{vim}\)\@=/ end=/\\\@<!`\({vim}\)\@=/ nextgroup=tutorInlineType contains=@VIM concealends
|
||||
syn region tutorCommand matchgroup=Delimiter start=/^\~\{3} cmd\( :\)\?\s*$/ end=/^\~\{3}/ keepend contains=@VIM
|
||||
syn region tutorInlineCommand matchgroup=Delimiter start=/\\\@<!`\(.*{vim}\)\@=/ end=/\\\@<!`\({vim}\)\@=/ nextgroup=tutorInlineType contains=@VIM
|
||||
|
||||
syn region tutorNormal matchgroup=Delimiter start=/^\~\{3} norm\(al\?\)\?\s*$/ end=/^\~\{3}/ contains=@VIMNORMAL concealends
|
||||
syn region tutorInlineNormal matchgroup=Delimiter start=/\\\@<!`\(\S*{normal}\)\@=/ end=/\\\@<!`\({normal}\)\@=/ nextgroup=tutorInlineType contains=@VIMNORMAL concealends
|
||||
syn region tutorNormal matchgroup=Delimiter start=/^\~\{3} norm\(al\?\)\?\s*$/ end=/^\~\{3}/ contains=@VIMNORMAL
|
||||
syn region tutorInlineNormal matchgroup=Delimiter start=/\\\@<!`\(\S*{normal}\)\@=/ end=/\\\@<!`\({normal}\)\@=/ nextgroup=tutorInlineType contains=@VIMNORMAL
|
||||
|
||||
syn match tutorInlineType /{\(normal\|vim\)}/ contained conceal
|
||||
syn match tutorInlineType /{\(normal\|vim\)}/ contained
|
||||
|
||||
syn match tutorInlineOK /✓/
|
||||
syn match tutorInlineX /✗/
|
||||
@ -72,7 +66,7 @@ hi! tutorMarks cterm=bold gui=bold
|
||||
hi! tutorEmphasis gui=italic cterm=italic
|
||||
hi! tutorBold gui=bold cterm=bold
|
||||
|
||||
hi! link tutorSampleText Special
|
||||
hi! link tutorExpect Special
|
||||
hi! tutorOK ctermfg=green guifg=#00ff88 cterm=bold gui=bold
|
||||
hi! tutorX ctermfg=red guifg=#ff2000 cterm=bold gui=bold
|
||||
hi! link tutorInlineOK tutorOK
|
||||
|
@ -18,10 +18,10 @@ be saved. Don't worry about messing things up; just remember that pressing
|
||||
[<Esc>](<Esc>) and then [u](u) will undo the latest change.
|
||||
|
||||
This tutorial is interactive, and there are a few things you should know.
|
||||
Pressing [<Enter>](<Enter>) over text highlighted [like this](holy-grail) will take you to some relevant
|
||||
help (hopefully), and pressing K over any word will try to do so too. Sometimes
|
||||
you will be required to modify text like
|
||||
---> this here {expect:this here}
|
||||
Pressing [<Enter>](<Enter>) over text highlighted [like this](holy-grail) will take you to some
|
||||
relevant help (hopefully), and pressing K over any word will try to do so too.
|
||||
Sometimes you will be required to modify text like
|
||||
this here
|
||||
Once you have done the changes correctly, the ✗ sign at the left will change
|
||||
to ✓. I imagine you can already see how neat Vim can be ;)
|
||||
Other times, you'll be prompted to run a command (I'll explain this later):
|
||||
@ -99,7 +99,7 @@ NOTE: [:q!](:q) <Enter> discards any changes you made. In a few lessons you
|
||||
|
||||
4. Repeat steps 2 through 4 until the sentence is correct.
|
||||
|
||||
---> The ccow jumpedd ovverr thhe mooon. {expect:The cow jumped over the moon.}
|
||||
The ccow jumpedd ovverr thhe mooon.
|
||||
|
||||
5. Now that the line is correct, go on to Lesson 1.4.
|
||||
|
||||
@ -119,8 +119,8 @@ NOTE: As you go through this tutor, do not try to memorize, learn by usage.
|
||||
4. As each error is fixed press <Esc> to return to Normal mode.
|
||||
Repeat steps 2 through 4 to correct the sentence.
|
||||
|
||||
---> There is text misng this . {expect:There is some text missing from this line.}
|
||||
---> There is some text missing from this line. {expect:There is some text missing from this line.}
|
||||
There is text misng this .
|
||||
There is some text missing from this line.
|
||||
|
||||
5. When you are comfortable inserting text move to lesson 1.5.
|
||||
|
||||
@ -138,10 +138,10 @@ NOTE: As you go through this tutor, do not try to memorize, learn by usage.
|
||||
4. Move the cursor to the second line marked ---> and repeat
|
||||
steps 2 and 3 to correct this sentence.
|
||||
|
||||
---> There is some text missing from th {expect:There is some text missing from this line.}
|
||||
---> There is some text missing from this line. {expect:There is some text missing from this line.}
|
||||
---> There is also some text miss {expect:There is also some text missing here.}
|
||||
---> There is also some text missing here. {expect:There is also some text missing here.}
|
||||
There is some text missing from th
|
||||
There is some text missing from this line.
|
||||
There is also some text miss
|
||||
There is also some text missing here.
|
||||
|
||||
5. When you are comfortable appending text move to lesson 1.6.
|
||||
|
||||
@ -212,7 +212,7 @@ Now continue with Lesson 2.
|
||||
|
||||
4. Type [d](d)[w](w) to make the word disappear.
|
||||
|
||||
---> There are a some words fun that don't belong paper in this sentence. {expect:There are some words that don't belong in this sentence.}
|
||||
There are a some words fun that don't belong paper in this sentence.
|
||||
|
||||
5. Repeat steps 3 and 4 until the sentence is correct and go to Lesson 2.2.
|
||||
|
||||
@ -228,7 +228,7 @@ Now continue with Lesson 2.
|
||||
|
||||
4. Type `d$`{normal} to delete to the end of the line.
|
||||
|
||||
---> Somebody typed the end of this line twice. end of this line twice. {expect:ANYTHING}
|
||||
Somebody typed the end of this line twice. end of this line twice.
|
||||
|
||||
5. Move on to Lesson 2.3 to understand what is happening.
|
||||
|
||||
@ -268,7 +268,7 @@ NOTE: Pressing just the motion while in Normal mode without an operator will
|
||||
|
||||
5. Repeat steps 2 and 3 with different numbers.
|
||||
|
||||
---> This is just a line with words you can move around in. {expect:ANYTHING}
|
||||
This is just a line with words you can move around in.
|
||||
|
||||
6. Move on to Lesson 2.5.
|
||||
|
||||
@ -287,7 +287,7 @@ insert a count before the motion to delete more:
|
||||
3. Repeat steps 1 and 2 with a different count to delete the consecutive
|
||||
UPPER CASE words with one command
|
||||
|
||||
---> this ABC DE line FGHI JK LMN OP of words is Q RS TUV cleaned up. {expect:this line of words is cleaned up.}
|
||||
this ABC DE line FGHI JK LMN OP of words is Q RS TUV cleaned up.
|
||||
|
||||
# Lesson 2.6: OPERATING ON LINES
|
||||
|
||||
@ -301,13 +301,13 @@ insert a count before the motion to delete more:
|
||||
3. Now move to the fourth line.
|
||||
4. Type `2dd`{normal} to delete two lines.
|
||||
|
||||
---> 1) Roses are red, {expect:ANYTHING}
|
||||
---> 2) Mud is fun, {expect:ANYTHING}
|
||||
---> 3) Violets are blue, {expect:ANYTHING}
|
||||
---> 4) I have a car, {expect:ANYTHING}
|
||||
---> 5) Clocks tell time, {expect:ANYTHING}
|
||||
---> 6) Sugar is sweet {expect:ANYTHING}
|
||||
---> 7) And so are you. {expect:ANYTHING}
|
||||
1) Roses are red,
|
||||
2) Mud is fun,
|
||||
3) Violets are blue,
|
||||
4) I have a car,
|
||||
5) Clocks tell time,
|
||||
6) Sugar is sweet
|
||||
7) And so are you.
|
||||
|
||||
# Lesson 2.7: THE UNDO COMMAND
|
||||
|
||||
@ -322,7 +322,7 @@ insert a count before the motion to delete more:
|
||||
6. Now type `u`{normal} a few times to undo the U and preceding commands.
|
||||
7. Now type `<Ctrl-r>`{normal} a few times to redo the commands (undo the undo's).
|
||||
|
||||
---> Fiix the errors oon thhis line and reeplace them witth undo. {expect:Fix the errors on this line and replace them with undo.}
|
||||
Fiix the errors oon thhis line and reeplace them witth undo.
|
||||
|
||||
8. These are very useful commands. Now move on to the Lesson 2 Summary.
|
||||
|
||||
@ -362,10 +362,10 @@ insert a count before the motion to delete more:
|
||||
|
||||
5. Repeat steps 2 through 4 to put all the lines in correct order.
|
||||
|
||||
---> d) Can you learn too? {expect:ANYTHING}
|
||||
---> b) Violets are blue, {expect:ANYTHING}
|
||||
---> c) Intelligence is learned, {expect:ANYTHING}
|
||||
---> a) Roses are red, {expect:ANYTHING}
|
||||
d) Can you learn too?
|
||||
b) Violets are blue,
|
||||
c) Intelligence is learned,
|
||||
a) Roses are red,
|
||||
|
||||
# Lesson 3.2: THE REPLACE COMMAND
|
||||
|
||||
@ -379,8 +379,8 @@ insert a count before the motion to delete more:
|
||||
|
||||
4. Repeat steps 2 and 3 until the first line is equal to the second one.
|
||||
|
||||
---> Whan this lime was tuoed in, someone presswd some wrojg keys! {expect:When this line was typed in, someone pressed some wrong keys!}
|
||||
---> When this line was typed in, someone pressed some wrong keys! {expect:When this line was typed in, someone pressed some wrong keys!}
|
||||
Whan this lime was tuoed in, someone presswd some wrojg keys!
|
||||
When this line was typed in, someone pressed some wrong keys!
|
||||
|
||||
5. Now move on to Lesson 3.3.
|
||||
|
||||
@ -400,8 +400,8 @@ NOTE: Remember that you should be learning by doing, not memorization.
|
||||
|
||||
5. Repeat steps 3 and 4 until the first sentence is the same as the second.
|
||||
|
||||
---> This lubw has a few wptfd that mrrf changing usf the change operator. {expect:This line has a few words that need changing using the change operator.}
|
||||
---> This line has a few words that need changing using the change operator. {expect:This line has a few words that need changing using the change operator.}
|
||||
This lubw has a few wptfd that mrrf changing usf the change operator.
|
||||
This line has a few words that need changing using the change operator.
|
||||
|
||||
Notice that [c](c)e deletes the word and places you in Insert mode.
|
||||
|
||||
@ -421,8 +421,8 @@ Notice that [c](c)e deletes the word and places you in Insert mode.
|
||||
|
||||
5. Type `c$`{normal} and type the rest of the line like the second and press `<Esc>`{normal}.
|
||||
|
||||
---> The end of this line needs some help to make it like the second. {expect:The end of this line needs to be corrected using the c$ command.}
|
||||
---> The end of this line needs to be corrected using the c$ command. {expect:The end of this line needs to be corrected using the c$ command.}
|
||||
The end of this line needs some help to make it like the second.
|
||||
The end of this line needs to be corrected using the c$ command.
|
||||
|
||||
NOTE: You can use the Backspace key to correct mistakes while typing.
|
||||
|
||||
@ -484,7 +484,7 @@ NOTE: You may see the cursor position in the lower right corner of the screen
|
||||
5. To go back to where you came from press `<Ctrl-o>`{normal} (Keep Ctrl down while
|
||||
pressing the letter o). Repeat to go back further. `<Ctrl-i>`{normal} goes forward.
|
||||
|
||||
---> "errroor" is not the way to spell error; errroor is an error. {expect:ANYTHING}
|
||||
"errroor" is not the way to spell error; errroor is an error.
|
||||
|
||||
NOTE: When the search reaches the end of the file it will continue at the
|
||||
start, unless the ['wrapscan']('wrapscan') option has been reset.
|
||||
@ -503,7 +503,7 @@ NOTE: When the search reaches the end of the file it will continue at the
|
||||
|
||||
5. Move the cursor to another (,),[,],{ or } and see what `%`{normal} does.
|
||||
|
||||
---> This ( is a test line with ('s, ['s ] and {'s } in it. )) {expect:ANYTHING}
|
||||
This ( is a test line with ('s, ['s ] and {'s } in it. ))
|
||||
|
||||
NOTE: This is very useful in debugging a program with unmatched parentheses!
|
||||
|
||||
@ -528,7 +528,7 @@ NOTE: This is very useful in debugging a program with unmatched parentheses!
|
||||
Adding the g [flag](:s_flags) means to substitute globally in the line, change
|
||||
all occurrences of "thee" in the line.
|
||||
|
||||
---> thee best time to see thee flowers is in thee spring. {expect:the best time to see the flowers is in the spring.}
|
||||
thee best time to see thee flowers is in thee spring.
|
||||
|
||||
4. To change every occurrence of a character string between two lines, type
|
||||
~~~ cmd
|
||||
@ -719,12 +719,12 @@ NOTE: You can also read the output of an external command. For example,
|
||||
|
||||
3. Now type some text and press `<Esc>`{normal} to exit Insert mode.
|
||||
|
||||
---> After typing o the cursor is placed on the open line in Insert mode. {expect:ANYTHING}
|
||||
After typing o the cursor is placed on the open line in Insert mode.
|
||||
|
||||
4. To open up a line ABOVE the cursor, simply type a [capital O](O), rather
|
||||
than a lowercase `o`{normal}. Try this on the line below.
|
||||
|
||||
---> Open up a line above this by typing O while the cursor is on this line. {expect:ANYTHING}
|
||||
Open up a line above this by typing O while the cursor is on this line.
|
||||
|
||||
# Lesson 6.2: THE APPEND COMMAND
|
||||
|
||||
@ -741,8 +741,8 @@ NOTE: You can also read the output of an external command. For example,
|
||||
|
||||
5. Use `e`{normal} to move to the next incomplete word and repeat steps 3 and 4.
|
||||
|
||||
---> This li will allow you to pract appendi text to a line. {expect:This line will allow you to practice appending text to a line.}
|
||||
---> This line will allow you to practice appending text to a line. {expect:This line will allow you to practice appending text to a line.}
|
||||
This li will allow you to pract appendi text to a line.
|
||||
This line will allow you to practice appending text to a line.
|
||||
|
||||
NOTE: [a](a), [i](i) and [A](A) all go to the same Insert mode, the only difference is where
|
||||
the characters are inserted.
|
||||
@ -762,8 +762,8 @@ NOTE: [a](a), [i](i) and [A](A) all go to the same Insert mode, the only differ
|
||||
|
||||
4. Repeat the steps to replace the remaining "xxx".
|
||||
|
||||
---> Adding 123 to xxx gives you xxx. {expect:Adding 123 to 456 gives you 579.}
|
||||
---> Adding 123 to 456 gives you 579. {expect:Adding 123 to 456 gives you 579.}
|
||||
Adding 123 to xxx gives you xxx.
|
||||
Adding 123 to 456 gives you 579.
|
||||
|
||||
NOTE: Replace mode is like Insert mode, but every typed character deletes an
|
||||
existing character.
|
||||
@ -785,8 +785,8 @@ NOTE: Replace mode is like Insert mode, but every typed character deletes an
|
||||
6. Use Visual mode to select " item.", yank it with `y`{normal}, move to the end of
|
||||
the next line with `j$`{normal} and put the text there with `p`{normal}.
|
||||
|
||||
---> a) this is the first item.
|
||||
---> b) {expect: b) this is the second item}
|
||||
a) this is the first item.
|
||||
b)
|
||||
|
||||
NOTE: you can also use `y`{normal} as an operator; `yw`{normal} yanks one word.
|
||||
|
||||
@ -947,8 +947,10 @@ There are many resources online to learn more about vim. Here's a bunch of them:
|
||||
- Vim Video-Tutorials by Derek Wyatt: http://derekwyatt.org/vim/tutorials/
|
||||
- *Learn Vimscript the Hard Way*: http://learnvimscriptthehardway.stevelosh.com/
|
||||
- *7 Habits of Effective Text Editing*: http://www.moolenaar.net/habits.html
|
||||
- *vim-galore*: https://github.com/mhinz/vim-galore
|
||||
|
||||
If you prefer a book, *Practival Vim* by Drew Neil is recommended often.
|
||||
If you prefer a book, *Practical Vim* by Drew Neil is recommended often (the sequel, *Modern
|
||||
Vim*, includes material specific to nvim!).
|
||||
|
||||
This tutorial was written by Michael C. Pierce and Robert K. Ware, Colorado
|
||||
School of Mines using ideas supplied by Charles Smith, Colorado State
|
||||
|
45
runtime/tutor/en/vim-01-beginner.tutor.json
Normal file
45
runtime/tutor/en/vim-01-beginner.tutor.json
Normal file
@ -0,0 +1,45 @@
|
||||
{
|
||||
"expect": {
|
||||
"24": -1,
|
||||
"102": "The cow jumped over the moon.",
|
||||
"122": "There is some text missing from this line.",
|
||||
"123": "There is some text missing from this line.",
|
||||
"141": "There is some text missing from this line.",
|
||||
"142": "There is some text missing from this line.",
|
||||
"143": "There is also some text missing here.",
|
||||
"144": "There is also some text missing here.",
|
||||
"215": "There are some words that don't belong in this sentence.",
|
||||
"231": "Somebody typed the end of this line twice.",
|
||||
"271": -1,
|
||||
"290": "this line of words is cleaned up.",
|
||||
"304": -1,
|
||||
"305": -1,
|
||||
"306": -1,
|
||||
"307": -1,
|
||||
"308": -1,
|
||||
"309": -1,
|
||||
"310": -1,
|
||||
"325": "Fix the errors on this line and replace them with undo.",
|
||||
"365": -1,
|
||||
"366": -1,
|
||||
"367": -1,
|
||||
"368": -1,
|
||||
"382": "When this line was typed in, someone pressed some wrong keys!",
|
||||
"383": "When this line was typed in, someone pressed some wrong keys!",
|
||||
"403": "This line has a few words that need changing using the change operator.",
|
||||
"404": "This line has a few words that need changing using the change operator.",
|
||||
"424": "The end of this line needs to be corrected using the c$ command.",
|
||||
"425": "The end of this line needs to be corrected using the c$ command.",
|
||||
"487": -1,
|
||||
"506": -1,
|
||||
"531": "the best time to see the flowers is in the spring.",
|
||||
"722": -1,
|
||||
"727": -1,
|
||||
"744": "This line will allow you to practice appending text to a line.",
|
||||
"745": "This line will allow you to practice appending text to a line.",
|
||||
"765": "Adding 123 to 456 gives you 579.",
|
||||
"766": "Adding 123 to 456 gives you 579.",
|
||||
"788": "a) this is the first item.",
|
||||
"789": " b) this is the second item."
|
||||
}
|
||||
}
|
@ -60,27 +60,27 @@ is displayed like
|
||||
|
||||
1. Format the line below so it becomes a lesson description:
|
||||
|
||||
---> This is text with important information {expect:This is text with **important information**}
|
||||
---> This is text with **important information** {expect:This is text with **important information**}
|
||||
This is text with important information
|
||||
This is text with **important information**
|
||||
|
||||
Note: Some words (e.g., NOTE, IMPORTANT, tip, ATTENTION, etc.) will also be
|
||||
highlighted. You don't need to mark them specially.
|
||||
|
||||
2. Turn the line below into a TODO item:
|
||||
|
||||
---> Document '&variable' {expect:TODO: Document '&variable'}
|
||||
---> TODO: Document '&variable' {expect:TODO: Document '&variable'}
|
||||
Document '&variable'
|
||||
TODO: Document '&variable'
|
||||
|
||||
### Headers *headers*
|
||||
|
||||
3. Practice fixing the lines below:
|
||||
|
||||
---> This is a level 1 header {expect:# This is a level 1 header}
|
||||
---> # This is a level 1 header {expect:# This is a level 1 header}
|
||||
---> This is a level 3 header {expect:### This is a level 3 header}
|
||||
---> ### This is a level 3 header {expect:### This is a level 3 header}
|
||||
---> This is a header with a label {expect:# This is a header with a label {*label*}}
|
||||
---> # This is a header with a label {*label*} {expect:# This is a header with a label {*label*}}
|
||||
This is a level 1 header
|
||||
# This is a level 1 header
|
||||
This is a level 3 header
|
||||
### This is a level 3 header
|
||||
This is a header with a label
|
||||
# This is a header with a label {*label*}
|
||||
|
||||
4. Now, create a 4th level section here, and add a label like in the previous
|
||||
exercise:
|
||||
@ -105,8 +105,8 @@ If the target of a link matches a help topic, opening it will open it.
|
||||
|
||||
5. Fix the following line:
|
||||
|
||||
---> A link to help for the 'breakindent' option {expect:A link to help for the ['breakindent']('breakindent') option}
|
||||
---> A link to help for the ['breakindent']('breakindent') option {expect:A link to help for the ['breakindent']('breakindent') option}
|
||||
A link to help for the 'breakindent' option
|
||||
A link to help for the ['breakindent']('breakindent') option
|
||||
|
||||
#### Anchor links
|
||||
|
||||
@ -120,8 +120,8 @@ and are hidden by default. Links to them look like
|
||||
|
||||
6. Add the appropiate link:
|
||||
|
||||
---> A link to the Links section {expect:A link to the [Links](*links*) section}
|
||||
---> A link to the [Links](*links*) section {expect:A link to the [Links](*links*) section}
|
||||
A link to the Links section
|
||||
A link to the [Links](*links*) section
|
||||
|
||||
7. Now, create a link to the section you created on exercise 4
|
||||
above.
|
||||
@ -136,8 +136,8 @@ You can also have links to other tutorials. For this, you'll write the anchor in
|
||||
|
||||
7. Create a link to this tutorial:
|
||||
|
||||
---> A link to the vim-tutor-mode tutorial {expect:A link to [the vim-tutor-mode tutorial](@tutor:tutor)}
|
||||
---> A link to [the vim-tutor-mode tutorial](@tutor:tutor) {expect:A link to [the vim-tutor-mode tutorial](@tutor:tutor)}
|
||||
A link to the vim-tutor-mode tutorial
|
||||
A link to [the vim-tutor-mode tutorial](@tutor:tutor)
|
||||
|
||||
### Codeblocks *codeblocks*
|
||||
|
||||
@ -154,13 +154,13 @@ echom "hello"
|
||||
|
||||
8. Copy the viml section below
|
||||
|
||||
---> {expect:~~~ viml}
|
||||
---> {expect:echom "the value of &number is".string(&number)}
|
||||
---> {expect:~~~}
|
||||
|
||||
---> ~~~ viml {expect:~~~ viml}
|
||||
---> echom "the value of &number is".string(&number) {expect:echom "the value of &number is".string(&number)}
|
||||
---> ~~~ {expect:~~~}
|
||||
|
||||
|
||||
|
||||
~~~ viml
|
||||
echom 'the value of &number is'.string(&number)
|
||||
~~~
|
||||
|
||||
You can inline viml code using "\`" and "\`{vim}":
|
||||
|
||||
@ -185,13 +185,13 @@ Note: you can also write `norm` or `normal`.
|
||||
|
||||
9. Copy the normal section below
|
||||
|
||||
---> {expect:~~~ normal}
|
||||
---> {expect:d2w}
|
||||
---> {expect:~~~}
|
||||
|
||||
---> ~~~ normal {expect:~~~ normal}
|
||||
---> d2w {expect:d2w}
|
||||
---> ~~~ {expect:~~~}
|
||||
|
||||
|
||||
|
||||
~~~ normal
|
||||
d2w
|
||||
~~~
|
||||
|
||||
You can also inline normal commands by using "\`" and "\`{normal}":
|
||||
|
||||
@ -203,10 +203,11 @@ is displayed:
|
||||
|
||||
10. Complete the line as shown
|
||||
|
||||
---> d {expect:«d2w»}
|
||||
---> «d2w» {expect:«d2w»}
|
||||
d
|
||||
`d2w`{normal}
|
||||
|
||||
Commands to run in the system shell can be highlighted by indenting a line starting with "$".
|
||||
Commands to run in the system shell can be highlighted by indenting a line
|
||||
starting with "$".
|
||||
|
||||
~~~ sh
|
||||
$ vim --version
|
||||
@ -215,45 +216,32 @@ Commands to run in the system shell can be highlighted by indenting a line start
|
||||
## INTERACTIVE ELEMENTS *interactive*
|
||||
|
||||
As visible in this very document, vim-tutor-mode includes some interactive
|
||||
elements, to provide feedback to the user about his progress. These elements
|
||||
all have the syntax
|
||||
|
||||
\---> TEXT {CLAUSE}
|
||||
|
||||
where \---> must start at the beginning of the line. If TEXT satisfies CLAUSE,
|
||||
a ✓ sign will appear to the left. A ✗ sign is displayed otherwise. The CLAUSE
|
||||
itself is hidden unless debug mode is set or ['conceallevel']('conceallevel')
|
||||
is 2.
|
||||
elements to provide feedback to the user about his progress. If the text in
|
||||
these elements satisfies some set condition, a ✓ sign will appear in the gutter
|
||||
to the left. Otherwise, a ✗ sign is displayed.
|
||||
|
||||
### expect *expect*
|
||||
|
||||
The basic clause is "expect", which is satisfied if TEXT is the same as the
|
||||
content of the clause. For example
|
||||
"expect" lines check that the contents of the line are identical to some preset text
|
||||
(like in the exercises above).
|
||||
|
||||
\---> TEXT {expect:TEXT}
|
||||
These elements are specified in separate JSON files like this
|
||||
|
||||
is satisfied, but
|
||||
~~~ json
|
||||
{
|
||||
"expect": {
|
||||
"1": "This is how this line should look.",
|
||||
"2": "This is how this line should look.",
|
||||
"3": -1
|
||||
}
|
||||
}
|
||||
~~~
|
||||
|
||||
\---> OTHER TEXT {expect:TEXT}
|
||||
These files contain an "expect" dictionary, for which the keys are line numbers and
|
||||
the values are the expected text. A value of -1 means that the condition for the line
|
||||
will always be satisfied, no matter what (this is useful for letting the user play a bit).
|
||||
|
||||
is not.
|
||||
This is an "expect" line that is always satisfied. Try changing it.
|
||||
|
||||
13. Make both lines the same:
|
||||
|
||||
---> this is not right {expect:---> this is right} |expect:---> this is right {expect:---> this is right}|
|
||||
---> ---> this is right {expect:---> this is right} |expect:---> this is right {expect:---> this is right}|
|
||||
|
||||
|
||||
If the content of a expect clause is ANYTHING, no checks will be performed. This is
|
||||
useful to create a line that is highlighted you want the user to play with.
|
||||
|
||||
\---> TEXT {expect:ANYTHING}
|
||||
|
||||
is displayed
|
||||
|
||||
---> this is free text {expect:ANYTHING}
|
||||
|
||||
14. Turn the line below into free text:
|
||||
|
||||
---> this is some text |expect:---> this is some text {expect:ANYTHING}|
|
||||
---> ---> this is some text {expect:ANYTHING} |expect:---> this is some text {expect:ANYTHING}|
|
||||
These files conventionally have the same name as the tutorial document with the `.json`
|
||||
extension appended (for a full example, see the file that corresponds to this tutorial).
|
||||
|
35
runtime/tutor/tutor.tutor.json
Normal file
35
runtime/tutor/tutor.tutor.json
Normal file
@ -0,0 +1,35 @@
|
||||
{
|
||||
"expect": {
|
||||
"63": "This is text with **important information**",
|
||||
"64": "This is text with **important information**",
|
||||
"71": "Document '&variable'",
|
||||
"72": "Document '&variable'",
|
||||
"78": "# This is a level 1 header",
|
||||
"79": "# This is a level 1 header",
|
||||
"80": "### This is a level 3 header",
|
||||
"81": "### This is a level 3 header",
|
||||
"82": "# This is a header with a label {*label*}",
|
||||
"83": "# This is a header with a label {*label*}",
|
||||
"108": "A link to help for the ['breakindent']('breakindent') option",
|
||||
"109": "A link to help for the ['breakindent']('breakindent') option",
|
||||
"123": "A link to the [Links](*links*) section",
|
||||
"124": "A link to the [Links](*links*) section",
|
||||
"139": "A link to [the vim-tutor-mode tutorial](@tutor:tutor)",
|
||||
"140": "A link to [the vim-tutor-mode tutorial](@tutor:tutor)",
|
||||
"157": "~~~ viml",
|
||||
"158": "echom 'the value of &number is'.string(&number)",
|
||||
"159": "~~~",
|
||||
"161": "~~~ viml",
|
||||
"162": "echom 'the value of &number is'.string(&number)",
|
||||
"163": "~~~",
|
||||
"188": "~~~ normal",
|
||||
"189": "d2w",
|
||||
"190": "~~~",
|
||||
"192": "~~~ normal",
|
||||
"193": "d2w",
|
||||
"194": "~~~",
|
||||
"206": "`d2w`{normal}",
|
||||
"207": "`d2w`{normal}",
|
||||
"244": -1
|
||||
}
|
||||
}
|
@ -1,14 +1,26 @@
|
||||
## Source code overview
|
||||
Nvim core source
|
||||
================
|
||||
|
||||
This document is an overview of how Nvim works internally, focusing on parts
|
||||
that are different from Vim. Since Nvim inherited from Vim, some information in
|
||||
[its README](https://raw.githubusercontent.com/vim/vim/master/src/README.txt)
|
||||
still applies.
|
||||
Module-specific details are documented at the top of each module (`terminal.c`,
|
||||
`screen.c`, ...).
|
||||
|
||||
For module-specific details, read the source code. Some files are extensively
|
||||
commented at the top (e.g. terminal.c, screen.c).
|
||||
See `:help development` for more guidelines.
|
||||
|
||||
### Source file name conventions
|
||||
Logs
|
||||
----
|
||||
|
||||
Low-level log messages sink to `$NVIM_LOG_FILE`.
|
||||
|
||||
You can use `LOG_CALLSTACK()` anywhere in the source to log the current
|
||||
stacktrace. (Currently Linux-only.)
|
||||
|
||||
UI events are logged at level 0 (`DEBUG_LOG_LEVEL`).
|
||||
|
||||
rm -rf build/
|
||||
make CMAKE_EXTRA_FLAGS="-DMIN_LOG_LEVEL=0"
|
||||
|
||||
Filename conventions
|
||||
--------------------
|
||||
|
||||
The source files use extensions to hint about their purpose.
|
||||
|
||||
@ -19,10 +31,12 @@ The source files use extensions to hint about their purpose.
|
||||
- `*.h.generated.h` - exported functions’ declarations.
|
||||
- `*.c.generated.h` - static functions’ declarations.
|
||||
|
||||
### Top-level program loops
|
||||
Nvim lifecycle
|
||||
--------------
|
||||
|
||||
Let's understand what a Vim-like program does by analyzing the workflow of
|
||||
a typical editing session:
|
||||
Following describes how Nvim processes input.
|
||||
|
||||
Consider a typical Vim-like editing session:
|
||||
|
||||
01. Vim dispays the welcome screen
|
||||
02. User types: `:`
|
||||
@ -154,7 +168,8 @@ modes managed by the `state_enter` loop:
|
||||
- insert mode: `insert_{enter,check,execute}()`(`edit.c`)
|
||||
- terminal mode: `terminal_{enter,execute}()`(`terminal.c`)
|
||||
|
||||
### Async event support
|
||||
Async event support
|
||||
-------------------
|
||||
|
||||
One of the features Nvim added is the support for handling arbitrary
|
||||
asynchronous events, which can include:
|
||||
|
@ -1203,8 +1203,8 @@ do_buffer (
|
||||
*/
|
||||
while (buf == curbuf
|
||||
&& !(curwin->w_closing || curwin->w_buffer->b_locked > 0)
|
||||
&& (firstwin != lastwin || first_tabpage->tp_next != NULL)) {
|
||||
if (win_close(curwin, FALSE) == FAIL)
|
||||
&& (!ONE_WINDOW || first_tabpage->tp_next != NULL)) {
|
||||
if (win_close(curwin, false) == FAIL)
|
||||
break;
|
||||
}
|
||||
|
||||
@ -4428,15 +4428,17 @@ do_arg_all (
|
||||
continue;
|
||||
}
|
||||
}
|
||||
/* don't close last window */
|
||||
if (firstwin == lastwin
|
||||
&& (first_tabpage->tp_next == NULL || !had_tab))
|
||||
use_firstwin = TRUE;
|
||||
else {
|
||||
// don't close last window
|
||||
if (ONE_WINDOW
|
||||
&& (first_tabpage->tp_next == NULL || !had_tab)) {
|
||||
use_firstwin = true;
|
||||
} else {
|
||||
win_close(wp, !P_HID(buf) && !bufIsChanged(buf));
|
||||
/* check if autocommands removed the next window */
|
||||
if (!win_valid(wpnext))
|
||||
wpnext = firstwin; /* start all over... */
|
||||
// check if autocommands removed the next window
|
||||
if (!win_valid(wpnext)) {
|
||||
// start all over...
|
||||
wpnext = firstwin;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -4593,7 +4595,7 @@ void ex_buffer_all(exarg_T *eap)
|
||||
- tabline_height()
|
||||
: wp->w_width != Columns)
|
||||
|| (had_tab > 0 && wp != firstwin))
|
||||
&& firstwin != lastwin
|
||||
&& !ONE_WINDOW
|
||||
&& !(wp->w_closing || wp->w_buffer->b_locked > 0)
|
||||
) {
|
||||
win_close(wp, FALSE);
|
||||
|
@ -793,6 +793,7 @@ static digr_T digraphdefault[] =
|
||||
{ '/', '-', 0x2020 },
|
||||
{ '/', '=', 0x2021 },
|
||||
{ '.', '.', 0x2025 },
|
||||
{ ',', '.', 0x2026 },
|
||||
{ '%', '0', 0x2030 },
|
||||
{ '1', '\'', 0x2032 },
|
||||
{ '2', '\'', 0x2033 },
|
||||
|
@ -47,6 +47,7 @@
|
||||
#include "nvim/mbyte.h"
|
||||
#include "nvim/memline.h"
|
||||
#include "nvim/memory.h"
|
||||
#include "nvim/menu.h"
|
||||
#include "nvim/message.h"
|
||||
#include "nvim/misc1.h"
|
||||
#include "nvim/keymap.h"
|
||||
@ -4239,11 +4240,17 @@ static int eval7(
|
||||
// use its contents.
|
||||
s = deref_func_name((const char *)s, &len, &partial, !evaluate);
|
||||
|
||||
// Need to make a copy, in case evaluating the arguments makes
|
||||
// the name invalid.
|
||||
s = xmemdupz(s, len);
|
||||
|
||||
// Invoke the function.
|
||||
ret = get_func_tv(s, len, rettv, arg,
|
||||
curwin->w_cursor.lnum, curwin->w_cursor.lnum,
|
||||
&len, evaluate, partial, NULL);
|
||||
|
||||
xfree(s);
|
||||
|
||||
// If evaluate is false rettv->v_type was not set in
|
||||
// get_func_tv, but it's needed in handle_subscript() to parse
|
||||
// what follows. So set it here.
|
||||
@ -8167,6 +8174,19 @@ static void f_expand(typval_T *argvars, typval_T *rettv, FunPtr fptr)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// "menu_get(path [, modes])" function
|
||||
static void f_menu_get(typval_T *argvars, typval_T *rettv, FunPtr fptr)
|
||||
{
|
||||
tv_list_alloc_ret(rettv);
|
||||
int modes = MENU_ALL_MODES;
|
||||
if (argvars[1].v_type == VAR_STRING) {
|
||||
const char_u *const strmodes = (char_u *)tv_get_string(&argvars[1]);
|
||||
modes = get_menu_cmd_modes(strmodes, false, NULL, NULL);
|
||||
}
|
||||
menu_get((char_u *)tv_get_string(&argvars[0]), modes, rettv->vval.v_list);
|
||||
}
|
||||
|
||||
/*
|
||||
* "extend(list, list [, idx])" function
|
||||
* "extend(dict, dict [, action])" function
|
||||
@ -15140,7 +15160,8 @@ static void f_sockconnect(typval_T *argvars, typval_T *rettv, FunPtr fptr)
|
||||
}
|
||||
|
||||
const char *error = NULL;
|
||||
uint64_t id = channel_connect(tcp, address, 50, &error);
|
||||
eval_format_source_name_line((char *)IObuff, sizeof(IObuff));
|
||||
uint64_t id = channel_connect(tcp, address, 50, (char *)IObuff, &error);
|
||||
|
||||
if (error) {
|
||||
EMSG2(_("connection failed: %s"), error);
|
||||
@ -22448,8 +22469,9 @@ static inline bool common_job_start(TerminalJobData *data, typval_T *rettv)
|
||||
|
||||
|
||||
if (data->rpc) {
|
||||
// the rpc channel takes over the in and out streams
|
||||
channel_from_process(proc, data->id);
|
||||
eval_format_source_name_line((char *)IObuff, sizeof(IObuff));
|
||||
// RPC channel takes over the in/out streams.
|
||||
channel_from_process(proc, data->id, (char *)IObuff);
|
||||
} else {
|
||||
wstream_init(proc->in, 0);
|
||||
if (proc->out) {
|
||||
@ -22774,3 +22796,11 @@ bool eval_has_provider(const char *name)
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// Writes "<sourcing_name>:<sourcing_lnum>" to `buf[bufsize]`.
|
||||
void eval_format_source_name_line(char *buf, size_t bufsize)
|
||||
{
|
||||
snprintf(buf, bufsize, "%s:%" PRIdLINENR,
|
||||
(sourcing_name ? sourcing_name : (char_u *)"?"),
|
||||
(sourcing_name ? sourcing_lnum : 0));
|
||||
}
|
||||
|
@ -2,10 +2,10 @@
|
||||
--
|
||||
-- Keys:
|
||||
--
|
||||
-- args Number of arguments, list with maximum and minimum number of arguments
|
||||
-- or list with a minimum number of arguments only. Defaults to zero
|
||||
-- args Number of arguments, list with maximum and minimum number of arguments
|
||||
-- or list with a minimum number of arguments only. Defaults to zero
|
||||
-- arguments.
|
||||
-- func Name of the C function which implements the VimL function. Defaults to
|
||||
-- func Name of the C function which implements the VimL function. Defaults to
|
||||
-- `f_{funcname}`.
|
||||
|
||||
local varargs = function(nr)
|
||||
@ -29,7 +29,7 @@ return {
|
||||
assert_exception={args={1, 2}},
|
||||
assert_fails={args={1, 2}},
|
||||
assert_false={args={1, 2}},
|
||||
assert_inrange={args={2, 3}},
|
||||
assert_inrange={args={3, 4}},
|
||||
assert_match={args={2, 3}},
|
||||
assert_notequal={args={2, 3}},
|
||||
assert_notmatch={args={2, 3}},
|
||||
@ -208,6 +208,7 @@ return {
|
||||
matchstr={args={2, 4}},
|
||||
matchstrpos={args={2,4}},
|
||||
max={args=1},
|
||||
menu_get={args={1, 2}},
|
||||
min={args=1},
|
||||
mkdir={args={1, 3}},
|
||||
mode={args={0, 1}},
|
||||
|
@ -2802,16 +2802,18 @@ void ex_z(exarg_T *eap)
|
||||
int j;
|
||||
linenr_T lnum = eap->line2;
|
||||
|
||||
/* Vi compatible: ":z!" uses display height, without a count uses
|
||||
* 'scroll' */
|
||||
if (eap->forceit)
|
||||
// Vi compatible: ":z!" uses display height, without a count uses
|
||||
// 'scroll'
|
||||
if (eap->forceit) {
|
||||
bigness = curwin->w_height;
|
||||
else if (firstwin == lastwin)
|
||||
} else if (ONE_WINDOW) {
|
||||
bigness = curwin->w_p_scr * 2;
|
||||
else
|
||||
} else {
|
||||
bigness = curwin->w_height - 3;
|
||||
if (bigness < 1)
|
||||
}
|
||||
if (bigness < 1) {
|
||||
bigness = 1;
|
||||
}
|
||||
|
||||
x = eap->arg;
|
||||
kind = x;
|
||||
|
@ -1,4 +1,4 @@
|
||||
bit = require 'bit'
|
||||
local bit = require 'bit'
|
||||
|
||||
-- Description of the values below is contained in ex_cmds_defs.h file.
|
||||
local RANGE = 0x001
|
||||
|
@ -844,8 +844,6 @@ int do_cmdline(char_u *cmdline, LineGetter fgetline,
|
||||
break;
|
||||
case ET_INTERRUPT:
|
||||
break;
|
||||
default:
|
||||
p = vim_strsave((char_u *)_(e_internal));
|
||||
}
|
||||
|
||||
saved_sourcing_name = sourcing_name;
|
||||
@ -3440,6 +3438,11 @@ const char * set_one_cmd_context(
|
||||
xp->xp_pattern = (char_u *)arg;
|
||||
break;
|
||||
|
||||
case CMD_messages:
|
||||
xp->xp_context = EXPAND_MESSAGES;
|
||||
xp->xp_pattern = (char_u *)arg;
|
||||
break;
|
||||
|
||||
case CMD_history:
|
||||
xp->xp_context = EXPAND_HISTORY;
|
||||
xp->xp_pattern = (char_u *)arg;
|
||||
@ -4874,6 +4877,7 @@ static struct {
|
||||
#endif
|
||||
{ EXPAND_MAPPINGS, "mapping" },
|
||||
{ EXPAND_MENUS, "menu" },
|
||||
{ EXPAND_MESSAGES, "messages" },
|
||||
{ EXPAND_OWNSYNTAX, "syntax" },
|
||||
{ EXPAND_SYNTIME, "syntime" },
|
||||
{ EXPAND_SETTINGS, "option" },
|
||||
@ -5976,7 +5980,7 @@ static void ex_quit(exarg_T *eap)
|
||||
// specified. Example:
|
||||
// :h|wincmd w|1q - don't quit
|
||||
// :h|wincmd w|q - quit
|
||||
if (only_one_window() && (firstwin == lastwin || eap->addr_count == 0)) {
|
||||
if (only_one_window() && (ONE_WINDOW || eap->addr_count == 0)) {
|
||||
getout(0);
|
||||
}
|
||||
/* close window; may free buffer */
|
||||
@ -6174,12 +6178,14 @@ static void ex_tabonly(exarg_T *eap)
|
||||
*/
|
||||
void tabpage_close(int forceit)
|
||||
{
|
||||
/* First close all the windows but the current one. If that worked then
|
||||
* close the last window in this tab, that will close it. */
|
||||
if (lastwin != firstwin)
|
||||
close_others(TRUE, forceit);
|
||||
if (lastwin == firstwin)
|
||||
// First close all the windows but the current one. If that worked then
|
||||
// close the last window in this tab, that will close it.
|
||||
if (!ONE_WINDOW) {
|
||||
close_others(true, forceit);
|
||||
}
|
||||
if (ONE_WINDOW) {
|
||||
ex_win_close(forceit, curwin, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@ -9593,6 +9599,16 @@ char_u *get_behave_arg(expand_T *xp, int idx)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Function given to ExpandGeneric() to obtain the possible arguments of the
|
||||
// ":messages {clear}" command.
|
||||
char_u *get_messages_arg(expand_T *xp FUNC_ATTR_UNUSED, int idx)
|
||||
{
|
||||
if (idx == 0) {
|
||||
return (char_u *)"clear";
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static TriState filetype_detect = kNone;
|
||||
static TriState filetype_plugin = kNone;
|
||||
static TriState filetype_indent = kNone;
|
||||
|
@ -374,10 +374,9 @@ int do_intthrow(struct condstack *cstack)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get an exception message that is to be stored in current_exception->value.
|
||||
*/
|
||||
char_u *get_exception_string(void *value, int type, char_u *cmdname, int *should_free)
|
||||
// Get an exception message that is to be stored in current_exception->value.
|
||||
char_u *get_exception_string(void *value, except_type_T type, char_u *cmdname,
|
||||
int *should_free)
|
||||
{
|
||||
char_u *ret, *mesg;
|
||||
char_u *p, *val;
|
||||
@ -435,13 +434,11 @@ char_u *get_exception_string(void *value, int type, char_u *cmdname, int *should
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Throw a new exception. Return FAIL when out of memory or it was tried to
|
||||
* throw an illegal user exception. "value" is the exception string for a
|
||||
* user or interrupt exception, or points to a message list in case of an
|
||||
* error exception.
|
||||
*/
|
||||
static int throw_exception(void *value, int type, char_u *cmdname)
|
||||
// Throw a new exception. Return FAIL when out of memory or it was tried to
|
||||
// throw an illegal user exception. "value" is the exception string for a
|
||||
// user or interrupt exception, or points to a message list in case of an
|
||||
// error exception.
|
||||
static int throw_exception(void *value, except_type_T type, char_u *cmdname)
|
||||
{
|
||||
except_T *excp;
|
||||
int should_free;
|
||||
|
@ -89,27 +89,28 @@ struct msglist {
|
||||
struct msglist *next; /* next of several messages in a row */
|
||||
};
|
||||
|
||||
// The exception types.
|
||||
typedef enum
|
||||
{
|
||||
ET_USER, // exception caused by ":throw" command
|
||||
ET_ERROR, // error exception
|
||||
ET_INTERRUPT // interrupt exception triggered by Ctrl-C
|
||||
} except_type_T;
|
||||
|
||||
/*
|
||||
* Structure describing an exception.
|
||||
* (don't use "struct exception", it's used by the math library).
|
||||
*/
|
||||
typedef struct vim_exception except_T;
|
||||
struct vim_exception {
|
||||
int type; /* exception type */
|
||||
char_u *value; /* exception value */
|
||||
struct msglist *messages; /* message(s) causing error exception */
|
||||
char_u *throw_name; /* name of the throw point */
|
||||
linenr_T throw_lnum; /* line number of the throw point */
|
||||
except_T *caught; /* next exception on the caught stack */
|
||||
except_type_T type; // exception type
|
||||
char_u *value; // exception value
|
||||
struct msglist *messages; // message(s) causing error exception
|
||||
char_u *throw_name; // name of the throw point
|
||||
linenr_T throw_lnum; // line number of the throw point
|
||||
except_T *caught; // next exception on the caught stack
|
||||
};
|
||||
|
||||
/*
|
||||
* The exception types.
|
||||
*/
|
||||
#define ET_USER 0 /* exception caused by ":throw" command */
|
||||
#define ET_ERROR 1 /* error exception */
|
||||
#define ET_INTERRUPT 2 /* interrupt exception triggered by Ctrl-C */
|
||||
|
||||
/*
|
||||
* Structure to save the error/interrupt/exception state between calls to
|
||||
* enter_cleanup() and leave_cleanup(). Must be allocated as an automatic
|
||||
|
@ -4377,6 +4377,7 @@ ExpandFromContext (
|
||||
} tab[] = {
|
||||
{ EXPAND_COMMANDS, get_command_name, false, true },
|
||||
{ EXPAND_BEHAVE, get_behave_arg, true, true },
|
||||
{ EXPAND_MESSAGES, get_messages_arg, true, true },
|
||||
{ EXPAND_HISTORY, get_history_arg, true, true },
|
||||
{ EXPAND_USER_COMMANDS, get_user_commands, false, true },
|
||||
{ EXPAND_USER_ADDR_TYPE, get_user_cmd_addr_type, false, true },
|
||||
|
@ -119,7 +119,7 @@ for i = 1, #events do
|
||||
write_signature(bridge_output, ev, 'UI *ui')
|
||||
bridge_output:write('\n{\n')
|
||||
bridge_output:write(send)
|
||||
bridge_output:write(' UI_CALL(ui, '..ev.name..', '..argc..', ui'..argv..');\n}\n')
|
||||
bridge_output:write(' UI_BRIDGE_CALL(ui, '..ev.name..', '..argc..', ui'..argv..');\n}\n')
|
||||
end
|
||||
end
|
||||
|
||||
@ -128,6 +128,7 @@ for i = 1, #events do
|
||||
call_output:write('\n{\n')
|
||||
if ev.remote_only then
|
||||
write_arglist(call_output, ev, false)
|
||||
call_output:write(' UI_LOG('..ev.name..', 0);\n')
|
||||
call_output:write(' ui_event("'..ev.name..'", args);\n')
|
||||
else
|
||||
call_output:write(' UI_CALL')
|
||||
|
@ -5,12 +5,15 @@
|
||||
#include "nvim/buffer_defs.h"
|
||||
#include "nvim/ex_cmds_defs.h"
|
||||
|
||||
/* Values for "noremap" argument of ins_typebuf(). Also used for
|
||||
* map->m_noremap and menu->noremap[]. */
|
||||
#define REMAP_YES 0 /* allow remapping */
|
||||
#define REMAP_NONE -1 /* no remapping */
|
||||
#define REMAP_SCRIPT -2 /* remap script-local mappings only */
|
||||
#define REMAP_SKIP -3 /* no remapping for first char */
|
||||
/// Values for "noremap" argument of ins_typebuf(). Also used for
|
||||
/// map->m_noremap and menu->noremap[].
|
||||
/// @addtogroup REMAP_VALUES
|
||||
/// @{
|
||||
#define REMAP_YES 0 ///< allow remapping
|
||||
#define REMAP_NONE -1 ///< no remapping
|
||||
#define REMAP_SCRIPT -2 ///< remap script-local mappings only
|
||||
#define REMAP_SKIP -3 ///< no remapping for first char
|
||||
/// @}
|
||||
|
||||
#define KEYLEN_PART_KEY -1 /* keylen value for incomplete key-code */
|
||||
#define KEYLEN_PART_MAP -2 /* keylen value for incomplete mapping */
|
||||
|
@ -494,6 +494,7 @@ EXTERN int updating_screen INIT(= FALSE);
|
||||
EXTERN win_T *firstwin; /* first window */
|
||||
EXTERN win_T *lastwin; /* last window */
|
||||
EXTERN win_T *prevwin INIT(= NULL); /* previous window */
|
||||
# define ONE_WINDOW (firstwin == lastwin)
|
||||
/*
|
||||
* When using this macro "break" only breaks out of the inner loop. Use "goto"
|
||||
* to break out of the tabpage loop.
|
||||
|
@ -25,6 +25,10 @@ static uv_mutex_t mutex;
|
||||
# include "log.c.generated.h"
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_EXECINFO_BACKTRACE
|
||||
# include <execinfo.h>
|
||||
#endif
|
||||
|
||||
static bool log_try_create(char *fname)
|
||||
{
|
||||
if (fname == NULL || fname[0] == '\0') {
|
||||
@ -173,6 +177,52 @@ FILE *open_log_file(void)
|
||||
return stderr;
|
||||
}
|
||||
|
||||
#ifdef HAVE_EXECINFO_BACKTRACE
|
||||
void log_callstack(const char *const func_name, const int line_num)
|
||||
{
|
||||
void *trace[100];
|
||||
int trace_size = backtrace(trace, ARRAY_SIZE(trace));
|
||||
|
||||
char exepath[MAXPATHL] = { 0 };
|
||||
size_t exepathlen = MAXPATHL;
|
||||
if (os_exepath(exepath, &exepathlen) != 0) {
|
||||
abort();
|
||||
}
|
||||
assert(24 + exepathlen < IOSIZE); // Must fit in `cmdbuf` below.
|
||||
|
||||
do_log(DEBUG_LOG_LEVEL, func_name, line_num, true, "trace:");
|
||||
|
||||
char cmdbuf[IOSIZE + (20 * ARRAY_SIZE(trace))];
|
||||
snprintf(cmdbuf, sizeof(cmdbuf), "addr2line -e %s -f -p", exepath);
|
||||
for (int i = 1; i < trace_size; i++) {
|
||||
char buf[20]; // 64-bit pointer 0xNNNNNNNNNNNNNNNN with leading space.
|
||||
snprintf(buf, sizeof(buf), " %p", trace[i]);
|
||||
xstrlcat(cmdbuf, buf, sizeof(cmdbuf));
|
||||
}
|
||||
// Now we have a command string like:
|
||||
// addr2line -e /path/to/exe -f -p 0x123 0x456 ...
|
||||
|
||||
log_lock();
|
||||
FILE *log_file = open_log_file();
|
||||
if (log_file == NULL) {
|
||||
goto end;
|
||||
}
|
||||
|
||||
FILE *fp = popen(cmdbuf, "r");
|
||||
char linebuf[IOSIZE];
|
||||
while (fgets(linebuf, sizeof(linebuf) - 1, fp) != NULL) {
|
||||
fprintf(log_file, " %s", linebuf);
|
||||
}
|
||||
pclose(fp);
|
||||
|
||||
if (log_file != stderr && log_file != stdout) {
|
||||
fclose(log_file);
|
||||
}
|
||||
end:
|
||||
log_unlock();
|
||||
}
|
||||
#endif
|
||||
|
||||
static bool do_log_to_file(FILE *log_file, int log_level,
|
||||
const char *func_name, int line_num, bool eol,
|
||||
const char* fmt, ...)
|
||||
|
@ -61,6 +61,10 @@
|
||||
__VA_ARGS__)
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_EXECINFO_BACKTRACE
|
||||
# define LOG_CALLSTACK() log_callstack(__func__, __LINE__)
|
||||
#endif
|
||||
|
||||
#ifdef INCLUDE_GENERATED_DECLARATIONS
|
||||
# include "log.h.generated.h"
|
||||
#endif
|
||||
|
@ -932,12 +932,12 @@ int utf_char2len(int c)
|
||||
return 6;
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert Unicode character "c" to UTF-8 string in "buf[]".
|
||||
* Returns the number of bytes.
|
||||
* This does not include composing characters.
|
||||
*/
|
||||
int utf_char2bytes(int c, char_u *buf)
|
||||
/// Convert Unicode character to UTF-8 string
|
||||
///
|
||||
/// @param c character to convert to \p buf
|
||||
/// @param[out] buf UTF-8 string generated from \p c, does not add \0
|
||||
/// @return Number of bytes (1-6). Does not include composing characters.
|
||||
int utf_char2bytes(int c, char_u *const buf)
|
||||
{
|
||||
if (c < 0x80) { /* 7 bits */
|
||||
buf[0] = c;
|
||||
|
@ -585,7 +585,7 @@ void free_all_mem(void)
|
||||
p_ea = false;
|
||||
if (first_tabpage->tp_next != NULL)
|
||||
do_cmdline_cmd("tabonly!");
|
||||
if (firstwin != lastwin)
|
||||
if (!ONE_WINDOW)
|
||||
do_cmdline_cmd("only!");
|
||||
|
||||
/* Free all spell info. */
|
||||
|
294
src/nvim/menu.c
294
src/nvim/menu.c
@ -26,7 +26,7 @@
|
||||
#include "nvim/state.h"
|
||||
#include "nvim/strings.h"
|
||||
#include "nvim/ui.h"
|
||||
|
||||
#include "nvim/eval/typval.h"
|
||||
|
||||
#define MENUDEPTH 10 /* maximum depth of menus */
|
||||
|
||||
@ -38,8 +38,8 @@
|
||||
|
||||
|
||||
|
||||
/* The character for each menu mode */
|
||||
static char_u menu_mode_chars[] = {'n', 'v', 's', 'o', 'i', 'c', 't'};
|
||||
/// The character for each menu mode
|
||||
static char_u menu_mode_chars[] = { 'n', 'v', 's', 'o', 'i', 'c', 't' };
|
||||
|
||||
static char_u e_notsubmenu[] = N_(
|
||||
"E327: Part of menu-item path is not sub-menu");
|
||||
@ -47,17 +47,14 @@ static char_u e_othermode[] = N_("E328: Menu only exists in another mode");
|
||||
static char_u e_nomenu[] = N_("E329: No menu \"%s\"");
|
||||
|
||||
|
||||
/*
|
||||
* Do the :menu command and relatives.
|
||||
*/
|
||||
void
|
||||
ex_menu (
|
||||
exarg_T *eap /* Ex command arguments */
|
||||
)
|
||||
/// Do the :menu command and relatives.
|
||||
/// @param eap Ex command arguments
|
||||
void
|
||||
ex_menu(exarg_T *eap)
|
||||
{
|
||||
char_u *menu_path;
|
||||
int modes;
|
||||
char_u *map_to;
|
||||
char_u *map_to; // command mapped to the menu entry
|
||||
int noremap;
|
||||
bool silent = false;
|
||||
int unmenu;
|
||||
@ -93,7 +90,8 @@ ex_menu (
|
||||
}
|
||||
|
||||
|
||||
/* Locate an optional "icon=filename" argument. */
|
||||
// Locate an optional "icon=filename" argument
|
||||
// TODO(nvim): Currently this is only parsed. Should expose it to UIs.
|
||||
if (STRNCMP(arg, "icon=", 5) == 0) {
|
||||
arg += 5;
|
||||
while (*arg != NUL && *arg != ' ') {
|
||||
@ -107,12 +105,12 @@ ex_menu (
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Fill in the priority table.
|
||||
*/
|
||||
for (p = arg; *p; ++p)
|
||||
if (!ascii_isdigit(*p) && *p != '.')
|
||||
// Fill in the priority table.
|
||||
for (p = arg; *p; p++) {
|
||||
if (!ascii_isdigit(*p) && *p != '.') {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (ascii_iswhite(*p)) {
|
||||
for (i = 0; i < MENUDEPTH && !ascii_iswhite(*arg); ++i) {
|
||||
pri_tab[i] = getdigits_long(&arg);
|
||||
@ -226,8 +224,7 @@ ex_menu (
|
||||
menuarg.modes = modes;
|
||||
menuarg.noremap[0] = noremap;
|
||||
menuarg.silent[0] = silent;
|
||||
add_menu_path(menu_path, &menuarg, pri_tab, map_to
|
||||
);
|
||||
add_menu_path(menu_path, &menuarg, pri_tab, map_to);
|
||||
|
||||
/*
|
||||
* For the PopUp menu, add a menu for each mode separately.
|
||||
@ -252,16 +249,18 @@ theend:
|
||||
;
|
||||
}
|
||||
|
||||
/*
|
||||
* Add the menu with the given name to the menu hierarchy
|
||||
*/
|
||||
static int
|
||||
add_menu_path (
|
||||
char_u *menu_path,
|
||||
vimmenu_T *menuarg, /* passes modes, iconfile, iconidx,
|
||||
icon_builtin, silent[0], noremap[0] */
|
||||
long *pri_tab,
|
||||
char_u *call_data
|
||||
|
||||
/// Add the menu with the given name to the menu hierarchy
|
||||
///
|
||||
/// @param[out] menuarg menu entry
|
||||
/// @param[] pri_tab priority table
|
||||
/// @param[in] call_data Right hand side command
|
||||
static int
|
||||
add_menu_path(
|
||||
const char_u *const menu_path,
|
||||
vimmenu_T *menuarg,
|
||||
const long *const pri_tab,
|
||||
const char_u *const call_data
|
||||
)
|
||||
{
|
||||
char_u *path_name;
|
||||
@ -296,8 +295,9 @@ add_menu_path (
|
||||
if (map_to != NULL) {
|
||||
en_name = name;
|
||||
name = map_to;
|
||||
} else
|
||||
} else {
|
||||
en_name = NULL;
|
||||
}
|
||||
dname = menu_text(name, NULL, NULL);
|
||||
if (*dname == NUL) {
|
||||
/* Only a mnemonic or accelerator is not valid. */
|
||||
@ -311,14 +311,15 @@ add_menu_path (
|
||||
while (menu != NULL) {
|
||||
if (menu_name_equal(name, menu) || menu_name_equal(dname, menu)) {
|
||||
if (*next_name == NUL && menu->children != NULL) {
|
||||
if (!sys_menu)
|
||||
if (!sys_menu) {
|
||||
EMSG(_("E330: Menu path must not lead to a sub-menu"));
|
||||
}
|
||||
goto erret;
|
||||
}
|
||||
if (*next_name != NUL && menu->children == NULL
|
||||
) {
|
||||
if (!sys_menu)
|
||||
if (*next_name != NUL && menu->children == NULL) {
|
||||
if (!sys_menu) {
|
||||
EMSG(_(e_notsubmenu));
|
||||
}
|
||||
goto erret;
|
||||
}
|
||||
break;
|
||||
@ -352,7 +353,7 @@ add_menu_path (
|
||||
menu->modes = modes;
|
||||
menu->enabled = MENU_ALL_MODES;
|
||||
menu->name = vim_strsave(name);
|
||||
/* separate mnemonic and accelerator text from actual menu name */
|
||||
// separate mnemonic and accelerator text from actual menu name
|
||||
menu->dname = menu_text(name, &menu->mnemonic, &menu->actext);
|
||||
if (en_name != NULL) {
|
||||
menu->en_name = vim_strsave(en_name);
|
||||
@ -364,9 +365,7 @@ add_menu_path (
|
||||
menu->priority = pri_tab[pri_idx];
|
||||
menu->parent = parent;
|
||||
|
||||
/*
|
||||
* Add after menu that has lower priority.
|
||||
*/
|
||||
// Add after menu that has lower priority.
|
||||
menu->next = *lower_pri;
|
||||
*lower_pri = menu;
|
||||
|
||||
@ -392,8 +391,9 @@ add_menu_path (
|
||||
name = next_name;
|
||||
xfree(dname);
|
||||
dname = NULL;
|
||||
if (pri_tab[pri_idx + 1] != -1)
|
||||
++pri_idx;
|
||||
if (pri_tab[pri_idx + 1] != -1) {
|
||||
pri_idx++;
|
||||
}
|
||||
}
|
||||
xfree(path_name);
|
||||
|
||||
@ -419,8 +419,7 @@ add_menu_path (
|
||||
// Don't do this for "<Nop>".
|
||||
c = 0;
|
||||
d = 0;
|
||||
if (amenu && call_data != NULL && *call_data != NUL
|
||||
) {
|
||||
if (amenu && call_data != NULL && *call_data != NUL) {
|
||||
switch (1 << i) {
|
||||
case MENU_VISUAL_MODE:
|
||||
case MENU_SELECT_MODE:
|
||||
@ -438,9 +437,9 @@ add_menu_path (
|
||||
if (c != 0) {
|
||||
menu->strings[i] = xmalloc(STRLEN(call_data) + 5 );
|
||||
menu->strings[i][0] = c;
|
||||
if (d == 0)
|
||||
if (d == 0) {
|
||||
STRCPY(menu->strings[i] + 1, call_data);
|
||||
else {
|
||||
} else {
|
||||
menu->strings[i][1] = d;
|
||||
STRCPY(menu->strings[i] + 2, call_data);
|
||||
}
|
||||
@ -452,8 +451,9 @@ add_menu_path (
|
||||
menu->strings[i][len + 1] = Ctrl_G;
|
||||
menu->strings[i][len + 2] = NUL;
|
||||
}
|
||||
} else
|
||||
} else {
|
||||
menu->strings[i] = p;
|
||||
}
|
||||
menu->noremap[i] = menuarg->noremap[0];
|
||||
menu->silent[i] = menuarg->silent[0];
|
||||
}
|
||||
@ -657,20 +657,109 @@ static void free_menu_string(vimmenu_T *menu, int idx)
|
||||
menu->strings[idx] = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Show the mapping associated with a menu item or hierarchy in a sub-menu.
|
||||
*/
|
||||
static int show_menus(char_u *path_name, int modes)
|
||||
/// Export menus
|
||||
///
|
||||
/// @param[in] menu if null, starts from root_menu
|
||||
/// @param modes, a choice of \ref MENU_MODES
|
||||
/// @return a dict with name/commands
|
||||
/// @see menu_get
|
||||
static dict_T *menu_get_recursive(const vimmenu_T *menu, int modes)
|
||||
{
|
||||
dict_T *dict;
|
||||
char buf[sizeof(menu->mnemonic)];
|
||||
int mnemonic_len;
|
||||
|
||||
if (!menu || (menu->modes & modes) == 0x0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
dict = tv_dict_alloc();
|
||||
tv_dict_add_str(dict, S_LEN("name"), (char *)menu->dname);
|
||||
tv_dict_add_nr(dict, S_LEN("priority"), (int)menu->priority);
|
||||
tv_dict_add_nr(dict, S_LEN("hidden"), menu_is_hidden(menu->dname));
|
||||
|
||||
if (menu->mnemonic) {
|
||||
mnemonic_len = utf_char2bytes(menu->mnemonic, (u_char *)buf);
|
||||
buf[mnemonic_len] = '\0';
|
||||
tv_dict_add_str(dict, S_LEN("shortcut"), buf);
|
||||
}
|
||||
|
||||
if (menu->modes & MENU_TIP_MODE && menu->strings[MENU_INDEX_TIP]) {
|
||||
tv_dict_add_str(dict, S_LEN("tooltip"),
|
||||
(char *)menu->strings[MENU_INDEX_TIP]);
|
||||
}
|
||||
|
||||
if (!menu->children) {
|
||||
// leaf menu
|
||||
dict_T *commands = tv_dict_alloc();
|
||||
tv_dict_add_dict(dict, S_LEN("mappings"), commands);
|
||||
|
||||
for (int bit = 0; bit < MENU_MODES; bit++) {
|
||||
if ((menu->modes & modes & (1 << bit)) != 0) {
|
||||
dict_T *impl = tv_dict_alloc();
|
||||
if (*menu->strings[bit] == NUL) {
|
||||
tv_dict_add_str(impl, S_LEN("rhs"), (char *)"<Nop>");
|
||||
} else {
|
||||
tv_dict_add_str(impl, S_LEN("rhs"), (char *)menu->strings[bit]);
|
||||
}
|
||||
tv_dict_add_nr(impl, S_LEN("silent"), menu->silent[bit]);
|
||||
tv_dict_add_nr(impl, S_LEN("enabled"),
|
||||
(menu->enabled & (1 << bit)) ? 1 : 0);
|
||||
tv_dict_add_nr(impl, S_LEN("noremap"),
|
||||
(menu->noremap[bit] & REMAP_NONE) ? 1 : 0);
|
||||
tv_dict_add_nr(impl, S_LEN("sid"),
|
||||
(menu->noremap[bit] & REMAP_SCRIPT) ? 1 : 0);
|
||||
tv_dict_add_dict(commands, (char *)&menu_mode_chars[bit], 1, impl);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// visit recursively all children
|
||||
list_T *children_list = tv_list_alloc();
|
||||
for (menu = menu->children; menu != NULL; menu = menu->next) {
|
||||
dict_T *dic = menu_get_recursive(menu, modes);
|
||||
if (dict && tv_dict_len(dict) > 0) {
|
||||
tv_list_append_dict(children_list, dic);
|
||||
}
|
||||
}
|
||||
tv_dict_add_list(dict, S_LEN("submenus"), children_list);
|
||||
}
|
||||
return dict;
|
||||
}
|
||||
|
||||
|
||||
/// Export menus matching path \p path_name
|
||||
///
|
||||
/// @param path_name
|
||||
/// @param modes supported modes, see \ref MENU_MODES
|
||||
/// @param[in,out] list must be allocated
|
||||
/// @return false if could not find path_name
|
||||
bool menu_get(char_u *const path_name, int modes, list_T *list)
|
||||
{
|
||||
char_u *p;
|
||||
char_u *name;
|
||||
vimmenu_T *menu;
|
||||
vimmenu_T *parent = NULL;
|
||||
menu = find_menu(root_menu, path_name, modes);
|
||||
if (!menu) {
|
||||
return false;
|
||||
}
|
||||
for (; menu != NULL; menu = menu->next) {
|
||||
dict_T *dict = menu_get_recursive(menu, modes);
|
||||
if (dict && tv_dict_len(dict) > 0) {
|
||||
tv_list_append_dict(list, dict);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
menu = root_menu;
|
||||
name = path_name = vim_strsave(path_name);
|
||||
|
||||
/* First, find the (sub)menu with the given name */
|
||||
/// Find menu matching required name and modes
|
||||
///
|
||||
/// @param menu top menu to start looking from
|
||||
/// @param name path towards the menu
|
||||
/// @return menu if \p name is null, found menu or NULL
|
||||
vimmenu_T *
|
||||
find_menu(vimmenu_T *menu, char_u * name, int modes)
|
||||
{
|
||||
char_u *p;
|
||||
|
||||
while (*name) {
|
||||
p = menu_name_skip(name);
|
||||
while (menu != NULL) {
|
||||
@ -678,39 +767,46 @@ static int show_menus(char_u *path_name, int modes)
|
||||
/* Found menu */
|
||||
if (*p != NUL && menu->children == NULL) {
|
||||
EMSG(_(e_notsubmenu));
|
||||
xfree(path_name);
|
||||
return FAIL;
|
||||
return NULL;
|
||||
} else if ((menu->modes & modes) == 0x0) {
|
||||
EMSG(_(e_othermode));
|
||||
xfree(path_name);
|
||||
return FAIL;
|
||||
return NULL;
|
||||
}
|
||||
break;
|
||||
}
|
||||
menu = menu->next;
|
||||
}
|
||||
|
||||
if (menu == NULL) {
|
||||
EMSG2(_(e_nomenu), name);
|
||||
xfree(path_name);
|
||||
return FAIL;
|
||||
return NULL;
|
||||
}
|
||||
name = p;
|
||||
parent = menu;
|
||||
menu = menu->children;
|
||||
}
|
||||
xfree(path_name);
|
||||
return menu;
|
||||
}
|
||||
|
||||
/// Show the mapping associated with a menu item or hierarchy in a sub-menu.
|
||||
static int show_menus(char_u *const path_name, int modes)
|
||||
{
|
||||
vimmenu_T *menu;
|
||||
|
||||
// First, find the (sub)menu with the given name
|
||||
menu = find_menu(root_menu, path_name, modes);
|
||||
if (!menu) {
|
||||
return FAIL;
|
||||
}
|
||||
|
||||
/* Now we have found the matching menu, and we list the mappings */
|
||||
/* Highlight title */
|
||||
MSG_PUTS_TITLE(_("\n--- Menus ---"));
|
||||
|
||||
show_menus_recursive(parent, modes, 0);
|
||||
show_menus_recursive(menu->parent, modes, 0);
|
||||
return OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* Recursively show the mappings associated with the menus under the given one
|
||||
*/
|
||||
/// Recursively show the mappings associated with the menus under the given one
|
||||
static void show_menus_recursive(vimmenu_T *menu, int modes, int depth)
|
||||
{
|
||||
int i;
|
||||
@ -993,12 +1089,13 @@ char_u *get_menu_names(expand_T *xp, int idx)
|
||||
return str;
|
||||
}
|
||||
|
||||
/*
|
||||
* Skip over this element of the menu path and return the start of the next
|
||||
* element. Any \ and ^Vs are removed from the current element.
|
||||
* "name" may be modified.
|
||||
*/
|
||||
char_u *menu_name_skip(char_u *name)
|
||||
|
||||
/// Skip over this element of the menu path and return the start of the next
|
||||
/// element. Any \ and ^Vs are removed from the current element.
|
||||
///
|
||||
/// @param name may be modified.
|
||||
/// @return start of the next element
|
||||
char_u *menu_name_skip(char_u *const name)
|
||||
{
|
||||
char_u *p;
|
||||
|
||||
@ -1018,16 +1115,16 @@ char_u *menu_name_skip(char_u *name)
|
||||
* Return TRUE when "name" matches with menu "menu". The name is compared in
|
||||
* two ways: raw menu name and menu name without '&'. ignore part after a TAB.
|
||||
*/
|
||||
static int menu_name_equal(char_u *name, vimmenu_T *menu)
|
||||
static bool menu_name_equal(const char_u *const name, vimmenu_T *const menu)
|
||||
{
|
||||
if (menu->en_name != NULL
|
||||
&& (menu_namecmp(name, menu->en_name)
|
||||
|| menu_namecmp(name, menu->en_dname)))
|
||||
return TRUE;
|
||||
return true;
|
||||
return menu_namecmp(name, menu->name) || menu_namecmp(name, menu->dname);
|
||||
}
|
||||
|
||||
static int menu_namecmp(char_u *name, char_u *mname)
|
||||
static bool menu_namecmp(const char_u *const name, const char_u *const mname)
|
||||
{
|
||||
int i;
|
||||
|
||||
@ -1038,18 +1135,20 @@ static int menu_namecmp(char_u *name, char_u *mname)
|
||||
&& (mname[i] == NUL || mname[i] == TAB);
|
||||
}
|
||||
|
||||
/*
|
||||
* Return the modes specified by the given menu command (eg :menu! returns
|
||||
* MENU_CMDLINE_MODE | MENU_INSERT_MODE).
|
||||
* If "noremap" is not NULL, then the flag it points to is set according to
|
||||
* whether the command is a "nore" command.
|
||||
* If "unmenu" is not NULL, then the flag it points to is set according to
|
||||
* whether the command is an "unmenu" command.
|
||||
*/
|
||||
static int
|
||||
get_menu_cmd_modes (
|
||||
char_u *cmd,
|
||||
int forceit, /* Was there a "!" after the command? */
|
||||
|
||||
/// Returns the \ref MENU_MODES specified by menu command `cmd`.
|
||||
/// (eg :menu! returns MENU_CMDLINE_MODE | MENU_INSERT_MODE)
|
||||
///
|
||||
/// @param[in] cmd string like "nmenu", "vmenu", etc.
|
||||
/// @param[in] forceit bang (!) was given after the command
|
||||
/// @param[out] noremap If not NULL, the flag it points to is set according
|
||||
/// to whether the command is a "nore" command.
|
||||
/// @param[out] unmenu If not NULL, the flag it points to is set according
|
||||
/// to whether the command is an "unmenu" command.
|
||||
int
|
||||
get_menu_cmd_modes(
|
||||
const char_u * cmd,
|
||||
bool forceit,
|
||||
int *noremap,
|
||||
int *unmenu
|
||||
)
|
||||
@ -1090,12 +1189,15 @@ get_menu_cmd_modes (
|
||||
}
|
||||
/* FALLTHROUGH */
|
||||
default:
|
||||
--cmd;
|
||||
if (forceit) /* menu!! */
|
||||
cmd--;
|
||||
if (forceit) {
|
||||
// menu!!
|
||||
modes = MENU_INSERT_MODE | MENU_CMDLINE_MODE;
|
||||
else /* menu */
|
||||
} else {
|
||||
// menu
|
||||
modes = MENU_NORMAL_MODE | MENU_VISUAL_MODE | MENU_SELECT_MODE
|
||||
| MENU_OP_PENDING_MODE;
|
||||
}
|
||||
}
|
||||
|
||||
if (noremap != NULL)
|
||||
@ -1201,12 +1303,14 @@ int menu_is_separator(char_u *name)
|
||||
return name[0] == '-' && name[STRLEN(name) - 1] == '-';
|
||||
}
|
||||
|
||||
/*
|
||||
* Return TRUE if the menu is hidden: Starts with ']'
|
||||
*/
|
||||
|
||||
/// True if a popup menu or starts with \ref MNU_HIDDEN_CHAR
|
||||
///
|
||||
/// @return true if the menu is hidden
|
||||
static int menu_is_hidden(char_u *name)
|
||||
{
|
||||
return (name[0] == ']') || (menu_is_popup(name) && name[5] != NUL);
|
||||
return (name[0] == MNU_HIDDEN_CHAR)
|
||||
|| (menu_is_popup(name) && name[5] != NUL);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -6,7 +6,9 @@
|
||||
#include "nvim/types.h" // for char_u and expand_T
|
||||
#include "nvim/ex_cmds_defs.h" // for exarg_T
|
||||
|
||||
/* Indices into vimmenu_T->strings[] and vimmenu_T->noremap[] for each mode */
|
||||
/// Indices into vimmenu_T->strings[] and vimmenu_T->noremap[] for each mode
|
||||
/// \addtogroup MENU_INDEX
|
||||
/// @{
|
||||
#define MENU_INDEX_INVALID -1
|
||||
#define MENU_INDEX_NORMAL 0
|
||||
#define MENU_INDEX_VISUAL 1
|
||||
@ -16,8 +18,12 @@
|
||||
#define MENU_INDEX_CMDLINE 5
|
||||
#define MENU_INDEX_TIP 6
|
||||
#define MENU_MODES 7
|
||||
/// @}
|
||||
/// note MENU_INDEX_TIP is not a 'real' mode
|
||||
|
||||
/* Menu modes */
|
||||
/// Menu modes
|
||||
/// \addtogroup MENU_MODES
|
||||
/// @{
|
||||
#define MENU_NORMAL_MODE (1 << MENU_INDEX_NORMAL)
|
||||
#define MENU_VISUAL_MODE (1 << MENU_INDEX_VISUAL)
|
||||
#define MENU_SELECT_MODE (1 << MENU_INDEX_SELECT)
|
||||
@ -26,31 +32,30 @@
|
||||
#define MENU_CMDLINE_MODE (1 << MENU_INDEX_CMDLINE)
|
||||
#define MENU_TIP_MODE (1 << MENU_INDEX_TIP)
|
||||
#define MENU_ALL_MODES ((1 << MENU_INDEX_TIP) - 1)
|
||||
/*note MENU_INDEX_TIP is not a 'real' mode*/
|
||||
/// @}
|
||||
|
||||
/* Start a menu name with this to not include it on the main menu bar */
|
||||
/// Start a menu name with this to not include it on the main menu bar
|
||||
#define MNU_HIDDEN_CHAR ']'
|
||||
|
||||
typedef struct VimMenu vimmenu_T;
|
||||
|
||||
struct VimMenu {
|
||||
int modes; /* Which modes is this menu visible for? */
|
||||
int enabled; /* for which modes the menu is enabled */
|
||||
char_u *name; /* Name of menu, possibly translated */
|
||||
char_u *dname; /* Displayed Name ("name" without '&') */
|
||||
char_u *en_name; /* "name" untranslated, NULL when "name"
|
||||
* was not translated */
|
||||
char_u *en_dname; /* "dname" untranslated, NULL when "dname"
|
||||
* was not translated */
|
||||
int mnemonic; /* mnemonic key (after '&') */
|
||||
char_u *actext; /* accelerator text (after TAB) */
|
||||
long priority; /* Menu order priority */
|
||||
char_u *strings[MENU_MODES]; /* Mapped string for each mode */
|
||||
int noremap[MENU_MODES]; /* A REMAP_ flag for each mode */
|
||||
bool silent[MENU_MODES]; /* A silent flag for each mode */
|
||||
vimmenu_T *children; /* Children of sub-menu */
|
||||
vimmenu_T *parent; /* Parent of menu */
|
||||
vimmenu_T *next; /* Next item in menu */
|
||||
int modes; ///< Which modes is this menu visible for
|
||||
int enabled; ///< for which modes the menu is enabled
|
||||
char_u *name; ///< Name of menu, possibly translated
|
||||
char_u *dname; ///< Displayed Name ("name" without '&')
|
||||
char_u *en_name; ///< "name" untranslated, NULL when
|
||||
///< was not translated
|
||||
char_u *en_dname; ///< NULL when "dname" untranslated
|
||||
int mnemonic; ///< mnemonic key (after '&')
|
||||
char_u *actext; ///< accelerator text (after TAB)
|
||||
long priority; ///< Menu order priority
|
||||
char_u *strings[MENU_MODES]; ///< Mapped string for each mode
|
||||
int noremap[MENU_MODES]; ///< A \ref REMAP_VALUES flag for each mode
|
||||
bool silent[MENU_MODES]; ///< A silent flag for each mode
|
||||
vimmenu_T *children; ///< Children of sub-menu
|
||||
vimmenu_T *parent; ///< Parent of menu
|
||||
vimmenu_T *next; ///< Next item in menu
|
||||
};
|
||||
|
||||
|
||||
|
@ -1763,7 +1763,7 @@ int onepage(int dir, long count)
|
||||
|
||||
loff.fill = 0;
|
||||
if (dir == FORWARD) {
|
||||
if (firstwin == lastwin && p_window > 0 && p_window < Rows - 1) {
|
||||
if (ONE_WINDOW && p_window > 0 && p_window < Rows - 1) {
|
||||
/* Vi compatible scrolling */
|
||||
if (p_window <= 2)
|
||||
++curwin->w_topline;
|
||||
@ -1797,7 +1797,7 @@ int onepage(int dir, long count)
|
||||
max_topfill();
|
||||
continue;
|
||||
}
|
||||
if (firstwin == lastwin && p_window > 0 && p_window < Rows - 1) {
|
||||
if (ONE_WINDOW && p_window > 0 && p_window < Rows - 1) {
|
||||
/* Vi compatible scrolling (sort of) */
|
||||
if (p_window <= 2)
|
||||
--curwin->w_topline;
|
||||
|
@ -117,12 +117,15 @@ void channel_teardown(void)
|
||||
/// Creates an API channel by starting a process and connecting to its
|
||||
/// stdin/stdout. stderr is handled by the job infrastructure.
|
||||
///
|
||||
/// @param argv The argument vector for the process. [consumed]
|
||||
/// @return The channel id (> 0), on success.
|
||||
/// 0, on error.
|
||||
uint64_t channel_from_process(Process *proc, uint64_t id)
|
||||
/// @param proc process object
|
||||
/// @param id (optional) channel id
|
||||
/// @param source description of source function, rplugin name, TCP addr, etc
|
||||
///
|
||||
/// @return Channel id (> 0), on success. 0, on error.
|
||||
uint64_t channel_from_process(Process *proc, uint64_t id, char *source)
|
||||
{
|
||||
Channel *channel = register_channel(kChannelTypeProc, id, proc->events);
|
||||
Channel *channel = register_channel(kChannelTypeProc, id, proc->events,
|
||||
source);
|
||||
incref(channel); // process channels are only closed by the exit_cb
|
||||
channel->data.proc = proc;
|
||||
|
||||
@ -138,7 +141,8 @@ uint64_t channel_from_process(Process *proc, uint64_t id)
|
||||
/// @param watcher The SocketWatcher ready to accept the connection
|
||||
void channel_from_connection(SocketWatcher *watcher)
|
||||
{
|
||||
Channel *channel = register_channel(kChannelTypeSocket, 0, NULL);
|
||||
Channel *channel = register_channel(kChannelTypeSocket, 0, NULL,
|
||||
watcher->addr);
|
||||
socket_watcher_accept(watcher, &channel->data.stream);
|
||||
incref(channel); // close channel only after the stream is closed
|
||||
channel->data.stream.internal_close_cb = close_cb;
|
||||
@ -148,8 +152,9 @@ void channel_from_connection(SocketWatcher *watcher)
|
||||
rstream_start(&channel->data.stream, receive_msgpack, channel);
|
||||
}
|
||||
|
||||
uint64_t channel_connect(bool tcp, const char *address,
|
||||
int timeout, const char **error)
|
||||
/// @param source description of source function, rplugin name, TCP addr, etc
|
||||
uint64_t channel_connect(bool tcp, const char *address, int timeout,
|
||||
char *source, const char **error)
|
||||
{
|
||||
if (!tcp) {
|
||||
char *path = fix_fname(address);
|
||||
@ -161,7 +166,7 @@ uint64_t channel_connect(bool tcp, const char *address,
|
||||
xfree(path);
|
||||
}
|
||||
|
||||
Channel *channel = register_channel(kChannelTypeSocket, 0, NULL);
|
||||
Channel *channel = register_channel(kChannelTypeSocket, 0, NULL, source);
|
||||
if (!socket_connect(&main_loop, &channel->data.stream,
|
||||
tcp, address, timeout, error)) {
|
||||
decref(channel);
|
||||
@ -329,11 +334,10 @@ bool channel_close(uint64_t id)
|
||||
return true;
|
||||
}
|
||||
|
||||
/// Creates an API channel from stdin/stdout. This is used when embedding
|
||||
/// Neovim
|
||||
/// Creates an API channel from stdin/stdout. Used to embed Nvim.
|
||||
void channel_from_stdio(void)
|
||||
{
|
||||
Channel *channel = register_channel(kChannelTypeStdio, 0, NULL);
|
||||
Channel *channel = register_channel(kChannelTypeStdio, 0, NULL, NULL);
|
||||
incref(channel); // stdio channels are only closed on exit
|
||||
// read stream
|
||||
rstream_init_fd(&main_loop, &channel->data.std.in, 0, CHANNEL_BUFFER_SIZE);
|
||||
@ -346,7 +350,7 @@ void channel_from_stdio(void)
|
||||
/// when an instance connects to its own named pipe.
|
||||
uint64_t channel_create_internal(void)
|
||||
{
|
||||
Channel *channel = register_channel(kChannelTypeInternal, 0, NULL);
|
||||
Channel *channel = register_channel(kChannelTypeInternal, 0, NULL, NULL);
|
||||
incref(channel); // internal channel lives until process exit
|
||||
return channel->id;
|
||||
}
|
||||
@ -745,9 +749,12 @@ static void close_cb(Stream *stream, void *data)
|
||||
decref(data);
|
||||
}
|
||||
|
||||
/// @param source description of source function, rplugin name, TCP addr, etc
|
||||
static Channel *register_channel(ChannelType type, uint64_t id,
|
||||
MultiQueue *events)
|
||||
MultiQueue *events, char *source)
|
||||
{
|
||||
// Jobs and channels share the same id namespace.
|
||||
assert(id == 0 || !pmap_get(uint64_t)(channels, id));
|
||||
Channel *rv = xmalloc(sizeof(Channel));
|
||||
rv->events = events ? events : multiqueue_new_child(main_loop.events);
|
||||
rv->type = type;
|
||||
@ -761,6 +768,14 @@ static Channel *register_channel(ChannelType type, uint64_t id,
|
||||
kv_init(rv->call_stack);
|
||||
kv_init(rv->delayed_notifications);
|
||||
pmap_put(uint64_t)(channels, rv->id, rv);
|
||||
|
||||
ILOG("new channel %" PRIu64 " (%s): %s", rv->id,
|
||||
(type == kChannelTypeProc ? "proc"
|
||||
: (type == kChannelTypeSocket ? "socket"
|
||||
: (type == kChannelTypeStdio ? "stdio"
|
||||
: (type == kChannelTypeInternal ? "internal" : "?")))),
|
||||
(source ? source : "?"));
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
@ -3657,6 +3657,39 @@ nv_gd (
|
||||
}
|
||||
}
|
||||
|
||||
// Return true if line[offset] is not inside a C-style comment or string, false
|
||||
// otherwise.
|
||||
static bool is_ident(char_u *line, int offset)
|
||||
{
|
||||
bool incomment = false;
|
||||
int instring = 0;
|
||||
int prev = 0;
|
||||
|
||||
for (int i = 0; i < offset && line[i] != NUL; i++) {
|
||||
if (instring != 0) {
|
||||
if (prev != '\\' && line[i] == instring) {
|
||||
instring = 0;
|
||||
}
|
||||
} else if ((line[i] == '"' || line[i] == '\'') && !incomment) {
|
||||
instring = line[i];
|
||||
} else {
|
||||
if (incomment) {
|
||||
if (prev == '*' && line[i] == '/') {
|
||||
incomment = false;
|
||||
}
|
||||
} else if (prev == '/' && line[i] == '*') {
|
||||
incomment = true;
|
||||
} else if (prev == '/' && line[i] == '/') {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
prev = line[i];
|
||||
}
|
||||
|
||||
return incomment == false && instring == 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Search for variable declaration of "ptr[len]".
|
||||
* When "locally" is true in the current function ("gd"), otherwise in the
|
||||
@ -3683,6 +3716,7 @@ find_decl (
|
||||
bool retval = true;
|
||||
bool incll;
|
||||
int searchflags = flags_arg;
|
||||
bool valid;
|
||||
|
||||
pat = xmalloc(len + 7);
|
||||
|
||||
@ -3717,6 +3751,7 @@ find_decl (
|
||||
/* Search forward for the identifier, ignore comment lines. */
|
||||
clearpos(&found_pos);
|
||||
for (;; ) {
|
||||
valid = false;
|
||||
t = searchit(curwin, curbuf, &curwin->w_cursor, FORWARD,
|
||||
pat, 1L, searchflags, RE_LAST, (linenr_T)0, NULL);
|
||||
if (curwin->w_cursor.lnum >= old_pos.lnum)
|
||||
@ -3747,20 +3782,35 @@ find_decl (
|
||||
curwin->w_cursor.col = 0;
|
||||
continue;
|
||||
}
|
||||
if (!locally) /* global search: use first match found */
|
||||
valid = is_ident(get_cursor_line_ptr(), curwin->w_cursor.col);
|
||||
|
||||
// If the current position is not a valid identifier and a previous match is
|
||||
// present, favor that one instead.
|
||||
if (!valid && found_pos.lnum != 0) {
|
||||
curwin->w_cursor = found_pos;
|
||||
break;
|
||||
if (curwin->w_cursor.lnum >= par_pos.lnum) {
|
||||
/* If we previously found a valid position, use it. */
|
||||
if (found_pos.lnum != 0)
|
||||
}
|
||||
// global search: use first match found
|
||||
if (valid && !locally) {
|
||||
break;
|
||||
}
|
||||
if (valid && curwin->w_cursor.lnum >= par_pos.lnum) {
|
||||
// If we previously found a valid position, use it.
|
||||
if (found_pos.lnum != 0) {
|
||||
curwin->w_cursor = found_pos;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// For finding a local variable and the match is before the "{" search
|
||||
// to find a later match. For K&R style function declarations this
|
||||
// skips the function header without types. Remove SEARCH_START from
|
||||
// flags to avoid getting stuck at one position.
|
||||
found_pos = curwin->w_cursor;
|
||||
// For finding a local variable and the match is before the "{" or
|
||||
// inside a comment, continue searching. For K&R style function
|
||||
// declarations this skips the function header without types.
|
||||
if (!valid) {
|
||||
clearpos(&found_pos);
|
||||
} else {
|
||||
found_pos = curwin->w_cursor;
|
||||
}
|
||||
// Remove SEARCH_START from flags to avoid getting stuck at one position.
|
||||
searchflags &= ~SEARCH_START;
|
||||
}
|
||||
|
||||
|
@ -2457,12 +2457,11 @@ did_set_string_option (
|
||||
if ((secure || sandbox != 0)
|
||||
&& (options[opt_idx].flags & P_SECURE)) {
|
||||
errmsg = e_secure;
|
||||
}
|
||||
/* Check for a "normal" file name in some options. Disallow a path
|
||||
* separator (slash and/or backslash), wildcards and characters that are
|
||||
* often illegal in a file name. */
|
||||
else if ((options[opt_idx].flags & P_NFNAME)
|
||||
&& vim_strpbrk(*varp, (char_u *)"/\\*?[|<>") != NULL) {
|
||||
} else if ((options[opt_idx].flags & P_NFNAME)
|
||||
&& vim_strpbrk(*varp, (char_u *)"/\\*?[|;&<>\r\n") != NULL) {
|
||||
// Check for a "normal" file name in some options. Disallow a path
|
||||
// separator (slash and/or backslash), wildcards and characters that are
|
||||
// often illegal in a file name.
|
||||
errmsg = e_invarg;
|
||||
}
|
||||
/* 'backupcopy' */
|
||||
@ -4078,7 +4077,7 @@ static char *set_num_option(int opt_idx, char_u *varp, long value,
|
||||
}
|
||||
|
||||
/* Change window height NOW */
|
||||
if (lastwin != firstwin) {
|
||||
if (!ONE_WINDOW) {
|
||||
if (pp == &p_wh && curwin->w_height < p_wh)
|
||||
win_setheight((int)p_wh);
|
||||
if (pp == &p_hh && curbuf->b_help && curwin->w_height < p_hh)
|
||||
@ -4107,7 +4106,7 @@ static char *set_num_option(int opt_idx, char_u *varp, long value,
|
||||
}
|
||||
|
||||
/* Change window width NOW */
|
||||
if (lastwin != firstwin && curwin->w_width < p_wiw)
|
||||
if (!ONE_WINDOW && curwin->w_width < p_wiw)
|
||||
win_setwidth((int)p_wiw);
|
||||
}
|
||||
/* 'winminwidth' */
|
||||
@ -5239,7 +5238,7 @@ static int put_setbool(FILE *fd, char *cmd, char *name, int value)
|
||||
|
||||
void comp_col(void)
|
||||
{
|
||||
int last_has_status = (p_ls == 2 || (p_ls == 1 && firstwin != lastwin));
|
||||
int last_has_status = (p_ls == 2 || (p_ls == 1 && !ONE_WINDOW));
|
||||
|
||||
sc_col = 0;
|
||||
ru_col = 0;
|
||||
@ -5718,7 +5717,22 @@ void buf_copy_options(buf_T *buf, int flags)
|
||||
free_buf_options(buf, TRUE);
|
||||
buf->b_p_ro = FALSE; /* don't copy readonly */
|
||||
buf->b_p_fenc = vim_strsave(p_fenc);
|
||||
buf->b_p_ff = vim_strsave(p_ff);
|
||||
switch (*p_ffs) {
|
||||
case 'm':
|
||||
buf->b_p_ff = vim_strsave((char_u *)FF_MAC);
|
||||
break;
|
||||
case 'd':
|
||||
buf->b_p_ff = vim_strsave((char_u *)FF_DOS);
|
||||
break;
|
||||
case 'u':
|
||||
buf->b_p_ff = vim_strsave((char_u *)FF_UNIX);
|
||||
break;
|
||||
default:
|
||||
buf->b_p_ff = vim_strsave(p_ff);
|
||||
}
|
||||
if (buf->b_p_ff != NULL) {
|
||||
buf->b_start_ffc = *buf->b_p_ff;
|
||||
}
|
||||
buf->b_p_bh = empty_option;
|
||||
buf->b_p_bt = empty_option;
|
||||
} else
|
||||
@ -7039,8 +7053,11 @@ dict_T *get_winbuf_options(const int bufopt)
|
||||
if (opt->flags & P_STRING) {
|
||||
tv_dict_add_str(d, opt->fullname, strlen(opt->fullname),
|
||||
*(const char **)varp);
|
||||
} else if (opt->flags & P_NUM) {
|
||||
tv_dict_add_nr(d, opt->fullname, strlen(opt->fullname),
|
||||
*(long *)varp);
|
||||
} else {
|
||||
tv_dict_add_nr(d, opt->fullname, strlen(opt->fullname), *varp);
|
||||
tv_dict_add_nr(d, opt->fullname, strlen(opt->fullname), *(int *)varp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -447,7 +447,7 @@ static void out_data_append_to_screen(char *output, size_t remaining,
|
||||
size_t off = 0;
|
||||
int last_row = (int)Rows - 1;
|
||||
|
||||
while (off < remaining) {
|
||||
while (output != NULL && off < remaining) {
|
||||
// Found end of line?
|
||||
if (output[off] == NL) {
|
||||
// Can we start a new line or do we need to continue the last one?
|
||||
@ -473,7 +473,7 @@ static void out_data_append_to_screen(char *output, size_t remaining,
|
||||
off++;
|
||||
}
|
||||
|
||||
if (remaining) {
|
||||
if (output != NULL && remaining) {
|
||||
if (last_col == 0) {
|
||||
screen_del_lines(0, 0, 1, (int)Rows, NULL);
|
||||
}
|
||||
@ -496,12 +496,8 @@ static void out_data_cb(Stream *stream, RBuffer *buf, size_t count, void *data,
|
||||
size_t cnt;
|
||||
char *ptr = rbuffer_read_ptr(buf, &cnt);
|
||||
|
||||
if (ptr == NULL || cnt == 0) {
|
||||
// Nothing to read;
|
||||
return;
|
||||
}
|
||||
|
||||
if (out_data_decide_throttle(cnt)) { // Skip output above a threshold.
|
||||
if (ptr != NULL && cnt > 0
|
||||
&& out_data_decide_throttle(cnt)) { // Skip output above a threshold.
|
||||
// Save the skipped output. If it is the final chunk, we display it later.
|
||||
out_data_ring(ptr, cnt);
|
||||
} else {
|
||||
|
@ -383,6 +383,8 @@ static int efm_to_regpat(char_u *efm, int len, efm_T *fmt_ptr,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static efm_T *fmt_start = NULL; // cached across qf_parse_line() calls
|
||||
|
||||
static void free_efm_list(efm_T **efm_first)
|
||||
{
|
||||
for (efm_T *efm_ptr = *efm_first; efm_ptr != NULL; efm_ptr = *efm_first) {
|
||||
@ -390,6 +392,8 @@ static void free_efm_list(efm_T **efm_first)
|
||||
vim_regfree(efm_ptr->prog);
|
||||
xfree(efm_ptr);
|
||||
}
|
||||
|
||||
fmt_start = NULL;
|
||||
}
|
||||
|
||||
// Parse 'errorformat' option
|
||||
@ -671,7 +675,6 @@ static int qf_parse_line(qf_info_T *qi, char_u *linebuf, size_t linelen,
|
||||
efm_T *fmt_first, qffields_T *fields)
|
||||
{
|
||||
efm_T *fmt_ptr;
|
||||
static efm_T *fmt_start = NULL; // cached across calls
|
||||
size_t len;
|
||||
int i;
|
||||
int idx = 0;
|
||||
@ -875,36 +878,38 @@ restofline:
|
||||
qi->qf_multiignore = false; // reset continuation
|
||||
} else if (vim_strchr((char_u *)"CZ", idx)
|
||||
!= NULL) { // continuation of multi-line msg
|
||||
qfline_T *qfprev = qi->qf_lists[qi->qf_curlist].qf_last;
|
||||
if (qfprev == NULL) {
|
||||
return QF_FAIL;
|
||||
}
|
||||
if (*fields->errmsg && !qi->qf_multiignore) {
|
||||
size_t len = STRLEN(qfprev->qf_text);
|
||||
qfprev->qf_text = xrealloc(qfprev->qf_text,
|
||||
len + STRLEN(fields->errmsg) + 2);
|
||||
qfprev->qf_text[len] = '\n';
|
||||
STRCPY(qfprev->qf_text + len + 1, fields->errmsg);
|
||||
}
|
||||
if (qfprev->qf_nr == -1) {
|
||||
qfprev->qf_nr = fields->enr;
|
||||
}
|
||||
if (vim_isprintc(fields->type) && !qfprev->qf_type) {
|
||||
qfprev->qf_type = fields->type; // only printable chars allowed
|
||||
}
|
||||
if (!qfprev->qf_lnum) {
|
||||
qfprev->qf_lnum = fields->lnum;
|
||||
}
|
||||
if (!qfprev->qf_col) {
|
||||
qfprev->qf_col = fields->col;
|
||||
}
|
||||
qfprev->qf_viscol = fields->use_viscol;
|
||||
if (!qfprev->qf_fnum) {
|
||||
qfprev->qf_fnum = qf_get_fnum(qi, qi->qf_directory,
|
||||
*fields->namebuf || qi->qf_directory
|
||||
? fields->namebuf
|
||||
: qi->qf_currfile && fields->valid
|
||||
? qi->qf_currfile : 0);
|
||||
if (!qi->qf_multiignore) {
|
||||
qfline_T *qfprev = qi->qf_lists[qi->qf_curlist].qf_last;
|
||||
if (qfprev == NULL) {
|
||||
return QF_FAIL;
|
||||
}
|
||||
if (*fields->errmsg && !qi->qf_multiignore) {
|
||||
size_t len = STRLEN(qfprev->qf_text);
|
||||
qfprev->qf_text = xrealloc(qfprev->qf_text,
|
||||
len + STRLEN(fields->errmsg) + 2);
|
||||
qfprev->qf_text[len] = '\n';
|
||||
STRCPY(qfprev->qf_text + len + 1, fields->errmsg);
|
||||
}
|
||||
if (qfprev->qf_nr == -1) {
|
||||
qfprev->qf_nr = fields->enr;
|
||||
}
|
||||
if (vim_isprintc(fields->type) && !qfprev->qf_type) {
|
||||
qfprev->qf_type = fields->type; // only printable chars allowed
|
||||
}
|
||||
if (!qfprev->qf_lnum) {
|
||||
qfprev->qf_lnum = fields->lnum;
|
||||
}
|
||||
if (!qfprev->qf_col) {
|
||||
qfprev->qf_col = fields->col;
|
||||
}
|
||||
qfprev->qf_viscol = fields->use_viscol;
|
||||
if (!qfprev->qf_fnum) {
|
||||
qfprev->qf_fnum = qf_get_fnum(qi, qi->qf_directory,
|
||||
*fields->namebuf || qi->qf_directory
|
||||
? fields->namebuf
|
||||
: qi->qf_currfile && fields->valid
|
||||
? qi->qf_currfile : 0);
|
||||
}
|
||||
}
|
||||
if (idx == 'Z') {
|
||||
qi->qf_multiline = qi->qf_multiignore = false;
|
||||
@ -967,6 +972,7 @@ qf_init_ext(
|
||||
NULL, 0, 0 };
|
||||
qffields_T fields = { NULL, NULL, 0, 0L, 0, false, NULL, 0, 0, 0 };
|
||||
qfline_T *old_last = NULL;
|
||||
bool adding = false;
|
||||
static efm_T *fmt_first = NULL;
|
||||
char_u *efm;
|
||||
static char_u *last_efm = NULL;
|
||||
@ -992,6 +998,7 @@ qf_init_ext(
|
||||
qf_new_list(qi, qf_title);
|
||||
} else if (qi->qf_lists[qi->qf_curlist].qf_count > 0) {
|
||||
// Adding to existing list, use last entry.
|
||||
adding = true;
|
||||
old_last = qi->qf_lists[qi->qf_curlist].qf_last;
|
||||
}
|
||||
|
||||
@ -1108,10 +1115,12 @@ qf_init_ext(
|
||||
}
|
||||
EMSG(_(e_readerrf));
|
||||
error2:
|
||||
qf_free(qi, qi->qf_curlist);
|
||||
qi->qf_listcount--;
|
||||
if (qi->qf_curlist > 0) {
|
||||
qi->qf_curlist--;
|
||||
if (!adding) {
|
||||
qf_free(qi, qi->qf_curlist);
|
||||
qi->qf_listcount--;
|
||||
if (qi->qf_curlist > 0) {
|
||||
qi->qf_curlist--;
|
||||
}
|
||||
}
|
||||
qf_init_end:
|
||||
if (state.fd != NULL) {
|
||||
@ -1408,7 +1417,7 @@ void copy_loclist(win_T *from, win_T *to)
|
||||
to->w_llist->qf_curlist = qi->qf_curlist; /* current list */
|
||||
}
|
||||
|
||||
// Get buffer number for file "directory.fname".
|
||||
// Get buffer number for file "directory/fname".
|
||||
// Also sets the b_has_qf_entry flag.
|
||||
static int qf_get_fnum(qf_info_T *qi, char_u *directory, char_u *fname)
|
||||
{
|
||||
@ -1869,7 +1878,7 @@ win_found:
|
||||
* If there is only one window and it is the quickfix window, create a
|
||||
* new one above the quickfix window.
|
||||
*/
|
||||
if (((firstwin == lastwin) && bt_quickfix(curbuf)) || !usable_win) {
|
||||
if ((ONE_WINDOW && bt_quickfix(curbuf)) || !usable_win) {
|
||||
flags = WSP_ABOVE;
|
||||
if (ll_ref != NULL)
|
||||
flags |= WSP_NEWLOC;
|
||||
@ -2362,7 +2371,9 @@ static void qf_free(qf_info_T *qi, int idx)
|
||||
qi->qf_lists[idx].qf_index = 0;
|
||||
|
||||
qf_clean_dir_stack(&qi->qf_dir_stack);
|
||||
qi->qf_directory = NULL;
|
||||
qf_clean_dir_stack(&qi->qf_file_stack);
|
||||
qi->qf_currfile = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -3116,7 +3127,7 @@ static char_u *get_mef_name(void)
|
||||
STRCPY(name, p_mef);
|
||||
sprintf((char *)name + (p - p_mef), "%d%d", start, off);
|
||||
STRCAT(name, p + 2);
|
||||
// Don't accept a symbolic link, its a security risk.
|
||||
// Don't accept a symbolic link, it's a security risk.
|
||||
FileInfo file_info;
|
||||
bool file_or_link_found = os_fileinfo_link((char *)name, &file_info);
|
||||
if (!file_or_link_found) {
|
||||
@ -4025,9 +4036,12 @@ int get_errorlist_properties(win_T *wp, dict_T *what, dict_T *retdict)
|
||||
if ((di = tv_dict_find(what, S_LEN("nr"))) != NULL) {
|
||||
// Use the specified quickfix/location list
|
||||
if (di->di_tv.v_type == VAR_NUMBER) {
|
||||
qf_idx = (int)di->di_tv.vval.v_number - 1;
|
||||
if (qf_idx < 0 || qf_idx >= qi->qf_listcount) {
|
||||
return FAIL;
|
||||
// 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) {
|
||||
return FAIL;
|
||||
}
|
||||
}
|
||||
flags |= QF_GETLIST_NR;
|
||||
} else {
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -4882,7 +4882,7 @@ static long find_match_text(colnr_T startcol, int regstart, char_u *match_text)
|
||||
int c2_len = PTR2LEN(s2);
|
||||
int c2 = PTR2CHAR(s2);
|
||||
|
||||
if ((c1 != c2 && (!ireg_ic || mb_tolower(c1) != mb_tolower(c2)))
|
||||
if ((c1 != c2 && (!rex.reg_ic || mb_tolower(c1) != mb_tolower(c2)))
|
||||
|| c1_len != c2_len) {
|
||||
match = false;
|
||||
break;
|
||||
@ -4895,13 +4895,13 @@ static long find_match_text(colnr_T startcol, int regstart, char_u *match_text)
|
||||
&& !(enc_utf8 && utf_iscomposing(PTR2CHAR(s2)))) {
|
||||
cleanup_subexpr();
|
||||
if (REG_MULTI) {
|
||||
reg_startpos[0].lnum = reglnum;
|
||||
reg_startpos[0].col = col;
|
||||
reg_endpos[0].lnum = reglnum;
|
||||
reg_endpos[0].col = s2 - regline;
|
||||
rex.reg_startpos[0].lnum = reglnum;
|
||||
rex.reg_startpos[0].col = col;
|
||||
rex.reg_endpos[0].lnum = reglnum;
|
||||
rex.reg_endpos[0].col = s2 - regline;
|
||||
} else {
|
||||
reg_startp[0] = regline + col;
|
||||
reg_endp[0] = s2;
|
||||
rex.reg_startp[0] = regline + col;
|
||||
rex.reg_endp[0] = s2;
|
||||
}
|
||||
return 1L;
|
||||
}
|
||||
@ -5116,8 +5116,8 @@ static int nfa_regmatch(nfa_regprog_T *prog, nfa_state_T *start,
|
||||
case NFA_MATCH:
|
||||
{
|
||||
// If the match ends before a composing characters and
|
||||
// ireg_icombine is not set, that is not really a match.
|
||||
if (enc_utf8 && !ireg_icombine && utf_iscomposing(curc)) {
|
||||
// rex.reg_icombine is not set, that is not really a match.
|
||||
if (enc_utf8 && !rex.reg_icombine && utf_iscomposing(curc)) {
|
||||
break;
|
||||
}
|
||||
nfa_match = true;
|
||||
@ -5400,15 +5400,15 @@ static int nfa_regmatch(nfa_regprog_T *prog, nfa_state_T *start,
|
||||
int this_class;
|
||||
|
||||
// Get class of current and previous char (if it exists).
|
||||
this_class = mb_get_class_tab(reginput, reg_buf->b_chartab);
|
||||
this_class = mb_get_class_tab(reginput, rex.reg_buf->b_chartab);
|
||||
if (this_class <= 1) {
|
||||
result = false;
|
||||
} else if (reg_prev_class() == this_class) {
|
||||
result = false;
|
||||
}
|
||||
} else if (!vim_iswordc_buf(curc, reg_buf)
|
||||
} else if (!vim_iswordc_buf(curc, rex.reg_buf)
|
||||
|| (reginput > regline
|
||||
&& vim_iswordc_buf(reginput[-1], reg_buf))) {
|
||||
&& vim_iswordc_buf(reginput[-1], rex.reg_buf))) {
|
||||
result = false;
|
||||
}
|
||||
if (result) {
|
||||
@ -5425,15 +5425,15 @@ static int nfa_regmatch(nfa_regprog_T *prog, nfa_state_T *start,
|
||||
int this_class, prev_class;
|
||||
|
||||
// Get class of current and previous char (if it exists).
|
||||
this_class = mb_get_class_tab(reginput, reg_buf->b_chartab);
|
||||
this_class = mb_get_class_tab(reginput, rex.reg_buf->b_chartab);
|
||||
prev_class = reg_prev_class();
|
||||
if (this_class == prev_class
|
||||
|| prev_class == 0 || prev_class == 1) {
|
||||
result = false;
|
||||
}
|
||||
} else if (!vim_iswordc_buf(reginput[-1], reg_buf)
|
||||
} else if (!vim_iswordc_buf(reginput[-1], rex.reg_buf)
|
||||
|| (reginput[0] != NUL
|
||||
&& vim_iswordc_buf(curc, reg_buf))) {
|
||||
&& vim_iswordc_buf(curc, rex.reg_buf))) {
|
||||
result = false;
|
||||
}
|
||||
if (result) {
|
||||
@ -5444,14 +5444,14 @@ static int nfa_regmatch(nfa_regprog_T *prog, nfa_state_T *start,
|
||||
|
||||
case NFA_BOF:
|
||||
if (reglnum == 0 && reginput == regline
|
||||
&& (!REG_MULTI || reg_firstlnum == 1)) {
|
||||
&& (!REG_MULTI || rex.reg_firstlnum == 1)) {
|
||||
add_here = true;
|
||||
add_state = t->state->out;
|
||||
}
|
||||
break;
|
||||
|
||||
case NFA_EOF:
|
||||
if (reglnum == reg_maxline && curc == NUL) {
|
||||
if (reglnum == rex.reg_maxline && curc == NUL) {
|
||||
add_here = true;
|
||||
add_state = t->state->out;
|
||||
}
|
||||
@ -5475,7 +5475,7 @@ static int nfa_regmatch(nfa_regprog_T *prog, nfa_state_T *start,
|
||||
// (no preceding character).
|
||||
len += mb_char2len(mc);
|
||||
}
|
||||
if (ireg_icombine && len == 0) {
|
||||
if (rex.reg_icombine && len == 0) {
|
||||
// If \Z was present, then ignore composing characters.
|
||||
// When ignoring the base character this always matches.
|
||||
if (sta->c != curc) {
|
||||
@ -5526,14 +5526,14 @@ static int nfa_regmatch(nfa_regprog_T *prog, nfa_state_T *start,
|
||||
}
|
||||
|
||||
case NFA_NEWL:
|
||||
if (curc == NUL && !reg_line_lbr && REG_MULTI
|
||||
&& reglnum <= reg_maxline) {
|
||||
if (curc == NUL && !rex.reg_line_lbr && REG_MULTI
|
||||
&& reglnum <= rex.reg_maxline) {
|
||||
go_to_nextline = true;
|
||||
// Pass -1 for the offset, which means taking the position
|
||||
// at the start of the next line.
|
||||
add_state = t->state->out;
|
||||
add_off = -1;
|
||||
} else if (curc == '\n' && reg_line_lbr) {
|
||||
} else if (curc == '\n' && rex.reg_line_lbr) {
|
||||
// match \n as if it is an ordinary character
|
||||
add_state = t->state->out;
|
||||
add_off = 1;
|
||||
@ -5574,7 +5574,7 @@ static int nfa_regmatch(nfa_regprog_T *prog, nfa_state_T *start,
|
||||
result = result_if_matched;
|
||||
break;
|
||||
}
|
||||
if (ireg_ic) {
|
||||
if (rex.reg_ic) {
|
||||
int curc_low = mb_tolower(curc);
|
||||
int done = false;
|
||||
|
||||
@ -5591,7 +5591,7 @@ static int nfa_regmatch(nfa_regprog_T *prog, nfa_state_T *start,
|
||||
}
|
||||
} else if (state->c < 0 ? check_char_class(state->c, curc)
|
||||
: (curc == state->c
|
||||
|| (ireg_ic && mb_tolower(curc)
|
||||
|| (rex.reg_ic && mb_tolower(curc)
|
||||
== mb_tolower(state->c)))) {
|
||||
result = result_if_matched;
|
||||
break;
|
||||
@ -5639,13 +5639,13 @@ static int nfa_regmatch(nfa_regprog_T *prog, nfa_state_T *start,
|
||||
break;
|
||||
|
||||
case NFA_KWORD: // \k
|
||||
result = vim_iswordp_buf(reginput, reg_buf);
|
||||
result = vim_iswordp_buf(reginput, rex.reg_buf);
|
||||
ADD_STATE_IF_MATCH(t->state);
|
||||
break;
|
||||
|
||||
case NFA_SKWORD: // \K
|
||||
result = !ascii_isdigit(curc)
|
||||
&& vim_iswordp_buf(reginput, reg_buf);
|
||||
&& vim_iswordp_buf(reginput, rex.reg_buf);
|
||||
ADD_STATE_IF_MATCH(t->state);
|
||||
break;
|
||||
|
||||
@ -5760,24 +5760,24 @@ static int nfa_regmatch(nfa_regprog_T *prog, nfa_state_T *start,
|
||||
break;
|
||||
|
||||
case NFA_LOWER_IC: // [a-z]
|
||||
result = ri_lower(curc) || (ireg_ic && ri_upper(curc));
|
||||
result = ri_lower(curc) || (rex.reg_ic && ri_upper(curc));
|
||||
ADD_STATE_IF_MATCH(t->state);
|
||||
break;
|
||||
|
||||
case NFA_NLOWER_IC: // [^a-z]
|
||||
result = curc != NUL
|
||||
&& !(ri_lower(curc) || (ireg_ic && ri_upper(curc)));
|
||||
&& !(ri_lower(curc) || (rex.reg_ic && ri_upper(curc)));
|
||||
ADD_STATE_IF_MATCH(t->state);
|
||||
break;
|
||||
|
||||
case NFA_UPPER_IC: // [A-Z]
|
||||
result = ri_upper(curc) || (ireg_ic && ri_lower(curc));
|
||||
result = ri_upper(curc) || (rex.reg_ic && ri_lower(curc));
|
||||
ADD_STATE_IF_MATCH(t->state);
|
||||
break;
|
||||
|
||||
case NFA_NUPPER_IC: // [^A-Z]
|
||||
result = curc != NUL
|
||||
&& !(ri_upper(curc) || (ireg_ic && ri_lower(curc)));
|
||||
&& !(ri_upper(curc) || (rex.reg_ic && ri_lower(curc)));
|
||||
ADD_STATE_IF_MATCH(t->state);
|
||||
break;
|
||||
|
||||
@ -5851,13 +5851,15 @@ static int nfa_regmatch(nfa_regprog_T *prog, nfa_state_T *start,
|
||||
case NFA_LNUM_GT:
|
||||
case NFA_LNUM_LT:
|
||||
assert(t->state->val >= 0
|
||||
&& !((reg_firstlnum > 0 && reglnum > LONG_MAX - reg_firstlnum)
|
||||
|| (reg_firstlnum <0 && reglnum < LONG_MIN + reg_firstlnum))
|
||||
&& reglnum + reg_firstlnum >= 0);
|
||||
&& !((rex.reg_firstlnum > 0
|
||||
&& reglnum > LONG_MAX - rex.reg_firstlnum)
|
||||
|| (rex.reg_firstlnum < 0
|
||||
&& reglnum < LONG_MIN + rex.reg_firstlnum))
|
||||
&& reglnum + rex.reg_firstlnum >= 0);
|
||||
result = (REG_MULTI
|
||||
&& nfa_re_num_cmp((uintmax_t)t->state->val,
|
||||
t->state->c - NFA_LNUM,
|
||||
(uintmax_t)(reglnum + reg_firstlnum)));
|
||||
(uintmax_t)(reglnum + rex.reg_firstlnum)));
|
||||
if (result) {
|
||||
add_here = true;
|
||||
add_state = t->state->out;
|
||||
@ -5893,7 +5895,7 @@ static int nfa_regmatch(nfa_regprog_T *prog, nfa_state_T *start,
|
||||
}
|
||||
|
||||
result = false;
|
||||
win_T *wp = reg_win == NULL ? curwin : reg_win;
|
||||
win_T *wp = rex.reg_win == NULL ? curwin : rex.reg_win;
|
||||
if (op == 1 && col - 1 > t->state->val && col > 100) {
|
||||
long ts = wp->w_buffer->b_p_ts;
|
||||
|
||||
@ -5920,18 +5922,18 @@ static int nfa_regmatch(nfa_regprog_T *prog, nfa_state_T *start,
|
||||
case NFA_MARK_GT:
|
||||
case NFA_MARK_LT:
|
||||
{
|
||||
pos_T *pos = getmark_buf(reg_buf, t->state->val, FALSE);
|
||||
pos_T *pos = getmark_buf(rex.reg_buf, t->state->val, false);
|
||||
|
||||
// Compare the mark position to the match position.
|
||||
result = (pos != NULL // mark doesn't exist
|
||||
&& pos->lnum > 0 // mark isn't set in reg_buf
|
||||
&& (pos->lnum == reglnum + reg_firstlnum
|
||||
&& (pos->lnum == reglnum + rex.reg_firstlnum
|
||||
? (pos->col == (colnr_T)(reginput - regline)
|
||||
? t->state->c == NFA_MARK
|
||||
: (pos->col < (colnr_T)(reginput - regline)
|
||||
? t->state->c == NFA_MARK_GT
|
||||
: t->state->c == NFA_MARK_LT))
|
||||
: (pos->lnum < reglnum + reg_firstlnum
|
||||
: (pos->lnum < reglnum + rex.reg_firstlnum
|
||||
? t->state->c == NFA_MARK_GT
|
||||
: t->state->c == NFA_MARK_LT)));
|
||||
if (result) {
|
||||
@ -5942,10 +5944,10 @@ static int nfa_regmatch(nfa_regprog_T *prog, nfa_state_T *start,
|
||||
}
|
||||
|
||||
case NFA_CURSOR:
|
||||
result = (reg_win != NULL
|
||||
&& (reglnum + reg_firstlnum == reg_win->w_cursor.lnum)
|
||||
result = (rex.reg_win != NULL
|
||||
&& (reglnum + rex.reg_firstlnum == rex.reg_win->w_cursor.lnum)
|
||||
&& ((colnr_T)(reginput - regline)
|
||||
== reg_win->w_cursor.col));
|
||||
== rex.reg_win->w_cursor.col));
|
||||
if (result) {
|
||||
add_here = true;
|
||||
add_state = t->state->out;
|
||||
@ -5995,13 +5997,13 @@ static int nfa_regmatch(nfa_regprog_T *prog, nfa_state_T *start,
|
||||
#endif
|
||||
result = (c == curc);
|
||||
|
||||
if (!result && ireg_ic) {
|
||||
if (!result && rex.reg_ic) {
|
||||
result = mb_tolower(c) == mb_tolower(curc);
|
||||
}
|
||||
|
||||
// If ireg_icombine is not set only skip over the character
|
||||
// If rex.reg_icombine is not set only skip over the character
|
||||
// itself. When it is set skip over composing characters.
|
||||
if (result && enc_utf8 && !ireg_icombine) {
|
||||
if (result && enc_utf8 && !rex.reg_icombine) {
|
||||
clen = utf_ptr2len(reginput);
|
||||
}
|
||||
|
||||
@ -6109,8 +6111,8 @@ static int nfa_regmatch(nfa_regprog_T *prog, nfa_state_T *start,
|
||||
&& ((toplevel
|
||||
&& reglnum == 0
|
||||
&& clen != 0
|
||||
&& (ireg_maxcol == 0
|
||||
|| (colnr_T)(reginput - regline) < ireg_maxcol))
|
||||
&& (rex.reg_maxcol == 0
|
||||
|| (colnr_T)(reginput - regline) < rex.reg_maxcol))
|
||||
|| (nfa_endp != NULL
|
||||
&& (REG_MULTI
|
||||
? (reglnum < nfa_endp->se_u.pos.lnum
|
||||
@ -6145,7 +6147,7 @@ static int nfa_regmatch(nfa_regprog_T *prog, nfa_state_T *start,
|
||||
// Checking if the required start character matches is
|
||||
// cheaper than adding a state that won't match.
|
||||
c = PTR2CHAR(reginput + clen);
|
||||
if (c != prog->regstart && (!ireg_ic || mb_tolower(c)
|
||||
if (c != prog->regstart && (!rex.reg_ic || mb_tolower(c)
|
||||
!= mb_tolower(prog->regstart))) {
|
||||
#ifdef REGEXP_DEBUG
|
||||
fprintf(log_fd,
|
||||
@ -6271,34 +6273,37 @@ static long nfa_regtry(nfa_regprog_T *prog, colnr_T col, proftime_T *tm)
|
||||
cleanup_subexpr();
|
||||
if (REG_MULTI) {
|
||||
for (i = 0; i < subs.norm.in_use; i++) {
|
||||
reg_startpos[i].lnum = subs.norm.list.multi[i].start_lnum;
|
||||
reg_startpos[i].col = subs.norm.list.multi[i].start_col;
|
||||
rex.reg_startpos[i].lnum = subs.norm.list.multi[i].start_lnum;
|
||||
rex.reg_startpos[i].col = subs.norm.list.multi[i].start_col;
|
||||
|
||||
reg_endpos[i].lnum = subs.norm.list.multi[i].end_lnum;
|
||||
reg_endpos[i].col = subs.norm.list.multi[i].end_col;
|
||||
rex.reg_endpos[i].lnum = subs.norm.list.multi[i].end_lnum;
|
||||
rex.reg_endpos[i].col = subs.norm.list.multi[i].end_col;
|
||||
}
|
||||
|
||||
if (reg_startpos[0].lnum < 0) {
|
||||
reg_startpos[0].lnum = 0;
|
||||
reg_startpos[0].col = col;
|
||||
if (rex.reg_startpos[0].lnum < 0) {
|
||||
rex.reg_startpos[0].lnum = 0;
|
||||
rex.reg_startpos[0].col = col;
|
||||
}
|
||||
if (rex.reg_endpos[0].lnum < 0) {
|
||||
// pattern has a \ze but it didn't match, use current end
|
||||
rex.reg_endpos[0].lnum = reglnum;
|
||||
rex.reg_endpos[0].col = (int)(reginput - regline);
|
||||
} else {
|
||||
// Use line number of "\ze".
|
||||
reglnum = rex.reg_endpos[0].lnum;
|
||||
}
|
||||
if (reg_endpos[0].lnum < 0) {
|
||||
/* pattern has a \ze but it didn't match, use current end */
|
||||
reg_endpos[0].lnum = reglnum;
|
||||
reg_endpos[0].col = (int)(reginput - regline);
|
||||
} else
|
||||
/* Use line number of "\ze". */
|
||||
reglnum = reg_endpos[0].lnum;
|
||||
} else {
|
||||
for (i = 0; i < subs.norm.in_use; i++) {
|
||||
reg_startp[i] = subs.norm.list.line[i].start;
|
||||
reg_endp[i] = subs.norm.list.line[i].end;
|
||||
rex.reg_startp[i] = subs.norm.list.line[i].start;
|
||||
rex.reg_endp[i] = subs.norm.list.line[i].end;
|
||||
}
|
||||
|
||||
if (reg_startp[0] == NULL)
|
||||
reg_startp[0] = regline + col;
|
||||
if (reg_endp[0] == NULL)
|
||||
reg_endp[0] = reginput;
|
||||
if (rex.reg_startp[0] == NULL) {
|
||||
rex.reg_startp[0] = regline + col;
|
||||
}
|
||||
if (rex.reg_endp[0] == NULL) {
|
||||
rex.reg_endp[0] = reginput;
|
||||
}
|
||||
}
|
||||
|
||||
/* Package any found \z(...\) matches for export. Default is none. */
|
||||
@ -6352,14 +6357,14 @@ static long nfa_regexec_both(char_u *line, colnr_T startcol, proftime_T *tm)
|
||||
colnr_T col = startcol;
|
||||
|
||||
if (REG_MULTI) {
|
||||
prog = (nfa_regprog_T *)reg_mmatch->regprog;
|
||||
line = reg_getline((linenr_T)0); /* relative to the cursor */
|
||||
reg_startpos = reg_mmatch->startpos;
|
||||
reg_endpos = reg_mmatch->endpos;
|
||||
prog = (nfa_regprog_T *)rex.reg_mmatch->regprog;
|
||||
line = reg_getline((linenr_T)0); // relative to the cursor
|
||||
rex.reg_startpos = rex.reg_mmatch->startpos;
|
||||
rex.reg_endpos = rex.reg_mmatch->endpos;
|
||||
} else {
|
||||
prog = (nfa_regprog_T *)reg_match->regprog;
|
||||
reg_startp = reg_match->startp;
|
||||
reg_endp = reg_match->endp;
|
||||
prog = (nfa_regprog_T *)rex.reg_match->regprog;
|
||||
rex.reg_startp = rex.reg_match->startp;
|
||||
rex.reg_endp = rex.reg_match->endp;
|
||||
}
|
||||
|
||||
/* Be paranoid... */
|
||||
@ -6368,15 +6373,17 @@ static long nfa_regexec_both(char_u *line, colnr_T startcol, proftime_T *tm)
|
||||
goto theend;
|
||||
}
|
||||
|
||||
/* If pattern contains "\c" or "\C": overrule value of ireg_ic */
|
||||
if (prog->regflags & RF_ICASE)
|
||||
ireg_ic = TRUE;
|
||||
else if (prog->regflags & RF_NOICASE)
|
||||
ireg_ic = FALSE;
|
||||
// If pattern contains "\c" or "\C": overrule value of rex.reg_ic
|
||||
if (prog->regflags & RF_ICASE) {
|
||||
rex.reg_ic = true;
|
||||
} else if (prog->regflags & RF_NOICASE) {
|
||||
rex.reg_ic = false;
|
||||
}
|
||||
|
||||
/* If pattern contains "\Z" overrule value of ireg_icombine */
|
||||
if (prog->regflags & RF_ICOMBINE)
|
||||
ireg_icombine = TRUE;
|
||||
// If pattern contains "\Z" overrule value of rex.reg_icombine
|
||||
if (prog->regflags & RF_ICOMBINE) {
|
||||
rex.reg_icombine = true;
|
||||
}
|
||||
|
||||
regline = line;
|
||||
reglnum = 0; /* relative to line */
|
||||
@ -6405,17 +6412,17 @@ static long nfa_regexec_both(char_u *line, colnr_T startcol, proftime_T *tm)
|
||||
if (skip_to_start(prog->regstart, &col) == FAIL)
|
||||
return 0L;
|
||||
|
||||
/* If match_text is set it contains the full text that must match.
|
||||
* Nothing else to try. Doesn't handle combining chars well. */
|
||||
if (prog->match_text != NULL
|
||||
&& !ireg_icombine
|
||||
)
|
||||
// If match_text is set it contains the full text that must match.
|
||||
// Nothing else to try. Doesn't handle combining chars well.
|
||||
if (prog->match_text != NULL && !rex.reg_icombine) {
|
||||
return find_match_text(col, prog->regstart, prog->match_text);
|
||||
}
|
||||
}
|
||||
|
||||
/* If the start column is past the maximum column: no need to try. */
|
||||
if (ireg_maxcol > 0 && col >= ireg_maxcol)
|
||||
// If the start column is past the maximum column: no need to try.
|
||||
if (rex.reg_maxcol > 0 && col >= rex.reg_maxcol) {
|
||||
goto theend;
|
||||
}
|
||||
|
||||
nstate = prog->nstate;
|
||||
for (i = 0; i < nstate; ++i) {
|
||||
@ -6567,15 +6574,15 @@ nfa_regexec_nl (
|
||||
bool line_lbr
|
||||
)
|
||||
{
|
||||
reg_match = rmp;
|
||||
reg_mmatch = NULL;
|
||||
reg_maxline = 0;
|
||||
reg_line_lbr = line_lbr;
|
||||
reg_buf = curbuf;
|
||||
reg_win = NULL;
|
||||
ireg_ic = rmp->rm_ic;
|
||||
ireg_icombine = FALSE;
|
||||
ireg_maxcol = 0;
|
||||
rex.reg_match = rmp;
|
||||
rex.reg_mmatch = NULL;
|
||||
rex.reg_maxline = 0;
|
||||
rex.reg_line_lbr = line_lbr;
|
||||
rex.reg_buf = curbuf;
|
||||
rex.reg_win = NULL;
|
||||
rex.reg_ic = rmp->rm_ic;
|
||||
rex.reg_icombine = false;
|
||||
rex.reg_maxcol = 0;
|
||||
return nfa_regexec_both(line, col, NULL);
|
||||
}
|
||||
|
||||
@ -6616,16 +6623,16 @@ nfa_regexec_nl (
|
||||
static long nfa_regexec_multi(regmmatch_T *rmp, win_T *win, buf_T *buf,
|
||||
linenr_T lnum, colnr_T col, proftime_T *tm)
|
||||
{
|
||||
reg_match = NULL;
|
||||
reg_mmatch = rmp;
|
||||
reg_buf = buf;
|
||||
reg_win = win;
|
||||
reg_firstlnum = lnum;
|
||||
reg_maxline = reg_buf->b_ml.ml_line_count - lnum;
|
||||
reg_line_lbr = FALSE;
|
||||
ireg_ic = rmp->rmm_ic;
|
||||
ireg_icombine = FALSE;
|
||||
ireg_maxcol = rmp->rmm_maxcol;
|
||||
rex.reg_match = NULL;
|
||||
rex.reg_mmatch = rmp;
|
||||
rex.reg_buf = buf;
|
||||
rex.reg_win = win;
|
||||
rex.reg_firstlnum = lnum;
|
||||
rex.reg_maxline = rex.reg_buf->b_ml.ml_line_count - lnum;
|
||||
rex.reg_line_lbr = false;
|
||||
rex.reg_ic = rmp->rmm_ic;
|
||||
rex.reg_icombine = false;
|
||||
rex.reg_maxcol = rmp->rmm_maxcol;
|
||||
|
||||
return nfa_regexec_both(NULL, col, tm);
|
||||
}
|
||||
|
@ -991,7 +991,7 @@ static void win_update(win_T *wp)
|
||||
* first. */
|
||||
if (mid_start == 0) {
|
||||
mid_end = wp->w_height;
|
||||
if (lastwin == firstwin) {
|
||||
if (ONE_WINDOW) {
|
||||
/* Clear the screen when it was not done by win_del_lines() or
|
||||
* win_ins_lines() above, "screen_cleared" is FALSE or MAYBE
|
||||
* then. */
|
||||
@ -7160,7 +7160,7 @@ static int fillchar_status(int *attr, win_T *wp)
|
||||
* window differs, or the fillchars differ, or this is not the
|
||||
* current window */
|
||||
if (*attr != 0 && ((win_hl_attr(wp, HLF_S) != win_hl_attr(wp, HLF_SNC)
|
||||
|| !is_curwin || firstwin == lastwin)
|
||||
|| !is_curwin || ONE_WINDOW)
|
||||
|| (fill_stl != fill_stlnc))) {
|
||||
return fill;
|
||||
}
|
||||
|
@ -79,7 +79,11 @@ let $NVIM_LOG_FILE = exists($NVIM_LOG_FILE) ? $NVIM_LOG_FILE : 'Xnvim.log'
|
||||
func RunTheTest(test)
|
||||
echo 'Executing ' . a:test
|
||||
if exists("*SetUp")
|
||||
call SetUp()
|
||||
try
|
||||
call SetUp()
|
||||
catch
|
||||
call add(v:errors, 'Caught exception in SetUp() before ' . a:test . ': ' . v:exception . ' @ ' . v:throwpoint)
|
||||
endtry
|
||||
endif
|
||||
|
||||
call add(s:messages, 'Executing ' . a:test)
|
||||
@ -94,7 +98,11 @@ func RunTheTest(test)
|
||||
endtry
|
||||
|
||||
if exists("*TearDown")
|
||||
call TearDown()
|
||||
try
|
||||
call TearDown()
|
||||
catch
|
||||
call add(v:errors, 'Caught exception in TearDown() after ' . a:test . ': ' . v:exception . ' @ ' . v:throwpoint)
|
||||
endtry
|
||||
endif
|
||||
|
||||
" Close any extra windows and make the current one not modified.
|
||||
|
@ -14,6 +14,7 @@ source test_float_func.vim
|
||||
source test_functions.vim
|
||||
source test_goto.vim
|
||||
source test_jumps.vim
|
||||
source test_fileformat.vim
|
||||
source test_lambda.vim
|
||||
source test_menu.vim
|
||||
source test_mapping.vim
|
||||
|
@ -87,9 +87,17 @@ function Test_get_buf_options()
|
||||
endfunc
|
||||
|
||||
function Test_get_win_options()
|
||||
if has('folding')
|
||||
set foldlevel=999
|
||||
endif
|
||||
set list
|
||||
let opts = getwinvar(1, '&')
|
||||
call assert_equal(v:t_dict, type(opts))
|
||||
call assert_equal(0, opts.linebreak)
|
||||
call assert_equal(1, opts.list)
|
||||
if has('folding')
|
||||
call assert_equal(999, opts.foldlevel)
|
||||
endif
|
||||
if has('signs')
|
||||
call assert_equal('auto', opts.signcolumn)
|
||||
endif
|
||||
@ -97,7 +105,12 @@ function Test_get_win_options()
|
||||
let opts = gettabwinvar(1, 1, '&')
|
||||
call assert_equal(v:t_dict, type(opts))
|
||||
call assert_equal(0, opts.linebreak)
|
||||
call assert_equal(1, opts.list)
|
||||
if has('signs')
|
||||
call assert_equal('auto', opts.signcolumn)
|
||||
endif
|
||||
set list&
|
||||
if has('folding')
|
||||
set foldlevel=0
|
||||
endif
|
||||
endfunc
|
||||
|
@ -130,6 +130,11 @@ func Test_getcompletion()
|
||||
let l = getcompletion('dark', 'highlight')
|
||||
call assert_equal([], l)
|
||||
|
||||
let l = getcompletion('', 'messages')
|
||||
call assert_true(index(l, 'clear') >= 0)
|
||||
let l = getcompletion('not', 'messages')
|
||||
call assert_equal([], l)
|
||||
|
||||
if has('cscope')
|
||||
let l = getcompletion('', 'cscope')
|
||||
let cmds = ['add', 'find', 'help', 'kill', 'reset', 'show']
|
||||
@ -204,3 +209,26 @@ func Test_expand_star_star()
|
||||
bwipe!
|
||||
call delete('a', 'rf')
|
||||
endfunc
|
||||
|
||||
func Test_paste_in_cmdline()
|
||||
let @a = "def"
|
||||
call feedkeys(":abc \<C-R>a ghi\<C-B>\"\<CR>", 'tx')
|
||||
call assert_equal('"abc def ghi', @:)
|
||||
|
||||
new
|
||||
call setline(1, 'asdf.x /tmp/some verylongword a;b-c*d ')
|
||||
|
||||
call feedkeys(":aaa \<C-R>\<C-W> bbb\<C-B>\"\<CR>", 'tx')
|
||||
call assert_equal('"aaa asdf bbb', @:)
|
||||
|
||||
call feedkeys("ft:aaa \<C-R>\<C-F> bbb\<C-B>\"\<CR>", 'tx')
|
||||
call assert_equal('"aaa /tmp/some bbb', @:)
|
||||
|
||||
set incsearch
|
||||
call feedkeys("fy:aaa veryl\<C-R>\<C-W> bbb\<C-B>\"\<CR>", 'tx')
|
||||
call assert_equal('"aaa verylongword bbb', @:)
|
||||
|
||||
call feedkeys("f;:aaa \<C-R>\<C-A> bbb\<C-B>\"\<CR>", 'tx')
|
||||
call assert_equal('"aaa a;b-c*d bbb', @:)
|
||||
bwipe!
|
||||
endfunc
|
||||
|
@ -384,9 +384,10 @@ func Test_substitute_expr()
|
||||
\ {-> submatch(2) . submatch(3) . submatch(1)}, ''))
|
||||
|
||||
func Recurse()
|
||||
return substitute('yyy', 'y*', {-> g:val}, '')
|
||||
return substitute('yyy', 'y\(.\)y', {-> submatch(1)}, '')
|
||||
endfunc
|
||||
call assert_equal('--', substitute('xxx', 'x*', {-> '-' . Recurse() . '-'}, ''))
|
||||
" recursive call works
|
||||
call assert_equal('-y-x-', substitute('xxx', 'x\(.\)x', {-> '-' . Recurse() . '-' . submatch(1) . '-'}, ''))
|
||||
endfunc
|
||||
|
||||
func Test_invalid_submatch()
|
||||
@ -418,6 +419,9 @@ func Test_function_with_funcref()
|
||||
let s:fref = function(s:f)
|
||||
call assert_equal(v:t_string, s:fref('x'))
|
||||
call assert_fails("call function('s:f')", 'E700:')
|
||||
|
||||
call assert_fails("call function('foo()')", 'E475:')
|
||||
call assert_fails("call function('foo()')", 'foo()')
|
||||
endfunc
|
||||
|
||||
func Test_funcref()
|
||||
|
17
src/nvim/testdir/test_fileformat.vim
Normal file
17
src/nvim/testdir/test_fileformat.vim
Normal file
@ -0,0 +1,17 @@
|
||||
" Test behavior of fileformat after bwipeout of last buffer
|
||||
|
||||
func Test_fileformat_after_bw()
|
||||
bwipeout
|
||||
set fileformat&
|
||||
if &fileformat == 'dos'
|
||||
let test_fileformats = 'unix'
|
||||
elseif &fileformat == 'unix'
|
||||
let test_fileformats = 'mac'
|
||||
else " must be mac
|
||||
let test_fileformats = 'dos'
|
||||
endif
|
||||
exec 'set fileformats='.test_fileformats
|
||||
bwipeout!
|
||||
call assert_equal(test_fileformats, &fileformat)
|
||||
set fileformats&
|
||||
endfunc
|
@ -1,22 +1,277 @@
|
||||
" Test commands that jump somewhere.
|
||||
|
||||
func Test_geeDEE()
|
||||
" Create a new buffer using "lines" and place the cursor on the word after the
|
||||
" first occurrence of return and invoke "cmd". The cursor should now be
|
||||
" positioned at the given line and col.
|
||||
func XTest_goto_decl(cmd, lines, line, col)
|
||||
new
|
||||
call setline(1, ["Filename x;", "", "int Filename", "int func() {", "Filename y;"])
|
||||
/y;/
|
||||
normal gD
|
||||
call assert_equal(1, line('.'))
|
||||
call setline(1, a:lines)
|
||||
/return/
|
||||
normal! W
|
||||
execute 'norm! ' . a:cmd
|
||||
call assert_equal(a:line, line('.'))
|
||||
call assert_equal(a:col, col('.'))
|
||||
quit!
|
||||
endfunc
|
||||
|
||||
func Test_gee_dee()
|
||||
new
|
||||
call setline(1, ["int x;", "", "int func(int x)", "{", " return x;", "}"])
|
||||
/return/
|
||||
normal $hgd
|
||||
call assert_equal(3, line('.'))
|
||||
call assert_equal(14, col('.'))
|
||||
quit!
|
||||
func Test_gD()
|
||||
let lines = [
|
||||
\ 'int x;',
|
||||
\ '',
|
||||
\ 'int func(void)',
|
||||
\ '{',
|
||||
\ ' return x;',
|
||||
\ '}',
|
||||
\ ]
|
||||
call XTest_goto_decl('gD', lines, 1, 5)
|
||||
endfunc
|
||||
|
||||
func Test_gD_too()
|
||||
let lines = [
|
||||
\ 'Filename x;',
|
||||
\ '',
|
||||
\ 'int Filename',
|
||||
\ 'int func() {',
|
||||
\ ' Filename x;',
|
||||
\ ' return x;',
|
||||
\ ]
|
||||
call XTest_goto_decl('gD', lines, 1, 10)
|
||||
endfunc
|
||||
|
||||
func Test_gD_comment()
|
||||
let lines = [
|
||||
\ '/* int x; */',
|
||||
\ 'int x;',
|
||||
\ '',
|
||||
\ 'int func(void)',
|
||||
\ '{',
|
||||
\ ' return x;',
|
||||
\ '}',
|
||||
\ ]
|
||||
call XTest_goto_decl('gD', lines, 2, 5)
|
||||
endfunc
|
||||
|
||||
func Test_gD_inline_comment()
|
||||
let lines = [
|
||||
\ 'int y /* , x */;',
|
||||
\ 'int x;',
|
||||
\ '',
|
||||
\ 'int func(void)',
|
||||
\ '{',
|
||||
\ ' return x;',
|
||||
\ '}',
|
||||
\ ]
|
||||
call XTest_goto_decl('gD', lines, 2, 5)
|
||||
endfunc
|
||||
|
||||
func Test_gD_string()
|
||||
let lines = [
|
||||
\ 'char *s[] = "x";',
|
||||
\ 'int x = 1;',
|
||||
\ '',
|
||||
\ 'int func(void)',
|
||||
\ '{',
|
||||
\ ' return x;',
|
||||
\ '}',
|
||||
\ ]
|
||||
call XTest_goto_decl('gD', lines, 2, 5)
|
||||
endfunc
|
||||
|
||||
func Test_gD_string_same_line()
|
||||
let lines = [
|
||||
\ 'char *s[] = "x", int x = 1;',
|
||||
\ '',
|
||||
\ 'int func(void)',
|
||||
\ '{',
|
||||
\ ' return x;',
|
||||
\ '}',
|
||||
\ ]
|
||||
call XTest_goto_decl('gD', lines, 1, 22)
|
||||
endfunc
|
||||
|
||||
func Test_gD_char()
|
||||
let lines = [
|
||||
\ "char c = 'x';",
|
||||
\ 'int x = 1;',
|
||||
\ '',
|
||||
\ 'int func(void)',
|
||||
\ '{',
|
||||
\ ' return x;',
|
||||
\ '}',
|
||||
\ ]
|
||||
call XTest_goto_decl('gD', lines, 2, 5)
|
||||
endfunc
|
||||
|
||||
func Test_gd()
|
||||
let lines = [
|
||||
\ 'int x;',
|
||||
\ '',
|
||||
\ 'int func(int x)',
|
||||
\ '{',
|
||||
\ ' return x;',
|
||||
\ '}',
|
||||
\ ]
|
||||
call XTest_goto_decl('gd', lines, 3, 14)
|
||||
endfunc
|
||||
|
||||
func Test_gd_not_local()
|
||||
let lines = [
|
||||
\ 'int func1(void)',
|
||||
\ '{',
|
||||
\ ' return x;',
|
||||
\ '}',
|
||||
\ '',
|
||||
\ 'int func2(int x)',
|
||||
\ '{',
|
||||
\ ' return x;',
|
||||
\ '}',
|
||||
\ ]
|
||||
call XTest_goto_decl('gd', lines, 3, 10)
|
||||
endfunc
|
||||
|
||||
func Test_gd_kr_style()
|
||||
let lines = [
|
||||
\ 'int func(x)',
|
||||
\ ' int x;',
|
||||
\ '{',
|
||||
\ ' return x;',
|
||||
\ '}',
|
||||
\ ]
|
||||
call XTest_goto_decl('gd', lines, 2, 7)
|
||||
endfunc
|
||||
|
||||
func Test_gd_missing_braces()
|
||||
let lines = [
|
||||
\ 'def func1(a)',
|
||||
\ ' a + 1',
|
||||
\ 'end',
|
||||
\ '',
|
||||
\ 'a = 1',
|
||||
\ '',
|
||||
\ 'def func2()',
|
||||
\ ' return a',
|
||||
\ 'end',
|
||||
\ ]
|
||||
call XTest_goto_decl('gd', lines, 1, 11)
|
||||
endfunc
|
||||
|
||||
func Test_gd_comment()
|
||||
let lines = [
|
||||
\ 'int func(void)',
|
||||
\ '{',
|
||||
\ ' /* int x; */',
|
||||
\ ' int x;',
|
||||
\ ' return x;',
|
||||
\ '}',
|
||||
\]
|
||||
call XTest_goto_decl('gd', lines, 4, 7)
|
||||
endfunc
|
||||
|
||||
func Test_gd_comment_in_string()
|
||||
let lines = [
|
||||
\ 'int func(void)',
|
||||
\ '{',
|
||||
\ ' char *s ="//"; int x;',
|
||||
\ ' int x;',
|
||||
\ ' return x;',
|
||||
\ '}',
|
||||
\]
|
||||
call XTest_goto_decl('gd', lines, 3, 22)
|
||||
endfunc
|
||||
|
||||
func Test_gd_string_in_comment()
|
||||
set comments=
|
||||
let lines = [
|
||||
\ 'int func(void)',
|
||||
\ '{',
|
||||
\ ' /* " */ int x;',
|
||||
\ ' int x;',
|
||||
\ ' return x;',
|
||||
\ '}',
|
||||
\]
|
||||
call XTest_goto_decl('gd', lines, 3, 15)
|
||||
set comments&
|
||||
endfunc
|
||||
|
||||
func Test_gd_inline_comment()
|
||||
let lines = [
|
||||
\ 'int func(/* x is an int */ int x)',
|
||||
\ '{',
|
||||
\ ' return x;',
|
||||
\ '}',
|
||||
\ ]
|
||||
call XTest_goto_decl('gd', lines, 1, 32)
|
||||
endfunc
|
||||
|
||||
func Test_gd_inline_comment_only()
|
||||
let lines = [
|
||||
\ 'int func(void) /* one lonely x */',
|
||||
\ '{',
|
||||
\ ' return x;',
|
||||
\ '}',
|
||||
\ ]
|
||||
call XTest_goto_decl('gd', lines, 3, 10)
|
||||
endfunc
|
||||
|
||||
func Test_gd_inline_comment_body()
|
||||
let lines = [
|
||||
\ 'int func(void)',
|
||||
\ '{',
|
||||
\ ' int y /* , x */;',
|
||||
\ '',
|
||||
\ ' for (/* int x = 0 */; y < 2; y++);',
|
||||
\ '',
|
||||
\ ' int x = 0;',
|
||||
\ '',
|
||||
\ ' return x;',
|
||||
\ '}',
|
||||
\ ]
|
||||
call XTest_goto_decl('gd', lines, 7, 7)
|
||||
endfunc
|
||||
|
||||
func Test_gd_trailing_multiline_comment()
|
||||
let lines = [
|
||||
\ 'int func(int x) /* x is an int */',
|
||||
\ '{',
|
||||
\ ' return x;',
|
||||
\ '}',
|
||||
\ ]
|
||||
call XTest_goto_decl('gd', lines, 1, 14)
|
||||
endfunc
|
||||
|
||||
func Test_gd_trailing_comment()
|
||||
let lines = [
|
||||
\ 'int func(int x) // x is an int',
|
||||
\ '{',
|
||||
\ ' return x;',
|
||||
\ '}',
|
||||
\ ]
|
||||
call XTest_goto_decl('gd', lines, 1, 14)
|
||||
endfunc
|
||||
|
||||
func Test_gd_string()
|
||||
let lines = [
|
||||
\ 'int func(void)',
|
||||
\ '{',
|
||||
\ ' char *s = "x";',
|
||||
\ ' int x = 1;',
|
||||
\ '',
|
||||
\ ' return x;',
|
||||
\ '}',
|
||||
\ ]
|
||||
call XTest_goto_decl('gd', lines, 4, 7)
|
||||
endfunc
|
||||
|
||||
func Test_gd_string_only()
|
||||
let lines = [
|
||||
\ 'int func(void)',
|
||||
\ '{',
|
||||
\ ' char *s = "x";',
|
||||
\ '',
|
||||
\ ' return x;',
|
||||
\ '}',
|
||||
\ ]
|
||||
call XTest_goto_decl('gd', lines, 5, 10)
|
||||
endfunc
|
||||
|
||||
" Check that setting 'cursorline' does not change curswant
|
||||
|
@ -277,6 +277,7 @@ function! Test_matchadd_and_syn_conceal()
|
||||
call assert_notequal(screenattr(1, 11) , screenattr(1, 12))
|
||||
call assert_equal(screenattr(1, 11) , screenattr(1, 32))
|
||||
call matchadd('CheckedByCoq', '\%<2l\%>9c\%<16c')
|
||||
redraw!
|
||||
call assert_equal(expect, s:screenline(1))
|
||||
call assert_notequal(screenattr(1, 10) , screenattr(1, 11))
|
||||
call assert_notequal(screenattr(1, 11) , screenattr(1, 12))
|
||||
|
@ -1,32 +1,42 @@
|
||||
"Tests for nested functions
|
||||
"
|
||||
function! NestedFunc()
|
||||
fu! Func1()
|
||||
func NestedFunc()
|
||||
func! Func1()
|
||||
let g:text .= 'Func1 '
|
||||
endfunction
|
||||
endfunc
|
||||
call Func1()
|
||||
fu! s:func2()
|
||||
func! s:func2()
|
||||
let g:text .= 's:func2 '
|
||||
endfunction
|
||||
endfunc
|
||||
call s:func2()
|
||||
fu! s:_func3()
|
||||
func! s:_func3()
|
||||
let g:text .= 's:_func3 '
|
||||
endfunction
|
||||
endfunc
|
||||
call s:_func3()
|
||||
let fn = 'Func4'
|
||||
fu! {fn}()
|
||||
func! {fn}()
|
||||
let g:text .= 'Func4 '
|
||||
endfunction
|
||||
endfunc
|
||||
call {fn}()
|
||||
let fn = 'func5'
|
||||
fu! s:{fn}()
|
||||
func! s:{fn}()
|
||||
let g:text .= 's:func5'
|
||||
endfunction
|
||||
endfunc
|
||||
call s:{fn}()
|
||||
endfunction
|
||||
endfunc
|
||||
|
||||
function! Test_nested_functions()
|
||||
func Test_nested_functions()
|
||||
let g:text = ''
|
||||
call NestedFunc()
|
||||
call assert_equal('Func1 s:func2 s:_func3 Func4 s:func5', g:text)
|
||||
endfunction
|
||||
|
||||
func Test_nested_argument()
|
||||
func g:X()
|
||||
let g:Y = function('sort')
|
||||
endfunc
|
||||
let g:Y = function('sort')
|
||||
echo g:Y([], g:X())
|
||||
delfunc g:X
|
||||
unlet g:Y
|
||||
endfunc
|
||||
|
@ -1255,21 +1255,27 @@ func! Test_normal22_zet()
|
||||
" Test for ZZ
|
||||
" let shell = &shell
|
||||
" let &shell = 'sh'
|
||||
call writefile(['1', '2'], 'Xfile')
|
||||
let args = ' --headless -u NONE -N -U NONE -i NONE --noplugins'
|
||||
call system(v:progpath . args . ' -c "%d" -c ":norm! ZZ" Xfile')
|
||||
let a = readfile('Xfile')
|
||||
call assert_equal([], a)
|
||||
" Test for ZQ
|
||||
call writefile(['1', '2'], 'Xfile')
|
||||
call system(v:progpath . args . ' -c "%d" -c ":norm! ZQ" Xfile')
|
||||
let a = readfile('Xfile')
|
||||
call assert_equal(['1', '2'], a)
|
||||
|
||||
" clean up
|
||||
for file in ['Xfile']
|
||||
" Remove any stale test files from previous run.
|
||||
for file in ['Xfile_Test_normal22_zet']
|
||||
call delete(file)
|
||||
endfor
|
||||
|
||||
call writefile(['1', '2'], 'Xfile_Test_normal22_zet')
|
||||
let args = ' --headless -u NONE -N -U NONE -i NONE --noplugins'
|
||||
call system(v:progpath . args . ' -c "%d" -c ":norm! ZZ" Xfile_Test_normal22_zet')
|
||||
let a = readfile('Xfile_Test_normal22_zet')
|
||||
call assert_equal([], a)
|
||||
" Test for ZQ
|
||||
call writefile(['1', '2'], 'Xfile_Test_normal22_zet')
|
||||
call system(v:progpath . args . ' -c "%d" -c ":norm! ZQ" Xfile_Test_normal22_zet')
|
||||
let a = readfile('Xfile_Test_normal22_zet')
|
||||
call assert_equal(['1', '2'], a)
|
||||
|
||||
" Nvim: This sometimes hangs the TSAN build.
|
||||
" for file in ['Xfile_Test_normal22_zet']
|
||||
" call delete(file)
|
||||
" endfor
|
||||
" let &shell = shell
|
||||
endfunc
|
||||
|
||||
|
@ -6,7 +6,7 @@ endif
|
||||
|
||||
set encoding=utf-8
|
||||
|
||||
function! s:setup_commands(cchar)
|
||||
func s:setup_commands(cchar)
|
||||
if a:cchar == 'c'
|
||||
command! -nargs=* -bang Xlist <mods>clist<bang> <args>
|
||||
command! -nargs=* Xgetexpr <mods>cgetexpr <args>
|
||||
@ -68,10 +68,10 @@ function! s:setup_commands(cchar)
|
||||
let g:Xgetlist = function('getloclist', [0])
|
||||
let g:Xsetlist = function('setloclist', [0])
|
||||
endif
|
||||
endfunction
|
||||
endfunc
|
||||
|
||||
" Tests for the :clist and :llist commands
|
||||
function XlistTests(cchar)
|
||||
func XlistTests(cchar)
|
||||
call s:setup_commands(a:cchar)
|
||||
|
||||
" With an empty list, command should return error
|
||||
@ -128,17 +128,17 @@ function XlistTests(cchar)
|
||||
let l = split(result, "\n")
|
||||
call assert_equal([' 2 Xtestfile1:1 col 3: Line1',
|
||||
\ ' 3: non-error 2', ' 4 Xtestfile2:2 col 2: Line2'], l)
|
||||
endfunction
|
||||
endfunc
|
||||
|
||||
function Test_clist()
|
||||
func Test_clist()
|
||||
call XlistTests('c')
|
||||
call XlistTests('l')
|
||||
endfunction
|
||||
endfunc
|
||||
|
||||
" Tests for the :colder, :cnewer, :lolder and :lnewer commands
|
||||
" Note that this test assumes that a quickfix/location list is
|
||||
" already set by the caller.
|
||||
function XageTests(cchar)
|
||||
func XageTests(cchar)
|
||||
call s:setup_commands(a:cchar)
|
||||
|
||||
" Jumping to a non existent list should return error
|
||||
@ -171,20 +171,20 @@ function XageTests(cchar)
|
||||
Xnewer 2
|
||||
let l = g:Xgetlist()
|
||||
call assert_equal('Line3', l[0].text)
|
||||
endfunction
|
||||
endfunc
|
||||
|
||||
function Test_cage()
|
||||
func Test_cage()
|
||||
let list = [{'bufnr': 1, 'lnum': 1}]
|
||||
call setqflist(list)
|
||||
call XageTests('c')
|
||||
|
||||
call setloclist(0, list)
|
||||
call XageTests('l')
|
||||
endfunction
|
||||
endfunc
|
||||
|
||||
" Tests for the :cwindow, :lwindow :cclose, :lclose, :copen and :lopen
|
||||
" commands
|
||||
function XwindowTests(cchar)
|
||||
func XwindowTests(cchar)
|
||||
call s:setup_commands(a:cchar)
|
||||
|
||||
" Create a list with no valid entries
|
||||
@ -227,16 +227,16 @@ function XwindowTests(cchar)
|
||||
" Calling cwindow should close the quickfix window with no valid errors
|
||||
Xwindow
|
||||
call assert_true(winnr('$') == 1)
|
||||
endfunction
|
||||
endfunc
|
||||
|
||||
function Test_cwindow()
|
||||
func Test_cwindow()
|
||||
call XwindowTests('c')
|
||||
call XwindowTests('l')
|
||||
endfunction
|
||||
endfunc
|
||||
|
||||
" Tests for the :cfile, :lfile, :caddfile, :laddfile, :cgetfile and :lgetfile
|
||||
" commands.
|
||||
function XfileTests(cchar)
|
||||
func XfileTests(cchar)
|
||||
call s:setup_commands(a:cchar)
|
||||
|
||||
call writefile(['Xtestfile1:700:10:Line 700',
|
||||
@ -275,16 +275,16 @@ function XfileTests(cchar)
|
||||
\ l[1].lnum == 333 && l[1].col == 88 && l[1].text ==# 'Line 333')
|
||||
|
||||
call delete('Xqftestfile1')
|
||||
endfunction
|
||||
endfunc
|
||||
|
||||
function Test_cfile()
|
||||
func Test_cfile()
|
||||
call XfileTests('c')
|
||||
call XfileTests('l')
|
||||
endfunction
|
||||
endfunc
|
||||
|
||||
" Tests for the :cbuffer, :lbuffer, :caddbuffer, :laddbuffer, :cgetbuffer and
|
||||
" :lgetbuffer commands.
|
||||
function XbufferTests(cchar)
|
||||
func XbufferTests(cchar)
|
||||
call s:setup_commands(a:cchar)
|
||||
|
||||
enew!
|
||||
@ -316,26 +316,26 @@ function XbufferTests(cchar)
|
||||
\ l[3].lnum == 750 && l[3].col == 25 && l[3].text ==# 'Line 750')
|
||||
enew!
|
||||
|
||||
endfunction
|
||||
endfunc
|
||||
|
||||
function Test_cbuffer()
|
||||
func Test_cbuffer()
|
||||
call XbufferTests('c')
|
||||
call XbufferTests('l')
|
||||
endfunction
|
||||
endfunc
|
||||
|
||||
function XexprTests(cchar)
|
||||
func XexprTests(cchar)
|
||||
call s:setup_commands(a:cchar)
|
||||
|
||||
call assert_fails('Xexpr 10', 'E777:')
|
||||
endfunction
|
||||
endfunc
|
||||
|
||||
function Test_cexpr()
|
||||
func Test_cexpr()
|
||||
call XexprTests('c')
|
||||
call XexprTests('l')
|
||||
endfunction
|
||||
endfunc
|
||||
|
||||
" Tests for :cnext, :cprev, :cfirst, :clast commands
|
||||
function Xtest_browse(cchar)
|
||||
func Xtest_browse(cchar)
|
||||
call s:setup_commands(a:cchar)
|
||||
|
||||
call s:create_test_file('Xqftestfile1')
|
||||
@ -366,14 +366,14 @@ function Xtest_browse(cchar)
|
||||
|
||||
call delete('Xqftestfile1')
|
||||
call delete('Xqftestfile2')
|
||||
endfunction
|
||||
endfunc
|
||||
|
||||
function Test_browse()
|
||||
func Test_browse()
|
||||
call Xtest_browse('c')
|
||||
call Xtest_browse('l')
|
||||
endfunction
|
||||
endfunc
|
||||
|
||||
function! s:test_xhelpgrep(cchar)
|
||||
func s:test_xhelpgrep(cchar)
|
||||
call s:setup_commands(a:cchar)
|
||||
Xhelpgrep quickfix
|
||||
Xopen
|
||||
@ -385,9 +385,9 @@ function! s:test_xhelpgrep(cchar)
|
||||
call assert_true(w:quickfix_title =~ title_text, w:quickfix_title)
|
||||
" This wipes out the buffer, make sure that doesn't cause trouble.
|
||||
Xclose
|
||||
endfunction
|
||||
endfunc
|
||||
|
||||
function Test_helpgrep()
|
||||
func Test_helpgrep()
|
||||
call s:test_xhelpgrep('c')
|
||||
helpclose
|
||||
call s:test_xhelpgrep('l')
|
||||
@ -425,7 +425,7 @@ func Test_vimgreptitle()
|
||||
augroup! QfBufWinEnter
|
||||
endfunc
|
||||
|
||||
function XqfTitleTests(cchar)
|
||||
func XqfTitleTests(cchar)
|
||||
call s:setup_commands(a:cchar)
|
||||
|
||||
Xgetexpr ['file:1:1:message']
|
||||
@ -444,16 +444,16 @@ function XqfTitleTests(cchar)
|
||||
endif
|
||||
call assert_equal(title, w:quickfix_title)
|
||||
Xclose
|
||||
endfunction
|
||||
endfunc
|
||||
|
||||
" Tests for quickfix window's title
|
||||
function Test_qf_title()
|
||||
func Test_qf_title()
|
||||
call XqfTitleTests('c')
|
||||
call XqfTitleTests('l')
|
||||
endfunction
|
||||
endfunc
|
||||
|
||||
" Tests for 'errorformat'
|
||||
function Test_efm()
|
||||
func Test_efm()
|
||||
let save_efm = &efm
|
||||
set efm=%EEEE%m,%WWWW%m,%+CCCC%.%#,%-GGGG%.%#
|
||||
cgetexpr ['WWWW', 'EEEE', 'CCCC']
|
||||
@ -466,7 +466,7 @@ function Test_efm()
|
||||
let l = strtrans(string(map(getqflist(), '[v:val.text, v:val.valid]')))
|
||||
call assert_equal("[['W', 1], ['ZZZZ', 0], ['E^@CCCC', 1], ['YYYY', 0]]", l)
|
||||
let &efm = save_efm
|
||||
endfunction
|
||||
endfunc
|
||||
|
||||
" This will test for problems in quickfix:
|
||||
" A. incorrectly copying location lists which caused the location list to show
|
||||
@ -477,7 +477,7 @@ endfunction
|
||||
" window it belongs to.
|
||||
"
|
||||
" Set up the test environment:
|
||||
function! ReadTestProtocol(name)
|
||||
func ReadTestProtocol(name)
|
||||
let base = substitute(a:name, '\v^test://(.*)%(\.[^.]+)?', '\1', '')
|
||||
let word = substitute(base, '\v(.*)\..*', '\1', '')
|
||||
|
||||
@ -496,9 +496,9 @@ function! ReadTestProtocol(name)
|
||||
setl nomodifiable
|
||||
setl readonly
|
||||
exe 'doautocmd BufRead ' . substitute(a:name, '\v^test://(.*)', '\1', '')
|
||||
endfunction
|
||||
endfunc
|
||||
|
||||
function Test_locationlist()
|
||||
func Test_locationlist()
|
||||
enew
|
||||
|
||||
augroup testgroup
|
||||
@ -578,15 +578,15 @@ function Test_locationlist()
|
||||
wincmd n | only
|
||||
|
||||
augroup! testgroup
|
||||
endfunction
|
||||
endfunc
|
||||
|
||||
function Test_locationlist_curwin_was_closed()
|
||||
func Test_locationlist_curwin_was_closed()
|
||||
augroup testgroup
|
||||
au!
|
||||
autocmd BufReadCmd test_curwin.txt call R(expand("<amatch>"))
|
||||
augroup END
|
||||
|
||||
function! R(n)
|
||||
func! R(n)
|
||||
quit
|
||||
endfunc
|
||||
|
||||
@ -597,9 +597,9 @@ function Test_locationlist_curwin_was_closed()
|
||||
call assert_fails('lrewind', 'E924:')
|
||||
|
||||
augroup! testgroup
|
||||
endfunction
|
||||
endfunc
|
||||
|
||||
function Test_locationlist_cross_tab_jump()
|
||||
func Test_locationlist_cross_tab_jump()
|
||||
call writefile(['loclistfoo'], 'loclistfoo')
|
||||
call writefile(['loclistbar'], 'loclistbar')
|
||||
set switchbuf=usetab
|
||||
@ -613,10 +613,10 @@ function Test_locationlist_cross_tab_jump()
|
||||
set switchbuf&vim
|
||||
call delete('loclistfoo')
|
||||
call delete('loclistbar')
|
||||
endfunction
|
||||
endfunc
|
||||
|
||||
" More tests for 'errorformat'
|
||||
function! Test_efm1()
|
||||
func Test_efm1()
|
||||
if !has('unix')
|
||||
" The 'errorformat' setting is different on non-Unix systems.
|
||||
" This test works only on Unix-like systems.
|
||||
@ -734,10 +734,10 @@ function! Test_efm1()
|
||||
call delete('Xerrorfile1')
|
||||
call delete('Xerrorfile2')
|
||||
call delete('Xtestfile')
|
||||
endfunction
|
||||
endfunc
|
||||
|
||||
" Test for quickfix directory stack support
|
||||
function! s:dir_stack_tests(cchar)
|
||||
func s:dir_stack_tests(cchar)
|
||||
call s:setup_commands(a:cchar)
|
||||
|
||||
let save_efm=&efm
|
||||
@ -779,10 +779,10 @@ function! s:dir_stack_tests(cchar)
|
||||
call assert_equal(5, qf[11].lnum)
|
||||
|
||||
let &efm=save_efm
|
||||
endfunction
|
||||
endfunc
|
||||
|
||||
" Tests for %D and %X errorformat options
|
||||
function! Test_efm_dirstack()
|
||||
func Test_efm_dirstack()
|
||||
" Create the directory stack and files
|
||||
call mkdir('dir1')
|
||||
call mkdir('dir1/a')
|
||||
@ -814,10 +814,33 @@ function! Test_efm_dirstack()
|
||||
call delete('dir1', 'rf')
|
||||
call delete('dir2', 'rf')
|
||||
call delete('habits1.txt')
|
||||
endfunction
|
||||
endfunc
|
||||
|
||||
" Test for resync after continuing an ignored message
|
||||
func Xefm_ignore_continuations(cchar)
|
||||
call s:setup_commands(a:cchar)
|
||||
|
||||
let save_efm = &efm
|
||||
|
||||
let &efm =
|
||||
\ '%Eerror %m %l,' .
|
||||
\ '%-Wignored %m %l,' .
|
||||
\ '%+Cmore ignored %m %l,' .
|
||||
\ '%Zignored end'
|
||||
Xgetexpr ['ignored warning 1', 'more ignored continuation 2', 'ignored end', 'error resync 4']
|
||||
let l = map(g:Xgetlist(), '[v:val.text, v:val.valid, v:val.lnum, v:val.type]')
|
||||
call assert_equal([['resync', 1, 4, 'E']], l)
|
||||
|
||||
let &efm = save_efm
|
||||
endfunc
|
||||
|
||||
func Test_efm_ignore_continuations()
|
||||
call Xefm_ignore_continuations('c')
|
||||
call Xefm_ignore_continuations('l')
|
||||
endfunc
|
||||
|
||||
" Tests for invalid error format specifies
|
||||
function Xinvalid_efm_Tests(cchar)
|
||||
func Xinvalid_efm_Tests(cchar)
|
||||
call s:setup_commands(a:cchar)
|
||||
|
||||
let save_efm = &efm
|
||||
@ -850,17 +873,17 @@ function Xinvalid_efm_Tests(cchar)
|
||||
call assert_fails('Xexpr ["Entering dir abc", "abc.txt:1:Hello world"]', 'E379:')
|
||||
|
||||
let &efm = save_efm
|
||||
endfunction
|
||||
endfunc
|
||||
|
||||
function Test_invalid_efm()
|
||||
func Test_invalid_efm()
|
||||
call Xinvalid_efm_Tests('c')
|
||||
call Xinvalid_efm_Tests('l')
|
||||
endfunction
|
||||
endfunc
|
||||
|
||||
" TODO:
|
||||
" Add tests for the following formats in 'errorformat'
|
||||
" %r %O
|
||||
function! Test_efm2()
|
||||
func Test_efm2()
|
||||
let save_efm = &efm
|
||||
|
||||
" Test for %s format in efm
|
||||
@ -946,19 +969,19 @@ function! Test_efm2()
|
||||
call assert_equal('unittests/dbfacadeTest.py', bufname(l[4].bufnr))
|
||||
|
||||
let &efm = save_efm
|
||||
endfunction
|
||||
endfunc
|
||||
|
||||
function XquickfixChangedByAutocmd(cchar)
|
||||
func XquickfixChangedByAutocmd(cchar)
|
||||
call s:setup_commands(a:cchar)
|
||||
if a:cchar == 'c'
|
||||
let ErrorNr = 'E925'
|
||||
function! ReadFunc()
|
||||
func! ReadFunc()
|
||||
colder
|
||||
cgetexpr []
|
||||
endfunc
|
||||
else
|
||||
let ErrorNr = 'E926'
|
||||
function! ReadFunc()
|
||||
func! ReadFunc()
|
||||
lolder
|
||||
lgetexpr []
|
||||
endfunc
|
||||
@ -981,10 +1004,10 @@ function XquickfixChangedByAutocmd(cchar)
|
||||
augroup! testgroup
|
||||
endfunc
|
||||
|
||||
function Test_quickfix_was_changed_by_autocmd()
|
||||
func Test_quickfix_was_changed_by_autocmd()
|
||||
call XquickfixChangedByAutocmd('c')
|
||||
call XquickfixChangedByAutocmd('l')
|
||||
endfunction
|
||||
endfunc
|
||||
|
||||
func Test_caddbuffer_to_empty()
|
||||
helpgr quickfix
|
||||
@ -1006,7 +1029,7 @@ func Test_cgetexpr_works()
|
||||
endfunc
|
||||
|
||||
" Tests for the setqflist() and setloclist() functions
|
||||
function SetXlistTests(cchar, bnum)
|
||||
func SetXlistTests(cchar, bnum)
|
||||
call s:setup_commands(a:cchar)
|
||||
|
||||
call g:Xsetlist([{'bufnr': a:bnum, 'lnum': 1},
|
||||
@ -1041,9 +1064,9 @@ function SetXlistTests(cchar, bnum)
|
||||
call g:Xsetlist([])
|
||||
let l = g:Xgetlist()
|
||||
call assert_equal(0, len(l))
|
||||
endfunction
|
||||
endfunc
|
||||
|
||||
function Test_setqflist()
|
||||
func Test_setqflist()
|
||||
new Xtestfile | only
|
||||
let bnum = bufnr('%')
|
||||
call setline(1, range(1,5))
|
||||
@ -1053,9 +1076,9 @@ function Test_setqflist()
|
||||
|
||||
enew!
|
||||
call delete('Xtestfile')
|
||||
endfunction
|
||||
endfunc
|
||||
|
||||
function Xlist_empty_middle(cchar)
|
||||
func Xlist_empty_middle(cchar)
|
||||
call s:setup_commands(a:cchar)
|
||||
|
||||
" create three quickfix lists
|
||||
@ -1078,12 +1101,12 @@ function Xlist_empty_middle(cchar)
|
||||
call assert_equal(matchlen, len(g:Xgetlist()))
|
||||
endfunc
|
||||
|
||||
function Test_setqflist_empty_middle()
|
||||
func Test_setqflist_empty_middle()
|
||||
call Xlist_empty_middle('c')
|
||||
call Xlist_empty_middle('l')
|
||||
endfunction
|
||||
endfunc
|
||||
|
||||
function Xlist_empty_older(cchar)
|
||||
func Xlist_empty_older(cchar)
|
||||
call s:setup_commands(a:cchar)
|
||||
|
||||
" create three quickfix lists
|
||||
@ -1104,14 +1127,14 @@ function Xlist_empty_older(cchar)
|
||||
call assert_equal(twolen, len(g:Xgetlist()))
|
||||
Xnewer
|
||||
call assert_equal(threelen, len(g:Xgetlist()))
|
||||
endfunction
|
||||
endfunc
|
||||
|
||||
function Test_setqflist_empty_older()
|
||||
func Test_setqflist_empty_older()
|
||||
call Xlist_empty_older('c')
|
||||
call Xlist_empty_older('l')
|
||||
endfunction
|
||||
endfunc
|
||||
|
||||
function! XquickfixSetListWithAct(cchar)
|
||||
func XquickfixSetListWithAct(cchar)
|
||||
call s:setup_commands(a:cchar)
|
||||
|
||||
let list1 = [{'filename': 'fnameA', 'text': 'A'},
|
||||
@ -1185,12 +1208,12 @@ function! XquickfixSetListWithAct(cchar)
|
||||
call assert_fails("call g:Xsetlist(list1, 0)", 'E928:')
|
||||
endfunc
|
||||
|
||||
function Test_quickfix_set_list_with_act()
|
||||
func Test_quickfix_set_list_with_act()
|
||||
call XquickfixSetListWithAct('c')
|
||||
call XquickfixSetListWithAct('l')
|
||||
endfunction
|
||||
endfunc
|
||||
|
||||
function XLongLinesTests(cchar)
|
||||
func XLongLinesTests(cchar)
|
||||
let l = g:Xgetlist()
|
||||
|
||||
call assert_equal(4, len(l))
|
||||
@ -1208,9 +1231,9 @@ function XLongLinesTests(cchar)
|
||||
call assert_equal(10, len(l[3].text))
|
||||
|
||||
call g:Xsetlist([], 'r')
|
||||
endfunction
|
||||
endfunc
|
||||
|
||||
function s:long_lines_tests(cchar)
|
||||
func s:long_lines_tests(cchar)
|
||||
call s:setup_commands(a:cchar)
|
||||
|
||||
let testfile = 'samples/quickfix.txt'
|
||||
@ -1231,22 +1254,22 @@ function s:long_lines_tests(cchar)
|
||||
exe 'edit' testfile
|
||||
exe 'Xbuffer' bufnr('%')
|
||||
call XLongLinesTests(a:cchar)
|
||||
endfunction
|
||||
endfunc
|
||||
|
||||
function Test_long_lines()
|
||||
func Test_long_lines()
|
||||
call s:long_lines_tests('c')
|
||||
call s:long_lines_tests('l')
|
||||
endfunction
|
||||
endfunc
|
||||
|
||||
function! s:create_test_file(filename)
|
||||
func s:create_test_file(filename)
|
||||
let l = []
|
||||
for i in range(1, 20)
|
||||
call add(l, 'Line' . i)
|
||||
endfor
|
||||
call writefile(l, a:filename)
|
||||
endfunction
|
||||
endfunc
|
||||
|
||||
function! Test_switchbuf()
|
||||
func Test_switchbuf()
|
||||
call s:create_test_file('Xqftestfile1')
|
||||
call s:create_test_file('Xqftestfile2')
|
||||
call s:create_test_file('Xqftestfile3')
|
||||
@ -1333,9 +1356,9 @@ function! Test_switchbuf()
|
||||
call delete('Xqftestfile1')
|
||||
call delete('Xqftestfile2')
|
||||
call delete('Xqftestfile3')
|
||||
endfunction
|
||||
endfunc
|
||||
|
||||
function! Xadjust_qflnum(cchar)
|
||||
func Xadjust_qflnum(cchar)
|
||||
call s:setup_commands(a:cchar)
|
||||
|
||||
enew | only
|
||||
@ -1360,17 +1383,17 @@ function! Xadjust_qflnum(cchar)
|
||||
|
||||
enew!
|
||||
call delete(fname)
|
||||
endfunction
|
||||
endfunc
|
||||
|
||||
function! Test_adjust_lnum()
|
||||
func Test_adjust_lnum()
|
||||
call setloclist(0, [])
|
||||
call Xadjust_qflnum('c')
|
||||
call setqflist([])
|
||||
call Xadjust_qflnum('l')
|
||||
endfunction
|
||||
endfunc
|
||||
|
||||
" Tests for the :grep/:lgrep and :grepadd/:lgrepadd commands
|
||||
function! s:test_xgrep(cchar)
|
||||
func s:test_xgrep(cchar)
|
||||
call s:setup_commands(a:cchar)
|
||||
|
||||
" The following lines are used for the grep test. Don't remove.
|
||||
@ -1389,9 +1412,9 @@ function! s:test_xgrep(cchar)
|
||||
set makeef=Temp_File_##
|
||||
silent Xgrepadd GrepAdd_Test_Text: test_quickfix.vim
|
||||
call assert_true(len(g:Xgetlist()) == 6)
|
||||
endfunction
|
||||
endfunc
|
||||
|
||||
function! Test_grep()
|
||||
func Test_grep()
|
||||
if !has('unix')
|
||||
" The grepprg may not be set on non-Unix systems
|
||||
return
|
||||
@ -1399,9 +1422,9 @@ function! Test_grep()
|
||||
|
||||
call s:test_xgrep('c')
|
||||
call s:test_xgrep('l')
|
||||
endfunction
|
||||
endfunc
|
||||
|
||||
function! Test_two_windows()
|
||||
func Test_two_windows()
|
||||
" Use one 'errorformat' for two windows. Add an expression to each of them,
|
||||
" make sure they each keep their own state.
|
||||
set efm=%DEntering\ dir\ '%f',%f:%l:%m,%XLeaving\ dir\ '%f'
|
||||
@ -1427,12 +1450,10 @@ function! Test_two_windows()
|
||||
laddexpr 'one.txt:3:one one one'
|
||||
|
||||
let loc_one = getloclist(one_id)
|
||||
echo string(loc_one)
|
||||
call assert_equal('Xone/a/one.txt', bufname(loc_one[1].bufnr))
|
||||
call assert_equal(3, loc_one[1].lnum)
|
||||
|
||||
let loc_two = getloclist(two_id)
|
||||
echo string(loc_two)
|
||||
call assert_equal('Xtwo/a/two.txt', bufname(loc_two[1].bufnr))
|
||||
call assert_equal(5, loc_two[1].lnum)
|
||||
|
||||
@ -1444,7 +1465,7 @@ echo string(loc_two)
|
||||
call delete('Xtwo', 'rf')
|
||||
endfunc
|
||||
|
||||
function XbottomTests(cchar)
|
||||
func XbottomTests(cchar)
|
||||
call s:setup_commands(a:cchar)
|
||||
|
||||
call g:Xsetlist([{'filename': 'foo', 'lnum': 42}])
|
||||
@ -1460,12 +1481,12 @@ function XbottomTests(cchar)
|
||||
endfunc
|
||||
|
||||
" Tests for the :cbottom and :lbottom commands
|
||||
function Test_cbottom()
|
||||
func Test_cbottom()
|
||||
call XbottomTests('c')
|
||||
call XbottomTests('l')
|
||||
endfunction
|
||||
endfunc
|
||||
|
||||
function HistoryTest(cchar)
|
||||
func HistoryTest(cchar)
|
||||
call s:setup_commands(a:cchar)
|
||||
|
||||
call assert_fails(a:cchar . 'older 99', 'E380:')
|
||||
@ -1505,7 +1526,7 @@ func Test_duplicate_buf()
|
||||
endfunc
|
||||
|
||||
" Quickfix/Location list set/get properties tests
|
||||
function Xproperty_tests(cchar)
|
||||
func Xproperty_tests(cchar)
|
||||
call s:setup_commands(a:cchar)
|
||||
|
||||
" Error cases
|
||||
@ -1532,6 +1553,11 @@ function Xproperty_tests(cchar)
|
||||
call assert_equal('N1', g:Xgetlist({'all':1}).title)
|
||||
call g:Xsetlist([], ' ', {'title' : 'N2'})
|
||||
call assert_equal(qfnr + 1, g:Xgetlist({'all':1}).nr)
|
||||
|
||||
let res = g:Xgetlist({'nr': 0})
|
||||
call assert_equal(qfnr + 1, res.nr)
|
||||
call assert_equal(['nr'], keys(res))
|
||||
|
||||
call g:Xsetlist([], ' ', {'title' : 'N3'})
|
||||
call assert_equal('N2', g:Xgetlist({'nr':2, 'title':1}).title)
|
||||
|
||||
@ -1544,21 +1570,21 @@ function Xproperty_tests(cchar)
|
||||
call assert_equal({}, g:Xgetlist({'abc':1}))
|
||||
|
||||
if a:cchar == 'l'
|
||||
call assert_equal({}, getloclist(99, ['title']))
|
||||
call assert_equal({}, getloclist(99, {'title': 1}))
|
||||
endif
|
||||
endfunction
|
||||
endfunc
|
||||
|
||||
function Test_qf_property()
|
||||
func Test_qf_property()
|
||||
call Xproperty_tests('c')
|
||||
call Xproperty_tests('l')
|
||||
endfunction
|
||||
endfunc
|
||||
|
||||
" Tests for the QuickFixCmdPre/QuickFixCmdPost autocommands
|
||||
function QfAutoCmdHandler(loc, cmd)
|
||||
func QfAutoCmdHandler(loc, cmd)
|
||||
call add(g:acmds, a:loc . a:cmd)
|
||||
endfunction
|
||||
endfunc
|
||||
|
||||
function Test_Autocmd()
|
||||
func Test_Autocmd()
|
||||
autocmd QuickFixCmdPre * call QfAutoCmdHandler('pre', expand('<amatch>'))
|
||||
autocmd QuickFixCmdPost * call QfAutoCmdHandler('post', expand('<amatch>'))
|
||||
|
||||
@ -1586,9 +1612,9 @@ function Test_Autocmd()
|
||||
\ 'precaddbuffer',
|
||||
\ 'postcaddbuffer']
|
||||
call assert_equal(l, g:acmds)
|
||||
endfunction
|
||||
endfunc
|
||||
|
||||
function! Test_Autocmd_Exception()
|
||||
func Test_Autocmd_Exception()
|
||||
set efm=%m
|
||||
lgetexpr '?'
|
||||
|
||||
@ -1603,4 +1629,47 @@ function! Test_Autocmd_Exception()
|
||||
call assert_equal('1', getloclist(0)[0].text)
|
||||
|
||||
set efm&vim
|
||||
endfunction
|
||||
endfunc
|
||||
|
||||
func Test_caddbuffer_wrong()
|
||||
" This used to cause a memory access in freed memory.
|
||||
let save_efm = &efm
|
||||
set efm=%EEEE%m,%WWWW,%+CCCC%>%#,%GGGG%.#
|
||||
cgetexpr ['WWWW', 'EEEE', 'CCCC']
|
||||
let &efm = save_efm
|
||||
caddbuffer
|
||||
bwipe!
|
||||
endfunc
|
||||
|
||||
func Test_caddexpr_wrong()
|
||||
" This used to cause a memory access in freed memory.
|
||||
cbuffer
|
||||
cbuffer
|
||||
copen
|
||||
let save_efm = &efm
|
||||
set efm=%
|
||||
call assert_fails('caddexpr ""', 'E376:')
|
||||
let &efm = save_efm
|
||||
endfunc
|
||||
|
||||
func Test_dirstack_cleanup()
|
||||
" This used to cause a memory access in freed memory.
|
||||
let save_efm = &efm
|
||||
lexpr '0'
|
||||
lopen
|
||||
fun X(c)
|
||||
let save_efm=&efm
|
||||
set efm=%D%f
|
||||
if a:c == 'c'
|
||||
caddexpr '::'
|
||||
else
|
||||
laddexpr ':0:0'
|
||||
endif
|
||||
let &efm=save_efm
|
||||
endfun
|
||||
call X('c')
|
||||
call X('l')
|
||||
call setqflist([], 'r')
|
||||
caddbuffer
|
||||
let &efm = save_efm
|
||||
endfunc
|
||||
|
@ -1007,7 +1007,7 @@ static void tui_flush(UI *ui)
|
||||
|
||||
size_t nrevents = loop_size(data->loop);
|
||||
if (nrevents > TOO_MANY_EVENTS) {
|
||||
ILOG("TUI event-queue flooded (thread_events=%zu); purging", nrevents);
|
||||
WLOG("TUI event-queue flooded (thread_events=%zu); purging", nrevents);
|
||||
// Back-pressure: UI events may accumulate much faster than the terminal
|
||||
// device can serve them. Even if SIGINT/CTRL-C is received, user must still
|
||||
// wait for the TUI event-queue to drain, and if there are ~millions of
|
||||
@ -1537,11 +1537,11 @@ static void augment_terminfo(TUIData *data, const char *term,
|
||||
bool teraterm = terminfo_is_term_family(term, "teraterm");
|
||||
bool putty = terminfo_is_term_family(term, "putty");
|
||||
bool screen = terminfo_is_term_family(term, "screen");
|
||||
bool tmux = terminfo_is_term_family(term, "tmux") || !!os_getenv("TMUX");
|
||||
bool iterm = terminfo_is_term_family(term, "iterm")
|
||||
|| terminfo_is_term_family(term, "iTerm.app");
|
||||
// None of the following work over SSH; see :help TERM .
|
||||
bool iterm_pretending_xterm = xterm && iterm_env;
|
||||
bool tmux_wrap = screen && !!os_getenv("TMUX");
|
||||
|
||||
const char * xterm_version = os_getenv("XTERM_VERSION");
|
||||
bool true_xterm = xterm && !!xterm_version;
|
||||
@ -1573,12 +1573,11 @@ static void augment_terminfo(TUIData *data, const char *term,
|
||||
// specific ones.
|
||||
|
||||
// can use colons like ISO 8613-6:1994/ITU T.416:1993 says.
|
||||
bool has_colon_rgb = false
|
||||
// per GNOME bug #685759 and bug #704449
|
||||
|| (vte_version >= 3600)
|
||||
|| iterm || iterm_pretending_xterm // per analysis of VT100Terminal.m
|
||||
// per http://invisible-island.net/xterm/xterm.log.html#xterm_282
|
||||
|| true_xterm;
|
||||
bool has_colon_rgb = !tmux && !screen
|
||||
&& ((vte_version >= 3600) // per GNOME bug #685759, #704449
|
||||
|| iterm || iterm_pretending_xterm // per analysis of VT100Terminal.m
|
||||
// per http://invisible-island.net/xterm/xterm.log.html#xterm_282
|
||||
|| true_xterm);
|
||||
|
||||
data->unibi_ext.set_rgb_foreground = unibi_find_ext_str(ut, "setrgbf");
|
||||
if (-1 == data->unibi_ext.set_rgb_foreground) {
|
||||
@ -1606,7 +1605,7 @@ static void augment_terminfo(TUIData *data, const char *term,
|
||||
// all panes, which is not particularly desirable. A better approach
|
||||
// would use a tmux control sequence and an extra if(screen) test.
|
||||
data->unibi_ext.set_cursor_color = (int)unibi_add_ext_str(
|
||||
ut, NULL, TMUX_WRAP(tmux_wrap, "\033]Pl%p1%06x\033\\"));
|
||||
ut, NULL, TMUX_WRAP(tmux, "\033]Pl%p1%06x\033\\"));
|
||||
} else if (xterm || (vte_version != 0) || rxvt) {
|
||||
// This seems to be supported for a long time in VTE
|
||||
// urxvt also supports this
|
||||
@ -1690,7 +1689,7 @@ static const char *tui_get_stty_erase(void)
|
||||
if (tcgetattr(input_global_fd(), &t) != -1) {
|
||||
stty_erase[0] = (char)t.c_cc[VERASE];
|
||||
stty_erase[1] = '\0';
|
||||
ILOG("stty/termios:erase=%s", stty_erase);
|
||||
DLOG("stty/termios:erase=%s", stty_erase);
|
||||
}
|
||||
#endif
|
||||
return stty_erase;
|
||||
@ -1707,12 +1706,12 @@ static const char *tui_tk_ti_getstr(const char *name, const char *value,
|
||||
}
|
||||
|
||||
if (strequal(name, "key_backspace")) {
|
||||
ILOG("libtermkey:kbs=%s", value);
|
||||
DLOG("libtermkey:kbs=%s", value);
|
||||
if (stty_erase[0] != 0) {
|
||||
return stty_erase;
|
||||
}
|
||||
} else if (strequal(name, "key_dc")) {
|
||||
ILOG("libtermkey:kdch1=%s", value);
|
||||
DLOG("libtermkey:kdch1=%s", value);
|
||||
// Vim: "If <BS> and <DEL> are now the same, redefine <DEL>."
|
||||
if (value != NULL && strequal(stty_erase, value)) {
|
||||
return stty_erase[0] == DEL ? CTRL_H_STR : DEL_STR;
|
||||
|
@ -8,6 +8,7 @@
|
||||
#include <limits.h>
|
||||
|
||||
#include "nvim/vim.h"
|
||||
#include "nvim/log.h"
|
||||
#include "nvim/ui.h"
|
||||
#include "nvim/charset.h"
|
||||
#include "nvim/cursor.h"
|
||||
@ -59,6 +60,27 @@ static int busy = 0;
|
||||
static int height, width;
|
||||
static int old_mode_idx = -1;
|
||||
|
||||
#if MIN_LOG_LEVEL > DEBUG_LOG_LEVEL
|
||||
# define UI_LOG(funname, ...)
|
||||
#else
|
||||
static size_t uilog_seen = 0;
|
||||
static char uilog_last_event[1024] = { 0 };
|
||||
# define UI_LOG(funname, ...) \
|
||||
do { \
|
||||
if (strequal(uilog_last_event, STR(funname))) { \
|
||||
uilog_seen++; \
|
||||
} else { \
|
||||
if (uilog_seen > 0) { \
|
||||
do_log(DEBUG_LOG_LEVEL, "ui", 0, true, \
|
||||
"%s (+%zu times...)", uilog_last_event, uilog_seen); \
|
||||
} \
|
||||
DLOG("ui: " STR(funname)); \
|
||||
uilog_seen = 0; \
|
||||
xstrlcpy(uilog_last_event, STR(funname), sizeof(uilog_last_event)); \
|
||||
} \
|
||||
} while (0)
|
||||
#endif
|
||||
|
||||
// UI_CALL invokes a function on all registered UI instances. The functions can
|
||||
// have 0-5 arguments (configurable by SELECT_NTH).
|
||||
//
|
||||
@ -67,6 +89,7 @@ static int old_mode_idx = -1;
|
||||
# define UI_CALL(funname, ...) \
|
||||
do { \
|
||||
flush_cursor_update(); \
|
||||
UI_LOG(funname, 0); \
|
||||
for (size_t i = 0; i < ui_count; i++) { \
|
||||
UI *ui = uis[i]; \
|
||||
UI_CALL_MORE(funname, __VA_ARGS__); \
|
||||
@ -76,6 +99,7 @@ static int old_mode_idx = -1;
|
||||
# define UI_CALL(...) \
|
||||
do { \
|
||||
flush_cursor_update(); \
|
||||
UI_LOG(__VA_ARGS__, 0); \
|
||||
for (size_t i = 0; i < ui_count; i++) { \
|
||||
UI *ui = uis[i]; \
|
||||
UI_CALL_HELPER(CNT(__VA_ARGS__), __VA_ARGS__); \
|
||||
@ -85,6 +109,7 @@ static int old_mode_idx = -1;
|
||||
#define CNT(...) SELECT_NTH(__VA_ARGS__, MORE, MORE, MORE, MORE, ZERO, ignore)
|
||||
#define SELECT_NTH(a1, a2, a3, a4, a5, a6, ...) a6
|
||||
#define UI_CALL_HELPER(c, ...) UI_CALL_HELPER2(c, __VA_ARGS__)
|
||||
// Resolves to UI_CALL_MORE or UI_CALL_ZERO.
|
||||
#define UI_CALL_HELPER2(c, ...) UI_CALL_##c(__VA_ARGS__)
|
||||
#define UI_CALL_MORE(method, ...) if (ui->method) ui->method(ui, __VA_ARGS__)
|
||||
#define UI_CALL_ZERO(method) if (ui->method) ui->method(ui)
|
||||
|
@ -24,30 +24,10 @@
|
||||
|
||||
#define UI(b) (((UIBridgeData *)b)->ui)
|
||||
|
||||
#if MIN_LOG_LEVEL <= DEBUG_LOG_LEVEL
|
||||
static size_t uilog_seen = 0;
|
||||
static argv_callback uilog_event = NULL;
|
||||
#define UI_CALL(ui, name, argc, ...) \
|
||||
do { \
|
||||
if (uilog_event == ui_bridge_##name##_event) { \
|
||||
uilog_seen++; \
|
||||
} else { \
|
||||
if (uilog_seen > 0) { \
|
||||
DLOG("UI bridge: ...%zu times", uilog_seen); \
|
||||
} \
|
||||
DLOG("UI bridge: " STR(name)); \
|
||||
uilog_seen = 0; \
|
||||
uilog_event = ui_bridge_##name##_event; \
|
||||
} \
|
||||
((UIBridgeData *)ui)->scheduler( \
|
||||
event_create(ui_bridge_##name##_event, argc, __VA_ARGS__), UI(ui)); \
|
||||
} while (0)
|
||||
#else
|
||||
// Schedule a function call on the UI bridge thread.
|
||||
#define UI_CALL(ui, name, argc, ...) \
|
||||
#define UI_BRIDGE_CALL(ui, name, argc, ...) \
|
||||
((UIBridgeData *)ui)->scheduler( \
|
||||
event_create(ui_bridge_##name##_event, argc, __VA_ARGS__), UI(ui))
|
||||
#endif
|
||||
|
||||
#define INT2PTR(i) ((void *)(intptr_t)i)
|
||||
#define PTR2INT(p) ((Integer)(intptr_t)p)
|
||||
@ -128,7 +108,7 @@ static void ui_bridge_stop(UI *b)
|
||||
{
|
||||
UIBridgeData *bridge = (UIBridgeData *)b;
|
||||
bool stopped = bridge->stopped = false;
|
||||
UI_CALL(b, stop, 1, b);
|
||||
UI_BRIDGE_CALL(b, stop, 1, b);
|
||||
for (;;) {
|
||||
uv_mutex_lock(&bridge->mutex);
|
||||
stopped = bridge->stopped;
|
||||
@ -154,7 +134,7 @@ static void ui_bridge_highlight_set(UI *b, HlAttrs attrs)
|
||||
{
|
||||
HlAttrs *a = xmalloc(sizeof(HlAttrs));
|
||||
*a = attrs;
|
||||
UI_CALL(b, highlight_set, 2, b, a);
|
||||
UI_BRIDGE_CALL(b, highlight_set, 2, b, a);
|
||||
}
|
||||
static void ui_bridge_highlight_set_event(void **argv)
|
||||
{
|
||||
@ -167,7 +147,7 @@ static void ui_bridge_suspend(UI *b)
|
||||
{
|
||||
UIBridgeData *data = (UIBridgeData *)b;
|
||||
uv_mutex_lock(&data->mutex);
|
||||
UI_CALL(b, suspend, 1, b);
|
||||
UI_BRIDGE_CALL(b, suspend, 1, b);
|
||||
data->ready = false;
|
||||
// suspend the main thread until CONTINUE is called by the UI thread
|
||||
while (!data->ready) {
|
||||
|
@ -605,12 +605,12 @@ static const int included_patches[] = {
|
||||
127,
|
||||
// 126,
|
||||
// 125,
|
||||
// 124,
|
||||
124,
|
||||
// 123 NA
|
||||
// 122 NA
|
||||
121,
|
||||
// 120 NA
|
||||
// 119,
|
||||
119,
|
||||
// 118,
|
||||
// 117 NA
|
||||
116,
|
||||
@ -629,7 +629,7 @@ static const int included_patches[] = {
|
||||
// 103 NA
|
||||
// 102,
|
||||
// 101,
|
||||
// 100,
|
||||
100,
|
||||
99,
|
||||
// 98 NA
|
||||
// 97 NA
|
||||
@ -641,33 +641,33 @@ static const int included_patches[] = {
|
||||
// 91,
|
||||
// 90,
|
||||
// 89 NA
|
||||
// 88,
|
||||
88,
|
||||
// 87 NA
|
||||
// 86,
|
||||
// 85,
|
||||
// 84,
|
||||
85,
|
||||
84,
|
||||
83,
|
||||
// 82 NA
|
||||
// 81,
|
||||
// 80 NA
|
||||
// 79,
|
||||
// 78,
|
||||
79,
|
||||
78,
|
||||
// 77 NA
|
||||
// 76 NA
|
||||
// 75,
|
||||
75,
|
||||
// 74,
|
||||
// 73,
|
||||
73,
|
||||
// 72 NA
|
||||
// 71 NA
|
||||
// 70 NA
|
||||
// 69,
|
||||
69,
|
||||
68,
|
||||
// 67 NA
|
||||
66,
|
||||
// 65 NA
|
||||
64,
|
||||
// 63,
|
||||
// 62,
|
||||
// 63 NA
|
||||
62,
|
||||
// 61 NA
|
||||
60,
|
||||
// 59 NA
|
||||
@ -677,13 +677,13 @@ static const int included_patches[] = {
|
||||
// 55 NA
|
||||
// 54 NA
|
||||
53,
|
||||
// 52,
|
||||
52,
|
||||
// 51 NA
|
||||
// 50 NA
|
||||
49,
|
||||
// 48 NA
|
||||
47,
|
||||
// 46,
|
||||
46,
|
||||
// 45 NA
|
||||
// 44,
|
||||
43,
|
||||
@ -691,33 +691,33 @@ static const int included_patches[] = {
|
||||
41,
|
||||
40,
|
||||
// 39 NA
|
||||
// 38,
|
||||
38,
|
||||
37,
|
||||
// 36 NA
|
||||
35,
|
||||
// 34,
|
||||
34,
|
||||
33,
|
||||
32,
|
||||
// 31,
|
||||
31,
|
||||
// 30 NA
|
||||
// 29 NA
|
||||
// 28 NA
|
||||
// 27 NA
|
||||
// 26,
|
||||
// 25,
|
||||
26,
|
||||
25,
|
||||
// 24 NA
|
||||
// 23,
|
||||
23,
|
||||
// 22 NA
|
||||
// 21,
|
||||
// 20,
|
||||
20,
|
||||
19,
|
||||
// 18,
|
||||
// 17,
|
||||
17,
|
||||
// 16 NA
|
||||
// 15 NA
|
||||
// 14 NA
|
||||
// 13 NA
|
||||
// 12,
|
||||
12,
|
||||
// 11 NA
|
||||
// 10 NA
|
||||
// 9 NA
|
||||
@ -725,8 +725,8 @@ static const int included_patches[] = {
|
||||
// 7 NA
|
||||
6,
|
||||
// 5 NA
|
||||
// 4,
|
||||
// 3,
|
||||
4,
|
||||
3,
|
||||
2,
|
||||
1,
|
||||
0
|
||||
@ -993,7 +993,7 @@ void intro_message(int colon)
|
||||
static char *(lines[]) = {
|
||||
N_(NVIM_VERSION_LONG),
|
||||
"",
|
||||
N_("by Bram Moolenaar et al."),
|
||||
N_("by al."),
|
||||
N_("Nvim is open source and freely distributable"),
|
||||
N_("https://neovim.io/community"),
|
||||
"",
|
||||
|
@ -163,6 +163,7 @@ enum {
|
||||
EXPAND_SYNTIME,
|
||||
EXPAND_USER_ADDR_TYPE,
|
||||
EXPAND_PACKADD,
|
||||
EXPAND_MESSAGES,
|
||||
};
|
||||
|
||||
|
||||
@ -319,7 +320,7 @@ enum { FOLD_TEXT_LEN = 51 }; //!< buffer size for get_foldtext()
|
||||
// Lowest number used for window ID. Cannot have this many windows per tab.
|
||||
#define LOWEST_WIN_ID 1000
|
||||
|
||||
#if defined(__FreeBSD__) && defined(S_ISCHR)
|
||||
#if (defined(__FreeBSD__) || defined(__FreeBSD_kernel__)) && defined(S_ISCHR)
|
||||
# define OPEN_CHR_FILES
|
||||
#endif
|
||||
|
||||
|
@ -193,7 +193,7 @@ newwindow:
|
||||
/* cursor to previous window with wrap around */
|
||||
case 'W':
|
||||
CHECK_CMDWIN
|
||||
if (firstwin == lastwin && Prenum != 1) /* just one window */
|
||||
if (ONE_WINDOW && Prenum != 1) /* just one window */
|
||||
beep_flush();
|
||||
else {
|
||||
if (Prenum) { /* go to specified window */
|
||||
@ -574,7 +574,7 @@ int win_split_ins(int size, int flags, win_T *new_wp, int dir)
|
||||
oldwin = curwin;
|
||||
|
||||
/* add a status line when p_ls == 1 and splitting the first window */
|
||||
if (lastwin == firstwin && p_ls == 1 && oldwin->w_status_height == 0) {
|
||||
if (ONE_WINDOW && p_ls == 1 && oldwin->w_status_height == 0) {
|
||||
if (oldwin->w_height <= p_wmh && new_wp == NULL) {
|
||||
EMSG(_(e_noroom));
|
||||
return FAIL;
|
||||
@ -1182,7 +1182,7 @@ static void win_exchange(long Prenum)
|
||||
win_T *wp2;
|
||||
int temp;
|
||||
|
||||
if (lastwin == firstwin) { /* just one window */
|
||||
if (ONE_WINDOW) { /* just one window */
|
||||
beep_flush();
|
||||
return;
|
||||
}
|
||||
@ -1271,7 +1271,7 @@ static void win_rotate(int upwards, int count)
|
||||
frame_T *frp;
|
||||
int n;
|
||||
|
||||
if (firstwin == lastwin) { /* nothing to do */
|
||||
if (ONE_WINDOW) { /* nothing to do */
|
||||
beep_flush();
|
||||
return;
|
||||
}
|
||||
@ -1343,7 +1343,7 @@ static void win_totop(int size, int flags)
|
||||
int dir;
|
||||
int height = curwin->w_height;
|
||||
|
||||
if (lastwin == firstwin) {
|
||||
if (ONE_WINDOW) {
|
||||
beep_flush();
|
||||
return;
|
||||
}
|
||||
@ -1728,7 +1728,7 @@ void close_windows(buf_T *buf, int keep_curwin)
|
||||
|
||||
++RedrawingDisabled;
|
||||
|
||||
for (win_T *wp = firstwin; wp != NULL && lastwin != firstwin; ) {
|
||||
for (win_T *wp = firstwin; wp != NULL && !ONE_WINDOW; ) {
|
||||
if (wp->w_buffer == buf && (!keep_curwin || wp != curwin)
|
||||
&& !(wp->w_closing || wp->w_buffer->b_locked > 0)) {
|
||||
if (win_close(wp, false) == FAIL) {
|
||||
@ -1810,7 +1810,7 @@ static bool close_last_window_tabpage(win_T *win, bool free_buf,
|
||||
tabpage_T *prev_curtab)
|
||||
FUNC_ATTR_NONNULL_ARG(1)
|
||||
{
|
||||
if (firstwin != lastwin) {
|
||||
if (!ONE_WINDOW) {
|
||||
return false;
|
||||
}
|
||||
buf_T *old_curbuf = curbuf;
|
||||
@ -2194,7 +2194,7 @@ winframe_remove (
|
||||
/*
|
||||
* If there is only one window there is nothing to remove.
|
||||
*/
|
||||
if (tp == NULL ? firstwin == lastwin : tp->tp_firstwin == tp->tp_lastwin)
|
||||
if (tp == NULL ? ONE_WINDOW : tp->tp_firstwin == tp->tp_lastwin)
|
||||
return NULL;
|
||||
|
||||
/*
|
||||
@ -2331,7 +2331,7 @@ win_altframe (
|
||||
frame_T *frp;
|
||||
int b;
|
||||
|
||||
if (tp == NULL ? firstwin == lastwin : tp->tp_firstwin == tp->tp_lastwin)
|
||||
if (tp == NULL ? ONE_WINDOW : tp->tp_firstwin == tp->tp_lastwin)
|
||||
/* Last window in this tab page, will go to next tab page. */
|
||||
return alt_tabpage()->tp_curwin->w_frame;
|
||||
|
||||
@ -2851,7 +2851,7 @@ close_others (
|
||||
win_close(wp, !P_HID(wp->w_buffer) && !bufIsChanged(wp->w_buffer));
|
||||
}
|
||||
|
||||
if (message && lastwin != firstwin)
|
||||
if (message && !ONE_WINDOW)
|
||||
EMSG(_("E445: Other window contains changes"));
|
||||
}
|
||||
|
||||
@ -5173,7 +5173,7 @@ last_status (
|
||||
{
|
||||
/* Don't make a difference between horizontal or vertical split. */
|
||||
last_status_rec(topframe, (p_ls == 2
|
||||
|| (p_ls == 1 && (morewin || lastwin != firstwin))));
|
||||
|| (p_ls == 1 && (morewin || !ONE_WINDOW))));
|
||||
}
|
||||
|
||||
static void last_status_rec(frame_T *fr, int statusline)
|
||||
|
@ -2,6 +2,8 @@ local helpers = require('test.functional.helpers')(after_each)
|
||||
local clear, command, nvim = helpers.clear, helpers.command, helpers.nvim
|
||||
local expect, feed = helpers.expect, helpers.feed
|
||||
local eq, eval = helpers.eq, helpers.eval
|
||||
local funcs = helpers.funcs
|
||||
|
||||
|
||||
describe(':emenu', function()
|
||||
|
||||
@ -56,3 +58,326 @@ describe(':emenu', function()
|
||||
eq('thiscmdmode', eval('getcmdline()'))
|
||||
end)
|
||||
end)
|
||||
|
||||
describe('menu_get', function()
|
||||
|
||||
before_each(function()
|
||||
clear()
|
||||
command('nnoremenu &Test.Test inormal<ESC>')
|
||||
command('inoremenu Test.Test insert')
|
||||
command('vnoremenu Test.Test x')
|
||||
command('cnoremenu Test.Test cmdmode')
|
||||
command('menu Test.Nested.test level1')
|
||||
command('menu Test.Nested.Nested2 level2')
|
||||
|
||||
command('nnoremenu <script> Export.Script p')
|
||||
command('tmenu Export.Script This is the tooltip')
|
||||
command('menu ]Export.hidden thisoneshouldbehidden')
|
||||
|
||||
command('nnoremenu Edit.Paste p')
|
||||
command('cnoremenu Edit.Paste <C-R>"')
|
||||
end)
|
||||
|
||||
it("path='', modes='a'", function()
|
||||
local m = funcs.menu_get("","a");
|
||||
-- HINT: To print the expected table and regenerate the tests:
|
||||
-- print(require('pl.pretty').dump(m))
|
||||
local expected = {
|
||||
{
|
||||
shortcut = "T",
|
||||
hidden = 0,
|
||||
submenus = {
|
||||
{
|
||||
mappings = {
|
||||
i = {
|
||||
sid = 1,
|
||||
noremap = 1,
|
||||
enabled = 1,
|
||||
rhs = "insert",
|
||||
silent = 0
|
||||
},
|
||||
s = {
|
||||
sid = 1,
|
||||
noremap = 1,
|
||||
enabled = 1,
|
||||
rhs = "x",
|
||||
silent = 0
|
||||
},
|
||||
n = {
|
||||
sid = 1,
|
||||
noremap = 1,
|
||||
enabled = 1,
|
||||
rhs = "inormal\27",
|
||||
silent = 0
|
||||
},
|
||||
v = {
|
||||
sid = 1,
|
||||
noremap = 1,
|
||||
enabled = 1,
|
||||
rhs = "x",
|
||||
silent = 0
|
||||
},
|
||||
c = {
|
||||
sid = 1,
|
||||
noremap = 1,
|
||||
enabled = 1,
|
||||
rhs = "cmdmode",
|
||||
silent = 0
|
||||
}
|
||||
},
|
||||
priority = 500,
|
||||
name = "Test",
|
||||
hidden = 0
|
||||
},
|
||||
{
|
||||
priority = 500,
|
||||
name = "Nested",
|
||||
submenus = {
|
||||
{
|
||||
mappings = {
|
||||
o = {
|
||||
sid = 0,
|
||||
noremap = 0,
|
||||
enabled = 1,
|
||||
rhs = "level1",
|
||||
silent = 0
|
||||
},
|
||||
v = {
|
||||
sid = 0,
|
||||
noremap = 0,
|
||||
enabled = 1,
|
||||
rhs = "level1",
|
||||
silent = 0
|
||||
},
|
||||
s = {
|
||||
sid = 0,
|
||||
noremap = 0,
|
||||
enabled = 1,
|
||||
rhs = "level1",
|
||||
silent = 0
|
||||
},
|
||||
n = {
|
||||
sid = 0,
|
||||
noremap = 0,
|
||||
enabled = 1,
|
||||
rhs = "level1",
|
||||
silent = 0
|
||||
}
|
||||
},
|
||||
priority = 500,
|
||||
name = "test",
|
||||
hidden = 0
|
||||
},
|
||||
{
|
||||
mappings = {
|
||||
o = {
|
||||
sid = 0,
|
||||
noremap = 0,
|
||||
enabled = 1,
|
||||
rhs = "level2",
|
||||
silent = 0
|
||||
},
|
||||
v = {
|
||||
sid = 0,
|
||||
noremap = 0,
|
||||
enabled = 1,
|
||||
rhs = "level2",
|
||||
silent = 0
|
||||
},
|
||||
s = {
|
||||
sid = 0,
|
||||
noremap = 0,
|
||||
enabled = 1,
|
||||
rhs = "level2",
|
||||
silent = 0
|
||||
},
|
||||
n = {
|
||||
sid = 0,
|
||||
noremap = 0,
|
||||
enabled = 1,
|
||||
rhs = "level2",
|
||||
silent = 0
|
||||
}
|
||||
},
|
||||
priority = 500,
|
||||
name = "Nested2",
|
||||
hidden = 0
|
||||
}
|
||||
},
|
||||
hidden = 0
|
||||
}
|
||||
},
|
||||
priority = 500,
|
||||
name = "Test"
|
||||
},
|
||||
{
|
||||
priority = 500,
|
||||
name = "Export",
|
||||
submenus = {
|
||||
{
|
||||
tooltip = "This is the tooltip",
|
||||
hidden = 0,
|
||||
name = "Script",
|
||||
priority = 500,
|
||||
mappings = {
|
||||
n = {
|
||||
sid = 1,
|
||||
noremap = 1,
|
||||
enabled = 1,
|
||||
rhs = "p",
|
||||
silent = 0
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
hidden = 0
|
||||
},
|
||||
{
|
||||
priority = 500,
|
||||
name = "Edit",
|
||||
submenus = {
|
||||
{
|
||||
mappings = {
|
||||
c = {
|
||||
sid = 1,
|
||||
noremap = 1,
|
||||
enabled = 1,
|
||||
rhs = "\18\"",
|
||||
silent = 0
|
||||
},
|
||||
n = {
|
||||
sid = 1,
|
||||
noremap = 1,
|
||||
enabled = 1,
|
||||
rhs = "p",
|
||||
silent = 0
|
||||
}
|
||||
},
|
||||
priority = 500,
|
||||
name = "Paste",
|
||||
hidden = 0
|
||||
}
|
||||
},
|
||||
hidden = 0
|
||||
},
|
||||
{
|
||||
priority = 500,
|
||||
name = "]Export",
|
||||
submenus = {
|
||||
{
|
||||
mappings = {
|
||||
o = {
|
||||
sid = 0,
|
||||
noremap = 0,
|
||||
enabled = 1,
|
||||
rhs = "thisoneshouldbehidden",
|
||||
silent = 0
|
||||
},
|
||||
v = {
|
||||
sid = 0,
|
||||
noremap = 0,
|
||||
enabled = 1,
|
||||
rhs = "thisoneshouldbehidden",
|
||||
silent = 0
|
||||
},
|
||||
s = {
|
||||
sid = 0,
|
||||
noremap = 0,
|
||||
enabled = 1,
|
||||
rhs = "thisoneshouldbehidden",
|
||||
silent = 0
|
||||
},
|
||||
n = {
|
||||
sid = 0,
|
||||
noremap = 0,
|
||||
enabled = 1,
|
||||
rhs = "thisoneshouldbehidden",
|
||||
silent = 0
|
||||
}
|
||||
},
|
||||
priority = 500,
|
||||
name = "hidden",
|
||||
hidden = 0
|
||||
}
|
||||
},
|
||||
hidden = 1
|
||||
}
|
||||
}
|
||||
eq(expected, m)
|
||||
end)
|
||||
|
||||
it('matching path, default modes', function()
|
||||
local m = funcs.menu_get("Export", "a")
|
||||
local expected = {
|
||||
{
|
||||
tooltip = "This is the tooltip",
|
||||
hidden = 0,
|
||||
name = "Script",
|
||||
priority = 500,
|
||||
mappings = {
|
||||
n = {
|
||||
sid = 1,
|
||||
noremap = 1,
|
||||
enabled = 1,
|
||||
rhs = "p",
|
||||
silent = 0
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
eq(expected, m)
|
||||
end)
|
||||
|
||||
it('no path, matching modes', function()
|
||||
local m = funcs.menu_get("","i")
|
||||
local expected = {
|
||||
{
|
||||
shortcut = "T",
|
||||
hidden = 0,
|
||||
submenus = {
|
||||
{
|
||||
mappings = {
|
||||
i = {
|
||||
sid = 1,
|
||||
noremap = 1,
|
||||
enabled = 1,
|
||||
rhs = "insert",
|
||||
silent = 0
|
||||
}
|
||||
},
|
||||
priority = 500,
|
||||
name = "Test",
|
||||
hidden = 0
|
||||
},
|
||||
{
|
||||
}
|
||||
},
|
||||
priority = 500,
|
||||
name = "Test"
|
||||
}
|
||||
}
|
||||
eq(expected, m)
|
||||
end)
|
||||
|
||||
it('matching path and modes', function()
|
||||
local m = funcs.menu_get("Test","i")
|
||||
local expected = {
|
||||
{
|
||||
mappings = {
|
||||
i = {
|
||||
sid = 1,
|
||||
noremap = 1,
|
||||
enabled = 1,
|
||||
rhs = "insert",
|
||||
silent = 0
|
||||
}
|
||||
},
|
||||
priority = 500,
|
||||
name = "Test",
|
||||
hidden = 0
|
||||
}
|
||||
}
|
||||
eq(expected, m)
|
||||
end)
|
||||
|
||||
end)
|
||||
|
@ -253,6 +253,11 @@ describe('assert function:', function()
|
||||
"Expected range 5 - 7, but got 8",
|
||||
})
|
||||
end)
|
||||
|
||||
it('assert_inrange(1, 1) returns E119', function()
|
||||
eq('Vim(call):E119: Not enough arguments for function: assert_inrange',
|
||||
exc_exec("call assert_inrange(1, 1)"))
|
||||
end)
|
||||
end)
|
||||
|
||||
-- assert_report({msg})
|
||||
|
@ -13,9 +13,6 @@ describe('ui/mouse/input', function()
|
||||
clear()
|
||||
meths.set_option('mouse', 'a')
|
||||
meths.set_option('listchars', 'eol:$')
|
||||
-- set mousetime to very high value to ensure that even in valgrind/travis,
|
||||
-- nvim will still pick multiple clicks
|
||||
meths.set_option('mousetime', 5000)
|
||||
screen = Screen.new(25, 5)
|
||||
screen:attach()
|
||||
screen:set_default_attr_ids({
|
||||
@ -119,7 +116,6 @@ describe('ui/mouse/input', function()
|
||||
sel = { bold=true },
|
||||
fill = { reverse=true }
|
||||
})
|
||||
screen.timeout = 15000
|
||||
end)
|
||||
|
||||
it('in tabline on filler space moves tab to the end', function()
|
||||
|
Loading…
Reference in New Issue
Block a user