diff --git a/supacode/Assets.xcassets/CommandIcons/AWS.imageset/AWS.svg b/supacode/Assets.xcassets/CommandIcons/AWS.imageset/AWS.svg new file mode 100644 index 00000000..932945eb --- /dev/null +++ b/supacode/Assets.xcassets/CommandIcons/AWS.imageset/AWS.svg @@ -0,0 +1 @@ +Amazon Web Services \ No newline at end of file diff --git a/supacode/Assets.xcassets/CommandIcons/AWS.imageset/Contents.json b/supacode/Assets.xcassets/CommandIcons/AWS.imageset/Contents.json new file mode 100644 index 00000000..4d7fdc0a --- /dev/null +++ b/supacode/Assets.xcassets/CommandIcons/AWS.imageset/Contents.json @@ -0,0 +1,16 @@ +{ + "images" : [ + { + "filename" : "AWS.svg", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "preserves-vector-representation" : true, + "template-rendering-intent" : "template" + } +} diff --git a/supacode/Assets.xcassets/CommandIcons/Amp.imageset/Amp.svg b/supacode/Assets.xcassets/CommandIcons/Amp.imageset/Amp.svg new file mode 100644 index 00000000..683e16c7 --- /dev/null +++ b/supacode/Assets.xcassets/CommandIcons/Amp.imageset/Amp.svg @@ -0,0 +1 @@ +Amp \ No newline at end of file diff --git a/supacode/Assets.xcassets/CommandIcons/Amp.imageset/Contents.json b/supacode/Assets.xcassets/CommandIcons/Amp.imageset/Contents.json new file mode 100644 index 00000000..07cace17 --- /dev/null +++ b/supacode/Assets.xcassets/CommandIcons/Amp.imageset/Contents.json @@ -0,0 +1,16 @@ +{ + "images" : [ + { + "filename" : "Amp.svg", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "preserves-vector-representation" : true, + "template-rendering-intent" : "template" + } +} diff --git a/supacode/Assets.xcassets/CommandIcons/Azure.imageset/Azure.svg b/supacode/Assets.xcassets/CommandIcons/Azure.imageset/Azure.svg new file mode 100644 index 00000000..69a264e2 --- /dev/null +++ b/supacode/Assets.xcassets/CommandIcons/Azure.imageset/Azure.svg @@ -0,0 +1 @@ +Microsoft Azure \ No newline at end of file diff --git a/supacode/Assets.xcassets/CommandIcons/Azure.imageset/Contents.json b/supacode/Assets.xcassets/CommandIcons/Azure.imageset/Contents.json new file mode 100644 index 00000000..e4e3043a --- /dev/null +++ b/supacode/Assets.xcassets/CommandIcons/Azure.imageset/Contents.json @@ -0,0 +1,16 @@ +{ + "images" : [ + { + "filename" : "Azure.svg", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "preserves-vector-representation" : true, + "template-rendering-intent" : "template" + } +} diff --git a/supacode/Assets.xcassets/CommandIcons/Deno.imageset/Contents.json b/supacode/Assets.xcassets/CommandIcons/Deno.imageset/Contents.json new file mode 100644 index 00000000..6b3bafda --- /dev/null +++ b/supacode/Assets.xcassets/CommandIcons/Deno.imageset/Contents.json @@ -0,0 +1,16 @@ +{ + "images" : [ + { + "filename" : "Deno.svg", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "preserves-vector-representation" : true, + "template-rendering-intent" : "template" + } +} diff --git a/supacode/Assets.xcassets/CommandIcons/Deno.imageset/Deno.svg b/supacode/Assets.xcassets/CommandIcons/Deno.imageset/Deno.svg new file mode 100644 index 00000000..ceee2b8b --- /dev/null +++ b/supacode/Assets.xcassets/CommandIcons/Deno.imageset/Deno.svg @@ -0,0 +1 @@ +Deno \ No newline at end of file diff --git a/supacode/Assets.xcassets/CommandIcons/Gemini.imageset/Contents.json b/supacode/Assets.xcassets/CommandIcons/Gemini.imageset/Contents.json new file mode 100644 index 00000000..135944f7 --- /dev/null +++ b/supacode/Assets.xcassets/CommandIcons/Gemini.imageset/Contents.json @@ -0,0 +1,16 @@ +{ + "images" : [ + { + "filename" : "Gemini.svg", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "preserves-vector-representation" : true, + "template-rendering-intent" : "template" + } +} diff --git a/supacode/Assets.xcassets/CommandIcons/Gemini.imageset/Gemini.svg b/supacode/Assets.xcassets/CommandIcons/Gemini.imageset/Gemini.svg new file mode 100644 index 00000000..765adb08 --- /dev/null +++ b/supacode/Assets.xcassets/CommandIcons/Gemini.imageset/Gemini.svg @@ -0,0 +1 @@ +Google Gemini \ No newline at end of file diff --git a/supacode/Assets.xcassets/CommandIcons/GitHubCopilot.imageset/Contents.json b/supacode/Assets.xcassets/CommandIcons/GitHubCopilot.imageset/Contents.json new file mode 100644 index 00000000..a9a5e13b --- /dev/null +++ b/supacode/Assets.xcassets/CommandIcons/GitHubCopilot.imageset/Contents.json @@ -0,0 +1,16 @@ +{ + "images" : [ + { + "filename" : "GitHubCopilot.svg", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "preserves-vector-representation" : true, + "template-rendering-intent" : "template" + } +} diff --git a/supacode/Assets.xcassets/CommandIcons/GitHubCopilot.imageset/GitHubCopilot.svg b/supacode/Assets.xcassets/CommandIcons/GitHubCopilot.imageset/GitHubCopilot.svg new file mode 100644 index 00000000..3cbf22a5 --- /dev/null +++ b/supacode/Assets.xcassets/CommandIcons/GitHubCopilot.imageset/GitHubCopilot.svg @@ -0,0 +1 @@ +GithubCopilot \ No newline at end of file diff --git a/supacode/Assets.xcassets/CommandIcons/Go.imageset/Contents.json b/supacode/Assets.xcassets/CommandIcons/Go.imageset/Contents.json new file mode 100644 index 00000000..f47b6a07 --- /dev/null +++ b/supacode/Assets.xcassets/CommandIcons/Go.imageset/Contents.json @@ -0,0 +1,16 @@ +{ + "images" : [ + { + "filename" : "Go.svg", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "preserves-vector-representation" : true, + "template-rendering-intent" : "template" + } +} diff --git a/supacode/Assets.xcassets/CommandIcons/Go.imageset/Go.svg b/supacode/Assets.xcassets/CommandIcons/Go.imageset/Go.svg new file mode 100644 index 00000000..0cadd56b --- /dev/null +++ b/supacode/Assets.xcassets/CommandIcons/Go.imageset/Go.svg @@ -0,0 +1 @@ +Go \ No newline at end of file diff --git a/supacode/Assets.xcassets/CommandIcons/GoogleCloud.imageset/Contents.json b/supacode/Assets.xcassets/CommandIcons/GoogleCloud.imageset/Contents.json new file mode 100644 index 00000000..fc36b8e0 --- /dev/null +++ b/supacode/Assets.xcassets/CommandIcons/GoogleCloud.imageset/Contents.json @@ -0,0 +1,16 @@ +{ + "images" : [ + { + "filename" : "GoogleCloud.svg", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "preserves-vector-representation" : true, + "template-rendering-intent" : "template" + } +} diff --git a/supacode/Assets.xcassets/CommandIcons/GoogleCloud.imageset/GoogleCloud.svg b/supacode/Assets.xcassets/CommandIcons/GoogleCloud.imageset/GoogleCloud.svg new file mode 100644 index 00000000..b7b4dcc0 --- /dev/null +++ b/supacode/Assets.xcassets/CommandIcons/GoogleCloud.imageset/GoogleCloud.svg @@ -0,0 +1 @@ +Google Cloud \ No newline at end of file diff --git a/supacode/Assets.xcassets/CommandIcons/Homebrew.imageset/Contents.json b/supacode/Assets.xcassets/CommandIcons/Homebrew.imageset/Contents.json new file mode 100644 index 00000000..9f1b1223 --- /dev/null +++ b/supacode/Assets.xcassets/CommandIcons/Homebrew.imageset/Contents.json @@ -0,0 +1,16 @@ +{ + "images" : [ + { + "filename" : "Homebrew.svg", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "preserves-vector-representation" : true, + "template-rendering-intent" : "template" + } +} diff --git a/supacode/Assets.xcassets/CommandIcons/Homebrew.imageset/Homebrew.svg b/supacode/Assets.xcassets/CommandIcons/Homebrew.imageset/Homebrew.svg new file mode 100644 index 00000000..71d0ae28 --- /dev/null +++ b/supacode/Assets.xcassets/CommandIcons/Homebrew.imageset/Homebrew.svg @@ -0,0 +1 @@ +Homebrew \ No newline at end of file diff --git a/supacode/Assets.xcassets/CommandIcons/Kimi.imageset/Contents.json b/supacode/Assets.xcassets/CommandIcons/Kimi.imageset/Contents.json new file mode 100644 index 00000000..e9bada61 --- /dev/null +++ b/supacode/Assets.xcassets/CommandIcons/Kimi.imageset/Contents.json @@ -0,0 +1,16 @@ +{ + "images" : [ + { + "filename" : "Kimi.svg", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "preserves-vector-representation" : true, + "template-rendering-intent" : "template" + } +} diff --git a/supacode/Assets.xcassets/CommandIcons/Kimi.imageset/Kimi.svg b/supacode/Assets.xcassets/CommandIcons/Kimi.imageset/Kimi.svg new file mode 100644 index 00000000..1915850e --- /dev/null +++ b/supacode/Assets.xcassets/CommandIcons/Kimi.imageset/Kimi.svg @@ -0,0 +1 @@ +Kimi \ No newline at end of file diff --git a/supacode/Assets.xcassets/CommandIcons/Node.imageset/Contents.json b/supacode/Assets.xcassets/CommandIcons/Node.imageset/Contents.json new file mode 100644 index 00000000..55bf28a4 --- /dev/null +++ b/supacode/Assets.xcassets/CommandIcons/Node.imageset/Contents.json @@ -0,0 +1,16 @@ +{ + "images" : [ + { + "filename" : "Node.svg", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "preserves-vector-representation" : true, + "template-rendering-intent" : "template" + } +} diff --git a/supacode/Assets.xcassets/CommandIcons/Node.imageset/Node.svg b/supacode/Assets.xcassets/CommandIcons/Node.imageset/Node.svg new file mode 100644 index 00000000..281c8296 --- /dev/null +++ b/supacode/Assets.xcassets/CommandIcons/Node.imageset/Node.svg @@ -0,0 +1 @@ +Node.js \ No newline at end of file diff --git a/supacode/Assets.xcassets/CommandIcons/OpenCode.imageset/Contents.json b/supacode/Assets.xcassets/CommandIcons/OpenCode.imageset/Contents.json new file mode 100644 index 00000000..e5e3ffb8 --- /dev/null +++ b/supacode/Assets.xcassets/CommandIcons/OpenCode.imageset/Contents.json @@ -0,0 +1,16 @@ +{ + "images" : [ + { + "filename" : "OpenCode.svg", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "preserves-vector-representation" : true, + "template-rendering-intent" : "template" + } +} diff --git a/supacode/Assets.xcassets/CommandIcons/OpenCode.imageset/OpenCode.svg b/supacode/Assets.xcassets/CommandIcons/OpenCode.imageset/OpenCode.svg new file mode 100644 index 00000000..9c4cb89e --- /dev/null +++ b/supacode/Assets.xcassets/CommandIcons/OpenCode.imageset/OpenCode.svg @@ -0,0 +1 @@ +opencode \ No newline at end of file diff --git a/supacode/Assets.xcassets/CommandIcons/Python.imageset/Contents.json b/supacode/Assets.xcassets/CommandIcons/Python.imageset/Contents.json new file mode 100644 index 00000000..eb4fbe9e --- /dev/null +++ b/supacode/Assets.xcassets/CommandIcons/Python.imageset/Contents.json @@ -0,0 +1,16 @@ +{ + "images" : [ + { + "filename" : "Python.svg", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "preserves-vector-representation" : true, + "template-rendering-intent" : "template" + } +} diff --git a/supacode/Assets.xcassets/CommandIcons/Python.imageset/Python.svg b/supacode/Assets.xcassets/CommandIcons/Python.imageset/Python.svg new file mode 100644 index 00000000..30587d81 --- /dev/null +++ b/supacode/Assets.xcassets/CommandIcons/Python.imageset/Python.svg @@ -0,0 +1 @@ +Python \ No newline at end of file diff --git a/supacode/Assets.xcassets/CommandIcons/Terraform.imageset/Contents.json b/supacode/Assets.xcassets/CommandIcons/Terraform.imageset/Contents.json new file mode 100644 index 00000000..5926ed77 --- /dev/null +++ b/supacode/Assets.xcassets/CommandIcons/Terraform.imageset/Contents.json @@ -0,0 +1,16 @@ +{ + "images" : [ + { + "filename" : "Terraform.svg", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "preserves-vector-representation" : true, + "template-rendering-intent" : "template" + } +} diff --git a/supacode/Assets.xcassets/CommandIcons/Terraform.imageset/Terraform.svg b/supacode/Assets.xcassets/CommandIcons/Terraform.imageset/Terraform.svg new file mode 100644 index 00000000..7aafae13 --- /dev/null +++ b/supacode/Assets.xcassets/CommandIcons/Terraform.imageset/Terraform.svg @@ -0,0 +1 @@ +Terraform \ No newline at end of file diff --git a/supacode/Assets.xcassets/CommandIcons/Tmux.imageset/Contents.json b/supacode/Assets.xcassets/CommandIcons/Tmux.imageset/Contents.json new file mode 100644 index 00000000..ff20607f --- /dev/null +++ b/supacode/Assets.xcassets/CommandIcons/Tmux.imageset/Contents.json @@ -0,0 +1,16 @@ +{ + "images" : [ + { + "filename" : "Tmux.svg", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "preserves-vector-representation" : true, + "template-rendering-intent" : "template" + } +} diff --git a/supacode/Assets.xcassets/CommandIcons/Tmux.imageset/Tmux.svg b/supacode/Assets.xcassets/CommandIcons/Tmux.imageset/Tmux.svg new file mode 100644 index 00000000..34b2ea1b --- /dev/null +++ b/supacode/Assets.xcassets/CommandIcons/Tmux.imageset/Tmux.svg @@ -0,0 +1 @@ +tmux \ No newline at end of file diff --git a/supacode/Assets.xcassets/CommandIcons/VSCode.imageset/Contents.json b/supacode/Assets.xcassets/CommandIcons/VSCode.imageset/Contents.json new file mode 100644 index 00000000..7f057fb4 --- /dev/null +++ b/supacode/Assets.xcassets/CommandIcons/VSCode.imageset/Contents.json @@ -0,0 +1,16 @@ +{ + "images" : [ + { + "filename" : "VSCode.svg", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "preserves-vector-representation" : true, + "template-rendering-intent" : "template" + } +} diff --git a/supacode/Assets.xcassets/CommandIcons/VSCode.imageset/VSCode.svg b/supacode/Assets.xcassets/CommandIcons/VSCode.imageset/VSCode.svg new file mode 100644 index 00000000..51ed6bd9 --- /dev/null +++ b/supacode/Assets.xcassets/CommandIcons/VSCode.imageset/VSCode.svg @@ -0,0 +1 @@ +Visual Studio Code \ No newline at end of file diff --git a/supacode/Features/Debug/Views/IconCatalogView.swift b/supacode/Features/Debug/Views/IconCatalogView.swift index c69d53f7..f272ca24 100644 --- a/supacode/Features/Debug/Views/IconCatalogView.swift +++ b/supacode/Features/Debug/Views/IconCatalogView.swift @@ -6,19 +6,39 @@ import SwiftUI /// renders a `CommandIconMap` entry through the same `TabIconImage` /// the actual tab UI uses, so the asset / SF Symbol fallback / size /// behaviour shown here matches what users see on a real tab. + /// + /// `.searchable` puts the filter field in the window toolbar + /// (NavigationSplitView's detail toolbar slot on macOS). Filtering + /// is a case-insensitive substring match on the token, so typing + /// `git` surfaces `git`, `gh`, `lazygit`, … struct IconCatalogView: View { + @State private var searchText: String = "" + var body: some View { - let entries = CommandIconMap.debugAllEntries + let entries = filteredEntries ScrollView { - LazyVStack(spacing: 0) { - ForEach(entries, id: \.token) { entry in - IconCatalogRow(token: entry.token, icon: entry.icon) - Divider().padding(.leading, 60) + if entries.isEmpty { + ContentUnavailableView.search(text: searchText) + .frame(maxWidth: .infinity, minHeight: 200) + } else { + LazyVStack(spacing: 0) { + ForEach(entries, id: \.token) { entry in + IconCatalogRow(token: entry.token, icon: entry.icon) + Divider().padding(.leading, 60) + } } + .padding(.horizontal) } - .padding(.horizontal) } .frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .topLeading) + .searchable(text: $searchText, placement: .toolbar, prompt: "Filter commands") + } + + private var filteredEntries: [(token: String, icon: TabIconSource)] { + let all = CommandIconMap.debugAllEntries + let needle = searchText.trimmingCharacters(in: .whitespacesAndNewlines) + guard !needle.isEmpty else { return all } + return all.filter { $0.token.localizedCaseInsensitiveContains(needle) } } } diff --git a/supacode/Features/Terminal/Models/CommandIconMap.swift b/supacode/Features/Terminal/Models/CommandIconMap.swift index 299a3c6b..2419f463 100644 --- a/supacode/Features/Terminal/Models/CommandIconMap.swift +++ b/supacode/Features/Terminal/Models/CommandIconMap.swift @@ -33,22 +33,47 @@ enum CommandIconMap { // Coding agents "claude": TabIconSource(systemSymbol: "sparkle", assetName: "ClaudeCode"), "codex": TabIconSource(systemSymbol: "sparkle", assetName: "Codex"), + "gemini": TabIconSource(systemSymbol: "sparkle", assetName: "Gemini"), + "opencode": TabIconSource(systemSymbol: "sparkle", assetName: "OpenCode"), + "amp": TabIconSource(systemSymbol: "sparkle", assetName: "Amp"), + "kimi": TabIconSource(systemSymbol: "sparkle", assetName: "Kimi"), + "copilot": TabIconSource(systemSymbol: "sparkle", assetName: "GitHubCopilot"), "aider": TabIconSource(systemSymbol: "sparkle"), + "droid": TabIconSource(systemSymbol: "sparkle"), - // Editors / pagers + // Editors / IDEs / pagers "vim": TabIconSource(systemSymbol: "pencil.and.scribble", assetName: "Vim"), "nvim": TabIconSource(systemSymbol: "pencil.and.scribble", assetName: "Neovim"), "nano": TabIconSource(systemSymbol: "pencil.and.scribble"), + "code": TabIconSource( + systemSymbol: "chevron.left.forwardslash.chevron.right", + assetName: "VSCode" + ), - // Package managers / JS runtimes + // Package managers "npm": TabIconSource(systemSymbol: "shippingbox", assetName: "Npm"), "pnpm": TabIconSource(systemSymbol: "shippingbox", assetName: "Pnpm"), "yarn": TabIconSource(systemSymbol: "shippingbox", assetName: "Yarn"), "bun": TabIconSource(systemSymbol: "shippingbox", assetName: "Bun"), + "brew": TabIconSource(systemSymbol: "shippingbox", assetName: "Homebrew"), - // VCS + // Runtime / version managers + "mise": TabIconSource(systemSymbol: "arrow.up.arrow.down"), + + // Languages / runtimes + "node": TabIconSource(systemSymbol: "terminal", assetName: "Node"), + "go": TabIconSource(systemSymbol: "terminal", assetName: "Go"), + "deno": TabIconSource(systemSymbol: "terminal", assetName: "Deno"), + "python": TabIconSource(systemSymbol: "terminal", assetName: "Python"), + "python3": TabIconSource(systemSymbol: "terminal", assetName: "Python"), + + // Terminal multiplexers + "tmux": TabIconSource(systemSymbol: "rectangle.split.3x1", assetName: "Tmux"), + + // VCS — `lazygit` is a TUI front-end for git, share the icon. "git": TabIconSource(systemSymbol: "arrow.triangle.branch", assetName: "Git"), "gh": TabIconSource(systemSymbol: "arrow.triangle.branch", assetName: "GitHub"), + "lazygit": TabIconSource(systemSymbol: "arrow.triangle.branch", assetName: "Git"), // Build tools "make": TabIconSource(systemSymbol: "hammer"), @@ -57,15 +82,24 @@ enum CommandIconMap { "xcodebuild": TabIconSource(systemSymbol: "hammer", assetName: "Xcode"), "gradle": TabIconSource(systemSymbol: "hammer", assetName: "Gradle"), - // Container / orchestration + // Container / orchestration — `lazydocker` is a TUI for docker, + // shares the icon. "docker": TabIconSource(systemSymbol: "shippingbox.fill", assetName: "Docker"), "kubectl": TabIconSource(systemSymbol: "shippingbox.fill", assetName: "Kubernetes"), "podman": TabIconSource(systemSymbol: "shippingbox.fill", assetName: "Podman"), + "lazydocker": TabIconSource(systemSymbol: "shippingbox.fill", assetName: "Docker"), + + // IaC / cloud CLIs + "terraform": TabIconSource(systemSymbol: "cloud", assetName: "Terraform"), + "aws": TabIconSource(systemSymbol: "cloud", assetName: "AWS"), + "az": TabIconSource(systemSymbol: "cloud", assetName: "Azure"), + "gcloud": TabIconSource(systemSymbol: "cloud", assetName: "GoogleCloud"), // Network / remote "ssh": TabIconSource(systemSymbol: "network"), "mosh": TabIconSource(systemSymbol: "network"), "curl": TabIconSource(systemSymbol: "network", assetName: "Curl"), + "wget": TabIconSource(systemSymbol: "arrow.down.circle"), // Process / system viewers "htop": TabIconSource(systemSymbol: "waveform.path.ecg"),