]> quire.kejadlen.dev Git - quire.git/commitdiff
Fix line extraction for names containing colons
authorAlpha Chen <alpha@kejadlen.dev>
Sun, 26 Apr 2026 00:40:20 +0000 (00:40 +0000)
committerAlpha Chen <alpha@kejadlen.dev>
Sun, 26 Apr 2026 00:43:57 +0000 (00:43 +0000)
extract_line_offset split on : from the left, so names like
HEAD:.quire/config.fnl broke the parser. Use regex-lite to match
the first :LINE:COLUMN: run instead, which is unambiguous.

Assisted-by: GLM-5.1 via pi
Cargo.lock
Cargo.toml
src/fennel.rs

index eba8b25344025de5e467ef9cac662f56c20b8413..57016a51fbce630b4a4cadb5251fa0c459139fe1 100644 (file)
@@ -882,6 +882,7 @@ dependencies = [
  "miette",
  "mlua",
  "predicates",
+ "regex",
  "serde",
  "shell-words",
  "tempfile",
index 0e0a608b15b2e573846e3a9eced2ea004ebed474..114eebebc8ff5d0595c81ce711a99a4a3ce7a021 100644 (file)
@@ -10,6 +10,7 @@ path = "src/bin/quire/main.rs"
 [dependencies]
 axum = "*"
 mlua = { version = "*", features = ["lua54", "serde", "vendored"] }
+regex = "*"
 serde = { version = "*", features = ["derive"] }
 clap = { version = "*", features = ["derive", "env"] }
 clap_complete = "*"
index d99539de9bb684eae47b7e5874078be7151e910d..a14d346d9a91b6855401469b14151ea880a223cf 100644 (file)
@@ -168,15 +168,19 @@ fn eval_error(source: &str, name: &str, err: &mlua::Error) -> FennelError {
 
 /// Try to extract a line number from a Lua error message.
 ///
-/// Lua errors look like `filename:LINE: message`.
+/// Lua/Fennel errors embed the source location as `name:LINE:COLUMN: message`.
+/// The name may contain colons (e.g. `HEAD:.quire/config.fnl`), so splitting
+/// from the left breaks. Match the first `:LINE:COLUMN: ` run, which is
+/// unambiguous — filenames don't end with `:digits:digits:`.
 fn extract_line_offset(err: &mlua::Error) -> Option<usize> {
     let msg = err.to_string();
-    let mut parts = msg.split(':');
-    // Skip the filename part.
-    parts.next()?;
-    // Next should be the line number.
-    let line_str = parts.next()?.trim();
-    line_str.parse::<usize>().ok().filter(|&n| n > 0)
+    let re = regex::Regex::new(r":(\d+):\d+: ").ok()?;
+    let caps = re.captures(&msg)?;
+    caps.get(1)?
+        .as_str()
+        .parse::<usize>()
+        .ok()
+        .filter(|&n| n > 0)
 }
 
 /// Convert a 1-based line number to a byte offset in the source.
@@ -337,4 +341,19 @@ mod tests {
         assert!(result.is_err());
         assert!(matches!(result.unwrap_err(), FennelError::FileNotFound(..)));
     }
+
+    #[test]
+    fn error_label_works_with_colon_in_name() {
+        let f = fennel();
+        let source = "\n{:bad {:}";
+        let result: Result<MirrorConfig, _> = f.load_string(source, "HEAD:.quire/config.fnl");
+        let err = result.unwrap_err();
+        if let FennelError::Eval { label, .. } = &err {
+            assert_eq!(
+                label.offset(),
+                1,
+                "label should point at line 2 despite colons in name"
+            );
+        }
+    }
 }