Skip to content

Commit 0458bd1

Browse files
authored
Add ability to set cursor position (#83)
* Add ability to set cursor position. * Fix lint issues * Add default value to initializer
1 parent 1aa200a commit 0458bd1

File tree

2 files changed

+49
-4
lines changed

2 files changed

+49
-4
lines changed

Sources/CodeEditTextView/CodeEditTextView.swift

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,14 +25,16 @@ public struct CodeEditTextView: NSViewControllerRepresentable {
2525
theme: Binding<EditorTheme>,
2626
font: Binding<NSFont>,
2727
tabWidth: Binding<Int>,
28-
lineHeight: Binding<Double>
28+
lineHeight: Binding<Double>,
29+
cursorPosition: Published<(Int, Int)>.Publisher? = nil
2930
) {
3031
self._text = text
3132
self.language = language
3233
self._theme = theme
3334
self._font = font
3435
self._tabWidth = tabWidth
3536
self._lineHeight = lineHeight
37+
self.cursorPosition = cursorPosition
3638
}
3739

3840
@Binding private var text: String
@@ -41,6 +43,7 @@ public struct CodeEditTextView: NSViewControllerRepresentable {
4143
@Binding private var font: NSFont
4244
@Binding private var tabWidth: Int
4345
@Binding private var lineHeight: Double
46+
private var cursorPosition: Published<(Int, Int)>.Publisher?
4447

4548
public typealias NSViewControllerType = STTextViewController
4649

@@ -50,7 +53,8 @@ public struct CodeEditTextView: NSViewControllerRepresentable {
5053
language: language,
5154
font: font,
5255
theme: theme,
53-
tabWidth: tabWidth
56+
tabWidth: tabWidth,
57+
cursorPosition: cursorPosition
5458
)
5559
controller.lineHeightMultiple = lineHeight
5660
return controller

Sources/CodeEditTextView/STTextViewController.swift

Lines changed: 43 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
import AppKit
99
import SwiftUI
10+
import Combine
1011
import STTextView
1112
import SwiftTreeSitter
1213

@@ -47,13 +48,20 @@ public class STTextViewController: NSViewController, STTextViewDelegate, ThemeAt
4748

4849
// MARK: Init
4950

50-
public init(text: Binding<String>, language: CodeLanguage, font: NSFont, theme: EditorTheme, tabWidth: Int) {
51+
public init(
52+
text: Binding<String>,
53+
language: CodeLanguage,
54+
font: NSFont,
55+
theme: EditorTheme,
56+
tabWidth: Int,
57+
cursorPosition: Published<(Int, Int)>.Publisher? = nil
58+
) {
5159
self.text = text
5260
self.language = language
5361
self.font = font
5462
self.theme = theme
5563
self.tabWidth = tabWidth
56-
64+
self.cursorPosition = cursorPosition
5765
super.init(nibName: nil, bundle: nil)
5866
}
5967

@@ -124,6 +132,10 @@ public class STTextViewController: NSViewController, STTextViewDelegate, ThemeAt
124132
}
125133

126134
setUpHighlighting()
135+
136+
self.cursorPositionCancellable = self.cursorPosition?.sink(receiveValue: { value in
137+
self.setCursorPosition(value)
138+
})
127139
}
128140

129141
internal func setUpHighlighting() {
@@ -223,6 +235,35 @@ public class STTextViewController: NSViewController, STTextViewDelegate, ThemeAt
223235
keyIsDown = false
224236
}
225237

238+
// MARK: Cursor Position
239+
240+
private var cursorPosition: Published<(Int, Int)>.Publisher?
241+
private var cursorPositionCancellable: AnyCancellable?
242+
243+
private func setCursorPosition(_ position: (Int, Int)) {
244+
guard let provider = textView.textLayoutManager.textContentManager else {
245+
return
246+
}
247+
248+
var (line, column) = position
249+
let string = textView.string
250+
if line > 0 {
251+
string.enumerateSubstrings(in: string.startIndex..<string.endIndex) { _, lineRange, _, done in
252+
line -= 1
253+
if line < 1 {
254+
// If `column` exceeds the line length, set cursor to the end of the line.
255+
let index = min(lineRange.upperBound, string.index(lineRange.lowerBound, offsetBy: column - 1))
256+
if let newRange = NSTextRange(NSRange(index..<index, in: string), provider: provider) {
257+
self.textView.setSelectedRange(newRange)
258+
}
259+
done = true
260+
} else {
261+
done = false
262+
}
263+
}
264+
}
265+
}
266+
226267
deinit {
227268
textView = nil
228269
highlighter = nil

0 commit comments

Comments
 (0)