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(clj) Fix broken/inconsistent highlighting for $, Numbers, namespaced maps, HINT mode. Add charachter, regex and punctuation modes. #3397

Merged
merged 13 commits into from Nov 10, 2021
Merged
10 changes: 9 additions & 1 deletion CHANGES.md
Expand Up @@ -5,7 +5,15 @@ Grammars:
- fix(python) Fix recognition of numeric literals followed by keywords without whitespace (#2985) [Richard Gibson][]
- enh(swift) add SE-0290 unavailability condition (#3382) [Bradley Mackey][]
- enh(java) add `sealed` and `non-sealed` keywords (#3386) [Bradley Mackey][]
- fix(clojure) `comment` macro catches more than it should [Björn Ebbinghaus][]
- fix(clojure) Several issues with Clojure highlighting (#3397) [Björn Ebbinghaus][]
- fix(clojure) `comment` macro catches more than it should (#3395)
- fix(clojure) `$` in symbol breaks highlighting
- fix(clojure) Add complete regex for number detection
- enh(clojure) Add character mode for character literals
- fix(clojure) Inconsistent namespaced map highlighting
- enh(clojure) Add `regex` mode to regex literal
- fix(clojure) Remove inconsistent/broken highlighting for metadata
- enh(clojure) Add `punctuation` mode for commas.
MrEbbinghaus marked this conversation as resolved.
Show resolved Hide resolved

[Richard Gibson]: https://github.com/gibson042
[Bradley Mackey]: https://github.com/bradleymackey
Expand Down
43 changes: 27 additions & 16 deletions src/languages/clojure.js
Expand Up @@ -8,8 +8,8 @@ Category: lisp

/** @type LanguageFn */
export default function(hljs) {
const SYMBOLSTART = 'a-zA-Z_\\-!.?+*=<>&#\'';
const SYMBOL_RE = '[' + SYMBOLSTART + '][' + SYMBOLSTART + '0-9/;:]*';
const SYMBOLSTART = 'a-zA-Z_\\-!.?+*=<>&\'';
MrEbbinghaus marked this conversation as resolved.
Show resolved Hide resolved
const SYMBOL_RE = '[#]?[' + SYMBOLSTART + '][' + SYMBOLSTART + '0-9/;:$#]*';
const globals = 'def defonce defprotocol defstruct defmulti defmethod defn- defn defmacro deftype defrecord';
const keywords = {
$pattern: SYMBOL_RE,
Expand Down Expand Up @@ -45,20 +45,35 @@ export default function(hljs) {
'lazy-seq spread list* str find-keyword keyword symbol gensym force rationalize'
};

const SIMPLE_NUMBER_RE = '[-+]?\\d+(\\.\\d+)?';
const NUMBER_RE = /[-+]?(((0[xX][0-9a-fA-F]+|0[0-7]+|[1-9][0-9]?[rR][0-9a-zA-Z]+)N?)|[0-9]+(\/[0-9]+|N|((\.[0-9]*)?([eE][+-]?[0-9]+)?M?)))/
MrEbbinghaus marked this conversation as resolved.
Show resolved Hide resolved
const CHAR_RE = /\\(o[0-3]?[0-7]{1,2}|u[0-9a-fA-F]{4}|newline|space|tab|formfeed|backspace|return|\S)/

const SYMBOL = {
begin: SYMBOL_RE,
relevance: 0
};
const NUMBER = {
className: 'number',
begin: SIMPLE_NUMBER_RE,
scope: 'number',
match: NUMBER_RE,
relevance: 0
};
const CHARACTER = {
scope: 'character',
match: CHAR_RE
}
const REGEX = {
scope: 'regex',
begin: /#"/,
end: /"/
}
const STRING = hljs.inherit(hljs.QUOTE_STRING_MODE, {
illegal: null
});
const COMMA = {
scope: 'punctuation',
match: /,/,
relevance: 0
}
const COMMENT = hljs.COMMENT(
';',
'$',
Expand All @@ -71,15 +86,10 @@ export default function(hljs) {
begin: /\b(true|false|nil)\b/
};
const COLLECTION = {
begin: '[\\[\\{]',
begin: "\\[|(#::?" + SYMBOL_RE + ")?\\{",
end: '[\\]\\}]',
relevance: 0
};
const HINT = {
className: 'comment',
begin: '\\^' + SYMBOL_RE
};
const HINT_COL = hljs.COMMENT('\\^\\{', '\\}');
const KEY = {
className: 'symbol',
begin: '[:]{1,2}' + SYMBOL_RE
Expand All @@ -100,10 +110,11 @@ export default function(hljs) {
starts: BODY
};
const DEFAULT_CONTAINS = [
COMMA,
LIST,
CHARACTER,
REGEX,
STRING,
HINT,
HINT_COL,
COMMENT,
KEY,
COLLECTION,
Expand Down Expand Up @@ -138,17 +149,17 @@ export default function(hljs) {
];
BODY.contains = DEFAULT_CONTAINS;
COLLECTION.contains = DEFAULT_CONTAINS;
HINT_COL.contains = [ COLLECTION ];

return {
name: 'Clojure',
aliases: [ 'clj', 'edn' ],
illegal: /\S/,
contains: [
COMMA,
LIST,
CHARACTER,
REGEX,
STRING,
HINT,
HINT_COL,
COMMENT,
KEY,
COLLECTION,
Expand Down
5 changes: 5 additions & 0 deletions test/markup/clojure/character.expect.txt
@@ -0,0 +1,5 @@
<span class="hljs-character">\A</span>
<span class="hljs-character">\a</span>
<span class="hljs-character">\formfeed</span>
<span class="hljs-character">\u00DF</span>
<span class="hljs-character">\o303</span>
5 changes: 5 additions & 0 deletions test/markup/clojure/character.txt
@@ -0,0 +1,5 @@
\A
\a
\formfeed
\u00DF
\o303
18 changes: 9 additions & 9 deletions test/markup/clojure/deps_edn.expect.txt
@@ -1,14 +1,14 @@
{<span class="hljs-symbol">:aliases</span> {<span class="hljs-symbol">:export</span> {<span class="hljs-symbol">:exec-fn</span> stelcodes.dev-blog.generator/export},
<span class="hljs-symbol">:repl</span> {<span class="hljs-symbol">:extra-deps</span> {cider/cider-nrepl {<span class="hljs-symbol">:mvn/version</span> <span class="hljs-string">&quot;0.25.2&quot;</span>},
nrepl/nrepl {<span class="hljs-symbol">:mvn/version</span> <span class="hljs-string">&quot;0.8.3&quot;</span>}},
<span class="hljs-symbol">:extra-paths</span> [<span class="hljs-string">&quot;dev&quot;</span>],
{<span class="hljs-symbol">:aliases</span> {<span class="hljs-symbol">:export</span> {<span class="hljs-symbol">:exec-fn</span> stelcodes.dev-blog.generator/export}<span class="hljs-punctuation">,</span>
<span class="hljs-symbol">:repl</span> {<span class="hljs-symbol">:extra-deps</span> {cider/cider-nrepl {<span class="hljs-symbol">:mvn/version</span> <span class="hljs-string">&quot;0.25.2&quot;</span>}<span class="hljs-punctuation">,</span>
nrepl/nrepl {<span class="hljs-symbol">:mvn/version</span> <span class="hljs-string">&quot;0.8.3&quot;</span>}}<span class="hljs-punctuation">,</span>
<span class="hljs-symbol">:extra-paths</span> [<span class="hljs-string">&quot;dev&quot;</span>]<span class="hljs-punctuation">,</span>
<span class="hljs-symbol">:main-opts</span> [<span class="hljs-string">&quot;-m&quot;</span>
<span class="hljs-string">&quot;nrepl.cmdline&quot;</span>
<span class="hljs-string">&quot;--middleware&quot;</span>
<span class="hljs-string">&quot;[cider.nrepl/cider-middleware]&quot;</span>
<span class="hljs-string">&quot;--interactive&quot;</span>]},
<span class="hljs-symbol">:webhook</span> {<span class="hljs-symbol">:exec-fn</span> stelcodes.dev-blog.webhook/listen}},
<span class="hljs-symbol">:deps</span> {http-kit/http-kit {<span class="hljs-symbol">:mvn/version</span> <span class="hljs-string">&quot;2.5.3&quot;</span>},
org.clojure/clojure {<span class="hljs-symbol">:mvn/version</span> <span class="hljs-string">&quot;1.10.1&quot;</span>},
stasis/stasis {<span class="hljs-symbol">:mvn/version</span> <span class="hljs-string">&quot;2.5.1&quot;</span>}},
<span class="hljs-string">&quot;--interactive&quot;</span>]}<span class="hljs-punctuation">,</span>
<span class="hljs-symbol">:webhook</span> {<span class="hljs-symbol">:exec-fn</span> stelcodes.dev-blog.webhook/listen}}<span class="hljs-punctuation">,</span>
<span class="hljs-symbol">:deps</span> {http-kit/http-kit {<span class="hljs-symbol">:mvn/version</span> <span class="hljs-string">&quot;2.5.3&quot;</span>}<span class="hljs-punctuation">,</span>
org.clojure/clojure {<span class="hljs-symbol">:mvn/version</span> <span class="hljs-string">&quot;1.10.1&quot;</span>}<span class="hljs-punctuation">,</span>
stasis/stasis {<span class="hljs-symbol">:mvn/version</span> <span class="hljs-string">&quot;2.5.1&quot;</span>}}<span class="hljs-punctuation">,</span>
<span class="hljs-symbol">:paths</span> [<span class="hljs-string">&quot;src&quot;</span> <span class="hljs-string">&quot;resources&quot;</span>]}
13 changes: 9 additions & 4 deletions test/markup/clojure/globals_definition.expect.txt
Expand Up @@ -5,21 +5,26 @@
<span class="hljs-comment">; function</span>
(<span class="hljs-keyword">defn</span> <span class="hljs-title">clojure-function</span> [args]
(<span class="hljs-name"><span class="hljs-built_in">let</span></span> [string <span class="hljs-string">&quot;multiline\nstring&quot;</span>
regexp #<span class="hljs-string">&quot;regexp&quot;</span>
number <span class="hljs-number">100</span>,<span class="hljs-number">000</span>
regexp <span class="hljs-regex">#&quot;regexp&quot;</span>
number <span class="hljs-number">100000</span>
booleans [<span class="hljs-literal">false</span> <span class="hljs-literal">true</span>]
keyword <span class="hljs-symbol">::the-keyword</span>]
<span class="hljs-comment">;; this is comment</span>
(<span class="hljs-name"><span class="hljs-built_in">if</span></span> <span class="hljs-literal">true</span>
(<span class="hljs-name"><span class="hljs-built_in">-&gt;&gt;</span></span>
(<span class="hljs-name"><span class="hljs-built_in">list</span></span> [vector] {<span class="hljs-symbol">:map</span> map} #{&#x27;set})))))

#:person{<span class="hljs-symbol">:first</span> <span class="hljs-string">&quot;Han&quot;</span>
<span class="hljs-symbol">:last</span> <span class="hljs-string">&quot;Solo&quot;</span>
<span class="hljs-symbol">:ship</span> #:ship{<span class="hljs-symbol">:name</span> <span class="hljs-string">&quot;Millenium Falcon&quot;</span>}}
#::{<span class="hljs-symbol">:a</span> <span class="hljs-number">1</span><span class="hljs-punctuation">,</span> <span class="hljs-symbol">:b</span> <span class="hljs-number">2</span>}

<span class="hljs-comment">; global</span>
(<span class="hljs-keyword">def</span> <span class="hljs-title">some-var</span>)
<span class="hljs-comment">; another one</span>
(<span class="hljs-keyword">def</span> <span class="hljs-title">alternative-var</span> <span class="hljs-string">&quot;132&quot;</span>)
<span class="hljs-comment">; defonce</span>
(<span class="hljs-keyword">defonce</span> ^<span class="hljs-symbol">:private</span> <span class="hljs-title">another-var</span> #<span class="hljs-string">&quot;foo&quot;</span>)
(<span class="hljs-keyword">defonce</span> ^<span class="hljs-symbol">:private</span> <span class="hljs-title">another-var</span> <span class="hljs-regex">#&quot;foo&quot;</span>)

<span class="hljs-comment">; private function</span>
(<span class="hljs-keyword">defn-</span> <span class="hljs-title">add</span> [x y] (<span class="hljs-name"><span class="hljs-built_in">+</span></span> x y))
Expand Down Expand Up @@ -58,4 +63,4 @@

<span class="hljs-comment">;; create a couple shapes and get their area</span>
(<span class="hljs-keyword">def</span> <span class="hljs-title">myCircle</span> (<span class="hljs-name">Circle.</span> <span class="hljs-number">10</span>))
(<span class="hljs-keyword">def</span> <span class="hljs-title">mySquare</span> (<span class="hljs-name">Square.</span> <span class="hljs-number">5</span> <span class="hljs-number">11</span>))
(<span class="hljs-keyword">def</span> <span class="hljs-title">mySquare</span> (<span class="hljs-name">Square.</span> <span class="hljs-number">5</span> <span class="hljs-number">11</span>))
7 changes: 6 additions & 1 deletion test/markup/clojure/globals_definition.txt
Expand Up @@ -6,14 +6,19 @@
(defn clojure-function [args]
(let [string "multiline\nstring"
regexp #"regexp"
number 100,000
number 100000
joshgoebel marked this conversation as resolved.
Show resolved Hide resolved
booleans [false true]
keyword ::the-keyword]
;; this is comment
(if true
(->>
(list [vector] {:map map} #{'set})))))

#:person{:first "Han"
:last "Solo"
:ship #:ship{:name "Millenium Falcon"}}
#::{:a 1, :b 2}

; global
(def some-var)
; another one
Expand Down
34 changes: 0 additions & 34 deletions test/markup/clojure/hint_col.expect.txt

This file was deleted.

34 changes: 0 additions & 34 deletions test/markup/clojure/hint_col.txt

This file was deleted.

50 changes: 50 additions & 0 deletions test/markup/clojure/number.expect.txt
@@ -0,0 +1,50 @@
<span class="hljs-comment">; integer</span>
<span class="hljs-number">00</span>
<span class="hljs-number">42</span>

<span class="hljs-comment">; BigInt</span>
<span class="hljs-number">42N</span>
<span class="hljs-number">0N</span>

<span class="hljs-comment">; octal</span>
<span class="hljs-number">052</span>
<span class="hljs-number">00N</span>

<span class="hljs-comment">; hex</span>
<span class="hljs-number">0x2a</span>
<span class="hljs-number">0x0N</span>

<span class="hljs-comment">; radix</span>
<span class="hljs-number">2r101010</span>
<span class="hljs-number">8r52</span>
<span class="hljs-number">16r2a</span>
<span class="hljs-number">36r16</span>

<span class="hljs-comment">; radix BigInt</span>
<span class="hljs-number">2r101010N</span>
<span class="hljs-number">8r52N</span>
<span class="hljs-number">16r2aN</span>
<span class="hljs-number">36r16N</span>

<span class="hljs-comment">;; ratios</span>
<span class="hljs-number">1/2</span>
<span class="hljs-number">-1/2</span>

<span class="hljs-comment">;; floats</span>
<span class="hljs-number">42.0</span>
<span class="hljs-number">-42.0</span>
<span class="hljs-number">42.</span>

<span class="hljs-comment">; BigDecimal</span>
<span class="hljs-number">42.0M</span>
<span class="hljs-number">-42M</span>
<span class="hljs-number">42.M</span>
<span class="hljs-number">42M</span>

<span class="hljs-comment">; with Exponent</span>
<span class="hljs-number">42.0E2</span>
<span class="hljs-number">-42.0E+9</span>
<span class="hljs-number">42E-0</span>

<span class="hljs-number">42.0E2M</span>
<span class="hljs-number">42E+9M</span>
50 changes: 50 additions & 0 deletions test/markup/clojure/number.txt
@@ -0,0 +1,50 @@
; integer
00
42

; BigInt
42N
0N

; octal
052
00N

; hex
0x2a
0x0N

; radix
2r101010
8r52
16r2a
36r16

; radix BigInt
2r101010N
8r52N
16r2aN
36r16N

;; ratios
1/2
-1/2

;; floats
42.0
-42.0
42.

; BigDecimal
42.0M
-42M
42.M
42M

; with Exponent
42.0E2
-42.0E+9
42E-0

42.0E2M
42E+9M
3 changes: 3 additions & 0 deletions test/markup/clojure/symbols-numbers.expect.txt
@@ -1 +1,4 @@
(<span class="hljs-keyword">def</span> <span class="hljs-title">+x</span> [(<span class="hljs-name">a</span> <span class="hljs-number">1</span>) <span class="hljs-number">+2</span> <span class="hljs-number">-3.0</span> y-5])
(<span class="hljs-name">System/getProperty</span> <span class="hljs-string">&quot;java.vm.version&quot;</span>)
(<span class="hljs-name">.getEnclosingClass</span> java.util.Map$Entry)
(<span class="hljs-name">java.util.Map$Entry.</span> .getEnclosingClass)
3 changes: 3 additions & 0 deletions test/markup/clojure/symbols-numbers.txt
@@ -1 +1,4 @@
(def +x [(a 1) +2 -3.0 y-5])
(System/getProperty "java.vm.version")
(.getEnclosingClass java.util.Map$Entry)
(java.util.Map$Entry. .getEnclosingClass)