current commit
260727.3.1.1 · https://gitlab.com/saalen/highlight/-/work_items/262 added KDL language definition
Description="KDL"

Categories = {"config"}

-- KDL 2.0.0, plus the KDL 1 spellings of the keywords and of raw strings, as
-- most configuration files in the wild are still written against KDL 1

Identifiers=[[ [a-zA-Z_][\w\-\.]*|[\-\.]+[a-zA-Z_][\w\-\.]* ]]

Digits=[[ [\-\+]?(?:0x[0-9a-fA-F][0-9a-fA-F_]*|0o[0-7][0-7_]*|0b[01][01_]*|\d[\d_]*(?:\.[\d_]+)?(?:[eE][\-\+]?\d[\d_]*)?) ]]

Keywords={
  -- the property key must precede the node name: on a line continued with "\"
  -- both match, and only this one is right
  { Id=2,
    Regex=[[([\w\-\.\x80-\xFF][^\s\(\)\{\}\[\];=\\\/"]*)\s*=]],
  },
  { Id=1,
    Regex=[[^\s*([\w\-\.\x80-\xFF][^\s\(\)\{\}\[\];=\\\/"]*)]],
  },
  { Id=3,
    Regex=[[#(?:true|false|null|inf|-inf|nan)]],
  },
  { Id=3,
    List={"true", "false", "null"}
  },
  { Id=4,
    Regex=[[\(\s*([^\s\(\)]+)\s*\)]],
  },
  -- Raw string delimiters, handed to the string state by OnStateChange, which
  -- pairs their hashes by length. #"""# holds a quote, it is not a multi line
  -- opener; and since "#ff0000" opens a plain string, only close a raw one
  -- where a value ends and cannot begin.
  { Id=5,
    Regex=[[#+"""(?!#)|#+"]]
  },
  { Id=6,
    Regex=[["""#+]]
  },
  { Id=6,
    Regex=[[[^\s=]("#+)(?=[\s;\)\}=]|$)]],
  },
}

Strings={
  Delimiter=[["""|"]],
  AssertEqualLength=true,
  RawPrefix="r",
  -- \" is an escape everywhere except as the tail of a raw string terminator
  Escape=[[ \\u\{[0-9a-fA-F]{1,6}\}|\\[nrtsbf\\\/]|\\"(?!#+(?:[\s;\)\}=]|$)) ]],
}

IgnoreCase=false

Comments={
  -- "/*" and a slashdashed node with a child block share one nesting counter,
  -- so a "}" ends a block comment opened inside a commented out node. The bare
  -- "{" alternative is what feeds the counter the inner blocks.
  { Block=true,
    Nested=true,
    Delimiter= { [[\/\*|\/\-[^\{\}]*\{|\{]], [[\*\/|\}]] }
  },
  -- slashdash without a child block: the node ends with the line
  { Block=false,
    Delimiter= { [[\/\-]] }
  },
  { Block=false,
    Delimiter= { [[\/\/]] }
  },
}

Operators=[[\(|\)|\{|\}|\;|\=|\\]]

function OnStateChange(oldState, newState, token, groupID)

  -- braces delimit a comment only while a slashdashed node is being skipped
  if (token=="{" or token=="}") and oldState~=HL_BLOCK_COMMENT then
    return HL_OPERATOR
  end

  if groupID==5 then
    -- inside a string the hashes are content, and the quote closes it
    if oldState==HL_STRING then
      return HL_REJECT
    end
    OverrideParam("state.string.raw", "true")
    return HL_STRING
  end
  if groupID==6 and oldState==HL_STRING then
    return HL_STRING_END
  end

  return newState
end