dotfiles/mzte-nv/src/modules/tsn_actions.zig

103 lines
2.7 KiB
Zig

//! Module for tree-sitter node actions
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, .{
.zigToggleMutability = ffi.luaFunc(lZigToggleMutability),
.intToHex = ffi.luaFunc(lIntToHex),
.intToDec = ffi.luaFunc(lIntToDec),
.intToggle = ffi.luaFunc(lIntToggle),
});
}
fn lZigToggleMutability(l: *c.lua_State) !c_int {
const inp = ffi.luaCheckstring(l, 1);
// this has got to be enough for any halfway reasonable variable declaration
var buf: [1024 * 4]u8 = undefined;
const out = if (std.mem.startsWith(u8, inp, "var"))
try std.fmt.bufPrint(&buf, "const{s}", .{inp[3..]})
else if (std.mem.startsWith(u8, inp, "const"))
try std.fmt.bufPrint(&buf, "var{s}", .{inp[5..]})
else
inp;
// split into lines
c.lua_newtable(l);
var liter = std.mem.split(u8, out, "\n");
var idx: c_int = 1;
while (liter.next()) |line| {
ffi.luaPushString(l, line);
c.lua_rawseti(l, -2, idx);
idx += 1;
}
return 1;
}
/// Given a hex number literal, determine the index where the actual number starts.
/// Returns 0 if this isn't a hex number.
fn hexStartIdx(s: []const u8) u2 {
if (s.len < 3)
return 0;
const offset: u2 = if (s[0] == '-') 1 else 0;
if (s.len - offset < 3 or !std.mem.eql(u8, "0x", s[offset..][0..2]))
return 0;
return 2 + offset;
}
fn lIntToHex(l: *c.lua_State) !c_int {
const inp = ffi.luaCheckstring(l, 1);
const parsed = try std.fmt.parseInt(i64, inp, 10);
var buf: [128]u8 = undefined;
ffi.luaPushString(
l,
if (parsed < 0)
try std.fmt.bufPrint(&buf, "-0x{x}", .{-parsed})
else
try std.fmt.bufPrint(&buf, "0x{x}", .{parsed}),
);
return 1;
}
fn lIntToDec(l: *c.lua_State) !c_int {
const inp = ffi.luaCheckstring(l, 1);
const start_idx = hexStartIdx(inp);
if (start_idx == 0)
return error.InvalidHex;
const parsed = try std.fmt.parseInt(
i64,
inp[start_idx..],
16,
) * @as(i2, if (start_idx == 3) -1 else 1);
var buf: [128]u8 = undefined;
ffi.luaPushString(l, try std.fmt.bufPrint(&buf, "{d}", .{parsed}));
return 1;
}
fn lIntToggle(l: *c.lua_State) !c_int {
const inp = ffi.luaCheckstring(l, 1);
for (inp) |char| {
// return input for floats
if (char == '.' or char == 'f' or char == 'f') {
c.lua_pushvalue(l, 1);
return 1;
}
}
if (hexStartIdx(inp) != 0) {
return try lIntToDec(l);
} else {
return try lIntToHex(l);
}
}