-
Notifications
You must be signed in to change notification settings - Fork 689
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
config: window-inherit-working-directory options #1694
config: window-inherit-working-directory options #1694
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So far so good. Am I missing where the kind is actually set from the apprts?
For the const kind: CoreSurface.Kind = .window; // TODO
var config = try apprt.surface.newConfig(app.app, &app.config, kind); |
00bd212
to
4e088ac
Compare
4e088ac
to
22403b5
Compare
A few notes on the configuration parsing: Parsing BoolsTo maintain some backwards compatibility with the previous boolean config value, I added logic to the diff --git i/src/cli/args.zig w/src/cli/args.zig
index 49c5152a..acf9c839 100644
--- i/src/cli/args.zig
+++ w/src/cli/args.zig
@@ -281,6 +281,8 @@ fn parsePackedStruct(comptime T: type, v: []const u8) !T {
const info = @typeInfo(T).Struct;
assert(info.layout == .@"packed");
+ const parseBoolFn: ?std.builtin.Type.Fn = if (@hasDecl(T, "parseBool")) @typeInfo(@TypeOf(T.parseBool)).Fn else null;
+
var result: T = .{};
// We split each value by ","
@@ -306,6 +308,20 @@ fn parsePackedStruct(comptime T: type, v: []const u8) !T {
}
}
+ if (parseBoolFn) |pb| {
+ const b = parseBool(part) catch |err| switch (err) {
+ error.InvalidValue => continue :loop,
+ else => return err,
+ };
+
+ switch (pb.params.len) {
+ 2 => try result.parseBool(b),
+ else => @compileError("parseBool invalid argument count"),
+ }
+
+ continue :loop;
+ }
+
// No field matched
return error.InvalidValue;
} This felt like the most flexible approach, but there are two other related options we could take:
Default Field ValuesThe current This is why I have this line in my custom self.* = .{ .split = false, .tab = false, .window = false };
var iter = std.mem.splitSequence(u8, value, ",");
// ... I can't decide if this is a shortcoming of the currently If the former, it wouldn't be hard to fix -- reset all fields to "off" before parsing the new, explicit values -- but I thought I'd bring it up in context here first. With some blend of the above, configuration types like this new |
22403b5
to
fa421d1
Compare
fa421d1
to
18722d0
Compare
fbabc96
to
9e85018
Compare
In the interest of moving this forward, I simplified this to use the standard |
d38ff6d
to
b6215ee
Compare
Thanks @jparise. My main delay in merging this was that plus one more thing: I don't super love how information is flowing through this. It may be correct, though, but I want to spend some time thinking about it and just haven't yet... annoyingly, so sorry. |
No worries! Happy to take your feedback (once you find time for it), or if you'd prefer to restructure things yourself, that sounds great, too. |
9b68c6b
to
7d60959
Compare
I tried out another approach locally that moves the const font_size: f32 = font_size: { // ...
const working_directory: [*:0]const u8 = working_directory: { // ...
return .{
.font_size = font_size,
.working_directory = working_directory,
};
... but the downside is that it makes each apprt responsible for the Does this feel like a nicer approach to pursue? |
a76500e
to
a8d2d8b
Compare
I'm back to playing with this approach:
I generally prefer it, but I'm not sure "who" should own the All of these objects have different lifetimes, and I don't think I can add an allocator to Any advice, @mitchellh? |
a8d2d8b
to
5a9dfe6
Compare
I suppose I could try stuffing the ArenaAllocator into |
Sorry for neglecting this PR. I'm still on the fence about the approach. I go back and forth on it. With the recent tmux control mode issue, I've been considering making the core more aware of the window/tab/split hierarchy. That would make doing something like this a lot simpler I think (I mean, this PR is already only +/- like 80 lines, but I'm not sure about all the data ownership). I've also considered making the window vs tab vs split config related to the "conditional config" we've talked about in the issue for system theme changes. For example, I could imagine hypothetically letting you do That's my current line of thinking... anyways... sorry for the delay. |
That sounds good, although the trickier bits here have been more about configuration data flow and ownership rather than tracking the surface types. Any architectural improvements here would be easy to build upon, though!
Is the applicable idea that we'd have a general |
`window-inherit-working-directory` was previously a boolean value. This change makes it a more granular option, allowing you to enable this behavior for one or more surface "kinds": split, tab, window. The configuration value can be `true` (all), `false` (none), or a comma-delimited string of kinds (e.g. `tab` or `split,window`). The full behavior is only implemented for the embedded runtime and macOS app. The other runtimes still need their own plumbing to track surface kind creation (stubbed as `.window` by default in this change).
This setting previously defaulted to `true`, so flip all of our packed booleans on by default. Also, note that the granular values are only supported on macOS.
This introduces an ArenaAllocator that models the lifetime of the Surface.Options structure from initial surface creation command to the actual surface creation. This implementation is a little rough and relies on an `anyopaque` pointer (because `extern struct`), but it demonstrates a more apprt-centric approach. Still only implemented for embedded apprt and macOS. The other apprts will need their own plumbing to support this approach. We can also chose to clean up newConfig() and call Config.shallowClone() directly after this change.
5a9dfe6
to
2fb8434
Compare
I pushed an initial (rough) implementation of this approach for reference. Understood that it's probably not the approach we ultimately want to take with this. |
@@ -1499,6 +1541,7 @@ pub const CAPI = struct { | |||
app: *App, | |||
opts: *const apprt.Surface.Options, | |||
) !*Surface { | |||
defer @constCast(opts).deinit(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I acknowledge this is gross for multiple reasons.
Nothing that the work started in #2735 might provide what we need to unblock this aspect of this change. |
maybe it's better to make this as a parameter (enum) for
in this approach surface does not need to know anything about splits or tabs |
Chatted with @jparise on Discord awhile back about next steps for this PR and I think we're on the same page so I'm going to close this for now. The config bike shed isn't too hard, the hard part is actually the plumbing of awareness of what a thing is. Ghostty core isn't aware of what is a tab split window etc. That's all in the apprts. So plumbing that through in a thoughtful way is the "hard" part (not technically hard, but hard to design well). |
That's exactly right. I've tried a few versions of it but haven't landed on something that I liked enough to submit. |
window-inherit-working-directory
was previously a boolean value. This change makes it a more granular option, allowing you to enable this behavior for one or more surface "kinds": split, tab, window.The full behavior is only implemented for the embedded runtime and macOS app. The other runtimes still need their own plumbing to track surface kind creation (stubbed as
.window
by default in this change).Resolves #1392