Skip to content

Commit

Permalink
Merge branch dev into published
Browse files Browse the repository at this point in the history
  • Loading branch information
PEZ committed Oct 29, 2024
2 parents 453b4d6 + 28df841 commit fd37ef7
Show file tree
Hide file tree
Showing 14 changed files with 116 additions and 43 deletions.
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,13 @@ Changes to Calva.

## [Unreleased]

## [2.0.481] - 2024-10-29

- [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

- Fix: [Custom command snippets use the wrong ns when repl sessions types do not match](https://github.com/BetterThanTomorrow/calva/issues/2653)
Expand Down
4 changes: 3 additions & 1 deletion docs/site/evaluation.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ Some of the commands also let you choose what should happen with the results:
* The `line` style is the default.
* The `ignore` style will put an ignore marker (`#_`) before the result.
* The `rcf` style will wrap the result in a rich comment form ( `(comment ...)`).

Here are some example keybindings for using the different comment styles with the **Evaluate Top Level Form (defun) to Comment** command:

```jsonc
Expand Down Expand Up @@ -108,6 +108,8 @@ The **current top-level form** means top-level in a structural sense. It is _not

An ”exception” is introduced by the `comment` form. It will create a new top level context, so that any forms immediately inside a `(comment ...)` form will be considered top-level by Calva. This is to support a workflow with what is often referred to the [Rich Comments](rich-comments.md).

A special case is ignored forms (using the `#_` marker) at the top level. They will always be selected as top level forms separately from their ignore marker, enabling evaluating them as top level forms. Similar to Rich Comments.

At the top level the selection of which form is the current top level form follows the same rules as those for [the current form](#current-form).

### Evaluate Enclosing Form
Expand Down
3 changes: 2 additions & 1 deletion docs/site/syntax-highlighting.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +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"}` |
| `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"
Expand Down
4 changes: 3 additions & 1 deletion docs/site/when-clauses.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,6 @@ description: Calva comes with batteries included and preconfigured, and if you d
* `calva:cursorAfterComment`: `true` when the cursor is adjacent after a line comment
* `calva:cursorAtStartOfLine`: `true` when the cursor is at the start of a line including any leading whitespace
* `calva:cursorAtEndOfLine`: `true` when the cursor is at the end of a line including any trailing whitespace

* `calva:projectRoot`: A string with the absolute path to the repl project root, _without trailing slash_
* `calva:ns`: A string with the current namespace
* `calva:replSessionType`: `clj`, or `cljs` depending on the file type of the current file
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 7 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"displayName": "Calva: Clojure & ClojureScript Interactive Programming",
"description": "Integrated REPL, formatter, Paredit, and more. Powered by cider-nrepl and clojure-lsp.",
"icon": "assets/calva.png",
"version": "2.0.480",
"version": "2.0.481",
"publisher": "betterthantomorrow",
"author": {
"name": "Better Than Tomorrow",
Expand Down Expand Up @@ -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"
}
}
}
Expand Down
15 changes: 5 additions & 10 deletions src/cursor-doc/token-cursor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -316,12 +316,7 @@ export class LispTokenCursor extends TokenCursor {
*
* @returns true if the cursor was moved, false otherwise.
*/
backwardSexp(
skipComments = true,
skipMetadata = false,
skipIgnoredForms = false,
skipReaders = true
) {
backwardSexp(skipComments = true, skipMetadata = false, skipReaders = true) {
const stack = [];
this.backwardWhitespace(skipComments);
if (this.getPrevToken().type === 'open') {
Expand All @@ -345,9 +340,9 @@ export class LispTokenCursor extends TokenCursor {
}
if (skipMetadata) {
const metaCursor = this.clone();
metaCursor.backwardSexp(true, false, false, false);
metaCursor.backwardSexp(true, false, false);
if (metaCursor.tokenBeginsMetadata()) {
this.backwardSexp(skipComments, skipMetadata, skipIgnoredForms);
this.backwardSexp(skipComments, skipMetadata, skipReaders);
}
}
if (skipReaders) {
Expand Down Expand Up @@ -376,9 +371,9 @@ export class LispTokenCursor extends TokenCursor {
}
if (skipMetadata) {
const metaCursor = this.clone();
metaCursor.backwardSexp(true, false, false, false);
metaCursor.backwardSexp(true, false, false);
if (metaCursor.tokenBeginsMetadata()) {
this.backwardSexp(skipComments, skipMetadata, skipIgnoredForms);
this.backwardSexp(skipComments, skipMetadata, skipReaders);
}
}
if (skipReaders) {
Expand Down
2 changes: 1 addition & 1 deletion src/cursor-doc/utilities.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ export function isRightSexpStructural(cursor: LispTokenCursor): boolean {
return false;
}
cursor.forwardSexp(true, true, false);
cursor.backwardSexp(false, false, false, false);
cursor.backwardSexp(false, false, false);

const token = cursor.getToken();
if (token.type === 'open') {
Expand Down
28 changes: 28 additions & 0 deletions src/extension-test/unit/cursor-doc/token-cursor-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,20 @@ describe('Token Cursor', () => {
cursor.backwardSexp(true, true);
expect(cursor.offsetStart).toBe(b.selections[0].anchor);
});
it('Does not skip ignored forms if skipIgnoredForms', () => {
const a = docFromTextNotation('(a #_1 #_2 |3)');
const b = docFromTextNotation('(a #_a #_|2 3)');
const cursor = a.getTokenCursor(a.selections[0].anchor);
cursor.backwardSexp(true, true);
expect(cursor.offsetStart).toBe(b.selections[0].anchor);
});
it('Does not skip stacked ignored forms', () => {
const a = docFromTextNotation('(a #_ #_ 1 2 |3)');
const b = docFromTextNotation('(a #_ #_ 1 |2 3)');
const cursor = a.getTokenCursor(a.selections[0].anchor);
cursor.backwardSexp(true, true);
expect(cursor.offsetStart).toBe(b.selections[0].anchor);
});
});

describe('downList', () => {
Expand Down Expand Up @@ -790,6 +804,13 @@ describe('Token Cursor', () => {
const cursor: LispTokenCursor = a.getTokenCursor(a.selections[0].active);
expect(cursor.rangeForDefun(a.selections[0].active)).toEqual(textAndSelection(b)[1]);
});
// https://github.com/BetterThanTomorrow/calva/issues/2655
it('Does not include ignore marker', () => {
const a = docFromTextNotation('a #_ [b (c|)] [d]');
const b = docFromTextNotation('a #_ |[b (c)]| [d]');
const cursor: LispTokenCursor = a.getTokenCursor(a.selections[0].active);
expect(cursor.rangeForDefun(a.selections[0].active)).toEqual(textAndSelection(b)[1]);
});
describe('Rich Comment Form top level context', () => {
it('Finds range for a top level form inside a comment', () => {
const a = docFromTextNotation('aaa (comment [bbb cc|c] ddd)');
Expand Down Expand Up @@ -940,6 +961,13 @@ describe('Token Cursor', () => {
const cursor: LispTokenCursor = a.getTokenCursor(0);
expect(cursor.rangeForDefun(a.selections[0].anchor)).toEqual(textAndSelection(b)[1]);
});
// https://github.com/BetterThanTomorrow/calva/issues/2655
it('Does not include ignore marker', () => {
const a = docFromTextNotation('aaa (comment #_ [bbb ccc|] ddd)');
const b = docFromTextNotation('aaa (comment #_ |[bbb ccc]| ddd)');
const cursor: LispTokenCursor = a.getTokenCursor(a.selections[0].active);
expect(cursor.rangeForDefun(a.selections[0].active)).toEqual(textAndSelection(b)[1]);
});
});
});

Expand Down
62 changes: 41 additions & 21 deletions src/highlight/src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ let lastHighlightedEditor,
commentFormType: vscode.TextEditorDecorationType,
ignoredFormStyle,
ignoredFormType: vscode.TextEditorDecorationType,
ignoredTopLevelFormStyle,
ignoredTopLevelFormType: vscode.TextEditorDecorationType,
enableBracketColors,
useRainbowIndentGuides,
highlightActiveIndent,
Expand Down Expand Up @@ -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;
}

Expand Down Expand Up @@ -206,6 +215,11 @@ function reloadConfig() {
dirty = true;
}

if (!isEqual(ignoredTopLevelFormStyle, configuration.get('ignoredTopLevelFormStyle'))) {
ignoredTopLevelFormStyle = configuration.get('ignoredTopLevelFormStyle');
dirty = true;
}

if (dirty) {
scheduleRainbowBrackets();
}
Expand All @@ -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;
Expand All @@ -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;
Expand Down Expand Up @@ -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(),
Expand Down Expand Up @@ -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();
Expand Down
2 changes: 2 additions & 0 deletions src/state.ts
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,8 @@ export async function initProjectDir(
);
}
if (projectRootPath) {
console.log('Setting project root to: ', projectRootPath.fsPath);
void vscode.commands.executeCommand('setContext', 'calva:projectRoot', projectRootPath.fsPath);
setStateValue(PROJECT_DIR_KEY, projectRootPath.fsPath);
setStateValue(PROJECT_DIR_URI_KEY, projectRootPath);
return projectRootPath;
Expand Down
7 changes: 7 additions & 0 deletions src/when-contexts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@ import { deepEqual } from './util/object';
import * as docMirror from './doc-mirror';
import * as context from './cursor-doc/cursor-context';
import * as util from './utilities';
import * as namespace from './namespace';
import * as session from './nrepl/repl-session';
import { cljsLib } from './utilities';

export let lastContexts: context.CursorContext[] = [];
export let currentContexts: context.CursorContext[] = [];
Expand All @@ -18,6 +21,10 @@ export function setCursorContextIfChanged(editor: vscode.TextEditor) {
}
const contexts = determineCursorContexts(editor.document, editor.selections[0].active);
setCursorContexts(contexts);
const [ns, _form] = namespace.getDocumentNamespace(editor.document);
void vscode.commands.executeCommand('setContext', 'calva:ns', ns);
const sessionType = session.getReplSessionType(cljsLib.getStateValue('connected'));
void vscode.commands.executeCommand('setContext', 'calva:replSessionType', sessionType);
}

function determineCursorContexts(
Expand Down
5 changes: 4 additions & 1 deletion test-data/.vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -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)"
}
}
8 changes: 4 additions & 4 deletions test-data/test-files/highlight_test.clj
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
;; \
"()"
;; \
;;
;;
(((#((())))))
([ #{ }()[]])
Expand Down Expand Up @@ -54,10 +54,10 @@
(println "I ❤️Clojure")
([{} () []]))
(comment
(+ (* 2 2)
2)
2)
(Math/abs -1)
(defn hello [s]
(str "Hello " s))
Expand Down Expand Up @@ -143,7 +143,7 @@ bar
[:c {:d :e}]]
[:b
[:c {:d :e}]]]
(comment
(comment
(foo #_"bar" baz))
#_{:foo "foo"
:bar (comment [["bar"]])}
Expand Down

0 comments on commit fd37ef7

Please sign in to comment.