mirror of
https://github.com/neovim/neovim.git
synced 2024-12-20 03:05:11 -07:00
39d70fcafd
This is the first PR featuring a conversion of an upstream vim9script file into a Lua file. The generated file can be found in `runtime/autoload/ccomplete.vim` in the vim repository. Below is a limited history of the changes of that file at the time of conversion. ``` ❯ git log --format=oneline runtime/autoload/ccomplete.vim c4573eb12dba6a062af28ee0b8938d1521934ce4 Update runtime files a4d131d11052cafcc5baad2273ef48e0dd4d09c5 Update runtime files 4466ad6baa22485abb1147aca3340cced4778a66 Update runtime files d1caa941d876181aae0ebebc6ea954045bf0da24 Update runtime files 20aac6c1126988339611576d425965a25a777658 Update runtime files. 30b658179962cc3c9f0a98f071b36b09a36c2b94 Updated runtime files. b6b046b281fac168a78b3eafdea9274bef06882f Updated runtime files. 00a927d62b68a3523cb1c4f9aa3f7683345c8182 Updated runtime files. 8c8de839325eda0bed68917d18179d2003b344d1 (tag: v7.2a) updated for version 7.2a ... ``` The file runtime/lua/_vim9script.lua only needs to be updated when vim9jit is updated (for any bug fixes or new features, like implementing class and interface, the latest in vim9script). Further PRs will improve the DX of generated the converted lua and tracking which files in the neovim's code base have been generated.
628 lines
15 KiB
Lua
628 lines
15 KiB
Lua
-------------------------------------------------------------------------------
|
|
-- This file is auto generated by vim9jit. Do not edit by hand.
|
|
-- All content is in the source repository.
|
|
-- Bugs should be reported to: github.com/tjdevries/vim9jit
|
|
--
|
|
-- In addition, this file is considered "private" by neovim. You should
|
|
-- not expect any of the APIs, functions, etc to be stable. They are subject
|
|
-- to change at any time.
|
|
-------------------------------------------------------------------------------
|
|
|
|
local vim9 = (function()
|
|
local M = {}
|
|
|
|
M.ternary = function(cond, if_true, if_false)
|
|
if cond then
|
|
if type(if_true) == 'function' then
|
|
return if_true()
|
|
else
|
|
return if_true
|
|
end
|
|
else
|
|
if type(if_false) == 'function' then
|
|
return if_false()
|
|
else
|
|
return if_false
|
|
end
|
|
end
|
|
end
|
|
|
|
M.fn_mut = function(name, args, info)
|
|
local result = vim.fn._Vim9ScriptFn(name, args)
|
|
for idx, val in pairs(result[2]) do
|
|
M.replace(args[idx], val)
|
|
end
|
|
|
|
-- Substitute returning the reference to the
|
|
-- returned value
|
|
if info.replace then
|
|
return args[info.replace + 1]
|
|
end
|
|
|
|
return result[1]
|
|
end
|
|
|
|
M.replace = function(orig, new)
|
|
if type(orig) == 'table' and type(new) == 'table' then
|
|
for k in pairs(orig) do
|
|
orig[k] = nil
|
|
end
|
|
|
|
for k, v in pairs(new) do
|
|
orig[k] = v
|
|
end
|
|
|
|
return orig
|
|
end
|
|
|
|
return new
|
|
end
|
|
|
|
M.index = function(obj, idx)
|
|
if vim.tbl_islist(obj) then
|
|
if idx < 0 then
|
|
return obj[#obj + idx + 1]
|
|
else
|
|
return obj[idx + 1]
|
|
end
|
|
elseif type(obj) == 'table' then
|
|
return obj[idx]
|
|
elseif type(obj) == 'string' then
|
|
return string.sub(obj, idx + 1, idx + 1)
|
|
end
|
|
|
|
error('invalid type for indexing: ' .. vim.inspect(obj))
|
|
end
|
|
|
|
M.index_expr = function(idx)
|
|
if type(idx) == 'string' then
|
|
return idx
|
|
elseif type(idx) == 'number' then
|
|
return idx + 1
|
|
else
|
|
error(string.format('not yet handled: %s', vim.inspect(idx)))
|
|
end
|
|
end
|
|
|
|
M.slice = function(obj, start, finish)
|
|
if start == nil then
|
|
start = 0
|
|
end
|
|
|
|
if start < 0 then
|
|
start = #obj + start
|
|
end
|
|
assert(type(start) == 'number')
|
|
|
|
if finish == nil then
|
|
finish = #obj
|
|
end
|
|
|
|
if finish < 0 then
|
|
finish = #obj + finish
|
|
end
|
|
assert(type(finish) == 'number')
|
|
|
|
local slicer
|
|
if vim.tbl_islist(obj) then
|
|
slicer = vim.list_slice
|
|
elseif type(obj) == 'string' then
|
|
slicer = string.sub
|
|
else
|
|
error('invalid type for slicing: ' .. vim.inspect(obj))
|
|
end
|
|
|
|
return slicer(obj, start + 1, finish + 1)
|
|
end
|
|
|
|
-- Currently unused, but this could be used to embed vim9jit within a
|
|
-- running nvim application and transpile "on the fly" as files are
|
|
-- sourced. There would still need to be some work done to make that
|
|
-- work correctly with imports and what not, but overall it could
|
|
-- work well for calling ":source X" from within a vimscript/vim9script
|
|
-- function
|
|
M.make_source_cmd = function()
|
|
local group = vim.api.nvim_create_augroup('vim9script-source', {})
|
|
vim.api.nvim_create_autocmd('SourceCmd', {
|
|
pattern = '*.vim',
|
|
group = group,
|
|
callback = function(a)
|
|
local file = vim.fn.readfile(a.file)
|
|
for _, line in ipairs(file) do
|
|
-- TODO: Or starts with def <something>
|
|
-- You can use def in legacy vim files
|
|
if vim.startswith(line, 'vim9script') then
|
|
-- TODO: Use the rust lib to actually
|
|
-- generate the corresponding lua code and then
|
|
-- execute that (instead of sourcing it directly)
|
|
return
|
|
end
|
|
end
|
|
|
|
vim.api.nvim_exec(table.concat(file, '\n'), false)
|
|
end,
|
|
})
|
|
end
|
|
|
|
M.iter = function(expr)
|
|
if vim.tbl_islist(expr) then
|
|
return ipairs(expr)
|
|
else
|
|
return pairs(expr)
|
|
end
|
|
end
|
|
|
|
M.ITER_DEFAULT = 0
|
|
M.ITER_CONTINUE = 1
|
|
M.ITER_BREAK = 2
|
|
M.ITER_RETURN = 3
|
|
|
|
return M
|
|
end)()
|
|
|
|
vim.cmd([[
|
|
function! _Vim9ScriptFn(name, args) abort
|
|
try
|
|
let ret = function(a:name, a:args)()
|
|
catch
|
|
echo "Failed..."
|
|
echo a:name
|
|
echo a:args
|
|
|
|
throw v:errmsg
|
|
endtry
|
|
|
|
return [ret, a:args]
|
|
endfunction
|
|
]])
|
|
|
|
vim9['autoload'] = (function()
|
|
return function(path)
|
|
return loadfile(path)()
|
|
end
|
|
end)()
|
|
vim9['bool'] = (function()
|
|
return function(...)
|
|
return vim9.convert.to_vim_bool(...)
|
|
end
|
|
end)()
|
|
vim9['convert'] = (function()
|
|
local M = {}
|
|
|
|
M.decl_bool = function(val)
|
|
if type(val) == 'boolean' then
|
|
return val
|
|
elseif type(val) == 'number' then
|
|
if val == 0 then
|
|
return false
|
|
elseif val == 1 then
|
|
return true
|
|
else
|
|
error(string.format('bad number passed to bool declaration: %s', val))
|
|
end
|
|
end
|
|
|
|
error(string.format('invalid bool declaration: %s', vim.inspect(val)))
|
|
end
|
|
|
|
M.decl_dict = function(val)
|
|
if type(val) == 'nil' then
|
|
return vim.empty_dict()
|
|
elseif type(val) == 'table' then
|
|
if vim.tbl_isempty(val) then
|
|
return vim.empty_dict()
|
|
elseif vim.tbl_islist(val) then
|
|
error(string.format('Cannot pass list to dictionary? %s', vim.inspect(val)))
|
|
else
|
|
return val
|
|
end
|
|
end
|
|
|
|
error(string.format('invalid dict declaration: %s', vim.inspect(val)))
|
|
end
|
|
|
|
M.to_vim_bool = function(val)
|
|
if type(val) == 'boolean' then
|
|
return val
|
|
elseif type(val) == 'number' then
|
|
return val ~= 0
|
|
elseif type(val) == 'string' then
|
|
return string.len(val) ~= 0
|
|
elseif type(val) == 'table' then
|
|
return not vim.tbl_isempty(val)
|
|
elseif val == nil then
|
|
return false
|
|
end
|
|
|
|
error('unhandled type: ' .. vim.inspect(val))
|
|
end
|
|
|
|
return M
|
|
end)()
|
|
vim9['fn'] = (function()
|
|
local M = {}
|
|
|
|
M.insert = function(list, item, idx)
|
|
if idx == nil then
|
|
idx = 1
|
|
end
|
|
|
|
table.insert(list, idx + 1, item)
|
|
|
|
return list
|
|
end
|
|
|
|
M.extend = function(left, right, expr3)
|
|
if expr3 ~= nil then
|
|
error("haven't written this code yet")
|
|
end
|
|
|
|
if vim.tbl_islist(right) then
|
|
vim.list_extend(left, right)
|
|
return left
|
|
else
|
|
-- local result = vim.tbl_extend(left, right)
|
|
for k, v in pairs(right) do
|
|
left[k] = v
|
|
end
|
|
|
|
return left
|
|
end
|
|
end
|
|
|
|
M.add = function(list, item)
|
|
table.insert(list, item)
|
|
return list
|
|
end
|
|
|
|
M.has_key = function(obj, key)
|
|
return not not obj[key]
|
|
end
|
|
|
|
M.prop_type_add = function(...)
|
|
local args = { ... }
|
|
print('[prop_type_add]', vim.inspect(args))
|
|
end
|
|
|
|
do
|
|
local has_overrides = {
|
|
-- We do have vim9script ;) that's this plugin
|
|
['vim9script'] = true,
|
|
|
|
-- Include some vim patches that are sometimes required by variuos vim9script plugins
|
|
-- that we implement via vim9jit
|
|
[ [[patch-8.2.2261]] ] = true,
|
|
[ [[patch-8.2.4257]] ] = true,
|
|
}
|
|
|
|
M.has = function(patch)
|
|
if has_overrides[patch] then
|
|
return true
|
|
end
|
|
|
|
return vim.fn.has(patch)
|
|
end
|
|
end
|
|
|
|
--[=[
|
|
Currently missing patch, can be removed in the future.
|
|
|
|
readdirex({directory} [, {expr} [, {dict}]]) *readdirex()*
|
|
Extended version of |readdir()|.
|
|
Return a list of Dictionaries with file and directory
|
|
information in {directory}.
|
|
This is useful if you want to get the attributes of file and
|
|
directory at the same time as getting a list of a directory.
|
|
This is much faster than calling |readdir()| then calling
|
|
|getfperm()|, |getfsize()|, |getftime()| and |getftype()| for
|
|
each file and directory especially on MS-Windows.
|
|
The list will by default be sorted by name (case sensitive),
|
|
the sorting can be changed by using the optional {dict}
|
|
argument, see |readdir()|.
|
|
|
|
The Dictionary for file and directory information has the
|
|
following items:
|
|
group Group name of the entry. (Only on Unix)
|
|
name Name of the entry.
|
|
perm Permissions of the entry. See |getfperm()|.
|
|
size Size of the entry. See |getfsize()|.
|
|
time Timestamp of the entry. See |getftime()|.
|
|
type Type of the entry.
|
|
On Unix, almost same as |getftype()| except:
|
|
Symlink to a dir "linkd"
|
|
Other symlink "link"
|
|
On MS-Windows:
|
|
Normal file "file"
|
|
Directory "dir"
|
|
Junction "junction"
|
|
Symlink to a dir "linkd"
|
|
Other symlink "link"
|
|
Other reparse point "reparse"
|
|
user User name of the entry's owner. (Only on Unix)
|
|
On Unix, if the entry is a symlink, the Dictionary includes
|
|
the information of the target (except the "type" item).
|
|
On MS-Windows, it includes the information of the symlink
|
|
itself because of performance reasons.
|
|
--]=]
|
|
M.readdirex = function(dir)
|
|
local files = vim.fn.readdir(dir)
|
|
local direx = {}
|
|
for _, f in ipairs(files) do
|
|
table.insert(direx, {
|
|
name = f,
|
|
type = vim.fn.getftype(f),
|
|
})
|
|
end
|
|
|
|
return direx
|
|
end
|
|
|
|
M.mapnew = function(tbl, expr)
|
|
return vim.fn.map(tbl, expr)
|
|
end
|
|
|
|
M.typename = function(val)
|
|
local ty = type(val)
|
|
if ty == 'string' then
|
|
return 'string'
|
|
elseif ty == 'boolean' then
|
|
return 'bool'
|
|
elseif ty == 'number' then
|
|
return 'number'
|
|
else
|
|
error(string.format('typename: %s', val))
|
|
end
|
|
end
|
|
|
|
-- Popup menu stuff: Could be rolled into other plugin later
|
|
-- but currently is here for testing purposes (and implements
|
|
-- some very simple compat layers at the moment)
|
|
do
|
|
local pos_map = {
|
|
topleft = 'NW',
|
|
topright = 'NE',
|
|
botleft = 'SW',
|
|
botright = 'SE',
|
|
}
|
|
|
|
M.popup_menu = function(_, options)
|
|
-- print "OPTIONS:"
|
|
|
|
local buf = vim.api.nvim_create_buf(false, true)
|
|
local win = vim.api.nvim_open_win(buf, true, {
|
|
relative = 'editor',
|
|
style = 'minimal',
|
|
anchor = pos_map[options.pos],
|
|
height = options.maxheight or options.minheight,
|
|
width = options.maxwidth or options.minwidth,
|
|
row = options.line,
|
|
col = options.col,
|
|
})
|
|
|
|
if options.filter then
|
|
local loop
|
|
loop = function()
|
|
vim.cmd([[redraw!]])
|
|
local ok, ch = pcall(vim.fn.getcharstr)
|
|
if not ok then
|
|
return
|
|
end -- interrupted
|
|
|
|
if ch == '<C-C>' then
|
|
return
|
|
end
|
|
|
|
if not require('vim9script').bool(options.filter(nil, ch)) then
|
|
vim.cmd.normal(ch)
|
|
end
|
|
|
|
vim.schedule(loop)
|
|
end
|
|
|
|
vim.schedule(loop)
|
|
end
|
|
|
|
return win
|
|
end
|
|
|
|
M.popup_settext = function(id, text)
|
|
if type(text) == 'string' then
|
|
-- text = vim.split(text, "\n")
|
|
error("Haven't handled string yet")
|
|
end
|
|
|
|
local lines = {}
|
|
for _, obj in ipairs(text) do
|
|
table.insert(lines, obj.text)
|
|
end
|
|
|
|
vim.api.nvim_buf_set_lines(vim.api.nvim_win_get_buf(id), 0, -1, false, lines)
|
|
end
|
|
|
|
M.popup_filter_menu = function()
|
|
print('ok, just pretend we filtered the menu')
|
|
end
|
|
|
|
M.popup_setoptions = function(id, _)
|
|
print('setting options...', id)
|
|
end
|
|
end
|
|
|
|
M = setmetatable(M, {
|
|
__index = vim.fn,
|
|
})
|
|
|
|
return M
|
|
end)()
|
|
vim9['heredoc'] = (function()
|
|
local M = {}
|
|
|
|
M.trim = function(lines)
|
|
local min_whitespace = 9999
|
|
for _, line in ipairs(lines) do
|
|
local _, finish = string.find(line, '^%s*')
|
|
min_whitespace = math.min(min_whitespace, finish)
|
|
end
|
|
|
|
local trimmed_lines = {}
|
|
for _, line in ipairs(lines) do
|
|
table.insert(trimmed_lines, string.sub(line, min_whitespace + 1))
|
|
end
|
|
|
|
return trimmed_lines
|
|
end
|
|
|
|
return M
|
|
end)()
|
|
vim9['import'] = (function()
|
|
local imported = {}
|
|
imported.autoload = setmetatable({}, {
|
|
__index = function(_, name)
|
|
local luaname = 'autoload/' .. string.gsub(name, '%.vim$', '.lua')
|
|
local runtime_file = vim.api.nvim_get_runtime_file(luaname, false)[1]
|
|
if not runtime_file then
|
|
error('unable to find autoload file:' .. name)
|
|
end
|
|
|
|
return imported.absolute[vim.fn.fnamemodify(runtime_file, ':p')]
|
|
end,
|
|
})
|
|
|
|
imported.absolute = setmetatable({}, {
|
|
__index = function(self, name)
|
|
if vim.loop.fs_stat(name) then
|
|
local result = loadfile(name)()
|
|
rawset(self, name, result)
|
|
|
|
return result
|
|
end
|
|
|
|
error(string.format('unabled to find absolute file: %s', name))
|
|
end,
|
|
})
|
|
|
|
return function(info)
|
|
local name = info.name
|
|
|
|
if info.autoload then
|
|
return imported.autoload[info.name]
|
|
end
|
|
|
|
local debug_info = debug.getinfo(2, 'S')
|
|
local sourcing_path = vim.fn.fnamemodify(string.sub(debug_info.source, 2), ':p')
|
|
|
|
-- Relative paths
|
|
if vim.startswith(name, '../') or vim.startswith(name, './') then
|
|
local luaname = string.gsub(name, '%.vim$', '.lua')
|
|
local directory = vim.fn.fnamemodify(sourcing_path, ':h')
|
|
local search = directory .. '/' .. luaname
|
|
return imported.absolute[search]
|
|
end
|
|
|
|
if vim.startswith(name, '/') then
|
|
error('absolute path')
|
|
-- local luaname = string.gsub(name, "%.vim", ".lua")
|
|
-- local runtime_file = vim.api.nvim_get_runtime_file(luaname, false)[1]
|
|
-- if runtime_file then
|
|
-- runtime_file = vim.fn.fnamemodify(runtime_file, ":p")
|
|
-- return loadfile(runtime_file)()
|
|
-- end
|
|
end
|
|
|
|
error('Unhandled case' .. vim.inspect(info) .. vim.inspect(debug_info))
|
|
end
|
|
end)()
|
|
vim9['ops'] = (function()
|
|
local lib = vim9
|
|
|
|
local M = {}
|
|
|
|
M['And'] = function(left, right)
|
|
return lib.bool(left) and lib.bool(right)
|
|
end
|
|
|
|
M['Or'] = function(left, right)
|
|
return lib.bool(left) or lib.bool(right)
|
|
end
|
|
|
|
M['Plus'] = function(left, right)
|
|
return left + right
|
|
end
|
|
|
|
M['Multiply'] = function(left, right)
|
|
return left * right
|
|
end
|
|
|
|
M['Divide'] = function(left, right)
|
|
return left / right
|
|
end
|
|
|
|
M['StringConcat'] = function(left, right)
|
|
return left .. right
|
|
end
|
|
|
|
M['EqualTo'] = function(left, right)
|
|
return left == right
|
|
end
|
|
|
|
M['NotEqualTo'] = function(left, right)
|
|
return not M['EqualTo'](left, right)
|
|
end
|
|
|
|
M['LessThan'] = function(left, right)
|
|
return left < right
|
|
end
|
|
|
|
M['LessThanOrEqual'] = function(left, right)
|
|
return left <= right
|
|
end
|
|
|
|
M['GreaterThan'] = function(left, right)
|
|
return left > right
|
|
end
|
|
|
|
M['GreaterThanOrEqual'] = function(left, right)
|
|
return left >= right
|
|
end
|
|
|
|
M['RegexpMatches'] = function(left, right)
|
|
return not not vim.regex(right):match_str(left)
|
|
end
|
|
|
|
M['RegexpMatchesIns'] = function(left, right)
|
|
return not not vim.regex('\\c' .. right):match_str(left)
|
|
end
|
|
|
|
M['NotRegexpMatches'] = function(left, right)
|
|
return not M['RegexpMatches'](left, right)
|
|
end
|
|
|
|
M['Modulo'] = function(left, right)
|
|
return left % right
|
|
end
|
|
|
|
M['Minus'] = function(left, right)
|
|
-- TODO: This is not right :)
|
|
return left - right
|
|
end
|
|
|
|
return M
|
|
end)()
|
|
vim9['prefix'] = (function()
|
|
local lib = vim9
|
|
|
|
local M = {}
|
|
|
|
M['Minus'] = function(right)
|
|
return -right
|
|
end
|
|
|
|
M['Bang'] = function(right)
|
|
return not lib.bool(right)
|
|
end
|
|
|
|
return M
|
|
end)()
|
|
|
|
return vim9
|