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.
|
||||
+ 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).
|
||||
+ 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.
|
||||
|
||||
|
|
|
|||
|
|
@ -16,6 +16,9 @@ asterisk = *
|
|||
# Erase password input on failure
|
||||
clear_password = false
|
||||
|
||||
# Enable vi keybindings
|
||||
vi_mode = false
|
||||
|
||||
# The `fg` and `bg` color settings take a digit 0-8 corresponding to:
|
||||
#define TB_DEFAULT 0x00
|
||||
#define TB_BLACK 0x01
|
||||
|
|
|
|||
|
|
@ -120,7 +120,7 @@ pub fn draw(self: *Matrix) void {
|
|||
// Head's down offscreen
|
||||
if (i > buf_height) {
|
||||
self.dots[buf_width * tail + j].value = ' ';
|
||||
continue :height_it;
|
||||
break :height_it;
|
||||
}
|
||||
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();
|
||||
|
||||
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 });
|
||||
_ = interop.execl(shell, shell, "-c", cmd_str.ptr, @as([*c]const u8, 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 {
|
||||
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 });
|
||||
_ = 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();
|
||||
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 });
|
||||
_ = interop.execl(shell, shell, "-c", cmd_str.ptr, @as([*c]const u8, 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();
|
||||
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 });
|
||||
_ = interop.execl(shell, shell, "-c", cmd_str.ptr, @as([*c]const u8, 0));
|
||||
std.os.exit(0);
|
||||
|
|
|
|||
|
|
@ -43,6 +43,7 @@ sleep_key: []const u8 = "F3",
|
|||
term_reset_cmd: []const u8 = "/usr/bin/tput reset",
|
||||
term_restore_cursor_cmd: []const u8 = "/usr/bin/tput cnorm",
|
||||
tty: u8 = 2,
|
||||
vi_mode: bool = false,
|
||||
wayland_cmd: []const u8 = build_options.data_directory ++ "/wsetup.sh",
|
||||
waylandsessions: []const u8 = "/usr/share/wayland-sessions",
|
||||
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_xsessions_dir: []const u8 = "failed to find sessions folder",
|
||||
err_xsessions_open: []const u8 = "failed to open sessions folder",
|
||||
insert: []const u8 = "Insert",
|
||||
login: []const u8 = "login:",
|
||||
logout: []const u8 = "logged out",
|
||||
normal: []const u8 = "Normal",
|
||||
numlock: []const u8 = "numlock",
|
||||
password: []const u8 = "password:",
|
||||
restart: []const u8 = "reboot",
|
||||
|
|
@ -45,4 +47,4 @@ shell: []const u8 = "shell",
|
|||
shutdown: []const u8 = "shutdown",
|
||||
sleep: []const u8 = "sleep",
|
||||
wayland: []const u8 = "wayland",
|
||||
xinitrc: []const u8 = "xinitrc"
|
||||
xinitrc: []const u8 = "xinitrc",
|
||||
|
|
|
|||
|
|
@ -16,3 +16,8 @@ pub const Input = enum {
|
|||
login,
|
||||
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 Save = @import("config/Save.zig");
|
||||
const LogFile = @import("logger/LogFile.zig");
|
||||
const ViMode = @import("enums.zig").ViMode;
|
||||
|
||||
const Ini = ini.Ini;
|
||||
const termbox = interop.termbox;
|
||||
|
|
@ -150,6 +151,7 @@ pub fn main() !void {
|
|||
defer password.deinit();
|
||||
|
||||
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
|
||||
if (config.load) {
|
||||
|
|
@ -178,11 +180,11 @@ pub fn main() !void {
|
|||
password.position(coordinates.x, coordinates.y + 6, coordinates.visible_length);
|
||||
|
||||
switch (active_input) {
|
||||
.session => desktop.handle(null),
|
||||
.login => login.handle(null) catch {
|
||||
.session => desktop.handle(null, vi_mode),
|
||||
.login => login.handle(null, vi_mode) catch {
|
||||
info_line = lang.err_alloc;
|
||||
},
|
||||
.password => password.handle(null) catch {
|
||||
.password => password.handle(null, vi_mode) catch {
|
||||
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 (auth_fails < 10) {
|
||||
switch (active_input) {
|
||||
.session => desktop.handle(null),
|
||||
.login => login.handle(null) catch {
|
||||
.session => desktop.handle(null, vi_mode),
|
||||
.login => login.handle(null, vi_mode) catch {
|
||||
info_line = lang.err_alloc;
|
||||
},
|
||||
.password => password.handle(null) catch {
|
||||
.password => password.handle(null, vi_mode) catch {
|
||||
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: {
|
||||
const lock_state = interop.getLockState(allocator, config.console_dev) catch |err| {
|
||||
if (err == error.CannotOpenConsoleDev) {
|
||||
|
|
@ -440,15 +447,22 @@ pub fn main() !void {
|
|||
if (event_error < 0 or event.type != termbox.TB_EVENT_KEY) continue;
|
||||
|
||||
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 => {
|
||||
if (0xFFFF - event.key + 1 == shutdown_key) {
|
||||
termbox.TB_KEY_ESC => {
|
||||
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;
|
||||
run = false;
|
||||
} else if (0xFFFF - event.key + 1 == restart_key) {
|
||||
} else if (pressed_key == restart_key) {
|
||||
restart = true;
|
||||
run = false;
|
||||
} else if (0xFFFF - event.key + 1 == sleep_key and config.sleep_cmd != null) {
|
||||
const pid = std.c.fork();
|
||||
} else if (pressed_key == sleep_key and config.sleep_cmd != null) {
|
||||
const pid = try std.os.fork();
|
||||
if (pid == 0) {
|
||||
std.process.execv(allocator, &[_][]const u8{ "/bin/sh", "-c", config.sleep_cmd.? }) catch {};
|
||||
}
|
||||
|
|
@ -524,12 +538,39 @@ pub fn main() !void {
|
|||
}
|
||||
},
|
||||
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) {
|
||||
.session => desktop.handle(&event),
|
||||
.login => login.handle(&event) catch {
|
||||
.session => desktop.handle(&event, vi_mode),
|
||||
.login => login.handle(&event, vi_mode) catch {
|
||||
info_line = lang.err_alloc;
|
||||
},
|
||||
.password => password.handle(&event) catch {
|
||||
.password => password.handle(&event, vi_mode) catch {
|
||||
info_line = lang.err_alloc;
|
||||
},
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ const Allocator = std.mem.Allocator;
|
|||
const EnvironmentList = std.ArrayList(Environment);
|
||||
|
||||
const DisplayServer = enums.DisplayServer;
|
||||
const ViMode = enums.ViMode;
|
||||
|
||||
const termbox = interop.termbox;
|
||||
|
||||
|
|
@ -115,14 +116,22 @@ 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 (event.type != termbox.TB_EVENT_KEY) break :blk;
|
||||
|
||||
switch (event.key) {
|
||||
termbox.TB_KEY_ARROW_LEFT, termbox.TB_KEY_CTRL_H => self.goLeft(),
|
||||
termbox.TB_KEY_ARROW_RIGHT, termbox.TB_KEY_CTRL_L => self.goRight(),
|
||||
else => {},
|
||||
else => {
|
||||
if (vi_mode == .normal) {
|
||||
switch (event.ch) {
|
||||
'h' => self.goLeft(),
|
||||
'l' => self.goRight(),
|
||||
else => {},
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ const std = @import("std");
|
|||
const interop = @import("../../interop.zig");
|
||||
const TerminalBuffer = @import("../TerminalBuffer.zig");
|
||||
const utils = @import("../utils.zig");
|
||||
const ViMode = @import("../../enums.zig").ViMode;
|
||||
|
||||
const Allocator = std.mem.Allocator;
|
||||
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;
|
||||
}
|
||||
|
||||
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 (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_RIGHT => self.goRight(),
|
||||
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(' '),
|
||||
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