port nvim-cmp tab handler to zig

This commit is contained in:
LordMZTE 2022-10-22 13:21:48 +02:00
parent 16e21c8274
commit 6176faad12
Signed by: LordMZTE
GPG key ID: B64802DC33A64FF6
3 changed files with 117 additions and 17 deletions

View file

@ -1,11 +1,6 @@
local cmp = require "cmp"
local luasnip = require "luasnip"
-- checks if the char before the cursor is a whitespace
local function has_words_before()
local line, col = unpack(vim.api.nvim_win_get_cursor(0))
return col ~= 0 and vim.api.nvim_buf_get_lines(0, line - 1, line, true)[1]:sub(col, col):match "%s" == nil
end
local mztenv = require "mzte_nv"
cmp.setup {
snippet = {
@ -18,17 +13,7 @@ cmp.setup {
["<C-b>"] = cmp.mapping(cmp.mapping.scroll_docs(-4), { "i", "c" }),
["<C-f>"] = cmp.mapping(cmp.mapping.scroll_docs(4), { "i", "c" }),
["<C-Space>"] = cmp.mapping(cmp.mapping.complete(), { "i", "c" }),
["<Tab>"] = cmp.mapping(function(fallback)
if cmp.visible() then
cmp.select_next_item()
elseif luasnip.expand_or_jumpable() then
luasnip.expand_or_jump()
elseif has_words_before() then
cmp.complete()
else
fallback()
end
end, { "i", "s" }),
["<Tab>"] = cmp.mapping(mztenv.cmp.onTab, { "i", "s" }),
["<S-Tab>"] = cmp.mapping(cmp.mapping.select_prev_item()),
["<CR>"] = cmp.mapping.confirm { select = true },
},

View file

@ -6,6 +6,7 @@ const c = ffi.c;
pub const version = "0.2.0";
const modules = struct {
const cmp = @import("modules/cmp.zig");
const jdtls = @import("modules/jdtls.zig");
};
@ -13,6 +14,7 @@ export fn luaopen_mzte_nv(l_: ?*c.lua_State) c_int {
const l = l_.?;
ser.luaPushAny(l, .{
.onInit = ffi.luaFunc(lOnInit),
.cmp = modules.cmp,
.jdtls = modules.jdtls,
});
return 1;

113
mzte-nv/src/modules/cmp.zig Normal file
View file

@ -0,0 +1,113 @@
const std = @import("std");
const ser = @import("../ser.zig");
const ffi = @import("../ffi.zig");
const c = ffi.c;
pub fn luaPush(l: *c.lua_State) void {
ser.luaPushAny(l, .{
.onTab = ffi.luaFunc(lOnTab),
});
}
fn lOnTab(l: *c.lua_State) !c_int {
// param 1 is the fallback function
c.luaL_checktype(l, 1, c.LUA_TFUNCTION);
// vim.api at idx 2
c.lua_getglobal(l, "vim");
c.lua_getfield(l, -1, "api");
c.lua_remove(l, 2);
// cmp module on stack idx 3
c.lua_getglobal(l, "require");
c.lua_pushstring(l, "cmp");
c.lua_call(l, 1, 1);
// luasnip module on stack idx 4
c.lua_getglobal(l, "require");
c.lua_pushstring(l, "luasnip");
c.lua_call(l, 1, 1);
// call cmp.visible()
c.lua_getfield(l, 3, "visible");
c.lua_call(l, 0, 1);
const cmp_visible = c.lua_toboolean(l, -1);
c.lua_pop(l, 1);
if (cmp_visible != 0) {
// call cmp.select_next_item()
c.lua_getfield(l, 3, "select_next_item");
c.lua_call(l, 0, 0);
} else if (blk: {
// call luasnip.expand_or_jumpable()
c.lua_getfield(l, 4, "expand_or_jumpable");
c.lua_call(l, 0, 1);
const b = c.lua_toboolean(l, -1) != 0;
c.lua_pop(l, 1);
break :blk b;
}) {
// call luasnip.expand_or_jump()
c.lua_getfield(l, 4, "expand_or_jump");
c.lua_call(l, 0, 0);
} else if (blk: {
// in this if, we check if the char before the cursor is NOT a whitespace,
// in which case we have cmp complete.
// call vim.api.nvim_win_get_cursor(0), returns the cursor position in the current buf
// in an array table with 2 values
c.lua_getfield(l, 2, "nvim_win_get_cursor");
c.lua_pushinteger(l, 0);
c.lua_call(l, 1, 1);
c.lua_rawgeti(l, -1, 1);
const cursor_line = c.lua_tointeger(l, -1);
c.lua_pop(l, 1);
c.lua_rawgeti(l, -1, 2);
const cursor_col = c.lua_tointeger(l, -1);
c.lua_pop(l, 2);
// If the cursor column is 0, that counts as a whitespace.
if (cursor_col == 0) {
break :blk false;
}
// call vim.api.nvim_buf_get_lines(0, line - 1, line, true)
// returns in array containing the line the cursor is at
c.lua_getfield(l, 2, "nvim_buf_get_lines");
c.lua_pushinteger(l, 0);
c.lua_pushinteger(l, cursor_line - 1);
c.lua_pushinteger(l, cursor_line);
c.lua_pushboolean(l, 1);
c.lua_call(l, 4, 1);
// get the line
c.lua_rawgeti(l, -1, 1);
var strlen: usize = 0;
const line = c.lua_tolstring(l, -1, &strlen)[0..strlen];
// char at the cursor is NOT whitespace
const b = std.mem.indexOfScalar(
u8,
" \t\n",
line[@intCast(usize, cursor_col) - 1],
) == null;
// remove the string and the string array from the stack
c.lua_pop(l, 2);
break :blk b;
}) {
// call cmp.complete()
c.lua_getfield(l, 3, "complete");
c.lua_call(l, 0, 0);
} else {
// call fallback function
c.lua_pushvalue(l, 1);
c.lua_call(l, 0, 0);
}
// clear stack
c.lua_settop(l, 0);
return 0;
}