Skip to content

Commit

Permalink
Sort workspaces logically
Browse files Browse the repository at this point in the history
  • Loading branch information
nikitabobko committed Jun 12, 2024
1 parent f649909 commit 5aee831
Show file tree
Hide file tree
Showing 3 changed files with 59 additions and 3 deletions.
2 changes: 1 addition & 1 deletion Sources/AppBundle/command/WorkspaceCommand.swift
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ func getNextPrevWorkspace(current: Workspace, relative: WTarget.Relative, stdin:
? Workspace.all.filter { $0.workspaceMonitor.rect.topLeftCorner == currentMonitor.rect.topLeftCorner }
.toSet()
.union([current])
.sortedBy { $0.name }
.sorted()
: stdinWorkspaces.map { Workspace.get(byName: $0) }
let index = workspaces.firstIndex(where: { $0 == Workspace.focused }) ?? 0
let workspace: Workspace?
Expand Down
8 changes: 6 additions & 2 deletions Sources/AppBundle/tree/Workspace.swift
Original file line number Diff line number Diff line change
Expand Up @@ -28,19 +28,21 @@ private func getStubWorkspace(forPoint point: CGPoint) -> Workspace {
?? errorT("Can't create empty workspace")
}

class Workspace: TreeNode, NonLeafTreeNodeObject, Hashable, Identifiable, CustomStringConvertible {
class Workspace: TreeNode, NonLeafTreeNodeObject, Hashable, Identifiable, CustomStringConvertible, Comparable {
let name: String
private let nameLogicalSegments: StringLogicalSegments
var id: String { name } // satisfy Identifiable
/// `assignedMonitorPoint` must be interpreted only when the workspace is invisible
fileprivate var assignedMonitorPoint: CGPoint? = nil

private init(_ name: String) {
self.name = name
self.nameLogicalSegments = name.toLogicalSegments()
super.init(parent: NilTreeNode.instance, adaptiveWeight: 0, index: 0)
}

static var all: [Workspace] {
workspaceNameToWorkspace.values.sortedBy(\.name)
workspaceNameToWorkspace.values.sorted()
}

static func get(byName name: String) -> Workspace {
Expand All @@ -53,6 +55,8 @@ class Workspace: TreeNode, NonLeafTreeNodeObject, Hashable, Identifiable, Custom
}
}

static func < (lhs: Workspace, rhs: Workspace) -> Bool { lhs.nameLogicalSegments < rhs.nameLogicalSegments }

override func getWeight(_ targetOrientation: Orientation) -> CGFloat {
workspaceMonitor.visibleRectPaddedByOuterGaps.getDimension(targetOrientation)
}
Expand Down
52 changes: 52 additions & 0 deletions Sources/Common/util/StringLogicalSegments.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
public typealias StringLogicalSegments = [StringLogicalSegment]
extension StringLogicalSegments: Comparable {
public static func < (lhs: Self, rhs: Self) -> Bool {
for (a, b) in zip(lhs, rhs) {
if a < b {
return true
}
if a > b {
return false
}
}
if lhs.count != rhs.count {
return lhs.count < rhs.count
}
return false
}
}

public enum StringLogicalSegment: Comparable, Equatable {
case string(String)
case number(Int)

public static func < (lhs: Self, rhs: Self) -> Bool {
switch (lhs, rhs) {
case (.string(let a), .string(let b)): a < b
case (.number(let a), .number(let b)): a < b
case (.number, _): true
case (.string, _): false
}
}
}

public extension String {
func toLogicalSegments() -> StringLogicalSegments {
var currentSegment: String = ""
var isPrevNumber: Bool = false // Initial value doesn't matter
var result: [String] = []
for char in self {
let isCurNumber = Int(char.description) != nil
if isCurNumber != isPrevNumber && !currentSegment.isEmpty {
result.append(currentSegment)
currentSegment = ""
}
currentSegment.append(char)
isPrevNumber = isCurNumber
}
if !currentSegment.isEmpty {
result.append(currentSegment)
}
return result.map { Int($0).flatMap(StringLogicalSegment.number) ?? .string($0) }
}
}

0 comments on commit 5aee831

Please sign in to comment.