Skip to content

Commit

Permalink
Add --when-visible (focus|swap) option to the summon-workspace comm…
Browse files Browse the repository at this point in the history
…and.

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
  • Loading branch information
lynaghk committed Nov 9, 2024
1 parent 00cbb63 commit 4148543
Show file tree
Hide file tree
Showing 3 changed files with 53 additions and 6 deletions.
31 changes: 26 additions & 5 deletions Sources/AppBundle/command/impl/SummonWorkspaceCommand.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,36 @@ struct SummonWorkspaceCommand: Command {
func run(_ env: CmdEnv, _ io: CmdIo) -> Bool {
check(Thread.current.isMainThread)
let workspace = Workspace.get(byName: args.target.val.raw)
let monitor = focus.workspace.workspaceMonitor
if monitor.activeWorkspace == workspace {
let focusedMonitor = focus.workspace.workspaceMonitor

if focusedMonitor.activeWorkspace == workspace {
io.err("Workspace '\(workspace.name)' is already visible on the focused monitor. Tip: use --fail-if-noop to exit with non-zero code")
return !args.failIfNoop
}
if monitor.setActiveWorkspace(workspace) {
return workspace.focusWorkspace()

if !workspace.isVisible {
// then we just need to summon the workspace to the focused monitor
if focusedMonitor.setActiveWorkspace(workspace) {
return workspace.focusWorkspace()
} else {
return io.err("Can't move workspace '\(workspace.name)' to monitor '\(focusedMonitor.name)'. workspace-to-monitor-force-assignment doesn't allow it")
}
} else {
return io.err("Can't move workspace '\(workspace.name)' to monitor '\(monitor.name)'. workspace-to-monitor-force-assignment doesn't allow it")
let otherMonitor = workspace.workspaceMonitor
let currentWorkspace = focusedMonitor.activeWorkspace

switch args.whenVisible {
case .swap:
if otherMonitor.setActiveWorkspace(currentWorkspace) && focusedMonitor.setActiveWorkspace(workspace) {
return workspace.focusWorkspace()
} else {
return io.err("Can't swap workspaces due to monitor force assignment restrictions")
}
case .focus:
return workspace.focusWorkspace()
}


}
}
}
21 changes: 21 additions & 0 deletions Sources/Common/cmdArgs/impl/SummonWorkspaceCmdArgs.swift
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
private let actio = "<action>"

public struct SummonWorkspaceCmdArgs: CmdArgs {
public let rawArgs: EquatableNoop<[String]>
public init(rawArgs: [String]) { self.rawArgs = .init(rawArgs) }
Expand All @@ -7,6 +9,7 @@ public struct SummonWorkspaceCmdArgs: CmdArgs {
help: summon_workspace_help_generated,
options: [
"--fail-if-noop": trueBoolFlag(\.failIfNoop),
"--when-visible": ArgParser(\.rawWhenVisibleAction, upcastArgParserFun(parseWhenVisibleAction)),
],
arguments: [newArgParser(\.target, parseWorkspaceName, mandatoryArgPlaceholder: "<workspace>")]
)
Expand All @@ -16,8 +19,26 @@ public struct SummonWorkspaceCmdArgs: CmdArgs {

public var target: Lateinit<WorkspaceName> = .uninitialized
public var failIfNoop: Bool = false
public var rawWhenVisibleAction: WhenVisible? = nil

public enum WhenVisible: String, CaseIterable, Equatable {
case focus = "focus"
case swap = "swap"
}
}

public extension SummonWorkspaceCmdArgs {
var whenVisible: WhenVisible { rawWhenVisibleAction ?? .focus }
}

private func parseWorkspaceName(arg: String, nextArgs: inout [String]) -> Parsed<WorkspaceName> {
WorkspaceName.parse(arg)
}

private func parseWhenVisibleAction(arg: String, nextArgs: inout [String]) -> Parsed<SummonWorkspaceCmdArgs.WhenVisible> {
if let arg = nextArgs.nextNonFlagOrNil() {
return parseEnum(arg, SummonWorkspaceCmdArgs.WhenVisible.self)
} else {
return .failure("\(actio) is mandatory")
}
}
7 changes: 6 additions & 1 deletion docs/aerospace-summon-workspace.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ include::util/man-attributes.adoc[]
== Synopsis
[verse]
// tag::synopsis[]
aerospace summon-workspace [-h|--help] [--fail-if-noop] <workspace>
aerospace summon-workspace [-h|--help] [--fail-if-noop] [--when-visible (focus|swap)] <workspace>

// end::synopsis[]

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

--when-visible <action>::
Defines the behavior if the workspace is already visible on another monitor.
`<action>` possible values: `(focus|swap)`. +
The default is: `focus`

// =========================================================== Arguments
include::./util/conditional-arguments-header.adoc[]

Expand Down

0 comments on commit 4148543

Please sign in to comment.