neovim/runtime/lua/_vim9script.lua
TJ DeVries 39d70fcafd
dist: generated version of ccomplete.vim (#21623)
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.
2023-01-05 11:00:32 -05:00

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