mirror of https://github.com/fairyglade/ly.git
vi mode
This commit is contained in:
parent
f904be8fc0
commit
2ffd051eee
|
|
@ -8,8 +8,9 @@ res/config.ini contains all of the available config options and their default va
|
||||||
|
|
||||||
+ border\_fg has been introduced to change the color of the borders.
|
+ border\_fg has been introduced to change the color of the borders.
|
||||||
+ term\_restore\_cursor\_cmd should restore the cursor to it's usual state.
|
+ term\_restore\_cursor\_cmd should restore the cursor to it's usual state.
|
||||||
+ sleep\_key and sleep\_cmd.
|
|
||||||
+ log\_path is used to store ly.log and ly.log.old for debugging purposes (pretty much nothing is logged currently).
|
+ log\_path is used to store ly.log and ly.log.old for debugging purposes (pretty much nothing is logged currently).
|
||||||
|
+ enable\_vi\_mode to enable vi keybindings.
|
||||||
|
+ sleep\_key and sleep\_cmd.
|
||||||
|
|
||||||
Note: sleep\_cmd is unset by default, meaning it's hidden and has no effect.
|
Note: sleep\_cmd is unset by default, meaning it's hidden and has no effect.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,9 @@ asterisk = *
|
||||||
# Erase password input on failure
|
# Erase password input on failure
|
||||||
clear_password = false
|
clear_password = false
|
||||||
|
|
||||||
|
# Enable vi keybindings
|
||||||
|
vi_mode = false
|
||||||
|
|
||||||
# The `fg` and `bg` color settings take a digit 0-8 corresponding to:
|
# The `fg` and `bg` color settings take a digit 0-8 corresponding to:
|
||||||
#define TB_DEFAULT 0x00
|
#define TB_DEFAULT 0x00
|
||||||
#define TB_BLACK 0x01
|
#define TB_BLACK 0x01
|
||||||
|
|
|
||||||
|
|
@ -120,7 +120,7 @@ pub fn draw(self: *Matrix) void {
|
||||||
// Head's down offscreen
|
// Head's down offscreen
|
||||||
if (i > buf_height) {
|
if (i > buf_height) {
|
||||||
self.dots[buf_width * tail + j].value = ' ';
|
self.dots[buf_width * tail + j].value = ' ';
|
||||||
continue :height_it;
|
break :height_it;
|
||||||
}
|
}
|
||||||
dot = &self.dots[buf_width * i + j];
|
dot = &self.dots[buf_width * i + j];
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -355,7 +355,7 @@ fn xauth(display_name: [:0]u8, shell: [*:0]const u8, pw_dir: [*:0]const u8, xaut
|
||||||
const pid = std.c.fork();
|
const pid = std.c.fork();
|
||||||
|
|
||||||
if (pid == 0) {
|
if (pid == 0) {
|
||||||
var cmd_buffer = std.mem.zeroes([1024]u8);
|
var cmd_buffer: [1024]u8 = undefined;
|
||||||
const cmd_str = try std.fmt.bufPrintZ(&cmd_buffer, "{s} add {s} . $({s})", .{ xauth_cmd, display_name, mcookie_cmd });
|
const cmd_str = try std.fmt.bufPrintZ(&cmd_buffer, "{s} add {s} . $({s})", .{ xauth_cmd, display_name, mcookie_cmd });
|
||||||
_ = interop.execl(shell, shell, "-c", cmd_str.ptr, @as([*c]const u8, 0));
|
_ = interop.execl(shell, shell, "-c", cmd_str.ptr, @as([*c]const u8, 0));
|
||||||
std.os.exit(0);
|
std.os.exit(0);
|
||||||
|
|
@ -366,7 +366,7 @@ fn xauth(display_name: [:0]u8, shell: [*:0]const u8, pw_dir: [*:0]const u8, xaut
|
||||||
}
|
}
|
||||||
|
|
||||||
fn executeWaylandCmd(shell: [*:0]const u8, wayland_cmd: []const u8, desktop_cmd: []const u8) !void {
|
fn executeWaylandCmd(shell: [*:0]const u8, wayland_cmd: []const u8, desktop_cmd: []const u8) !void {
|
||||||
var cmd_buffer = std.mem.zeroes([1024]u8);
|
var cmd_buffer: [1024]u8 = undefined;
|
||||||
|
|
||||||
const cmd_str = try std.fmt.bufPrintZ(&cmd_buffer, "{s} {s}", .{ wayland_cmd, desktop_cmd });
|
const cmd_str = try std.fmt.bufPrintZ(&cmd_buffer, "{s} {s}", .{ wayland_cmd, desktop_cmd });
|
||||||
_ = interop.execl(shell, shell, "-c", cmd_str.ptr, @as([*c]const u8, 0));
|
_ = interop.execl(shell, shell, "-c", cmd_str.ptr, @as([*c]const u8, 0));
|
||||||
|
|
@ -380,7 +380,7 @@ fn executeX11Cmd(shell: [*:0]const u8, pw_dir: [*:0]const u8, config: Config, de
|
||||||
|
|
||||||
const pid = std.c.fork();
|
const pid = std.c.fork();
|
||||||
if (pid == 0) {
|
if (pid == 0) {
|
||||||
var cmd_buffer = std.mem.zeroes([1024]u8);
|
var cmd_buffer: [1024]u8 = undefined;
|
||||||
const cmd_str = try std.fmt.bufPrintZ(&cmd_buffer, "{s} {s} {s}", .{ config.x_cmd, display_name, vt });
|
const cmd_str = try std.fmt.bufPrintZ(&cmd_buffer, "{s} {s} {s}", .{ config.x_cmd, display_name, vt });
|
||||||
_ = interop.execl(shell, shell, "-c", cmd_str.ptr, @as([*c]const u8, 0));
|
_ = interop.execl(shell, shell, "-c", cmd_str.ptr, @as([*c]const u8, 0));
|
||||||
std.os.exit(0);
|
std.os.exit(0);
|
||||||
|
|
@ -405,7 +405,7 @@ fn executeX11Cmd(shell: [*:0]const u8, pw_dir: [*:0]const u8, config: Config, de
|
||||||
|
|
||||||
const xorg_pid = std.c.fork();
|
const xorg_pid = std.c.fork();
|
||||||
if (xorg_pid == 0) {
|
if (xorg_pid == 0) {
|
||||||
var cmd_buffer = std.mem.zeroes([1024]u8);
|
var cmd_buffer: [1024]u8 = undefined;
|
||||||
const cmd_str = try std.fmt.bufPrintZ(&cmd_buffer, "{s} {s}", .{ config.x_cmd_setup, desktop_cmd });
|
const cmd_str = try std.fmt.bufPrintZ(&cmd_buffer, "{s} {s}", .{ config.x_cmd_setup, desktop_cmd });
|
||||||
_ = interop.execl(shell, shell, "-c", cmd_str.ptr, @as([*c]const u8, 0));
|
_ = interop.execl(shell, shell, "-c", cmd_str.ptr, @as([*c]const u8, 0));
|
||||||
std.os.exit(0);
|
std.os.exit(0);
|
||||||
|
|
|
||||||
|
|
@ -43,6 +43,7 @@ sleep_key: []const u8 = "F3",
|
||||||
term_reset_cmd: []const u8 = "/usr/bin/tput reset",
|
term_reset_cmd: []const u8 = "/usr/bin/tput reset",
|
||||||
term_restore_cursor_cmd: []const u8 = "/usr/bin/tput cnorm",
|
term_restore_cursor_cmd: []const u8 = "/usr/bin/tput cnorm",
|
||||||
tty: u8 = 2,
|
tty: u8 = 2,
|
||||||
|
vi_mode: bool = false,
|
||||||
wayland_cmd: []const u8 = build_options.data_directory ++ "/wsetup.sh",
|
wayland_cmd: []const u8 = build_options.data_directory ++ "/wsetup.sh",
|
||||||
waylandsessions: []const u8 = "/usr/share/wayland-sessions",
|
waylandsessions: []const u8 = "/usr/share/wayland-sessions",
|
||||||
x_cmd: []const u8 = "/usr/bin/X",
|
x_cmd: []const u8 = "/usr/bin/X",
|
||||||
|
|
|
||||||
|
|
@ -36,8 +36,10 @@ err_user_init: []const u8 = "failed to initialize user",
|
||||||
err_user_uid: []const u8 = "failed to set user UID",
|
err_user_uid: []const u8 = "failed to set user UID",
|
||||||
err_xsessions_dir: []const u8 = "failed to find sessions folder",
|
err_xsessions_dir: []const u8 = "failed to find sessions folder",
|
||||||
err_xsessions_open: []const u8 = "failed to open sessions folder",
|
err_xsessions_open: []const u8 = "failed to open sessions folder",
|
||||||
|
insert: []const u8 = "Insert",
|
||||||
login: []const u8 = "login:",
|
login: []const u8 = "login:",
|
||||||
logout: []const u8 = "logged out",
|
logout: []const u8 = "logged out",
|
||||||
|
normal: []const u8 = "Normal",
|
||||||
numlock: []const u8 = "numlock",
|
numlock: []const u8 = "numlock",
|
||||||
password: []const u8 = "password:",
|
password: []const u8 = "password:",
|
||||||
restart: []const u8 = "reboot",
|
restart: []const u8 = "reboot",
|
||||||
|
|
@ -45,4 +47,4 @@ shell: []const u8 = "shell",
|
||||||
shutdown: []const u8 = "shutdown",
|
shutdown: []const u8 = "shutdown",
|
||||||
sleep: []const u8 = "sleep",
|
sleep: []const u8 = "sleep",
|
||||||
wayland: []const u8 = "wayland",
|
wayland: []const u8 = "wayland",
|
||||||
xinitrc: []const u8 = "xinitrc"
|
xinitrc: []const u8 = "xinitrc",
|
||||||
|
|
|
||||||
|
|
@ -16,3 +16,8 @@ pub const Input = enum {
|
||||||
login,
|
login,
|
||||||
password,
|
password,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
pub const ViMode = enum {
|
||||||
|
normal,
|
||||||
|
insert,
|
||||||
|
};
|
||||||
|
|
|
||||||
69
src/main.zig
69
src/main.zig
|
|
@ -15,6 +15,7 @@ const ini = @import("config/ini.zig");
|
||||||
const Lang = @import("config/Lang.zig");
|
const Lang = @import("config/Lang.zig");
|
||||||
const Save = @import("config/Save.zig");
|
const Save = @import("config/Save.zig");
|
||||||
const LogFile = @import("logger/LogFile.zig");
|
const LogFile = @import("logger/LogFile.zig");
|
||||||
|
const ViMode = @import("enums.zig").ViMode;
|
||||||
|
|
||||||
const Ini = ini.Ini;
|
const Ini = ini.Ini;
|
||||||
const termbox = interop.termbox;
|
const termbox = interop.termbox;
|
||||||
|
|
@ -150,6 +151,7 @@ pub fn main() !void {
|
||||||
defer password.deinit();
|
defer password.deinit();
|
||||||
|
|
||||||
var active_input = config.default_input;
|
var active_input = config.default_input;
|
||||||
|
var vi_mode: ViMode = if (config.vi_mode) .normal else .insert;
|
||||||
|
|
||||||
// Load last saved username and desktop selection, if any
|
// Load last saved username and desktop selection, if any
|
||||||
if (config.load) {
|
if (config.load) {
|
||||||
|
|
@ -178,11 +180,11 @@ pub fn main() !void {
|
||||||
password.position(coordinates.x, coordinates.y + 6, coordinates.visible_length);
|
password.position(coordinates.x, coordinates.y + 6, coordinates.visible_length);
|
||||||
|
|
||||||
switch (active_input) {
|
switch (active_input) {
|
||||||
.session => desktop.handle(null),
|
.session => desktop.handle(null, vi_mode),
|
||||||
.login => login.handle(null) catch {
|
.login => login.handle(null, vi_mode) catch {
|
||||||
info_line = lang.err_alloc;
|
info_line = lang.err_alloc;
|
||||||
},
|
},
|
||||||
.password => password.handle(null) catch {
|
.password => password.handle(null, vi_mode) catch {
|
||||||
info_line = lang.err_alloc;
|
info_line = lang.err_alloc;
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
@ -280,11 +282,11 @@ pub fn main() !void {
|
||||||
// If the user entered a wrong password 10 times in a row, play a cascade animation, else update normally
|
// If the user entered a wrong password 10 times in a row, play a cascade animation, else update normally
|
||||||
if (auth_fails < 10) {
|
if (auth_fails < 10) {
|
||||||
switch (active_input) {
|
switch (active_input) {
|
||||||
.session => desktop.handle(null),
|
.session => desktop.handle(null, vi_mode),
|
||||||
.login => login.handle(null) catch {
|
.login => login.handle(null, vi_mode) catch {
|
||||||
info_line = lang.err_alloc;
|
info_line = lang.err_alloc;
|
||||||
},
|
},
|
||||||
.password => password.handle(null) catch {
|
.password => password.handle(null, vi_mode) catch {
|
||||||
info_line = lang.err_alloc;
|
info_line = lang.err_alloc;
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
@ -373,6 +375,11 @@ pub fn main() !void {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (config.vi_mode) {
|
||||||
|
const label_txt = if (vi_mode == .normal) lang.normal else lang.insert;
|
||||||
|
buffer.drawLabel(label_txt, buffer.box_x, buffer.box_y - 1);
|
||||||
|
}
|
||||||
|
|
||||||
draw_lock_state: {
|
draw_lock_state: {
|
||||||
const lock_state = interop.getLockState(allocator, config.console_dev) catch |err| {
|
const lock_state = interop.getLockState(allocator, config.console_dev) catch |err| {
|
||||||
if (err == error.CannotOpenConsoleDev) {
|
if (err == error.CannotOpenConsoleDev) {
|
||||||
|
|
@ -440,15 +447,22 @@ pub fn main() !void {
|
||||||
if (event_error < 0 or event.type != termbox.TB_EVENT_KEY) continue;
|
if (event_error < 0 or event.type != termbox.TB_EVENT_KEY) continue;
|
||||||
|
|
||||||
switch (event.key) {
|
switch (event.key) {
|
||||||
termbox.TB_KEY_F1, termbox.TB_KEY_F2, termbox.TB_KEY_F3, termbox.TB_KEY_F4, termbox.TB_KEY_F5, termbox.TB_KEY_F6, termbox.TB_KEY_F7, termbox.TB_KEY_F8, termbox.TB_KEY_F9, termbox.TB_KEY_F10, termbox.TB_KEY_F11, termbox.TB_KEY_F12 => {
|
termbox.TB_KEY_ESC => {
|
||||||
if (0xFFFF - event.key + 1 == shutdown_key) {
|
if (config.vi_mode and vi_mode != .normal) {
|
||||||
|
vi_mode = .normal;
|
||||||
|
update = true;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
termbox.TB_KEY_F12...termbox.TB_KEY_F1 => {
|
||||||
|
const pressed_key = 0xFFFF - event.key + 1;
|
||||||
|
if (pressed_key == shutdown_key) {
|
||||||
shutdown = true;
|
shutdown = true;
|
||||||
run = false;
|
run = false;
|
||||||
} else if (0xFFFF - event.key + 1 == restart_key) {
|
} else if (pressed_key == restart_key) {
|
||||||
restart = true;
|
restart = true;
|
||||||
run = false;
|
run = false;
|
||||||
} else if (0xFFFF - event.key + 1 == sleep_key and config.sleep_cmd != null) {
|
} else if (pressed_key == sleep_key and config.sleep_cmd != null) {
|
||||||
const pid = std.c.fork();
|
const pid = try std.os.fork();
|
||||||
if (pid == 0) {
|
if (pid == 0) {
|
||||||
std.process.execv(allocator, &[_][]const u8{ "/bin/sh", "-c", config.sleep_cmd.? }) catch {};
|
std.process.execv(allocator, &[_][]const u8{ "/bin/sh", "-c", config.sleep_cmd.? }) catch {};
|
||||||
}
|
}
|
||||||
|
|
@ -524,12 +538,39 @@ pub fn main() !void {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
else => {
|
else => {
|
||||||
|
if (vi_mode == .normal) {
|
||||||
|
switch (event.ch) {
|
||||||
|
'k' => {
|
||||||
|
active_input = switch (active_input) {
|
||||||
|
.session, .login => .session,
|
||||||
|
.password => .login,
|
||||||
|
};
|
||||||
|
update = true;
|
||||||
|
continue;
|
||||||
|
},
|
||||||
|
'j' => {
|
||||||
|
active_input = switch (active_input) {
|
||||||
|
.session => .login,
|
||||||
|
.login, .password => .password,
|
||||||
|
};
|
||||||
|
update = true;
|
||||||
|
continue;
|
||||||
|
},
|
||||||
|
'i' => {
|
||||||
|
vi_mode = .insert;
|
||||||
|
update = true;
|
||||||
|
continue;
|
||||||
|
},
|
||||||
|
else => {},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
switch (active_input) {
|
switch (active_input) {
|
||||||
.session => desktop.handle(&event),
|
.session => desktop.handle(&event, vi_mode),
|
||||||
.login => login.handle(&event) catch {
|
.login => login.handle(&event, vi_mode) catch {
|
||||||
info_line = lang.err_alloc;
|
info_line = lang.err_alloc;
|
||||||
},
|
},
|
||||||
.password => password.handle(&event) catch {
|
.password => password.handle(&event, vi_mode) catch {
|
||||||
info_line = lang.err_alloc;
|
info_line = lang.err_alloc;
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@ const Allocator = std.mem.Allocator;
|
||||||
const EnvironmentList = std.ArrayList(Environment);
|
const EnvironmentList = std.ArrayList(Environment);
|
||||||
|
|
||||||
const DisplayServer = enums.DisplayServer;
|
const DisplayServer = enums.DisplayServer;
|
||||||
|
const ViMode = enums.ViMode;
|
||||||
|
|
||||||
const termbox = interop.termbox;
|
const termbox = interop.termbox;
|
||||||
|
|
||||||
|
|
@ -115,16 +116,24 @@ pub fn crawl(self: *Desktop, path: []const u8, display_server: DisplayServer) !v
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn handle(self: *Desktop, maybe_event: ?*termbox.tb_event) void {
|
pub fn handle(self: *Desktop, maybe_event: ?*termbox.tb_event, vi_mode: ViMode) void {
|
||||||
if (maybe_event) |event| blk: {
|
if (maybe_event) |event| blk: {
|
||||||
if (event.type != termbox.TB_EVENT_KEY) break :blk;
|
if (event.type != termbox.TB_EVENT_KEY) break :blk;
|
||||||
|
|
||||||
switch (event.key) {
|
switch (event.key) {
|
||||||
termbox.TB_KEY_ARROW_LEFT, termbox.TB_KEY_CTRL_H => self.goLeft(),
|
termbox.TB_KEY_ARROW_LEFT, termbox.TB_KEY_CTRL_H => self.goLeft(),
|
||||||
termbox.TB_KEY_ARROW_RIGHT, termbox.TB_KEY_CTRL_L => self.goRight(),
|
termbox.TB_KEY_ARROW_RIGHT, termbox.TB_KEY_CTRL_L => self.goRight(),
|
||||||
|
else => {
|
||||||
|
if (vi_mode == .normal) {
|
||||||
|
switch (event.ch) {
|
||||||
|
'h' => self.goLeft(),
|
||||||
|
'l' => self.goRight(),
|
||||||
else => {},
|
else => {},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
termbox.tb_set_cursor(@intCast(self.x + 2), @intCast(self.y));
|
termbox.tb_set_cursor(@intCast(self.x + 2), @intCast(self.y));
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ const std = @import("std");
|
||||||
const interop = @import("../../interop.zig");
|
const interop = @import("../../interop.zig");
|
||||||
const TerminalBuffer = @import("../TerminalBuffer.zig");
|
const TerminalBuffer = @import("../TerminalBuffer.zig");
|
||||||
const utils = @import("../utils.zig");
|
const utils = @import("../utils.zig");
|
||||||
|
const ViMode = @import("../../enums.zig").ViMode;
|
||||||
|
|
||||||
const Allocator = std.mem.Allocator;
|
const Allocator = std.mem.Allocator;
|
||||||
const DynamicString = std.ArrayList(u8);
|
const DynamicString = std.ArrayList(u8);
|
||||||
|
|
@ -46,7 +47,7 @@ pub fn position(self: *Text, x: u64, y: u64, visible_length: u64) void {
|
||||||
self.visible_length = visible_length;
|
self.visible_length = visible_length;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn handle(self: *Text, maybe_event: ?*termbox.tb_event) !void {
|
pub fn handle(self: *Text, maybe_event: ?*termbox.tb_event, vi_mode: ViMode) !void {
|
||||||
if (maybe_event) |event| blk: {
|
if (maybe_event) |event| blk: {
|
||||||
if (event.type != termbox.TB_EVENT_KEY) break :blk;
|
if (event.type != termbox.TB_EVENT_KEY) break :blk;
|
||||||
|
|
||||||
|
|
@ -54,9 +55,27 @@ pub fn handle(self: *Text, maybe_event: ?*termbox.tb_event) !void {
|
||||||
termbox.TB_KEY_ARROW_LEFT => self.goLeft(),
|
termbox.TB_KEY_ARROW_LEFT => self.goLeft(),
|
||||||
termbox.TB_KEY_ARROW_RIGHT => self.goRight(),
|
termbox.TB_KEY_ARROW_RIGHT => self.goRight(),
|
||||||
termbox.TB_KEY_DELETE => self.delete(),
|
termbox.TB_KEY_DELETE => self.delete(),
|
||||||
termbox.TB_KEY_BACKSPACE, termbox.TB_KEY_BACKSPACE2 => self.backspace(),
|
termbox.TB_KEY_BACKSPACE, termbox.TB_KEY_BACKSPACE2 => {
|
||||||
|
if (vi_mode == .insert) {
|
||||||
|
self.backspace();
|
||||||
|
} else {
|
||||||
|
self.goLeft();
|
||||||
|
}
|
||||||
|
},
|
||||||
termbox.TB_KEY_SPACE => try self.write(' '),
|
termbox.TB_KEY_SPACE => try self.write(' '),
|
||||||
else => if (event.ch > 31 and event.ch < 127) try self.write(@intCast(event.ch)),
|
else => {
|
||||||
|
if (event.ch > 31 and event.ch < 127) {
|
||||||
|
if (vi_mode == .insert) {
|
||||||
|
try self.write(@intCast(event.ch));
|
||||||
|
} else {
|
||||||
|
switch (event.ch) {
|
||||||
|
'h' => self.goLeft(),
|
||||||
|
'l' => self.goRight(),
|
||||||
|
else => {},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue