macos: configurable undo timeout
parent
3e02c0cbd5
commit
49cc88f0d3
|
|
@ -77,7 +77,7 @@ class BaseTerminalController: NSWindowController,
|
||||||
|
|
||||||
/// The time that undo/redo operations that contain running ptys are valid for.
|
/// The time that undo/redo operations that contain running ptys are valid for.
|
||||||
var undoExpiration: Duration {
|
var undoExpiration: Duration {
|
||||||
.seconds(5)
|
ghostty.config.undoTimeout
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The undo manager for this controller is the undo manager of the window,
|
/// The undo manager for this controller is the undo manager of the window,
|
||||||
|
|
|
||||||
|
|
@ -506,6 +506,14 @@ extension Ghostty {
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var undoTimeout: Duration {
|
||||||
|
guard let config = self.config else { return .seconds(5) }
|
||||||
|
var v: UInt = 0
|
||||||
|
let key = "undo-timeout"
|
||||||
|
_ = ghostty_config_get(config, &v, key, UInt(key.count))
|
||||||
|
return .milliseconds(v)
|
||||||
|
}
|
||||||
|
|
||||||
var autoUpdate: AutoUpdate? {
|
var autoUpdate: AutoUpdate? {
|
||||||
guard let config = self.config else { return nil }
|
guard let config = self.config else { return nil }
|
||||||
var v: UnsafePointer<Int8>? = nil
|
var v: UnsafePointer<Int8>? = nil
|
||||||
|
|
|
||||||
|
|
@ -29,6 +29,9 @@ class ExpiringUndoManager: UndoManager {
|
||||||
expiresAfter duration: Duration,
|
expiresAfter duration: Duration,
|
||||||
handler: @escaping (TargetType) -> Void
|
handler: @escaping (TargetType) -> Void
|
||||||
) {
|
) {
|
||||||
|
// Ignore instantly expiring undos
|
||||||
|
guard duration.timeInterval > 0 else { return }
|
||||||
|
|
||||||
let expiringTarget = ExpiringTarget(
|
let expiringTarget = ExpiringTarget(
|
||||||
target,
|
target,
|
||||||
expiresAfter: duration,
|
expiresAfter: duration,
|
||||||
|
|
|
||||||
|
|
@ -1705,6 +1705,52 @@ keybind: Keybinds = .{},
|
||||||
/// window is ever created. Only implemented on Linux and macOS.
|
/// window is ever created. Only implemented on Linux and macOS.
|
||||||
@"initial-window": bool = true,
|
@"initial-window": bool = true,
|
||||||
|
|
||||||
|
/// The duration that undo operations remain available. After this
|
||||||
|
/// time, the operation will be removed from the undo stack and
|
||||||
|
/// cannot be undone.
|
||||||
|
///
|
||||||
|
/// The default value is 5 seconds.
|
||||||
|
///
|
||||||
|
/// This timeout applies per operation, meaning that if you perform
|
||||||
|
/// multiple operations, each operation will have its own timeout.
|
||||||
|
/// New operations do not reset the timeout of previous operations.
|
||||||
|
///
|
||||||
|
/// A timeout of zero will effectively disable undo operations. It is
|
||||||
|
/// not possible to set an infinite timeout, but you can set a very
|
||||||
|
/// large timeout to effectively disable the timeout (on the order of years).
|
||||||
|
/// This is highly discouraged, as it will cause the undo stack to grow
|
||||||
|
/// indefinitely, memory usage to grow unbounded, and terminal sessions
|
||||||
|
/// to never actually quit.
|
||||||
|
///
|
||||||
|
/// The duration is specified as a series of numbers followed by time units.
|
||||||
|
/// Whitespace is allowed between numbers and units. Each number and unit will
|
||||||
|
/// be added together to form the total duration.
|
||||||
|
///
|
||||||
|
/// The allowed time units are as follows:
|
||||||
|
///
|
||||||
|
/// * `y` - 365 SI days, or 8760 hours, or 31536000 seconds. No adjustments
|
||||||
|
/// are made for leap years or leap seconds.
|
||||||
|
/// * `d` - one SI day, or 86400 seconds.
|
||||||
|
/// * `h` - one hour, or 3600 seconds.
|
||||||
|
/// * `m` - one minute, or 60 seconds.
|
||||||
|
/// * `s` - one second.
|
||||||
|
/// * `ms` - one millisecond, or 0.001 second.
|
||||||
|
/// * `us` or `µs` - one microsecond, or 0.000001 second.
|
||||||
|
/// * `ns` - one nanosecond, or 0.000000001 second.
|
||||||
|
///
|
||||||
|
/// Examples:
|
||||||
|
/// * `1h30m`
|
||||||
|
/// * `45s`
|
||||||
|
///
|
||||||
|
/// Units can be repeated and will be added together. This means that
|
||||||
|
/// `1h1h` is equivalent to `2h`. This is confusing and should be avoided.
|
||||||
|
/// A future update may disallow this.
|
||||||
|
///
|
||||||
|
/// This configuration is only supported on macOS. Linux doesn't
|
||||||
|
/// support undo operations at all so this configuration has no
|
||||||
|
/// effect.
|
||||||
|
@"undo-timeout": Duration = .{ .duration = 5 * std.time.ns_per_s },
|
||||||
|
|
||||||
/// The position of the "quick" terminal window. To learn more about the
|
/// The position of the "quick" terminal window. To learn more about the
|
||||||
/// quick terminal, see the documentation for the `toggle_quick_terminal`
|
/// quick terminal, see the documentation for the `toggle_quick_terminal`
|
||||||
/// binding action.
|
/// binding action.
|
||||||
|
|
@ -6583,7 +6629,7 @@ pub const Duration = struct {
|
||||||
if (remaining.len == 0) break;
|
if (remaining.len == 0) break;
|
||||||
|
|
||||||
// Find the longest number
|
// Find the longest number
|
||||||
const number = number: {
|
const number: u64 = number: {
|
||||||
var prev_number: ?u64 = null;
|
var prev_number: ?u64 = null;
|
||||||
var prev_remaining: ?[]const u8 = null;
|
var prev_remaining: ?[]const u8 = null;
|
||||||
for (1..remaining.len + 1) |index| {
|
for (1..remaining.len + 1) |index| {
|
||||||
|
|
@ -6597,8 +6643,17 @@ pub const Duration = struct {
|
||||||
break :number prev_number;
|
break :number prev_number;
|
||||||
} orelse return error.InvalidValue;
|
} orelse return error.InvalidValue;
|
||||||
|
|
||||||
// A number without a unit is invalid
|
// A number without a unit is invalid unless the number is
|
||||||
if (remaining.len == 0) return error.InvalidValue;
|
// exactly zero. In that case, the unit is unambiguous since
|
||||||
|
// its all the same.
|
||||||
|
if (remaining.len == 0) {
|
||||||
|
if (number == 0) {
|
||||||
|
value = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return error.InvalidValue;
|
||||||
|
}
|
||||||
|
|
||||||
// Find the longest matching unit. Needs to be the longest matching
|
// Find the longest matching unit. Needs to be the longest matching
|
||||||
// to distinguish 'm' from 'ms'.
|
// to distinguish 'm' from 'ms'.
|
||||||
|
|
@ -6808,6 +6863,11 @@ test "parse duration" {
|
||||||
try std.testing.expectEqual(unit.factor, d.duration);
|
try std.testing.expectEqual(unit.factor, d.duration);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
const d = try Duration.parseCLI("0");
|
||||||
|
try std.testing.expectEqual(@as(u64, 0), d.duration);
|
||||||
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
const d = try Duration.parseCLI("100ns");
|
const d = try Duration.parseCLI("100ns");
|
||||||
try std.testing.expectEqual(@as(u64, 100), d.duration);
|
try std.testing.expectEqual(@as(u64, 100), d.duration);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue