@@ -2,6 +2,7 @@ import AppKit
22import Common
33import HotKey
44import TOMLKit
5+ import Foundation
56
67func readConfig( forceConfigUrl: URL ? = nil ) -> Result < ( Config , URL ) , String > {
78 let customConfigUrl : URL
@@ -30,7 +31,7 @@ func readConfig(forceConfigUrl: URL? = nil) -> Result<(Config, URL), String> {
3031 }
3132}
3233
33- enum TomlParseError : Error , CustomStringConvertible , Equatable {
34+ enum TomlParseError : Error , CustomStringConvertible , Equatable , LocalizedError {
3435 case semantic( _ backtrace: TomlBacktrace , _ message: String )
3536 case syntax( _ message: String )
3637
@@ -41,6 +42,9 @@ enum TomlParseError: Error, CustomStringConvertible, Equatable {
4142 case . syntax( let message) : message
4243 }
4344 }
45+ var errorDescription : String ? {
46+ return description
47+ }
4448}
4549
4650typealias ParsedToml < T> = Result < T , TomlParseError >
@@ -153,9 +157,26 @@ func parseCommandOrCommands(_ raw: TOMLValueConvertible) -> Parsed<[any Command]
153157 }
154158}
155159
160+ // Note: this is only required due to a TOML parsing bug in TOMLKit which throws SIGABORT in parsing failures
161+ // Should be removed once TOMLKit is patched
162+ private func validateTOMLTableHeaderSyntax( in input: String ) throws {
163+ // Matches [[ followed by at least one more [ While ignoring commented lines #
164+ let pattern = #"^(?!\s*#)\s*\[\[(?=\[)"#
165+ let regex = try NSRegularExpression ( pattern: pattern, options: . anchorsMatchLines)
166+ let lines = input. components ( separatedBy: . newlines)
167+
168+ for (index, line) in lines. enumerated ( ) {
169+ let range = NSRange ( location: 0 , length: line. utf16. count)
170+ if regex. firstMatch ( in: line, options: [ ] , range: range) != nil {
171+ throw TomlParseError . syntax ( " TOML Parsing Error: Invalid Table Header \n → expected a header string but found '[' \n → Location: Line \( index + 1 ) \n → Content: \( line) " )
172+ }
173+ }
174+ }
175+
156176func parseConfig( _ rawToml: String ) -> ( config: Config , errors: [ TomlParseError ] ) { // todo change return value to Result
157177 let rawTable : TOMLTable
158178 do {
179+ try validateTOMLTableHeaderSyntax ( in: rawToml)
159180 rawTable = try TOMLTable ( string: rawToml)
160181 } catch let e as TOMLParseError {
161182 return ( defaultConfig, [ . syntax( e. debugDescription) ] )
0 commit comments