Tune Bonsplit tab bar action lane
This commit is contained in:
@@ -5350,6 +5350,13 @@ class TabManager: ObservableObject {
|
||||
}
|
||||
}
|
||||
|
||||
/// Refresh Bonsplit right-side action button backdrop tuning for all workspaces.
|
||||
func refreshSplitButtonBackdropEffect() {
|
||||
for workspace in tabs {
|
||||
workspace.refreshSplitButtonBackdropEffect()
|
||||
}
|
||||
}
|
||||
|
||||
func applySurfaceTabBarButtons(
|
||||
_ buttons: [CmuxSurfaceTabBarButton],
|
||||
sourcePath: String?,
|
||||
|
||||
+119
-2
@@ -74,6 +74,115 @@ private final class WorkspacePendingTerminalInputObserver: @unchecked Sendable {
|
||||
var observer: NSObjectProtocol?
|
||||
}
|
||||
|
||||
struct BonsplitTabBarDebugNumberSetting {
|
||||
let key: String
|
||||
let defaultValue: Double
|
||||
let range: ClosedRange<Double>
|
||||
let step: Double
|
||||
|
||||
func resolved(_ value: Double) -> Double {
|
||||
guard value.isFinite else { return defaultValue }
|
||||
return min(max(value, range.lowerBound), range.upperBound)
|
||||
}
|
||||
|
||||
func currentValue(defaults: UserDefaults = .standard) -> Double {
|
||||
guard defaults.object(forKey: key) != nil else {
|
||||
return defaultValue
|
||||
}
|
||||
return resolved(defaults.double(forKey: key))
|
||||
}
|
||||
|
||||
func format(_ value: Double) -> String {
|
||||
String(format: "%.3f", resolved(value))
|
||||
}
|
||||
}
|
||||
|
||||
enum BonsplitTabBarDebugSettings {
|
||||
static let backdropFadeWidth = 99.75
|
||||
|
||||
static let separatorFadeWidthSetting = BonsplitTabBarDebugNumberSetting(
|
||||
key: "debugBonsplitTabBarSeparatorFadeWidthV2",
|
||||
defaultValue: backdropFadeWidth,
|
||||
range: 0.0...140.0,
|
||||
step: 0.25
|
||||
)
|
||||
static let contentFadeWidthSetting = BonsplitTabBarDebugNumberSetting(
|
||||
key: "debugBonsplitTabBarContentFadeWidth",
|
||||
defaultValue: 28.875,
|
||||
range: 0.0...80.0,
|
||||
step: 0.5
|
||||
)
|
||||
static let solidSurfaceWidthAdjustmentSetting = BonsplitTabBarDebugNumberSetting(
|
||||
key: "debugBonsplitTabBarSolidSurfaceWidthAdjustmentV2",
|
||||
defaultValue: -80.0,
|
||||
range: -80.0...120.0,
|
||||
step: 0.5
|
||||
)
|
||||
|
||||
static let separatorFadeWidthKey = separatorFadeWidthSetting.key
|
||||
static let contentFadeWidthKey = contentFadeWidthSetting.key
|
||||
static let solidSurfaceWidthAdjustmentKey = solidSurfaceWidthAdjustmentSetting.key
|
||||
static let defaultSeparatorFadeWidth = separatorFadeWidthSetting.defaultValue
|
||||
static let defaultContentFadeWidth = contentFadeWidthSetting.defaultValue
|
||||
static let defaultSolidSurfaceWidthAdjustment = solidSurfaceWidthAdjustmentSetting.defaultValue
|
||||
static let separatorFadeWidthRange = separatorFadeWidthSetting.range
|
||||
static let contentFadeWidthRange = contentFadeWidthSetting.range
|
||||
static let solidSurfaceWidthAdjustmentRange = solidSurfaceWidthAdjustmentSetting.range
|
||||
static let separatorFadeWidthStep = separatorFadeWidthSetting.step
|
||||
static let contentFadeWidthStep = contentFadeWidthSetting.step
|
||||
static let solidSurfaceWidthAdjustmentStep = solidSurfaceWidthAdjustmentSetting.step
|
||||
|
||||
static func resolvedSeparatorFadeWidth(_ width: Double) -> Double {
|
||||
separatorFadeWidthSetting.resolved(width)
|
||||
}
|
||||
|
||||
static func resolvedContentFadeWidth(_ width: Double) -> Double {
|
||||
contentFadeWidthSetting.resolved(width)
|
||||
}
|
||||
|
||||
static func resolvedSolidSurfaceWidthAdjustment(_ width: Double) -> Double {
|
||||
solidSurfaceWidthAdjustmentSetting.resolved(width)
|
||||
}
|
||||
|
||||
static func separatorFadeWidth(defaults: UserDefaults = .standard) -> Double {
|
||||
separatorFadeWidthSetting.currentValue(defaults: defaults)
|
||||
}
|
||||
|
||||
static func contentFadeWidth(defaults: UserDefaults = .standard) -> Double {
|
||||
contentFadeWidthSetting.currentValue(defaults: defaults)
|
||||
}
|
||||
|
||||
static func solidSurfaceWidthAdjustment(defaults: UserDefaults = .standard) -> Double {
|
||||
solidSurfaceWidthAdjustmentSetting.currentValue(defaults: defaults)
|
||||
}
|
||||
|
||||
static func formatPixels(_ value: Double) -> String {
|
||||
String(format: "%.3f", value)
|
||||
}
|
||||
|
||||
static func currentTuningDescription(defaults: UserDefaults = .standard) -> String {
|
||||
let effect = Workspace.bonsplitSplitButtonBackdropEffect()
|
||||
return [
|
||||
"bonsplit-tabbar-tuning",
|
||||
"separatorFadeWidth=\(formatPixels(separatorFadeWidth(defaults: defaults)))",
|
||||
"contentFadeWidth=\(formatPixels(contentFadeWidth(defaults: defaults)))",
|
||||
"solidSurfaceWidthAdjustment=\(formatPixels(solidSurfaceWidthAdjustment(defaults: defaults)))",
|
||||
"fadeWidth=\(String(format: "%.3f", Double(effect.fadeWidth)))",
|
||||
"solidWidth=\(String(format: "%.3f", Double(effect.solidWidth)))",
|
||||
"fadeRampStartFraction=\(String(format: "%.3f", Double(effect.fadeRampStartFraction)))",
|
||||
"trailingOpacity=\(String(format: "%.3f", Double(effect.trailingOpacity)))",
|
||||
"contentOcclusionFraction=\(String(format: "%.3f", Double(effect.contentOcclusionFraction)))",
|
||||
"masksTabContent=\(effect.masksTabContent ? "true" : "false")"
|
||||
].joined(separator: " ")
|
||||
}
|
||||
|
||||
static func copyCurrentTuningToPasteboard(defaults: UserDefaults = .standard) {
|
||||
let pasteboard = NSPasteboard.general
|
||||
pasteboard.clearContents()
|
||||
pasteboard.setString(currentTuningDescription(defaults: defaults), forType: .string)
|
||||
}
|
||||
}
|
||||
|
||||
func cmuxSurfaceContextName(_ context: ghostty_surface_context_e) -> String {
|
||||
switch context {
|
||||
case GHOSTTY_SURFACE_CONTEXT_WINDOW:
|
||||
@@ -7588,9 +7697,11 @@ final class Workspace: Identifiable, ObservableObject {
|
||||
nonisolated static func bonsplitSplitButtonBackdropEffect() -> BonsplitConfiguration.Appearance.SplitButtonBackdropEffect {
|
||||
.init(
|
||||
style: .translucentChrome,
|
||||
fadeWidth: 99.75,
|
||||
contentFadeWidth: 28.875,
|
||||
fadeWidth: CGFloat(BonsplitTabBarDebugSettings.backdropFadeWidth),
|
||||
contentFadeWidth: CGFloat(BonsplitTabBarDebugSettings.contentFadeWidth()),
|
||||
solidWidth: 23.875,
|
||||
solidSurfaceWidthAdjustment: CGFloat(BonsplitTabBarDebugSettings.solidSurfaceWidthAdjustment()),
|
||||
separatorFadeWidth: CGFloat(BonsplitTabBarDebugSettings.separatorFadeWidth()),
|
||||
fadeRampStartFraction: bonsplitSplitButtonBackdropSoftness,
|
||||
leadingOpacity: 0,
|
||||
trailingOpacity: 0.8625,
|
||||
@@ -7952,6 +8063,12 @@ final class Workspace: Identifiable, ObservableObject {
|
||||
bonsplitController.configuration = configuration
|
||||
}
|
||||
|
||||
func refreshSplitButtonBackdropEffect() {
|
||||
var configuration = bonsplitController.configuration
|
||||
configuration.appearance.splitButtonBackdropEffect = Self.bonsplitSplitButtonBackdropEffect()
|
||||
bonsplitController.configuration = configuration
|
||||
}
|
||||
|
||||
func applySurfaceTabBarButtons(
|
||||
_ buttons: [CmuxSurfaceTabBarButton],
|
||||
sourcePath: String?,
|
||||
|
||||
+208
-1
@@ -383,6 +383,9 @@ struct cmuxApp: App {
|
||||
Button("Split Button Layout Debug…") {
|
||||
SplitButtonLayoutDebugWindowController.shared.show()
|
||||
}
|
||||
Button("Bonsplit Tab Bar Debug…") {
|
||||
BonsplitTabBarDebugWindowController.shared.show()
|
||||
}
|
||||
Button(
|
||||
String(
|
||||
localized: "debug.menu.tabBarBackdropLab",
|
||||
@@ -1104,6 +1107,7 @@ struct cmuxApp: App {
|
||||
FeedPreviewWindowController.shared.show()
|
||||
FeedTextEditorDebugWindowController.shared.show()
|
||||
FeedButtonStyleDebugWindowController.shared.show()
|
||||
BonsplitTabBarDebugWindowController.shared.show()
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@@ -1136,6 +1140,7 @@ private let cmuxAuxiliaryWindowIdentifiers: Set<String> = [
|
||||
"cmux.menubarDebug",
|
||||
"cmux.backgroundDebug",
|
||||
"cmux.startupAppearanceDebug",
|
||||
"cmux.bonsplitTabBarDebug",
|
||||
]
|
||||
|
||||
/// Returns whether the given window should handle the standard close shortcut
|
||||
@@ -1750,6 +1755,9 @@ private struct DebugWindowControlsView: View {
|
||||
) {
|
||||
PDFPreviewChromeDebugWindowController.shared.show()
|
||||
}
|
||||
Button("Bonsplit Tab Bar Debug…") {
|
||||
BonsplitTabBarDebugWindowController.shared.show()
|
||||
}
|
||||
Button(
|
||||
String(
|
||||
localized: "debug.menu.tabBarBackdropLab",
|
||||
@@ -1775,6 +1783,7 @@ private struct DebugWindowControlsView: View {
|
||||
StartupAppearanceDebugWindowController.shared.show()
|
||||
MenuBarExtraDebugWindowController.shared.show()
|
||||
PDFPreviewChromeDebugWindowController.shared.show()
|
||||
BonsplitTabBarDebugWindowController.shared.show()
|
||||
TabBarBackdropLabWindowController.shared.show()
|
||||
FeedTextEditorDebugWindowController.shared.show()
|
||||
}
|
||||
@@ -3331,6 +3340,203 @@ private struct SplitButtonLayoutDebugView: View {
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Bonsplit Tab Bar Debug Window
|
||||
|
||||
private final class BonsplitTabBarDebugWindowController: NSWindowController, NSWindowDelegate {
|
||||
static let shared = BonsplitTabBarDebugWindowController()
|
||||
|
||||
private init() {
|
||||
let window = NSPanel(
|
||||
contentRect: NSRect(x: 0, y: 0, width: 520, height: 420),
|
||||
styleMask: [.titled, .closable, .utilityWindow],
|
||||
backing: .buffered,
|
||||
defer: false
|
||||
)
|
||||
window.title = "Bonsplit Tab Bar Debug"
|
||||
window.titleVisibility = .visible
|
||||
window.titlebarAppearsTransparent = false
|
||||
window.isMovableByWindowBackground = true
|
||||
window.isReleasedWhenClosed = false
|
||||
window.identifier = NSUserInterfaceItemIdentifier("cmux.bonsplitTabBarDebug")
|
||||
window.center()
|
||||
window.contentView = NSHostingView(rootView: BonsplitTabBarDebugView())
|
||||
AppDelegate.shared?.applyWindowDecorations(to: window)
|
||||
super.init(window: window)
|
||||
window.delegate = self
|
||||
}
|
||||
|
||||
@available(*, unavailable)
|
||||
required init?(coder: NSCoder) { fatalError() }
|
||||
|
||||
func show() {
|
||||
window?.center()
|
||||
window?.makeKeyAndOrderFront(nil)
|
||||
}
|
||||
}
|
||||
|
||||
private struct BonsplitTabBarDebugView: View {
|
||||
@AppStorage(BonsplitTabBarDebugSettings.separatorFadeWidthKey)
|
||||
private var separatorFadeWidth = BonsplitTabBarDebugSettings.defaultSeparatorFadeWidth
|
||||
@AppStorage(BonsplitTabBarDebugSettings.contentFadeWidthKey)
|
||||
private var contentFadeWidth = BonsplitTabBarDebugSettings.defaultContentFadeWidth
|
||||
@AppStorage(BonsplitTabBarDebugSettings.solidSurfaceWidthAdjustmentKey)
|
||||
private var solidSurfaceWidthAdjustment = BonsplitTabBarDebugSettings.defaultSolidSurfaceWidthAdjustment
|
||||
|
||||
private var resolvedSeparatorFadeWidth: Double {
|
||||
BonsplitTabBarDebugSettings.resolvedSeparatorFadeWidth(separatorFadeWidth)
|
||||
}
|
||||
|
||||
private var resolvedContentFadeWidth: Double {
|
||||
BonsplitTabBarDebugSettings.resolvedContentFadeWidth(contentFadeWidth)
|
||||
}
|
||||
|
||||
private var resolvedSolidSurfaceWidthAdjustment: Double {
|
||||
BonsplitTabBarDebugSettings.resolvedSolidSurfaceWidthAdjustment(solidSurfaceWidthAdjustment)
|
||||
}
|
||||
|
||||
private var separatorFadeBinding: Binding<Double> {
|
||||
Binding(
|
||||
get: { resolvedSeparatorFadeWidth },
|
||||
set: { setSeparatorFadeWidth($0) }
|
||||
)
|
||||
}
|
||||
|
||||
private var contentFadeBinding: Binding<Double> {
|
||||
Binding(
|
||||
get: { resolvedContentFadeWidth },
|
||||
set: { setContentFadeWidth($0) }
|
||||
)
|
||||
}
|
||||
|
||||
private var solidSurfaceWidthAdjustmentBinding: Binding<Double> {
|
||||
Binding(
|
||||
get: { resolvedSolidSurfaceWidthAdjustment },
|
||||
set: { setSolidSurfaceWidthAdjustment($0) }
|
||||
)
|
||||
}
|
||||
|
||||
var body: some View {
|
||||
VStack(alignment: .leading, spacing: 14) {
|
||||
Text("Bonsplit Tab Bar")
|
||||
.font(.headline)
|
||||
|
||||
GroupBox("Action Lane Geometry") {
|
||||
VStack(alignment: .leading, spacing: 10) {
|
||||
BonsplitTabBarDebugSliderRow(
|
||||
title: "Content fade",
|
||||
value: contentFadeBinding,
|
||||
setting: BonsplitTabBarDebugSettings.contentFadeWidthSetting
|
||||
)
|
||||
BonsplitTabBarDebugSliderRow(
|
||||
title: "Solid bg extra",
|
||||
value: solidSurfaceWidthAdjustmentBinding,
|
||||
setting: BonsplitTabBarDebugSettings.solidSurfaceWidthAdjustmentSetting
|
||||
)
|
||||
}
|
||||
.padding(.top, 2)
|
||||
}
|
||||
|
||||
GroupBox("Action Lane Border") {
|
||||
VStack(alignment: .leading, spacing: 10) {
|
||||
BonsplitTabBarDebugSliderRow(
|
||||
title: "Separator fade frame",
|
||||
value: separatorFadeBinding,
|
||||
setting: BonsplitTabBarDebugSettings.separatorFadeWidthSetting
|
||||
)
|
||||
}
|
||||
.padding(.top, 2)
|
||||
}
|
||||
|
||||
HStack(spacing: 10) {
|
||||
Button("Reset") {
|
||||
setSeparatorFadeWidth(BonsplitTabBarDebugSettings.defaultSeparatorFadeWidth)
|
||||
setContentFadeWidth(BonsplitTabBarDebugSettings.defaultContentFadeWidth)
|
||||
setSolidSurfaceWidthAdjustment(BonsplitTabBarDebugSettings.defaultSolidSurfaceWidthAdjustment)
|
||||
}
|
||||
Button("Copy Config") {
|
||||
BonsplitTabBarDebugSettings.copyCurrentTuningToPasteboard()
|
||||
}
|
||||
}
|
||||
|
||||
Text(verbatim: BonsplitTabBarDebugSettings.currentTuningDescription())
|
||||
.font(.system(.caption, design: .monospaced))
|
||||
.textSelection(.enabled)
|
||||
.lineLimit(3)
|
||||
.frame(maxWidth: .infinity, alignment: .leading)
|
||||
}
|
||||
.padding(16)
|
||||
.frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .topLeading)
|
||||
}
|
||||
|
||||
private func setSeparatorFadeWidth(_ value: Double) {
|
||||
separatorFadeWidth = BonsplitTabBarDebugSettings.resolvedSeparatorFadeWidth(value)
|
||||
refreshLiveWorkspaces()
|
||||
}
|
||||
|
||||
private func setContentFadeWidth(_ value: Double) {
|
||||
contentFadeWidth = BonsplitTabBarDebugSettings.resolvedContentFadeWidth(value)
|
||||
refreshLiveWorkspaces()
|
||||
}
|
||||
|
||||
private func setSolidSurfaceWidthAdjustment(_ value: Double) {
|
||||
solidSurfaceWidthAdjustment = BonsplitTabBarDebugSettings.resolvedSolidSurfaceWidthAdjustment(value)
|
||||
refreshLiveWorkspaces()
|
||||
}
|
||||
|
||||
private func refreshLiveWorkspaces() {
|
||||
let managers = [
|
||||
AppDelegate.shared?.activeTabManagerForCommands(),
|
||||
AppDelegate.shared?.tabManager
|
||||
].compactMap { $0 }
|
||||
var seen = Set<ObjectIdentifier>()
|
||||
for manager in managers {
|
||||
guard seen.insert(ObjectIdentifier(manager)).inserted else { continue }
|
||||
manager.refreshSplitButtonBackdropEffect()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private struct BonsplitTabBarDebugSliderRow: View {
|
||||
let title: String
|
||||
@Binding var value: Double
|
||||
let setting: BonsplitTabBarDebugNumberSetting
|
||||
|
||||
private var resolvedValue: Double {
|
||||
setting.resolved(value)
|
||||
}
|
||||
|
||||
var body: some View {
|
||||
VStack(alignment: .leading, spacing: 6) {
|
||||
HStack(spacing: 8) {
|
||||
Text(title)
|
||||
.frame(width: 112, alignment: .leading)
|
||||
Slider(
|
||||
value: Binding(
|
||||
get: { resolvedValue },
|
||||
set: { value = setting.resolved($0) }
|
||||
),
|
||||
in: setting.range,
|
||||
step: setting.step
|
||||
)
|
||||
Text("\(setting.format(resolvedValue)) px")
|
||||
.font(.caption)
|
||||
.monospacedDigit()
|
||||
.frame(width: 76, alignment: .trailing)
|
||||
}
|
||||
|
||||
Stepper(
|
||||
"Fine tune",
|
||||
value: Binding(
|
||||
get: { resolvedValue },
|
||||
set: { value = setting.resolved($0) }
|
||||
),
|
||||
in: setting.range,
|
||||
step: setting.step
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Tab Bar Backdrop Lab Window
|
||||
|
||||
private final class TabBarBackdropLabWindowController: NSWindowController, NSWindowDelegate {
|
||||
@@ -3390,7 +3596,7 @@ private struct TabBarBackdropLabVariant: Identifiable {
|
||||
let opacity: CGFloat
|
||||
|
||||
var renderIdentity: String {
|
||||
"\(id)-\(chromeHex)-\(tabBarHex)-\(splitButtonBackdropHex)-\(paneHex)-\(borderHex)-\(String(format: "%.3f", opacity))-\(String(format: "%.1f", effect.fadeWidth))-\(String(format: "%.1f", effect.contentFadeWidth))-\(String(format: "%.1f", effect.solidWidth))-\(String(format: "%.2f", effect.fadeRampStartFraction))-\(String(format: "%.2f", effect.leadingOpacity))-\(String(format: "%.2f", effect.trailingOpacity))-\(String(format: "%.2f", effect.contentOcclusionFraction))-\(effect.masksTabContent ? 1 : 0)"
|
||||
"\(id)-\(chromeHex)-\(tabBarHex)-\(splitButtonBackdropHex)-\(paneHex)-\(borderHex)-\(String(format: "%.3f", opacity))-\(String(format: "%.1f", effect.fadeWidth))-\(String(format: "%.1f", effect.contentFadeWidth))-\(String(format: "%.1f", effect.solidWidth))-\(String(format: "%.1f", effect.solidSurfaceWidthAdjustment))-\(String(format: "%.2f", effect.fadeRampStartFraction))-\(String(format: "%.2f", effect.leadingOpacity))-\(String(format: "%.2f", effect.trailingOpacity))-\(String(format: "%.2f", effect.contentOcclusionFraction))-\(effect.masksTabContent ? 1 : 0)"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3435,6 +3641,7 @@ private struct TabBarBackdropLabView: View {
|
||||
fadeWidth: interpolate(strong: 20, production: production.fadeWidth, soft: 240),
|
||||
contentFadeWidth: interpolate(strong: 0, production: production.contentFadeWidth, soft: 80),
|
||||
solidWidth: interpolate(strong: 72, production: production.solidWidth, soft: 0),
|
||||
solidSurfaceWidthAdjustment: production.solidSurfaceWidthAdjustment,
|
||||
fadeRampStartFraction: interpolate(strong: 0, production: production.fadeRampStartFraction, soft: 0.98),
|
||||
leadingOpacity: production.leadingOpacity,
|
||||
trailingOpacity: interpolate(strong: 1.0, production: production.trailingOpacity, soft: 0.25),
|
||||
|
||||
@@ -8,6 +8,7 @@ Use a terminal pane in cmux and `cd` into these directories:
|
||||
- `dogfood/directory-actions/alpha/nested`
|
||||
- `dogfood/directory-actions/legacy`
|
||||
- `dogfood/directory-actions/legacy/prefer-dot-cmux`
|
||||
- `dogfood/directory-actions/many-tab-actions`
|
||||
|
||||
What each one demonstrates:
|
||||
|
||||
@@ -25,6 +26,9 @@ What each one demonstrates:
|
||||
- `legacy/prefer-dot-cmux`
|
||||
- Contains both `./cmux.json` and `./.cmux/cmux.json`
|
||||
- The `./.cmux/cmux.json` file should win
|
||||
- `many-tab-actions`
|
||||
- Defines 24 custom actions plus the 4 built-ins
|
||||
- Replaces the surface tab bar button list to stress wide action rows
|
||||
|
||||
General expectations:
|
||||
|
||||
|
||||
@@ -0,0 +1,254 @@
|
||||
{
|
||||
"actions": {
|
||||
"many.action01": {
|
||||
"type": "command",
|
||||
"title": "Action 01",
|
||||
"subtitle": "Many tab actions dogfood",
|
||||
"command": "printf 'MANY TAB ACTION 01\\n'; pwd",
|
||||
"target": "newTabInCurrentPane",
|
||||
"palette": false,
|
||||
"icon": { "type": "symbol", "name": "terminal" }
|
||||
},
|
||||
"many.action02": {
|
||||
"type": "command",
|
||||
"title": "Action 02",
|
||||
"subtitle": "Many tab actions dogfood",
|
||||
"command": "printf 'MANY TAB ACTION 02\\n'; pwd",
|
||||
"target": "newTabInCurrentPane",
|
||||
"palette": false,
|
||||
"icon": { "type": "symbol", "name": "globe" }
|
||||
},
|
||||
"many.action03": {
|
||||
"type": "command",
|
||||
"title": "Action 03",
|
||||
"subtitle": "Many tab actions dogfood",
|
||||
"command": "printf 'MANY TAB ACTION 03\\n'; pwd",
|
||||
"target": "newTabInCurrentPane",
|
||||
"palette": false,
|
||||
"icon": { "type": "symbol", "name": "square.split.2x1" }
|
||||
},
|
||||
"many.action04": {
|
||||
"type": "command",
|
||||
"title": "Action 04",
|
||||
"subtitle": "Many tab actions dogfood",
|
||||
"command": "printf 'MANY TAB ACTION 04\\n'; pwd",
|
||||
"target": "newTabInCurrentPane",
|
||||
"palette": false,
|
||||
"icon": { "type": "symbol", "name": "square.split.1x2" }
|
||||
},
|
||||
"many.action05": {
|
||||
"type": "command",
|
||||
"title": "Action 05",
|
||||
"subtitle": "Many tab actions dogfood",
|
||||
"command": "printf 'MANY TAB ACTION 05\\n'; pwd",
|
||||
"target": "newTabInCurrentPane",
|
||||
"palette": false,
|
||||
"icon": { "type": "symbol", "name": "doc" }
|
||||
},
|
||||
"many.action06": {
|
||||
"type": "command",
|
||||
"title": "Action 06",
|
||||
"subtitle": "Many tab actions dogfood",
|
||||
"command": "printf 'MANY TAB ACTION 06\\n'; pwd",
|
||||
"target": "newTabInCurrentPane",
|
||||
"palette": false,
|
||||
"icon": { "type": "symbol", "name": "folder" }
|
||||
},
|
||||
"many.action07": {
|
||||
"type": "command",
|
||||
"title": "Action 07",
|
||||
"subtitle": "Many tab actions dogfood",
|
||||
"command": "printf 'MANY TAB ACTION 07\\n'; pwd",
|
||||
"target": "newTabInCurrentPane",
|
||||
"palette": false,
|
||||
"icon": { "type": "symbol", "name": "magnifyingglass" }
|
||||
},
|
||||
"many.action08": {
|
||||
"type": "command",
|
||||
"title": "Action 08",
|
||||
"subtitle": "Many tab actions dogfood",
|
||||
"command": "printf 'MANY TAB ACTION 08\\n'; pwd",
|
||||
"target": "newTabInCurrentPane",
|
||||
"palette": false,
|
||||
"icon": { "type": "symbol", "name": "gearshape" }
|
||||
},
|
||||
"many.action09": {
|
||||
"type": "command",
|
||||
"title": "Action 09",
|
||||
"subtitle": "Many tab actions dogfood",
|
||||
"command": "printf 'MANY TAB ACTION 09\\n'; pwd",
|
||||
"target": "newTabInCurrentPane",
|
||||
"palette": false,
|
||||
"icon": { "type": "symbol", "name": "hammer" }
|
||||
},
|
||||
"many.action10": {
|
||||
"type": "command",
|
||||
"title": "Action 10",
|
||||
"subtitle": "Many tab actions dogfood",
|
||||
"command": "printf 'MANY TAB ACTION 10\\n'; pwd",
|
||||
"target": "newTabInCurrentPane",
|
||||
"palette": false,
|
||||
"icon": { "type": "symbol", "name": "wrench.and.screwdriver" }
|
||||
},
|
||||
"many.action11": {
|
||||
"type": "command",
|
||||
"title": "Action 11",
|
||||
"subtitle": "Many tab actions dogfood",
|
||||
"command": "printf 'MANY TAB ACTION 11\\n'; pwd",
|
||||
"target": "newTabInCurrentPane",
|
||||
"palette": false,
|
||||
"icon": { "type": "symbol", "name": "bolt" }
|
||||
},
|
||||
"many.action12": {
|
||||
"type": "command",
|
||||
"title": "Action 12",
|
||||
"subtitle": "Many tab actions dogfood",
|
||||
"command": "printf 'MANY TAB ACTION 12\\n'; pwd",
|
||||
"target": "newTabInCurrentPane",
|
||||
"palette": false,
|
||||
"icon": { "type": "symbol", "name": "flag" }
|
||||
},
|
||||
"many.action13": {
|
||||
"type": "command",
|
||||
"title": "Action 13",
|
||||
"subtitle": "Many tab actions dogfood",
|
||||
"command": "printf 'MANY TAB ACTION 13\\n'; pwd",
|
||||
"target": "newTabInCurrentPane",
|
||||
"palette": false,
|
||||
"icon": { "type": "symbol", "name": "star" }
|
||||
},
|
||||
"many.action14": {
|
||||
"type": "command",
|
||||
"title": "Action 14",
|
||||
"subtitle": "Many tab actions dogfood",
|
||||
"command": "printf 'MANY TAB ACTION 14\\n'; pwd",
|
||||
"target": "newTabInCurrentPane",
|
||||
"palette": false,
|
||||
"icon": { "type": "symbol", "name": "bookmark" }
|
||||
},
|
||||
"many.action15": {
|
||||
"type": "command",
|
||||
"title": "Action 15",
|
||||
"subtitle": "Many tab actions dogfood",
|
||||
"command": "printf 'MANY TAB ACTION 15\\n'; pwd",
|
||||
"target": "newTabInCurrentPane",
|
||||
"palette": false,
|
||||
"icon": { "type": "symbol", "name": "bell" }
|
||||
},
|
||||
"many.action16": {
|
||||
"type": "command",
|
||||
"title": "Action 16",
|
||||
"subtitle": "Many tab actions dogfood",
|
||||
"command": "printf 'MANY TAB ACTION 16\\n'; pwd",
|
||||
"target": "newTabInCurrentPane",
|
||||
"palette": false,
|
||||
"icon": { "type": "symbol", "name": "tray" }
|
||||
},
|
||||
"many.action17": {
|
||||
"type": "command",
|
||||
"title": "Action 17",
|
||||
"subtitle": "Many tab actions dogfood",
|
||||
"command": "printf 'MANY TAB ACTION 17\\n'; pwd",
|
||||
"target": "newTabInCurrentPane",
|
||||
"palette": false,
|
||||
"icon": { "type": "symbol", "name": "arrow.clockwise" }
|
||||
},
|
||||
"many.action18": {
|
||||
"type": "command",
|
||||
"title": "Action 18",
|
||||
"subtitle": "Many tab actions dogfood",
|
||||
"command": "printf 'MANY TAB ACTION 18\\n'; pwd",
|
||||
"target": "newTabInCurrentPane",
|
||||
"palette": false,
|
||||
"icon": { "type": "symbol", "name": "play" }
|
||||
},
|
||||
"many.action19": {
|
||||
"type": "command",
|
||||
"title": "Action 19",
|
||||
"subtitle": "Many tab actions dogfood",
|
||||
"command": "printf 'MANY TAB ACTION 19\\n'; pwd",
|
||||
"target": "newTabInCurrentPane",
|
||||
"palette": false,
|
||||
"icon": { "type": "symbol", "name": "stop" }
|
||||
},
|
||||
"many.action20": {
|
||||
"type": "command",
|
||||
"title": "Action 20",
|
||||
"subtitle": "Many tab actions dogfood",
|
||||
"command": "printf 'MANY TAB ACTION 20\\n'; pwd",
|
||||
"target": "newTabInCurrentPane",
|
||||
"palette": false,
|
||||
"icon": { "type": "symbol", "name": "pause" }
|
||||
},
|
||||
"many.action21": {
|
||||
"type": "command",
|
||||
"title": "Action 21",
|
||||
"subtitle": "Many tab actions dogfood",
|
||||
"command": "printf 'MANY TAB ACTION 21\\n'; pwd",
|
||||
"target": "newTabInCurrentPane",
|
||||
"palette": false,
|
||||
"icon": { "type": "symbol", "name": "record.circle" }
|
||||
},
|
||||
"many.action22": {
|
||||
"type": "command",
|
||||
"title": "Action 22",
|
||||
"subtitle": "Many tab actions dogfood",
|
||||
"command": "printf 'MANY TAB ACTION 22\\n'; pwd",
|
||||
"target": "newTabInCurrentPane",
|
||||
"palette": false,
|
||||
"icon": { "type": "symbol", "name": "shippingbox" }
|
||||
},
|
||||
"many.action23": {
|
||||
"type": "command",
|
||||
"title": "Action 23",
|
||||
"subtitle": "Many tab actions dogfood",
|
||||
"command": "printf 'MANY TAB ACTION 23\\n'; pwd",
|
||||
"target": "newTabInCurrentPane",
|
||||
"palette": false,
|
||||
"icon": { "type": "symbol", "name": "network" }
|
||||
},
|
||||
"many.action24": {
|
||||
"type": "command",
|
||||
"title": "Action 24",
|
||||
"subtitle": "Many tab actions dogfood",
|
||||
"command": "printf 'MANY TAB ACTION 24\\n'; pwd",
|
||||
"target": "newTabInCurrentPane",
|
||||
"palette": false,
|
||||
"icon": { "type": "symbol", "name": "externaldrive" }
|
||||
}
|
||||
},
|
||||
"ui": {
|
||||
"surfaceTabBar": {
|
||||
"buttons": [
|
||||
"cmux.newTerminal",
|
||||
"cmux.newBrowser",
|
||||
"cmux.splitRight",
|
||||
"cmux.splitDown",
|
||||
"many.action01",
|
||||
"many.action02",
|
||||
"many.action03",
|
||||
"many.action04",
|
||||
"many.action05",
|
||||
"many.action06",
|
||||
"many.action07",
|
||||
"many.action08",
|
||||
"many.action09",
|
||||
"many.action10",
|
||||
"many.action11",
|
||||
"many.action12",
|
||||
"many.action13",
|
||||
"many.action14",
|
||||
"many.action15",
|
||||
"many.action16",
|
||||
"many.action17",
|
||||
"many.action18",
|
||||
"many.action19",
|
||||
"many.action20",
|
||||
"many.action21",
|
||||
"many.action22",
|
||||
"many.action23",
|
||||
"many.action24"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
Vendored
+1
-1
Submodule vendor/bonsplit updated: d0de5d1740...cc0f548608
Reference in New Issue
Block a user