Merge pull request #1350 from jcollie/keybind-docs

Generate help strings for keybind actions and use them in manpages and +list-keybinds.
This commit is contained in:
Mitchell Hashimoto
2024-01-21 20:51:05 -08:00
committed by GitHub
5 changed files with 89 additions and 37 deletions

View File

@ -3,6 +3,7 @@ const help_strings = @import("help_strings");
const build_options = @import("build_options"); const build_options = @import("build_options");
const Config = @import("../../config/Config.zig"); const Config = @import("../../config/Config.zig");
const Action = @import("../../cli/action.zig").Action; const Action = @import("../../cli/action.zig").Action;
const KeybindAction = @import("../../input/Binding.zig").Action;
pub fn substitute(alloc: std.mem.Allocator, input: []const u8, writer: anytype) !void { pub fn substitute(alloc: std.mem.Allocator, input: []const u8, writer: anytype) !void {
const version_string = try std.fmt.allocPrint(alloc, "{}", .{build_options.version}); const version_string = try std.fmt.allocPrint(alloc, "{}", .{build_options.version});
@ -83,3 +84,35 @@ pub fn genActions(writer: anytype) !void {
} }
} }
} }
pub fn genKeybindActions(writer: anytype) !void {
try writer.writeAll(
\\
\\# KEYBIND ACTIONS
\\
\\
);
const info = @typeInfo(KeybindAction);
std.debug.assert(info == .Union);
inline for (info.Union.fields) |field| {
if (field.name[0] == '_') continue;
try writer.writeAll("`");
try writer.writeAll(field.name);
try writer.writeAll("`\n\n");
if (@hasDecl(help_strings.KeybindAction, field.name)) {
var iter = std.mem.splitScalar(u8, @field(help_strings.KeybindAction, field.name), '\n');
var first = true;
while (iter.next()) |s| {
try writer.writeAll(if (first) ": " else " ");
try writer.writeAll(s);
try writer.writeAll("\n");
first = false;
}
try writer.writeAll("\n\n");
}
}
}

View File

@ -1,5 +1,4 @@
const std = @import("std"); const std = @import("std");
const inputpkg = @import("../input.zig");
const args = @import("args.zig"); const args = @import("args.zig");
const Action = @import("action.zig").Action; const Action = @import("action.zig").Action;
const Arena = std.heap.ArenaAllocator; const Arena = std.heap.ArenaAllocator;

View File

@ -6,6 +6,7 @@ const std = @import("std");
const ziglyph = @import("ziglyph"); const ziglyph = @import("ziglyph");
const Config = @import("config/Config.zig"); const Config = @import("config/Config.zig");
const Action = @import("cli/action.zig").Action; const Action = @import("cli/action.zig").Action;
const KeybindAction = @import("input/Binding.zig").Action;
pub fn main() !void { pub fn main() !void {
var gpa = std.heap.GeneralPurposeAllocator(.{}){}; var gpa = std.heap.GeneralPurposeAllocator(.{}){};
@ -20,6 +21,7 @@ pub fn main() !void {
try genConfig(alloc, stdout); try genConfig(alloc, stdout);
try genActions(alloc, stdout); try genActions(alloc, stdout);
try genKeybindActions(alloc, stdout);
} }
fn genConfig(alloc: std.mem.Allocator, writer: anytype) !void { fn genConfig(alloc: std.mem.Allocator, writer: anytype) !void {
@ -114,6 +116,25 @@ fn genActions(alloc: std.mem.Allocator, writer: anytype) !void {
try writer.writeAll("};\n"); try writer.writeAll("};\n");
} }
fn genKeybindActions(alloc: std.mem.Allocator, writer: anytype) !void {
var ast = try std.zig.Ast.parse(alloc, @embedFile("input/Binding.zig"), .zig);
defer ast.deinit(alloc);
try writer.writeAll(
\\/// keybind actions help
\\pub const KeybindAction = struct {
\\
\\
);
inline for (@typeInfo(KeybindAction).Union.fields) |field| {
if (field.name[0] == '_') continue;
try genConfigField(alloc, writer, ast, field.name);
}
try writer.writeAll("};\n");
}
fn extractDocComments( fn extractDocComments(
alloc: std.mem.Allocator, alloc: std.mem.Allocator,
ast: std.zig.Ast, ast: std.zig.Ast,

View File

@ -118,41 +118,40 @@ pub fn parse(raw_input: []const u8) !Binding {
/// The set of actions that a keybinding can take. /// The set of actions that a keybinding can take.
pub const Action = union(enum) { pub const Action = union(enum) {
/// Ignore this key combination, don't send it to the child process, /// Ignore this key combination, don't send it to the child process, just
/// just black hole it. /// black hole it.
ignore: void, ignore: void,
/// This action is used to flag that the binding should be removed /// This action is used to flag that the binding should be removed from
/// from the set. This should never exist in an active set and /// the set. This should never exist in an active set and `set.put` has an
/// `set.put` has an assertion to verify this. /// assertion to verify this.
unbind: void, unbind: void,
/// Send a CSI sequence. The value should be the CSI sequence /// Send a CSI sequence. The value should be the CSI sequence without the
/// without the CSI header ("ESC ]" or "\x1b]"). /// CSI header (`ESC ]` or `\x1b]`).
csi: []const u8, csi: []const u8,
/// Send an ESC sequence. /// Send an `ESC` sequence.
esc: []const u8, esc: []const u8,
// Send the given text. Uses Zig string literal syntax. This is // Send the given text. Uses Zig string literal syntax. This is currently
// currently not validated. If the text is invalid (i.e. contains // not validated. If the text is invalid (i.e. contains an invalid escape
// an invalid escape sequence), the error will currently only show // sequence), the error will currently only show up in logs.
// up in logs.
text: []const u8, text: []const u8,
/// Send data to the pty depending on whether cursor key mode is /// Send data to the pty depending on whether cursor key mode is enabled
/// enabled ("application") or disabled ("normal"). /// (`application`) or disabled (`normal`).
cursor_key: CursorKey, cursor_key: CursorKey,
/// Copy and paste. /// Copy and paste.
copy_to_clipboard: void, copy_to_clipboard: void,
paste_from_clipboard: void, paste_from_clipboard: void,
/// Increase/decrease the font size by a certain amount /// Increase/decrease the font size by a certain amount.
increase_font_size: u16, increase_font_size: u16,
decrease_font_size: u16, decrease_font_size: u16,
/// Reset the font size to the original configured size /// Reset the font size to the original configured size.
reset_font_size: void, reset_font_size: void,
/// Clear the screen. This also clears all scrollback. /// Clear the screen. This also clears all scrollback.
@ -169,32 +168,31 @@ pub const Action = union(enum) {
scroll_page_fractional: f32, scroll_page_fractional: f32,
scroll_page_lines: i16, scroll_page_lines: i16,
/// Jump the viewport forward or back by prompt. Positive /// Jump the viewport forward or back by prompt. Positive number is the
/// number is the number of prompts to jump forward, negative /// number of prompts to jump forward, negative is backwards.
/// is backwards.
jump_to_prompt: i16, jump_to_prompt: i16,
/// Write the entire scrollback into a temporary file and write the /// Write the entire scrollback into a temporary file and write the path to
/// path to the file to the tty. /// the file to the tty.
write_scrollback_file: void, write_scrollback_file: void,
/// Open a new window /// Open a new window.
new_window: void, new_window: void,
/// Open a new tab /// Open a new tab.
new_tab: void, new_tab: void,
/// Go to the previous tab /// Go to the previous tab.
previous_tab: void, previous_tab: void,
/// Go to the next tab /// Go to the next tab.
next_tab: void, next_tab: void,
/// Go to the tab with the specific number, 1-indexed. /// Go to the tab with the specific number, 1-indexed.
goto_tab: usize, goto_tab: usize,
/// Create a new split in the given direction. The new split will appear /// Create a new split in the given direction. The new split will appear in
/// in the direction given. /// the direction given.
new_split: SplitDirection, new_split: SplitDirection,
/// Focus on a split in a given direction. /// Focus on a split in a given direction.
@ -210,13 +208,13 @@ pub const Action = union(enum) {
/// Equalize all splits in the current window /// Equalize all splits in the current window
equalize_splits: void, equalize_splits: void,
/// Show, hide, or toggle the terminal inspector for the currently /// Show, hide, or toggle the terminal inspector for the currently focused
/// focused terminal. /// terminal.
inspector: InspectorMode, inspector: InspectorMode,
/// Open the configuration file in the default OS editor. If your default /// Open the configuration file in the default OS editor. If your default OS
/// OS editor isn't configured then this will fail. Currently, any failures /// editor isn't configured then this will fail. Currently, any failures to
/// to open the configuration will show up only in the logs. /// open the configuration will show up only in the logs.
open_config: void, open_config: void,
/// Reload the configuration. The exact meaning depends on the app runtime /// Reload the configuration. The exact meaning depends on the app runtime
@ -225,9 +223,9 @@ pub const Action = union(enum) {
/// runtime. /// runtime.
reload_config: void, reload_config: void,
/// Close the current "surface", whether that is a window, tab, split, /// Close the current "surface", whether that is a window, tab, split, etc.
/// etc. This only closes ONE surface. This will trigger close confirmation /// This only closes ONE surface. This will trigger close confirmation as
/// as configured. /// configured.
close_surface: void, close_surface: void,
/// Close the window, regardless of how many tabs or splits there may be. /// Close the window, regardless of how many tabs or splits there may be.
@ -241,7 +239,7 @@ pub const Action = union(enum) {
/// Toggle fullscreen mode of window. /// Toggle fullscreen mode of window.
toggle_fullscreen: void, toggle_fullscreen: void,
/// Quit ghostty /// Quit ghostty.
quit: void, quit: void,
pub const CursorKey = struct { pub const CursorKey = struct {

View File

@ -8,5 +8,6 @@ pub fn main() !void {
const output = std.io.getStdOut().writer(); const output = std.io.getStdOut().writer();
try gen.substitute(alloc, @embedFile("build/mdgen/ghostty_5_header.md"), output); try gen.substitute(alloc, @embedFile("build/mdgen/ghostty_5_header.md"), output);
try gen.genConfig(output, false); try gen.genConfig(output, false);
try gen.genKeybindActions(output);
try gen.substitute(alloc, @embedFile("build/mdgen/ghostty_5_footer.md"), output); try gen.substitute(alloc, @embedFile("build/mdgen/ghostty_5_footer.md"), output);
} }