From f6876d224626a6a4c1be44d7d8d81fa12f9c46bc Mon Sep 17 00:00:00 2001 From: Franz Murner Date: Sat, 7 Dec 2024 22:36:12 +0100 Subject: [PATCH] Provide the user of the "move-workspace-to-monitor" command more capabiltities for moving their workspaces between monitors The "move-workspace-to-monitor" command provides now the requested features of Issue https://github.com/nikitabobko/AeroSpace/issues/766. This commit makes it possible to move workspaces to a specific monitor with a monitor pattern Additonally to the next|prev i have added the left|down|up|right option closes https://github.com/nikitabobko/AeroSpace/pull/831 --- .../impl/MoveWorkspaceToMonitorCommand.swift | 32 +++++++++++-------- .../Cli/subcommandDescriptionsGenerated.swift | 2 +- Sources/Common/cmdArgs/cmdArgsManifest.swift | 2 +- .../impl/MoveWorkpsaceToMonitorCmdArgs.swift | 20 ++++++++---- Sources/Common/cmdHelpGenerated.swift | 4 ++- docs/aerospace-move-workspace-to-monitor.adoc | 11 ++++++- grammar/commands-bnf-grammar.txt | 3 +- 7 files changed, 49 insertions(+), 25 deletions(-) diff --git a/Sources/AppBundle/command/impl/MoveWorkspaceToMonitorCommand.swift b/Sources/AppBundle/command/impl/MoveWorkspaceToMonitorCommand.swift index 38a7fa66..890172d8 100644 --- a/Sources/AppBundle/command/impl/MoveWorkspaceToMonitorCommand.swift +++ b/Sources/AppBundle/command/impl/MoveWorkspaceToMonitorCommand.swift @@ -9,20 +9,26 @@ struct MoveWorkspaceToMonitorCommand: Command { guard let target = args.resolveTargetOrReportError(env, io) else { return false } let focusedWorkspace = target.workspace let prevMonitor = focusedWorkspace.workspaceMonitor - let sortedMonitors = sortedMonitors - guard let index = sortedMonitors.firstIndex(where: { $0.rect.topLeftCorner == prevMonitor.rect.topLeftCorner }) else { return false } - let targetMonitor = args.wrapAround - ? sortedMonitors.get(wrappingIndex: args.target.val == .next ? index + 1 : index - 1) - : sortedMonitors.getOrNil(atIndex: args.target.val == .next ? index + 1 : index - 1) - guard let targetMonitor else { return false } - if targetMonitor.setActiveWorkspace(focusedWorkspace) { - let stubWorkspace = getStubWorkspace(for: prevMonitor) - check(prevMonitor.setActiveWorkspace(stubWorkspace), - "getStubWorkspace generated incompatible stub workspace (\(stubWorkspace)) for the monitor (\(prevMonitor)") - return true - } else { - return io.err("Can't move workspace '\(focusedWorkspace.name)' to monitor '\(targetMonitor.name)'. workspace-to-monitor-force-assignment doesn't allow it") + switch args.target.val.resolve(target.workspace.workspaceMonitor, wrapAround: args.wrapAround) { + case .success(let targetMonitor): + if targetMonitor.monitorId == prevMonitor.monitorId { + return true + } + if targetMonitor.setActiveWorkspace(focusedWorkspace) { + let stubWorkspace = getStubWorkspace(for: prevMonitor) + check( + prevMonitor.setActiveWorkspace(stubWorkspace), + "getStubWorkspace generated incompatible stub workspace (\(stubWorkspace)) for the monitor (\(prevMonitor)" + ) + return true + } else { + return io.err( + "Can't move workspace '\(focusedWorkspace.name)' to monitor '\(targetMonitor.name)'. workspace-to-monitor-force-assignment doesn't allow it" + ) + } + case .failure(let msg): + return io.err(msg) } } } diff --git a/Sources/Cli/subcommandDescriptionsGenerated.swift b/Sources/Cli/subcommandDescriptionsGenerated.swift index b6a1997d..72ec0734 100644 --- a/Sources/Cli/subcommandDescriptionsGenerated.swift +++ b/Sources/Cli/subcommandDescriptionsGenerated.swift @@ -27,7 +27,7 @@ let subcommandDescriptions = [ [" move-mouse", "Move mouse to the requested position"], [" move-node-to-monitor", "Move window to monitor targeted by relative direction, by order, or by pattern"], [" move-node-to-workspace", "Move the focused window to the specified workspace"], - [" move-workspace-to-monitor", "Move the focused workspace to the next or previous monitor."], + [" move-workspace-to-monitor", "Move workspace to monitor targeted by relative direction, by order, or by pattern."], [" move", "Move the focused window in the given direction"], [" reload-config", "Reload currently active config"], [" resize", "Resize the focused window"], diff --git a/Sources/Common/cmdArgs/cmdArgsManifest.swift b/Sources/Common/cmdArgs/cmdArgsManifest.swift index 2befd72c..dc4aae27 100644 --- a/Sources/Common/cmdArgs/cmdArgsManifest.swift +++ b/Sources/Common/cmdArgs/cmdArgsManifest.swift @@ -102,7 +102,7 @@ func initSubcommands() -> [String: any SubCommandParserProtocol] { case .moveNodeToWorkspace: result[kind.rawValue] = SubCommandParser(parseMoveNodeToWorkspaceCmdArgs) case .moveWorkspaceToMonitor: - result[kind.rawValue] = SubCommandParser(MoveWorkspaceToMonitorCmdArgs.init) + result[kind.rawValue] = SubCommandParser(parseWorkspaceToMonitorCmdArgs) // deprecated result["move-workspace-to-display"] = SubCommandParser(MoveWorkspaceToMonitorCmdArgs.init) case .reloadConfig: diff --git a/Sources/Common/cmdArgs/impl/MoveWorkpsaceToMonitorCmdArgs.swift b/Sources/Common/cmdArgs/impl/MoveWorkpsaceToMonitorCmdArgs.swift index 6307d75b..27cb8577 100644 --- a/Sources/Common/cmdArgs/impl/MoveWorkpsaceToMonitorCmdArgs.swift +++ b/Sources/Common/cmdArgs/impl/MoveWorkpsaceToMonitorCmdArgs.swift @@ -9,18 +9,24 @@ public struct MoveWorkspaceToMonitorCmdArgs: CmdArgs { "--wrap-around": trueBoolFlag(\.wrapAround), "--workspace": optionalWorkspaceFlag(), ], - arguments: [newArgParser(\.target, parseMonitorTarget, mandatoryArgPlaceholder: "(next|prev)")] + arguments: [ + newArgParser( + \.target, + parseTarget, + mandatoryArgPlaceholder: "(left|down|up|right|next|prev|)" + ), + ] ) public var windowId: UInt32? public var workspaceName: WorkspaceName? public var wrapAround: Bool = false - public var target: Lateinit = .uninitialized - public enum MonitorTarget: String, CaseIterable { - case next, prev - } + public var target: Lateinit = .uninitialized } -private func parseMonitorTarget(arg: String, nextArgs: inout [String]) -> Parsed { - parseEnum(arg, MoveWorkspaceToMonitorCmdArgs.MonitorTarget.self) +public func parseWorkspaceToMonitorCmdArgs(_ args: [String]) -> ParsedCmd { + parseSpecificCmdArgs(MoveWorkspaceToMonitorCmdArgs(rawArgs: args), args) + .filter("--wrap-around is incompatible with argument") { + $0.wrapAround.implies(!$0.target.val.isPatterns) + } } diff --git a/Sources/Common/cmdHelpGenerated.swift b/Sources/Common/cmdHelpGenerated.swift index 8a06b7a8..390bc6e1 100644 --- a/Sources/Common/cmdHelpGenerated.swift +++ b/Sources/Common/cmdHelpGenerated.swift @@ -109,7 +109,9 @@ let move_node_to_workspace_help_generated = """ [--window-id ] """ let move_workspace_to_monitor_help_generated = """ - USAGE: move-workspace-to-monitor [-h|--help] [--workspace ] [--wrap-around] (next|prev) + USAGE: move-workspace-to-monitor [-h|--help] [--workspace ] [--wrap-around] (left|down|up|right) + OR: move-workspace-to-monitor [-h|--help] [--workspace ] [--wrap-around] (next|prev) + OR: move-workspace-to-monitor [-h|--help] [--workspace ] ... """ let move_help_generated = """ USAGE: move [-h|--help] [--window-id ] (left|down|up|right) diff --git a/docs/aerospace-move-workspace-to-monitor.adoc b/docs/aerospace-move-workspace-to-monitor.adoc index 23e4fa36..6b103ca4 100644 --- a/docs/aerospace-move-workspace-to-monitor.adoc +++ b/docs/aerospace-move-workspace-to-monitor.adoc @@ -2,14 +2,16 @@ include::util/man-attributes.adoc[] :manname: aerospace-move-workspace-to-monitor // tag::purpose[] -:manpurpose: Move the focused workspace to the next or previous monitor. +:manpurpose: Move workspace to monitor targeted by relative direction, by order, or by pattern. // end::purpose[] // =========================================================== Synopsis == Synopsis [verse] // tag::synopsis[] +aerospace move-workspace-to-monitor [-h|--help] [--workspace ] [--wrap-around] (left|down|up|right) aerospace move-workspace-to-monitor [-h|--help] [--workspace ] [--wrap-around] (next|prev) +aerospace move-workspace-to-monitor [-h|--help] [--workspace ] ... // end::synopsis[] @@ -34,10 +36,17 @@ include::./util/workspace-flag-desc.adoc[] // =========================================================== Arguments include::./util/conditional-arguments-header.adoc[] +(left|down|up|right):: +Move workspace to monitor in direction relative to the focused monitor + (next|prev):: Move the workspace to next or prev monitor. 'next' or 'prev' monitor is calculated relative to the monitor `` currently belongs to. +:: +Find the first monitor pattern in the list that doesn't describe the current monitor and move the workspace to the appropriate monitor. +Monitor pattern is the same as in `workspace-to-monitor-force-assignment` config option + // end::body[] // =========================================================== Footer diff --git a/grammar/commands-bnf-grammar.txt b/grammar/commands-bnf-grammar.txt index 891cfb85..30cca020 100644 --- a/grammar/commands-bnf-grammar.txt +++ b/grammar/commands-bnf-grammar.txt @@ -54,7 +54,8 @@ aerospace -h; | move-node-to-workspace [--wrap-around|--focus-follows-window]... (next|prev) [--wrap-around|--focus-follows-window]... | move-node-to-workspace [--fail-if-noop|--window-id |--focus-follows-window]... [--fail-if-noop|--window-id |--focus-follows-window]... - | move-workspace-to-monitor [--wrap-around] (next|prev) [--wrap-around] + | move-workspace-to-monitor [--wrap-around] (left|down|up|right|next|prev) [--wrap-around] + | move-workspace-to-monitor [--wrap-around] ... [--wrap-around] | reload-config [--no-gui | --dry-run]...