Skip to content

Commit 4148543

Browse files
committed
Add --when-visible (focus|swap) option to the summon-workspace command.
What should happen when the summoned workspace is visible on another monitor? This option introduces a choice to either: - `focus` the monitor on which the target workspace is already visible (the current behavior) - `swap` the workspaces between the monitors, so that the summoned workspace appears on the focused monitor. The default is `focus`, for backwards compatibility. Ref: #603
1 parent 00cbb63 commit 4148543

File tree

3 files changed

+53
-6
lines changed

3 files changed

+53
-6
lines changed

Sources/AppBundle/command/impl/SummonWorkspaceCommand.swift

Lines changed: 26 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,15 +7,36 @@ struct SummonWorkspaceCommand: Command {
77
func run(_ env: CmdEnv, _ io: CmdIo) -> Bool {
88
check(Thread.current.isMainThread)
99
let workspace = Workspace.get(byName: args.target.val.raw)
10-
let monitor = focus.workspace.workspaceMonitor
11-
if monitor.activeWorkspace == workspace {
10+
let focusedMonitor = focus.workspace.workspaceMonitor
11+
12+
if focusedMonitor.activeWorkspace == workspace {
1213
io.err("Workspace '\(workspace.name)' is already visible on the focused monitor. Tip: use --fail-if-noop to exit with non-zero code")
1314
return !args.failIfNoop
1415
}
15-
if monitor.setActiveWorkspace(workspace) {
16-
return workspace.focusWorkspace()
16+
17+
if !workspace.isVisible {
18+
// then we just need to summon the workspace to the focused monitor
19+
if focusedMonitor.setActiveWorkspace(workspace) {
20+
return workspace.focusWorkspace()
21+
} else {
22+
return io.err("Can't move workspace '\(workspace.name)' to monitor '\(focusedMonitor.name)'. workspace-to-monitor-force-assignment doesn't allow it")
23+
}
1724
} else {
18-
return io.err("Can't move workspace '\(workspace.name)' to monitor '\(monitor.name)'. workspace-to-monitor-force-assignment doesn't allow it")
25+
let otherMonitor = workspace.workspaceMonitor
26+
let currentWorkspace = focusedMonitor.activeWorkspace
27+
28+
switch args.whenVisible {
29+
case .swap:
30+
if otherMonitor.setActiveWorkspace(currentWorkspace) && focusedMonitor.setActiveWorkspace(workspace) {
31+
return workspace.focusWorkspace()
32+
} else {
33+
return io.err("Can't swap workspaces due to monitor force assignment restrictions")
34+
}
35+
case .focus:
36+
return workspace.focusWorkspace()
37+
}
38+
39+
1940
}
2041
}
2142
}

Sources/Common/cmdArgs/impl/SummonWorkspaceCmdArgs.swift

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
private let actio = "<action>"
2+
13
public struct SummonWorkspaceCmdArgs: CmdArgs {
24
public let rawArgs: EquatableNoop<[String]>
35
public init(rawArgs: [String]) { self.rawArgs = .init(rawArgs) }
@@ -7,6 +9,7 @@ public struct SummonWorkspaceCmdArgs: CmdArgs {
79
help: summon_workspace_help_generated,
810
options: [
911
"--fail-if-noop": trueBoolFlag(\.failIfNoop),
12+
"--when-visible": ArgParser(\.rawWhenVisibleAction, upcastArgParserFun(parseWhenVisibleAction)),
1013
],
1114
arguments: [newArgParser(\.target, parseWorkspaceName, mandatoryArgPlaceholder: "<workspace>")]
1215
)
@@ -16,8 +19,26 @@ public struct SummonWorkspaceCmdArgs: CmdArgs {
1619

1720
public var target: Lateinit<WorkspaceName> = .uninitialized
1821
public var failIfNoop: Bool = false
22+
public var rawWhenVisibleAction: WhenVisible? = nil
23+
24+
public enum WhenVisible: String, CaseIterable, Equatable {
25+
case focus = "focus"
26+
case swap = "swap"
27+
}
28+
}
29+
30+
public extension SummonWorkspaceCmdArgs {
31+
var whenVisible: WhenVisible { rawWhenVisibleAction ?? .focus }
1932
}
2033

2134
private func parseWorkspaceName(arg: String, nextArgs: inout [String]) -> Parsed<WorkspaceName> {
2235
WorkspaceName.parse(arg)
2336
}
37+
38+
private func parseWhenVisibleAction(arg: String, nextArgs: inout [String]) -> Parsed<SummonWorkspaceCmdArgs.WhenVisible> {
39+
if let arg = nextArgs.nextNonFlagOrNil() {
40+
return parseEnum(arg, SummonWorkspaceCmdArgs.WhenVisible.self)
41+
} else {
42+
return .failure("\(actio) is mandatory")
43+
}
44+
}

docs/aerospace-summon-workspace.adoc

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ include::util/man-attributes.adoc[]
99
== Synopsis
1010
[verse]
1111
// tag::synopsis[]
12-
aerospace summon-workspace [-h|--help] [--fail-if-noop] <workspace>
12+
aerospace summon-workspace [-h|--help] [--fail-if-noop] [--when-visible (focus|swap)] <workspace>
1313

1414
// end::synopsis[]
1515

@@ -30,6 +30,11 @@ include::./util/conditional-options-header.adoc[]
3030
-h, --help:: Print help
3131
--fail-if-noop:: Exit with non-zero exit code if the workspace already visible on the focused monitor.
3232

33+
--when-visible <action>::
34+
Defines the behavior if the workspace is already visible on another monitor.
35+
`<action>` possible values: `(focus|swap)`. +
36+
The default is: `focus`
37+
3338
// =========================================================== Arguments
3439
include::./util/conditional-arguments-header.adoc[]
3540

0 commit comments

Comments
 (0)