Skip to content

Commit

Permalink
Merge branch 'dev'
Browse files Browse the repository at this point in the history
  • Loading branch information
PEZ committed Oct 10, 2019
2 parents 9a9d96f + ba990c2 commit 0e1fed1
Show file tree
Hide file tree
Showing 18 changed files with 350 additions and 144 deletions.
9 changes: 8 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,14 @@ Changes to Calva.

## [Unreleased]

## [2.0.45] - 08.10.2019
## [2.0.47] - 10.10.2019
- [Support Jack-in without file open for single-rooted workspace](https://github.com/BetterThanTomorrow/calva/issues/366)
- [Show argument list of fn](https://github.com/BetterThanTomorrow/calva/issues/238)
- [Make code more robust in case Jack-in task fails](https://github.com/BetterThanTomorrow/calva/issues/367)
- [Fix dimming out of stacked ignored forms](https://github.com/BetterThanTomorrow/calva/issues/385)
- [The extension should specify the default schemes for document selectors](https://github.com/BetterThanTomorrow/calva/issues/368)

## [2.0.46] - 08.10.2019
- [Connect warnings and errors as popups](https://github.com/BetterThanTomorrow/calva/issues/356)
- [Don't remove default indents when Calva is not the auto-formatter](https://github.com/BetterThanTomorrow/calva/pull/383)

Expand Down
43 changes: 17 additions & 26 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,21 +16,23 @@ Calva's main reason for existance is to _provide Visual Studio Code users with a

## How to Connect Calva to your project

Let Calva start your project (_a.k.a. **Jack-in**_).
Let Calva start your project _a.k.a. **Jack-in**_. (Assuming you have a single project workspace. See [Workspace Layout](https://github.com/BetterThanTomorrow/calva/wiki/Workspace-Layouts) on the wiki for other setups)

1. Open your project in VS Code, and a file in the project. From the command line it could be something like: `code path/to/myproject README.md`.
1. Open your project folder in VS Code.
1. Issue the command **Start a Project REPL and Connect (aka Jack-In)**: `ctrl+alt+c ctrl+alt+j`.
1. Answer the prompts where Calva asks you a few things about your project.

When Calva has connected, it will open a REPL window giving you some getting started tips, and you can start hacking. The first thing you should always do to ”wake” Calva is to load/evaluate the current Clojure(Script) file: `ctrl+alt+c enter`.
When Calva has connected, it will open a REPL window giving you some getting started tips, and you can start hacking.

Troubles connecting? [Check here](https://github.com/BetterThanTomorrow/calva/wiki/Connect-Calva-to-Your-Project). (Please help keep that wiki page updated.)
Troubles connecting? See [Connect Calva to Your Project](https://github.com/BetterThanTomorrow/calva/wiki/Connect-Calva-to-Your-Project) on the wiki. (Please help keep that page updated.)

## Something to try first

You might want to start with evaluating some code. Calva has this notion about the ”current” form (the symbol under the cursor or the paren enclosed s-expr immediately adjacent to the cursor). Issue the **Evaluate Current Form Inline** command: `ctrl+alt+c e`.
You might want to start with evaluating some code. Calva has this notion about the ”current” form. Issue the **Evaluate Current Form Inline** command, `ctrl+alt+c e` with the cursor placed in different locations to get a feeling for how the current form is determined.

There is also a command for evaluating the current top level form, which aösp works inside `(comment)` forms supporting code experimentation. It looks something like so:
There is also a command for evaluating the current top level form. Good for evaluating various `def`s `defn`, `defthis`, `defthat`. With your cursor placed anywhere inside such a form, issue the **Evaluate Current Top Level Form (defun)** command (`ctrl+alt+c space`).

The Top Level command also works inside `(comment ...)` forms, treating the `comment` as creating a new top level context. It is good for in-file code experimentation. To use it place the cursor inside a form contained inside a `(comment...)` and issue the command from there. It looks something like so:

![Annotate clojure code evaluation!](assets/howto/evaluate.gif)

Expand All @@ -40,37 +42,22 @@ See also [Calva Top 10 Commands](https://github.com/BetterThanTomorrow/calva/wik

When something doesn't work and you think there might be a workaround for it, please see the [wiki](https://github.com/BetterThanTomorrow/calva/wiki/). Anyone can author the wiki so if you know about workarounds or gotchas or anything that is good to know about when using Calva, please edit the appropriate page (or create a new page).


## Features

### At a glance
- Syntax highlighting, plus:
- Rainbow parens
- Highlights misplaced brackets
- LISP friendly bracket matching
- Ignore form (`#_`) dimming and `(comment)` form highlighting
- Clojure code formatting
- Quickly and easily get your REPL connected
- Evaluate code inline
- Run tests
- Integrated REPL windows
- Code formatting and autoindent according to https://github.com/bbatsov/clojure-style-guide
- Support for [Clojure tools/deps](https://clojure.org/guides/deps_and_cli), [Leiningen](https://leiningen.org), [shadow-cljs](http://shadow-cljs.org), [lein-figwheel](https://github.com/bhauman/lein-figwheel), and [Figwheel Main](https://figwheel.org), and Nashorn repls. (For [Boot](https://boot-clj.com), only Connect scenarios work, there is no Jack-in yet.)
- Your [Custom Connect Sequences](https://github.com/BetterThanTomorrow/calva/wiki/Custom-Connect-Sequences), including fully customized CLJS REPLs.
- Switch the CLJS REPL connection between your different CLJS builds at will.
- Intellisense
- Go to / Peek at definition
- View docstrings on hover
- View function signatures on hover
- Supports all Clojure filetypes: `clj`, `cljc`, and `cljs`
- Easy toggle between `clj` and `cljs` repl for `cljc` files
- Autoindent according to https://github.com/bbatsov/clojure-style-guide
- Enables `clj` evaluation of Clojure code in all files (e.g. Markdown, etcetera).
- Support for [Clojure tools/deps](https://clojure.org/guides/deps_and_cli), [Leiningen](https://leiningen.org), [shadow-cljs](http://shadow-cljs.org), [lein-figwheel](https://github.com/bhauman/lein-figwheel), and [Figwheel Main](https://figwheel.org), and Nashorn repls. (For [Boot](https://boot-clj.com), only Connect scenarios work, no Jack-in yet.)
- Your [Custom Connect Sequences](https://github.com/BetterThanTomorrow/calva/wiki/Custom-Connect-Sequences), including fully customized CLJS REPLs.
- Switch the CLJS REPL connection between your different CLJS builds at will.

Demo: switch between `clj` and `cljs` repl sessions for `cljc` files:

![CLJC repl switching](/assets/howto/cljc-clj-cljs.gif)

### More in depth (and some usage info)
### More features (and some usage info)
- Running tests through the REPL connection, and mark them in the Problems tab
- Run namespace tests: `ctrl+alt+c t`
- Run all tests: `ctrl+alt+c shift+t`
Expand Down Expand Up @@ -103,6 +90,10 @@ Demo: Peek at definitions, etcetera:

![Features](/assets/howto/features.gif)

Demo: switch between `clj` and `cljs` repl sessions for `cljc` files:

![CLJC repl switching](/assets/howto/cljc-clj-cljs.gif)

### Test features not available with ClojureScript

Currently [`cider-nrepl` does not provide its test functionality for ClojureScript](https://github.com/clojure-emacs/cider-nrepl/issues/555) code. Please consider contributing to fixing that.
Expand Down
10 changes: 7 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,10 @@
"onCommand:calva.jackIn",
"onCommand:calva.jackInOrConnect",
"onCommand:calva.connect",
"onCommand:calva.connectNonProjectREPL"
"onCommand:calva.connectNonProjectREPL",
"workspaceContains:**/project.clj",
"workspaceContains:**/shadow-cljs.edn",
"workspaceContains:**/deps.edn"
],
"main": "./out/extension",
"contributes": {
Expand Down Expand Up @@ -571,8 +574,8 @@
},
{
"command": "calva.disconnect",
"title": "Disonnect from the REPL Server",
"enablement": "calva:connected || calva:connecting",
"title": "Disconnect from the REPL Server",
"enablement": "calva:connected || calva:connecting || calva:launching",
"category": "Calva"
},
{
Expand Down Expand Up @@ -736,6 +739,7 @@
{
"command": "calva.refreshAll",
"title": "Refresh All Namespaces",
"enablement": "calva:connected",
"category": "Calva"
},
{
Expand Down
5 changes: 3 additions & 2 deletions src/calva-fmt/src/extension.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import * as vscode from 'vscode';
import * as state from '../../state';
import { FormatOnTypeEditProvider } from './providers/ontype_formatter';
import { RangeEditProvider } from './providers/range_formatter';
import * as formatter from './format';
Expand Down Expand Up @@ -40,8 +41,8 @@ export function activate(context: vscode.ExtensionContext) {
context.subscriptions.push(vscode.commands.registerTextEditorCommand('calva-fmt.inferParens', inferer.inferParensCommand));
context.subscriptions.push(vscode.commands.registerTextEditorCommand('calva-fmt.tabIndent', (e) => { inferer.indentCommand(e, " ", true) }));
context.subscriptions.push(vscode.commands.registerTextEditorCommand('calva-fmt.tabDedent', (e) => { inferer.indentCommand(e, " ", false) }));
context.subscriptions.push(vscode.languages.registerOnTypeFormattingEditProvider("clojure", new FormatOnTypeEditProvider, "\r", "\n"));
context.subscriptions.push(vscode.languages.registerDocumentRangeFormattingEditProvider("clojure", new RangeEditProvider));
context.subscriptions.push(vscode.languages.registerOnTypeFormattingEditProvider(state.documentSelector, new FormatOnTypeEditProvider, "\r", "\n"));
context.subscriptions.push(vscode.languages.registerDocumentRangeFormattingEditProvider(state.documentSelector, new RangeEditProvider));
vscode.window.onDidChangeActiveTextEditor(inferer.updateState);
vscode.workspace.onDidChangeConfiguration(e => {
if (e.affectsConfiguration("calva.fmt.formatAsYouType")) {
Expand Down
6 changes: 5 additions & 1 deletion src/connector.ts
Original file line number Diff line number Diff line change
Expand Up @@ -504,7 +504,11 @@ export default {
state.cursor.set('cljc', null);
status.update();

nClient.close();
if(nClient) {
// the connection may be ended before
// the REPL client was connected.
nClient.close();
}
callback();
},
toggleCLJCSession: () => {
Expand Down
19 changes: 11 additions & 8 deletions src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -120,13 +120,16 @@ function activate(context: vscode.ExtensionContext) {
context.subscriptions.push(vscode.commands.registerCommand('calva.jackIn', jackIn.calvaJackIn))
context.subscriptions.push(vscode.commands.registerCommand('calva.connectNonProjectREPL', connector.connectNonProjectREPLCommand));
context.subscriptions.push(vscode.commands.registerCommand('calva.connect', connector.connectCommand));
context.subscriptions.push(vscode.commands.registerCommand('calva.disconnect', jackIn.calvaDisonnect));
context.subscriptions.push(vscode.commands.registerCommand('calva.disconnect', jackIn.calvaDisconnect));
context.subscriptions.push(vscode.commands.registerCommand('calva.toggleCLJCSession', connector.toggleCLJCSession));
context.subscriptions.push(vscode.commands.registerCommand('calva.switchCljsBuild', connector.switchCljsBuild));
context.subscriptions.push(vscode.commands.registerCommand('calva.selectCurrentForm', select.selectCurrentForm));
context.subscriptions.push(vscode.commands.registerCommand('calva.loadFile', () => {
EvaluateMiddleWare.loadFile();
chan.show(true);
EvaluateMiddleWare.loadFile().then((resolved) => {
chan.show(true);
}).catch((reason) => {
chan.show(true);
});
}));
context.subscriptions.push(vscode.commands.registerCommand('calva.evaluateSelection', EvaluateMiddleWare.evaluateCurrentForm));
context.subscriptions.push(vscode.commands.registerCommand('calva.evaluateCurrentTopLevelForm', EvaluateMiddleWare.evaluateTopLevelForm));
Expand Down Expand Up @@ -157,15 +160,15 @@ function activate(context: vscode.ExtensionContext) {

// Initial set of the provided contexts
vscode.commands.executeCommand("setContext", "calva:replWindowActive", false);
vscode.commands.executeCommand("setContext", "calva:launching", false);
vscode.commands.executeCommand("setContext", "calva:connected", false);
vscode.commands.executeCommand("setContext", "calva:connecting", false);
vscode.commands.executeCommand("setContext", "calva:pareditValid", false);


// PROVIDERS
context.subscriptions.push(vscode.languages.registerCompletionItemProvider(state.mode, new CalvaCompletionItemProvider()));
context.subscriptions.push(vscode.languages.registerHoverProvider(state.mode, new HoverProvider()));
context.subscriptions.push(vscode.languages.registerDefinitionProvider(state.mode, useWSL ? new WslDefinitionProvider() : new DefinitionProvider()));
context.subscriptions.push(vscode.languages.registerCompletionItemProvider(state.documentSelector, new CalvaCompletionItemProvider()));
context.subscriptions.push(vscode.languages.registerHoverProvider(state.documentSelector, new HoverProvider()));
context.subscriptions.push(vscode.languages.registerDefinitionProvider(state.documentSelector, useWSL ? new WslDefinitionProvider() : new DefinitionProvider()));

vscode.workspace.registerTextDocumentContentProvider('jar', new TextDocumentContentProvider());

Expand Down Expand Up @@ -227,7 +230,7 @@ function activate(context: vscode.ExtensionContext) {

for (const config of ["enableBracketColors", "bracketColors", "cycleBracketColors", "misplacedBracketStyle", "matchedBracketStyle", "commentFormStyle", "ignoredFormStyle"]) {
if (cwConfig.get(config) !== undefined) {
vscode.window.showWarningMessage("Legacy Clojure Warrior settings detected. These settings have changed prefix/namespace from `clojureWarrior´ to `calva.highlight`. You should update `settings.json`.", ...["Roger that!"]);
vscode.window.showWarningMessage("Legacy Clojure Warrior settings detected. These settings have changed prefix/namespace to from `clojureWarrior´ to `calva.highlight`. You should update `settings.json`.", ...["Roger that!"]);
break;
}
}
Expand Down
36 changes: 23 additions & 13 deletions src/highlight/src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -174,10 +174,11 @@ export function activate(context: vscode.ExtensionContext) {
let match,
in_string = false,
in_comment = false,
in_ignore = false,
ignore_counter = 0,
ignore_start: Position,
ignored_text_start: Position,
ignored_list_opened = false,
ignore_pushed_by_closing = false,
in_comment_form = false,
stack = [],
stack_depth = 0;
Expand All @@ -198,16 +199,22 @@ export function activate(context: vscode.ExtensionContext) {
} else if (char === "\"") {
in_string = true;
continue;
} else if (char.startsWith("#_") && !in_ignore) {
in_ignore = true;
ignore_start = activeEditor.document.positionAt(match.index);
} else if (char.startsWith("#_")) {
if (ignore_counter == 0) {
ignore_start = activeEditor.document.positionAt(match.index);
}
ignored_text_start = activeEditor.document.positionAt(match.index + char.length);
ignore_counter++
continue;
} else if (char.match(/[\s,]+/)) {
if (in_ignore && !ignored_list_opened) {
in_ignore = false;
ignores.push(new Range(ignore_start, activeEditor.document.positionAt(match.index)));
} else if (char.match(/^[\s,]+$/)) {
if (ignore_counter > 0 && !ignored_list_opened) {
ignored_text_start = activeEditor.document.positionAt(match.index + char.length);
if (!ignore_pushed_by_closing) {
ignore_counter--;
ignores.push(new Range(ignore_start, activeEditor.document.positionAt(match.index)));
}
}
ignore_pushed_by_closing = false;
continue;
} else {
if (!in_comment_form && char === "comment" && stack[stack.length - 1].char === "(") {
Expand All @@ -222,9 +229,10 @@ export function activate(context: vscode.ExtensionContext) {
rainbow[colorIndex(stack_depth)].push(decoration);
}
++stack_depth;
const opens_ignore = in_ignore && !ignored_list_opened && pos.isEqual(ignored_text_start);
if (opens_ignore)
ignored_list_opened = true;
const opens_ignore = ignore_counter > 0 && !ignored_list_opened && pos.isEqual(ignored_text_start);
if (opens_ignore) {
ignored_list_opened = opens_ignore;
}
stack.push({ char: char, pos: pos, pair_idx: undefined, opens_comment_form: false, opens_ignore: opens_ignore });
continue;
} else if (closing[char]) {
Expand All @@ -244,11 +252,13 @@ export function activate(context: vscode.ExtensionContext) {
comment_forms.push(new Range(pair.pos, pos.translate(0, char.length)));
in_comment_form = false;
}
if (in_ignore && (pair.opens_ignore || !ignored_list_opened)) {
if (ignore_counter > 0 && (pair.opens_ignore || !ignored_list_opened)) {
const ignore_end = ignored_list_opened ? pos.translate(0, char.length) : pos;
ignore_counter--;
ignores.push(new Range(ignore_start, ignore_end));
in_ignore = false;
ignored_list_opened = false;
ignored_text_start = activeEditor.document.positionAt(match.index + char.length);
ignore_pushed_by_closing = true;
}
stack.push({ char: char, pos: pos, pair_idx: pair_idx });
for (let i = 0; i < char.length; ++i)
Expand Down
2 changes: 1 addition & 1 deletion src/nrepl/connectSequence.ts
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,7 @@ async function askForConnectSequence(cljTypes: string[], saveAs: string, logLabe
saveAs: `${state.getProjectRoot()}/${saveAs}`,
autoSelect: true
});
if (!projectConnectSequenceName) {
if (!projectConnectSequenceName || projectConnectSequenceName.length <= 0) {
state.analytics().logEvent("REPL", logLabel, "NoProjectTypePicked").send();
return;
}
Expand Down
6 changes: 3 additions & 3 deletions src/nrepl/index.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import * as net from "net";
import { BEncoderStream, BDecoderStream } from "./bencode";
import * as state from '../state';
import * as replWindow from '../repl-window';
import * as state from './../state';
import * as replWindow from './../repl-window';

/** An nRREPL client */
export class NReplClient {
Expand Down Expand Up @@ -291,8 +291,8 @@ export class NReplSession {
}

loadFile(file: string, opts: { fileName?: string, filePath?: string, stderr?: (x: string) => void, stdout?: (x: string) => void } = {}) {

let id = this.client.nextId;

let evaluation = new NReplEvaluation(id, this, opts.stderr, opts.stdout, new Promise((resolve, reject) => {
this.messageHandlers[id] = (msg) => {
if (msg.value)
Expand Down
Loading

0 comments on commit 0e1fed1

Please sign in to comment.