diff --git a/.config/nvim/ftplugin/java.lua b/.config/nvim/ftplugin/java.lua new file mode 100644 index 0000000..c388a10 --- /dev/null +++ b/.config/nvim/ftplugin/java.lua @@ -0,0 +1,24 @@ +local caps = require("cmp_nvim_lsp").default_capabilities(vim.lsp.protocol.make_client_capabilities()) +local mztenv = require "mzte_nv" + +require("jdtls").start_or_attach { + cmd = { + "jdtls", + "-configuration", + vim.loop.os_homedir() .. "/.cache/jdtls/config", + "-data", + vim.loop.os_homedir() .. "/.cache/jdtls/workspace", + }, + + capabilities = caps, + + root_dir = require("jdtls.setup").find_root { ".git", "mvnw", "gradlew", "build.gradle" }, + + settings = { + java = { + configuration = { + runtimes = mztenv.jdtls.findRuntimes(), + }, + }, + }, +} diff --git a/.config/nvim/init.lua b/.config/nvim/init.lua index 8d1c51a..d80d075 100644 --- a/.config/nvim/init.lua +++ b/.config/nvim/init.lua @@ -1,3 +1,5 @@ +require "mzte_nv_preloader" + require "plugins" require "settings" require "maps" diff --git a/.config/nvim/lua/mzte_nv_preloader.lua b/.config/nvim/lua/mzte_nv_preloader.lua new file mode 100644 index 0000000..d73bdc1 --- /dev/null +++ b/.config/nvim/lua/mzte_nv_preloader.lua @@ -0,0 +1,7 @@ +-- This module is responsible for loading the native mzte_nv lua module +package.cpath = package.cpath .. ";" .. vim.loop.os_homedir() .. "/.local/share/nvim/mzte_nv.so" + +local success = pcall(require, "mzte_nv"); +if not success then + error "Failed to preload mzte_nv. Is it installed?" +end diff --git a/.config/nvim/lua/plugins.lua b/.config/nvim/lua/plugins.lua index 6d3f583..bfd108f 100644 --- a/.config/nvim/lua/plugins.lua +++ b/.config/nvim/lua/plugins.lua @@ -146,22 +146,24 @@ return require("packer").startup(function(use) "rcarriga/nvim-notify", config = function() vim.notify = require "notify" - end + end, } use { "stevearc/dressing.nvim", config = function() require("dressing").setup {} - end + end, } use { "nvim-treesitter/nvim-treesitter-context", - config = pconf "ts-context" + config = pconf "ts-context", } use "DaeZak/crafttweaker-vim-highlighting" + use "mfussenegger/nvim-jdtls" + cmp_plugins(use) end) diff --git a/.config/nvim/lua/settings.lua b/.config/nvim/lua/settings.lua index e5acd54..c0c75b3 100644 --- a/.config/nvim/lua/settings.lua +++ b/.config/nvim/lua/settings.lua @@ -17,8 +17,7 @@ o.termguicolors = true wo.cursorline = true wo.cursorcolumn = true -g.neoterm_default_mod = "tab" -g.neovide_iso_layout = true +g.zig_fmt_autosave = 0 o.conceallevel = 2 diff --git a/justfile b/justfile index 0ec2ee0..2d7f74d 100644 --- a/justfile +++ b/justfile @@ -34,3 +34,7 @@ install-lsps-paru: ocamlformat fi + +install-mzte-nv: + cd mzte_nv && zig build -Drelease-fast + cp mzte_nv/zig-out/lib/libmzte_nv.so ~/.local/share/nvim/mzte_nv.so diff --git a/mzte_nv/.gitignore b/mzte_nv/.gitignore new file mode 100644 index 0000000..1ae1b10 --- /dev/null +++ b/mzte_nv/.gitignore @@ -0,0 +1,5 @@ +zig-cache/ +zig-out/ +deps.zig +gyro.lock +.gyro diff --git a/mzte_nv/README.md b/mzte_nv/README.md new file mode 100644 index 0000000..24e0307 --- /dev/null +++ b/mzte_nv/README.md @@ -0,0 +1,3 @@ +# mzte_nv + +Native components of my neovim config, implemented as a native LuaJIT module. diff --git a/mzte_nv/build.zig b/mzte_nv/build.zig new file mode 100644 index 0000000..0ff0e87 --- /dev/null +++ b/mzte_nv/build.zig @@ -0,0 +1,23 @@ +const std = @import("std"); + +pub fn build(b: *std.build.Builder) void { + // Standard release options allow the person running `zig build` to select + // between Debug, ReleaseSafe, ReleaseFast, and ReleaseSmall. + const mode = b.standardReleaseOptions(); + + const lib = b.addSharedLibrary("mzte_nv", "src/main.zig", .unversioned); + lib.setBuildMode(mode); + + lib.linkLibC(); + lib.linkSystemLibrary("luajit"); + + lib.strip = mode != .Debug; + + lib.install(); + + const main_tests = b.addTest("src/main.zig"); + main_tests.setBuildMode(mode); + + const test_step = b.step("test", "Run library tests"); + test_step.dependOn(&main_tests.step); +} diff --git a/mzte_nv/src/ffi.zig b/mzte_nv/src/ffi.zig new file mode 100644 index 0000000..098f572 --- /dev/null +++ b/mzte_nv/src/ffi.zig @@ -0,0 +1,25 @@ +const std = @import("std"); + +pub const c = @cImport({ + @cInclude("lua.h"); + @cInclude("lauxlib.h"); +}); + +/// Generates a wrapper function with error handling for a lua CFunction +pub fn luaFunc(comptime func: fn (*c.lua_State) anyerror!c_int) c.lua_CFunction { + return &struct { + fn f(l: ?*c.lua_State) callconv(.C) c_int { + return func(l.?) catch |e| { + var buf: [128]u8 = undefined; + const err_s = std.fmt.bufPrintZ( + &buf, + "Zig Error: {s}", + .{@errorName(e)}, + ) catch unreachable; + c.lua_pushstring(l, err_s.ptr); + _ = c.lua_error(l); + unreachable; + }; + } + }.f; +} diff --git a/mzte_nv/src/main.zig b/mzte_nv/src/main.zig new file mode 100644 index 0000000..62bef89 --- /dev/null +++ b/mzte_nv/src/main.zig @@ -0,0 +1,15 @@ +const std = @import("std"); +const ffi = @import("ffi.zig"); +const c = ffi.c; + +const modules = struct { + const jdtls = @import("modules/jdtls.zig"); +}; + +export fn luaopen_mzte_nv(l_: ?*c.lua_State) c_int { + const l = l_.?; + c.lua_newtable(l); + modules.jdtls.pushModtable(l); + c.lua_setfield(l, -2, "jdtls"); + return 1; +} diff --git a/mzte_nv/src/modules/jdtls.zig b/mzte_nv/src/modules/jdtls.zig new file mode 100644 index 0000000..3f4b6ea --- /dev/null +++ b/mzte_nv/src/modules/jdtls.zig @@ -0,0 +1,70 @@ +/// Module for the JDTLS java language server, including utilities +/// for setting up nvim-jdtls +const std = @import("std"); +const ffi = @import("../ffi.zig"); +const c = ffi.c; + +pub fn pushModtable(l: *c.lua_State) void { + c.lua_newtable(l); + c.lua_pushcfunction(l, ffi.luaFunc(lFindRuntimes)); + c.lua_setfield(l, -2, "findRuntimes"); +} + +const Runtime = struct { + version: []const u8, + name: []const u8, +}; +const runtime_map = [_]Runtime{ + .{ .version = "18", .name = "JavaSE-18" }, + .{ .version = "17", .name = "JavaSE-17" }, + .{ .version = "16", .name = "JavaSE-16" }, + .{ .version = "15", .name = "JavaSE-15" }, + .{ .version = "14", .name = "JavaSE-14" }, + .{ .version = "13", .name = "JavaSE-13" }, + .{ .version = "12", .name = "JavaSE-12" }, + .{ .version = "11", .name = "JavaSE-11" }, + .{ .version = "10", .name = "JavaSE-10" }, + .{ .version = "9", .name = "JavaSE-9" }, + .{ .version = "8", .name = "JavaSE-1.8" }, + .{ .version = "7", .name = "JavaSE-1.7" }, + .{ .version = "6", .name = "JavaSE-1.6" }, + .{ .version = "5", .name = "J2SE-1.5" }, // probably redundant, but JDTLS supports it +}; + +fn lFindRuntimes(l: *c.lua_State) !c_int { + const jvmdir = try std.fs.openIterableDirAbsolute("/usr/lib/jvm/", .{}); + + c.lua_newtable(l); + + var buf: [512]u8 = undefined; + var idx: c_int = 1; + var iter = jvmdir.iterate(); + while (try iter.next()) |jvm| { + if (jvm.kind != .Directory or !std.mem.startsWith(u8, jvm.name, "java-")) + continue; + + for (runtime_map) |rt| { + if (!std.mem.containsAtLeast(u8, jvm.name, 1, rt.version)) + continue; + + // push a table with a name field (must be a V from runtime_map) + // and a path field (path to the runtime's home) + c.lua_newtable(l); + + c.lua_pushstring(l, rt.name.ptr); + c.lua_setfield(l, -2, "name"); + + const path = try std.fmt.bufPrintZ(&buf, "/usr/lib/jvm/{s}/", .{jvm.name}); + c.lua_pushstring(l, path.ptr); + c.lua_setfield(l, -2, "path"); + + // append table to list + c.lua_rawseti(l, -2, idx); + idx += 1; + + break; + } + } + + return 1; +}