jgm/skylighting

ini file highlighting doesn't preserve highlight for strings

jjallaire opened this issue · 9 comments

With pandoc 2.14.0.2 if you render the following markdown:

```ini
[Section]
Field = "something-v4.2.4.yaml"
```

You get this highlighting treatment:

image (6)

Note the "2.4" highlighted as a float rather than preserving the string highlighting color.

jgm commented

I'll move this to skylighting (which does the highlighting).
We can see what's going on this way:

 % skylighting --syntax ini --trace
[Section]
Field = "something-v4.2.4.yaml"
Trying rule Rule {rMatcher = RangeDetect '[' ']', rAttribute = KeywordTok, rIncludeAttribute = False, rDynamic = False, rCaseSensitive = True, rChildren = [], rLookahead = False, rFirstNonspace = False, rColumn = Nothing, rContextSwitch = []}
RangeDetect MATCHED Just (KeywordTok,"[Section]")
Trying rule Rule {rMatcher = RangeDetect '[' ']', rAttribute = KeywordTok, rIncludeAttribute = False, rDynamic = False, rCaseSensitive = True, rChildren = [], rLookahead = False, rFirstNonspace = False, rColumn = Nothing, rContextSwitch = []}
Trying rule Rule {rMatcher = DetectChar '=', rAttribute = OtherTok, rIncludeAttribute = False, rDynamic = False, rCaseSensitive = True, rChildren = [], rLookahead = False, rFirstNonspace = False, rColumn = Nothing, rContextSwitch = [Push ("INI Files","Value")]}
Trying rule Rule {rMatcher = AnyChar (fromList "#;"), rAttribute = CommentTok, rIncludeAttribute = False, rDynamic = False, rCaseSensitive = True, rChildren = [], rLookahead = False, rFirstNonspace = True, rColumn = Nothing, rContextSwitch = [Push ("INI Files","Comment")]}
FALLTHROUGH Just (DataTypeTok,"Field")
Trying rule Rule {rMatcher = RangeDetect '[' ']', rAttribute = KeywordTok, rIncludeAttribute = False, rDynamic = False, rCaseSensitive = True, rChildren = [], rLookahead = False, rFirstNonspace = False, rColumn = Nothing, rContextSwitch = []}
Trying rule Rule {rMatcher = DetectChar '=', rAttribute = OtherTok, rIncludeAttribute = False, rDynamic = False, rCaseSensitive = True, rChildren = [], rLookahead = False, rFirstNonspace = False, rColumn = Nothing, rContextSwitch = [Push ("INI Files","Value")]}
Trying rule Rule {rMatcher = AnyChar (fromList "#;"), rAttribute = CommentTok, rIncludeAttribute = False, rDynamic = False, rCaseSensitive = True, rChildren = [], rLookahead = False, rFirstNonspace = True, rColumn = Nothing, rContextSwitch = [Push ("INI Files","Comment")]}
FALLTHROUGH Just (DataTypeTok," ")
Trying rule Rule {rMatcher = RangeDetect '[' ']', rAttribute = KeywordTok, rIncludeAttribute = False, rDynamic = False, rCaseSensitive = True, rChildren = [], rLookahead = False, rFirstNonspace = False, rColumn = Nothing, rContextSwitch = []}
Trying rule Rule {rMatcher = DetectChar '=', rAttribute = OtherTok, rIncludeAttribute = False, rDynamic = False, rCaseSensitive = True, rChildren = [], rLookahead = False, rFirstNonspace = False, rColumn = Nothing, rContextSwitch = [Push ("INI Files","Value")]}
DetectChar MATCHED Just (OtherTok,"=")
CONTEXT STACK ["Value","ini"]
Trying rule Rule {rMatcher = Float, rAttribute = FloatTok, rIncludeAttribute = False, rDynamic = False, rCaseSensitive = True, rChildren = [], rLookahead = False, rFirstNonspace = False, rColumn = Nothing, rContextSwitch = []}
Trying rule Rule {rMatcher = Int, rAttribute = DecValTok, rIncludeAttribute = False, rDynamic = False, rCaseSensitive = True, rChildren = [], rLookahead = False, rFirstNonspace = False, rColumn = Nothing, rContextSwitch = []}
Trying rule Rule {rMatcher = Keyword (KeywordAttr {keywordCaseSensitive = False, keywordDelims = fromList "\t\n !%&()*+,-./:;<=>?[\\]^{|}~"}) (CaseInsensitiveWords (fromList ["default","defaults","e_all","e_compile_error","e_compile_warning","e_core_error","e_core_warning","e_error","e_notice","e_parse","e_strict","e_user_error","e_user_notice","e_user_warning","e_warning","false","localhost","no","normal","null","off","on","true","yes"])), rAttribute = KeywordTok, rIncludeAttribute = False, rDynamic = False, rCaseSensitive = True, rChildren = [], rLookahead = False, rFirstNonspace = False, rColumn = Nothing, rContextSwitch = []}
FALLTHROUGH Just (StringTok," ")
Trying rule Rule {rMatcher = Float, rAttribute = FloatTok, rIncludeAttribute = False, rDynamic = False, rCaseSensitive = True, rChildren = [], rLookahead = False, rFirstNonspace = False, rColumn = Nothing, rContextSwitch = []}
Trying rule Rule {rMatcher = Int, rAttribute = DecValTok, rIncludeAttribute = False, rDynamic = False, rCaseSensitive = True, rChildren = [], rLookahead = False, rFirstNonspace = False, rColumn = Nothing, rContextSwitch = []}
Trying rule Rule {rMatcher = Keyword (KeywordAttr {keywordCaseSensitive = False, keywordDelims = fromList "\t\n !%&()*+,-./:;<=>?[\\]^{|}~"}) (CaseInsensitiveWords (fromList ["default","defaults","e_all","e_compile_error","e_compile_warning","e_core_error","e_core_warning","e_error","e_notice","e_parse","e_strict","e_user_error","e_user_notice","e_user_warning","e_warning","false","localhost","no","normal","null","off","on","true","yes"])), rAttribute = KeywordTok, rIncludeAttribute = False, rDynamic = False, rCaseSensitive = True, rChildren = [], rLookahead = False, rFirstNonspace = False, rColumn = Nothing, rContextSwitch = []}
FALLTHROUGH Just (StringTok,"\"")
Trying rule Rule {rMatcher = Float, rAttribute = FloatTok, rIncludeAttribute = False, rDynamic = False, rCaseSensitive = True, rChildren = [], rLookahead = False, rFirstNonspace = False, rColumn = Nothing, rContextSwitch = []}
Trying rule Rule {rMatcher = Int, rAttribute = DecValTok, rIncludeAttribute = False, rDynamic = False, rCaseSensitive = True, rChildren = [], rLookahead = False, rFirstNonspace = False, rColumn = Nothing, rContextSwitch = []}
Trying rule Rule {rMatcher = Keyword (KeywordAttr {keywordCaseSensitive = False, keywordDelims = fromList "\t\n !%&()*+,-./:;<=>?[\\]^{|}~"}) (CaseInsensitiveWords (fromList ["default","defaults","e_all","e_compile_error","e_compile_warning","e_core_error","e_core_warning","e_error","e_notice","e_parse","e_strict","e_user_error","e_user_notice","e_user_warning","e_warning","false","localhost","no","normal","null","off","on","true","yes"])), rAttribute = KeywordTok, rIncludeAttribute = False, rDynamic = False, rCaseSensitive = True, rChildren = [], rLookahead = False, rFirstNonspace = False, rColumn = Nothing, rContextSwitch = []}
FALLTHROUGH Just (StringTok,"something")
Trying rule Rule {rMatcher = Float, rAttribute = FloatTok, rIncludeAttribute = False, rDynamic = False, rCaseSensitive = True, rChildren = [], rLookahead = False, rFirstNonspace = False, rColumn = Nothing, rContextSwitch = []}
Trying rule Rule {rMatcher = Int, rAttribute = DecValTok, rIncludeAttribute = False, rDynamic = False, rCaseSensitive = True, rChildren = [], rLookahead = False, rFirstNonspace = False, rColumn = Nothing, rContextSwitch = []}
Trying rule Rule {rMatcher = Keyword (KeywordAttr {keywordCaseSensitive = False, keywordDelims = fromList "\t\n !%&()*+,-./:;<=>?[\\]^{|}~"}) (CaseInsensitiveWords (fromList ["default","defaults","e_all","e_compile_error","e_compile_warning","e_core_error","e_core_warning","e_error","e_notice","e_parse","e_strict","e_user_error","e_user_notice","e_user_warning","e_warning","false","localhost","no","normal","null","off","on","true","yes"])), rAttribute = KeywordTok, rIncludeAttribute = False, rDynamic = False, rCaseSensitive = True, rChildren = [], rLookahead = False, rFirstNonspace = False, rColumn = Nothing, rContextSwitch = []}
FALLTHROUGH Just (StringTok,"-")
Trying rule Rule {rMatcher = Float, rAttribute = FloatTok, rIncludeAttribute = False, rDynamic = False, rCaseSensitive = True, rChildren = [], rLookahead = False, rFirstNonspace = False, rColumn = Nothing, rContextSwitch = []}
Trying rule Rule {rMatcher = Int, rAttribute = DecValTok, rIncludeAttribute = False, rDynamic = False, rCaseSensitive = True, rChildren = [], rLookahead = False, rFirstNonspace = False, rColumn = Nothing, rContextSwitch = []}
Trying rule Rule {rMatcher = Keyword (KeywordAttr {keywordCaseSensitive = False, keywordDelims = fromList "\t\n !%&()*+,-./:;<=>?[\\]^{|}~"}) (CaseInsensitiveWords (fromList ["default","defaults","e_all","e_compile_error","e_compile_warning","e_core_error","e_core_warning","e_error","e_notice","e_parse","e_strict","e_user_error","e_user_notice","e_user_warning","e_warning","false","localhost","no","normal","null","off","on","true","yes"])), rAttribute = KeywordTok, rIncludeAttribute = False, rDynamic = False, rCaseSensitive = True, rChildren = [], rLookahead = False, rFirstNonspace = False, rColumn = Nothing, rContextSwitch = []}
FALLTHROUGH Just (StringTok,"v4")
Trying rule Rule {rMatcher = Float, rAttribute = FloatTok, rIncludeAttribute = False, rDynamic = False, rCaseSensitive = True, rChildren = [], rLookahead = False, rFirstNonspace = False, rColumn = Nothing, rContextSwitch = []}
Trying rule Rule {rMatcher = Int, rAttribute = DecValTok, rIncludeAttribute = False, rDynamic = False, rCaseSensitive = True, rChildren = [], rLookahead = False, rFirstNonspace = False, rColumn = Nothing, rContextSwitch = []}
Trying rule Rule {rMatcher = Keyword (KeywordAttr {keywordCaseSensitive = False, keywordDelims = fromList "\t\n !%&()*+,-./:;<=>?[\\]^{|}~"}) (CaseInsensitiveWords (fromList ["default","defaults","e_all","e_compile_error","e_compile_warning","e_core_error","e_core_warning","e_error","e_notice","e_parse","e_strict","e_user_error","e_user_notice","e_user_warning","e_warning","false","localhost","no","normal","null","off","on","true","yes"])), rAttribute = KeywordTok, rIncludeAttribute = False, rDynamic = False, rCaseSensitive = True, rChildren = [], rLookahead = False, rFirstNonspace = False, rColumn = Nothing, rContextSwitch = []}
FALLTHROUGH Just (StringTok,".")
Trying rule Rule {rMatcher = Float, rAttribute = FloatTok, rIncludeAttribute = False, rDynamic = False, rCaseSensitive = True, rChildren = [], rLookahead = False, rFirstNonspace = False, rColumn = Nothing, rContextSwitch = []}
Trying rule Rule {rMatcher = Int, rAttribute = DecValTok, rIncludeAttribute = False, rDynamic = False, rCaseSensitive = True, rChildren = [], rLookahead = False, rFirstNonspace = False, rColumn = Nothing, rContextSwitch = []}
Int MATCHED Just (DecValTok,"2")
Trying rule Rule {rMatcher = Float, rAttribute = FloatTok, rIncludeAttribute = False, rDynamic = False, rCaseSensitive = True, rChildren = [], rLookahead = False, rFirstNonspace = False, rColumn = Nothing, rContextSwitch = []}
Trying rule Rule {rMatcher = Int, rAttribute = DecValTok, rIncludeAttribute = False, rDynamic = False, rCaseSensitive = True, rChildren = [], rLookahead = False, rFirstNonspace = False, rColumn = Nothing, rContextSwitch = []}
Trying rule Rule {rMatcher = Keyword (KeywordAttr {keywordCaseSensitive = False, keywordDelims = fromList "\t\n !%&()*+,-./:;<=>?[\\]^{|}~"}) (CaseInsensitiveWords (fromList ["default","defaults","e_all","e_compile_error","e_compile_warning","e_core_error","e_core_warning","e_error","e_notice","e_parse","e_strict","e_user_error","e_user_notice","e_user_warning","e_warning","false","localhost","no","normal","null","off","on","true","yes"])), rAttribute = KeywordTok, rIncludeAttribute = False, rDynamic = False, rCaseSensitive = True, rChildren = [], rLookahead = False, rFirstNonspace = False, rColumn = Nothing, rContextSwitch = []}
FALLTHROUGH Just (StringTok,".")
Trying rule Rule {rMatcher = Float, rAttribute = FloatTok, rIncludeAttribute = False, rDynamic = False, rCaseSensitive = True, rChildren = [], rLookahead = False, rFirstNonspace = False, rColumn = Nothing, rContextSwitch = []}
Float MATCHED Just (FloatTok,"4.")
Trying rule Rule {rMatcher = Float, rAttribute = FloatTok, rIncludeAttribute = False, rDynamic = False, rCaseSensitive = True, rChildren = [], rLookahead = False, rFirstNonspace = False, rColumn = Nothing, rContextSwitch = []}
Trying rule Rule {rMatcher = Int, rAttribute = DecValTok, rIncludeAttribute = False, rDynamic = False, rCaseSensitive = True, rChildren = [], rLookahead = False, rFirstNonspace = False, rColumn = Nothing, rContextSwitch = []}
Trying rule Rule {rMatcher = Keyword (KeywordAttr {keywordCaseSensitive = False, keywordDelims = fromList "\t\n !%&()*+,-./:;<=>?[\\]^{|}~"}) (CaseInsensitiveWords (fromList ["default","defaults","e_all","e_compile_error","e_compile_warning","e_core_error","e_core_warning","e_error","e_notice","e_parse","e_strict","e_user_error","e_user_notice","e_user_warning","e_warning","false","localhost","no","normal","null","off","on","true","yes"])), rAttribute = KeywordTok, rIncludeAttribute = False, rDynamic = False, rCaseSensitive = True, rChildren = [], rLookahead = False, rFirstNonspace = False, rColumn = Nothing, rContextSwitch = []}
FALLTHROUGH Just (StringTok,"yaml")
Trying rule Rule {rMatcher = Float, rAttribute = FloatTok, rIncludeAttribute = False, rDynamic = False, rCaseSensitive = True, rChildren = [], rLookahead = False, rFirstNonspace = False, rColumn = Nothing, rContextSwitch = []}
Trying rule Rule {rMatcher = Int, rAttribute = DecValTok, rIncludeAttribute = False, rDynamic = False, rCaseSensitive = True, rChildren = [], rLookahead = False, rFirstNonspace = False, rColumn = Nothing, rContextSwitch = []}
Trying rule Rule {rMatcher = Keyword (KeywordAttr {keywordCaseSensitive = False, keywordDelims = fromList "\t\n !%&()*+,-./:;<=>?[\\]^{|}~"}) (CaseInsensitiveWords (fromList ["default","defaults","e_all","e_compile_error","e_compile_warning","e_core_error","e_core_warning","e_error","e_notice","e_parse","e_strict","e_user_error","e_user_notice","e_user_warning","e_warning","false","localhost","no","normal","null","off","on","true","yes"])), rAttribute = KeywordTok, rIncludeAttribute = False, rDynamic = False, rCaseSensitive = True, rChildren = [], rLookahead = False, rFirstNonspace = False, rColumn = Nothing, rContextSwitch = []}
FALLTHROUGH Just (StringTok,"\"")
checkLineEnd for "Value" eol = True cLineEndContext = [Pop]
CONTEXT STACK ["ini"]
jgm commented

The problem is in the KDE ini.xml syntax definition, which seems to be very primitive.
I tried in the Kate editor and got the same bad highlighting:

Screen Shot 2021-06-15 at 10 50 07 PM

So, we are implementing this correctly but the underlying syntax definition needs improvement. (If you improve it, submit upstream to KDE as described in this project's README.)

Okay, we will take a shot at improving this and submit to KDE once we have. Thanks!

jgm commented

Great. Let's see if you get any reactions from KDE. If they're okay with it, we can merge it here too.

jgm commented

Thinking more about this, it seems to me that instead of adding special support for quoted strings, you should remove the special highlighting of numbers. Reasons:

  1. The description of ini file format here https://en.wikipedia.org/wiki/INI_file#Quoted_values says nothing at all about special treatment of numbers.
  2. With the fix you've given, we'd still get similar problems with numbers in the middle of unquoted strings, which are allowed in ini.

Okay, agreed. I re-opened the original issue w/ a new suggested patch: https://invent.kde.org/frameworks/syntax-highlighting/-/issues/10#note_262011

It looks like they've merged an improved version that only colorizes numbers for values that are entirely composed of a number: https://invent.kde.org/frameworks/syntax-highlighting/-/merge_requests/224

jgm commented

Great, I've merged this now.