diff options
26 files changed, 193 insertions, 99 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 009b562953..c3b37cbb35 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -309,7 +309,7 @@ ExternalProject_Add(uncrustify CMAKE_ARGS ${DEPS_CMAKE_ARGS} CMAKE_CACHE_ARGS ${DEPS_CMAKE_CACHE_ARGS} EXCLUDE_FROM_ALL TRUE - ${EXTERNALPROJECT_OPTIONS}) + DOWNLOAD_NO_PROGRESS TRUE) option(USE_BUNDLED_BUSTED "Use bundled busted" ON) if(USE_BUNDLED_BUSTED) @@ -322,7 +322,7 @@ if(USE_BUNDLED_BUSTED) BUILD_COMMAND "" INSTALL_COMMAND "" EXCLUDE_FROM_ALL TRUE - ${EXTERNALPROJECT_OPTIONS}) + DOWNLOAD_NO_PROGRESS TRUE) else() add_custom_target(lua-dev-deps) endif() diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 2f5c2cce5a..b10289a694 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -318,6 +318,30 @@ types, etc. See [:help dev-lua-doc][dev-lua-doc]. - Private functions usually should be underscore-prefixed (named "_foo", not "foo"). - Mark deprecated functions with `@deprecated`. +Third-party dependencies +------------------------ + +To build Nvim using a different commit of a dependency change the appropriate +URL in `cmake.deps/deps.txt`. For example, to use a different version of luajit +replace the value in `LUAJIT_URL` with the wanted commit hash: + +```bash +LUAJIT_URL https://github.com/LuaJIT/LuaJIT/archive/<sha>.tar.gz +``` + +Set `DEPS_IGNORE_SHA` to `TRUE` in `cmake.deps/CMakeLists.txt` to skip hash +check from cmake. + +Alternatively, you may point the URL as a local path where the repository is. +This is convenient when bisecting a problem in a dependency with `git bisect`. +This requires running `make distclean` the first time once to remove traces of +the previous build. Hash checking is always skipped in this case regardless of +`DEPS_IGNORE_SHA`. + +```bash +LUAJIT_URL /home/user/luajit +``` + Reviewing --------- diff --git a/cmake.deps/cmake/BuildGettext.cmake b/cmake.deps/cmake/BuildGettext.cmake index 0d6b323fa2..c80a826f96 100644 --- a/cmake.deps/cmake/BuildGettext.cmake +++ b/cmake.deps/cmake/BuildGettext.cmake @@ -1,8 +1,6 @@ if(MSVC) - get_sha(gettext ${DEPS_IGNORE_SHA}) + get_externalproject_options(gettext ${DEPS_IGNORE_SHA}) ExternalProject_Add(gettext - URL ${GETTEXT_URL} - ${EXTERNALPROJECT_URL_HASH} DOWNLOAD_DIR ${DEPS_DOWNLOAD_DIR}/gettext PATCH_COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/cmake/GettextCMakeLists.txt diff --git a/cmake.deps/cmake/BuildLibiconv.cmake b/cmake.deps/cmake/BuildLibiconv.cmake index f4d7ace2c6..93dc251166 100644 --- a/cmake.deps/cmake/BuildLibiconv.cmake +++ b/cmake.deps/cmake/BuildLibiconv.cmake @@ -1,8 +1,6 @@ if(MSVC) - get_sha(libiconv ${DEPS_IGNORE_SHA}) + get_externalproject_options(libiconv ${DEPS_IGNORE_SHA}) ExternalProject_Add(libiconv - URL ${LIBICONV_URL} - ${EXTERNALPROJECT_URL_HASH} DOWNLOAD_DIR ${DEPS_DOWNLOAD_DIR}/libiconv PATCH_COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/cmake/LibiconvCMakeLists.txt diff --git a/cmake.deps/cmake/BuildLibuv.cmake b/cmake.deps/cmake/BuildLibuv.cmake index 98d78db8f1..aacee9fd4a 100644 --- a/cmake.deps/cmake/BuildLibuv.cmake +++ b/cmake.deps/cmake/BuildLibuv.cmake @@ -1,7 +1,5 @@ -get_sha(libuv ${DEPS_IGNORE_SHA}) +get_externalproject_options(libuv ${DEPS_IGNORE_SHA}) ExternalProject_Add(libuv - URL ${LIBUV_URL} - ${EXTERNALPROJECT_URL_HASH} DOWNLOAD_DIR ${DEPS_DOWNLOAD_DIR}/libuv CMAKE_ARGS ${DEPS_CMAKE_ARGS} -D CMAKE_INSTALL_LIBDIR=lib diff --git a/cmake.deps/cmake/BuildLibvterm.cmake b/cmake.deps/cmake/BuildLibvterm.cmake index f928faad01..a3b59d9374 100644 --- a/cmake.deps/cmake/BuildLibvterm.cmake +++ b/cmake.deps/cmake/BuildLibvterm.cmake @@ -1,7 +1,5 @@ -get_sha(libvterm ${DEPS_IGNORE_SHA}) +get_externalproject_options(libvterm ${DEPS_IGNORE_SHA}) ExternalProject_Add(libvterm - URL ${LIBVTERM_URL} - ${EXTERNALPROJECT_URL_HASH} DOWNLOAD_DIR ${DEPS_DOWNLOAD_DIR}/libvterm PATCH_COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/cmake/LibvtermCMakeLists.txt diff --git a/cmake.deps/cmake/BuildLpeg.cmake b/cmake.deps/cmake/BuildLpeg.cmake index e46a3cb16f..a8455a9976 100644 --- a/cmake.deps/cmake/BuildLpeg.cmake +++ b/cmake.deps/cmake/BuildLpeg.cmake @@ -1,7 +1,5 @@ -get_sha(lpeg ${DEPS_IGNORE_SHA}) +get_externalproject_options(lpeg ${DEPS_IGNORE_SHA}) ExternalProject_Add(lpeg - URL ${LPEG_URL} - ${EXTERNALPROJECT_URL_HASH} DOWNLOAD_DIR ${DEPS_DOWNLOAD_DIR}/lpeg PATCH_COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/cmake/LpegCMakeLists.txt diff --git a/cmake.deps/cmake/BuildLua.cmake b/cmake.deps/cmake/BuildLua.cmake index e47720de47..9a9f90db31 100644 --- a/cmake.deps/cmake/BuildLua.cmake +++ b/cmake.deps/cmake/BuildLua.cmake @@ -40,10 +40,8 @@ set(LUA_CONFIGURE_COMMAND -i ${DEPS_BUILD_DIR}/src/lua/src/luaconf.h) set(LUA_INSTALL_TOP_ARG "INSTALL_TOP=${DEPS_INSTALL_DIR}") -get_sha(lua ${DEPS_IGNORE_SHA}) +get_externalproject_options(lua ${DEPS_IGNORE_SHA}) ExternalProject_Add(lua - URL ${LUA_URL} - ${EXTERNALPROJECT_URL_HASH} DOWNLOAD_DIR ${DEPS_DOWNLOAD_DIR}/lua CONFIGURE_COMMAND "${LUA_CONFIGURE_COMMAND}" BUILD_IN_SOURCE 1 diff --git a/cmake.deps/cmake/BuildLuajit.cmake b/cmake.deps/cmake/BuildLuajit.cmake index de9add43ca..c5068d6986 100644 --- a/cmake.deps/cmake/BuildLuajit.cmake +++ b/cmake.deps/cmake/BuildLuajit.cmake @@ -11,10 +11,8 @@ function(BuildLuajit) set(_luajit_TARGET "luajit") endif() - get_sha(luajit ${DEPS_IGNORE_SHA}) + get_externalproject_options(luajit ${DEPS_IGNORE_SHA}) ExternalProject_Add(${_luajit_TARGET} - URL ${LUAJIT_URL} - ${EXTERNALPROJECT_URL_HASH} DOWNLOAD_DIR ${DEPS_DOWNLOAD_DIR}/${_luajit_TARGET} CONFIGURE_COMMAND "${_luajit_CONFIGURE_COMMAND}" BUILD_IN_SOURCE 1 diff --git a/cmake.deps/cmake/BuildLuv.cmake b/cmake.deps/cmake/BuildLuv.cmake index bf87cde68b..beadf028ee 100644 --- a/cmake.deps/cmake/BuildLuv.cmake +++ b/cmake.deps/cmake/BuildLuv.cmake @@ -17,21 +17,17 @@ if(CMAKE_GENERATOR MATCHES "Unix Makefiles" AND list(APPEND LUV_CMAKE_ARGS -D CMAKE_MAKE_PROGRAM=gmake) endif() -get_sha(lua_compat53 ${DEPS_IGNORE_SHA}) +get_externalproject_options(lua_compat53 ${DEPS_IGNORE_SHA}) ExternalProject_Add(lua_compat53 - URL ${LUA_COMPAT53_URL} - ${EXTERNALPROJECT_URL_HASH} DOWNLOAD_DIR ${DEPS_DOWNLOAD_DIR}/lua_compat53 CONFIGURE_COMMAND "" BUILD_COMMAND "" INSTALL_COMMAND "" ${EXTERNALPROJECT_OPTIONS}) -get_sha(luv ${DEPS_IGNORE_SHA}) +get_externalproject_options(luv ${DEPS_IGNORE_SHA}) ExternalProject_Add(luv DEPENDS lua_compat53 - URL ${LUV_URL} - ${EXTERNALPROJECT_URL_HASH} DOWNLOAD_DIR ${DEPS_DOWNLOAD_DIR}/luv SOURCE_DIR ${DEPS_BUILD_DIR}/src/luv CMAKE_ARGS ${DEPS_CMAKE_ARGS} ${LUV_CMAKE_ARGS} diff --git a/cmake.deps/cmake/BuildMsgpack.cmake b/cmake.deps/cmake/BuildMsgpack.cmake index 8cc648db13..190a37bbc6 100644 --- a/cmake.deps/cmake/BuildMsgpack.cmake +++ b/cmake.deps/cmake/BuildMsgpack.cmake @@ -1,7 +1,5 @@ -get_sha(msgpack ${DEPS_IGNORE_SHA}) +get_externalproject_options(msgpack ${DEPS_IGNORE_SHA}) ExternalProject_Add(msgpack - URL ${MSGPACK_URL} - ${EXTERNALPROJECT_URL_HASH} DOWNLOAD_DIR ${DEPS_DOWNLOAD_DIR}/msgpack CMAKE_ARGS ${DEPS_CMAKE_ARGS} -D MSGPACK_BUILD_TESTS=OFF diff --git a/cmake.deps/cmake/BuildTreesitter.cmake b/cmake.deps/cmake/BuildTreesitter.cmake index 839b7b19c3..6757185425 100644 --- a/cmake.deps/cmake/BuildTreesitter.cmake +++ b/cmake.deps/cmake/BuildTreesitter.cmake @@ -1,7 +1,5 @@ -get_sha(treesitter ${DEPS_IGNORE_SHA}) +get_externalproject_options(treesitter ${DEPS_IGNORE_SHA}) ExternalProject_Add(treesitter - URL ${TREESITTER_URL} - ${EXTERNALPROJECT_URL_HASH} DOWNLOAD_DIR ${DEPS_DOWNLOAD_DIR}/treesitter PATCH_COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/cmake/TreesitterCMakeLists.txt diff --git a/cmake.deps/cmake/BuildTreesitterParsers.cmake b/cmake.deps/cmake/BuildTreesitterParsers.cmake index d251d65354..892e5928a5 100644 --- a/cmake.deps/cmake/BuildTreesitterParsers.cmake +++ b/cmake.deps/cmake/BuildTreesitterParsers.cmake @@ -15,14 +15,10 @@ function(BuildTSParser) set(TS_CMAKE_FILE TreesitterParserCMakeLists.txt) endif() - set(NAME treesitter-${TS_LANG}) - string(TOUPPER "TREESITTER_${TS_LANG}_URL" URL_VARNAME) - set(URL ${${URL_VARNAME}}) + set(NAME treesitter_${TS_LANG}) - get_sha(treesitter_${TS_LANG} ${DEPS_IGNORE_SHA}) + get_externalproject_options(${NAME} ${DEPS_IGNORE_SHA}) ExternalProject_Add(${NAME} - URL ${URL} - ${EXTERNALPROJECT_URL_HASH} DOWNLOAD_DIR ${DEPS_DOWNLOAD_DIR}/${NAME} PATCH_COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/cmake/${TS_CMAKE_FILE} diff --git a/cmake.deps/cmake/BuildUnibilium.cmake b/cmake.deps/cmake/BuildUnibilium.cmake index 5cbf8a961b..bb9c8f183b 100644 --- a/cmake.deps/cmake/BuildUnibilium.cmake +++ b/cmake.deps/cmake/BuildUnibilium.cmake @@ -1,7 +1,5 @@ -get_sha(unibilium ${DEPS_IGNORE_SHA}) +get_externalproject_options(unibilium ${DEPS_IGNORE_SHA}) ExternalProject_Add(unibilium - URL ${UNIBILIUM_URL} - ${EXTERNALPROJECT_URL_HASH} DOWNLOAD_DIR ${DEPS_DOWNLOAD_DIR}/unibilium CMAKE_ARGS ${DEPS_CMAKE_ARGS} CMAKE_CACHE_ARGS ${DEPS_CMAKE_CACHE_ARGS} diff --git a/cmake.deps/cmake/GetBinaryDeps.cmake b/cmake.deps/cmake/GetBinaryDeps.cmake index 2f1e237588..6d3ce48e4f 100644 --- a/cmake.deps/cmake/GetBinaryDeps.cmake +++ b/cmake.deps/cmake/GetBinaryDeps.cmake @@ -24,7 +24,7 @@ function(GetBinaryDep) BUILD_COMMAND "" INSTALL_COMMAND ${CMAKE_COMMAND} -E make_directory ${DEPS_BIN_DIR} COMMAND "${_gettool_INSTALL_COMMAND}" - ${EXTERNALPROJECT_OPTIONS}) + DOWNLOAD_NO_PROGRESS TRUE) endfunction() # Download executable and move it to DEPS_BIN_DIR @@ -49,5 +49,5 @@ function(GetExecutable) BUILD_COMMAND "" INSTALL_COMMAND ${CMAKE_COMMAND} -E make_directory ${DEPS_BIN_DIR} COMMAND ${CMAKE_COMMAND} -E copy <DOWNLOADED_FILE> ${DEPS_BIN_DIR} - ${EXTERNALPROJECT_OPTIONS}) + DOWNLOAD_NO_PROGRESS TRUE) endfunction() diff --git a/cmake/Deps.cmake b/cmake/Deps.cmake index 4700d08427..2e9a78ee22 100644 --- a/cmake/Deps.cmake +++ b/cmake/Deps.cmake @@ -19,7 +19,6 @@ if(APPLE) endif() set(DEPS_CMAKE_CACHE_ARGS -DCMAKE_OSX_ARCHITECTURES:STRING=${CMAKE_OSX_ARCHITECTURES}) -set(EXTERNALPROJECT_OPTIONS DOWNLOAD_NO_PROGRESS TRUE) # MAKE_PRG if(UNIX) @@ -55,10 +54,24 @@ if(CMAKE_OSX_ARCHITECTURES) endforeach() endif() -function(get_sha name ignore) - unset(EXTERNALPROJECT_URL_HASH) - if(NOT ${ignore}) - string(TOUPPER ${name} name_allcaps) - set(EXTERNALPROJECT_URL_HASH URL_HASH SHA256=${${name_allcaps}_SHA256} PARENT_SCOPE) +function(get_externalproject_options name DEPS_IGNORE_SHA) + string(TOUPPER ${name} name_allcaps) + set(url ${${name_allcaps}_URL}) + + set(EXTERNALPROJECT_OPTIONS DOWNLOAD_NO_PROGRESS TRUE) + + if(EXISTS ${url}) + list(APPEND EXTERNALPROJECT_OPTIONS + GIT_REPOSITORY ${${name_allcaps}_URL}) + if(${CMAKE_VERSION} VERSION_GREATER_EQUAL 3.18) + list(APPEND EXTERNALPROJECT_OPTIONS GIT_REMOTE_UPDATE_STRATEGY CHECKOUT) + endif() + else() + list(APPEND EXTERNALPROJECT_OPTIONS URL ${${name_allcaps}_URL}) + if(NOT ${DEPS_IGNORE_SHA}) + list(APPEND EXTERNALPROJECT_OPTIONS URL_HASH SHA256=${${name_allcaps}_SHA256}) + endif() endif() + + set(EXTERNALPROJECT_OPTIONS ${EXTERNALPROJECT_OPTIONS} PARENT_SCOPE) endfunction() diff --git a/runtime/doc/builtin.txt b/runtime/doc/builtin.txt index be81451d08..c88513ad75 100644 --- a/runtime/doc/builtin.txt +++ b/runtime/doc/builtin.txt @@ -7411,7 +7411,8 @@ slice({expr}, {start} [, {end}]) *slice()* Similar to using a |slice| "expr[start : end]", but "end" is used exclusive. And for a string the indexes are used as character indexes instead of byte indexes. - Also, composing characters are not counted. + Also, composing characters are treated as a part of the + preceding base character. When {end} is omitted the slice continues to the last item. When {end} is -1 the last item is omitted. Returns an empty value if {start} or {end} are invalid. @@ -7758,8 +7759,8 @@ strcharpart({src}, {start} [, {len} [, {skipcc}]]) *strcharpart()* of byte index and length. When {skipcc} is omitted or zero, composing characters are counted separately. - When {skipcc} set to 1, Composing characters are ignored, - similar to |slice()|. + When {skipcc} set to 1, composing characters are treated as a + part of the preceding base character, similar to |slice()|. When a character index is used where a character does not exist it is omitted and counted as one character. For example: >vim @@ -7773,7 +7774,7 @@ strchars({string} [, {skipcc}]) *strchars()* in String {string}. When {skipcc} is omitted or zero, composing characters are counted separately. - When {skipcc} set to 1, Composing characters are ignored. + When {skipcc} set to 1, composing characters are ignored. |strcharlen()| always does this. Returns zero on error. diff --git a/runtime/filetype.lua b/runtime/filetype.lua index 3f2a7c2960..4880ed55ef 100644 --- a/runtime/filetype.lua +++ b/runtime/filetype.lua @@ -11,7 +11,12 @@ vim.api.nvim_create_autocmd({ 'BufRead', 'BufNewFile', 'StdinReadPost' }, { if not vim.api.nvim_buf_is_valid(args.buf) then return end - local ft, on_detect = vim.filetype.match({ filename = args.match, buf = args.buf }) + local ft, on_detect = vim.filetype.match({ + -- The unexpanded file name is needed here. #27914 + -- Neither args.file nor args.match are guaranteed to be unexpanded. + filename = vim.fn.bufname(args.buf), + buf = args.buf, + }) if not ft then -- Generic configuration file used as fallback ft = require('vim.filetype.detect').conf(args.file, args.buf) diff --git a/runtime/lua/vim/_meta/vimfn.lua b/runtime/lua/vim/_meta/vimfn.lua index da251f89ad..caddd4dde2 100644 --- a/runtime/lua/vim/_meta/vimfn.lua +++ b/runtime/lua/vim/_meta/vimfn.lua @@ -8800,7 +8800,8 @@ function vim.fn.sinh(expr) end --- Similar to using a |slice| "expr[start : end]", but "end" is --- used exclusive. And for a string the indexes are used as --- character indexes instead of byte indexes. ---- Also, composing characters are not counted. +--- Also, composing characters are treated as a part of the +--- preceding base character. --- When {end} is omitted the slice continues to the last item. --- When {end} is -1 the last item is omitted. --- Returns an empty value if {start} or {end} are invalid. @@ -9208,8 +9209,8 @@ function vim.fn.strcharlen(string) end --- of byte index and length. --- When {skipcc} is omitted or zero, composing characters are --- counted separately. ---- When {skipcc} set to 1, Composing characters are ignored, ---- similar to |slice()|. +--- When {skipcc} set to 1, composing characters are treated as a +--- part of the preceding base character, similar to |slice()|. --- When a character index is used where a character does not --- exist it is omitted and counted as one character. For --- example: >vim @@ -9229,7 +9230,7 @@ function vim.fn.strcharpart(src, start, len, skipcc) end --- in String {string}. --- When {skipcc} is omitted or zero, composing characters are --- counted separately. ---- When {skipcc} set to 1, Composing characters are ignored. +--- When {skipcc} set to 1, composing characters are ignored. --- |strcharlen()| always does this. --- --- Returns zero on error. diff --git a/runtime/lua/vim/lsp/client.lua b/runtime/lua/vim/lsp/client.lua index d48be131f3..b06fab7319 100644 --- a/runtime/lua/vim/lsp/client.lua +++ b/runtime/lua/vim/lsp/client.lua @@ -693,7 +693,7 @@ function Client:_request(method, params, handler, bufnr) local request = { type = 'pending', bufnr = bufnr, method = method } self.requests[request_id] = request api.nvim_exec_autocmds('LspRequest', { - buffer = bufnr, + buffer = api.nvim_buf_is_valid(bufnr) and bufnr or nil, modeline = false, data = { client_id = self.id, request_id = request_id, request = request }, }) @@ -804,7 +804,7 @@ function Client:_cancel_request(id) if request and request.type == 'pending' then request.type = 'cancel' api.nvim_exec_autocmds('LspRequest', { - buffer = request.bufnr, + buffer = api.nvim_buf_is_valid(request.bufnr) and request.bufnr or nil, modeline = false, data = { client_id = self.id, request_id = id, request = request }, }) diff --git a/runtime/syntax/vim.vim b/runtime/syntax/vim.vim index d37c54a63f..640102562b 100644 --- a/runtime/syntax/vim.vim +++ b/runtime/syntax/vim.vim @@ -197,7 +197,7 @@ syn keyword vimFTOption contained detect indent off on plugin " Augroup : vimAugroupError removed because long augroups caused sync'ing problems. {{{2 " ======= : Trade-off: Increasing synclines with slower editing vs augroup END error checking. -syn cluster vimAugroupList contains=@vimCmdList,vimFilter,vimFunc,vimLineComment,vimSpecFile,vimOper,vimNumber,vimOperParen,vimComment,vim9Comment,vimString,vimSubst,vimRegister,vimCmplxRepeat,vimRegion,vimNotation,vimCtrlChar,vimFuncVar,vimContinue +syn cluster vimAugroupList contains=@vimCmdList,vimFilter,vimFunc,vimLineComment,vimSpecFile,vimOper,vimNumber,vimOperParen,vimComment,vim9Comment,vimString,vimSubst,vimRegister,vimCmplxRepeat,vimNotation,vimCtrlChar,vimFuncVar,vimContinue syn match vimAugroup "\<aug\%[roup]\>" contains=vimAugroupKey,vimAugroupBang skipwhite nextgroup=vimAugroupBang,vimAutoCmdGroup if exists("g:vimsyn_folding") && g:vimsyn_folding =~# 'a' syn region vimAugroup fold start="\<aug\%[roup]\>\ze\s\+\%([eE][nN][dD]\)\@!\S\+" matchgroup=vimAugroupKey end="\<aug\%[roup]\>\ze\s\+[eE][nN][dD]\>" contains=vimAutoCmd,@vimAugroupList,vimAugroupkey skipwhite nextgroup=vimAugroupEnd @@ -219,7 +219,7 @@ syn cluster vimOperGroup contains=vimEnvvar,vimFunc,vimFuncVar,vimOper,vimOperPa syn match vimOper "||\|&&\|[-+*/%.!]" skipwhite nextgroup=vimString,vimSpecFile syn match vimOper "\%#=1\(==\|!=\|>=\|<=\|=\~\|!\~\|>\|<\|=\|!\~#\)[?#]\{0,2}" skipwhite nextgroup=vimString,vimSpecFile syn match vimOper "\(\<is\|\<isnot\)[?#]\{0,2}\>" skipwhite nextgroup=vimString,vimSpecFile -syn region vimOperParen matchgroup=vimParenSep start="(" end=")" contains=vimoperStar,@vimOperGroup +syn region vimOperParen matchgroup=vimParenSep start="(" end=")" contains=@vimOperGroup syn region vimOperParen matchgroup=vimSep start="#\={" end="}" contains=@vimOperGroup nextgroup=vimVar,vimFuncVar if !exists("g:vimsyn_noerror") && !exists("g:vimsyn_noopererror") syn match vimOperError ")" @@ -272,8 +272,6 @@ endif syn match vimFuncVar contained "a:\%(\K\k*\|\d\+\)\>" syn match vimFuncBlank contained "\s\+" -syn keyword vimPattern contained start skip end - " Types: {{{2 " ===== " vimTypes : new for vim9 @@ -292,8 +290,7 @@ syn cluster vimType contains=vimType,vimCompoundType,vimUserType " Keymaps: (Vim Project Addition) {{{2 " ======= -" TODO: autogenerated vimCommand keyword list does not handle all abbreviations -" : handle Vim9 script comments when something like #13104 is merged +" TODO: handle Vim9 script comments when something like #13104 is merged syn match vimKeymapStart "^" contained skipwhite nextgroup=vimKeymapLhs,vimKeymapLineComment syn match vimKeymapLhs "\S\+" contained skipwhite nextgroup=vimKeymapRhs contains=vimNotation syn match vimKeymapRhs "\S\+" contained skipwhite nextgroup=vimKeymapTailComment contains=vimNotation @@ -314,7 +311,7 @@ syn match vimSpecFileMod "\(:[phtre]\)\+" contained " User-Specified Commands: {{{2 " ======================= -syn cluster vimUserCmdList contains=@vimCmdList,vimCmplxRepeat,vimComment,vim9Comment,vimCtrlChar,vimEscapeBrace,vimFunc,vimNotation,vimNumber,vimOper,vimRegion,vimRegister,vimSpecFile,vimString,vimSubst,vimSubstRep,vimSubstRange +syn cluster vimUserCmdList contains=@vimCmdList,vimCmplxRepeat,vimComment,vim9Comment,vimCtrlChar,vimEscapeBrace,vimFunc,vimNotation,vimNumber,vimOper,vimRegister,vimSpecFile,vimString,vimSubst,vimSubstRep,vimSubstRange syn keyword vimUserCommand contained com[mand] syn match vimUserCmd "\<com\%[mand]!\=\>.*$" contains=vimUserAttrb,vimUserAttrbError,vimUserCommand,@vimUserCmdList,vimComFilter syn match vimUserAttrbError contained "-\a\+\ze\s" @@ -463,6 +460,7 @@ VimFoldh syn region vimLetHereDoc matchgroup=vimLetHereDocStart start='=<<\s*\%( " For: {{{2 " === syn keyword vimFor for skipwhite nextgroup=vimVar,vimVarList + " Abbreviations: {{{2 " ============= " GEN_SYN_VIM: vimCommand abbrev, START_STR='syn keyword vimAbb', END_STR='skipwhite nextgroup=vimMapMod,vimMapLhs' @@ -616,7 +614,6 @@ if has("conceal") endif syn match vimSyntax "\<sy\%[ntax]\>" contains=vimCommand skipwhite nextgroup=vimSynType,vimComment,vim9Comment -syn match vimAuSyntax contained "\s+sy\%[ntax]" contains=vimCommand skipwhite nextgroup=vimSynType,vimComment,vim9Comment syn cluster vimFuncBodyList add=vimSyntax " Syntax: case {{{2 @@ -984,7 +981,6 @@ if !exists("skip_vim_syntax_inits") hi def link vimHiAttribList vimError hi def link vimHiCtermError vimError hi def link vimHiKeyError vimError - hi def link vimKeyCodeError vimError hi def link vimMapModErr vimError hi def link vimSubstFlagErr vimError hi def link vimSynCaseError vimError @@ -997,12 +993,9 @@ if !exists("skip_vim_syntax_inits") hi def link vimAugroupBang vimBang hi def link vimAugroupError vimError hi def link vimAugroupKey vimCommand - hi def link vimAuHighlight vimHighlight - hi def link vimAutoCmdOpt vimOption hi def link vimAutoCmd vimCommand hi def link vimAutoEvent Type hi def link vimAutoCmdMod Special - hi def link vimAutoSet vimCommand hi def link vimBang vimOper hi def link vimBehaveBang vimBang hi def link vimBehaveModel vimBehave @@ -1026,7 +1019,6 @@ if !exists("skip_vim_syntax_inits") hi def link vimEchohlNone vimGroup hi def link vimEchohl vimCommand hi def link vimElseIfErr Error - hi def link vimElseif vimCondHL hi def link vimEndfunction vimCommand hi def link vimEnddef vimCommand hi def link vimEnvvar PreProc @@ -1035,7 +1027,6 @@ if !exists("skip_vim_syntax_inits") hi def link vimFBVar vimVar hi def link vimFgBgAttrib vimHiAttrib hi def link vimFuncEcho vimCommand - hi def link vimFold Folded hi def link vimFor vimCommand hi def link vimFTCmd vimCommand hi def link vimFTOption vimSynType @@ -1072,13 +1063,10 @@ if !exists("skip_vim_syntax_inits") hi def link vimHiStartStop vimHiTerm hi def link vimHiTerm Type hi def link vimHLGroup vimGroup - hi def link vimHLMod PreProc hi def link vimInsert vimString hi def link vimIskSep Delimiter - hi def link vimKeyCode vimSpecFile hi def link vimKeymapLineComment vimComment hi def link vimKeymapTailComment vimComment - hi def link vimKeyword Statement hi def link vimLet vimCommand hi def link vimLetHereDoc vimString hi def link vimLetHereDocStart Special @@ -1109,7 +1097,6 @@ if !exists("skip_vim_syntax_inits") hi def link vimNumber Number hi def link vimOperError Error hi def link vimOper Operator - hi def link vimOperStar vimOper hi def link vimOption PreProc hi def link vimParenSep Delimiter hi def link vimPatSepErr vimError @@ -1131,7 +1118,6 @@ if !exists("skip_vim_syntax_inits") hi def link vimSpecFile Identifier hi def link vimSpecFileMod vimSpecFile hi def link vimSpecial Type - hi def link vimStatement Statement hi def link vimStringCont vimString hi def link vimString String hi def link vimStringEnd vimString diff --git a/src/nvim/eval.c b/src/nvim/eval.c index f5f9c4f77b..9e15ea9369 100644 --- a/src/nvim/eval.c +++ b/src/nvim/eval.c @@ -7519,29 +7519,44 @@ int check_luafunc_name(const char *const str, const bool paren) return (int)(p - str); } -/// Return the character "str[index]" where "index" is the character index. If -/// "index" is out of range NULL is returned. +/// Return the character "str[index]" where "index" is the character index, +/// including composing characters. +/// If "index" is out of range NULL is returned. char *char_from_string(const char *str, varnumber_T index) { - size_t nbyte = 0; varnumber_T nchar = index; - if (str == NULL || index < 0) { + if (str == NULL) { return NULL; } size_t slen = strlen(str); - while (nchar > 0 && nbyte < slen) { - nbyte += (size_t)utf_ptr2len(str + nbyte); - nchar--; + + // do the same as for a list: a negative index counts from the end + if (index < 0) { + int clen = 0; + + for (size_t nbyte = 0; nbyte < slen; clen++) { + nbyte += (size_t)utfc_ptr2len(str + nbyte); + } + nchar = clen + index; + if (nchar < 0) { + // unlike list: index out of range results in empty string + return NULL; + } + } + + size_t nbyte = 0; + for (; nchar > 0 && nbyte < slen; nchar--) { + nbyte += (size_t)utfc_ptr2len(str + nbyte); } if (nbyte >= slen) { return NULL; } - return xmemdupz(str + nbyte, (size_t)utf_ptr2len(str + nbyte)); + return xmemdupz(str + nbyte, (size_t)utfc_ptr2len(str + nbyte)); } /// Get the byte index for character index "idx" in string "str" with length -/// "str_len". +/// "str_len". Composing characters are included. /// If going over the end return "str_len". /// If "idx" is negative count from the end, -1 is the last character. /// When going over the start return -1. @@ -7552,7 +7567,7 @@ static ssize_t char_idx2byte(const char *str, size_t str_len, varnumber_T idx) if (nchar >= 0) { while (nchar > 0 && nbyte < str_len) { - nbyte += (size_t)utf_ptr2len(str + nbyte); + nbyte += (size_t)utfc_ptr2len(str + nbyte); nchar--; } } else { @@ -7569,7 +7584,8 @@ static ssize_t char_idx2byte(const char *str, size_t str_len, varnumber_T idx) return (ssize_t)nbyte; } -/// Return the slice "str[first:last]" using character indexes. +/// Return the slice "str[first : last]" using character indexes. Composing +/// characters are included. /// /// @param exclusive true for slice(). /// @@ -7591,7 +7607,7 @@ char *string_slice(const char *str, varnumber_T first, varnumber_T last, bool ex end_byte = char_idx2byte(str, slen, last); if (!exclusive && end_byte >= 0 && end_byte < (ssize_t)slen) { // end index is inclusive - end_byte += utf_ptr2len(str + end_byte); + end_byte += utfc_ptr2len(str + end_byte); } } diff --git a/src/nvim/eval.lua b/src/nvim/eval.lua index 7df4ab71ef..6a3eabc467 100644 --- a/src/nvim/eval.lua +++ b/src/nvim/eval.lua @@ -10485,7 +10485,8 @@ M.funcs = { Similar to using a |slice| "expr[start : end]", but "end" is used exclusive. And for a string the indexes are used as character indexes instead of byte indexes. - Also, composing characters are not counted. + Also, composing characters are treated as a part of the + preceding base character. When {end} is omitted the slice continues to the last item. When {end} is -1 the last item is omitted. Returns an empty value if {start} or {end} are invalid. @@ -10957,8 +10958,8 @@ M.funcs = { of byte index and length. When {skipcc} is omitted or zero, composing characters are counted separately. - When {skipcc} set to 1, Composing characters are ignored, - similar to |slice()|. + When {skipcc} set to 1, composing characters are treated as a + part of the preceding base character, similar to |slice()|. When a character index is used where a character does not exist it is omitted and counted as one character. For example: >vim @@ -10981,7 +10982,7 @@ M.funcs = { in String {string}. When {skipcc} is omitted or zero, composing characters are counted separately. - When {skipcc} set to 1, Composing characters are ignored. + When {skipcc} set to 1, composing characters are ignored. |strcharlen()| always does this. Returns zero on error. diff --git a/src/nvim/eval/typval.c b/src/nvim/eval/typval.c index 9328f53dbd..eb8c89c36e 100644 --- a/src/nvim/eval/typval.c +++ b/src/nvim/eval/typval.c @@ -859,7 +859,7 @@ int tv_list_slice_or_index(list_T *list, bool range, varnumber_T n1_arg, varnumb // A list index out of range is an error. if (!range) { if (verbose) { - semsg(_(e_list_index_out_of_range_nr), (int64_t)n1); + semsg(_(e_list_index_out_of_range_nr), (int64_t)n1_arg); } return FAIL; } diff --git a/test/functional/lua/filetype_spec.lua b/test/functional/lua/filetype_spec.lua index 8b0e0a8beb..3ef650a1d2 100644 --- a/test/functional/lua/filetype_spec.lua +++ b/test/functional/lua/filetype_spec.lua @@ -5,6 +5,10 @@ local api = helpers.api local clear = helpers.clear local pathroot = helpers.pathroot local command = helpers.command +local mkdir = helpers.mkdir +local rmdir = helpers.rmdir +local write_file = helpers.write_file +local uv = vim.uv local root = pathroot() @@ -161,10 +165,30 @@ describe('vim.filetype', function() end) describe('filetype.lua', function() + before_each(function() + mkdir('Xfiletype') + end) + + after_each(function() + rmdir('Xfiletype') + end) + it('does not override user autocommands that set filetype #20333', function() clear({ args = { '--clean', '--cmd', 'autocmd BufRead *.md set filetype=notmarkdown', 'README.md' }, }) eq('notmarkdown', api.nvim_get_option_value('filetype', {})) end) + + it('uses unexpanded path for matching when editing a symlink #27914', function() + mkdir('Xfiletype/.config') + mkdir('Xfiletype/actual') + write_file('Xfiletype/actual/config', '') + uv.fs_symlink(assert(uv.fs_realpath('Xfiletype/actual')), 'Xfiletype/.config/git') + finally(function() + uv.fs_unlink('Xfiletype/.config/git') + end) + clear({ args = { '--clean', 'Xfiletype/.config/git/config' } }) + eq('gitconfig', api.nvim_get_option_value('filetype', {})) + end) end) diff --git a/test/old/testdir/test_functions.vim b/test/old/testdir/test_functions.vim index 3f9ac94782..fdcd93a264 100644 --- a/test/old/testdir/test_functions.vim +++ b/test/old/testdir/test_functions.vim @@ -3610,4 +3610,55 @@ func Test_glob_extended_mswin() call delete('Xtestglob', 'rf') endfunc +" Tests for the slice() function. +func Test_slice() + let lines =<< trim END + call assert_equal([1, 2, 3, 4, 5], slice(range(6), 1)) + call assert_equal([2, 3, 4, 5], slice(range(6), 2)) + call assert_equal([2, 3], slice(range(6), 2, 4)) + call assert_equal([0, 1, 2, 3], slice(range(6), 0, 4)) + call assert_equal([1, 2, 3], slice(range(6), 1, 4)) + call assert_equal([1, 2, 3, 4], slice(range(6), 1, -1)) + call assert_equal([1, 2], slice(range(6), 1, -3)) + call assert_equal([1], slice(range(6), 1, -4)) + call assert_equal([], slice(range(6), 1, -5)) + call assert_equal([], slice(range(6), 1, -6)) + + call assert_equal(0z1122334455, slice(0z001122334455, 1)) + call assert_equal(0z22334455, slice(0z001122334455, 2)) + call assert_equal(0z2233, slice(0z001122334455, 2, 4)) + call assert_equal(0z00112233, slice(0z001122334455, 0, 4)) + call assert_equal(0z112233, slice(0z001122334455, 1, 4)) + call assert_equal(0z11223344, slice(0z001122334455, 1, -1)) + call assert_equal(0z1122, slice(0z001122334455, 1, -3)) + call assert_equal(0z11, slice(0z001122334455, 1, -4)) + call assert_equal(0z, slice(0z001122334455, 1, -5)) + call assert_equal(0z, slice(0z001122334455, 1, -6)) + + call assert_equal('12345', slice('012345', 1)) + call assert_equal('2345', slice('012345', 2)) + call assert_equal('23', slice('012345', 2, 4)) + call assert_equal('0123', slice('012345', 0, 4)) + call assert_equal('123', slice('012345', 1, 4)) + call assert_equal('1234', slice('012345', 1, -1)) + call assert_equal('12', slice('012345', 1, -3)) + call assert_equal('1', slice('012345', 1, -4)) + call assert_equal('', slice('012345', 1, -5)) + call assert_equal('', slice('012345', 1, -6)) + + #" Composing chars are treated as a part of the preceding base char. + call assert_equal('β̳́γ̳̂δ̳̃ε̳̄ζ̳̅', 'ὰ̳β̳́γ̳̂δ̳̃ε̳̄ζ̳̅'->slice(1)) + call assert_equal('γ̳̂δ̳̃ε̳̄ζ̳̅', 'ὰ̳β̳́γ̳̂δ̳̃ε̳̄ζ̳̅'->slice(2)) + call assert_equal('γ̳̂δ̳̃', 'ὰ̳β̳́γ̳̂δ̳̃ε̳̄ζ̳̅'->slice(2, 4)) + call assert_equal('ὰ̳β̳́γ̳̂δ̳̃', 'ὰ̳β̳́γ̳̂δ̳̃ε̳̄ζ̳̅'->slice(0, 4)) + call assert_equal('β̳́γ̳̂δ̳̃', 'ὰ̳β̳́γ̳̂δ̳̃ε̳̄ζ̳̅'->slice(1, 4)) + call assert_equal('β̳́γ̳̂δ̳̃ε̳̄', 'ὰ̳β̳́γ̳̂δ̳̃ε̳̄ζ̳̅'->slice(1, -1)) + call assert_equal('β̳́γ̳̂', 'ὰ̳β̳́γ̳̂δ̳̃ε̳̄ζ̳̅'->slice(1, -3)) + call assert_equal('β̳́', 'ὰ̳β̳́γ̳̂δ̳̃ε̳̄ζ̳̅'->slice(1, -4)) + call assert_equal('', 'ὰ̳β̳́γ̳̂δ̳̃ε̳̄ζ̳̅'->slice(1, -5)) + call assert_equal('', 'ὰ̳β̳́γ̳̂δ̳̃ε̳̄ζ̳̅'->slice(1, -6)) + END + call CheckLegacyAndVim9Success(lines) +endfunc + " vim: shiftwidth=2 sts=2 expandtab |