Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 3 additions & 26 deletions CLI/CLI+TmuxCompat.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,9 @@ import Security
#endif

extension ProgramaCLI {
/// The 23 tmux-emulation command names, all dispatched through the same
/// `runTmuxCompatCommand`. Help text preserves the original grouped
/// layout, including the two pipe-separated combo lines
/// ("next-window | previous-window | last-window" and
/// "bind-key | unbind-key | copy-mode") that documented three names on
/// one line while still being three independently-dispatchable commands.
/// The tmux-emulation command names, all dispatched through the same
/// `runTmuxCompatCommand`. The "next-window | previous-window | last-window"
/// help line documents three independently-dispatchable commands on one line.
static func tmuxCompatDescriptors(
runTmuxCompatCommand: @escaping (CommandContext) throws -> Void
) -> [CommandDescriptor] {
Expand All @@ -31,8 +28,6 @@ extension ProgramaCLI {
CommandDescriptor(names: ["find-window"], helpLines: ["find-window [--content] [--select] <query>"], grammar: CLIArgumentGrammar(booleanOptions: ["content", "select"], minPositionals: 1, maxPositionals: nil), execute: runTmuxCompatCommand),
CommandDescriptor(names: ["clear-history"], helpLines: ["clear-history [--workspace <id|ref>] [--surface <id|ref>]"], grammar: CLIArgumentGrammar(valueOptions: ["workspace", "surface"]), execute: runTmuxCompatCommand),
CommandDescriptor(names: ["set-hook"], helpLines: ["set-hook [--list] [--unset <event>] | <event> <command>"], execute: runTmuxCompatCommand),
CommandDescriptor(names: ["popup"], helpLines: ["popup"], execute: runTmuxCompatCommand),
CommandDescriptor(names: ["bind-key", "unbind-key", "copy-mode"], helpLines: ["bind-key | unbind-key | copy-mode"], execute: runTmuxCompatCommand),
CommandDescriptor(names: ["set-buffer"], helpLines: ["set-buffer [--name <name>] <text>"], grammar: CLIArgumentGrammar(valueOptions: ["name"], minPositionals: 1, maxPositionals: nil), execute: runTmuxCompatCommand),
CommandDescriptor(names: ["list-buffers"], helpLines: ["list-buffers"], grammar: CLIArgumentGrammar(), execute: runTmuxCompatCommand),
CommandDescriptor(names: ["paste-buffer"], helpLines: ["paste-buffer [--name <name>] [--workspace <id|ref>] [--surface <id|ref>]"], grammar: CLIArgumentGrammar(valueOptions: ["name", "workspace", "surface"]), execute: runTmuxCompatCommand),
Expand Down Expand Up @@ -2159,12 +2154,6 @@ extension ProgramaCLI {
}
print("OK")

case "popup":
throw CLIError(message: "popup is not supported yet in programa CLI parity mode")

case "bind-key", "unbind-key", "copy-mode":
throw CLIError(message: "\(command) is not supported yet in programa CLI parity mode")

case "set-buffer":
let (nameArg, rem0) = parseOption(commandArgs, name: "--name")
let name = (nameArg?.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty == false) ? nameArg! : "default"
Expand Down Expand Up @@ -2380,18 +2369,6 @@ extension ProgramaCLI {
--list List configured hooks
--unset <event> Remove a hook by event name
"""
case "popup":
return """
Usage: programa popup

tmux compatibility placeholder. This command is currently not supported.
"""
case "bind-key", "unbind-key", "copy-mode":
return """
Usage: programa \(command)

tmux compatibility placeholder. This command is currently not supported.
"""
case "set-buffer":
return """
Usage: programa set-buffer [--name <name>] [--] <text>
Expand Down
49 changes: 0 additions & 49 deletions CLI/SocketClient.swift
Original file line number Diff line number Diff line change
Expand Up @@ -380,55 +380,6 @@ final class SocketClient {
return client
}

static func waitForFilesystemPath(_ path: String, timeout: TimeInterval) throws {
if FileManager.default.fileExists(atPath: path) {
return
}

guard let watchDirectory = existingWatchDirectory(forPath: path) else {
throw CLIError(message: "Timed out waiting for \(path)")
}
let watchFD = open(watchDirectory, O_EVTONLY)
guard watchFD >= 0 else {
throw CLIError(message: "Timed out waiting for \(path)")
}

let queue = DispatchQueue(label: "com.programa.cli.path-watch.\(UUID().uuidString)")
let semaphore = DispatchSemaphore(value: 0)
var found = false
let source = DispatchSource.makeFileSystemObjectSource(
fileDescriptor: watchFD,
eventMask: [.write, .rename, .delete, .attrib, .extend, .link],
queue: queue
)

func checkPath() {
guard !found else { return }
if FileManager.default.fileExists(atPath: path) {
found = true
semaphore.signal()
}
}

source.setEventHandler {
checkPath()
}
source.setCancelHandler {
Darwin.close(watchFD)
}
source.resume()
queue.async {
checkPath()
}

guard semaphore.wait(timeout: .now() + timeout) == .success else {
source.cancel()
throw CLIError(message: "Timed out waiting for \(path)")
}

source.cancel()
}

private static func existingWatchDirectory(forPath path: String) -> String? {
let fileManager = FileManager.default
var candidate = URL(fileURLWithPath: (path as NSString).deletingLastPathComponent, isDirectory: true)
Expand Down
1 change: 0 additions & 1 deletion CLI/V2MethodNames.swift
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,6 @@ enum V2MethodNames {
static let debugTerminalRenderStats = "debug.terminal.render_stats"
static let debugTerminals = "debug.terminals"
static let debugType = "debug.type"
static let debugViewtree = "debug.viewtree"
static let debugWindowScreenshot = "debug.window.screenshot"
static let feedbackOpen = "feedback.open"
static let feedbackSubmit = "feedback.submit"
Expand Down
66 changes: 0 additions & 66 deletions CLI/programa.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3224,45 +3224,6 @@ struct ProgramaCLI {
return (cwd as NSString).appendingPathComponent(expanded)
}

func sanitizedFilenameComponent(_ raw: String) -> String {
let sanitized = raw.replacingOccurrences(
of: #"[^\p{L}\p{N}._-]+"#,
with: "-",
options: .regularExpression
)
let trimmed = sanitized.trimmingCharacters(in: CharacterSet(charactersIn: "-."))
return trimmed.isEmpty ? "item" : trimmed
}

func bestEffortPruneTemporaryFiles(
in directoryURL: URL,
keepingMostRecent maxCount: Int = 50,
maxAge: TimeInterval = 24 * 60 * 60
) {
guard let entries = try? FileManager.default.contentsOfDirectory(
at: directoryURL,
includingPropertiesForKeys: [.isRegularFileKey, .contentModificationDateKey, .creationDateKey],
options: [.skipsHiddenFiles]
) else {
return
}

let now = Date()
let datedEntries = entries.compactMap { url -> (url: URL, date: Date)? in
guard let values = try? url.resourceValues(forKeys: [.isRegularFileKey, .contentModificationDateKey, .creationDateKey]),
values.isRegularFile == true else {
return nil
}
return (url, values.contentModificationDate ?? values.creationDate ?? .distantPast)
}.sorted { $0.date > $1.date }

for (index, entry) in datedEntries.enumerated() {
if index >= maxCount || now.timeIntervalSince(entry.date) > maxAge {
try? FileManager.default.removeItem(at: entry.url)
}
}
}

/// Returns true if the argument looks like a filesystem path rather than a CLI command.
func looksLikePath(_ arg: String) -> Bool {
if arg == "." || arg == ".." { return true }
Expand Down Expand Up @@ -3548,14 +3509,6 @@ struct ProgramaCLI {
}
}

private func parsePositiveInt(_ raw: String?, label: String) throws -> Int? {
guard let raw else { return nil }
guard let value = Int(raw) else {
throw CLIError(message: "\(label) must be an integer")
}
return value
}

func isHandleRef(_ value: String) -> Bool {
let pieces = value.split(separator: ":", omittingEmptySubsequences: false)
guard pieces.count == 2 else { return false }
Expand Down Expand Up @@ -5046,10 +4999,6 @@ struct ProgramaCLI {
args.contains(name)
}

private func replaceToken(_ args: [String], from: String, to: String) -> [String] {
args.map { $0 == from ? to : $0 }
}

/// Unescape CLI escape sequences for send behavior.
/// \n and \r → carriage return (Enter), \t → tab.
private func unescapeSendText(_ text: String) -> String {
Expand Down Expand Up @@ -5537,8 +5486,6 @@ struct ProgramaCLI {
if parsed.options["list"] == nil, parsed.options["unset"] == nil, parsed.positional.count < 2 {
throw CLIError(message: "set-hook requires <event> <command>")
}
case "popup", "bind-key", "unbind-key", "copy-mode":
throw CLIError(message: "\(command) is not supported yet in programa CLI parity mode")
case "display-message":
let parsed = try parse(booleans: ["print"], minPositionals: 1, maxPositionals: nil)
guard parsed.positional.filter({ $0 != "-p" }).isEmpty == false else {
Expand Down Expand Up @@ -6343,19 +6290,6 @@ struct ProgramaCLI {
to ~/Library/Application Support/programa/programa.sock and never connects to tagged/debug sockets on its own.
"""
}

#if DEBUG
func debugUsageTextForTesting() -> String {
usage()
}

func debugFormatDebugTerminalsPayloadForTesting(
_ payload: [String: Any],
idFormat: CLIIDFormat = .refs
) -> String {
formatDebugTerminalsPayload(payload, idFormat: idFormat)
}
#endif
}

@main
Expand Down
4 changes: 0 additions & 4 deletions GhosttyTabs.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,6 @@
WTMG000005 /* ProgramaLayoutStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = WTMG000006 /* ProgramaLayoutStore.swift */; };
NRTM00000002 /* TabManager+UITestHarness.swift in Sources */ = {isa = PBXBuildFile; fileRef = NRTM00000001 /* TabManager+UITestHarness.swift */; };
A5001004 /* GhosttyConfig.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5001014 /* GhosttyConfig.swift */; };
A5001005 /* GhosttyTerminalView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5001015 /* GhosttyTerminalView.swift */; };
A5FF0051 /* GhosttyTerminalView+Keyboard.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5FF0041 /* GhosttyTerminalView+Keyboard.swift */; };
A5FF0052 /* GhosttyTerminalView+Mouse.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5FF0042 /* GhosttyTerminalView+Mouse.swift */; };
A5FF0053 /* GhosttyTerminalView+DragDrop.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5FF0043 /* GhosttyTerminalView+DragDrop.swift */; };
Expand Down Expand Up @@ -482,7 +481,6 @@
WTMG000006 /* ProgramaLayoutStore.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProgramaLayoutStore.swift; sourceTree = "<group>"; };
NRTM00000001 /* TabManager+UITestHarness.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "TabManager+UITestHarness.swift"; sourceTree = "<group>"; };
A5001014 /* GhosttyConfig.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GhosttyConfig.swift; sourceTree = "<group>"; };
A5001015 /* GhosttyTerminalView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GhosttyTerminalView.swift; sourceTree = "<group>"; };
A5FF0041 /* GhosttyTerminalView+Keyboard.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "GhosttyTerminalView+Keyboard.swift"; sourceTree = "<group>"; };
A5FF0042 /* GhosttyTerminalView+Mouse.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "GhosttyTerminalView+Mouse.swift"; sourceTree = "<group>"; };
A5FF0043 /* GhosttyTerminalView+DragDrop.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "GhosttyTerminalView+DragDrop.swift"; sourceTree = "<group>"; };
Expand Down Expand Up @@ -931,7 +929,6 @@
NRWS00000000000000000031 /* Workspace+Bonsplit.swift */,
A5001417 /* WorkspaceContentView.swift */,
A5001014 /* GhosttyConfig.swift */,
A5001015 /* GhosttyTerminalView.swift */,
A5FF0041 /* GhosttyTerminalView+Keyboard.swift */,
A5FF0042 /* GhosttyTerminalView+Mouse.swift */,
A5FF0043 /* GhosttyTerminalView+DragDrop.swift */,
Expand Down Expand Up @@ -1464,7 +1461,6 @@
NRWS00000000000000000032 /* Workspace+Bonsplit.swift in Sources */,
A5001407 /* WorkspaceContentView.swift in Sources */,
A5001004 /* GhosttyConfig.swift in Sources */,
A5001005 /* GhosttyTerminalView.swift in Sources */,
A5FF0051 /* GhosttyTerminalView+Keyboard.swift in Sources */,
A5FF0052 /* GhosttyTerminalView+Mouse.swift in Sources */,
A5FF0053 /* GhosttyTerminalView+DragDrop.swift in Sources */,
Expand Down
Loading
Loading