Skip to content

Commit 9dae81d

Browse files
committed
Ensure tab is handled as expected
1 parent 000dd57 commit 9dae81d

3 files changed

Lines changed: 60 additions & 3 deletions

File tree

Sources/CodeEditSourceEditor/Controller/TextViewController+IndentLines.swift

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,21 @@ extension TextViewController {
3838
textView.undoManager?.endUndoGrouping()
3939
}
4040

41+
/// This method is used to handle tabs appropriately when multiple lines are selected,
42+
/// allowing normal use of tabs.
43+
///
44+
/// - Returns: A Boolean value indicating whether multiple lines are highlighted.
45+
func multipleLinesHighlighted() -> Bool {
46+
for cursorPosition in self.cursorPositions {
47+
if let startLineInfo = textView.layoutManager.textLineForOffset(cursorPosition.range.lowerBound),
48+
let endLineInfo = textView.layoutManager.textLineForOffset(cursorPosition.range.upperBound),
49+
startLineInfo.index != endLineInfo.index {
50+
return true
51+
}
52+
}
53+
return false
54+
}
55+
4156
private func getHighlightedLines(for range: NSRange) -> [Int]? {
4257
guard let startLineInfo = textView.layoutManager.textLineForOffset(range.lowerBound) else {
4358
return nil

Sources/CodeEditSourceEditor/Controller/TextViewController+LoadView.swift

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -120,8 +120,7 @@ extension TextViewController {
120120
let modifierFlags = event.modifierFlags.intersection(.deviceIndependentFlagsMask).rawValue
121121

122122
if event.keyCode == tabKey {
123-
self?.handleTab(modifierFalgs: modifierFlags)
124-
return nil
123+
return self?.handleTab(event: event, modifierFalgs: modifierFlags)
125124
} else {
126125
return self?.handleCommand(event: event, modifierFlags: modifierFlags)
127126
}
@@ -145,13 +144,21 @@ extension TextViewController {
145144
}
146145
}
147146

148-
func handleTab(modifierFalgs: UInt) {
147+
/// Handles the tab key event.
148+
/// If the Shift key is pressed, it handles unindenting. If no modifier key is pressed, it checks if multiple lines
149+
/// are highlighted and handles indenting accordingly.
150+
///
151+
/// - Returns: The original event if it should be passed on, or `nil` to indicate handling within the method.
152+
func handleTab(event: NSEvent, modifierFalgs: UInt) -> NSEvent? {
149153
let shiftKey = NSEvent.ModifierFlags.shift.rawValue
150154

151155
if modifierFalgs == shiftKey {
152156
handleIndent(inwards: true)
153157
} else {
158+
// Only allow tab to work if multiple lines are selected
159+
guard multipleLinesHighlighted() else { return event }
154160
handleIndent()
155161
}
162+
return nil
156163
}
157164
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
//
2+
// TextViewController+IndentTests.swift
3+
// CodeEditSourceEditor
4+
//
5+
// Created by Ludwig, Tom on 08.10.24.
6+
//
7+
8+
import XCTest
9+
10+
final class TextViewController_IndentTests: XCTestCase {
11+
12+
override func setUpWithError() throws {
13+
// Put setup code here. This method is called before the invocation of each test method in the class.
14+
}
15+
16+
override func tearDownWithError() throws {
17+
// Put teardown code here. This method is called after the invocation of each test method in the class.
18+
}
19+
20+
func testExample() throws {
21+
// This is an example of a functional test case.
22+
// Use XCTAssert and related functions to verify your tests produce the correct results.
23+
// Any test you write for XCTest can be annotated as throws and async.
24+
// Mark your test throws to produce an unexpected failure when your test encounters an uncaught error.
25+
// Mark your test async to allow awaiting for asynchronous code to complete. Check the results with assertions afterwards.
26+
}
27+
28+
func testPerformanceExample() throws {
29+
// This is an example of a performance test case.
30+
self.measure {
31+
// Put the code you want to measure the time of here.
32+
}
33+
}
34+
35+
}

0 commit comments

Comments
 (0)