From 2309bd0a31d5e7d7f822730cbdf6d30c903fcd08 Mon Sep 17 00:00:00 2001 From: LordMZTE Date: Tue, 14 Jun 2022 17:57:22 +0200 Subject: [PATCH] finish zig port --- gyro.zzz | 5 ++ src/main.rs | 117 ------------------------ src/main.zig | 221 +++++++++++++++++++++++++++++++++++++++++++++- src/powerline.rs | 114 ------------------------ src/powerline.zig | 78 ++++++++++++++++ src/settings.zig | 18 ++++ src/util.rs | 9 -- src/util.zig | 21 +++++ 8 files changed, 340 insertions(+), 243 deletions(-) delete mode 100644 src/main.rs delete mode 100644 src/powerline.rs create mode 100644 src/powerline.zig create mode 100644 src/settings.zig delete mode 100644 src/util.rs create mode 100644 src/util.zig diff --git a/gyro.zzz b/gyro.zzz index 147d8f7..58095cf 100644 --- a/gyro.zzz +++ b/gyro.zzz @@ -11,3 +11,8 @@ deps: url: "https://mzte.de/git/LordMZTE/zellzig.git" ref: master root: src/main.zig + ansi-term: + git: + url: "https://github.com/ziglibs/ansi-term.git" + ref: 1c4b9aa23e159b297e4008181ff649c246dc8abe + root: src/main.zig diff --git a/src/main.rs b/src/main.rs deleted file mode 100644 index fa0f3f7..0000000 --- a/src/main.rs +++ /dev/null @@ -1,117 +0,0 @@ -use powerline::Segment; -use zellij_tile::prelude::*; - -use crate::{powerline::Powerline, util::to_owo}; - -mod powerline; -mod util; - -// There's really no good palette color to use for this in zellij. I'll add this -// as a custom plugin option once that's possible. -const ALT_BG: PaletteColor = PaletteColor::Rgb((68, 71, 90)); - -register_plugin!(State); - -#[derive(Default)] -struct State { - mode: ModeInfo, -} - -impl ZellijPlugin for State { - fn load(&mut self) { - set_selectable(false); - subscribe(&[EventType::ModeUpdate]); - } - - fn update(&mut self, event: Event) { - if let Event::ModeUpdate(mode) = event { - self.mode = mode; - } - } - - fn render(&mut self, _rows: usize, cols: usize) { - let pal = self.mode.style.colors; - let mut powerline = Powerline::new(to_owo(pal.bg)); - - match self.mode.mode { - InputMode::Locked => { - powerline.segment(Segment::from_palette("  ", pal.red, pal.black)) - }, - - InputMode::Normal => powerline.segments([ - Segment::from_palette("Normal", pal.black, pal.yellow), - Segment::from_palette(" |  ", pal.blue, ALT_BG), - Segment::from_palette(" |  ", pal.blue, ALT_BG), - Segment::from_palette(" | ﴵ ", pal.blue, ALT_BG), - Segment::from_palette(" | ﭕ ", pal.blue, ALT_BG), - Segment::from_palette(" |  ", pal.blue, ALT_BG), - Segment::from_palette(" |  ", pal.blue, ALT_BG), - Segment::from_palette(" |  ", pal.blue, ALT_BG), - Segment::from_palette(" |  ", pal.blue, ALT_BG), - Segment::from_palette("", pal.green, ALT_BG), - Segment::from_palette(" |  ", pal.green, ALT_BG), - Segment::from_palette(" | ﭔ ", pal.green, ALT_BG), - ]), - - InputMode::Pane => powerline.segments([ - Segment::from_palette("Pane", pal.black, pal.blue), - Segment::from_palette(" ", pal.magenta, ALT_BG), - Segment::from_palette("p | 怜", pal.magenta, ALT_BG), - Segment::from_palette("n |  ", pal.magenta, ALT_BG), - Segment::from_palette("d |   ", pal.magenta, ALT_BG), - Segment::from_palette("r |   ", pal.magenta, ALT_BG), - Segment::from_palette("x |  ", pal.magenta, ALT_BG), - Segment::from_palette("f |  ", pal.magenta, ALT_BG), - Segment::from_palette("z |  ", pal.magenta, ALT_BG), - Segment::from_palette("c | 凜 ", pal.magenta, ALT_BG), - Segment::from_palette("w |  ", pal.magenta, ALT_BG), - Segment::from_palette("e |  ", pal.magenta, ALT_BG), - Segment::from_palette(" |  ", pal.magenta, ALT_BG), - ]), - - InputMode::Tab => powerline.segments([ - Segment::from_palette("Tab", pal.black, pal.cyan), - Segment::from_palette(" ", pal.magenta, ALT_BG), - Segment::from_palette(" ", pal.magenta, ALT_BG), - Segment::from_palette("⇋", pal.magenta, ALT_BG), - Segment::from_palette("n |  ", pal.magenta, ALT_BG), - Segment::from_palette("x |  ", pal.magenta, ALT_BG), - Segment::from_palette("r | 凜 ", pal.magenta, ALT_BG), - Segment::from_palette("s | מּ ", pal.magenta, ALT_BG), - Segment::from_palette(" |  ", pal.magenta, ALT_BG), - ]), - - InputMode::Resize => powerline.segments([ - Segment::from_palette("Resize", pal.black, pal.red), - Segment::from_palette(" ", pal.magenta, ALT_BG), - Segment::from_palette("+-", pal.magenta, ALT_BG), - Segment::from_palette(" |  ", pal.magenta, ALT_BG), - ]), - - InputMode::Move => powerline.segments([ - Segment::from_palette("Move", pal.black, pal.gray), - Segment::from_palette(" ", pal.magenta, ALT_BG), - Segment::from_palette("⇋/n | ⇋", pal.magenta, ALT_BG), - Segment::from_palette(" |  ", pal.magenta, ALT_BG), - ]), - - InputMode::Scroll => powerline.segments([ - Segment::from_palette("Scroll", pal.black, pal.green), - Segment::from_palette("", pal.magenta, ALT_BG), - Segment::from_palette(" ", pal.magenta, ALT_BG), - Segment::from_palette("u/d | ﯕ ", pal.magenta, ALT_BG), - Segment::from_palette(" |  ", pal.magenta, ALT_BG), - ]), - - InputMode::Session => powerline.segments([ - Segment::from_palette("Session", pal.black, pal.red), - Segment::from_palette("d |  ", pal.magenta, ALT_BG), - Segment::from_palette(" |  ", pal.magenta, ALT_BG), - ]), - - _ => &mut powerline, - }; - - println!("{}", powerline.render(cols)); - } -} diff --git a/src/main.zig b/src/main.zig index 19a7950..6d64ae7 100644 --- a/src/main.zig +++ b/src/main.zig @@ -1,12 +1,25 @@ const std = @import("std"); const zz = @import("zellzig"); +const at = @import("ansi-term"); +const powerline = @import("powerline.zig"); +const sets = @import("settings.zig"); +const util = @import("util.zig"); + +const sty = util.sty; +const col = util.col; + +// There's really no good palette color to use for this in zellij. I'll add this +// as a custom plugin option once that's possible. +const alt_bg = zz.types.PaletteColor{ .Rgb = [_]u8{ 68, 71, 90 } }; comptime { zz.createPlugin(@This()); } var gpa = std.heap.GeneralPurposeAllocator(.{}){}; -var mode = zz.types.InputMode.Normal; + +// this is fine, as we should always get a mode event before rendering +var mi: zz.types.ModeInfo = undefined; pub fn init() void { zz.allocator = gpa.allocator(); @@ -17,12 +30,214 @@ pub fn init() void { pub fn update(ev: zz.Event) void { switch (ev) { - .ModeUpdate => |mi| mode = mi.mode, + .ModeUpdate => |info| mi = info, else => {}, } } +fn tryRender(cols: usize) !void { + const pal = mi.style.colors; + const ctrl_style = sets.ctrlStyle(pal); + const alt_style = sets.altStyle(pal); + const single_style = sets.singleStyle(pal); + + const writer = std.io.getStdOut().writer(); + var pl = powerline.Powerline(@TypeOf(writer)).init( + writer, + cols, + col(pal.bg), + ); + + switch (mi.mode) { + .Locked => { + try pl.draw(.{ + .text = "  ", + .style = sty(.{ + .font = .{ .bold = true }, + .fg = pal.red, + .bg = pal.black, + }), + }); + }, + + .Normal => { + try pl.draw(.{ + .text = "Normal", + .style = sty(.{ + .font = .{ .bold = true }, + .fg = pal.black, + .bg = pal.yellow, + }), + }); + + try pl.draw(.{ .text = " |  ", .style = ctrl_style }); + try pl.draw(.{ .text = " |  ", .style = ctrl_style }); + try pl.draw(.{ .text = " | ﴵ ", .style = ctrl_style }); + try pl.draw(.{ .text = " | ﭕ ", .style = ctrl_style }); + try pl.draw(.{ .text = " |  ", .style = ctrl_style }); + try pl.draw(.{ .text = " |  ", .style = ctrl_style }); + try pl.draw(.{ .text = " |  ", .style = ctrl_style }); + try pl.draw(.{ .text = " |  ", .style = ctrl_style }); + try pl.draw(.{ .text = "", .style = alt_style }); + try pl.draw(.{ .text = " |  ", .style = alt_style }); + try pl.draw(.{ .text = " | ﭔ ", .style = alt_style }); + }, + + .Pane => { + try pl.draw(.{ + .text = "Pane", + .style = sty(.{ + .font = .{ .bold = true }, + .fg = pal.black, + .bg = pal.blue, + }), + }); + + try pl.draw(.{ .text = " ", .style = single_style }); + try pl.draw(.{ .text = "p | 怜", .style = single_style }); + try pl.draw(.{ .text = "n |  ", .style = single_style }); + try pl.draw(.{ .text = "d |   ", .style = single_style }); + try pl.draw(.{ .text = "r |   ", .style = single_style }); + try pl.draw(.{ .text = "x |  ", .style = single_style }); + try pl.draw(.{ .text = "f |  ", .style = single_style }); + try pl.draw(.{ .text = "z |  ", .style = single_style }); + try pl.draw(.{ .text = "c | 凜 ", .style = single_style }); + try pl.draw(.{ .text = "w |  ", .style = single_style }); + try pl.draw(.{ .text = "e |  ", .style = single_style }); + try pl.draw(.{ .text = " |  ", .style = single_style }); + }, + + .Tab => { + try pl.draw(.{ + .text = "Tab", + .style = sty(.{ + .font = .{ .bold = true }, + .fg = pal.black, + .bg = pal.cyan, + }), + }); + + try pl.draw(.{ .text = " ", .style = single_style }); + try pl.draw(.{ .text = " ", .style = single_style }); + try pl.draw(.{ .text = "⇋", .style = single_style }); + try pl.draw(.{ .text = "n |  ", .style = single_style }); + try pl.draw(.{ .text = "x |  ", .style = single_style }); + try pl.draw(.{ .text = "r | 凜 ", .style = single_style }); + try pl.draw(.{ .text = "s | מּ ", .style = single_style }); + try pl.draw(.{ .text = " |  ", .style = single_style }); + }, + + .Resize => { + try pl.draw(.{ + .text = "Resize", + .style = sty(.{ + .font = .{ .bold = true }, + .fg = pal.black, + .bg = pal.red, + }), + }); + + try pl.draw(.{ .text = " ", .style = single_style }); + try pl.draw(.{ .text = "+-", .style = single_style }); + try pl.draw(.{ .text = " |  ", .style = single_style }); + }, + + .Move => { + try pl.draw(.{ + .text = "Move", + .style = sty(.{ + .font = .{ .bold = true }, + .fg = pal.black, + .bg = pal.gray, + }), + }); + + try pl.draw(.{ .text = " ", .style = single_style }); + try pl.draw(.{ .text = "⇋/n | ⇋", .style = single_style }); + try pl.draw(.{ .text = " |  ", .style = single_style }); + }, + + .Scroll => { + try pl.draw(.{ + .text = "Scroll", + .style = sty(.{ + .font = .{ .bold = true }, + .fg = pal.black, + .bg = pal.green, + }), + }); + + try pl.draw(.{ .text = "", .style = single_style }); + try pl.draw(.{ .text = " ", .style = single_style }); + try pl.draw(.{ .text = "u/d | ﯕ ", .style = single_style }); + try pl.draw(.{ .text = " |  ", .style = single_style }); + }, + + .Session => { + try pl.draw(.{ + .text = "Session", + .style = sty(.{ + .font = .{ .bold = true }, + .fg = pal.blue, + .bg = pal.red, + }), + }); + + try pl.draw(.{ .text = "d |  ", .style = single_style }); + try pl.draw(.{ .text = " |  ", .style = single_style }); + }, + + .RenameTab => { + try pl.draw(.{ + .text = "Rename Tab", + .style = sty(.{ + .font = .{ .bold = true }, + .fg = pal.black, + .bg = pal.blue, + }), + }); + }, + + .RenamePane => { + try pl.draw(.{ + .text = "Rename Pane", + .style = sty(.{ + .font = .{ .bold = true }, + .fg = pal.black, + .bg = pal.blue, + }), + }); + }, + + .Prompt => { + try pl.draw(.{ + .text = "Prompt", + .style = sty(.{ + .font = .{ .bold = true }, + .fg = pal.white, + .bg = pal.purple, + }), + }); + }, + + .Tmux => { + try pl.draw(.{ + .text = "TMUX", + .style = sty(.{ + .font = .{ .bold = true }, + .fg = pal.white, + .bg = pal.brown, + }), + }); + }, + } + + try pl.finish(); +} + pub fn render(rows: i32, cols: i32) void { _ = rows; - _ = cols; + tryRender(@intCast(usize, cols)) catch |e| { + std.log.err("Failed to render: {}", .{e}); + }; } diff --git a/src/powerline.rs b/src/powerline.rs deleted file mode 100644 index 81e6bc8..0000000 --- a/src/powerline.rs +++ /dev/null @@ -1,114 +0,0 @@ -use owo_colors::{DynColors, OwoColorize}; -use zellij_tile::prelude::*; - -use crate::util::to_owo; - -#[derive(Debug)] -pub struct Powerline { - segments: Vec, - separator: char, - background: DynColors, -} - -impl Powerline { - pub fn new(background: DynColors) -> Self { - Self::with_separator(background, '') - } - - pub fn with_separator(background: DynColors, separator: char) -> Self { - Self { - segments: vec![], - separator, - background, - } - } - - pub fn segment(&mut self, seg: Segment) -> &mut Self { - self.segments.push(seg); - self - } - - pub fn segments(&mut self, segs: impl IntoIterator) -> &mut Self { - for seg in segs { - self.segment(seg); - } - self - } - - pub fn render(&self, max_width: usize) -> String { - let mut buf = String::new(); - let mut max_segs = 0; - let mut cur_len = 0; - - for seg in &self.segments { - if cur_len >= max_width { - max_segs -= 1; - break; - } - - // 2 for worst-case separator width - cur_len += seg.txt.len() + 2; - max_segs += 1; - } - - for (i, seg) in self.segments.iter().enumerate().take(max_segs) { - let pos = match i { - 0 => SegPos::First, - n if n == max_segs - 1 => SegPos::Last, - _ => SegPos::Middle, - }; - - if pos == SegPos::First { - buf.push_str(&' '.on_color(seg.bg).to_string()); - } else { - buf.push_str( - &self - .separator - .color(self.background) - .on_color(seg.bg) - .to_string(), - ); - } - - buf.push_str(&seg.txt.color(seg.fg).on_color(seg.bg).to_string()); - - if pos == SegPos::Last || (pos == SegPos::First && max_segs == 1) { - buf.push_str(&self.separator.color(seg.bg).to_string()); - } else { - buf.push_str( - &self - .separator - .color(seg.bg) - .on_color(self.background) - .to_string(), - ); - } - } - - buf - } -} - -#[derive(Debug)] -pub struct Segment { - pub fg: DynColors, - pub bg: DynColors, - pub txt: String, -} - -impl Segment { - pub fn from_palette(txt: impl ToString, fg: PaletteColor, bg: PaletteColor) -> Self { - Self { - txt: txt.to_string(), - fg: to_owo(fg), - bg: to_owo(bg), - } - } -} - -#[derive(PartialEq, Eq)] -enum SegPos { - First, - Middle, - Last, -} diff --git a/src/powerline.zig b/src/powerline.zig new file mode 100644 index 0000000..b74f72b --- /dev/null +++ b/src/powerline.zig @@ -0,0 +1,78 @@ +const std = @import("std"); +const at = @import("ansi-term"); + +const separator = ""; + +pub fn Powerline(comptime Writer: type) type { + return struct { + current_len: usize, + last_style: ?at.Style, + writer: Writer, + max_len: usize, + background: at.Color, + + const Self = @This(); + + pub fn init(writer: Writer, max_len: usize, background: at.Color) Self { + return .{ + .current_len = 0, + .last_style = null, + .writer = writer, + .max_len = max_len, + .background = background, + }; + } + + pub fn draw(self: *Self, segment: Segment) !void { + // +2 for worst-case separator width + self.*.current_len += segment.text.len + 2; + + if (self.current_len > self.max_len) + return; + + // last style != null -> not first segment + if (self.last_style) |ls| { + try self.setStyle(.{ + .foreground = ls.background, + .background = self.*.background, + }); + try self.writeSeparator(); + + try self.setStyle(.{ + .foreground = self.*.background, + .background = segment.style.background, + }); + try self.writeSeparator(); + + try self.setStyle(segment.style); + } else { + try self.setStyle(segment.style); + try self.writer.writeAll(" "); + } + + try self.*.writer.writeAll(segment.text); + } + + pub fn finish(self: *Self) !void { + try self.setStyle(.{ + .foreground = (self.*.last_style orelse at.Style{}).background, + }); + + try self.*.writeSeparator(); + } + + fn setStyle(self: *Self, style: at.Style) !void { + try at.updateStyle(self.*.writer, style, self.*.last_style); + self.*.last_style = style; + } + + fn writeSeparator(self: *Self) !void { + try self.*.writer.writeAll(separator); + } + }; +} + +const Segment = struct { + style: at.Style, + text: []const u8, +}; diff --git a/src/settings.zig b/src/settings.zig new file mode 100644 index 0000000..124261e --- /dev/null +++ b/src/settings.zig @@ -0,0 +1,18 @@ +const zz = @import("zellzig"); +const at = @import("ansi-term"); +const sty = @import("util.zig").sty; + +// There's really no good palette color to use for this in zellij. I'll add this +// as a custom plugin option once that's possible. +const alt_bg = zz.types.PaletteColor{ .Rgb = [_]u8{ 68, 71, 90 } }; +pub fn ctrlStyle(pal: zz.types.Palette) at.Style { + return sty(.{ .fg = pal.blue, .bg = alt_bg }); +} + +pub fn altStyle(pal: zz.types.Palette) at.Style { + return sty(.{ .fg = pal.green, .bg = alt_bg }); +} + +pub fn singleStyle(pal: zz.types.Palette) at.Style { + return sty(.{ .fg = pal.magenta, .bg = alt_bg }); +} diff --git a/src/util.rs b/src/util.rs deleted file mode 100644 index 9de7582..0000000 --- a/src/util.rs +++ /dev/null @@ -1,9 +0,0 @@ -use owo_colors::DynColors; -use zellij_tile::prelude::PaletteColor; - -pub fn to_owo(color: PaletteColor) -> DynColors { - match color { - PaletteColor::Rgb((r, g, b)) => DynColors::Rgb(r, g, b), - PaletteColor::EightBit(n) => DynColors::Xterm(n.into()), - } -} diff --git a/src/util.zig b/src/util.zig new file mode 100644 index 0000000..17f9323 --- /dev/null +++ b/src/util.zig @@ -0,0 +1,21 @@ +const zz = @import("zellzig"); +const at = @import("ansi-term"); + +pub fn sty(palette_style: struct { + font: at.FontStyle = .{}, + bg: zz.types.PaletteColor, + fg: zz.types.PaletteColor, +}) at.Style { + return .{ + .font_style = palette_style.font, + .background = col(palette_style.bg), + .foreground = col(palette_style.fg), + }; +} + +pub fn col(color: zz.types.PaletteColor) at.Color { + return switch (color) { + .Rgb => |rgb| .{ .RGB = .{ .r = rgb[0], .g = rgb[1], .b = rgb[2] } }, + .EightBit => |c| .{ .Fixed = c }, + }; +}