From 1ee7c49fdb1ddedc3db197408050cca16924e423 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Peter=20Str=C3=B6mberg?= Date: Mon, 18 Oct 2021 20:51:00 +0200 Subject: [PATCH 01/23] WIP add clojuredocs command --- package.json | 6 ++++++ src/clojuredocs.ts | 43 +++++++++++++++++++++++++++++++++++++++++++ src/connector.ts | 3 +++ src/extension.ts | 2 ++ src/nrepl/index.ts | 22 ++++++++++++++++++++++ 5 files changed, 76 insertions(+) create mode 100644 src/clojuredocs.ts diff --git a/package.json b/package.json index bb2ec61be..e8a113f4c 100644 --- a/package.json +++ b/package.json @@ -1437,6 +1437,12 @@ "enablement": "calva:connected", "category": "Calva" }, + { + "command": "calva.clojureDocsLookup", + "title": "Lookup ClojureDocs examples", + "enablement": "calva:connected", + "category": "Calva" + }, { "command": "calva.refactor.cleanNs", "title": "Clean NS Form", diff --git a/src/clojuredocs.ts b/src/clojuredocs.ts new file mode 100644 index 000000000..b53acb8c6 --- /dev/null +++ b/src/clojuredocs.ts @@ -0,0 +1,43 @@ +import * as vscode from 'vscode'; +import annotations from './providers/annotations'; +import * as util from './utilities'; +import { NReplSession, NReplEvaluation } from './nrepl'; +import * as outputWindow from './results-output/results-doc'; +import * as namespace from './namespace'; +import { getConfig } from './config'; +import * as replSession from './nrepl/repl-session'; +import * as getText from './util/get-text'; + + +export function init(cljSession: NReplSession) { + cljSession.clojureDocsRefreshCache().catch(reason => { + console.error("Error refreshing ClojureDocs cache: ", reason); + }); +} + +export async function clojureDocsLookupSymbol(symbol: string) { + const doc = util.getDocument({}); + const ns = namespace.getNamespace(doc); + //const session = replSession.getSession(util.getFileType(doc)); + const session = replSession.getSession("clj"); + const docs = await session.clojureDocsLookup(ns, symbol); + console.log(docs); +} + +export async function clojureDocsLookup() { + const doc = util.getDocument({}); + const position = vscode.window.activeTextEditor.selection.active; + const symbol = util.getWordAtPosition(doc, position); + + await clojureDocsLookupSymbol(symbol); +} + +//export function getHoverText() { +// const copyCommandUri = `command:calva.copyAnnotationHoverText?${encodeURIComponent(JSON.stringify([{ text: resultString }]))}`, +// copyCommandMd = `[Copy](${copyCommandUri} "Copy results to the clipboard")`; +// const openWindowCommandUri = `command:calva.showOutputWindow`, +// openWindowCommandMd = `[Open Output Window](${openWindowCommandUri} "Open the output window")`; +// const hoverMessage = new vscode.MarkdownString(`${copyCommandMd} | ${openWindowCommandMd}\n` + '```clojure\n' + resultString + '\n```'); +// hoverMessage.isTrusted = true; +// decoration["hoverMessage"] = status == AnnotationStatus.ERROR ? resultString : hoverMessage; +//} \ No newline at end of file diff --git a/src/connector.ts b/src/connector.ts index 7fef50a28..55108d707 100644 --- a/src/connector.ts +++ b/src/connector.ts @@ -16,6 +16,7 @@ import * as liveShareSupport from './liveShareSupport'; import * as calvaDebug from './debugger/calva-debug'; import { setStateValue, getStateValue } from '../out/cljs-lib/cljs-lib'; import * as replSession from './nrepl/repl-session'; +import * as clojureDocs from './clojuredocs'; async function connectToHost(hostname: string, port: number, connectSequence: ReplConnectSequence) { state.analytics().logEvent("REPL", "Connecting").send(); @@ -69,6 +70,8 @@ async function connectToHost(hostname: string, port: number, connectSequence: Re outputWindow.appendPrompt(); + clojureDocs.init(cljSession); + let cljsSession = null, cljsBuild = null; try { diff --git a/src/extension.ts b/src/extension.ts index a85b9b022..838871cf1 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -35,6 +35,7 @@ import { setStateValue } from '../out/cljs-lib/cljs-lib'; import * as edit from './edit'; import * as nreplLogging from './nrepl/logging'; +import * as clojureDocs from './clojuredocs'; async function onDidSave(document) { let { evaluate, @@ -225,6 +226,7 @@ async function activate(context: vscode.ExtensionContext) { })) context.subscriptions.push(vscode.commands.registerCommand('calva.continueComment', edit.continueCommentCommand)); context.subscriptions.push(vscode.commands.registerCommand('calva.diagnostics.toggleNreplLoggingEnabled', nreplLogging.toggleEnabled)); + context.subscriptions.push(vscode.commands.registerCommand('calva.clojureDocsLookup', clojureDocs.clojureDocsLookup)); // Initial set of the provided contexts outputWindow.setContextForOutputWindowActive(false); diff --git a/src/nrepl/index.ts b/src/nrepl/index.ts index 9bff916bb..c630c565f 100644 --- a/src/nrepl/index.ts +++ b/src/nrepl/index.ts @@ -605,6 +605,28 @@ export class NReplSession { this.client.write({ op: 'debug-instrumented-defs', id, session: this.sessionId }); }); } + + clojureDocsRefreshCache() { + return new Promise((resolve, reject) => { + let id = this.client.nextId; + this.messageHandlers[id] = (msg) => { + resolve(msg); + return true; + } + this.client.write({ op: "clojuredocs-refresh-cache", id, session: this.sessionId }); + }) + } + + clojureDocsLookup(ns: string, symbol: string) { + return new Promise((resolve, reject) => { + let id = this.client.nextId; + this.messageHandlers[id] = (msg) => { + resolve(msg); + return true; + } + this.client.write({ op: "clojuredocs-lookup", id, ns, session: this.sessionId, sym: symbol }); + }) + } } /** From 67fa3d1ff75a943827c65c3e650ee8a5bd32c5aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Peter=20Str=C3=B6mberg?= Date: Sun, 24 Oct 2021 14:40:36 +0200 Subject: [PATCH 02/23] Update spelling dictionary --- .vscode/settings.json | 55 ++++++++++++++++++++++--------------------- 1 file changed, 28 insertions(+), 27 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index 0bd335801..5bb66db27 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -3,43 +3,22 @@ "mochaExplorer.files": "src/extension-test/unit/**/*-test.ts", "mochaExplorer.require": "ts-node/register", "cSpell.words": [ - "Batsov", - "Bozhidar", - "CLJSREPL", - "Calva's", - "Cognitect", - "Dedent", - "Docstring", - "FUBAR", - "Girardi", - "Hmmm", - "Insourcing", - "Jackin", - "Jackout", - "Libspec", - "Notespace", - "OVSX", - "Pseudoterminal", - "REBL", - "REPLs", - "Sdeps", - "Sexp", - "Sexpr", - "Sexps", - "Strömberg's", - "VSIX", "ahlbrecht", "alnum", + "Alsos", "analysing", "arglist", "arglists", "autoindent", + "Batsov", "bencode", "betterthantomorrow", "bhauman", "borkdude", + "Bozhidar", "brear", "calva", + "Calva's", "chmod", "cibuilds", "circleci", @@ -49,14 +28,17 @@ "cljfx", "cljify", "cljslib", + "CLJSREPL", "clojurians", "cmdline", "codeblock", "codehilite", "codelense", + "Cognitect", "cospaia", "debugable", "debugadapter", + "Dedent", "defproject", "defun", "deref", @@ -65,12 +47,14 @@ "devtool", "devtools", "docmirror", + "Docstring", "eckstein", "eldoc", "enablement", "enablements", "entrypoint", "errored", + "être", "eval", "evals", "falsesomething", @@ -80,15 +64,21 @@ "figwheel", "filipe", "fipp", + "FUBAR", "gifs", + "Girardi", "gsub", "hacky", "highlightning", + "Hmmm", "hopperdietzel", "howto", "inferer", "infoparser", + "Insourcing", "isequal", + "Jackin", + "Jackout", "janne", "jsify", "jszip", @@ -99,17 +89,20 @@ "lein", "leiningen", "lexing", + "Libspec", "luminus", "missmatch", "mkdir", "mkdocs", "nashorn", "niclas", + "Notespace", "nrepl", "ntqry", "ontype", "openjdk", "outdent", + "OVSX", "pageview", "paredit", "paren", @@ -122,19 +115,27 @@ "preinstall", "prepending", "prewatch", + "Pseudoterminal", "randr", + "REBL", "refactorings", + "REPLs", "reponame", "ringe", "sauvala", "sbin", "scaturro", "schäfer", + "Sdeps", "seqs", + "Sexp", + "Sexpr", + "Sexps", "sivertsen", "stacktraces", "stian", "strömberg", + "Strömberg's", "suitible", "terje", "togglemode", @@ -148,10 +149,10 @@ "visibles", "vsce", "vscodevim", + "VSIX", "webpack'ed", "webpacked", "xvfb", - "zprint", - "être" + "zprint" ] } \ No newline at end of file From 7fd9415122a05099ad93da16a78f8bf9b169b69e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Peter=20Str=C3=B6mberg?= Date: Sun, 24 Oct 2021 14:40:58 +0200 Subject: [PATCH 03/23] Add DocsEntry type --- src/clojuredocs.ts | 46 ++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 38 insertions(+), 8 deletions(-) diff --git a/src/clojuredocs.ts b/src/clojuredocs.ts index b53acb8c6..3c7cb8dc0 100644 --- a/src/clojuredocs.ts +++ b/src/clojuredocs.ts @@ -8,6 +8,20 @@ import { getConfig } from './config'; import * as replSession from './nrepl/repl-session'; import * as getText from './util/get-text'; +export type DocsEntry = { + name: string; + type: string; + ns: string; + doc: string; + argsLists: string[]; + baseUrl: string; + path: string; + examples: string[]; + notes: string[]; + seeAlsos: string[]; + added: string; + tag: string; +}; export function init(cljSession: NReplSession) { cljSession.clojureDocsRefreshCache().catch(reason => { @@ -15,21 +29,37 @@ export function init(cljSession: NReplSession) { }); } -export async function clojureDocsLookupSymbol(symbol: string) { - const doc = util.getDocument({}); - const ns = namespace.getNamespace(doc); - //const session = replSession.getSession(util.getFileType(doc)); - const session = replSession.getSession("clj"); - const docs = await session.clojureDocsLookup(ns, symbol); - console.log(docs); +export async function clojureDocsCiderNReplLookup(session: NReplSession, symbol: string, ns: string): Promise { + const ciderNReplDocs = await session.clojureDocsLookup(ns, symbol); + return ciderNRepl2DocsEntry(ciderNReplDocs.clojuredocs); } export async function clojureDocsLookup() { const doc = util.getDocument({}); const position = vscode.window.activeTextEditor.selection.active; const symbol = util.getWordAtPosition(doc, position); + const ns = namespace.getNamespace(doc); + const session = replSession.getSession(util.getFileType(doc)); + + const docs = await clojureDocsCiderNReplLookup(session, symbol, ns); + console.log(docs); +} - await clojureDocsLookupSymbol(symbol); +function ciderNRepl2DocsEntry(docs: any): DocsEntry { + return { + name: docs.name, + added: docs.added, + baseUrl: 'https://clojuredocs.org/', + doc: docs.doc, + argsLists: docs.argsLists, + examples: docs.examples, + notes: docs.notes, + ns: docs.ns, + path: docs.href, + seeAlsos: docs['see-alsos'], + tag: docs.tag, + type: docs.type + } } //export function getHoverText() { From 2185102a29d77ce873c35d4d9345ce66b3b55145 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Peter=20Str=C3=B6mberg?= Date: Sun, 24 Oct 2021 17:17:46 +0200 Subject: [PATCH 04/23] Add command for printing clojredocs to repl window WIP, addressing #689 --- package.json | 4 ++-- src/clojuredocs.ts | 44 ++++++++++++++++++++++++++++++++++++-------- src/extension.ts | 2 +- 3 files changed, 39 insertions(+), 11 deletions(-) diff --git a/package.json b/package.json index e8a113f4c..40ef0cb6e 100644 --- a/package.json +++ b/package.json @@ -1438,8 +1438,8 @@ "category": "Calva" }, { - "command": "calva.clojureDocsLookup", - "title": "Lookup ClojureDocs examples", + "command": "calva.printClojureDocsToOutputWindow", + "title": "Print clojuredocs.org examples to OutputWindow", "enablement": "calva:connected", "category": "Calva" }, diff --git a/src/clojuredocs.ts b/src/clojuredocs.ts index 3c7cb8dc0..a0e2e0525 100644 --- a/src/clojuredocs.ts +++ b/src/clojuredocs.ts @@ -15,7 +15,7 @@ export type DocsEntry = { doc: string; argsLists: string[]; baseUrl: string; - path: string; + urlPath: string; examples: string[]; notes: string[]; seeAlsos: string[]; @@ -29,33 +29,61 @@ export function init(cljSession: NReplSession) { }); } -export async function clojureDocsCiderNReplLookup(session: NReplSession, symbol: string, ns: string): Promise { +export async function printClojureDocsToOutputWindow(printDocString = false) { + const docs = await clojureDocsLookup(); + if (typeof docs === 'string') { + outputWindow.append(`;; ${docs}`) + } + else { + const exampleSeparatorB = `;; ------- BEGIN EXAMPLE` + const exampleSeparatorE = `;; ------- END EXAMPLE` + const name = `;; ${docs.ns}/${docs.name}`; + const webUrl = `;; ${docs.baseUrl}/${docs.urlPath}` + const doc = docs.doc.split(/\n/).map(line => `;; ${line.replace(/^ {0,3}/, '')}`).join('\n').trim(); + const examples = docs.examples.map((example, i) => `${exampleSeparatorB} ${i+1}\n${example.trim()}\n${exampleSeparatorE} ${i+1}`).join('\n\n'); + const seeAlsos = docs.seeAlsos.map(also => `${also} - ${docs.baseUrl}/${also.replace(/\?/g, '%3F')}?`).join(`\n`); + outputWindow.append(name); + outputWindow.append(webUrl); + if (printDocString) { + outputWindow.append(doc); + } + outputWindow.append('\n;; Examples:\n'); + outputWindow.append(examples); + outputWindow.append('\n;; See also:'); + outputWindow.append(seeAlsos); + outputWindow.appendPrompt(); + } +} + +async function clojureDocsCiderNReplLookup(session: NReplSession, symbol: string, ns: string): Promise { const ciderNReplDocs = await session.clojureDocsLookup(ns, symbol); - return ciderNRepl2DocsEntry(ciderNReplDocs.clojuredocs); + if (ciderNReplDocs.clojuredocs) { + return ciderNRepl2DocsEntry(ciderNReplDocs.clojuredocs); + } + return `No docs found for: ${symbol}`; } -export async function clojureDocsLookup() { +async function clojureDocsLookup(): Promise { const doc = util.getDocument({}); const position = vscode.window.activeTextEditor.selection.active; const symbol = util.getWordAtPosition(doc, position); const ns = namespace.getNamespace(doc); const session = replSession.getSession(util.getFileType(doc)); - const docs = await clojureDocsCiderNReplLookup(session, symbol, ns); - console.log(docs); + return clojureDocsCiderNReplLookup(session, symbol, ns); } function ciderNRepl2DocsEntry(docs: any): DocsEntry { return { name: docs.name, added: docs.added, - baseUrl: 'https://clojuredocs.org/', + baseUrl: 'https://clojuredocs.org', doc: docs.doc, argsLists: docs.argsLists, examples: docs.examples, notes: docs.notes, ns: docs.ns, - path: docs.href, + urlPath: docs.href.replace(/^\/?/, ''), seeAlsos: docs['see-alsos'], tag: docs.tag, type: docs.type diff --git a/src/extension.ts b/src/extension.ts index 838871cf1..b5f4810fa 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -226,7 +226,7 @@ async function activate(context: vscode.ExtensionContext) { })) context.subscriptions.push(vscode.commands.registerCommand('calva.continueComment', edit.continueCommentCommand)); context.subscriptions.push(vscode.commands.registerCommand('calva.diagnostics.toggleNreplLoggingEnabled', nreplLogging.toggleEnabled)); - context.subscriptions.push(vscode.commands.registerCommand('calva.clojureDocsLookup', clojureDocs.clojureDocsLookup)); + context.subscriptions.push(vscode.commands.registerCommand('calva.printClojureDocsToOutputWindow', clojureDocs.printClojureDocsToOutputWindow)); // Initial set of the provided contexts outputWindow.setContextForOutputWindowActive(false); From 67287c8c929ee8ec3a4ab5887ffc535917c506bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Peter=20Str=C3=B6mberg?= Date: Sun, 24 Oct 2021 17:24:52 +0200 Subject: [PATCH 05/23] See also urls in comment --- src/clojuredocs.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/clojuredocs.ts b/src/clojuredocs.ts index a0e2e0525..9b01803ca 100644 --- a/src/clojuredocs.ts +++ b/src/clojuredocs.ts @@ -41,7 +41,7 @@ export async function printClojureDocsToOutputWindow(printDocString = false) { const webUrl = `;; ${docs.baseUrl}/${docs.urlPath}` const doc = docs.doc.split(/\n/).map(line => `;; ${line.replace(/^ {0,3}/, '')}`).join('\n').trim(); const examples = docs.examples.map((example, i) => `${exampleSeparatorB} ${i+1}\n${example.trim()}\n${exampleSeparatorE} ${i+1}`).join('\n\n'); - const seeAlsos = docs.seeAlsos.map(also => `${also} - ${docs.baseUrl}/${also.replace(/\?/g, '%3F')}?`).join(`\n`); + const seeAlsos = docs.seeAlsos.map(also => `${also} ; ${docs.baseUrl}/${also.replace(/\?/g, '%3F')}`).join(`\n`); outputWindow.append(name); outputWindow.append(webUrl); if (printDocString) { From 6293462024cc474e6c63d404c48a6ff768e3d014 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Peter=20Str=C3=B6mberg?= Date: Sun, 24 Oct 2021 18:23:20 +0200 Subject: [PATCH 06/23] Make addRichComment take optional content --- src/cursor-doc/paredit.ts | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/cursor-doc/paredit.ts b/src/cursor-doc/paredit.ts index 4ee909627..d91a40b19 100644 --- a/src/cursor-doc/paredit.ts +++ b/src/cursor-doc/paredit.ts @@ -1061,8 +1061,12 @@ export function dragSexprBackwardDown(doc: EditableDocument, p = doc.selectionRi } } -export function addRichComment(doc: EditableDocument, p = doc.selection.active) { - const richComment = '(comment\n \n )'; +function adaptContentsToRichComment(contents: string): string { + return contents.split(/\n/).map(line => ` ${line}`).join('\n').trim(); +} + +export function addRichComment(doc: EditableDocument, p = doc.selection.active, contents?: string) { + const richComment = `(comment\n${contents ? adaptContentsToRichComment(contents) : ' '}\n )`; let cursor = doc.getTokenCursor(p); const topLevelRange = rangeForDefun(doc, p, false); const isInsideForm = !(p <= topLevelRange[0] || p >= topLevelRange[1]); @@ -1079,7 +1083,7 @@ export function addRichComment(doc: EditableDocument, p = doc.selection.active) } const insertStart = cursor.offsetStart; const insideNextTopLevelFormPos = rangeToForwardDownList(doc, insertStart)[1]; - if (insideNextTopLevelFormPos !== insertStart) { + if (!contents && insideNextTopLevelFormPos !== insertStart) { const checkIfRichCommentExistsCursor = doc.getTokenCursor(insideNextTopLevelFormPos); checkIfRichCommentExistsCursor.forwardWhitespace(true); if (checkIfRichCommentExistsCursor.getToken().raw == 'comment') { From ae923308d82990abb132efdb5c6d63c9791ac5cb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Peter=20Str=C3=B6mberg?= Date: Sun, 24 Oct 2021 19:08:50 +0200 Subject: [PATCH 07/23] Add clojuredocs -> RFC command --- package.json | 16 +++++++++++++ src/clojuredocs.ts | 47 ++++++++++++++++++++++++++++----------- src/cursor-doc/paredit.ts | 2 +- src/extension.ts | 1 + 4 files changed, 52 insertions(+), 14 deletions(-) diff --git a/package.json b/package.json index 40ef0cb6e..7075696b5 100644 --- a/package.json +++ b/package.json @@ -1443,6 +1443,12 @@ "enablement": "calva:connected", "category": "Calva" }, + { + "command": "calva.printClojureDocsToRichComment", + "title": "Print clojuredocs.org examples to Rich Comment", + "enablement": "calva:connected", + "category": "Calva" + }, { "command": "calva.refactor.cleanNs", "title": "Clean NS Form", @@ -2087,6 +2093,16 @@ "key": "alt+down", "when": "calva:keybindingsEnabled && editorLangId == clojure && calva:connected && calva:outputWindowActive" }, + { + "command": "calva.printClojureDocsToOutputWindow", + "key": "ctrl+alt+o d", + "when": "calva:keybindingsEnabled && editorLangId == clojure && calva:connected" + }, + { + "command": "calva.printClojureDocsToRichComment", + "key": "ctrl+alt+r d", + "when": "calva:keybindingsEnabled && editorLangId == clojure && calva:connected" + }, { "command": "calva.runCustomREPLCommand", "key": "ctrl+alt+space enter", diff --git a/src/clojuredocs.ts b/src/clojuredocs.ts index 9b01803ca..d09c62297 100644 --- a/src/clojuredocs.ts +++ b/src/clojuredocs.ts @@ -7,6 +7,8 @@ import * as namespace from './namespace'; import { getConfig } from './config'; import * as replSession from './nrepl/repl-session'; import * as getText from './util/get-text'; +import * as docMirror from './doc-mirror/index'; +import * as paredit from './cursor-doc/paredit'; export type DocsEntry = { name: string; @@ -29,29 +31,44 @@ export function init(cljSession: NReplSession) { }); } -export async function printClojureDocsToOutputWindow(printDocString = false) { +export async function printClojureDocsToOutputWindow() { const docs = await clojureDocsLookup(); if (typeof docs === 'string') { outputWindow.append(`;; ${docs}`) } + else { + outputWindow.append(docsEntry2ClojureCode(docs)); + } + outputWindow.appendPrompt(); +} + +export async function printClojureDocsToRichComment() { + const doc = util.getDocument({}); + const mirrorDoc = docMirror.getDocument(doc); + const docs = await clojureDocsLookup(); + if (typeof docs === 'string') { + paredit.addRichComment(mirrorDoc, mirrorDoc.selection.active, `;; ${docs}`); + } + else { + paredit.addRichComment(mirrorDoc, mirrorDoc.selection.active, docsEntry2ClojureCode(docs)); + } +} + +function docsEntry2ClojureCode(docs: DocsEntry, printDocString = false): string { + if (typeof docs === 'string') { + return `;; ${docs}`; + } else { const exampleSeparatorB = `;; ------- BEGIN EXAMPLE` const exampleSeparatorE = `;; ------- END EXAMPLE` const name = `;; ${docs.ns}/${docs.name}`; - const webUrl = `;; ${docs.baseUrl}/${docs.urlPath}` + const webUrl = `;; ${docs.baseUrl}/${docs.urlPath}`; + // Not planning to print docs string, but keeping this code anyway =) const doc = docs.doc.split(/\n/).map(line => `;; ${line.replace(/^ {0,3}/, '')}`).join('\n').trim(); const examples = docs.examples.map((example, i) => `${exampleSeparatorB} ${i+1}\n${example.trim()}\n${exampleSeparatorE} ${i+1}`).join('\n\n'); const seeAlsos = docs.seeAlsos.map(also => `${also} ; ${docs.baseUrl}/${also.replace(/\?/g, '%3F')}`).join(`\n`); - outputWindow.append(name); - outputWindow.append(webUrl); - if (printDocString) { - outputWindow.append(doc); - } - outputWindow.append('\n;; Examples:\n'); - outputWindow.append(examples); - outputWindow.append('\n;; See also:'); - outputWindow.append(seeAlsos); - outputWindow.appendPrompt(); + const code = `${name}\n${webUrl}\n${printDocString ? doc + '\n' : ''}\n;; Examples:\n${examples}\n\n;; See also:\n${seeAlsos}\n`; + return code; } } @@ -60,7 +77,7 @@ async function clojureDocsCiderNReplLookup(session: NReplSession, symbol: string if (ciderNReplDocs.clojuredocs) { return ciderNRepl2DocsEntry(ciderNReplDocs.clojuredocs); } - return `No docs found for: ${symbol}`; + return `Docs lookup failed: ${symbol ? 'Only Clojure core (ish) symbols supported' : 'Cursor not at a Clojure core (ish) symbol'}`; } async function clojureDocsLookup(): Promise { @@ -70,6 +87,10 @@ async function clojureDocsLookup(): Promise { const ns = namespace.getNamespace(doc); const session = replSession.getSession(util.getFileType(doc)); + if (session.replType !== 'clj') { + vscode.window.showErrorMessage('Clojuredocs Lookup is currently only supported with Clojure REPLs.'); + } + return clojureDocsCiderNReplLookup(session, symbol, ns); } diff --git a/src/cursor-doc/paredit.ts b/src/cursor-doc/paredit.ts index d91a40b19..8a4dfe592 100644 --- a/src/cursor-doc/paredit.ts +++ b/src/cursor-doc/paredit.ts @@ -1066,7 +1066,7 @@ function adaptContentsToRichComment(contents: string): string { } export function addRichComment(doc: EditableDocument, p = doc.selection.active, contents?: string) { - const richComment = `(comment\n${contents ? adaptContentsToRichComment(contents) : ' '}\n )`; + const richComment = `(comment\n ${contents ? adaptContentsToRichComment(contents) : ''}\n )`; let cursor = doc.getTokenCursor(p); const topLevelRange = rangeForDefun(doc, p, false); const isInsideForm = !(p <= topLevelRange[0] || p >= topLevelRange[1]); diff --git a/src/extension.ts b/src/extension.ts index b5f4810fa..c99723d69 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -227,6 +227,7 @@ async function activate(context: vscode.ExtensionContext) { context.subscriptions.push(vscode.commands.registerCommand('calva.continueComment', edit.continueCommentCommand)); context.subscriptions.push(vscode.commands.registerCommand('calva.diagnostics.toggleNreplLoggingEnabled', nreplLogging.toggleEnabled)); context.subscriptions.push(vscode.commands.registerCommand('calva.printClojureDocsToOutputWindow', clojureDocs.printClojureDocsToOutputWindow)); + context.subscriptions.push(vscode.commands.registerCommand('calva.printClojureDocsToRichComment', clojureDocs.printClojureDocsToRichComment)); // Initial set of the provided contexts outputWindow.setContextForOutputWindowActive(false); From 626f30480af01bf2199ef01235d533855024fb75 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Peter=20Str=C3=B6mberg?= Date: Mon, 25 Oct 2021 00:46:21 +0200 Subject: [PATCH 08/23] WIP: Add clojuredocs to hover --- src/clojuredocs.ts | 69 ++++++++++++++++++++++++++++++------------ src/extension.ts | 1 + src/providers/hover.ts | 5 ++- 3 files changed, 55 insertions(+), 20 deletions(-) diff --git a/src/clojuredocs.ts b/src/clojuredocs.ts index d09c62297..ec0764605 100644 --- a/src/clojuredocs.ts +++ b/src/clojuredocs.ts @@ -43,15 +43,56 @@ export async function printClojureDocsToOutputWindow() { } export async function printClojureDocsToRichComment() { - const doc = util.getDocument({}); - const mirrorDoc = docMirror.getDocument(doc); const docs = await clojureDocsLookup(); if (typeof docs === 'string') { - paredit.addRichComment(mirrorDoc, mirrorDoc.selection.active, `;; ${docs}`); + printTextToRichComment(`;; ${docs}`); } else { - paredit.addRichComment(mirrorDoc, mirrorDoc.selection.active, docsEntry2ClojureCode(docs)); - } + printTextToRichComment(docsEntry2ClojureCode(docs)); + } +} + +export function printTextToRichCommentCommand(args: { [x: string]: string; }) { + printTextToRichComment(args['text']); +} + +function printTextToRichComment(text: string) { + const doc = util.getDocument({}); + const mirrorDoc = docMirror.getDocument(doc); + paredit.addRichComment(mirrorDoc, mirrorDoc.selection.active, text); +} + +export async function getExamplesHover(document, position): Promise { + const docs = await clojureDocsLookup(document, position); + return getHoverForDocs(docs); +} + +function getHoverForDocs(docs: DocsEntry | string): vscode.MarkdownString { + if (typeof docs === 'string') { + return; + } + const webUrl = `${docs.baseUrl}/${docs.urlPath}`; + const linkMd = `[${webUrl}](${webUrl})`; + const hover = new vscode.MarkdownString(); + hover.isTrusted = true; + hover.appendMarkdown('## ClojureDocs Examples\n\n'); + hover.appendMarkdown(`${linkMd}\n\n`); + docs.examples.forEach((example, i) => { + hover.appendMarkdown(getHoverForExample(`Example ${i + 1}`, example).value); + }); + return hover; + //const seeAlsos = docs.seeAlsos.map(also => `${also} ; ${docs.baseUrl}/${also.replace(/\?/g, '%3F')}`).join(`\n`); +} + +function getHoverForExample(header: string, example: string): vscode.MarkdownString { + const printToRCFCommandUri = `command:calva.printTextToRichCommentCommand?${encodeURIComponent(JSON.stringify([{ text: example }]))}`; + const rcfCommandMd = `[As Rich Comment](${printToRCFCommandUri} "Print to Rich Comment")`; + const hover = new vscode.MarkdownString(); + hover.isTrusted = true; + hover.appendMarkdown(`### ${header}\n\n`); + hover.appendMarkdown(`${rcfCommandMd}\n`); + hover.appendCodeblock(example, 'clojure'); + return hover; } function docsEntry2ClojureCode(docs: DocsEntry, printDocString = false): string { @@ -65,7 +106,7 @@ function docsEntry2ClojureCode(docs: DocsEntry, printDocString = false): string const webUrl = `;; ${docs.baseUrl}/${docs.urlPath}`; // Not planning to print docs string, but keeping this code anyway =) const doc = docs.doc.split(/\n/).map(line => `;; ${line.replace(/^ {0,3}/, '')}`).join('\n').trim(); - const examples = docs.examples.map((example, i) => `${exampleSeparatorB} ${i+1}\n${example.trim()}\n${exampleSeparatorE} ${i+1}`).join('\n\n'); + const examples = docs.examples.map((example, i) => `${exampleSeparatorB} ${i + 1}\n${example.trim()}\n${exampleSeparatorE} ${i + 1}`).join('\n\n'); const seeAlsos = docs.seeAlsos.map(also => `${also} ; ${docs.baseUrl}/${also.replace(/\?/g, '%3F')}`).join(`\n`); const code = `${name}\n${webUrl}\n${printDocString ? doc + '\n' : ''}\n;; Examples:\n${examples}\n\n;; See also:\n${seeAlsos}\n`; return code; @@ -80,9 +121,9 @@ async function clojureDocsCiderNReplLookup(session: NReplSession, symbol: string return `Docs lookup failed: ${symbol ? 'Only Clojure core (ish) symbols supported' : 'Cursor not at a Clojure core (ish) symbol'}`; } -async function clojureDocsLookup(): Promise { - const doc = util.getDocument({}); - const position = vscode.window.activeTextEditor.selection.active; +async function clojureDocsLookup(d?, p?): Promise { + const doc = d ? d : util.getDocument({}); + const position = p ? p : vscode.window.activeTextEditor.selection.active; const symbol = util.getWordAtPosition(doc, position); const ns = namespace.getNamespace(doc); const session = replSession.getSession(util.getFileType(doc)); @@ -110,13 +151,3 @@ function ciderNRepl2DocsEntry(docs: any): DocsEntry { type: docs.type } } - -//export function getHoverText() { -// const copyCommandUri = `command:calva.copyAnnotationHoverText?${encodeURIComponent(JSON.stringify([{ text: resultString }]))}`, -// copyCommandMd = `[Copy](${copyCommandUri} "Copy results to the clipboard")`; -// const openWindowCommandUri = `command:calva.showOutputWindow`, -// openWindowCommandMd = `[Open Output Window](${openWindowCommandUri} "Open the output window")`; -// const hoverMessage = new vscode.MarkdownString(`${copyCommandMd} | ${openWindowCommandMd}\n` + '```clojure\n' + resultString + '\n```'); -// hoverMessage.isTrusted = true; -// decoration["hoverMessage"] = status == AnnotationStatus.ERROR ? resultString : hoverMessage; -//} \ No newline at end of file diff --git a/src/extension.ts b/src/extension.ts index c99723d69..999bc5101 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -228,6 +228,7 @@ async function activate(context: vscode.ExtensionContext) { context.subscriptions.push(vscode.commands.registerCommand('calva.diagnostics.toggleNreplLoggingEnabled', nreplLogging.toggleEnabled)); context.subscriptions.push(vscode.commands.registerCommand('calva.printClojureDocsToOutputWindow', clojureDocs.printClojureDocsToOutputWindow)); context.subscriptions.push(vscode.commands.registerCommand('calva.printClojureDocsToRichComment', clojureDocs.printClojureDocsToRichComment)); + context.subscriptions.push(vscode.commands.registerCommand('calva.printTextToRichCommentCommand', clojureDocs.printTextToRichCommentCommand)); // Initial set of the provided contexts outputWindow.setContextForOutputWindowActive(false); diff --git a/src/providers/hover.ts b/src/providers/hover.ts index 011f00741..cd0b1d73b 100644 --- a/src/providers/hover.ts +++ b/src/providers/hover.ts @@ -3,6 +3,7 @@ import * as util from '../utilities'; import * as infoparser from './infoparser'; import * as namespace from '../namespace'; import * as replSession from '../nrepl/repl-session'; +import * as clojureDocs from '../clojuredocs'; export async function provideHover(document, position) { if (util.getConnectedState()) { @@ -13,7 +14,9 @@ export async function provideHover(document, position) { await namespace.createNamespaceFromDocumentIfNotExists(document); let res = await client.info(ns, text); if (!res.status.includes('error')) { - return new vscode.Hover(infoparser.getHover(res)); + const docsMd = infoparser.getHover(res); + const clojureDocsMd = await clojureDocs.getExamplesHover(document, position); + return new vscode.Hover([docsMd, clojureDocsMd]); } } return null; //new vscode.Hover(infoparser.getHoverNotAvailable(text)); From 6b72eb8d7cfbe5cc4c69adc0a9c38440cca887f5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Peter=20Str=C3=B6mberg?= Date: Mon, 25 Oct 2021 09:43:25 +0200 Subject: [PATCH 09/23] WIP Better error handling --- src/clojuredocs.ts | 83 ++++++++++++++++++++++++------------------ src/providers/hover.ts | 2 +- 2 files changed, 49 insertions(+), 36 deletions(-) diff --git a/src/clojuredocs.ts b/src/clojuredocs.ts index ec0764605..2041aa53a 100644 --- a/src/clojuredocs.ts +++ b/src/clojuredocs.ts @@ -9,6 +9,7 @@ import * as replSession from './nrepl/repl-session'; import * as getText from './util/get-text'; import * as docMirror from './doc-mirror/index'; import * as paredit from './cursor-doc/paredit'; +import { string } from 'fast-check/*'; export type DocsEntry = { name: string; @@ -25,6 +26,13 @@ export type DocsEntry = { tag: string; }; +export type NoDocsEntry = { + noDocs: boolean; + symbol: string; + ns: string; + message: string; +}; + export function init(cljSession: NReplSession) { cljSession.clojureDocsRefreshCache().catch(reason => { console.error("Error refreshing ClojureDocs cache: ", reason); @@ -33,22 +41,22 @@ export function init(cljSession: NReplSession) { export async function printClojureDocsToOutputWindow() { const docs = await clojureDocsLookup(); - if (typeof docs === 'string') { - outputWindow.append(`;; ${docs}`) + if ((docs).noDocs) { + return; } else { - outputWindow.append(docsEntry2ClojureCode(docs)); + outputWindow.append(docsEntry2ClojureCode(docs)); } outputWindow.appendPrompt(); } export async function printClojureDocsToRichComment() { const docs = await clojureDocsLookup(); - if (typeof docs === 'string') { - printTextToRichComment(`;; ${docs}`); + if ((docs).noDocs) { + return; } else { - printTextToRichComment(docsEntry2ClojureCode(docs)); + printTextToRichComment(docsEntry2ClojureCode(docs)); } } @@ -64,7 +72,10 @@ function printTextToRichComment(text: string) { export async function getExamplesHover(document, position): Promise { const docs = await clojureDocsLookup(document, position); - return getHoverForDocs(docs); + if ((docs).noDocs) { + return null; + } + return getHoverForDocs(docs); } function getHoverForDocs(docs: DocsEntry | string): vscode.MarkdownString { @@ -112,42 +123,44 @@ function docsEntry2ClojureCode(docs: DocsEntry, printDocString = false): string return code; } } - -async function clojureDocsCiderNReplLookup(session: NReplSession, symbol: string, ns: string): Promise { - const ciderNReplDocs = await session.clojureDocsLookup(ns, symbol); - if (ciderNReplDocs.clojuredocs) { - return ciderNRepl2DocsEntry(ciderNReplDocs.clojuredocs); - } - return `Docs lookup failed: ${symbol ? 'Only Clojure core (ish) symbols supported' : 'Cursor not at a Clojure core (ish) symbol'}`; -} - -async function clojureDocsLookup(d?, p?): Promise { +async function clojureDocsLookup(d?: vscode.TextDocument, p?: vscode.Position): Promise { const doc = d ? d : util.getDocument({}); const position = p ? p : vscode.window.activeTextEditor.selection.active; const symbol = util.getWordAtPosition(doc, position); const ns = namespace.getNamespace(doc); const session = replSession.getSession(util.getFileType(doc)); - if (session.replType !== 'clj') { - vscode.window.showErrorMessage('Clojuredocs Lookup is currently only supported with Clojure REPLs.'); - } - return clojureDocsCiderNReplLookup(session, symbol, ns); } -function ciderNRepl2DocsEntry(docs: any): DocsEntry { - return { - name: docs.name, - added: docs.added, - baseUrl: 'https://clojuredocs.org', - doc: docs.doc, - argsLists: docs.argsLists, - examples: docs.examples, - notes: docs.notes, - ns: docs.ns, - urlPath: docs.href.replace(/^\/?/, ''), - seeAlsos: docs['see-alsos'], - tag: docs.tag, - type: docs.type +async function clojureDocsCiderNReplLookup(session: NReplSession, symbol: string, ns: string): Promise { + const ciderNReplDocs = await session.clojureDocsLookup(ns, symbol); + return ciderNRepl2DocsEntry(ciderNReplDocs, symbol, ns); +} + +function ciderNRepl2DocsEntry(docsResult: any, symbol: string, ns: string): DocsEntry | NoDocsEntry { + const docs = docsResult.clojuredocs; + if (docs) { + return { + name: docs.name, + added: docs.added, + baseUrl: 'https://clojuredocs.org', + doc: docs.doc, + argsLists: docs.argsLists, + examples: docs.examples, + notes: docs.notes, + ns: docs.ns, + urlPath: docs.href.replace(/^\/?/, ''), + seeAlsos: docs['see-alsos'], + tag: docs.tag, + type: docs.type + } + } else { + return { + noDocs: true, + symbol: symbol, + ns: ns, + message: `Docs lookup failed: ${symbol ? 'Only Clojure core (ish) symbols supported' : 'Cursor not at a Clojure core (ish) symbol'}` + } } } diff --git a/src/providers/hover.ts b/src/providers/hover.ts index cd0b1d73b..86dc78c81 100644 --- a/src/providers/hover.ts +++ b/src/providers/hover.ts @@ -13,7 +13,7 @@ export async function provideHover(document, position) { if(client) { await namespace.createNamespaceFromDocumentIfNotExists(document); let res = await client.info(ns, text); - if (!res.status.includes('error')) { + if (!res.status.includes('error') && !res.status.includes('no-info')) { const docsMd = infoparser.getHover(res); const clojureDocsMd = await clojureDocs.getExamplesHover(document, position); return new vscode.Hover([docsMd, clojureDocsMd]); From b738af26559ad39e1526ac46a747539e406746dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Peter=20Str=C3=B6mberg?= Date: Wed, 27 Oct 2021 16:30:14 +0200 Subject: [PATCH 10/23] Update changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index a67b31f85..1ed89d9b3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ Changes to Calva. ## [Unreleased] +- [Include material from clojuredocs.org in function documentation](https://github.com/BetterThanTomorrow/calva/issues/689) - Fix: [Not able to escape read-line in the output window](https://github.com/BetterThanTomorrow/calva/issues/783) - Fix: [Some keyboard shortcuts missing the languageID check](https://github.com/BetterThanTomorrow/calva/issues/823) - Fix: [Formatting form with comma whitespace inserts 0 and places the cursor wrong](https://github.com/BetterThanTomorrow/calva/issues/1370) From 2d517b635ce4a2e761ca5dc29ff944b8d48d4492 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Peter=20Str=C3=B6mberg?= Date: Sun, 31 Oct 2021 09:42:48 +0100 Subject: [PATCH 11/23] Don't offer rfc option in hover for readonly doc --- src/clojuredocs.ts | 22 ++++++++++++---------- src/utilities.ts | 8 ++++++++ 2 files changed, 20 insertions(+), 10 deletions(-) diff --git a/src/clojuredocs.ts b/src/clojuredocs.ts index 2041aa53a..8903319f6 100644 --- a/src/clojuredocs.ts +++ b/src/clojuredocs.ts @@ -61,24 +61,24 @@ export async function printClojureDocsToRichComment() { } export function printTextToRichCommentCommand(args: { [x: string]: string; }) { - printTextToRichComment(args['text']); + printTextToRichComment(args['text'], Number.parseInt(args['position'])); } -function printTextToRichComment(text: string) { +function printTextToRichComment(text: string, position?: number) { const doc = util.getDocument({}); const mirrorDoc = docMirror.getDocument(doc); - paredit.addRichComment(mirrorDoc, mirrorDoc.selection.active, text); + paredit.addRichComment(mirrorDoc, position ? position : mirrorDoc.selection.active, text); } -export async function getExamplesHover(document, position): Promise { +export async function getExamplesHover(document: vscode.TextDocument, position: vscode.Position): Promise { const docs = await clojureDocsLookup(document, position); if ((docs).noDocs) { return null; } - return getHoverForDocs(docs); + return getHoverForDocs(docs, document.offsetAt(position), await util.isDocumentWritable(document)); } -function getHoverForDocs(docs: DocsEntry | string): vscode.MarkdownString { +function getHoverForDocs(docs: DocsEntry | string, position: number, isWritableDocument: boolean): vscode.MarkdownString { if (typeof docs === 'string') { return; } @@ -89,19 +89,21 @@ function getHoverForDocs(docs: DocsEntry | string): vscode.MarkdownString { hover.appendMarkdown('## ClojureDocs Examples\n\n'); hover.appendMarkdown(`${linkMd}\n\n`); docs.examples.forEach((example, i) => { - hover.appendMarkdown(getHoverForExample(`Example ${i + 1}`, example).value); + hover.appendMarkdown(getHoverForExample(`Example ${i + 1}`, example, position, isWritableDocument).value); }); return hover; //const seeAlsos = docs.seeAlsos.map(also => `${also} ; ${docs.baseUrl}/${also.replace(/\?/g, '%3F')}`).join(`\n`); } -function getHoverForExample(header: string, example: string): vscode.MarkdownString { - const printToRCFCommandUri = `command:calva.printTextToRichCommentCommand?${encodeURIComponent(JSON.stringify([{ text: example }]))}`; +function getHoverForExample(header: string, example: string, position: number, isWritableDocument: boolean): vscode.MarkdownString { + const printToRCFCommandUri = `command:calva.printTextToRichCommentCommand?${encodeURIComponent(JSON.stringify([{ text: example, position: position }]))}`; const rcfCommandMd = `[As Rich Comment](${printToRCFCommandUri} "Print to Rich Comment")`; const hover = new vscode.MarkdownString(); hover.isTrusted = true; hover.appendMarkdown(`### ${header}\n\n`); - hover.appendMarkdown(`${rcfCommandMd}\n`); + if (isWritableDocument) { + hover.appendMarkdown(`${rcfCommandMd}\n`); + } hover.appendCodeblock(example, 'clojure'); return hover; } diff --git a/src/utilities.ts b/src/utilities.ts index cd5905ff2..6d90638ef 100644 --- a/src/utilities.ts +++ b/src/utilities.ts @@ -402,6 +402,14 @@ function randomSlug(length = 7) { const isWindows = process.platform === 'win32'; +export async function isDocumentWritable(document: vscode.TextDocument): Promise { + if (!vscode.workspace.fs.isWritableFileSystem(document.uri.scheme)) { + return false; + } + const fileStat = await vscode.workspace.fs.stat(document.uri); + return (fileStat.permissions & vscode.FilePermission.Readonly) !== 1; +} + export { getWordAtPosition, getDocument, From e5a05ea54964874b6a7188f630600f0b845d5340 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Peter=20Str=C3=B6mberg?= Date: Sun, 24 Oct 2021 12:39:30 +0200 Subject: [PATCH 12/23] WIP - Source clojuredocs from clojure-lsp Adding a command for testing how to get clojuredocs. (Which can't be done yet, see: https://github.com/clojure-lsp/clojure-lsp/issues/598) Addressing #689 --- package.json | 5 +++++ src/lsp/main.ts | 22 ++++++++++++++++++++++ 2 files changed, 27 insertions(+) diff --git a/package.json b/package.json index 7075696b5..7e8a8eae0 100644 --- a/package.json +++ b/package.json @@ -1538,6 +1538,11 @@ "title": "Clojure-lsp Server Info", "category": "Calva Diagnostics" }, + { + "category": "Calva", + "command": "calva.clojuredocs", + "title": "Clojuredocs" + }, { "category": "Calva", "command": "calva.toggleBetweenImplAndTest", diff --git a/src/lsp/main.ts b/src/lsp/main.ts index 25e47bc26..136e44459 100644 --- a/src/lsp/main.ts +++ b/src/lsp/main.ts @@ -332,8 +332,23 @@ function registerDiagnosticsCommands(context: vscode.ExtensionContext): void { context.subscriptions.push(vscode.commands.registerCommand('calva.diagnostics.openClojureLspLogFile', openLogFile)); } +async function clojuredocsCommandHandler(): Promise { + const client = getStateValue(LSP_CLIENT_KEY); + if (client) { + const clojuredocs = await getClojuredocs(client); + const calvaSaysChannel = state.outputChannel(); + calvaSaysChannel.appendLine(`Clojuredocs:`); + const clojuredocsPretty = JSON.stringify(clojuredocs, null, 2); + calvaSaysChannel.appendLine(clojuredocsPretty); + calvaSaysChannel.show(true); + } else { + vscode.window.showInformationMessage('There is no clojure-lsp server running.'); + } +} + async function activate(context: vscode.ExtensionContext): Promise { registerDiagnosticsCommands(context); + context.subscriptions.push(vscode.commands.registerCommand('calva.clojuredocs', clojuredocsCommandHandler)); const extensionPath = context.extensionPath; const currentVersion = readVersionFile(extensionPath); const userConfiguredClojureLspPath = config.getConfig().clojureLspPath; @@ -397,6 +412,13 @@ async function openLogFile(): Promise { } } +async function getClojuredocs(lspClient: LanguageClient): Promise { + return lspClient.sendRequest('clojure/clojuredocs/raw', { + symName: 'pprint', + symNs: 'clojure.core' + }); +} + export default { activate, deactivate, From 3d7dc12b4866d92fbe8b5fc1d95cbcbeae36698f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Peter=20Str=C3=B6mberg?= Date: Sun, 31 Oct 2021 16:03:28 +0100 Subject: [PATCH 13/23] Use LSP clojuredocs/raw if nrepl can't provide --- package.json | 5 ----- src/clojuredocs.ts | 31 ++++++++++++++++++++++--------- src/lsp/main.ts | 24 +++++------------------- 3 files changed, 27 insertions(+), 33 deletions(-) diff --git a/package.json b/package.json index 7e8a8eae0..7075696b5 100644 --- a/package.json +++ b/package.json @@ -1538,11 +1538,6 @@ "title": "Clojure-lsp Server Info", "category": "Calva Diagnostics" }, - { - "category": "Calva", - "command": "calva.clojuredocs", - "title": "Clojuredocs" - }, { "category": "Calva", "command": "calva.toggleBetweenImplAndTest", diff --git a/src/clojuredocs.ts b/src/clojuredocs.ts index 8903319f6..f17b13691 100644 --- a/src/clojuredocs.ts +++ b/src/clojuredocs.ts @@ -1,15 +1,13 @@ import * as vscode from 'vscode'; -import annotations from './providers/annotations'; import * as util from './utilities'; -import { NReplSession, NReplEvaluation } from './nrepl'; +import * as nrepl from './nrepl'; +import * as lsp from './lsp/main'; import * as outputWindow from './results-output/results-doc'; import * as namespace from './namespace'; import { getConfig } from './config'; import * as replSession from './nrepl/repl-session'; -import * as getText from './util/get-text'; import * as docMirror from './doc-mirror/index'; import * as paredit from './cursor-doc/paredit'; -import { string } from 'fast-check/*'; export type DocsEntry = { name: string; @@ -33,7 +31,7 @@ export type NoDocsEntry = { message: string; }; -export function init(cljSession: NReplSession) { +export function init(cljSession: nrepl.NReplSession) { cljSession.clojureDocsRefreshCache().catch(reason => { console.error("Error refreshing ClojureDocs cache: ", reason); }); @@ -132,15 +130,30 @@ async function clojureDocsLookup(d?: vscode.TextDocument, p?: vscode.Position): const ns = namespace.getNamespace(doc); const session = replSession.getSession(util.getFileType(doc)); - return clojureDocsCiderNReplLookup(session, symbol, ns); + const docsFromCider = await clojureDocsCiderNReplLookup(session, symbol, ns); + if (!(docsFromCider).noDocs) { + return docsFromCider; + } else { + return clojureDocsLspLookup(session, symbol, ns); + } } -async function clojureDocsCiderNReplLookup(session: NReplSession, symbol: string, ns: string): Promise { +async function clojureDocsCiderNReplLookup(session: nrepl.NReplSession, symbol: string, ns: string): Promise { const ciderNReplDocs = await session.clojureDocsLookup(ns, symbol); - return ciderNRepl2DocsEntry(ciderNReplDocs, symbol, ns); + return rawDocs2DocsEntry(ciderNReplDocs, symbol, ns); +} + +async function clojureDocsLspLookup(session: nrepl.NReplSession, symbol: string, ns: string): Promise { + const resolved = await session.info(ns, symbol); + try { + const docs = await lsp.getClojuredocs(resolved.name, resolved.ns); + return rawDocs2DocsEntry({ clojuredocs: docs }, resolved.name, resolved.ns); + } catch { + return rawDocs2DocsEntry({ clojuredocs: null }, resolved.name, resolved.ns); + } } -function ciderNRepl2DocsEntry(docsResult: any, symbol: string, ns: string): DocsEntry | NoDocsEntry { +function rawDocs2DocsEntry(docsResult: any, symbol: string, ns: string): DocsEntry | NoDocsEntry { const docs = docsResult.clojuredocs; if (docs) { return { diff --git a/src/lsp/main.ts b/src/lsp/main.ts index 136e44459..3bb0e9da1 100644 --- a/src/lsp/main.ts +++ b/src/lsp/main.ts @@ -332,23 +332,8 @@ function registerDiagnosticsCommands(context: vscode.ExtensionContext): void { context.subscriptions.push(vscode.commands.registerCommand('calva.diagnostics.openClojureLspLogFile', openLogFile)); } -async function clojuredocsCommandHandler(): Promise { - const client = getStateValue(LSP_CLIENT_KEY); - if (client) { - const clojuredocs = await getClojuredocs(client); - const calvaSaysChannel = state.outputChannel(); - calvaSaysChannel.appendLine(`Clojuredocs:`); - const clojuredocsPretty = JSON.stringify(clojuredocs, null, 2); - calvaSaysChannel.appendLine(clojuredocsPretty); - calvaSaysChannel.show(true); - } else { - vscode.window.showInformationMessage('There is no clojure-lsp server running.'); - } -} - async function activate(context: vscode.ExtensionContext): Promise { registerDiagnosticsCommands(context); - context.subscriptions.push(vscode.commands.registerCommand('calva.clojuredocs', clojuredocsCommandHandler)); const extensionPath = context.extensionPath; const currentVersion = readVersionFile(extensionPath); const userConfiguredClojureLspPath = config.getConfig().clojureLspPath; @@ -412,10 +397,11 @@ async function openLogFile(): Promise { } } -async function getClojuredocs(lspClient: LanguageClient): Promise { - return lspClient.sendRequest('clojure/clojuredocs/raw', { - symName: 'pprint', - symNs: 'clojure.core' +export async function getClojuredocs(symName: string, symNs: string): Promise { + const client: LanguageClient = getStateValue(LSP_CLIENT_KEY); + return client.sendRequest('clojure/clojuredocs/raw', { + symName, + symNs }); } From f71c2c076c84136792333e25618e7959d25f2cc5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Peter=20Str=C3=B6mberg?= Date: Sun, 31 Oct 2021 17:35:57 +0100 Subject: [PATCH 14/23] Check lsp server version before requesting clojuredocs --- src/lsp/main.ts | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/src/lsp/main.ts b/src/lsp/main.ts index 3bb0e9da1..2b75c8371 100644 --- a/src/lsp/main.ts +++ b/src/lsp/main.ts @@ -17,6 +17,7 @@ const LSP_CLIENT_KEY = 'lspClient'; const RESOLVE_MACRO_AS_COMMAND = 'resolve-macro-as'; const SERVER_NOT_RUNNING_OR_INITIALIZED_MESSAGE = 'The clojure-lsp server is not running or has not finished intializing.' const lspStatus = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Left, -1); +let serverVersion: string; function createClient(clojureLspPath: string): LanguageClient { const serverOptions: ServerOptions = { @@ -300,16 +301,16 @@ async function startClient(clojureLspPath: string, context: vscode.ExtensionCont setStateValue(LSP_CLIENT_KEY, client); registerCommands(context, client); registerEventHandlers(context, client); - sayClientVersionInfo(client); + const serverInfo = await getServerInfo(client); + serverVersion = serverInfo['server-version']; + sayClientVersionInfo(serverVersion, serverInfo); } -async function sayClientVersionInfo(client: LanguageClient) { - const serverInfo = await getServerInfo(client); - const clojureLspVersion = serverInfo['server-version']; +function sayClientVersionInfo(serverVersion: string, serverInfo: any) { const cljKondoVersion = serverInfo['clj-kondo-version']; const calvaSaysChannel = state.outputChannel(); calvaSaysChannel.appendLine(''); - calvaSaysChannel.appendLine(`clojure-lsp version used: ${clojureLspVersion}`); + calvaSaysChannel.appendLine(`clojure-lsp version used: ${serverVersion}`); calvaSaysChannel.appendLine(`clj-kondo version used: ${cljKondoVersion}`); } @@ -398,11 +399,15 @@ async function openLogFile(): Promise { } export async function getClojuredocs(symName: string, symNs: string): Promise { - const client: LanguageClient = getStateValue(LSP_CLIENT_KEY); - return client.sendRequest('clojure/clojuredocs/raw', { - symName, - symNs - }); + if (serverVersion > '2021.10.20-16.49.47') { + const client: LanguageClient = getStateValue(LSP_CLIENT_KEY); + return client.sendRequest('clojure/clojuredocs/raw', { + symName, + symNs + }); + } else { + return null; + } } export default { From a0bc0d7147066705d98ab67c86aa4f2cf044e558 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Peter=20Str=C3=B6mberg?= Date: Sun, 31 Oct 2021 18:59:45 +0100 Subject: [PATCH 15/23] Add hover command for printing to output window --- src/clojuredocs.ts | 32 ++++++++++++++++++++++---------- src/extension.ts | 1 + 2 files changed, 23 insertions(+), 10 deletions(-) diff --git a/src/clojuredocs.ts b/src/clojuredocs.ts index f17b13691..ffe929e2a 100644 --- a/src/clojuredocs.ts +++ b/src/clojuredocs.ts @@ -42,9 +42,15 @@ export async function printClojureDocsToOutputWindow() { if ((docs).noDocs) { return; } - else { - outputWindow.append(docsEntry2ClojureCode(docs)); - } + printTextToOutputWindow(docsEntry2ClojureCode(docs)); +} + +export function printTextToOutputWindowCommand(args: { [x: string]: string; }) { + printTextToOutputWindow(args['text']); +} + +function printTextToOutputWindow(text: string) { + outputWindow.append(text); outputWindow.appendPrompt(); } @@ -86,21 +92,27 @@ function getHoverForDocs(docs: DocsEntry | string, position: number, isWritableD hover.isTrusted = true; hover.appendMarkdown('## ClojureDocs Examples\n\n'); hover.appendMarkdown(`${linkMd}\n\n`); + const seeAlsos = docs.seeAlsos.map(also => `${also.replace(/^clojure.core\//, '')}`); docs.examples.forEach((example, i) => { - hover.appendMarkdown(getHoverForExample(`Example ${i + 1}`, example, position, isWritableDocument).value); + const symbol = `${docs.ns}/${docs.name}`.replace(/^clojure.core\//, ''); + hover.appendMarkdown(getHoverForExample(symbol, `Example ${i + 1}`, example, seeAlsos, position, isWritableDocument).value); }); + hover.appendMarkdown('### See also\n\n'); + hover.appendCodeblock(seeAlsos.join('\n'), 'clojure'); return hover; - //const seeAlsos = docs.seeAlsos.map(also => `${also} ; ${docs.baseUrl}/${also.replace(/\?/g, '%3F')}`).join(`\n`); } -function getHoverForExample(header: string, example: string, position: number, isWritableDocument: boolean): vscode.MarkdownString { - const printToRCFCommandUri = `command:calva.printTextToRichCommentCommand?${encodeURIComponent(JSON.stringify([{ text: example, position: position }]))}`; - const rcfCommandMd = `[As Rich Comment](${printToRCFCommandUri} "Print to Rich Comment")`; +function getHoverForExample(symbol: string, header: string, example: string, seeAlsos: string[], position: number, isWritableDocument: boolean): vscode.MarkdownString { + const exampleAndSeeAlsos = `;; = ${symbol} - ${header} = \n\n${example}\n;; See also:\n${seeAlsos.join('\n')}`; + const printToRCFCommandUri = `command:calva.printTextToRichCommentCommand?${encodeURIComponent(JSON.stringify([{ text: exampleAndSeeAlsos, position: position }]))}`; + const printToOutputWindowCommandUri = `command:calva.printTextToOutputWindowCommand?${encodeURIComponent(JSON.stringify([{ text: exampleAndSeeAlsos, position: position }]))}`; + const rcfCommandMd = `[To Rich Comment](${printToRCFCommandUri} "Print the example to a \`(comment ...)\` block")`; + const outputWindowCommandMd = `[To Output Window](${printToOutputWindowCommandUri} "Print the example to the Output/REPL Window")`; const hover = new vscode.MarkdownString(); hover.isTrusted = true; hover.appendMarkdown(`### ${header}\n\n`); if (isWritableDocument) { - hover.appendMarkdown(`${rcfCommandMd}\n`); + hover.appendMarkdown(`${rcfCommandMd} | ${outputWindowCommandMd}\n`); } hover.appendCodeblock(example, 'clojure'); return hover; @@ -118,7 +130,7 @@ function docsEntry2ClojureCode(docs: DocsEntry, printDocString = false): string // Not planning to print docs string, but keeping this code anyway =) const doc = docs.doc.split(/\n/).map(line => `;; ${line.replace(/^ {0,3}/, '')}`).join('\n').trim(); const examples = docs.examples.map((example, i) => `${exampleSeparatorB} ${i + 1}\n${example.trim()}\n${exampleSeparatorE} ${i + 1}`).join('\n\n'); - const seeAlsos = docs.seeAlsos.map(also => `${also} ; ${docs.baseUrl}/${also.replace(/\?/g, '%3F')}`).join(`\n`); + const seeAlsos = docs.seeAlsos.map(also => `${also.replace(/^clojure.core\//, '')} ; ${docs.baseUrl}/${also.replace(/\?/g, '%3F')}`).join(`\n`); const code = `${name}\n${webUrl}\n${printDocString ? doc + '\n' : ''}\n;; Examples:\n${examples}\n\n;; See also:\n${seeAlsos}\n`; return code; } diff --git a/src/extension.ts b/src/extension.ts index 999bc5101..e661f2739 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -229,6 +229,7 @@ async function activate(context: vscode.ExtensionContext) { context.subscriptions.push(vscode.commands.registerCommand('calva.printClojureDocsToOutputWindow', clojureDocs.printClojureDocsToOutputWindow)); context.subscriptions.push(vscode.commands.registerCommand('calva.printClojureDocsToRichComment', clojureDocs.printClojureDocsToRichComment)); context.subscriptions.push(vscode.commands.registerCommand('calva.printTextToRichCommentCommand', clojureDocs.printTextToRichCommentCommand)); + context.subscriptions.push(vscode.commands.registerCommand('calva.printTextToOutputWindowCommand', clojureDocs.printTextToOutputWindowCommand)); // Initial set of the provided contexts outputWindow.setContextForOutputWindowActive(false); From d5a2e70a5e758348e9c42d98d465b004610d4f08 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Peter=20Str=C3=B6mberg?= Date: Sun, 31 Oct 2021 21:33:37 +0100 Subject: [PATCH 16/23] npm i --- package-lock.json | 5 ----- 1 file changed, 5 deletions(-) diff --git a/package-lock.json b/package-lock.json index b379dd303..f5a2f3d51 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9967,11 +9967,6 @@ "safer-buffer": "^2.0.2", "tweetnacl": "~0.14.0" }, - "bin": { - "sshpk-conv": "bin/sshpk-conv", - "sshpk-sign": "bin/sshpk-sign", - "sshpk-verify": "bin/sshpk-verify" - }, "engines": { "node": ">=0.10.0" } From a5d200b4d726e9a8b2f11efba57537f52edbbfd7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Peter=20Str=C3=B6mberg?= Date: Sun, 31 Oct 2021 21:39:09 +0100 Subject: [PATCH 17/23] Change shortct for showing output window --- docs/site/output.md | 6 +++--- package.json | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/site/output.md b/docs/site/output.md index 37488e25e..67f1bcd1b 100644 --- a/docs/site/output.md +++ b/docs/site/output.md @@ -10,13 +10,13 @@ The first prompt is from when the `clj` REPL is connected, the second when Calva ## Find the Output/REPL Window -If you quickly want to open and switch to the output window there is the command **Calva: Show Output Window**, `ctrl+alt+c o`. +If you quickly want to open and switch to the output window there is the command **Calva: Show Output Window**, `ctrl+alt+o o`. To sync the Output/REPL window namespace with the current file before switching, use the **Switch Namespace of the Output/REPL Window to Current Namespace** command, `ctrl+alt+c alt+n`. ## Find the File for the Current REPL Window Namespace -When you are working from the Output/REPL window, and want to open the file that defines its current namespace, use the **Show File for the Current Output/REPL Window Namespace** command, `ctrl+alt+c o`. +When you are working from the Output/REPL window, and want to open the file that defines its current namespace, use the **Show File for the Current Output/REPL Window Namespace** command, `ctrl+alt+o o`. !!! Note This also works for Clojure core and library namespaces. @@ -37,7 +37,7 @@ The output window will print the defined var and then a new prompt reflecting th ![eval-results-1](images/howto/output/eval-results-1.png) -If you then switch to the output window (`ctrl+alt+c o`), and enter this at the prompt: +If you then switch to the output window (`ctrl+alt+o o`), and enter this at the prompt: ```clojure mount-target diff --git a/package.json b/package.json index 7075696b5..74a19df7d 100644 --- a/package.json +++ b/package.json @@ -2059,12 +2059,12 @@ }, { "command": "calva.showOutputWindow", - "key": "ctrl+alt+c o", + "key": "ctrl+alt+o o", "when": "calva:keybindingsEnabled && calva:connected && !calva:outputWindowActive" }, { "command": "calva.showFileForOutputWindowNS", - "key": "ctrl+alt+c o", + "key": "ctrl+alt+o o", "when": "calva:keybindingsEnabled && calva:connected && calva:outputWindowActive" }, { From 5a435125c63eeddd38244cde5d8e7aa907fc7f78 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Peter=20Str=C3=B6mberg?= Date: Mon, 1 Nov 2021 09:38:50 +0100 Subject: [PATCH 18/23] Remove NoDocsEntry type --- src/clojuredocs.ts | 61 ++++++++++++++++++---------------------------- 1 file changed, 24 insertions(+), 37 deletions(-) diff --git a/src/clojuredocs.ts b/src/clojuredocs.ts index ffe929e2a..d39b10b23 100644 --- a/src/clojuredocs.ts +++ b/src/clojuredocs.ts @@ -22,13 +22,7 @@ export type DocsEntry = { seeAlsos: string[]; added: string; tag: string; -}; - -export type NoDocsEntry = { - noDocs: boolean; - symbol: string; - ns: string; - message: string; + fromServer: "cider-nrepl" | "clojure-lsp"; }; export function init(cljSession: nrepl.NReplSession) { @@ -39,10 +33,10 @@ export function init(cljSession: nrepl.NReplSession) { export async function printClojureDocsToOutputWindow() { const docs = await clojureDocsLookup(); - if ((docs).noDocs) { + if (!docs) { return; } - printTextToOutputWindow(docsEntry2ClojureCode(docs)); + printTextToOutputWindow(docsEntry2ClojureCode(docs)); } export function printTextToOutputWindowCommand(args: { [x: string]: string; }) { @@ -56,11 +50,11 @@ function printTextToOutputWindow(text: string) { export async function printClojureDocsToRichComment() { const docs = await clojureDocsLookup(); - if ((docs).noDocs) { + if (!docs) { return; } else { - printTextToRichComment(docsEntry2ClojureCode(docs)); + printTextToRichComment(docsEntry2ClojureCode(docs)); } } @@ -76,22 +70,19 @@ function printTextToRichComment(text: string, position?: number) { export async function getExamplesHover(document: vscode.TextDocument, position: vscode.Position): Promise { const docs = await clojureDocsLookup(document, position); - if ((docs).noDocs) { + if (!docs) { return null; } - return getHoverForDocs(docs, document.offsetAt(position), await util.isDocumentWritable(document)); + return getHoverForDocs(docs, document.offsetAt(position), await util.isDocumentWritable(document)); } -function getHoverForDocs(docs: DocsEntry | string, position: number, isWritableDocument: boolean): vscode.MarkdownString { - if (typeof docs === 'string') { - return; - } +function getHoverForDocs(docs: DocsEntry, position: number, isWritableDocument: boolean): vscode.MarkdownString { const webUrl = `${docs.baseUrl}/${docs.urlPath}`; const linkMd = `[${webUrl}](${webUrl})`; const hover = new vscode.MarkdownString(); hover.isTrusted = true; hover.appendMarkdown('## ClojureDocs Examples\n\n'); - hover.appendMarkdown(`${linkMd}\n\n`); + hover.appendMarkdown(`${linkMd} via ${docs.fromServer}\n\n`); const seeAlsos = docs.seeAlsos.map(also => `${also.replace(/^clojure.core\//, '')}`); docs.examples.forEach((example, i) => { const symbol = `${docs.ns}/${docs.name}`.replace(/^clojure.core\//, ''); @@ -119,10 +110,6 @@ function getHoverForExample(symbol: string, header: string, example: string, see } function docsEntry2ClojureCode(docs: DocsEntry, printDocString = false): string { - if (typeof docs === 'string') { - return `;; ${docs}`; - } - else { const exampleSeparatorB = `;; ------- BEGIN EXAMPLE` const exampleSeparatorE = `;; ------- END EXAMPLE` const name = `;; ${docs.ns}/${docs.name}`; @@ -133,9 +120,9 @@ function docsEntry2ClojureCode(docs: DocsEntry, printDocString = false): string const seeAlsos = docs.seeAlsos.map(also => `${also.replace(/^clojure.core\//, '')} ; ${docs.baseUrl}/${also.replace(/\?/g, '%3F')}`).join(`\n`); const code = `${name}\n${webUrl}\n${printDocString ? doc + '\n' : ''}\n;; Examples:\n${examples}\n\n;; See also:\n${seeAlsos}\n`; return code; - } } -async function clojureDocsLookup(d?: vscode.TextDocument, p?: vscode.Position): Promise { + +async function clojureDocsLookup(d?: vscode.TextDocument, p?: vscode.Position): Promise { const doc = d ? d : util.getDocument({}); const position = p ? p : vscode.window.activeTextEditor.selection.active; const symbol = util.getWordAtPosition(doc, position); @@ -143,29 +130,31 @@ async function clojureDocsLookup(d?: vscode.TextDocument, p?: vscode.Position): const session = replSession.getSession(util.getFileType(doc)); const docsFromCider = await clojureDocsCiderNReplLookup(session, symbol, ns); - if (!(docsFromCider).noDocs) { + if (docsFromCider) { return docsFromCider; } else { return clojureDocsLspLookup(session, symbol, ns); } } -async function clojureDocsCiderNReplLookup(session: nrepl.NReplSession, symbol: string, ns: string): Promise { +async function clojureDocsCiderNReplLookup(session: nrepl.NReplSession, symbol: string, ns: string): Promise { const ciderNReplDocs = await session.clojureDocsLookup(ns, symbol); + ciderNReplDocs.fromServer = "cider-nrepl"; return rawDocs2DocsEntry(ciderNReplDocs, symbol, ns); } -async function clojureDocsLspLookup(session: nrepl.NReplSession, symbol: string, ns: string): Promise { +async function clojureDocsLspLookup(session: nrepl.NReplSession, symbol: string, ns: string): Promise { const resolved = await session.info(ns, symbol); + const symNs = resolved.ns.replace(/^cljs\./, 'clojure.'); try { const docs = await lsp.getClojuredocs(resolved.name, resolved.ns); - return rawDocs2DocsEntry({ clojuredocs: docs }, resolved.name, resolved.ns); + return rawDocs2DocsEntry({ clojuredocs: docs, fromServer: "clojure-lsp" }, resolved.name, symNs); } catch { - return rawDocs2DocsEntry({ clojuredocs: null }, resolved.name, resolved.ns); + return rawDocs2DocsEntry({ clojuredocs: null, fromServer: "clojure-lsp" }, resolved.name, resolved.ns); } } -function rawDocs2DocsEntry(docsResult: any, symbol: string, ns: string): DocsEntry | NoDocsEntry { +function rawDocs2DocsEntry(docsResult: any, symbol: string, ns: string): DocsEntry { const docs = docsResult.clojuredocs; if (docs) { return { @@ -180,14 +169,12 @@ function rawDocs2DocsEntry(docsResult: any, symbol: string, ns: string): DocsEnt urlPath: docs.href.replace(/^\/?/, ''), seeAlsos: docs['see-alsos'], tag: docs.tag, - type: docs.type + type: docs.type, + fromServer: docsResult.fromServer } } else { - return { - noDocs: true, - symbol: symbol, - ns: ns, - message: `Docs lookup failed: ${symbol ? 'Only Clojure core (ish) symbols supported' : 'Cursor not at a Clojure core (ish) symbol'}` - } + // TODO: Remove this debug logging + console.log(`No results for ${ns}/${symbol} from ${docsResult.fromServer}`); + return null; } } From 7bc44d22b56d47065ab157d27189c603198465b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Peter=20Str=C3=B6mberg?= Date: Mon, 1 Nov 2021 09:44:40 +0100 Subject: [PATCH 19/23] Remove clojuredocs urls from see-alsos --- src/clojuredocs.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/clojuredocs.ts b/src/clojuredocs.ts index d39b10b23..7dba9fe5b 100644 --- a/src/clojuredocs.ts +++ b/src/clojuredocs.ts @@ -117,7 +117,7 @@ function docsEntry2ClojureCode(docs: DocsEntry, printDocString = false): string // Not planning to print docs string, but keeping this code anyway =) const doc = docs.doc.split(/\n/).map(line => `;; ${line.replace(/^ {0,3}/, '')}`).join('\n').trim(); const examples = docs.examples.map((example, i) => `${exampleSeparatorB} ${i + 1}\n${example.trim()}\n${exampleSeparatorE} ${i + 1}`).join('\n\n'); - const seeAlsos = docs.seeAlsos.map(also => `${also.replace(/^clojure.core\//, '')} ; ${docs.baseUrl}/${also.replace(/\?/g, '%3F')}`).join(`\n`); + const seeAlsos = docs.seeAlsos.map(also => `${also.replace(/^clojure.core\//, '')}`).join(`\n`); const code = `${name}\n${webUrl}\n${printDocString ? doc + '\n' : ''}\n;; Examples:\n${examples}\n\n;; See also:\n${seeAlsos}\n`; return code; } From 431124da7198be7616036a5f39a94732466bc2a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Peter=20Str=C3=B6mberg?= Date: Mon, 1 Nov 2021 18:08:50 +0100 Subject: [PATCH 20/23] Fix bug preventing the docs to work in ClojureScript --- src/clojuredocs.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/clojuredocs.ts b/src/clojuredocs.ts index 7dba9fe5b..296f363ec 100644 --- a/src/clojuredocs.ts +++ b/src/clojuredocs.ts @@ -147,8 +147,8 @@ async function clojureDocsLspLookup(session: nrepl.NReplSession, symbol: string, const resolved = await session.info(ns, symbol); const symNs = resolved.ns.replace(/^cljs\./, 'clojure.'); try { - const docs = await lsp.getClojuredocs(resolved.name, resolved.ns); - return rawDocs2DocsEntry({ clojuredocs: docs, fromServer: "clojure-lsp" }, resolved.name, symNs); + const docs = await lsp.getClojuredocs(resolved.name, symNs); + return rawDocs2DocsEntry({ clojuredocs: docs, fromServer: "clojure-lsp" }, resolved.name, resolved.ns); } catch { return rawDocs2DocsEntry({ clojuredocs: null, fromServer: "clojure-lsp" }, resolved.name, resolved.ns); } @@ -167,7 +167,7 @@ function rawDocs2DocsEntry(docsResult: any, symbol: string, ns: string): DocsEnt notes: docs.notes, ns: docs.ns, urlPath: docs.href.replace(/^\/?/, ''), - seeAlsos: docs['see-alsos'], + seeAlsos: docsResult.fromServer === 'clojure-lsp' ? docs['see-alsos'].map(also => `${also.ns}/${also.name}`) : docs['see-alsos'], tag: docs.tag, type: docs.type, fromServer: docsResult.fromServer From 2386d6f15785886e6bfd1b09223179deaac7b354 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Peter=20Str=C3=B6mberg?= Date: Mon, 1 Nov 2021 18:10:57 +0100 Subject: [PATCH 21/23] Remove debug logging --- src/clojuredocs.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/clojuredocs.ts b/src/clojuredocs.ts index 296f363ec..76c124e66 100644 --- a/src/clojuredocs.ts +++ b/src/clojuredocs.ts @@ -173,8 +173,7 @@ function rawDocs2DocsEntry(docsResult: any, symbol: string, ns: string): DocsEnt fromServer: docsResult.fromServer } } else { - // TODO: Remove this debug logging - console.log(`No results for ${ns}/${symbol} from ${docsResult.fromServer}`); + // console.log(`No results for ${ns}/${symbol} from ${docsResult.fromServer}`); return null; } } From 480efd1e74558966e035a4667190129310a6fe1c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Peter=20Str=C3=B6mberg?= Date: Mon, 1 Nov 2021 20:53:49 +0100 Subject: [PATCH 22/23] Fix new see-alsos bug --- src/clojuredocs.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/clojuredocs.ts b/src/clojuredocs.ts index 76c124e66..be0002b8f 100644 --- a/src/clojuredocs.ts +++ b/src/clojuredocs.ts @@ -167,7 +167,7 @@ function rawDocs2DocsEntry(docsResult: any, symbol: string, ns: string): DocsEnt notes: docs.notes, ns: docs.ns, urlPath: docs.href.replace(/^\/?/, ''), - seeAlsos: docsResult.fromServer === 'clojure-lsp' ? docs['see-alsos'].map(also => `${also.ns}/${also.name}`) : docs['see-alsos'], + seeAlsos: docsResult.fromServer === 'clojure-lsp' ? docs['see-alsos'].map(also => `${also.sym.ns}/${also.sym.name}`) : docs['see-alsos'], tag: docs.tag, type: docs.type, fromServer: docsResult.fromServer From 1f65f1597e174d3335f6cdaebfdf090915e6822a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Peter=20Str=C3=B6mberg?= Date: Mon, 1 Nov 2021 20:54:10 +0100 Subject: [PATCH 23/23] Add documeentation fixes #689 --- docs/site/clojuredocs.md | 75 ++++++++++++++++++ .../clojuredocs-hover-when-not-example-1.png | Bin 0 -> 141301 bytes mkdocs.yml | 1 + 3 files changed, 76 insertions(+) create mode 100644 docs/site/clojuredocs.md create mode 100644 docs/site/images/clojuredocs-hover-when-not-example-1.png diff --git a/docs/site/clojuredocs.md b/docs/site/clojuredocs.md new file mode 100644 index 000000000..95c56c1e9 --- /dev/null +++ b/docs/site/clojuredocs.md @@ -0,0 +1,75 @@ +# ClojureDocs integration + +[clojuredocs.org](https://clojuredocs.org) is the goto place #1 for finding out more about Clojure core(-ish) functions, macros, etcetera. It contains the doc strings from the functions and adds crowd sourced examples of usage and see alsos. You can surf for quite long on that site without getting bored. 😄 + +Calva integrates this information in two ways: + +1. Commands for requesting the ClojureDocs information for a symbol under the cursor: + * **Print clojuredocs.org examples to Rich Comment**, default keybinding: `ctrl+alt+r d` + * **Print clojuredocs.org examples to OutputWindow**, `ctrl+alt+o d` +2. ClojureDocs information is included in the symbol lookup hovers, where each example has two buttons: + * **To Rich Comment** + * **To Output Window** + +That means that if you just want to glance at the examples, you look in the hover. And when you want to bring the examples to the REPL to play with them, you can do so very easily. + +!!! Note "ClojureScript support" + ClojureDocs information is available both for Clojure and ClojureScript files. However, clojuredocs.org only keeps info for Clojure. Thus: _All information Calva shows about a symbol will be about the Clojure respresentation of that symbol._ (The symbol might not even exist in ClojureScript.) + +## ClojureDocs REPL Surfing + +Since the ClojureDocs information includes see-alsos, you can go for super interactive ClojureDocs surfing right in the file you are editing. Say you have this function: + +```clojure +(defn trim-text + "Returns text without surrounding whitespace if not empty, otherwise nil" + [text] + (let [trimmed-text (clojure.string/trim text)] + (when-not (empty? trimmed-text) + trimmed-text))) +``` + +Then you hover on `when-not` and scroll down a bit in the hover: + +![when-not ClojureDocs Hover Example 1](images/clojuredocs-hover-when-not-example-1.png) + +That first example would be interesting to play with, right? Click **To Rich Comment** and you will get: + +```clojure +(defn trim-text + "Returns text without surrounding whitespace if not empty, otherwise nil" + [text] + (let [trimmed-text (clojure.string/trim text)] + (when-not (empty? trimmed-text) + trimmed-text))) + +(comment + ;; = when-not - Example 1 = + + ;; build tuples over sets with the same cardinality + (map + #(when-not (= %2 %3) [%1 %2 %3]) + (iterate inc 0) ; a lazy list of indecies + [:a :b :c] + [:a :a :a]) + ;;=> (nil [1 :b :a] [2 :c :a]) + + ;; See also: + when + when-let + if + ) +``` + +There you can evaluate the `(map ...)` form using `alt+enter`, modify it and evaluate again. You can also hover over `map`, `iterate`, or any of the ”See also:” symbols to find more fun examples to play with. And so on and so forth. + +See these two tweets for some videos of early versions of this functionality: + +* [Rich Comments surfing ClojureDocs Examples](https://twitter.com/pappapez/status/1452325865933746185) +* [Clojuredocs in #Calva WIP 2: Hover examples -> RFC](https://twitter.com/pappapez/status/1452409528511762444) + +Please retweet! + +## Quirks + +Some of the ClojureDocs entries have text that is not really Clojure code, and sometimes even structural errors. This can break the structural integrity of your Clojure file. If you run into trouble trying to heal things, you can always use **Undo** until the Rich Comment is gone. \ No newline at end of file diff --git a/docs/site/images/clojuredocs-hover-when-not-example-1.png b/docs/site/images/clojuredocs-hover-when-not-example-1.png new file mode 100644 index 0000000000000000000000000000000000000000..44af3e3a8163440a1a3d51b111da05aa171dba4d GIT binary patch literal 141301 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 literal 0 HcmV?d00001 diff --git a/mkdocs.yml b/mkdocs.yml index 5a12e9007..f4020871c 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -35,6 +35,7 @@ nav: - commands-top10.md - evaluation.md - rich-comments.md + - clojuredocs.md - output.md - formatting.md - paredit.md