Resolve string concatenation expressions in field values (#396)#565
Resolve string concatenation expressions in field values (#396)#565gaoflow wants to merge 1 commit into
Conversation
ResolveStringReferencesMiddleware only resolved a field whose entire value was a single string reference. A concatenation expression such as `10 # "~" # jan` was looked up as one key, failed, and was left raw (issue sciunto-org#396); an all-quoted expression like `"a" # "b"` was skipped by the enclosed-value guard and later mangled by RemoveEnclosingMiddleware. Detect top-level `#` concatenation (respecting quotes and braces), resolve each token (number, quoted/braced literal, or string reference) and join the results. The resolved value is kept enclosed in braces so the downstream enclosing middlewares treat it as a plain string and it round-trips to valid BibTeX. If any reference is unknown, the original expression is left untouched.
|
I independently explored a broader version of this fix while auditing the parser's round-trip behavior. I have published the result as a comparison branch rather than opening a competing PR: In addition to resolving ordinary entry-field concatenations, the branch tests and handles:
The branch has two commits so the expression resolver and the enclosing-middleware safeguard can be reviewed independently. Validation is clean: For transparency, this comparison implementation and its tests were prepared with ChatGPT Codex using GPT-5.6 Sol with high reasoning effort. They should still receive normal maintainer review, especially because the work deliberately covers more cases than the original report. |
Summary
Fixes #396 — string concatenation expressions in entry field values are now interpolated.
This is the second of the two PRs @MiWeiss outlined in the issue. The first (splitter capturing the full concatenation expression) is already merged; this one adapts
ResolveStringReferencesMiddlewareto actually resolve it.The bug
ResolveStringReferencesMiddlewareonly handled a field whose entire value was a single string reference. For a concatenation it failed in two ways:A purely-quoted expression was even worse — it was skipped by the enclosed-value guard and then mangled by
RemoveEnclosingMiddleware:The fix
In
ResolveStringReferencesMiddleware.transform, before the existing single-reference logic, detect a top-level#concatenation (the#splitting respects"..."and{...}so e.g.{C# program}is not treated as a concatenation). Each token is resolved independently:then the parts are joined. The result is kept enclosed in braces so the downstream enclosing middlewares treat it as a plain string — this matters for writing:
month = {10~Jan.}is valid BibTeX that round-trips, whereas a baremonth = 10~Jan.would be re-parsed as a (broken) reference.If any reference in the expression is unknown, the original expression is left untouched (no partial/incorrect resolution).
Scope
This handles concatenation in entry fields (the issue body). It does not yet resolve concatenation inside
@stringdefinitions (theasiacrypt91name = asiacryptname # "'91"case @kmccurley raised) — that needs string-to-string resolution and is worth a separate change. Happy to follow up on it.Tests
Added to
tests/middleware_tests/test_interpolate.py:test_string_interpolation_resolves_concatenation— number/quote/brace/reference mix at the middleware leveltest_string_interpolation_leaves_unresolvable_concatenation_untouched— unknown reference is a no-optest_parse_string_resolves_concatenation_end_to_end— exact issue Unexpected concatenation of field tokens #396 repro, plus a write + re-parse round-trip assertionFull suite: 2579 passed, 12 skipped (3 new, no regressions). black / isort / flake8 / pyupgrade / docstr-coverage all clean (pinned versions).
This pull request was prepared with the assistance of AI, under my direction and review.