aboutsummaryrefslogtreecommitdiff
path: root/runtime/lua/vim
diff options
context:
space:
mode:
Diffstat (limited to 'runtime/lua/vim')
-rw-r--r--runtime/lua/vim/_editor.lua17
-rw-r--r--runtime/lua/vim/filetype.lua86
-rw-r--r--runtime/lua/vim/filetype/detect.lua413
-rw-r--r--runtime/lua/vim/lsp.lua5
-rw-r--r--runtime/lua/vim/lsp/diagnostic.lua42
-rw-r--r--runtime/lua/vim/lsp/log.lua81
-rw-r--r--runtime/lua/vim/lsp/util.lua2
7 files changed, 550 insertions, 96 deletions
diff --git a/runtime/lua/vim/_editor.lua b/runtime/lua/vim/_editor.lua
index 8e372b806c..119467de16 100644
--- a/runtime/lua/vim/_editor.lua
+++ b/runtime/lua/vim/_editor.lua
@@ -58,6 +58,7 @@ vim.log = {
INFO = 2;
WARN = 3;
ERROR = 4;
+ OFF = 5;
}
}
@@ -735,6 +736,22 @@ function vim._cs_remote(rcid, server_addr, connect_error, args)
}
end
+--- Display a deprecation notification to the user.
+---
+---@param name string Deprecated function.
+---@param alternative string|nil Preferred alternative function.
+---@param version string Version in which the deprecated function will
+--- be removed.
+---@param plugin string|nil Plugin name that the function will be removed
+--- from. Defaults to "Nvim".
+function vim.deprecate(name, alternative, version, plugin)
+ local message = name .. ' is deprecated'
+ plugin = plugin or "Nvim"
+ message = alternative and (message .. ', use ' .. alternative .. ' instead.') or message
+ message = message .. ' See :h deprecated\nThis function will be removed in ' .. plugin .. ' version ' .. version
+ vim.notify_once(message, vim.log.levels.WARN)
+end
+
require('vim._meta')
return vim
diff --git a/runtime/lua/vim/filetype.lua b/runtime/lua/vim/filetype.lua
index 911950171f..32f4f825c1 100644
--- a/runtime/lua/vim/filetype.lua
+++ b/runtime/lua/vim/filetype.lua
@@ -784,19 +784,19 @@ local extension = {
zsh = "zsh",
vala = "vala",
E = function() vim.fn["dist#ft#FTe"]() end,
- EU = function() vim.fn["dist#ft#EuphoriaCheck"]() end,
- EW = function() vim.fn["dist#ft#EuphoriaCheck"]() end,
- EX = function() vim.fn["dist#ft#EuphoriaCheck"]() end,
- EXU = function() vim.fn["dist#ft#EuphoriaCheck"]() end,
- EXW = function() vim.fn["dist#ft#EuphoriaCheck"]() end,
+ EU = function(path, bufnr) return require("vim.filetype.detect").euphoria(bufnr) end,
+ EW = function(path, bufnr) return require("vim.filetype.detect").euphoria(bufnr) end,
+ EX = function(path, bufnr) return require("vim.filetype.detect").euphoria(bufnr) end,
+ EXU = function(path, bufnr) return require("vim.filetype.detect").euphoria(bufnr) end,
+ EXW = function(path, bufnr) return require("vim.filetype.detect").euphoria(bufnr) end,
PL = function() vim.fn["dist#ft#FTpl"]() end,
- R = function() vim.fn["dist#ft#FTr"]() end,
+ R = function(path, bufnr) require("vim.filetype.detect").r(bufnr) end,
asm = function() vim.fn["dist#ft#FTasm"]() end,
bas = function() vim.fn["dist#ft#FTbas"]() end,
bi = function() vim.fn["dist#ft#FTbas"]() end,
bm = function() vim.fn["dist#ft#FTbas"]() end,
bash = function() vim.fn["dist#ft#SetFileTypeSH"]("bash") end,
- btm = function() vim.fn["dist#ft#FTbtm"]() end,
+ btm = function(path, bufnr) return require("vim.filetype.detect").btm(bufnr) end,
c = function() vim.fn["dist#ft#FTlpc"]() end,
ch = function() vim.fn["dist#ft#FTchange"]() end,
com = function() vim.fn["dist#ft#BindzoneCheck"]('dcl') end,
@@ -808,29 +808,29 @@ local extension = {
e = function() vim.fn["dist#ft#FTe"]() end,
ebuild = function() vim.fn["dist#ft#SetFileTypeSH"]("bash") end,
eclass = function() vim.fn["dist#ft#SetFileTypeSH"]("bash") end,
- ent = function() vim.fn["dist#ft#FTent"]() end,
+ ent = function(path, bufnr) return require("vim.filetype.detect").ent(bufnr) end,
env = function() vim.fn["dist#ft#SetFileTypeSH"](vim.fn.getline(1)) end,
- eu = function() vim.fn["dist#ft#EuphoriaCheck"]() end,
- ew = function() vim.fn["dist#ft#EuphoriaCheck"]() end,
- ex = function() vim.fn["dist#ft#ExCheck"]() end,
- exu = function() vim.fn["dist#ft#EuphoriaCheck"]() end,
- exw = function() vim.fn["dist#ft#EuphoriaCheck"]() end,
- frm = function() vim.fn["dist#ft#FTfrm"]() end,
+ eu = function(path, bufnr) return require("vim.filetype.detect").euphoria(bufnr) end,
+ ew = function(path, bufnr) return require("vim.filetype.detect").euphoria(bufnr) end,
+ ex = function(path, bufnr) return require("vim.filetype.detect").ex(bufnr) end,
+ exu = function(path, bufnr) return require("vim.filetype.detect").euphoria(bufnr) end,
+ exw = function(path, bufnr) return require("vim.filetype.detect").euphoria(bufnr) end,
+ frm = function(path, bufnr) require("vim.filetype.detect").frm(bufnr) end,
fs = function() vim.fn["dist#ft#FTfs"]() end,
- h = function() vim.fn["dist#ft#FTheader"]() end,
+ h = function(path, bufnr) require("vim.filetype.detect").header(bufnr) end,
htm = function() vim.fn["dist#ft#FThtml"]() end,
html = function() vim.fn["dist#ft#FThtml"]() end,
i = function() vim.fn["dist#ft#FTprogress_asm"]() end,
- idl = function() vim.fn["dist#ft#FTidl"]() end,
+ idl = function(path, bufnr) require("vim.filetype.detect").idl(bufnr) end,
inc = function() vim.fn["dist#ft#FTinc"]() end,
- inp = function() vim.fn["dist#ft#Check_inp"]() end,
+ inp = function(path, bufnr) require("vim.filetype.detect").inp(bufnr) end,
ksh = function() vim.fn["dist#ft#SetFileTypeSH"]("ksh") end,
lst = function() vim.fn["dist#ft#FTasm"]() end,
m = function() vim.fn["dist#ft#FTm"]() end,
mac = function() vim.fn["dist#ft#FTasm"]() end,
- mc = function() vim.fn["dist#ft#McSetf"]() end,
+ mc = function(path, bufnr) require("vim.filetype.detect").mc(bufnr) end,
mm = function() vim.fn["dist#ft#FTmm"]() end,
- mms = function() vim.fn["dist#ft#FTmms"]() end,
+ mms = function(path, bufnr) require("vim.filetype.detect").mms(bufnr) end,
p = function() vim.fn["dist#ft#FTprogress_pascal"]() end,
patch = function(path, bufnr)
local firstline = getline(bufnr, 1)
@@ -844,22 +844,22 @@ local extension = {
pp = function() vim.fn["dist#ft#FTpp"]() end,
pro = function() vim.fn["dist#ft#ProtoCheck"]('idlang') end,
pt = function() vim.fn["dist#ft#FThtml"]() end,
- r = function() vim.fn["dist#ft#FTr"]() end,
- rdf = function() vim.fn["dist#ft#Redif"]() end,
+ r = function(path, bufnr) require("vim.filetype.detect").r(bufnr) end,
+ rdf = function(path, bufnr) require("vim.filetype.detect").redif(bufnr) end,
rules = function() vim.fn["dist#ft#FTRules"]() end,
- sc = function() vim.fn["dist#ft#FTsc"]() end,
- scd = function() vim.fn["dist#ft#FTscd"]() end,
+ sc = function(path, bufnr) require("vim.filetype.detect").sc(bufnr) end,
+ scd = function(path, bufnr) require("vim.filetype.detect").scd(bufnr) end,
sh = function() vim.fn["dist#ft#SetFileTypeSH"](vim.fn.getline(1)) end,
shtml = function() vim.fn["dist#ft#FThtml"]() end,
- sql = function() vim.fn["dist#ft#SQL"]() end,
+ sql = function(path, bufnr) require("vim.filetype.detect").sql(bufnr) end,
stm = function() vim.fn["dist#ft#FThtml"]() end,
tcsh = function() vim.fn["dist#ft#SetFileTypeShell"]("tcsh") end,
tex = function() vim.fn["dist#ft#FTtex"]() end,
- tf = function() vim.fn["dist#ft#FTtf"]() end,
- w = function() vim.fn["dist#ft#FTprogress_cweb"]() end,
- xml = function() vim.fn["dist#ft#FTxml"]() end,
- y = function() vim.fn["dist#ft#FTy"]() end,
- zsql = function() vim.fn["dist#ft#SQL"]() end,
+ tf = function(path, bufnr) require("vim.filetype.detect").tf(bufnr) end,
+ w = function(path, bufnr) require("vim.filetype.detect").progress_cweb(bufnr) end,
+ xml = function(path, bufnr) require("vim.filetype.detect").xml(bufnr) end,
+ y = function(path, bufnr) require("vim.filetype.detect").y(bufnr) end,
+ zsql = function(path, bufnr) require("vim.filetype.detect").sql(bufnr) end,
txt = function(path, bufnr)
--helpfiles match *.txt, but should have a modeline as last line
if not getline(bufnr, -1):match("vim:.*ft=help") then
@@ -933,10 +933,10 @@ local filename = {
["exim.conf"] = "exim",
exports = "exports",
[".fetchmailrc"] = "fetchmail",
- fvSchemes = function() vim.fn["dist#ft#FTfoam"]() end,
- fvSolution = function() vim.fn["dist#ft#FTfoam"]() end,
- fvConstraints = function() vim.fn["dist#ft#FTfoam"]() end,
- fvModels = function() vim.fn["dist#ft#FTfoam"]() end,
+ fvSchemes = function(path, bufnr) require("vim.filetype.detect").foam(bufnr) end,
+ fvSolution = function(path, bufnr) require("vim.filetype.detect").foam(bufnr) end,
+ fvConstraints = function(path, bufnr) require("vim.filetype.detect").foam(bufnr) end,
+ fvModels = function(path, bufnr) require("vim.filetype.detect").foam(bufnr) end,
fstab = "fstab",
mtab = "fstab",
[".gdbinit"] = "gdb",
@@ -1355,7 +1355,7 @@ local pattern = {
["%.zcompdump.*"] = starsetf('zsh'),
["%.zlog.*"] = starsetf('zsh'),
["%.zsh.*"] = starsetf('zsh'),
- [".*%.[1-9]"] = function() vim.fn["dist#ft#FTnroff"]() end,
+ [".*%.[1-9]"] = function(path, bufnr) return require("vim.filetype.detect").nroff(bufnr) end,
[".*%.[aA]"] = function() vim.fn["dist#ft#FTasm"]() end,
[".*%.[sS]"] = function() vim.fn["dist#ft#FTasm"]() end,
[".*%.properties_.._.._.*"] = starsetf('jproperties'),
@@ -1434,14 +1434,14 @@ local pattern = {
["mutt" .. string.rep("[%w_-]", 6)] = "mail",
["neomutt" .. string.rep("[%w_-]", 6)] = "mail",
["/tmp/SLRN[0-9A-Z.]+"] = "mail",
- ["[a-zA-Z0-9].*Dict"] = function() vim.fn["dist#ft#FTfoam"]() end,
- ["[a-zA-Z0-9].*Dict%..*"] = function() vim.fn["dist#ft#FTfoam"]() end,
- ["[a-zA-Z].*Properties"] = function() vim.fn["dist#ft#FTfoam"]() end,
- ["[a-zA-Z].*Properties%..*"] = function() vim.fn["dist#ft#FTfoam"]() end,
- [".*Transport%..*"] = function() vim.fn["dist#ft#FTfoam"]() end,
- [".*/constant/g"] = function() vim.fn["dist#ft#FTfoam"]() end,
- [".*/0/.*"] = function() vim.fn["dist#ft#FTfoam"]() end,
- [".*/0%.orig/.*"] = function() vim.fn["dist#ft#FTfoam"]() end,
+ ["[a-zA-Z0-9].*Dict"] = function(path, bufnr) require("vim.filetype.detect").foam(bufnr) end,
+ ["[a-zA-Z0-9].*Dict%..*"] = function(path, bufnr) require("vim.filetype.detect").foam(bufnr) end,
+ ["[a-zA-Z].*Properties"] = function(path, bufnr) require("vim.filetype.detect").foam(bufnr) end,
+ ["[a-zA-Z].*Properties%..*"] = function(path, bufnr) require("vim.filetype.detect").foam(bufnr) end,
+ [".*Transport%..*"] = function(path, bufnr) require("vim.filetype.detect").foam(bufnr) end,
+ [".*/constant/g"] = function(path, bufnr) require("vim.filetype.detect").foam(bufnr) end,
+ [".*/0/.*"] = function(path, bufnr) require("vim.filetype.detect").foam(bufnr) end,
+ [".*/0%.orig/.*"] = function(path, bufnr) require("vim.filetype.detect").foam(bufnr) end,
[".*/etc/sensors%.d/[^.].*"] = starsetf('sensors'),
[".*%.git/.*"] = function(path, bufnr)
local firstline = getline(bufnr, 1)
@@ -1490,7 +1490,7 @@ local function normalize_path(path, as_pattern)
if as_pattern then
-- Escape Lua's metacharacters when $HOME is used in a pattern.
-- The rest of path should already be properly escaped.
- normal = vim.env.HOME:gsub('[-^$()%%.%[%]+?]', '%%%0') .. normal:sub(2)
+ normal = vim.pesc(vim.env.HOME) .. normal:sub(2)
else
normal = vim.env.HOME .. normal:sub(2)
end
diff --git a/runtime/lua/vim/filetype/detect.lua b/runtime/lua/vim/filetype/detect.lua
new file mode 100644
index 0000000000..787b335251
--- /dev/null
+++ b/runtime/lua/vim/filetype/detect.lua
@@ -0,0 +1,413 @@
+local M = {}
+
+---@private
+local function getlines(bufnr, start_lnum, end_lnum, opts)
+ if not end_lnum then
+ -- Return a single line as a string
+ return vim.api.nvim_buf_get_lines(bufnr, start_lnum - 1, start_lnum, false)[1]
+ end
+
+ local lines = vim.api.nvim_buf_get_lines(bufnr, start_lnum - 1, end_lnum, false)
+ opts = opts or {}
+ return opts.concat and (table.concat(lines) or "") or lines
+end
+
+---@private
+local function findany(s, patterns)
+ for _, v in ipairs(patterns) do
+ if s:find(v) then
+ return true
+ end
+ end
+ return false
+end
+
+-- luacheck: push no unused args
+-- luacheck: push ignore 122
+
+function M.asm(path, bufnr) end
+
+function M.asm_syntax(path, bufnr) end
+
+function M.bas(path, bufnr) end
+
+function M.bindzone(path, bufnr) end
+
+function M.btm(bufnr)
+ if vim.g.dosbatch_syntax_for_btm and vim.g.dosbatch_syntax_for_btm ~= 0 then
+ vim.bo[bufnr].filetype = "dosbatch"
+ else
+ vim.bo[bufnr].filetype = "btm"
+ end
+end
+
+-- Returns true if file content looks like RAPID
+local function is_rapid(bufnr, extension)
+ if extension == "cfg" then
+ local line = getlines(bufnr, 1):lower()
+ return findany(line, { "eio:cfg", "mmc:cfg", "moc:cfg", "proc:cfg", "sio:cfg", "sys:cfg" })
+ end
+ local first = "^%s*module%s+%S+%s*"
+ -- Called from mod, prg or sys functions
+ for _, line in ipairs(getlines(bufnr, 1, -1)) do
+ if not line:find("^%s*$") then
+ return findany(line:lower(), { "^%s*%%%%%%", first .. "(", first .. "$" })
+ end
+ end
+ -- Only found blank lines
+ return false
+end
+
+function M.cfg(bufnr)
+ if vim.g.filetype_cfg then
+ vim.bo[bufnr].filetype = vim.g.filetype_cfg
+ elseif is_rapid(bufnr, "cfg") then
+ vim.bo[bufnr].filetype = "rapid"
+ else
+ vim.bo[bufnr].filetype = "cfg"
+ end
+end
+
+function M.change(path, bufnr) end
+
+function M.csh(path, bufnr) end
+
+function M.dat(path, bufnr) end
+
+function M.dep3patch(path, bufnr) end
+
+function M.dtrace(path, bufnr) end
+
+function M.e(path, bufnr) end
+
+-- This function checks for valid cl syntax in the first five lines.
+-- Look for either an opening comment, '#', or a block start, '{'.
+-- If not found, assume SGML.
+function M.ent(bufnr)
+ for _, line in ipairs(getlines(bufnr, 1, 5)) do
+ if line:find("^%s*[#{]") then
+ vim.bo[bufnr].filetype = "cl"
+ return
+ elseif not line:find("^%s*$") then
+ -- Not a blank line, not a comment, and not a block start,
+ -- so doesn't look like valid cl code.
+ break
+ end
+ end
+ vim.bo[bufnr].filetype = "dtd"
+end
+
+function M.euphoria(bufnr)
+ if vim.g.filetype_euphoria then
+ vim.bo[bufnr].filetype = vim.g.filetype_euphoria
+ else
+ vim.bo[bufnr].filetype = "euphoria3"
+ end
+end
+
+function M.ex(bufnr)
+ if vim.g.filetype_euphoria then
+ vim.bo[bufnr].filetype = vim.g.filetype_euphoria
+ else
+ for _, line in ipairs(getlines(bufnr, 1, 100)) do
+ -- TODO: in the Vim regex, \> is used to match the end of the word, can this be omitted?
+ if findany(line, { "^%-%-", "^ifdef", "^include" }) then
+ vim.bo[bufnr].filetype = "euphoria3"
+ return
+ end
+ end
+ vim.bo[bufnr].filetype = "elixir"
+ end
+end
+
+-- This function checks the first 15 lines for appearance of 'FoamFile'
+-- and then 'object' in a following line.
+-- In that case, it's probably an OpenFOAM file
+function M.foam(bufnr)
+ local foam_file = false
+ for _, line in ipairs(getlines(bufnr, 1, 15)) do
+ if line:find("^FoamFile") then
+ foam_file = true
+ elseif foam_file and line:find("^%s*object") then
+ vim.bo[bufnr].filetype = "foam"
+ return
+ end
+ end
+end
+
+function M.frm(bufnr)
+ if vim.g.filetype_frm then
+ vim.bo[bufnr].filetype = vim.g.filetype_frm
+ else
+ -- Always ignore case
+ local lines = getlines(bufnr, 1, 5, { concat = true }):lower()
+ if findany(lines, { "vb_name", "begin vb%.form", "begin vb%.mdiform" }) then
+ vim.bo[bufnr].filetype = "vb"
+ else
+ vim.bo[bufnr].filetype = "form"
+ end
+ end
+end
+
+function M.fs(path, bufnr) end
+
+function M.header(bufnr)
+ for _, line in ipairs(getlines(bufnr, 1, 200)) do
+ if findany(line, { "^@interface", "^@end", "^@class" }) then
+ if vim.g.c_syntax_for_h then
+ vim.bo[bufnr].filetype = "objc"
+ else
+ vim.bo[bufnr].filetype = "objcpp"
+ end
+ return
+ end
+ end
+ if vim.g.c_syntax_for_h then
+ vim.bo[bufnr].filetype = "c"
+ elseif vim.g.ch_syntax_for_h then
+ vim.bo[bufnr].filetype = "ch"
+ else
+ vim.bo[bufnr].filetype = "cpp"
+ end
+end
+
+function M.idl(bufnr)
+ for _, line in ipairs(getlines(bufnr, 1, 50)) do
+ -- Always ignore case
+ line = line:lower()
+ if findany(line, { '^%s*import%s+"unknwn"%.idl', '^%s*import%s+"objidl"%.idl' }) then
+ vim.bo[bufnr].filetype = "msidl"
+ return
+ end
+ end
+ vim.bo[bufnr].filetype = "idl"
+end
+
+function M.inc(path, bufnr) end
+
+function M.inp(bufnr)
+ if getlines(bufnr, 1):find("^%*") then
+ vim.bo[bufnr].filetype = "abaqus"
+ else
+ for _, line in ipairs(getlines(bufnr, 1, 500)) do
+ if line:lower():find("^header surface data") then
+ vim.bo[bufnr].filetype = "trasys"
+ return
+ end
+ end
+ end
+end
+
+function M.lpc(path, bufnr) end
+
+function M.lprolog(path, bufnr) end
+
+function M.m(path, bufnr) end
+
+-- Rely on the file to start with a comment.
+-- MS message text files use ';', Sendmail files use '#' or 'dnl'
+function M.mc(bufnr)
+ for _, line in ipairs(getlines(bufnr, 1, 20)) do
+ if findany(line:lower(), { "^%s*#", "^%s*dnl" }) then
+ -- Sendmail .mc file
+ vim.bo[bufnr].filetype = "m4"
+ return
+ elseif line:find("^%s*;") then
+ vim.bo[bufnr].filetype = "msmessages"
+ return
+ end
+ end
+ -- Default: Sendmail .mc file
+ vim.bo[bufnr].filetype = "m4"
+end
+
+function M.mm(path, bufnr) end
+
+function M.mms(bufnr)
+ for _, line in ipairs(getlines(bufnr, 1, 20)) do
+ if findany(line, { "^%s*%%", "^%s*//", "^%*" }) then
+ vim.bo[bufnr].filetype = "mmix"
+ return
+ elseif line:find("^%s*#") then
+ vim.bo[bufnr].filetype = "make"
+ return
+ end
+ end
+ vim.bo[bufnr].filetype = "mmix"
+end
+
+function M.mod(path, bufnr) end
+
+-- This function checks if one of the first five lines start with a dot. In
+-- that case it is probably an nroff file: 'filetype' is set and 1 is returned.
+function M.nroff(bufnr)
+ for _, line in ipairs(getlines(bufnr, 1, 5)) do
+ if line:find("^%.") then
+ vim.bo[bufnr].filetype = "nroff"
+ return 1
+ end
+ end
+ return 0
+end
+
+function M.perl(path, bufnr) end
+
+function M.pl(path, bufnr) end
+
+function M.pp(path, bufnr) end
+
+function M.prg(path, bufnr) end
+
+function M.progress_asm(path, bufnr) end
+
+function M.progress_cweb(bufnr)
+ if vim.g.filetype_w then
+ vim.bo[bufnr].filetype = vim.g.filetype_w
+ else
+ if getlines(bufnr, 1):find("^&ANALYZE") or getlines(bufnr, 3):find("^&GLOBAL%-DEFINE") then
+ vim.bo[bufnr].filetype = "progress"
+ else
+ vim.bo[bufnr].filetype = "cweb"
+ end
+ end
+end
+
+function M.progress_pascal(path, bufnr) end
+
+function M.proto(path, bufnr) end
+
+function M.r(bufnr)
+ local lines = getlines(bufnr, 1, 50)
+ -- TODO: \< / \> which match the beginning / end of a word
+ -- Rebol is easy to recognize, check for that first
+ if table.concat(lines):lower():find("rebol") then
+ vim.bo[bufnr].filetype = "rebol"
+ return
+ end
+
+ for _, line in ipairs(lines) do
+ -- R has # comments
+ if line:find("^%s*#") then
+ vim.bo[bufnr].filetype = "r"
+ return
+ end
+ -- Rexx has /* comments */
+ if line:find("^%s*/%*") then
+ vim.bo[bufnr].filetype = "rexx"
+ return
+ end
+ end
+
+ -- Nothing recognized, use user default or assume R
+ if vim.g.filetype_r then
+ vim.bo[bufnr].filetype = vim.g.filetype_r
+ else
+ -- Rexx used to be the default, but R appears to be much more popular.
+ vim.bo[bufnr].filetype = "r"
+ end
+end
+
+function M.redif(bufnr)
+ for _, line in ipairs(getlines(bufnr, 1, 5)) do
+ if line:lower():find("^template%-type:") then
+ vim.bo[bufnr].filetype = "redif"
+ end
+ end
+end
+
+function M.rules(path, bufnr) end
+
+-- This function checks the first 25 lines of file extension "sc" to resolve
+-- detection between scala and SuperCollider
+function M.sc(bufnr)
+ for _, line in ipairs(getlines(bufnr, 1, 25)) do
+ if findany(line, { "[A-Za-z0-9]*%s:%s[A-Za-z0-9]", "var%s<", "classvar%s<", "%^this.*", "|%w*|", "%+%s%w*%s{", "%*ar%s" }) then
+ vim.bo[bufnr].filetype = "supercollider"
+ return
+ end
+ end
+ vim.bo[bufnr].filetype = "scala"
+end
+
+-- This function checks the first line of file extension "scd" to resolve
+-- detection between scdoc and SuperCollider
+function M.scd(bufnr)
+ local first = "^%S+%(%d[0-9A-Za-z]*%)"
+ local opt = [[%s+"[^"]*"]]
+ local line = getlines(bufnr, 1)
+ if findany(line, { first .. "$", first .. opt .. "$", first .. opt .. opt .. "$" }) then
+ vim.bo[bufnr].filetype = "scdoc"
+ else
+ vim.bo[bufnr].filetype = "supercollider"
+ end
+end
+
+function M.sh(path, bufnr) end
+
+function M.shell(path, bufnr) end
+
+function M.sql(bufnr)
+ if vim.g.filetype_sql then
+ vim.bo[bufnr].filetype = vim.g.filetype_sql
+ else
+ vim.bo[bufnr].filetype = "sql"
+ end
+end
+
+function M.src(path, bufnr) end
+
+function M.sys(path, bufnr) end
+
+function M.tex(path, bufnr) end
+
+-- Determine if a *.tf file is TF mud client or terraform
+function M.tf(bufnr)
+ for _, line in ipairs(getlines(bufnr, 1, -1)) do
+ -- Assume terraform file on a non-empty line (not whitespace-only)
+ -- and when the first non-whitespace character is not a ; or /
+ if not line:find("^%s*$") and not line:find("^%s*[;/]") then
+ vim.bo[bufnr].filetype = "terraform"
+ return
+ end
+ end
+ vim.bo[bufnr].filetype = "tf"
+end
+
+function M.xml(bufnr)
+ for _, line in ipairs(getlines(bufnr, 1, 100)) do
+ line = line:lower()
+ local is_docbook4 = line:find("<!doctype.*docbook")
+ local is_docbook5 = line:find([[ xmlns="http://docbook.org/ns/docbook"]])
+ if is_docbook4 or is_docbook5 then
+ vim.b[bufnr].docbk_type = "xml"
+ vim.b[bufnr].docbk_ver = is_docbook4 and 4 or 5
+ vim.bo[bufnr].filetype = "docbk"
+ return
+ end
+ if line:find([[xmlns:xbl="http://www.mozilla.org/xbl"]]) then
+ vim.bo[bufnr].filetype = "xbl"
+ return
+ end
+ end
+ vim.bo[bufnr].filetype = "xml"
+end
+
+function M.y(bufnr)
+ for _, line in ipairs(getlines(bufnr, 1, 100)) do
+ if line:find("^%s*%%") then
+ vim.bo[bufnr].filetype = "yacc"
+ return
+ end
+ -- TODO: in the Vim regex, \> is used to match the end of the word after "class",
+ -- can this be omitted?
+ if findany(line, { "^%s*#", "^%class", "^%s*#%s*include" }) then
+ vim.bo[bufnr].filetype = "racc"
+ end
+ end
+ vim.bo[bufnr].filetype = "yacc"
+end
+
+-- luacheck: pop
+-- luacheck: pop
+
+return M
diff --git a/runtime/lua/vim/lsp.lua b/runtime/lua/vim/lsp.lua
index 19ee75a1b6..00f1c26692 100644
--- a/runtime/lua/vim/lsp.lua
+++ b/runtime/lua/vim/lsp.lua
@@ -1790,13 +1790,14 @@ end
--
-- Can be used to lookup the number from the name or the
-- name from the number.
--- Levels by name: "TRACE", "DEBUG", "INFO", "WARN", "ERROR"
+-- Levels by name: "TRACE", "DEBUG", "INFO", "WARN", "ERROR", "OFF"
-- Level numbers begin with "TRACE" at 0
lsp.log_levels = log.levels
--- Sets the global log level for LSP logging.
---
---- Levels by name: "TRACE", "DEBUG", "INFO", "WARN", "ERROR"
+--- Levels by name: "TRACE", "DEBUG", "INFO", "WARN", "ERROR", "OFF"
+---
--- Level numbers begin with "TRACE" at 0
---
--- Use `lsp.log_levels` for reverse lookup.
diff --git a/runtime/lua/vim/lsp/diagnostic.lua b/runtime/lua/vim/lsp/diagnostic.lua
index 6a8d6dcad7..28a236cc7e 100644
--- a/runtime/lua/vim/lsp/diagnostic.lua
+++ b/runtime/lua/vim/lsp/diagnostic.lua
@@ -251,7 +251,7 @@ end
---@param client_id number
---@private
function M.save(diagnostics, bufnr, client_id)
- vim.notify_once('vim.lsp.diagnostic.save is deprecated. See :h deprecated', vim.log.levels.WARN)
+ vim.deprecate('vim.lsp.diagnostic.save', 'vim.diagnostic.set', '0.8' )
local namespace = M.get_namespace(client_id)
vim.diagnostic.set(namespace, bufnr, diagnostic_lsp_to_vim(diagnostics, bufnr, client_id))
end
@@ -265,7 +265,7 @@ end
--- If nil, diagnostics of all clients are included.
---@return table with diagnostics grouped by bufnr (bufnr: Diagnostic[])
function M.get_all(client_id)
- vim.notify_once('vim.lsp.diagnostic.get_all is deprecated. See :h deprecated', vim.log.levels.WARN)
+ vim.deprecate('vim.lsp.diagnostic.get_all', 'vim.diagnostic.get', '0.8' )
local result = {}
local namespace
if client_id then
@@ -287,7 +287,7 @@ end
--- Else, return just the diagnostics associated with the client_id.
---@param predicate function|nil Optional function for filtering diagnostics
function M.get(bufnr, client_id, predicate)
- vim.notify_once('vim.lsp.diagnostic.get is deprecated. See :h deprecated', vim.log.levels.WARN)
+ vim.deprecate('vim.lsp.diagnostic.get', 'vim.diagnostic.get', '0.8' )
predicate = predicate or function() return true end
if client_id == nil then
local all_diagnostics = {}
@@ -349,7 +349,7 @@ end
---@param severity DiagnosticSeverity
---@param client_id number the client id
function M.get_count(bufnr, severity, client_id)
- vim.notify_once('vim.lsp.diagnostic.get_count is deprecated. See :h deprecated', vim.log.levels.WARN)
+ vim.deprecate('vim.lsp.diagnostic.get_count', 'vim.diagnostic.get', '0.8' )
severity = severity_lsp_to_vim(severity)
local opts = { severity = severity }
if client_id ~= nil then
@@ -366,7 +366,7 @@ end
---@param opts table See |vim.lsp.diagnostic.goto_next()|
---@return table Previous diagnostic
function M.get_prev(opts)
- vim.notify_once('vim.lsp.diagnostic.get_prev is deprecated. See :h deprecated', vim.log.levels.WARN)
+ vim.deprecate('vim.lsp.diagnostic.get_prev', 'vim.diagnostic.get_prev', '0.8' )
if opts then
if opts.severity then
opts.severity = severity_lsp_to_vim(opts.severity)
@@ -384,7 +384,7 @@ end
---@param opts table See |vim.lsp.diagnostic.goto_next()|
---@return table Previous diagnostic position
function M.get_prev_pos(opts)
- vim.notify_once('vim.lsp.diagnostic.get_prev_pos is deprecated. See :h deprecated', vim.log.levels.WARN)
+ vim.deprecate('vim.lsp.diagnostic.get_prev_pos', 'vim.diagnostic.get_prev_pos', '0.8' )
if opts then
if opts.severity then
opts.severity = severity_lsp_to_vim(opts.severity)
@@ -401,7 +401,7 @@ end
---
---@param opts table See |vim.lsp.diagnostic.goto_next()|
function M.goto_prev(opts)
- vim.notify_once('vim.lsp.diagnostic.goto_prev is deprecated. See :h deprecated', vim.log.levels.WARN)
+ vim.deprecate('vim.lsp.diagnostic.goto_prev', 'vim.diagnostic.goto_prev', '0.8' )
if opts then
if opts.severity then
opts.severity = severity_lsp_to_vim(opts.severity)
@@ -419,7 +419,7 @@ end
---@param opts table See |vim.lsp.diagnostic.goto_next()|
---@return table Next diagnostic
function M.get_next(opts)
- vim.notify_once('vim.lsp.diagnostic.get_next is deprecated. See :h deprecated', vim.log.levels.WARN)
+ vim.deprecate('vim.lsp.diagnostic.get_next', 'vim.diagnostic.get_next', '0.8' )
if opts then
if opts.severity then
opts.severity = severity_lsp_to_vim(opts.severity)
@@ -437,7 +437,7 @@ end
---@param opts table See |vim.lsp.diagnostic.goto_next()|
---@return table Next diagnostic position
function M.get_next_pos(opts)
- vim.notify_once('vim.lsp.diagnostic.get_next_pos is deprecated. See :h deprecated', vim.log.levels.WARN)
+ vim.deprecate('vim.lsp.diagnostic.get_next_pos', 'vim.diagnostic.get_next_pos', '0.8' )
if opts then
if opts.severity then
opts.severity = severity_lsp_to_vim(opts.severity)
@@ -452,7 +452,7 @@ end
---
---@deprecated Prefer |vim.diagnostic.goto_next()|
function M.goto_next(opts)
- vim.notify_once('vim.lsp.diagnostic.goto_next is deprecated. See :h deprecated', vim.log.levels.WARN)
+ vim.deprecate('vim.lsp.diagnostic.goto_next', 'vim.diagnostic.goto_next', '0.8' )
if opts then
if opts.severity then
opts.severity = severity_lsp_to_vim(opts.severity)
@@ -476,7 +476,7 @@ end
--- - severity_limit (DiagnosticSeverity):
--- - Limit severity of diagnostics found. E.g. "Warning" means { "Error", "Warning" } will be valid.
function M.set_signs(diagnostics, bufnr, client_id, _, opts)
- vim.notify_once('vim.lsp.diagnostic.set_signs is deprecated. See :h deprecated', vim.log.levels.WARN)
+ vim.deprecate('vim.lsp.diagnostic.set_signs', nil , '0.8' )
local namespace = M.get_namespace(client_id)
if opts and not opts.severity and opts.severity_limit then
opts.severity = {min=severity_lsp_to_vim(opts.severity_limit)}
@@ -497,7 +497,7 @@ end
--- - severity_limit (DiagnosticSeverity):
--- - Limit severity of diagnostics found. E.g. "Warning" means { "Error", "Warning" } will be valid.
function M.set_underline(diagnostics, bufnr, client_id, _, opts)
- vim.notify_once('vim.lsp.diagnostic.set_underline is deprecated. See :h deprecated', vim.log.levels.WARN)
+ vim.deprecate('vim.lsp.diagnostic.set_underline', nil , '0.8' )
local namespace = M.get_namespace(client_id)
if opts and not opts.severity and opts.severity_limit then
opts.severity = {min=severity_lsp_to_vim(opts.severity_limit)}
@@ -519,7 +519,7 @@ end
--- - severity_limit (DiagnosticSeverity):
--- - Limit severity of diagnostics found. E.g. "Warning" means { "Error", "Warning" } will be valid.
function M.set_virtual_text(diagnostics, bufnr, client_id, _, opts)
- vim.notify_once('vim.lsp.diagnostic.set_virtual_text is deprecated. See :h deprecated', vim.log.levels.WARN)
+ vim.deprecate('vim.lsp.diagnostic.set_virtual_text', nil , '0.8' )
local namespace = M.get_namespace(client_id)
if opts and not opts.severity and opts.severity_limit then
opts.severity = {min=severity_lsp_to_vim(opts.severity_limit)}
@@ -538,7 +538,7 @@ end
---@return an array of [text, hl_group] arrays. This can be passed directly to
--- the {virt_text} option of |nvim_buf_set_extmark()|.
function M.get_virtual_text_chunks_for_line(bufnr, _, line_diags, opts)
- vim.notify_once('vim.lsp.diagnostic.get_virtual_text_chunks_for_line is deprecated. See :h deprecated', vim.log.levels.WARN)
+ vim.deprecate('vim.lsp.diagnostic.get_virtual_text_chunks_for_line', nil, '0.8' )
return vim.diagnostic._get_virt_text_chunks(diagnostic_lsp_to_vim(line_diags, bufnr), opts)
end
@@ -556,7 +556,7 @@ end
---@param position table|nil The (0,0)-indexed position
---@return table {popup_bufnr, win_id}
function M.show_position_diagnostics(opts, buf_nr, position)
- vim.notify_once('vim.lsp.diagnostic.show_position_diagnostics is deprecated. See :h deprecated', vim.log.levels.WARN)
+ vim.deprecate('vim.lsp.diagnostic.show_position_diagnostics', 'vim.diagnostic.open_float', '0.8' )
opts = opts or {}
opts.scope = "cursor"
opts.pos = position
@@ -580,7 +580,7 @@ end
---@param client_id number|nil the client id
---@return table {popup_bufnr, win_id}
function M.show_line_diagnostics(opts, buf_nr, line_nr, client_id)
- vim.notify_once('vim.lsp.diagnostic.show_line_diagnostics is deprecated. See :h deprecated', vim.log.levels.WARN)
+ vim.deprecate('vim.lsp.diagnostic.show_line_diagnostics', 'vim.diagnostic.open_float', '0.8' )
opts = opts or {}
opts.scope = "line"
opts.pos = line_nr
@@ -604,7 +604,7 @@ end
--- client. The default is to redraw diagnostics for all attached
--- clients.
function M.redraw(bufnr, client_id)
- vim.notify_once('vim.lsp.diagnostic.redraw is deprecated. See :h deprecated', vim.log.levels.WARN)
+ vim.deprecate('vim.lsp.diagnostic.redraw', 'vim.diagnostic.show', '0.8' )
bufnr = get_bufnr(bufnr)
if not client_id then
return vim.lsp.for_each_buffer_client(bufnr, function(client)
@@ -632,7 +632,7 @@ end
--- - {workspace}: (boolean, default true)
--- - Set the list with workspace diagnostics
function M.set_qflist(opts)
- vim.notify_once('vim.lsp.diagnostic.set_qflist is deprecated. See :h deprecated', vim.log.levels.WARN)
+ vim.deprecate('vim.lsp.diagnostic.set_qflist', 'vim.diagnostic.setqflist', '0.8' )
opts = opts or {}
if opts.severity then
opts.severity = severity_lsp_to_vim(opts.severity)
@@ -664,7 +664,7 @@ end
--- - {workspace}: (boolean, default false)
--- - Set the list with workspace diagnostics
function M.set_loclist(opts)
- vim.notify_once('vim.lsp.diagnostic.set_loclist is deprecated. See :h deprecated', vim.log.levels.WARN)
+ vim.deprecate('vim.lsp.diagnostic.set_loclist', 'vim.diagnostic.setloclist', '0.8' )
opts = opts or {}
if opts.severity then
opts.severity = severity_lsp_to_vim(opts.severity)
@@ -692,7 +692,7 @@ end
-- send diagnostic information and the client will still process it. The
-- diagnostics are simply not displayed to the user.
function M.disable(bufnr, client_id)
- vim.notify_once('vim.lsp.diagnostic.disable is deprecated. See :h deprecated', vim.log.levels.WARN)
+ vim.deprecate('vim.lsp.diagnostic.disable', 'vim.diagnostic.disable', '0.8' )
if not client_id then
return vim.lsp.for_each_buffer_client(bufnr, function(client)
M.disable(bufnr, client.id)
@@ -713,7 +713,7 @@ end
--- client. The default is to enable diagnostics for all attached
--- clients.
function M.enable(bufnr, client_id)
- vim.notify_once('vim.lsp.diagnostic.enable is deprecated. See :h deprecated', vim.log.levels.WARN)
+ vim.deprecate('vim.lsp.diagnostic.enable', 'vim.diagnostic.enable', '0.8' )
if not client_id then
return vim.lsp.for_each_buffer_client(bufnr, function(client)
M.enable(bufnr, client.id)
diff --git a/runtime/lua/vim/lsp/log.lua b/runtime/lua/vim/lsp/log.lua
index e0b5653587..fff42fd011 100644
--- a/runtime/lua/vim/lsp/log.lua
+++ b/runtime/lua/vim/lsp/log.lua
@@ -8,7 +8,7 @@ local log = {}
-- Log level dictionary with reverse lookup as well.
--
-- Can be used to lookup the number from the name or the name from the number.
--- Levels by name: "TRACE", "DEBUG", "INFO", "WARN", "ERROR"
+-- Levels by name: "TRACE", "DEBUG", "INFO", "WARN", "ERROR", "OFF"
-- Level numbers begin with "TRACE" at 0
log.levels = vim.deepcopy(vim.log.levels)
@@ -25,27 +25,47 @@ do
end
local logfilename = path_join(vim.fn.stdpath('cache'), 'lsp.log')
+ -- TODO: Ideally the directory should be created in open_logfile(), right
+ -- before opening the log file, but open_logfile() can be called from libuv
+ -- callbacks, where using fn.mkdir() is not allowed.
+ vim.fn.mkdir(vim.fn.stdpath('cache'), "p")
+
--- Returns the log filename.
---@returns (string) log filename
function log.get_filename()
return logfilename
end
- vim.fn.mkdir(vim.fn.stdpath('cache'), "p")
- local logfile = assert(io.open(logfilename, "a+"))
-
- local log_info = vim.loop.fs_stat(logfilename)
- if log_info and log_info.size > 1e9 then
- local warn_msg = string.format(
- "LSP client log is large (%d MB): %s",
- log_info.size / (1000 * 1000),
- logfilename
- )
- vim.notify(warn_msg)
+ local logfile, openerr
+ ---@private
+ --- Opens log file. Returns true if file is open, false on error
+ local function open_logfile()
+ -- Try to open file only once
+ if logfile then return true end
+ if openerr then return false end
+
+ logfile, openerr = io.open(logfilename, "a+")
+ if not logfile then
+ local err_msg = string.format("Failed to open LSP client log file: %s", openerr)
+ vim.notify(err_msg, vim.log.levels.ERROR)
+ return false
+ end
+
+ local log_info = vim.loop.fs_stat(logfilename)
+ if log_info and log_info.size > 1e9 then
+ local warn_msg = string.format(
+ "LSP client log is large (%d MB): %s",
+ log_info.size / (1000 * 1000),
+ logfilename
+ )
+ vim.notify(warn_msg)
+ end
+
+ -- Start message for logging
+ logfile:write(string.format("[START][%s] LSP logging initiated\n", os.date(log_date_format)))
+ return true
end
- -- Start message for logging
- logfile:write(string.format("[START][%s] LSP logging initiated\n", os.date(log_date_format)))
for level, levelnr in pairs(log.levels) do
-- Also export the log level on the root object.
log[level] = levelnr
@@ -63,23 +83,26 @@ do
-- ```
--
-- This way you can avoid string allocations if the log level isn't high enough.
- log[level:lower()] = function(...)
- local argc = select("#", ...)
- if levelnr < current_log_level then return false end
- if argc == 0 then return true end
- local info = debug.getinfo(2, "Sl")
- local header = string.format("[%s][%s] ...%s:%s", level, os.date(log_date_format), string.sub(info.short_src, #info.short_src - 15), info.currentline)
- local parts = { header }
- for i = 1, argc do
- local arg = select(i, ...)
- if arg == nil then
- table.insert(parts, "nil")
- else
- table.insert(parts, format_func(arg))
+ if level ~= "OFF" then
+ log[level:lower()] = function(...)
+ local argc = select("#", ...)
+ if levelnr < current_log_level then return false end
+ if argc == 0 then return true end
+ if not open_logfile() then return false end
+ local info = debug.getinfo(2, "Sl")
+ local header = string.format("[%s][%s] ...%s:%s", level, os.date(log_date_format), string.sub(info.short_src, #info.short_src - 15), info.currentline)
+ local parts = { header }
+ for i = 1, argc do
+ local arg = select(i, ...)
+ if arg == nil then
+ table.insert(parts, "nil")
+ else
+ table.insert(parts, format_func(arg))
+ end
end
+ logfile:write(table.concat(parts, '\t'), "\n")
+ logfile:flush()
end
- logfile:write(table.concat(parts, '\t'), "\n")
- logfile:flush()
end
end
end
diff --git a/runtime/lua/vim/lsp/util.lua b/runtime/lua/vim/lsp/util.lua
index 77ab1d4224..72dfb3cd76 100644
--- a/runtime/lua/vim/lsp/util.lua
+++ b/runtime/lua/vim/lsp/util.lua
@@ -456,7 +456,7 @@ function M.apply_text_edits(text_edits, bufnr, offset_encoding)
-- Remove final line if needed
local fix_eol = has_eol_text_edit
- fix_eol = fix_eol and (api.nvim_buf_get_option(bufnr, 'eol') or (api.nvim_buf_get_option(bufnr, 'fixeol') and not api.nvim_buf_get_option('binary')))
+ fix_eol = fix_eol and (api.nvim_buf_get_option(bufnr, 'eol') or (api.nvim_buf_get_option(bufnr, 'fixeol') and not api.nvim_buf_get_option(bufnr, 'binary')))
fix_eol = fix_eol and get_line(bufnr, max - 1) == ''
if fix_eol then
vim.api.nvim_buf_set_lines(bufnr, -2, -1, false, {})