@@ -9,26 +9,36 @@ import CodeEditTextView
99import AppKit
1010
1111extension TextViewController {
12+ /// Handels indentation and unindentation
13+ ///
14+ /// Handles the indentation of lines in the text view based on the current indentation option.
15+ ///
16+ /// This function assumes that the document is formatted according to the current selected indentation option.
17+ /// It will not indent a tab character if spaces are selected, and vice versa. Ensure that the document is
18+ /// properly formatted before invoking this function.
19+ ///
20+ /// - Parameter inwards: A Boolean flag indicating whether to outdent (default is `false`).
1221 public func handleIndent( inwards: Bool = false ) {
13- // TODO: Get indentation chars and count form settings
14- let spaceCount = 2
15- let indentationChars = String ( repeating: " " , count: spaceCount)
16-
22+ let indentationChars : String = indentOption. stringValue
1723 guard !cursorPositions. isEmpty else { return }
1824
1925 textView. undoManager? . beginUndoGrouping ( )
2026 for cursorPosition in self . cursorPositions {
2127 // get lineindex, i.e line-numbers+1
22- guard let lineIndexes = getHeighlightedLines ( for: cursorPosition. range) else { continue }
28+ guard let lineIndexes = getHighlightedLines ( for: cursorPosition. range) else { continue }
2329
24- for lineIndex in lineIndexes {
25- adjustIndentation ( lineIndex: lineIndex, indentationChars: indentationChars, inwards: inwards)
30+ for lineIndex in lineIndexes {
31+ adjustIndentation (
32+ lineIndex: lineIndex,
33+ indentationChars: indentationChars,
34+ inwards: inwards
35+ )
2636 }
2737 }
2838 textView. undoManager? . endUndoGrouping ( )
2939 }
3040
31- private func getHeighlightedLines ( for range: NSRange ) -> [ Int ] ? {
41+ private func getHighlightedLines ( for range: NSRange ) -> [ Int ] ? {
3242 guard let startLineInfo = textView. layoutManager. textLineForOffset ( range. lowerBound) else {
3343 return nil
3444 }
@@ -45,11 +55,16 @@ extension TextViewController {
4555
4656 return Array ( startLineInfo. index... endLineInfo. index)
4757 }
58+
4859 private func adjustIndentation( lineIndex: Int , indentationChars: String , inwards: Bool ) {
4960 guard let lineInfo = textView. layoutManager. textLineForIndex ( lineIndex) else { return }
5061
5162 if inwards {
52- removeLeadingSpaces ( lineInfo: lineInfo, spaceCount: indentationChars. count)
63+ if indentOption != . tab {
64+ removeLeadingSpaces ( lineInfo: lineInfo, spaceCount: indentationChars. count)
65+ } else {
66+ removeLeadingTab ( lineInfo: lineInfo)
67+ }
5368 } else {
5469 addIndentation ( lineInfo: lineInfo, indentationChars: indentationChars)
5570 }
@@ -81,7 +96,20 @@ extension TextViewController {
8196 )
8297 }
8398
84- func countLeadingSpacesUpTo( line: String , maxCount: Int ) -> Int {
99+ private func removeLeadingTab( lineInfo: TextLineStorage < TextLine > . TextLinePosition ) {
100+ guard let lineContent = textView. textStorage. substring ( from: lineInfo. range) else {
101+ return
102+ }
103+
104+ if lineContent. first == " \t " {
105+ textView. replaceCharacters (
106+ in: NSRange ( location: lineInfo. range. lowerBound, length: 1 ) ,
107+ with: " "
108+ )
109+ }
110+ }
111+
112+ private func countLeadingSpacesUpTo( line: String , maxCount: Int ) -> Int {
85113 // Count leading spaces using prefix and `filter`
86114 return line. prefix ( maxCount) . filter { $0 == " " } . count
87115 }
0 commit comments