aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--runtime/autoload/provider/clipboard.vim215
-rw-r--r--runtime/doc/diagnostic.txt7
-rw-r--r--runtime/doc/lua.txt6
-rw-r--r--runtime/doc/news.txt4
-rw-r--r--runtime/doc/provider.txt21
-rw-r--r--runtime/ftplugin/dax.vim16
-rw-r--r--runtime/lua/vim/diagnostic.lua6
-rw-r--r--runtime/lua/vim/filetype.lua1
-rw-r--r--runtime/lua/vim/hl.lua57
-rw-r--r--runtime/syntax/dax.vim151
-rw-r--r--test/functional/lua/hl_spec.lua86
-rw-r--r--test/functional/lua/secure_spec.lua164
-rw-r--r--test/functional/plugin/shada_spec.lua4
-rw-r--r--test/old/testdir/test_filetype.vim1
14 files changed, 536 insertions, 203 deletions
diff --git a/runtime/autoload/provider/clipboard.vim b/runtime/autoload/provider/clipboard.vim
index 7e7feb50e0..32d8841b72 100644
--- a/runtime/autoload/provider/clipboard.vim
+++ b/runtime/autoload/provider/clipboard.vim
@@ -67,6 +67,113 @@ function! s:set_osc52() abort
return 'OSC 52'
endfunction
+function! s:set_pbcopy() abort
+ let s:copy['+'] = ['pbcopy']
+ let s:paste['+'] = ['pbpaste']
+ let s:copy['*'] = s:copy['+']
+ let s:paste['*'] = s:paste['+']
+ let s:cache_enabled = 0
+ return 'pbcopy'
+endfunction
+
+function! s:set_wayland() abort
+ let s:copy['+'] = ['wl-copy', '--type', 'text/plain']
+ let s:paste['+'] = ['wl-paste', '--no-newline']
+ let s:copy['*'] = ['wl-copy', '--primary', '--type', 'text/plain']
+ let s:paste['*'] = ['wl-paste', '--no-newline', '--primary']
+ return 'wl-copy'
+endfunction
+
+function! s:set_wayclip() abort
+ let s:copy['+'] = ['waycopy', '-t', 'text/plain']
+ let s:paste['+'] = ['waypaste', '-t', 'text/plain']
+ let s:copy['*'] = s:copy['+']
+ let s:paste['*'] = s:paste['+']
+ return 'wayclip'
+endfunction
+
+function! s:set_xsel() abort
+ let s:copy['+'] = ['xsel', '--nodetach', '-i', '-b']
+ let s:paste['+'] = ['xsel', '-o', '-b']
+ let s:copy['*'] = ['xsel', '--nodetach', '-i', '-p']
+ let s:paste['*'] = ['xsel', '-o', '-p']
+ return 'xsel'
+endfunction
+
+function! s:set_xclip() abort
+ let s:copy['+'] = ['xclip', '-quiet', '-i', '-selection', 'clipboard']
+ let s:paste['+'] = ['xclip', '-o', '-selection', 'clipboard']
+ let s:copy['*'] = ['xclip', '-quiet', '-i', '-selection', 'primary']
+ let s:paste['*'] = ['xclip', '-o', '-selection', 'primary']
+ return 'xclip'
+endfunction
+
+function! s:set_lemonade() abort
+ let s:copy['+'] = ['lemonade', 'copy']
+ let s:paste['+'] = ['lemonade', 'paste']
+ let s:copy['*'] = ['lemonade', 'copy']
+ let s:paste['*'] = ['lemonade', 'paste']
+ return 'lemonade'
+endfunction
+
+function! s:set_doitclient() abort
+ let s:copy['+'] = ['doitclient', 'wclip']
+ let s:paste['+'] = ['doitclient', 'wclip', '-r']
+ let s:copy['*'] = s:copy['+']
+ let s:paste['*'] = s:paste['+']
+ return 'doitclient'
+endfunction
+
+function! s:set_win32yank() abort
+ if has('wsl') && getftype(exepath('win32yank.exe')) == 'link'
+ let win32yank = resolve(exepath('win32yank.exe'))
+ else
+ let win32yank = 'win32yank.exe'
+ endif
+ let s:copy['+'] = [win32yank, '-i', '--crlf']
+ let s:paste['+'] = [win32yank, '-o', '--lf']
+ let s:copy['*'] = s:copy['+']
+ let s:paste['*'] = s:paste['+']
+ return 'win32yank'
+endfunction
+
+function! s:set_putclip() abort
+ let s:copy['+'] = ['putclip']
+ let s:paste['+'] = ['getclip']
+ let s:copy['*'] = s:copy['+']
+ let s:paste['*'] = s:paste['+']
+ return 'putclip'
+endfunction
+
+function! s:set_clip() abort
+ let s:copy['+'] = ['clip']
+ let s:paste['+'] = ['powershell', '-NoProfile', '-NoLogo', '-Command', 'Get-Clipboard']
+ let s:copy['*'] = s:copy['+']
+ let s:paste['*'] = s:paste['+']
+ return 'clip'
+endfunction
+
+function! s:set_termux() abort
+ let s:copy['+'] = ['termux-clipboard-set']
+ let s:paste['+'] = ['termux-clipboard-get']
+ let s:copy['*'] = s:copy['+']
+ let s:paste['*'] = s:paste['+']
+ return 'termux-clipboard'
+endfunction
+
+function! s:set_tmux() abort
+ let tmux_v = v:lua.vim.version.parse(system(['tmux', '-V']))
+ if !empty(tmux_v) && !v:lua.vim.version.lt(tmux_v, [3,2,0])
+ let s:copy['+'] = ['tmux', 'load-buffer', '-w', '-']
+ else
+ let s:copy['+'] = ['tmux', 'load-buffer', '-']
+ endif
+ let s:paste['+'] = ['tmux', 'save-buffer', '-']
+ let s:copy['*'] = s:copy['+']
+ let s:paste['*'] = s:paste['+']
+ return 'tmux'
+endfunction
+
let s:cache_enabled = 1
let s:err = ''
@@ -78,9 +185,34 @@ function! provider#clipboard#Executable() abort
" Setting g:clipboard to v:false explicitly opts-in to using the "builtin" clipboard providers below
if exists('g:clipboard') && g:clipboard isnot# v:false
if v:t_string ==# type(g:clipboard)
+ " Handle string form of g:clipboard for all builtin providers
if 'osc52' == g:clipboard
" User opted-in to OSC 52 by manually setting g:clipboard.
return s:set_osc52()
+ elseif 'pbcopy' == g:clipboard
+ return s:set_pbcopy()
+ elseif 'wl-copy' == g:clipboard
+ return s:set_wayland()
+ elseif 'wayclip' == g:clipboard
+ return s:set_wayclip()
+ elseif 'xsel' == g:clipboard
+ return s:set_xsel()
+ elseif 'xclip' == g:clipboard
+ return s:set_xclip()
+ elseif 'lemonade' == g:clipboard
+ return s:set_lemonade()
+ elseif 'doitclient' == g:clipboard
+ return s:set_doitclient()
+ elseif 'win32yank' == g:clipboard
+ return s:set_win32yank()
+ elseif 'putclip' == g:clipboard
+ return s:set_putclip()
+ elseif 'clip' == g:clipboard
+ return s:set_clip()
+ elseif 'termux' == g:clipboard
+ return s:set_termux()
+ elseif 'tmux' == g:clipboard
+ return s:set_tmux()
endif
endif
@@ -102,88 +234,29 @@ function! provider#clipboard#Executable() abort
let s:cache_enabled = get(g:clipboard, 'cache_enabled', 0)
return get(g:clipboard, 'name', 'g:clipboard')
elseif has('mac')
- let s:copy['+'] = ['pbcopy']
- let s:paste['+'] = ['pbpaste']
- let s:copy['*'] = s:copy['+']
- let s:paste['*'] = s:paste['+']
- let s:cache_enabled = 0
- return 'pbcopy'
+ return s:set_pbcopy()
elseif !empty($WAYLAND_DISPLAY) && executable('wl-copy') && executable('wl-paste')
- let s:copy['+'] = ['wl-copy', '--type', 'text/plain']
- let s:paste['+'] = ['wl-paste', '--no-newline']
- let s:copy['*'] = ['wl-copy', '--primary', '--type', 'text/plain']
- let s:paste['*'] = ['wl-paste', '--no-newline', '--primary']
- return 'wl-copy'
+ return s:set_wayland()
elseif !empty($WAYLAND_DISPLAY) && executable('waycopy') && executable('waypaste')
- let s:copy['+'] = ['waycopy', '-t', 'text/plain']
- let s:paste['+'] = ['waypaste', '-t', 'text/plain']
- let s:copy['*'] = s:copy['+']
- let s:paste['*'] = s:paste['+']
- return 'wayclip'
+ return s:set_wayclip()
elseif !empty($DISPLAY) && executable('xsel') && s:cmd_ok('xsel -o -b')
- let s:copy['+'] = ['xsel', '--nodetach', '-i', '-b']
- let s:paste['+'] = ['xsel', '-o', '-b']
- let s:copy['*'] = ['xsel', '--nodetach', '-i', '-p']
- let s:paste['*'] = ['xsel', '-o', '-p']
- return 'xsel'
+ return s:set_xsel()
elseif !empty($DISPLAY) && executable('xclip')
- let s:copy['+'] = ['xclip', '-quiet', '-i', '-selection', 'clipboard']
- let s:paste['+'] = ['xclip', '-o', '-selection', 'clipboard']
- let s:copy['*'] = ['xclip', '-quiet', '-i', '-selection', 'primary']
- let s:paste['*'] = ['xclip', '-o', '-selection', 'primary']
- return 'xclip'
+ return s:set_xclip()
elseif executable('lemonade')
- let s:copy['+'] = ['lemonade', 'copy']
- let s:paste['+'] = ['lemonade', 'paste']
- let s:copy['*'] = ['lemonade', 'copy']
- let s:paste['*'] = ['lemonade', 'paste']
- return 'lemonade'
+ return s:set_lemonade()
elseif executable('doitclient')
- let s:copy['+'] = ['doitclient', 'wclip']
- let s:paste['+'] = ['doitclient', 'wclip', '-r']
- let s:copy['*'] = s:copy['+']
- let s:paste['*'] = s:paste['+']
- return 'doitclient'
+ return s:set_doitclient()
elseif executable('win32yank.exe')
- if has('wsl') && getftype(exepath('win32yank.exe')) == 'link'
- let win32yank = resolve(exepath('win32yank.exe'))
- else
- let win32yank = 'win32yank.exe'
- endif
- let s:copy['+'] = [win32yank, '-i', '--crlf']
- let s:paste['+'] = [win32yank, '-o', '--lf']
- let s:copy['*'] = s:copy['+']
- let s:paste['*'] = s:paste['+']
- return 'win32yank'
+ return s:set_win32yank()
elseif executable('putclip') && executable('getclip')
- let s:copy['+'] = ['putclip']
- let s:paste['+'] = ['getclip']
- let s:copy['*'] = s:copy['+']
- let s:paste['*'] = s:paste['+']
- return 'putclip'
+ return s:set_putclip()
elseif executable('clip') && executable('powershell')
- let s:copy['+'] = ['clip']
- let s:paste['+'] = ['powershell', '-NoProfile', '-NoLogo', '-Command', 'Get-Clipboard']
- let s:copy['*'] = s:copy['+']
- let s:paste['*'] = s:paste['+']
- return 'clip'
+ return s:set_clip()
elseif executable('termux-clipboard-set')
- let s:copy['+'] = ['termux-clipboard-set']
- let s:paste['+'] = ['termux-clipboard-get']
- let s:copy['*'] = s:copy['+']
- let s:paste['*'] = s:paste['+']
- return 'termux-clipboard'
+ return s:set_termux()
elseif executable('tmux') && (!empty($TMUX) || 0 == jobwait([jobstart(['tmux', 'list-buffers'])], 2000)[0])
- let tmux_v = v:lua.vim.version.parse(system(['tmux', '-V']))
- if !empty(tmux_v) && !v:lua.vim.version.lt(tmux_v, [3,2,0])
- let s:copy['+'] = ['tmux', 'load-buffer', '-w', '-']
- else
- let s:copy['+'] = ['tmux', 'load-buffer', '-']
- endif
- let s:paste['+'] = ['tmux', 'save-buffer', '-']
- let s:copy['*'] = s:copy['+']
- let s:paste['*'] = s:paste['+']
- return 'tmux'
+ return s:set_tmux()
elseif get(get(g:, 'termfeatures', {}), 'osc52') && &clipboard ==# ''
" Don't use OSC 52 when 'clipboard' is set. It can be slow and cause a lot
" of user prompts. Users can opt-in to it by setting g:clipboard manually.
diff --git a/runtime/doc/diagnostic.txt b/runtime/doc/diagnostic.txt
index 2b891bde1b..efdfd2bfc6 100644
--- a/runtime/doc/diagnostic.txt
+++ b/runtime/doc/diagnostic.txt
@@ -574,8 +574,8 @@ Lua module: vim.diagnostic *diagnostic-api*
*vim.diagnostic.Opts.Signs*
Fields: ~
- • {severity}? (`vim.diagnostic.SeverityFilter`) Only show virtual text
- for diagnostics matching the given severity
+ • {severity}? (`vim.diagnostic.SeverityFilter`) Only show signs for
+ diagnostics matching the given severity
|diagnostic-severity|
• {priority}? (`integer`, default: `10`) Base priority to use for
signs. When {severity_sort} is used, the priority of a
@@ -607,6 +607,9 @@ Lua module: vim.diagnostic *diagnostic-api*
*vim.diagnostic.Opts.VirtualLines*
Fields: ~
+ • {severity}? (`vim.diagnostic.SeverityFilter`) Only show virtual
+ lines for diagnostics matching the given severity
+ |diagnostic-severity|
• {current_line}? (`boolean`, default: `false`) Only show diagnostics
for the current line.
• {format}? (`fun(diagnostic:vim.Diagnostic): string?`) A
diff --git a/runtime/doc/lua.txt b/runtime/doc/lua.txt
index be118cf790..c580c55a5e 100644
--- a/runtime/doc/lua.txt
+++ b/runtime/doc/lua.txt
@@ -640,6 +640,12 @@ vim.hl.range({bufnr}, {ns}, {higroup}, {start}, {finish}, {opts})
• {timeout}? (`integer`, default: -1 no timeout) Time in ms
before highlight is cleared
+ Return (multiple): ~
+ (`uv.uv_timer_t?`) range_timer A timer which manages how much time the
+ highlight has left
+ (`fun()?`) range_clear A function which allows clearing the highlight
+ manually. nil is returned if timeout is not specified
+
==============================================================================
VIM.DIFF *vim.diff*
diff --git a/runtime/doc/news.txt b/runtime/doc/news.txt
index eee39f81f5..72d394dd68 100644
--- a/runtime/doc/news.txt
+++ b/runtime/doc/news.txt
@@ -104,7 +104,7 @@ The following new features were added.
API
-• todo
+• |vim.hl.range()| now allows multiple timed highlights
DEFAULTS
@@ -138,6 +138,8 @@ OPTIONS
• 'winborder' add bold style.
+• |g:clipboard| accepts a string name to force any builtin clipboard tool.
+
PERFORMANCE
• todo
diff --git a/runtime/doc/provider.txt b/runtime/doc/provider.txt
index 7a4cc0ee7d..4f7807f721 100644
--- a/runtime/doc/provider.txt
+++ b/runtime/doc/provider.txt
@@ -240,6 +240,27 @@ The "copy" function stores a list of lines and the register type. The "paste"
function returns the clipboard as a `[lines, regtype]` list, where `lines` is
a list of lines and `regtype` is a register type conforming to |setreg()|.
+Nvim also supports setting g:clipboard to a string to use a builtin clipboard provider:
+
+ - "tmux" - Use tmux clipboard
+ - "xclip" - Use xclip for X11 clipboard
+ - "xsel" - Use xsel for X11 clipboard
+ - "wl-copy" - Use Wayland clipboard with wl-copy/wl-paste
+ - "wayclip" - Use Wayland clipboard with waycopy/waypaste
+ - "lemonade" - Use lemonade clipboard (for SSH)
+ - "doitclient" - Use doitclient clipboard (for SSH)
+ - "win32yank" - Use win32yank clipboard (for Windows)
+ - "clip" - Use clip/powershell clipboard (for Windows)
+ - "putclip" - Use putclip/getclip clipboard (for Windows/Cygwin)
+ - "termux" - Use Termux clipboard
+ - "pbcopy" - Use macOS clipboard
+ - "osc52" - Use OSC 52 sequence
+
+Example: >vim
+ let g:clipboard = 'tmux'
+
+This is equivalent to using the full dictionary configuration for tmux shown above.
+
*clipboard-wsl*
For Windows WSL, try this g:clipboard definition:
>vim
diff --git a/runtime/ftplugin/dax.vim b/runtime/ftplugin/dax.vim
new file mode 100644
index 0000000000..e5783f03a3
--- /dev/null
+++ b/runtime/ftplugin/dax.vim
@@ -0,0 +1,16 @@
+" Vim filetype plugin
+" Language: Data Analysis Expressions (DAX)
+" Maintainer: Anarion Dunedain <anarion80@gmail.com>
+" Last Change: 2025 Apr 2
+
+if exists('b:did_ftplugin')
+ finish
+endif
+
+let b:did_ftplugin = 1
+
+setlocal comments=sO:*\ -,mO:*\ \ ,exO:*/,s1:/*,mb:*,ex:*/,://
+
+setlocal commentstring=//\ %s
+
+let b:undo_ftplugin = 'setl com< cms<'
diff --git a/runtime/lua/vim/diagnostic.lua b/runtime/lua/vim/diagnostic.lua
index c52b42b382..6e91a27512 100644
--- a/runtime/lua/vim/diagnostic.lua
+++ b/runtime/lua/vim/diagnostic.lua
@@ -241,6 +241,10 @@ end
--- @class vim.diagnostic.Opts.VirtualLines
---
+--- Only show virtual lines for diagnostics matching the given
+--- severity |diagnostic-severity|
+--- @field severity? vim.diagnostic.SeverityFilter
+---
--- Only show diagnostics for the current line.
--- (default: `false`)
--- @field current_line? boolean
@@ -252,7 +256,7 @@ end
--- @class vim.diagnostic.Opts.Signs
---
---- Only show virtual text for diagnostics matching the given
+--- Only show signs for diagnostics matching the given
--- severity |diagnostic-severity|
--- @field severity? vim.diagnostic.SeverityFilter
---
diff --git a/runtime/lua/vim/filetype.lua b/runtime/lua/vim/filetype.lua
index a35a1a32b3..caa937aa83 100644
--- a/runtime/lua/vim/filetype.lua
+++ b/runtime/lua/vim/filetype.lua
@@ -380,6 +380,7 @@ local extension = {
dat = detect.dat,
Dat = detect.dat,
DAT = detect.dat,
+ dax = 'dax',
dcd = 'dcd',
decl = detect.decl,
dec = detect.decl,
diff --git a/runtime/lua/vim/hl.lua b/runtime/lua/vim/hl.lua
index a2b06c9727..d15ee1fd10 100644
--- a/runtime/lua/vim/hl.lua
+++ b/runtime/lua/vim/hl.lua
@@ -17,9 +17,6 @@ M.priorities = {
user = 200,
}
-local range_timer --- @type uv.uv_timer_t?
-local range_hl_clear --- @type fun()?
-
--- @class vim.hl.range.Opts
--- @inlinedoc
---
@@ -47,6 +44,10 @@ local range_hl_clear --- @type fun()?
---@param start integer[]|string Start of region as a (line, column) tuple or string accepted by |getpos()|
---@param finish integer[]|string End of region as a (line, column) tuple or string accepted by |getpos()|
---@param opts? vim.hl.range.Opts
+--- @return uv.uv_timer_t? range_timer A timer which manages how much time the
+--- highlight has left
+--- @return fun()? range_clear A function which allows clearing the highlight manually.
+--- nil is returned if timeout is not specified
function M.range(bufnr, ns, higroup, start, finish, opts)
opts = opts or {}
local regtype = opts.regtype or 'v'
@@ -108,38 +109,38 @@ function M.range(bufnr, ns, higroup, start, finish, opts)
end
end
- if range_timer and not range_timer:is_closing() then
- range_timer:close()
- assert(range_hl_clear)
- range_hl_clear()
- end
-
- range_hl_clear = function()
- range_timer = nil
- range_hl_clear = nil
- pcall(vim.api.nvim_buf_clear_namespace, bufnr, ns, 0, -1)
- pcall(vim.api.nvim__ns_set, { wins = {} })
- end
-
+ local extmarks = {} --- @type integer[]
for _, res in ipairs(region) do
local start_row = res[1][2] - 1
local start_col = res[1][3] - 1
local end_row = res[2][2] - 1
local end_col = res[2][3]
- api.nvim_buf_set_extmark(bufnr, ns, start_row, start_col, {
- hl_group = higroup,
- end_row = end_row,
- end_col = end_col,
- priority = priority,
- strict = false,
- })
+ table.insert(
+ extmarks,
+ api.nvim_buf_set_extmark(bufnr, ns, start_row, start_col, {
+ hl_group = higroup,
+ end_row = end_row,
+ end_col = end_col,
+ priority = priority,
+ strict = false,
+ })
+ )
+ end
+
+ local range_hl_clear = function()
+ for _, mark in ipairs(extmarks) do
+ api.nvim_buf_del_extmark(bufnr, ns, mark)
+ end
end
if timeout ~= -1 then
- range_timer = vim.defer_fn(range_hl_clear, timeout)
+ local range_timer = vim.defer_fn(range_hl_clear, timeout)
+ return range_timer, range_hl_clear
end
end
+local yank_timer --- @type uv.uv_timer_t?
+local yank_hl_clear --- @type fun()?
local yank_ns = api.nvim_create_namespace('nvim.hlyank')
--- Highlight the yanked text during a |TextYankPost| event.
@@ -179,8 +180,14 @@ function M.on_yank(opts)
local bufnr = vim.api.nvim_get_current_buf()
local winid = vim.api.nvim_get_current_win()
+ if yank_timer and not yank_timer:is_closing() then
+ yank_timer:close()
+ assert(yank_hl_clear)
+ yank_hl_clear()
+ end
+
vim.api.nvim__ns_set(yank_ns, { wins = { winid } })
- M.range(bufnr, yank_ns, higroup, "'[", "']", {
+ yank_timer, yank_hl_clear = M.range(bufnr, yank_ns, higroup, "'[", "']", {
regtype = event.regtype,
inclusive = true,
priority = opts.priority or M.priorities.user,
diff --git a/runtime/syntax/dax.vim b/runtime/syntax/dax.vim
new file mode 100644
index 0000000000..12e54ee1f5
--- /dev/null
+++ b/runtime/syntax/dax.vim
@@ -0,0 +1,151 @@
+" Vim syntax file
+" Language: Data Analysis Expressions (DAX)
+" Maintainer: Anarion Dunedain <anarion80@gmail.com>
+" Last Change:
+" 2025 Mar 28 First version
+
+" quit when a syntax file was already loaded
+if exists("b:current_syntax")
+ finish
+endif
+let s:keepcpo = &cpo
+set cpo&vim
+
+" There are DAX functions with dot in the name (like VARX.S)
+setlocal iskeyword+=.
+" DAX is case insensitive
+syn case ignore
+
+" DAX statements
+syn keyword daxStatement DEFINE EVALUATE MEASURE RETURN VAR
+syn match daxStatement "ORDER\ BY"
+syn match daxStatement "START\ AT"
+
+" TODO
+syn keyword daxTodo FIXME NOTE TODO OPTIMIZE XXX HACK contained
+
+" DAX functions
+syn keyword daxFunction
+ \ ABS ACCRINT ACCRINTM ACOS ACOSH ACOT ACOTH
+ \ ADDCOLUMNS ADDMISSINGITEMS ALL ALLCROSSFILTERED ALLEXCEPT ALLNOBLANKROW ALLSELECTED
+ \ AMORDEGRC AMORLINC AND APPROXIMATEDISTINCTCOUNT ASIN ASINH ATAN
+ \ ATANH AVERAGE AVERAGEA AVERAGEX BETA.DIST BETA.INV BITAND
+ \ BITLSHIFT BITOR BITRSHIFT BITXOR BLANK CALCULATE CALCULATETABLE
+ \ CALENDAR CALENDARAUTO CEILING CHISQ.DIST CHISQ.DIST.RT CHISQ.INV CHISQ.INV.RT
+ \ CLOSINGBALANCEMONTH CLOSINGBALANCEQUARTER CLOSINGBALANCEYEAR COALESCE COLUMNSTATISTICS COMBIN COMBINA
+ \ COMBINEVALUES CONCATENATE CONCATENATEX CONFIDENCE.NORM CONFIDENCE.T CONTAINSROW
+ \ CONTAINSSTRING CONTAINSSTRINGEXACT CONVERT COS COSH COT COTH
+ \ COUNT COUNTA COUNTAX COUNTBLANK COUNTROWS COUNTX COUPDAYBS
+ \ COUPDAYS COUPDAYSNC COUPNCD COUPNUM COUPPCD CROSSFILTER CROSSJOIN
+ \ CUMIPMT CUMPRINC CURRENCY CURRENTGROUP CUSTOMDATA DATATABLE DATE
+ \ DATEADD DATEDIFF DATESBETWEEN DATESINPERIOD DATESMTD DATESQTD DATESYTD
+ \ DATEVALUE DAY DB DDB DEGREES DETAILROWS DISC
+ \ DISTINCT column DISTINCT table DISTINCTCOUNT DISTINCTCOUNTNOBLANK DIVIDE DOLLARDE DOLLARFR
+ \ DURATION EARLIER EARLIEST EDATE EFFECT ENDOFMONTH ENDOFQUARTER
+ \ ENDOFYEAR EOMONTH ERROR EVALUATEANDLOG EVEN EXACT EXCEPT
+ \ EXP EXPON.DIST FACT FALSE FILTER FILTERS FIND
+ \ FIRST FIRSTDATE FIXED FLOOR FORMAT FV GCD
+ \ GENERATE GENERATEALL GENERATESERIES GEOMEAN GEOMEANX GROUPBY HASONEFILTER
+ \ HASONEVALUE HOUR IF IF.EAGER IFERROR IGNORE INDEX
+ \ INFO.ALTERNATEOFDEFINITIONS INFO.ANNOTATIONS INFO.ATTRIBUTEHIERARCHIES INFO.ATTRIBUTEHIERARCHYSTORAGES INFO.CALCDEPENDENCY INFO.CALCULATIONGROUPS INFO.CALCULATIONITEMS
+ \ INFO.CATALOGS INFO.CHANGEDPROPERTIES INFO.COLUMNPARTITIONSTORAGES INFO.COLUMNPERMISSIONS INFO.COLUMNS INFO.COLUMNSTORAGES INFO.CSDLMETADATA
+ \ INFO.CULTURES INFO.DATACOVERAGEDEFINITIONS INFO.DATASOURCES INFO.DELTATABLEMETADATASTORAGES INFO.DEPENDENCIES INFO.DETAILROWSDEFINITIONS INFO.DICTIONARYSTORAGES
+ \ INFO.EXCLUDEDARTIFACTS INFO.EXPRESSIONS INFO.EXTENDEDPROPERTIES INFO.FORMATSTRINGDEFINITIONS INFO.FUNCTIONS INFO.GENERALSEGMENTMAPSEGMENTMETADATASTORAGES INFO.GROUPBYCOLUMNS
+ \ INFO.HIERARCHIES INFO.HIERARCHYSTORAGES INFO.KPIS INFO.LEVELS INFO.LINGUISTICMETADATA INFO.MEASURES INFO.MODEL
+ \ INFO.OBJECTTRANSLATIONS INFO.PARQUETFILESTORAGES INFO.PARTITIONS INFO.PARTITIONSTORAGES INFO.PERSPECTIVECOLUMNS INFO.PERSPECTIVEHIERARCHIES INFO.PERSPECTIVEMEASURES
+ \ INFO.PERSPECTIVES INFO.PERSPECTIVETABLES INFO.PROPERTIES INFO.QUERYGROUPS INFO.REFRESHPOLICIES INFO.RELATEDCOLUMNDETAILS INFO.RELATIONSHIPINDEXSTORAGES
+ \ INFO.RELATIONSHIPS INFO.RELATIONSHIPSTORAGES INFO.ROLEMEMBERSHIPS INFO.ROLES INFO.SEGMENTMAPSTORAGES INFO.SEGMENTSTORAGES INFO.STORAGEFILES
+ \ INFO.STORAGEFOLDERS INFO.STORAGETABLECOLUMNS INFO.STORAGETABLECOLUMNSEGMENTS INFO.STORAGETABLES INFO.TABLEPERMISSIONS INFO.TABLES INFO.TABLESTORAGES
+ \ INFO.VARIATIONS INFO.VIEW.COLUMNS INFO.VIEW.MEASURES INFO.VIEW.RELATIONSHIPS INFO.VIEW.TABLES INT INTERSECT
+ \ INTRATE IPMT ISAFTER ISBLANK ISCROSSFILTERED ISEMPTY ISERROR
+ \ ISEVEN ISFILTERED ISINSCOPE ISLOGICAL ISNONTEXT ISNUMBER ISO.CEILING
+ \ ISODD ISONORAFTER ISPMT ISSELECTEDMEASURE ISSUBTOTAL ISTEXT KEEPFILTERS
+ \ LAST LASTDATE LCM LEFT LEN LINEST LINESTX
+ \ LN LOG LOG10 LOOKUPVALUE LOWER MATCHBY MAX
+ \ MAXA MAXX MDURATION MEDIAN MEDIANX MID MIN
+ \ MINA MINUTE MINX MOD MONTH MOVINGAVERAGE MROUND
+ \ NATURALINNERJOIN NATURALLEFTOUTERJOIN NETWORKDAYS NEXT NEXTDAY NEXTMONTH NEXTQUARTER
+ \ NEXTYEAR NOMINAL NONVISUAL NORM.DIST NORM.INV NORM.S.DIST NORM.S.INV
+ \ NOT NOW NPER ODD ODDFPRICE ODDFYIELD ODDLPRICE
+ \ ODDLYIELD OFFSET OPENINGBALANCEMONTH OPENINGBALANCEQUARTER OPENINGBALANCEYEAR OR ORDERBY
+ \ PARALLELPERIOD PARTITIONBY PATH PATHCONTAINS PATHITEM PATHITEMREVERSE PATHLENGTH
+ \ PDURATION PERCENTILE.EXC PERCENTILE.INC PERCENTILEX.EXC PERCENTILEX.INC PERMUT PI
+ \ PMT POISSON.DIST POWER PPMT PREVIOUS PREVIOUSDAY PREVIOUSMONTH
+ \ PREVIOUSQUARTER PREVIOUSYEAR PRICE PRICEDISC PRICEMAT PRODUCT PRODUCTX
+ \ PV QUARTER QUOTIENT RADIANS RAND RANDBETWEEN RANGE
+ \ RANK RANK.EQ RANKX RATE RECEIVED RELATED RELATEDTABLE
+ \ REMOVEFILTERS REPLACE REPT RIGHT ROLLUP ROLLUPADDISSUBTOTAL ROLLUPGROUP
+ \ ROLLUPISSUBTOTAL ROUND ROUNDDOWN ROUNDUP ROW ROWNUMBER RRI
+ \ RUNNINGSUM SAMEPERIODLASTYEAR SAMPLE SEARCH SECOND SELECTCOLUMNS SELECTEDMEASURE
+ \ SELECTEDMEASUREFORMATSTRING SELECTEDMEASURENAME SELECTEDVALUE SIGN SIN SINH SLN
+ \ SQRT SQRTPI STARTOFMONTH STARTOFQUARTER STARTOFYEAR STDEV.P STDEV.S
+ \ STDEVX.P STDEVX.S SUBSTITUTE SUBSTITUTEWITHINDEX SUM SUMMARIZE SUMMARIZECOLUMNS
+ \ SUMX SWITCH SYD T.DIST T.DIST.2T T.DIST.RT T.INV
+ \ T.INV.2t TAN TANH TBILLEQ TBILLPRICE TBILLYIELD TIME
+ \ TIMEVALUE TOCSV TODAY TOJSON TOPN TOTALMTD TOTALQTD
+ \ TOTALYTD TREATAS TRIM TRUE TRUNC Table Constructor UNICHAR
+ \ UNICODE UNION UPPER USERCULTURE USERELATIONSHIP USERNAME USEROBJECTID
+ \ USERPRINCIPALNAME UTCNOW UTCTODAY VALUE VALUES VAR.P VAR.S
+ \ VARX.P VARX.S VDB WEEKDAY WEEKNUM WINDOW XIRR
+ \ XNPV YEAR YEARFRAC YIELD YIELDDISC YIELDMAT
+
+" CONTAINS is a vim syntax keyword and can't be a defined keyword
+syn match daxFunction "CONTAINS"
+
+" Numbers
+" integer number, or floating point number without a dot.
+syn match daxNumber "\<\d\+\>"
+" floating point number, with dot
+syn match daxNumber "\<\d\+\.\d*\>"
+
+syn match daxFloat "[-+]\=\<\d\+[eE][\-+]\=\d\+"
+syn match daxFloat "[-+]\=\<\d\+\.\d*\([eE][\-+]\=\d\+\)\="
+syn match daxFloat "[-+]\=\<\.\d\+\([eE][\-+]\=\d\+\)\="
+
+" String and Character constants
+syn region daxString start=+"+ end=+"+
+
+" DAX Table and Column names
+syn region daxTable start=+'+ms=s+1 end=+'+me=e-1
+syn region daxColumn matchgroup=daxParen start=/\[/ end=/\]/
+
+" Operators
+syn match daxOperator "+"
+syn match daxOperator "-"
+syn match daxOperator "*"
+syn match daxOperator "/"
+syn match daxOperator "\^"
+syn match daxOperator "\ NOT(\s\|\\)"
+syn match daxOperator "\ IN\ "
+syn match daxOperator "&&"
+syn match daxOperator "&"
+syn match daxOperator "\\|\\|"
+syn match daxOperator "[<>]=\="
+syn match daxOperator "<>"
+syn match daxOperator "="
+syn match daxOperator ">"
+syn match daxOperator "<"
+
+" Comments
+syn region daxComment start="\(^\|\s\)\//" end="$" contains=daxTodo
+syn region daxComment start="/\*" end="\*/" contains=daxTodo
+
+" Define highlighting
+hi def link daxComment Comment
+hi def link daxNumber Number
+hi def link daxFloat Float
+hi def link daxString String
+hi def link daxStatement Keyword
+hi def link daxOperator Operator
+hi def link daxFunction Function
+hi def link daxTable Number
+hi def link daxColumn Statement
+hi def link daxParen Delimiter
+hi def link daxTodo Todo
+
+let b:current_syntax = "dax"
+
+let &cpo = s:keepcpo
+unlet! s:keepcpo
+
+" vim: ts=8
diff --git a/test/functional/lua/hl_spec.lua b/test/functional/lua/hl_spec.lua
index 12be01e0a5..f17442912a 100644
--- a/test/functional/lua/hl_spec.lua
+++ b/test/functional/lua/hl_spec.lua
@@ -139,6 +139,80 @@ describe('vim.hl.range', function()
|
]])
end)
+
+ it('shows multiple highlights with different timeouts simultaneously', function()
+ local timeout1 = 300
+ local timeout2 = 600
+ exec_lua(function()
+ local ns = vim.api.nvim_create_namespace('')
+ vim.hl.range(0, ns, 'Search', { 0, 0 }, { 4, 0 }, { timeout = timeout1 })
+ vim.hl.range(0, ns, 'Search', { 2, 6 }, { 3, 5 }, { timeout = timeout2 })
+ end)
+ screen:expect({
+ grid = [[
+ {10:^asdfghjkl}{100:$} |
+ {10:«口=口»}{100:$} |
+ {10:qwertyuiop}{100:$} |
+ {10:口口=口口}{1:$} |
+ zxcvbnm{1:$} |
+ |
+ ]],
+ timeout = timeout1 / 3,
+ })
+ screen:expect({
+ grid = [[
+ ^asdfghjkl{1:$} |
+ «口=口»{1:$} |
+ qwerty{10:uiop}{100:$} |
+ {10:口口}=口口{1:$} |
+ zxcvbnm{1:$} |
+ |
+ ]],
+ timeout = timeout1 + ((timeout2 - timeout1) / 3),
+ })
+ screen:expect([[
+ ^asdfghjkl{1:$} |
+ «口=口»{1:$} |
+ qwertyuiop{1:$} |
+ 口口=口口{1:$} |
+ zxcvbnm{1:$} |
+ |
+ ]])
+ end)
+
+ it('allows cancelling a highlight that has not timed out', function()
+ exec_lua(function()
+ local timeout = 3000
+ local range_timer
+ local range_hl_clear
+ local ns = vim.api.nvim_create_namespace('')
+ range_timer, range_hl_clear = vim.hl.range(
+ 0,
+ ns,
+ 'Search',
+ { 0, 0 },
+ { 4, 0 },
+ { timeout = timeout }
+ )
+ if range_timer and not range_timer:is_closing() then
+ range_timer:close()
+ assert(range_hl_clear)
+ range_hl_clear()
+ range_hl_clear() -- Exercise redundant call
+ end
+ end)
+ screen:expect({
+ grid = [[
+ ^asdfghjkl{1:$} |
+ «口=口»{1:$} |
+ qwertyuiop{1:$} |
+ 口口=口口{1:$} |
+ zxcvbnm{1:$} |
+ |
+ ]],
+ unchanged = true,
+ })
+ end)
end)
describe('vim.hl.on_yank', function()
@@ -184,9 +258,9 @@ describe('vim.hl.on_yank', function()
eq({ win }, api.nvim__ns_get(ns).wins)
command('wincmd w')
eq({ win }, api.nvim__ns_get(ns).wins)
- -- Use a new vim.hl.range() call to cancel the previous timer
+ -- Use a new vim.hl.on_yank() call to cancel the previous timer
exec_lua(function()
- vim.hl.range(0, ns, 'Search', { 0, 0 }, { 0, 0 }, { timeout = 0 })
+ vim.hl.on_yank({ timeout = 0, on_macro = true, event = { operator = 'y' } })
end)
end)
@@ -209,9 +283,9 @@ describe('vim.hl.on_yank', function()
eq({ win }, api.nvim__ns_get(ns).wins)
command('wincmd w')
eq({ win }, api.nvim__ns_get(ns).wins)
- -- Use a new vim.hl.range() call to cancel the previous timer
+ -- Use a new vim.hl.on_yank() call to cancel the previous timer
exec_lua(function()
- vim.hl.range(0, ns, 'Search', { 0, 0 }, { 0, 0 }, { timeout = 0 })
+ vim.hl.on_yank({ timeout = 0, on_macro = true, event = { operator = 'y' } })
end)
end)
@@ -246,5 +320,9 @@ describe('vim.hl.on_yank', function()
{1:~ }|
|
]])
+ -- Use a new vim.hl.on_yank() call to cancel the previous timer
+ exec_lua(function()
+ vim.hl.on_yank({ timeout = 0, on_macro = true, event = { operator = 'y' } })
+ end)
end)
end)
diff --git a/test/functional/lua/secure_spec.lua b/test/functional/lua/secure_spec.lua
index cd3549fc8a..db83787588 100644
--- a/test/functional/lua/secure_spec.lua
+++ b/test/functional/lua/secure_spec.lua
@@ -38,7 +38,7 @@ describe('vim.secure', function()
end)
it('works', function()
- local screen = Screen.new(80, 8)
+ local screen = Screen.new(500, 8)
screen:set_default_attr_ids({
[1] = { bold = true, foreground = Screen.colors.Blue1 },
[2] = { bold = true, reverse = true },
@@ -46,129 +46,99 @@ describe('vim.secure', function()
[4] = { reverse = true },
})
- --- XXX: screen:expect() may fail if this path is too long.
local cwd = fn.getcwd()
+ if #cwd + 23 > 500 then
+ pending('path too long')
+ return
+ end
-- Need to use feed_command instead of exec_lua because of the confirmation prompt
feed_command([[lua vim.secure.read('Xfile')]])
- screen:expect {
- grid = [[
- |
- {1:~ }|*3
- {2: }|
- :lua vim.secure.read('Xfile') |
- {3:]]
- .. cwd
- .. pathsep
- .. [[Xfile is not trusted.}{MATCH:%s+}|
- {3:[i]gnore, (v)iew, (d)eny, (a)llow: }^ |
- ]],
- }
+ screen:expect([[
+ {MATCH: +}|
+ {1:~{MATCH: +}}|*3
+ {2:{MATCH: +}}|
+ :lua vim.secure.read('Xfile'){MATCH: +}|
+ {3:]] .. cwd .. pathsep .. [[Xfile is not trusted.}{MATCH: +}|
+ {3:[i]gnore, (v)iew, (d)eny, (a)llow: }^{MATCH: +}|
+ ]])
feed('d')
- screen:expect {
- grid = [[
- ^ |
- {1:~ }|*6
- |
- ]],
- }
+ screen:expect([[
+ ^{MATCH: +}|
+ {1:~{MATCH: +}}|*6
+ {MATCH: +}|
+ ]])
- local trust = read_file(stdpath('state') .. pathsep .. 'trust')
+ local trust = assert(read_file(stdpath('state') .. pathsep .. 'trust'))
eq(string.format('! %s', cwd .. pathsep .. 'Xfile'), vim.trim(trust))
eq(vim.NIL, exec_lua([[return vim.secure.read('Xfile')]]))
os.remove(stdpath('state') .. pathsep .. 'trust')
feed_command([[lua vim.secure.read('Xfile')]])
- screen:expect {
- grid = [[
- |
- {1:~ }|*3
- {2: }|
- :lua vim.secure.read('Xfile') |
- {3:]]
- .. cwd
- .. pathsep
- .. [[Xfile is not trusted.}{MATCH:%s+}|
- {3:[i]gnore, (v)iew, (d)eny, (a)llow: }^ |
- ]],
- }
+ screen:expect([[
+ {MATCH: +}|
+ {1:~{MATCH: +}}|*3
+ {2:{MATCH: +}}|
+ :lua vim.secure.read('Xfile'){MATCH: +}|
+ {3:]] .. cwd .. pathsep .. [[Xfile is not trusted.}{MATCH: +}|
+ {3:[i]gnore, (v)iew, (d)eny, (a)llow: }^{MATCH: +}|
+ ]])
feed('a')
- screen:expect {
- grid = [[
- ^ |
- {1:~ }|*6
- |
- ]],
- }
-
- local hash = fn.sha256(read_file('Xfile'))
- trust = read_file(stdpath('state') .. pathsep .. 'trust')
+ screen:expect([[
+ ^{MATCH: +}|
+ {1:~{MATCH: +}}|*6
+ {MATCH: +}|
+ ]])
+
+ local hash = fn.sha256(assert(read_file('Xfile')))
+ trust = assert(read_file(stdpath('state') .. pathsep .. 'trust'))
eq(string.format('%s %s', hash, cwd .. pathsep .. 'Xfile'), vim.trim(trust))
eq(vim.NIL, exec_lua([[vim.secure.read('Xfile')]]))
os.remove(stdpath('state') .. pathsep .. 'trust')
feed_command([[lua vim.secure.read('Xfile')]])
- screen:expect {
- grid = [[
- |
- {1:~ }|*3
- {2: }|
- :lua vim.secure.read('Xfile') |
- {3:]]
- .. cwd
- .. pathsep
- .. [[Xfile is not trusted.}{MATCH:%s+}|
- {3:[i]gnore, (v)iew, (d)eny, (a)llow: }^ |
- ]],
- }
+ screen:expect([[
+ {MATCH: +}|
+ {1:~{MATCH: +}}|*3
+ {2:{MATCH: +}}|
+ :lua vim.secure.read('Xfile'){MATCH: +}|
+ {3:]] .. cwd .. pathsep .. [[Xfile is not trusted.}{MATCH: +}|
+ {3:[i]gnore, (v)iew, (d)eny, (a)llow: }^{MATCH: +}|
+ ]])
feed('i')
- screen:expect {
- grid = [[
- ^ |
- {1:~ }|*6
- |
- ]],
- }
+ screen:expect([[
+ ^{MATCH: +}|
+ {1:~{MATCH: +}}|*6
+ {MATCH: +}|
+ ]])
-- Trust database is not updated
- trust = read_file(stdpath('state') .. pathsep .. 'trust')
- eq(nil, trust)
+ eq(nil, read_file(stdpath('state') .. pathsep .. 'trust'))
feed_command([[lua vim.secure.read('Xfile')]])
- screen:expect {
- grid = [[
- |
- {1:~ }|*3
- {2: }|
- :lua vim.secure.read('Xfile') |
- {3:]]
- .. cwd
- .. pathsep
- .. [[Xfile is not trusted.}{MATCH:%s+}|
- {3:[i]gnore, (v)iew, (d)eny, (a)llow: }^ |
- ]],
- }
+ screen:expect([[
+ {MATCH: +}|
+ {1:~{MATCH: +}}|*3
+ {2:{MATCH: +}}|
+ :lua vim.secure.read('Xfile'){MATCH: +}|
+ {3:]] .. cwd .. pathsep .. [[Xfile is not trusted.}{MATCH: +}|
+ {3:[i]gnore, (v)iew, (d)eny, (a)llow: }^{MATCH: +}|
+ ]])
feed('v')
- screen:expect {
- grid = [[
- ^let g:foobar = 42 |
- {1:~ }|*2
- {2:]]
- .. fn.fnamemodify(cwd, ':~')
- .. pathsep
- .. [[Xfile [RO]{MATCH:%s+}}|
- |
- {1:~ }|
- {4:[No Name] }|
- |
- ]],
- }
+ screen:expect([[
+ ^let g:foobar = 42{MATCH: +}|
+ {1:~{MATCH: +}}|*2
+ {2:]] .. fn.fnamemodify(cwd, ':~') .. pathsep .. [[Xfile [RO]{MATCH: +}}|
+ {MATCH: +}|
+ {1:~{MATCH: +}}|
+ {4:[No Name]{MATCH: +}}|
+ {MATCH: +}|
+ ]])
-- Trust database is not updated
- trust = read_file(stdpath('state') .. pathsep .. 'trust')
- eq(nil, trust)
+ eq(nil, read_file(stdpath('state') .. pathsep .. 'trust'))
-- Cannot write file
pcall_err(command, 'write')
diff --git a/test/functional/plugin/shada_spec.lua b/test/functional/plugin/shada_spec.lua
index f33819f364..ca005d9f12 100644
--- a/test/functional/plugin/shada_spec.lua
+++ b/test/functional/plugin/shada_spec.lua
@@ -3170,8 +3170,8 @@ describe('syntax/shada.vim', function()
month = htsnum(os.date('%m', 0)),
day = htsnum(os.date('%d', 0)),
hour = htsnum(os.date('!%H', 0)),
- minute = htsnum(os.date('%M', 0)),
- second = htsnum(os.date('%S', 0)),
+ minute = htsnum(os.date('!%M', 0)),
+ second = htsnum(os.date('!%S', 0)),
}
local msh = function(s)
return {
diff --git a/test/old/testdir/test_filetype.vim b/test/old/testdir/test_filetype.vim
index 4e54ff598f..8347178f79 100644
--- a/test/old/testdir/test_filetype.vim
+++ b/test/old/testdir/test_filetype.vim
@@ -213,6 +213,7 @@ func s:GetFilenameChecks() abort
\ 'dafny': ['file.dfy'],
\ 'dart': ['file.dart', 'file.drt'],
\ 'datascript': ['file.ds'],
+ \ 'dax': ['file.dax'],
\ 'dcd': ['file.dcd'],
\ 'deb822sources': ['/etc/apt/sources.list.d/file.sources', 'any/etc/apt/sources.list.d/file.sources'],
\ 'debchangelog': ['changelog.Debian', 'changelog.dch', 'NEWS.Debian', 'NEWS.dch', '/debian/changelog'],