260808.2.1 · 5aa172e997c0d77ac957b441a8d3796b2d445e7e
https://gitlab.com/saalen/highlight/-/work_items/209 fixed string highlighting of nested command substitutions
A recursive Strings.Interpolation hands the string engine a balanced $( ... ) token, so quotes inside a command substitution no longer break string pairing. OnStateChange rejects the span at root level and inside heredocs, leaving both tokenized exactly as before, and skips the cmdSubStack entry when the token is already balanced, since no closing paren follows to pop it again.
reading declarations
Changes to langDefs/shellscript.lang. All files
@@ -57,6 +57,10 @@ Keywords={ -- hereDoc opening delimiter, see OnStateChange to handle end of string Strings={ Delimiter=[[<<[\-]?\s*["']?\s*[A-Za-z_]+["']?|"|`|']],+ -- balanced $( ... ) span (recursive); within strings it is absorbed into the+ -- string unit so quotes inside command substitutions do not break pairing;+ -- outside strings OnStateChange rejects it so inner tokens keep their colors+ Interpolation=[[\$\((?:[^()]|(?R))*\)]], } IgnoreCase=false@@ -74,6 +78,13 @@ cmdSubStack = {} function OnStateChange(oldState, newState, token, kwClass) + -- the interpolation span is only wanted inside quoted strings; reject it at+ -- root level so the substitution's content is tokenized normally, and inside+ -- heredocs, which end at the delimiter word and need no quote pairing+ if newState == HL_INTERPOLATION and (oldState == HL_STANDARD or hereDoc ~= nil) then+ return HL_REJECT+ end+ if oldState == HL_STRING and token == hereDoc then hereDoc = nil return HL_STRING_END@@ -85,7 +96,13 @@ function OnStateChange(oldState, newState, token, kwClass) cmdSubStart = string.find(token, "%$%(") if cmdSubStart and cmdSubStack ~= nil then- table.insert(cmdSubStack, {depth = #cmdSubStack + 1, inString = true})+ -- a balanced $( ... ) arrives as a single token, so no closing ) follows+ -- to pop it again: tracking it would leave the stack filled for good+ cmdSubOpen = select(2, string.gsub(token, "%(", ""))+ cmdSubClose = select(2, string.gsub(token, "%)", ""))+ if cmdSubOpen > cmdSubClose then+ table.insert(cmdSubStack, {depth = #cmdSubStack + 1, inString = true})+ end return HL_STRING end