------------------------------------------------------------------------------- -- 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_ref = function(module, name, copied, ...) for _, val in ipairs({ ... }) do table.insert(copied, val) end local funcref = name if type(funcref) == 'function' then return funcref(unpack(copied)) elseif type(funcref) == 'string' then if vim.fn.exists('*' .. funcref) == 1 then return vim.fn[funcref](unpack(copied)) end if module[funcref] then module[funcref](unpack(copied)) end error('unknown function: ' .. funcref) else error(string.format('unable to call funcref: %s', funcref)) 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 -- 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_exec2(table.concat(file, '\n'), { output = 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 various 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 == '' 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.uv.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