Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(clojure) comment macro should not be comment scope #3395

Merged
merged 2 commits into from Nov 9, 2021

Conversation

MrEbbinghaus
Copy link
Contributor

Changes

Clojure has a macro comment, which evaluates to nothing. It is not a special language feature.
The current grammar highlights every list beginning with "comment" (See screenshot)
image

I guess the intention behind that mode was at some point that some editor themes highlight the whole blocks (not just the name) like comments.

Checklist

  • Added markup tests
  • Updated the changelog at CHANGES.md

@joshgoebel
Copy link
Member

  • So how does one write actual comments? With 'comment (string)'?

@MrEbbinghaus
Copy link
Contributor Author

MrEbbinghaus commented Nov 9, 2021

@joshgoebel
I wrote up an explanation of what are comments in Clojure and what may be used as comments. At the end of this comment, you can find examples how others render Clojure.

I may submit more PRs for the Clojure syntax as there are still things that are highlighted not quite right.

For Reference:
You can find a reference of the Clojure reader here: https://clojure.org/reference/reader
And "special symbols" here: https://clojure.org/guides/weird_characters

; line comments

Clojure has line comments starting with ;, this is a special form like in any other language.
This is handled here:

const COMMENT = hljs.COMMENT(
';',
'$',
{
relevance: 0
}
);

It is common practice to use multiple ; to signal hierarchy.
; for margin inline comments
;; for line comments
;;; for top-level comments

;;; Here is a function:
(defn square 
  "This is a docstring."
  [x]
  ;; Now we will square x.
  (* x x)) ; Clojure uses prefix notation.

(comment) Marco

Then there is the (comment) macro, that just ignores the body and yields' nil. It is nothing special really. What's important though is that code inside the comment macro is still code and has to be valid Clojure code!

(comment
  (defn 2abc [])) ; this will fail! Functions must not start with a number.
  
(comment (comment (comment "Why not?")))

;; Since it is nothing special, we could redefine it. 
(defn comment [str]
  (println str))  
  
;; This is rarely used in the wild, but some libraries overwrite core functions.
(ns html)
(defn comment [body] 
  (str "<!-- " body " -->")
  
(ns my-namespace)
(html/comment "my comment")
; => <!-- my comment -->

#_ Discard

Additionally, there is a reader macro, #_ ignores the following form completely. It is used to comment out code.

#_(comment
       (defn 2abc [])) ; this won't fail, the code is skipped while reading the file.

#_"You can skip any form" ; not only list forms.
#_42

;; You have no power here! #_(some-code 1 2 3)

(merge 
  {"a" 1}
  #_{"b" 2
     "c" 3}
  {"d" 4})
;; => {"a" 1, "d" 4}

How do others render Clojure?

; I am a comment

(+ 1 2 3) ; I am a comment behind a form

(defn square [x] (* x x))
; (comment) is mostly used for code that the dev wants to be evaluated "by hand"
; in a REPL, but not automatically. It has to be valid clojure code!
(comment
  ;; sanity check my code
  (= 9 (square 3)))
  
; #_ ignores the next form. This is used to comment out code during development.
#_(print "I will be skipped while reading")

; #_ is stackable, useful for maps.
{"a" 1
 #_#_"b" 2}

This is how Cursive, the Clojure plugin for IntelliJ, renders the text:
image

Calva, the VSCode plugin for Clojure, renders the skipped (#_) not like a comment, but in a lighter colour.
image

@MrEbbinghaus
Copy link
Contributor Author

@joshgoebel BTW, is there a way to overrule scopes?

Yesterday I experimented with highlighting everything as comment, when using (comment).
The mode should end on a matching bracket, for this I would use the other modes for normal Clojure code. But these have their own scope.

(comment
  (+ 1 2 3))

Would result in:

<span class="hljs-comment">
  (comment 
    (<span class="hljs-name">+</span> <span class="hljs-number">1</span> <span class="hljs-number">2</span> <span class="hljs-number">3</span>))
</span>

The only way I saw to overcome this is having a clone of all modes without the scopes for exclusive use in the comment mode.

@joshgoebel
Copy link
Member

The only way I saw to overcome this is having a clone of all modes without the scopes for exclusive use in the comment mode.

Not exactly. If your trying to not highlight them then you ONLY need modes to match things that could interfere with bracket counting... you don't need ALL the modes... so in many languages this would mean you'd need to match strings (unscoped) to avoid things like "I'm a string ) not a block close"... but from your other highlighting example it looks like usually these just get highlighted as normal.

@joshgoebel
Copy link
Member

I wonder if something like hljs.COMMENT('comment\\b(?!-)', ''), might not be better?

Screen Shot 2021-11-09 at 8 32 43 AM

So singular comments are still highlighted... (which I personally like)... but we avoid false positives... thoughts?

@joshgoebel
Copy link
Member

joshgoebel commented Nov 9, 2021

I experimented with highlighting everything as comment, when using (comment).

I'd also be willing to try this if it was reliable and you wanted to finish it up.

One could handle #_( the same way - as Cursive does - though nested #_ might be harder.

@MrEbbinghaus
Copy link
Contributor Author

In my opinion, (comment (+ 1 2 3)) should either be highlighted all grey or not at all, and looking at the examples not at all is preferred. I think just making the symbol grey looks out of place.

I can open an issue with other things I noticed off with Clojure highlighting.


You are right regarding ).
I think ) could only appear on its own in:

  • a string ")"
  • a character \)
  • a comment ;)

Regarding #_
It doesn't have to be followed by (.
I can be followed by any valid form, with white spaces and line comments in between.

#_1
#_                            1  ; spaces between
#_ ,,,,,,,,,,  ; commas are pruely decorative and treated as whitespace
1]

@joshgoebel
Copy link
Member

and looking at the examples not at all is preferred

Ok, we can try that for now. That would put this PR back on track. :)

Regarding #_ It doesn't have to be followed by (.

Yes I realized, but those other cases may be difficult (or impossible) to deal with properly as it is not our goal to parse languages (at other than a surface level)... trying to do so very quickly leads to grammars that are difficult or impossible to maintain.

@joshgoebel joshgoebel changed the title Fix clojure comment macro matching more then it should fix(clojure) comment macro isn't a comment, just another named macro Nov 9, 2021
@joshgoebel joshgoebel changed the title fix(clojure) comment macro isn't a comment, just another named macro fix(clojure) comment macro should not be comment scope Nov 9, 2021
@joshgoebel joshgoebel merged commit 1d8031b into highlightjs:main Nov 9, 2021
@MrEbbinghaus MrEbbinghaus deleted the fix-clojure-comment branch November 10, 2021 09:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants