aboutsummaryrefslogtreecommitdiff
path: root/Sources/NorgEditor/NorgAutoIndent.swift
diff options
context:
space:
mode:
authorRuben Beltran del Rio <jj@r.bdr.sh>2026-06-19 19:16:25 +0200
committerRuben Beltran del Rio <jj@r.bdr.sh>2026-06-19 22:32:15 +0200
commit25fc48fb17b53fe1c155c4f53f673ed91fdd8f74 (patch)
treede96add2a7ae8c5cc79a354fbffa26e80349cc15 /Sources/NorgEditor/NorgAutoIndent.swift
Initial extraction from Norganize
Diffstat (limited to 'Sources/NorgEditor/NorgAutoIndent.swift')
-rw-r--r--Sources/NorgEditor/NorgAutoIndent.swift37
1 files changed, 37 insertions, 0 deletions
diff --git a/Sources/NorgEditor/NorgAutoIndent.swift b/Sources/NorgEditor/NorgAutoIndent.swift
new file mode 100644
index 0000000..2e6fa4b
--- /dev/null
+++ b/Sources/NorgEditor/NorgAutoIndent.swift
@@ -0,0 +1,37 @@
+import Foundation
+import NorgKit
+
+/// Computes the leading whitespace to insert when the operator presses return.
+public enum NorgAutoIndent {
+
+ /// The whitespace to insert after a newline.
+ public static func indentation(for text: String, newlineAt location: Int) -> String {
+ let nsText = text as NSString
+ guard location >= 0, location <= nsText.length else { return "" }
+
+ let lineRange = nsText.lineRange(for: NSRange(location: location, length: 0))
+ let prefix = nsText.substring(to: NSMaxRange(lineRange))
+ return indentation(forPrefix: prefix)
+ }
+
+ static func indentation(forPrefix prefix: String) -> String {
+ var openHeadingLevels: [Int] = []
+ for token in NorgLexer.tokenize(prefix) {
+ switch token.kind {
+ case .heading(let level):
+ while let deepest = openHeadingLevels.last, deepest >= level {
+ openHeadingLevels.removeLast()
+ }
+ openHeadingLevels.append(level)
+ case .strongDelimiter:
+ openHeadingLevels.removeAll()
+ case .weakDelimiter:
+ if !openHeadingLevels.isEmpty { openHeadingLevels.removeLast() }
+ default:
+ break
+ }
+ }
+ guard let level = openHeadingLevels.last else { return "" }
+ return String(repeating: " ", count: level + 1)
+ }
+}