docs: add README
This commit is contained in:
parent
cf233fd3c6
commit
82b21f7161
1 changed files with 137 additions and 0 deletions
137
README.md
Normal file
137
README.md
Normal file
|
@ -0,0 +1,137 @@
|
|||
# znvim
|
||||
|
||||
Zig bindings for Neovim's internal C functions. The ABI follows Neovim's master branch!
|
||||
|
||||
## Usage
|
||||
|
||||
1. Add the dependency to your project's `build.zig.zon`:
|
||||
|
||||
```zig
|
||||
.{
|
||||
.name = "my-config",
|
||||
.version = "0.0.0",
|
||||
|
||||
.dependencies = .{
|
||||
.znvim = .{
|
||||
.url = "https://mzte.de/git/LordMZTE/znvim/archive/<latest commit hash>.tar.gz",
|
||||
.hash = "<paste hash here; leave this field out when pasting the URL>",
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
2. Structure your `build.zig` something like this:
|
||||
|
||||
```zig
|
||||
const std = @import("std");
|
||||
|
||||
pub fn build(b: *std.build.Builder) !void {
|
||||
const target = b.standardTargetOptions(.{});
|
||||
|
||||
if (target.os_tag orelse @import("builtin").os.tag == .windows)
|
||||
// windows is an error in many ways
|
||||
return error.Windows;
|
||||
|
||||
const mode = b.standardOptimizeOption(.{});
|
||||
|
||||
// Build your config as a dynamically linked library.
|
||||
const lib = b.addSharedLibrary(.{
|
||||
.name = "my-config",
|
||||
.root_source_file = .{ .path = "src/main.zig" },
|
||||
.target = target,
|
||||
.optimize = mode,
|
||||
});
|
||||
|
||||
// Declare the znvim dependency here.
|
||||
const znvim_dep = b.dependency("znvim", .{ .target = target, .optimize = mode });
|
||||
|
||||
// Add both the nvim_c and znvim modules. You can import these independantly.
|
||||
lib.addModule("nvim", znvim_dep.module("nvim_c"));
|
||||
lib.addModule("znvim", znvim_dep.module("znvim"));
|
||||
|
||||
// Link libc.
|
||||
lib.linkLibC();
|
||||
|
||||
// LuaJIT is required in order to create a native Lua module neovim can load as well as
|
||||
// for your Lua API.
|
||||
lib.linkSystemLibrary("luajit");
|
||||
|
||||
// IMPORTANT: without this, lua errors inside your module will cause nvim to SIGABRT!
|
||||
lib.unwind_tables = true;
|
||||
|
||||
// Set the output path to be something sensical.
|
||||
b.getInstallStep().dependOn(&b.addInstallFile(lib.getOutputSource(), "share/nvim/mzte-nv.so").step);
|
||||
|
||||
b.installArtifact(lib);
|
||||
}
|
||||
```
|
||||
|
||||
3. In your `main.zig`, you want a function called `luaopen_my_config` (where `my_config` is your module name)
|
||||
This function is loaded by neovim's LuaJIT runtime via `dlsym` and called as an entry point on each `require` of your module.
|
||||
|
||||
```zig
|
||||
const znvim = @import("znvim");
|
||||
|
||||
// cImport LuaJIT
|
||||
const c = @cImport({
|
||||
@cInclude("lua.h");
|
||||
@cInclude("lualib.h");
|
||||
@cInclude("lauxlib.h");
|
||||
});
|
||||
|
||||
pub const std_options = struct {
|
||||
// You may want to override logFn here in order to redirect std.log log messages to, for example
|
||||
// nvim notifications. Not doing so will clutter the GUI on log messages.
|
||||
};
|
||||
|
||||
var is_initialized = false;
|
||||
|
||||
export fn luaopen_my_config(l: ?*c.lua_State) c_int {
|
||||
// Make sure we only run initiailzation code once.
|
||||
// I also recommend putting this into a seperate function you call from Lua once, but that's
|
||||
// outside the scope of this quick guide.
|
||||
if (!is_initialized) {
|
||||
is_initialized = true;
|
||||
|
||||
// For example, you could set an option:
|
||||
// See docs of types inside the znvim module.
|
||||
znvim.OptionValue.of(true).setLog("number", .both) catch {};
|
||||
}
|
||||
|
||||
c.lua_newtable(l); // create a new lua table to return from `require`
|
||||
// ... add stuff to that table here
|
||||
return 1; // 1 indicates one value returned from the lua function
|
||||
}
|
||||
```
|
||||
|
||||
4. Build your config to `~/.local`
|
||||
```bash
|
||||
zig build \
|
||||
-Doptimize=ReleaseFast \ # Use ReleaseSafe for easier to debug segfaults :D
|
||||
-p ~/.local # The output path you set in build.zig will be appended to this.
|
||||
```
|
||||
|
||||
5. In Lua, add the path to your shared object to `package.cpath`:
|
||||
```lua
|
||||
package.cpath = package.cpath .. ";" .. vim.loop.os_homedir() .. "/.loca/share/nvim/my-config.so"
|
||||
|
||||
-- You can now require("my_config")!
|
||||
```
|
||||
|
||||
## WTF???
|
||||
|
||||
The whole point of this is so I (and you too!) can write your neovim config in Zig, without going
|
||||
through the Lua API (or the rather bulky `nvim_*` API functions).
|
||||
|
||||
The way this works is by compiling your config's Zig part to a native Lua module, which is then
|
||||
loaded using just a few lines of Lua code. Here, you can also create a Lua API to call into.
|
||||
|
||||
## Structure
|
||||
|
||||
znvim is split into 2 modules: `nvim_c` and `znvim`. The former is a `translate-c`'d file of all
|
||||
of neovim's headers while the latter contains a (work in progress) Zig API for them.
|
||||
|
||||
## Development
|
||||
|
||||
Apart from writing the Zig API, we need to keep `nvim_c.zig` updated. This file contains the raw C
|
||||
bindings. It's generated by `generate_bindings.sh`.
|
Loading…
Reference in a new issue