finish zig port

This commit is contained in:
LordMZTE 2022-06-14 17:57:22 +02:00
parent 99e60196e7
commit 2309bd0a31
Signed by: LordMZTE
GPG key ID: B64802DC33A64FF6
8 changed files with 340 additions and 243 deletions

View file

@ -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

View file

@ -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("<C-g>  ", pal.red, pal.black))
},
InputMode::Normal => powerline.segments([
Segment::from_palette("Normal", pal.black, pal.yellow),
Segment::from_palette("<C-g> |  ", pal.blue, ALT_BG),
Segment::from_palette("<C-p> |  ", pal.blue, ALT_BG),
Segment::from_palette("<C-t> | ﴵ ", pal.blue, ALT_BG),
Segment::from_palette("<C-n> | ﭕ ", pal.blue, ALT_BG),
Segment::from_palette("<C-h> |  ", pal.blue, ALT_BG),
Segment::from_palette("<C-s> |  ", pal.blue, ALT_BG),
Segment::from_palette("<C-o> |  ", pal.blue, ALT_BG),
Segment::from_palette("<C-q> |  ", pal.blue, ALT_BG),
Segment::from_palette("<M- >", pal.green, ALT_BG),
Segment::from_palette("<M-n> |  ", pal.green, ALT_BG),
Segment::from_palette("<M-+/-> | ﭔ ", 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));
}
}

View file

@ -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 = "<C-g>  ",
.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 = "<C-g> |  ", .style = ctrl_style });
try pl.draw(.{ .text = "<C-p> |  ", .style = ctrl_style });
try pl.draw(.{ .text = "<C-t> | ﴵ ", .style = ctrl_style });
try pl.draw(.{ .text = "<C-n> | ﭕ ", .style = ctrl_style });
try pl.draw(.{ .text = "<C-h> |  ", .style = ctrl_style });
try pl.draw(.{ .text = "<C-s> |  ", .style = ctrl_style });
try pl.draw(.{ .text = "<C-o> |  ", .style = ctrl_style });
try pl.draw(.{ .text = "<C-q> |  ", .style = ctrl_style });
try pl.draw(.{ .text = "<M- >", .style = alt_style });
try pl.draw(.{ .text = "<M-n> |  ", .style = alt_style });
try pl.draw(.{ .text = "<M-+/-> | ﭔ ", .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});
};
}

View file

@ -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<Segment>,
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<Item = Segment>) -> &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,
}

78
src/powerline.zig Normal file
View file

@ -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,
};

18
src/settings.zig Normal file
View file

@ -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 });
}

View file

@ -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()),
}
}

21
src/util.zig Normal file
View file

@ -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 },
};
}