From 69a56452af48456697d41bc5fcf15354d1fecf78 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Peter=20Str=C3=B6mberg?= <pez@pezius.com>
Date: Tue, 29 Oct 2024 22:01:19 +0100
Subject: [PATCH 1/4] Use separate style for top level ignored forms

---
 src/highlight/src/extension.ts | 62 ++++++++++++++++++++++------------
 1 file changed, 41 insertions(+), 21 deletions(-)

diff --git a/src/highlight/src/extension.ts b/src/highlight/src/extension.ts
index 77ed1d0b1..a5723e6c2 100755
--- a/src/highlight/src/extension.ts
+++ b/src/highlight/src/extension.ts
@@ -39,6 +39,8 @@ let lastHighlightedEditor,
   commentFormType: vscode.TextEditorDecorationType,
   ignoredFormStyle,
   ignoredFormType: vscode.TextEditorDecorationType,
+  ignoredTopLevelFormStyle,
+  ignoredTopLevelFormType: vscode.TextEditorDecorationType,
   enableBracketColors,
   useRainbowIndentGuides,
   highlightActiveIndent,
@@ -152,6 +154,13 @@ function reset_styles() {
   }
   ignoredFormType = decorationType(ignoredFormStyle || { textDecoration: 'none; opacity: 0.5' });
 
+  if (ignoredTopLevelFormType) {
+    activeEditor.setDecorations(ignoredTopLevelFormType, []);
+  }
+  ignoredTopLevelFormType = decorationType(
+    ignoredTopLevelFormStyle || ignoredFormStyle || { textDecoration: 'none; opacity: 0.5' }
+  );
+
   dirty = false;
 }
 
@@ -206,6 +215,11 @@ function reloadConfig() {
     dirty = true;
   }
 
+  if (!isEqual(ignoredTopLevelFormStyle, configuration.get('ignoredTopLevelFormStyle'))) {
+    ignoredTopLevelFormStyle = configuration.get('ignoredTopLevelFormStyle');
+    dirty = true;
+  }
+
   if (dirty) {
     scheduleRainbowBrackets();
   }
@@ -231,18 +245,19 @@ function updateRainbowBrackets() {
     reset_styles();
   }
 
-  const doc = activeEditor.document,
-    mirrorDoc = docMirror.getDocument(doc),
-    rainbow = rainbowTypes.map(() => []),
-    rainbowGuides = rainbowTypes.map(() => []),
-    misplaced = [],
-    comment_forms = [],
-    ignores = [],
-    len = rainbowTypes.length,
-    colorsEnabled = enableBracketColors && len > 0,
-    guideColorsEnabled = useRainbowIndentGuides && len > 0,
-    activeGuideEnabled = highlightActiveIndent && len > 0,
-    colorIndex = cycleBracketColors ? (i) => i % len : (i) => Math.min(i, len - 1);
+  const doc = activeEditor.document;
+  const mirrorDoc = docMirror.getDocument(doc);
+  const rainbow = rainbowTypes.map(() => []);
+  const rainbowGuides = rainbowTypes.map(() => []);
+  const misplaced = [];
+  const comment_forms = [];
+  const ignores = [];
+  const topLevelIgnores = [];
+  const len = rainbowTypes.length;
+  const colorsEnabled = enableBracketColors && len > 0;
+  const guideColorsEnabled = useRainbowIndentGuides && len > 0;
+  const activeGuideEnabled = highlightActiveIndent && len > 0;
+  const colorIndex = cycleBracketColors ? (i) => i % len : (i) => Math.min(i, len - 1);
 
   let in_comment_form = false;
   let stack_depth = 0;
@@ -252,14 +267,14 @@ function updateRainbowBrackets() {
   placedGuidesColor = new Map();
   activeEditor.visibleRanges.forEach((range) => {
     // Find the visible forms
-    const startOffset = doc.offsetAt(range.start),
-      endOffset = doc.offsetAt(range.end),
-      startCursor: LispTokenCursor = mirrorDoc.getTokenCursor(0),
-      startRange = startCursor.rangeForDefun(startOffset, false),
-      endCursor: LispTokenCursor = mirrorDoc.getTokenCursor(endOffset),
-      endRange = endCursor.rangeForDefun(endOffset, false),
-      rangeStart = startRange ? startRange[0] : startOffset,
-      rangeEnd = endRange ? endRange[1] : endOffset;
+    const startOffset = doc.offsetAt(range.start);
+    const endOffset = doc.offsetAt(range.end);
+    const startCursor: LispTokenCursor = mirrorDoc.getTokenCursor(0);
+    const startRange = startCursor.rangeForDefun(startOffset, false);
+    const endCursor: LispTokenCursor = mirrorDoc.getTokenCursor(endOffset);
+    const endRange = endCursor.rangeForDefun(endOffset, false);
+    const rangeStart = startRange ? startRange[0] : startOffset;
+    const rangeEnd = endRange ? endRange[1] : endOffset;
     // Look for top level ignores, and adjust starting point if found
     const topLevelSentinelCursor = mirrorDoc.getTokenCursor(rangeStart);
     let startPaintingFrom = rangeStart;
@@ -299,7 +314,11 @@ function updateRainbowBrackets() {
             ignoreCursor.forwardSexp(true, true, true);
           }
           const ignore_end = activeEditor.document.positionAt(ignoreCursor.offsetStart);
-          ignores.push(new Range(ignore_start, ignore_end));
+          if (cursor.atTopLevel()) {
+            topLevelIgnores.push(new Range(ignore_start, ignore_end));
+          } else {
+            ignores.push(new Range(ignore_start, ignore_end));
+          }
         }
       }
       const token = cursor.getToken(),
@@ -399,6 +418,7 @@ function updateRainbowBrackets() {
   activeEditor.setDecorations(misplacedType, misplaced);
   activeEditor.setDecorations(commentFormType, comment_forms);
   activeEditor.setDecorations(ignoredFormType, ignores);
+  activeEditor.setDecorations(ignoredTopLevelFormType, topLevelIgnores);
   matchPairs();
   if (activeGuideEnabled) {
     decorateActiveGuides();

From 44ae9fc53059ef3a402372cf9696c4ecbd8365eb Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Peter=20Str=C3=B6mberg?= <pez@pezius.com>
Date: Tue, 29 Oct 2024 22:59:40 +0100
Subject: [PATCH 2/4] Add configuration for `ignoredTopLevelForms`

* Fixes #2660
---
 docs/site/syntax-highlighting.md        | 1 +
 package.json                            | 6 ++++++
 test-data/.vscode/settings.json         | 5 ++++-
 test-data/test-files/highlight_test.clj | 8 ++++----
 4 files changed, 15 insertions(+), 5 deletions(-)

diff --git a/docs/site/syntax-highlighting.md b/docs/site/syntax-highlighting.md
index c85ebdafa..fbb6298b7 100644
--- a/docs/site/syntax-highlighting.md
+++ b/docs/site/syntax-highlighting.md
@@ -44,6 +44,7 @@ You are in charge of how brackets and comments are highlighted via the `calva.hi
 | `misplacedBracketStyle` | Style of misplaced bracket | `{ "border": "2px solid #c33" }` |
 | `matchedBracketStyle` | Style of bracket pair highlight | `{"backgroundColor": "#E0E0E0"}` |
 | `ignoredFormStyle` | Style of `#_...` form | `{"textDecoration": "none; opacity: 0.5"}` |
+| `ignoredTopLevelFormStyle` | Style of `#_...` form. (If not set uses `ignoredFormStyle`) | `{ "textDecoration": "none; text-shadow: 2px 2px 5px rgba(255, 215, 0, 0.75)" }` |
 | `commentFormStyle` | Style of `(comment ...)` form | `{"fontStyle": "italic"}` |
 
 !!! Note "Calva disables the VS Code built-in indent guides"
diff --git a/package.json b/package.json
index 00c23ca96..b425e30ab 100644
--- a/package.json
+++ b/package.json
@@ -1142,6 +1142,12 @@
             "default": null,
             "description": "Style of `#_` ignored forms",
             "scope": "resource"
+          },
+          "calva.highlight.ignoredTopLevelFormStyle": {
+            "type": "object",
+            "default": null,
+            "markdownDescription": "Style of top level `#_` ignored forms. If not specified, it will be the same as what's set for `calva.highlight.ignoredFormStyle`",
+            "scope": "resource"
           }
         }
       }
diff --git a/test-data/.vscode/settings.json b/test-data/.vscode/settings.json
index 4c610fb24..f9cd699ae 100644
--- a/test-data/.vscode/settings.json
+++ b/test-data/.vscode/settings.json
@@ -139,5 +139,8 @@
       "afterCL]ReplJackInCode": ["(println :hello)", "(println :world!)"],
       "cljsType": "none"
     }
-  ]
+  ],
+  "calva.highlight.ignoredTopLevelFormStyle": {
+    "textDecoration": "none; text-shadow: 2px 2px 5px rgba(255, 215, 0, 0.75)"
+  }
 }
diff --git a/test-data/test-files/highlight_test.clj b/test-data/test-files/highlight_test.clj
index 4ce8cd123..7f9489f73 100644
--- a/test-data/test-files/highlight_test.clj
+++ b/test-data/test-files/highlight_test.clj
@@ -22,7 +22,7 @@
 ;; \
 "()"
 ;; \
-;; 
+;;
 (((#((())))))
 ([ #{ }()[]])
 
@@ -54,10 +54,10 @@
   (println "I ❤️Clojure")
   ([{} () []]))
 
-    
+
     (comment
       (+ (* 2 2)
-         2)      
+         2)
       (Math/abs -1)
       (defn hello [s]
         (str "Hello " s))
@@ -143,7 +143,7 @@ bar
   [:c {:d :e}]]
  [:b
   [:c {:d :e}]]]
-(comment 
+(comment
   (foo #_"bar" baz))
 #_{:foo "foo"
    :bar (comment [["bar"]])}

From 1302306595e1a548f0a2b59f1e9e289e09a1e506 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Peter=20Str=C3=B6mberg?= <pez@pezius.com>
Date: Tue, 29 Oct 2024 23:07:52 +0100
Subject: [PATCH 3/4] Fix typo in documentation [skip ci]

---
 docs/site/syntax-highlighting.md | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/docs/site/syntax-highlighting.md b/docs/site/syntax-highlighting.md
index fbb6298b7..83f6cc41b 100644
--- a/docs/site/syntax-highlighting.md
+++ b/docs/site/syntax-highlighting.md
@@ -43,8 +43,8 @@ You are in charge of how brackets and comments are highlighted via the `calva.hi
 | `cycleBracketColors` | Whether same colors should be <br> reused for deeply nested brackets | `true` |
 | `misplacedBracketStyle` | Style of misplaced bracket | `{ "border": "2px solid #c33" }` |
 | `matchedBracketStyle` | Style of bracket pair highlight | `{"backgroundColor": "#E0E0E0"}` |
-| `ignoredFormStyle` | Style of `#_...` form | `{"textDecoration": "none; opacity: 0.5"}` |
-| `ignoredTopLevelFormStyle` | Style of `#_...` form. (If not set uses `ignoredFormStyle`) | `{ "textDecoration": "none; text-shadow: 2px 2px 5px rgba(255, 215, 0, 0.75)" }` |
+| `ignoredFormStyle` | Style of `#_...` forms | `{"textDecoration": "none; opacity: 0.5"}` |
+| `ignoredTopLevelFormStyle` | Style of `#_...` forms at the top level. (If not set, uses `ignoredFormStyle`) | `{ "textDecoration": "none; text-shadow: 2px 2px 5px rgba(255, 215, 0, 0.75)" }` |
 | `commentFormStyle` | Style of `(comment ...)` form | `{"fontStyle": "italic"}` |
 
 !!! Note "Calva disables the VS Code built-in indent guides"

From eef974a9ba24dc1eb869fba73ab15a4178b9dd8a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Peter=20Str=C3=B6mberg?= <pez@pezius.com>
Date: Tue, 29 Oct 2024 23:13:17 +0100
Subject: [PATCH 4/4] Update changelog [skip ci]

---
 CHANGELOG.md | 1 +
 1 file changed, 1 insertion(+)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index f5a014b01..7e206a93f 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -7,6 +7,7 @@ Changes to Calva.
 - [Add extension when contexts for Calva states such as project root, session type, ns](https://github.com/BetterThanTomorrow/calva/issues/2652)
 - Fix: [Calva internals: The `backwardSexp` function can't handle skipping ignored forms, even though it says it can](https://github.com/BetterThanTomorrow/calva/issues/2657)
 - Fix: [Keep support for evaluating top level form in ignored forms when at top level](https://github.com/BetterThanTomorrow/calva/issues/2655)
+- [Enable separate styling for top level ignored forms](https://github.com/BetterThanTomorrow/calva/issues/2660)
 
 ## [2.0.480] - 2024-10-21