summaryrefslogtreecommitdiff
path: root/src/output_pane.zig
diff options
context:
space:
mode:
Diffstat (limited to 'src/output_pane.zig')
-rw-r--r--src/output_pane.zig61
1 files changed, 48 insertions, 13 deletions
diff --git a/src/output_pane.zig b/src/output_pane.zig
index 8c93709c..8ff98845 100644
--- a/src/output_pane.zig
+++ b/src/output_pane.zig
@@ -27,7 +27,7 @@ const config = @import("config.zig");
const lsp = @import("lsp/lsp.zig");
/// the installed fonts, for openFonts. GUI only, behind the same comptime
/// branch builtins.zig imports it through — see the note there.
-const fonts = if (pardes.platform == .gui) @import("gui/fonts.zig") else struct {};
+const fonts = if (pardes.font_picker) @import("fonts.zig") else struct {};
/// What opened this buffer — THE field, and the only input to `traits`.
///
@@ -385,12 +385,13 @@ pub fn openThemes(p: *Pardes, id: usize) !void {
/// stopping picks one. Everything that makes that work is already above; this
/// is the same eight lines pointed at a different list.
///
-/// GUI only, and the body says so rather than the signature: fonts.list and
-/// the FontSel origin both exist only there, and a comptime-false `if` is what
-/// keeps the tty build from analysing either. The dead parameters on that
-/// build are the honest shape of "this platform cannot open one".
+/// Only where the shell draws its own text, and the body says so rather than
+/// the signature: fonts.list and the FontSel origin both exist only there, and
+/// a comptime-false `if` is what keeps the tty build from analysing either.
+/// The dead parameters on that build are the honest shape of "this platform
+/// cannot open one".
pub fn openFonts(p: *Pardes, id: usize) !void {
- if (pardes.platform == .gui) {
+ if (pardes.font_picker) {
const arena = p.scratch.allocator();
const font_list = fonts.list(arena, null);
var len: usize = 0;
@@ -437,7 +438,6 @@ fn openStepped(p: *Pardes, id: usize, from: Origin, text: []const u8) !void {
/// case. A second builtin would have been a second renderer over a superset of
/// these rows, and the two would have drifted the first time a column moved.
pub fn openHelp(p: *Pardes, id: usize, prefix: []const u8) !void {
- const pane = p.panes[id] orelse return error.MissingPane;
const full_header = "pardes builtins, and how to run each:\nSPC and its keys, a chord, a button, the\ntopbar - or the name, executed anywhere.\n\n";
const group_header = "pardes builtins under SPC";
var len: usize = if (prefix.len == 0)
@@ -451,7 +451,6 @@ pub fn openHelp(p: *Pardes, id: usize, prefix: []const u8) !void {
len += row.line.len + 1;
}
const content = try p.gpa.alloc(u8, len);
- errdefer p.gpa.free(content);
var at: usize = 0;
if (prefix.len == 0) {
@memcpy(content[0..full_header.len], full_header);
@@ -476,15 +475,51 @@ pub fn openHelp(p: *Pardes, id: usize, prefix: []const u8) !void {
at += 1;
}
std.debug.assert(at == content.len);
- // the buffer says what made it, so finding the open one is asking that and
- // not matching its name
+ // content is handed off unfreed on purpose: openRead adopts it or frees
+ // it, and nothing between the alloc above and this line can fail.
+ return openRead(p, id, .{ .cmd = .Help }, prefix, content);
+}
+
+/// The Config builtin: WHERE the startup config file is, as one line of text.
+///
+/// The PATH and not the file. `Look` on the line opens it when it exists, and
+/// when it does not the path is still the entire answer — "put your Theme and
+/// Font lines HERE" is the question this is asked, and a builtin that opened
+/// an empty buffer instead would have said nothing. The core never resolved
+/// it: the launcher did, before init (Options.startup_config_path), so this
+/// prints what was actually consulted rather than recomputing a guess that
+/// could differ from it.
+pub fn openConfig(p: *Pardes, id: usize) !void {
+ const content = if (p.opts.startup_config_path) |path|
+ try std.fmt.allocPrint(p.gpa, "{s}\n", .{path})
+ else
+ // the browser, and a native launch with no HOME to build one from
+ try p.gpa.dupe(u8, "no per-user config path\n");
+ return openRead(p, id, .{ .cmd = .Config }, "", content);
+}
+
+/// Open a buffer you READ, and go there: the shared tail of every builtin
+/// whose answer is a document rather than a list. Asking again REFRESHES the
+/// one already open instead of stacking a twin beside it — found by its
+/// ORIGIN, never by matching its name, for the reason the whole file exists.
+///
+/// The mirror of `openStepped`, and the difference is the two lines at the
+/// ends: focus comes HERE (you asked to read it) where a results buffer
+/// leaves you in the pane that asked, and n/N are not armed, because prose
+/// has nowhere to step to.
+///
+/// `content` is gpa-owned: adopted by the buffer, or freed here when there is
+/// nowhere to put it.
+fn openRead(p: *Pardes, id: usize, from: Origin, arg: []const u8, content: []u8) !void {
+ errdefer p.gpa.free(content);
+ const pane = p.panes[id] orelse return error.MissingPane;
for (p.panes, 0..) |slot, i| {
const hp = slot orelse continue;
const hf = if (hp.file) |*f| f else continue;
const ho = if (hf.output) |*o| o else continue;
- if (!std.meta.eql(ho.from, Origin{ .cmd = .Help })) continue;
+ if (!std.meta.eql(ho.from, from)) continue;
file_pane.setContent(p, hf, content);
- setArg(ho, prefix);
+ setArg(ho, arg);
hf.scroll = 0;
hp.cur_row = 0;
hp.msel.active = false;
@@ -493,7 +528,7 @@ pub fn openHelp(p: *Pardes, id: usize, prefix: []const u8) !void {
}
const dir = if (pane.file) |f| (std.fs.path.dirname(f.path) orelse "/") else pane.cwdSlice();
const free = p.freeSlot() orelse return error.NoPaneSlots;
- const np = try open(p, free, dir, .{ .cmd = .Help }, prefix, content);
+ const np = try open(p, free, dir, from, arg, content);
p.placeDoc(id, free, np);
p.active = free;
}