From b26af6899af96b34c1a6e74cb2d806ac23da424c Mon Sep 17 00:00:00 2001 From: LordMZTE Date: Sun, 16 Apr 2023 18:12:38 +0200 Subject: [PATCH] mzte-nv now acts as login shell --- .config/fish/conf.d/00-env.fish | 22 ------ .config/fish/conf.d/01-mzteinit.fish | 5 -- .config/wezterm/wezterm.lua.cgt | 4 +- scripts/mzteinit/src/DelimitedBuilder.zig | 55 ++++++++++++++ scripts/mzteinit/src/env.zig | 89 +++++++++++++++++++++++ scripts/mzteinit/src/main.zig | 40 +++++++++- scripts/mzteinit/src/run.zig | 12 ++- 7 files changed, 194 insertions(+), 33 deletions(-) delete mode 100644 .config/fish/conf.d/00-env.fish delete mode 100644 .config/fish/conf.d/01-mzteinit.fish create mode 100644 scripts/mzteinit/src/DelimitedBuilder.zig create mode 100644 scripts/mzteinit/src/env.zig diff --git a/.config/fish/conf.d/00-env.fish b/.config/fish/conf.d/00-env.fish deleted file mode 100644 index 9a07ccf..0000000 --- a/.config/fish/conf.d/00-env.fish +++ /dev/null @@ -1,22 +0,0 @@ -if set -q MZTE_ENV_SET - exit -end -set -gx MZTE_ENV_SET - -# mix should respect XDG standard -export MIX_XDG=1 - -# use clang compiler -export CC=clang -export CXX=clang++ - -# neovim editor -export EDITOR=nvim - -# paths -export PATH="$HOME/.mix/escripts:$HOME/.cargo/bin:$HOME/.local/bin:$HOME/go/bin:$PATH:$HOME/.roswell/bin" -export LUA_CPATH="$HOME/.local/lib/lua/?.so;$HOME/.local/lib/lua/?.lua;;" - -if which racket >/dev/null - set -ax PATH (racket -l racket/base -e '(require setup/dirs) (display (path->string (find-user-console-bin-dir)))') -end diff --git a/.config/fish/conf.d/01-mzteinit.fish b/.config/fish/conf.d/01-mzteinit.fish deleted file mode 100644 index d19cacf..0000000 --- a/.config/fish/conf.d/01-mzteinit.fish +++ /dev/null @@ -1,5 +0,0 @@ -if set -q MZTEINIT - exit -end -set -gx MZTEINIT -exec mzteinit diff --git a/.config/wezterm/wezterm.lua.cgt b/.config/wezterm/wezterm.lua.cgt index f13208d..b525de0 100644 --- a/.config/wezterm/wezterm.lua.cgt +++ b/.config/wezterm/wezterm.lua.cgt @@ -1,4 +1,5 @@ ; +; vim: filetype=fennel (local wt (require :wezterm)) @@ -37,7 +38,8 @@ (table.insert keys (kmap dir-key :ALT|SHIFT :AdjustPaneSize [dir-name resize-amt])))) -{:color_scheme "Dracula (Official)" +{:default_prog [:fish] + :color_scheme "Dracula (Official)" :font (wt.font "<% opt.term_font %>") :warn_about_missing_glyphs false :window_background_opacity 0.8 diff --git a/scripts/mzteinit/src/DelimitedBuilder.zig b/scripts/mzteinit/src/DelimitedBuilder.zig new file mode 100644 index 0000000..210a846 --- /dev/null +++ b/scripts/mzteinit/src/DelimitedBuilder.zig @@ -0,0 +1,55 @@ +//! Utility struct for building delimeter-separated strings +const std = @import("std"); + +str: []u8, +alloc: std.mem.Allocator, +delimeter: u8, + +const DelimitedBuilder = @This(); + +pub fn init(alloc: std.mem.Allocator, delimeter: u8) DelimitedBuilder { + return .{ + .str = "", + .alloc = alloc, + .delimeter = delimeter, + }; +} + +pub fn deinit(self: DelimitedBuilder) void { + if (self.str.len > 0) { + self.alloc.free(self.str); + } +} + +/// Push a string, inserting a delimiter if necessary +pub fn push(self: *DelimitedBuilder, str: []const u8) !void { + if (self.str.len == 0) { + self.str = try self.alloc.dupe(u8, str); + } else { + const old_len = self.str.len; + self.str = try self.alloc.realloc(self.str, old_len + str.len + 1); + self.str[old_len] = self.delimeter; + std.mem.copy(u8, self.str[old_len + 1 ..], str); + } +} + +/// Push a string without a delimiter +pub fn pushDirect(self: *DelimitedBuilder, str: []const u8) !void { + if (self.str.len == 0) { + self.str = try self.alloc.dupe(u8, str); + } else { + const old_len = self.str.len; + self.str = try self.alloc.realloc(self.str, old_len + str.len); + std.mem.copy(u8, self.str[old_len ..], str); + } +} + +/// Converts the builder's string to an allocated string. +/// Caller owns returned memory, the builder will be fully deinitialized. +pub fn toOwned(self: *const DelimitedBuilder) ![]u8 { + if (self.str.len == 0) { + return try self.alloc.alloc(u8, 0); + } else { + return self.str; + } +} diff --git a/scripts/mzteinit/src/env.zig b/scripts/mzteinit/src/env.zig new file mode 100644 index 0000000..a50420f --- /dev/null +++ b/scripts/mzteinit/src/env.zig @@ -0,0 +1,89 @@ +const std = @import("std"); +const DelimitedBuilder = @import("DelimitedBuilder.zig"); + +pub fn populateEnvironment(env: *std.process.EnvMap) !void { + if (env.get("MZTE_ENV_SET")) |_| { + return; + } + + const alloc = env.hash_map.allocator; + const home = if (env.get("HOME")) |home| try alloc.dupe(u8, home) else blk: { + std.log.warn("Home not set, defaulting to current directory", .{}); + break :blk try std.fs.realpathAlloc(alloc, "."); + }; + defer alloc.free(home); + + try env.put("MZTE_ENV_SET", "1"); + + // mix (elixir package manager) should respect XDG + try env.put("MIX_XDG", "1"); + + // use clang + try env.put("CC", "clang"); + try env.put("CXX", "clang++"); + + // neovim + try env.put("EDITOR", "nvim"); + + // PATH + { + var b = DelimitedBuilder.init(alloc, ':'); + errdefer b.deinit(); + + var buf: [512]u8 = undefined; + + const fixed_home = [_][]const u8{ + ".mix/escripts", + ".cargo/bin", + ".local/bin", + "go/bin", + ".roswell/bin", + }; + for (fixed_home) |fixed| { + try b.push(try std.fmt.bufPrint(&buf, "{s}/{s}", .{ home, fixed })); + } + + // racket bins + racket: { + const res = std.ChildProcess.exec(.{ + .allocator = alloc, + .argv = &.{ + "racket", + "-l", + "racket/base", + "-e", + "(require setup/dirs) (display (path->string (find-user-console-bin-dir)))", + }, + }) catch break :racket; + defer alloc.free(res.stdout); + defer alloc.free(res.stderr); + + try b.push(res.stdout); + } + + if (env.get("PATH")) |system_path| { + try b.push(system_path); + } + + try env.putMove(try alloc.dupe(u8, "PATH"), try b.toOwned()); + } + + // LUA_CPATH + { + var b = DelimitedBuilder.init(alloc, ';'); + errdefer b.deinit(); + + var buf: [512]u8 = undefined; + + const fixed_home = [_][]const u8{ + ".local/lib/lua/?.so", + ".local/lib/lua/?.lua", + }; + for (fixed_home) |fixed| { + try b.push(try std.fmt.bufPrint(&buf, "{s}/{s}", .{ home, fixed })); + } + try b.pushDirect(";;"); + + try env.putMove(try alloc.dupe(u8, "LUA_CPATH"), try b.toOwned()); + } +} diff --git a/scripts/mzteinit/src/main.zig b/scripts/mzteinit/src/main.zig index ed624b1..162289e 100644 --- a/scripts/mzteinit/src/main.zig +++ b/scripts/mzteinit/src/main.zig @@ -1,5 +1,6 @@ const std = @import("std"); const at = @import("ansi-term"); +const env = @import("env.zig"); const run = @import("run.zig"); const util = @import("util.zig"); @@ -7,6 +8,43 @@ pub fn main() !void { var stdout = std.io.bufferedWriter(std.io.getStdOut().writer()); var exit = false; + var gpa = std.heap.GeneralPurposeAllocator(.{}){}; + defer _ = gpa.deinit(); + const alloc = gpa.allocator(); + + var env_map = std.process.EnvMap.init(alloc); + defer env_map.deinit(); + + for (std.os.environ) |env_var| { + var idx: usize = 0; + while (env_var[idx] != '=') { + idx += 1; + } + + const eq_idx = idx; + + while (env_var[idx] != 0) { + idx += 1; + } + + const key = env_var[0..eq_idx]; + const value = env_var[eq_idx + 1..idx]; + + try env_map.put(key, value); + } + + if (env_map.get("MZTEINIT")) |_| { + try stdout.writer().writeAll("mzteinit running already, starting shell\n"); + try stdout.flush(); + var child = std.ChildProcess.init(&.{"fish"}, alloc); + _ = try child.spawnAndWait(); + return; + } else { + try env_map.put("MZTEINIT", "1"); + } + + try env.populateEnvironment(&env_map); + while (true) { try util.writeAnsiClear(stdout.writer()); @@ -18,7 +56,7 @@ pub fn main() !void { try util.writeAnsiClear(stdout.writer()); try stdout.flush(); - cmd.run(&exit) catch |e| { + cmd.run(alloc, &exit, &env_map) catch |e| { try stdout.writer().print("Error running command: {}\n\n", .{e}); continue; }; diff --git a/scripts/mzteinit/src/run.zig b/scripts/mzteinit/src/run.zig index d8c4d02..ed2ac32 100644 --- a/scripts/mzteinit/src/run.zig +++ b/scripts/mzteinit/src/run.zig @@ -31,16 +31,20 @@ pub const Command = enum { }; } - pub fn run(self: Command, exit: *bool) !void { + pub fn run( + self: Command, + alloc: std.mem.Allocator, + exit: *bool, + env: *const std.process.EnvMap, + ) !void { if (self == .logout) { exit.* = true; return; } - var mem: [512]u8 = undefined; - var fba = std.heap.FixedBufferAllocator.init(&mem); const arg = self.argv(); - var child = std.ChildProcess.init(arg, fba.allocator()); + var child = std.ChildProcess.init(arg, alloc); + child.env_map = env; _ = try child.spawnAndWait(); }