19 |
20 | As you can see on the screenshot, VS Code will also reveal the keyboard shortcut for the command. My advice is to make it a habit to try to remember those shortcuts and use them for a more effective workflow.
21 |
22 | Now might be a good time to see [Calva Top 10 Commands](commands-top10.md)
23 |
24 | ## All the Settings and Commands
25 |
26 | Did you know? There is a complete list of Calva settings and commands in the *Contributions* tab of the Calva entry in the *Extensions* pane in VS Code.
27 |
28 | 
29 |
--------------------------------------------------------------------------------
/test-data/projects/pirate-lang/src/pez/pirate_lang.clj:
--------------------------------------------------------------------------------
1 | (ns pez.pirate-lang
2 | (:require [clojure.string :as string]))
3 |
4 | (def english-o {:alphabet "abcdefghijklmnopqrstuvwxyz"
5 | :vowels "aeiou"
6 | :pirate-char "o"})
7 |
8 | (defn- configure
9 | [{:keys [alphabet vowels pirate-char]}]
10 | (let [alphabet (set (seq (string/upper-case alphabet)))
11 | vowels (set (seq (string/upper-case vowels)))
12 | consonants (set (remove vowels alphabet))
13 | pirates (if (vowels pirate-char)
14 | vowels
15 | consonants)]
16 | {:pirate-char pirate-char
17 | :pirates pirates}))
18 |
19 | (defn to-pirate-talk
20 | [text language]
21 | (let [{:keys [pirate-char pirates]} (configure language)]
22 | (apply str (mapcat (fn [c]
23 | (if (pirates (first (string/upper-case c)))
24 | (interpose pirate-char (repeat 2 c))
25 | [c]))
26 | text))))
27 |
28 | (defn from-pirate-talk
29 | [text language]
30 | (let [{:keys [pirate-char pirates]} (configure language)
31 | pattern (re-pattern (str "(?i)([" (apply str pirates) "])" pirate-char "\\1"))]
32 | (string/replace text pattern "$1")))
33 |
34 | (comment
35 | (to-pirate-talk "Have you heard about Pirate talk?" english-o)
36 | ;; => "HoHavove yoyou hohearordod aboboutot PoPiroratote totalolkok?"
37 |
38 | (from-pirate-talk "HoHavove yoyou hohearordod aboboutot PoPiroratote totalolkok?" english-o)
39 | ;; => "Have you heard about Pirate talk?"
40 | )
--------------------------------------------------------------------------------
/src/cljs-lib/test/calva/fmt/util_test.cljs:
--------------------------------------------------------------------------------
1 | (ns calva.fmt.util-test
2 | (:require [cljs.test :include-macros true :refer [deftest is]]
3 | [calva.fmt.util :as sut]))
4 |
5 |
6 | #_(deftest log
7 | (is (= (with-out-str (sut/log {:range-text ""} :range-text))
8 | {:range-text ""})))
9 |
10 |
11 | (def all-text "(def a 1)
12 |
13 |
14 | (defn foo [x] (let [bar 1]
15 |
16 | bar))")
17 |
18 |
19 | (deftest current-line
20 | (is (= "(def a 1)" (sut/current-line all-text 0)))
21 | (is (= "(def a 1)" (sut/current-line all-text 4)))
22 | (is (= "(def a 1)" (sut/current-line all-text 9)))
23 | (is (= "" (sut/current-line all-text 10)))
24 | (is (= "" (sut/current-line all-text 11)))
25 | (is (= "(defn foo [x] (let [bar 1]" (sut/current-line all-text 12)))
26 | (is (= "(defn foo [x] (let [bar 1]" (sut/current-line all-text 27)))
27 | (is (= "(defn foo [x] (let [bar 1]" (sut/current-line all-text 38)))
28 | (is (= "" (sut/current-line all-text 39)))
29 | (is (= "bar))" (sut/current-line all-text (count all-text)))))
30 |
31 |
32 | (deftest re-pos-one
33 | (is (= 6
34 | (sut/re-pos-first "\\s*x\\s*t$" "foo te x t")))
35 | (is (= 6
36 | (sut/re-pos-first "\\s*x\\s*t$" "foo te x t")))
37 | (is (= 5
38 | (sut/re-pos-first "\\s*e\\s*xt\\s*$" "foo te xt")))
39 | (is (= 173
40 | (sut/re-pos-first "\"\\s*#\\s*\"\\)$" "(create-state \"\"
41 | \"### \"
42 | \" ###\"
43 | \" ### \"
44 | \" # \")"))))
45 |
46 |
47 | (deftest escape-regexp
48 | (is (= "\\.\\*"
49 | (sut/escape-regexp ".*"))))
50 |
--------------------------------------------------------------------------------
/src/calva-fmt/src/providers/ontype_formatter.ts:
--------------------------------------------------------------------------------
1 | import * as vscode from 'vscode';
2 | import * as formatter from '../format';
3 |
4 | function continueComment(editor: vscode.TextEditor, document: vscode.TextDocument, position: vscode.Position): Thenable
45 |
46 | The items are numbered for you so that you can choose them in predictable way. The default keyboard shortcut for the command is ctrl+alt+c, .. Which means that to execute the **Refresh** command, `(refresh)`, in the `clj` REPL, you could do:
47 |
48 | ctrl+alt+c, ., 3, ENTER.
--------------------------------------------------------------------------------
/assets/styles/_theme-dark.scss:
--------------------------------------------------------------------------------
1 | body.vscode-dark {
2 | .winnage {
3 | color: #0f0;
4 | }
5 |
6 | .match {
7 | border-color: #777;
8 | color: tomato;
9 | }
10 |
11 | .fail-match {
12 | background-color: #f00;
13 | }
14 |
15 | .documentation {
16 | box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.16);
17 | }
18 |
19 | .completion {
20 | box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.16);
21 | }
22 |
23 | .completion .icon {
24 | text-shadow: 0px 1px rgba(0, 0, 0, 0), 0px -1px rgba(0, 0, 0, 0), -1px 0px rgba(0, 0, 0, 0),
25 | 1px 0px rgba(0, 0, 0, 0);
26 | }
27 |
28 | .completion .icon.ic-macro::before {
29 | color: #f80;
30 | }
31 |
32 | .completion .icon.ic-function::before {
33 | color: #f0f;
34 | }
35 | .completion .icon.ic-namespace::before {
36 | color: #080;
37 | }
38 | .completion .icon.ic-special-form::before {
39 | color: #08a;
40 | }
41 |
42 | .caret {
43 | border: solid 1px #aaa;
44 | }
45 |
46 | .is-focused .caret {
47 | border: solid 1px rgba(0, 0, 0, 0);
48 | background-color: #fff;
49 | }
50 |
51 | .id {
52 | color: #d4d4d4;
53 | }
54 |
55 | .kw {
56 | color: #9cdcfe;
57 | }
58 |
59 | .comment {
60 | color: #6a9955;
61 | }
62 |
63 | .lit {
64 | color: #b5cea8;
65 | }
66 |
67 | .str,
68 | .str-start,
69 | .str-inside,
70 | .str-end {
71 | color: #ce9178;
72 | }
73 |
74 | .decl {
75 | color: #c586c0;
76 | }
77 |
78 | .macro {
79 | color: #569cd6;
80 | }
81 |
82 | .stacktrace .stack .name {
83 | color: #fff;
84 | }
85 |
86 | .toggle {
87 | color: #aaa;
88 | }
89 |
90 | .stacktrace.dup .toggle.dup {
91 | color: #666;
92 | }
93 | .stacktrace.java .toggle.java {
94 | color: #666;
95 | }
96 | .stacktrace.tooling .toggle.tooling {
97 | color: #666;
98 | }
99 | .stacktrace.clj .toggle.clj {
100 | color: #666;
101 | }
102 |
103 | .no-source {
104 | opacity: 0.6;
105 | }
106 | }
--------------------------------------------------------------------------------
/src/calva-fmt/atom-language-clojure/snippets/language-clojure.cson:
--------------------------------------------------------------------------------
1 | '.source.clojure':
2 | 'ns':
3 | 'prefix': 'ns'
4 | 'body': """
5 | (ns ${1:name}
6 | (:require [${2:libraries}]))
7 | $0
8 | """
9 |
10 | 'def':
11 | 'prefix': 'def'
12 | 'body': '(def ${1:symbol} ${2:value})'
13 |
14 | 'defn':
15 | 'prefix': 'defn'
16 | 'body': """
17 | (defn ${1:name}
18 | [${2:params}]
19 | ${3:body})
20 | """
21 |
22 | 'fn':
23 | 'prefix': 'fn'
24 | 'body': """
25 | (fn [${1:params}]
26 | ${2:body})$0
27 | """
28 |
29 | 'let':
30 | 'prefix': 'let'
31 | 'body': """
32 | (let [${1:bindings}]
33 | ${2:body})
34 | """
35 |
36 | 'if':
37 | 'prefix': 'if'
38 | 'body': """
39 | (if ${1:test}
40 | ${2:then}
41 | ${3:else})
42 | """
43 |
44 | 'if-let':
45 | 'prefix': 'ifl'
46 | 'body': """
47 | (if-let [${1:bindings}]
48 | ${2:then}
49 | ${3:else})
50 | """
51 |
52 | 'if-not':
53 | 'prefix': 'ifn'
54 | 'body': """
55 | (if-not ${1:test}
56 | ${2:then}
57 | ${3:else})
58 | """
59 |
60 | 'when':
61 | 'prefix': 'when'
62 | 'body': """
63 | (when ${1:test}
64 | ${2:body})
65 | """
66 |
67 | 'when-let':
68 | 'prefix': 'whenl'
69 | 'body': """
70 | (when-let [${1:bindings}]
71 | ${2:body})
72 | """
73 |
74 | 'when-not':
75 | 'prefix': 'whenn'
76 | 'body': """
77 | (when-not ${1:test}
78 | ${2:body})
79 | """
80 |
81 | 'map':
82 | 'prefix': 'map'
83 | 'body': '(map $1 $2)'
84 |
85 | 'map lambda':
86 | 'prefix': 'mapl'
87 | 'body': '(map #($1) $2)'
88 |
89 | 'condp':
90 | 'prefix': 'condp'
91 | 'body': """
92 | (condp ${1:pred} ${2:expr}
93 | $0)
94 | """
95 |
96 | 'try':
97 | 'prefix': 'try'
98 | 'body': """
99 | (try
100 | $1
101 | (catch ${2:exception} e
102 | $3))
103 | """
104 |
105 | 'prn':
106 | 'prefix': 'prn'
107 | 'body': '(prn $1)'
108 |
109 | 'println':
110 | 'prefix': 'prnl'
111 | 'body': '(println $1)'
112 |
--------------------------------------------------------------------------------
/assets/styles/_theme-light.scss:
--------------------------------------------------------------------------------
1 | body.vscode-light {
2 | .winnage {
3 | color: #0c0;
4 | }
5 |
6 | .match {
7 | border-color: #777;
8 | color:deepskyblue;
9 | }
10 |
11 | .fail-match {
12 | background-color: #c00;
13 | }
14 |
15 | .documentation {
16 | box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.16);
17 | }
18 |
19 | .completion {
20 | box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.16);
21 | }
22 |
23 | .completion .icon {
24 | text-shadow: 0px 1px rgba(0, 0, 0, 0), 0px -1px rgba(0, 0, 0, 0), -1px 0px rgba(0, 0, 0, 0),
25 | 1px 0px rgba(0, 0, 0, 0);
26 | }
27 |
28 | .completion .icon.ic-macro::before {
29 | color: #f80;
30 | }
31 |
32 | .completion .icon.ic-function::before {
33 | color: #f0f;
34 | }
35 | .completion .icon.ic-namespace::before {
36 | color: #080;
37 | }
38 | .completion .icon.ic-special-form::before {
39 | color: #08a;
40 | }
41 |
42 | .caret {
43 | border: solid 1px #aaa;
44 | }
45 |
46 | .is-focused .caret {
47 | border: solid 1px rgba(0, 0, 0, 0);
48 | background-color: #3b3b3b;
49 | }
50 |
51 | .id {
52 | color: #000;
53 | }
54 |
55 | .kw {
56 | color: #b9008b;
57 | }
58 |
59 | .comment {
60 | color: #008000;
61 | }
62 |
63 | .lit {
64 | color: #008d2a;
65 | }
66 |
67 | .str,
68 | .str-start,
69 | .str-inside,
70 | .str-end {
71 | color: #a31515;
72 | }
73 |
74 | .decl {
75 | color: #c800fa;
76 | }
77 |
78 | .macro {
79 | color: #0026ff;
80 | }
81 |
82 | .stacktrace .stack .name {
83 | color: #000;
84 | }
85 |
86 | .toggle {
87 | color: #555;
88 | }
89 |
90 | .stacktrace.dup .toggle.dup {
91 | color: #999;
92 | }
93 | .stacktrace.java .toggle.java {
94 | color: #999;
95 | }
96 | .stacktrace.tooling .toggle.tooling {
97 | color: #999;
98 | }
99 | .stacktrace.clj .toggle.clj {
100 | color: #999;
101 | }
102 |
103 | .no-source {
104 | opacity: 0.5;
105 | }
106 | }
107 |
--------------------------------------------------------------------------------
/src/extension-test/unit/debugger/util-test.ts:
--------------------------------------------------------------------------------
1 | import { expect } from 'chai';
2 | import { moveTokenCursorToBreakpoint } from '../../../debugger/util';
3 | import * as mock from '../common/mock';
4 | import * as fs from "fs";
5 |
6 | function getCoordinates(text: string): (string | number)[] {
7 | return text.split('\n')[0].split(',').map(s => {
8 | const coor = s.replace(/;/g, '').trim();
9 | if (coor.startsWith('"')) {
10 | return coor.replace(/"/g, '');
11 | } else {
12 | return parseInt(coor);
13 | }
14 | });
15 | }
16 |
17 | function getTestFileText(fileName: string): string {
18 | return fs.readFileSync(__dirname + '/test-files/' + fileName, 'utf8');
19 | }
20 |
21 | describe('Debugger Util', async () => {
22 |
23 | let doc: mock.MockDocument;
24 | let debugResponse: any;
25 |
26 | beforeEach(() => {
27 | doc = new mock.MockDocument();
28 |
29 | debugResponse = {
30 | line: 0,
31 | column: 0
32 | };
33 | });
34 |
35 | describe('moveTokenCursorToBreakpoint', () => {
36 |
37 | function expectBreakpointToBeFound(fileName: string) {
38 | const docText = getTestFileText(fileName);
39 | debugResponse.coor = getCoordinates(docText);
40 | doc.insertString(docText);
41 | const tokenCursor = doc.getTokenCursor(0);
42 | moveTokenCursorToBreakpoint(tokenCursor, debugResponse);
43 | expect(tokenCursor.getPrevToken().raw.endsWith('|')).equals(true);
44 | }
45 |
46 | it('simple example', () => {
47 | expectBreakpointToBeFound('simple.clj');
48 | });
49 |
50 | it('function shorthand', () => {
51 | expectBreakpointToBeFound('fn-shorthand.clj');
52 | });
53 |
54 | it('map', () => {
55 | expectBreakpointToBeFound('map.clj');
56 | });
57 |
58 | it('metadata symbol', () => {
59 | expectBreakpointToBeFound('metadata-symbol.clj');
60 | });
61 |
62 | it('ignored forms', () => {
63 | expectBreakpointToBeFound('ignored-forms.clj');
64 | });
65 |
66 | it('syntax quote', () => {
67 | expectBreakpointToBeFound('syntax-quote.clj');
68 | });
69 | });
70 | });
71 |
--------------------------------------------------------------------------------
/test-data/test.clj:
--------------------------------------------------------------------------------
1 | ;; Clojure Warrior
2 |
3 | (())
4 | (((((((((((((((((((())))))))))))))))))))
5 | [[[[[[[[[[[[[[[[[[[[]]]]]]]]]]]]]]]]]]]]
6 | {{{{{{{{{{{{{{{{{{{{}}}}}}}}}}}}}}}}}}}}
7 | ((()))[[[]]]
8 | ([{}])
9 | ()
10 | []
11 | {}
12 |
13 | ("--)--")
14 | ("--)--
15 | --)--")
16 | ();;---)
17 |
18 | (\)\()
19 | ("--\"--)--")
20 | ;; ((()))
21 | ;; ())) "a[{(]})bc"
22 | ;; \
23 | "()"
24 | ;; \
25 | ;;
26 | (((#((())))))
27 | ([ #{ }()[]])
28 |
29 |
30 | (
31 | #()
32 | #{}
33 | #?()
34 | #?@()
35 | #_())
36 |
37 | (if comment :a :b)
38 |
39 | (comment
40 | (comment (foo bar)))
41 | (defn foo
42 | (let [x "y"]
43 | {:foo "bar"
44 | :bar (comment (fn [x]
45 | (let [foo :bar])
46 | (str foo)))
47 | :baz x}))
48 | (comment
49 | (foo 2)
50 | (Math/abs -1)
51 | (range 10)
52 | (println "I ❤️Clojure")
53 | ([{} () []]))
54 | [comment]
55 | (foo) comment (bar)
56 | "(comment foo)"
57 | foo(comment)bar
58 | (def contains-comment (go-fish))
59 | ( comment)
60 | (
61 | comment "[foo]")
62 | (comment
63 | (Math/abs -1)
64 | (range 10)
65 | (println "I ❤️Clojure")
66 | ([{} () []]))
67 | ( comment
68 | foo)
69 | (comment foo (comment bar))
70 | (foo (comment ({["(comment)"]})) ([{"(comment)"}]))
71 |
72 | #_foo bar
73 | #_ foo bar
74 | #_,foo,bar
75 | #_
76 | foo bar
77 | #_
78 | foo
79 | bar
80 |
81 | #_#_(1) (2 2)
82 |
83 | #_
84 | #_
85 | #_
86 |
87 | 1
88 |
89 | 2
90 |
91 | 3
92 | 4
93 |
94 | #_
95 | #_
96 | 2
97 | (1 (1))
98 | 3
99 |
100 | #_
101 | #_
102 | #_
103 | 1
104 | (2 (2))
105 | (3 3)
106 | 4
107 |
108 | #_#_#_#(1) 2 (3 4) (4) 5
109 |
110 | #_#_#_ (1) (2) (3 4) (4) 5
111 |
112 | #_ (1)2(3) (4)
113 |
114 | #_1(2)
115 |
116 | (let [#_#_x (get c :x "x")
117 | y (get c :y "y")
118 | #_ #_ z (get c :z "z")
119 | å {:ä :ö}]
120 | (str y å #_#_x z))
121 |
122 | #_x y z
123 |
124 | #_(:bar [#{foo}])
125 | ([{#_"foo"}])
126 | [:a
127 | #_
128 | [:b
129 | [:c {:d :e}]]
130 | [:b
131 | [:c {:d :e}]]]
132 | (comment
133 | (foo #_"bar" baz))
134 | #_{:foo "foo"
135 | :bar (comment [["bar"]])}
136 | #_^{:foo foo} ^{:foo foo}
137 | #_@foo @foo
138 | #_@(foo bar) @(foo bar)
139 | #_'(foo bar) '(foo bar)
140 | #_`(foo bar) `(foo bar)
141 | #_~(foo bar) ~(foo bar)
142 | #_'foo 'foo
143 | #_#foo #foo
144 | #_@foo @foo
145 | #_~foo ~foo
146 | #_#"foo\sbar" #"foo\sbar"
--------------------------------------------------------------------------------
/todo.org:
--------------------------------------------------------------------------------
1 | * DONE Migrate testRunner to use nrepl, and clean up
2 | * DONE Migrate connect, and add cljs support
3 | * DONE send cljs stuff to the right repl
4 | * DONE add pretty printing back to evaluate
5 | * DONE Move paredit here
6 | * DONE Bind paredit keys to Repl console
7 | * DONE Jack-in
8 | * DONE clj
9 | * DONE boot
10 | * DONE shadow-cljs - select watch project(s)
11 | * DONE lein
12 |
13 | * DONE Save as workspace configuration.
14 |
15 | * DONE kill/restart jack-in process command
16 |
17 | * DONE Cljs repls
18 | * DONE figwheel
19 | * DONE figwheel-main
20 | * DONE shadow-cljs
21 | * DONE inject piggieback
22 | * DONE { :repl-options {:nrepl-middleware [cider.piggieback/wrap-cljs-repl]}} in lein
23 | * DONE clj
24 |
25 | * DONE prompt for clj aliases
26 | * DONE prompt for lein profiles
27 |
28 | * DONE fix repl window to show stack traces
29 | * DONE add interrupt support to repl window
30 | * DONE make it clear that a repl window session has been disconnected.
31 | * DONE replace eval to terminal stuff with new repl stuff.
32 | * DONE re-connect repl window session when reconnected.
33 | * DONE support session disconnection messages - route them to the right window.
34 | * DONE webviews do not receive postMessages when not in the foreground. buffer them and blast them when it focuses.
35 | * DONE repl focus needs to be made sane.
36 | * DONE hollow cursor when not focused.
37 | * DONE don't snatch focus away from selection
38 | * DONE update status.update() to show repl type when focused.
39 | * DONE Repl completions
40 | * DONE context!
41 | * DONE up/down navigate completion
42 | * DONE tab complete
43 | * DONE documentation
44 | * DONE PageUp/PageDown in completion pane
45 | * DONE Only show completions on type or Ctrl+Space (repl-interactor support)
46 | * DONE Use tonsky font in project, don't use cdn...
47 | * DONE Preserve Repl history.
48 | * DONE clj/cljs status notification bugged with webviews because vscode is buggy.
49 | * DONE Open new cljs repl
50 | * TODO Ship first stab at repl?
51 |
52 | * DONE Move calva-fmt here.
53 | * DONE Use model from repl-interactor in vscode
54 | * TODO Select toplevel forms etc, should use model <<<<
55 | * TODO Use our Paredit logic for calva proper.
56 | * TODO Complete Jack-in
57 | * TODO Argument-based completions for vscode
58 | * TODO Remove diagnostics in docmirror that ensure the model doesn't desync from the document.
--------------------------------------------------------------------------------
/src/analytics.ts:
--------------------------------------------------------------------------------
1 | import * as vscode from 'vscode';
2 | import * as UA from 'universal-analytics';
3 | import * as uuid from "uuid/v4";
4 | import * as os from 'os';
5 |
6 | // var debug = require('debug');
7 | // debug.log = console.info.bind(console);
8 |
9 |
10 | function userAllowsTelemetry(): boolean {
11 | const config = vscode.workspace.getConfiguration('telemetry');
12 | return config.getThe REPL prompt is a multiline, Paredit powered, Clojure editor. Some useful shortcuts are: 33 |
Make it a habit to start any Calva session by loading a file. 43 | Use Ctrl+Alt+C Enter in the code editor to load (evaluate) the active file. 44 | Many things do not work before that is done. 45 |
46 |See also the Calva User Documentation.
47 |