Skip to content

Commit

Permalink
Add new manage clojure-lsp menu
Browse files Browse the repository at this point in the history
  • Loading branch information
julienvincent committed Jan 16, 2023
1 parent fa2d38f commit 995b865
Show file tree
Hide file tree
Showing 3 changed files with 129 additions and 83 deletions.
5 changes: 5 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -991,6 +991,11 @@
"title": "Restart the Clojure LSP Server",
"category": "Calva Clojure LSP"
},
{
"command": "calva.clojureLsp.manage",
"title": "Manage Clojure LSP Servers",
"category": "Calva Clojure LSP"
},
{
"command": "calva.diagnostics.openClojureLspLogFile",
"title": "Open Clojure LSP Log File",
Expand Down
205 changes: 123 additions & 82 deletions src/lsp/commands/vscode-commands.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import * as vscode_lsp from 'vscode-languageclient/node';
import * as project_utils from '../../project-root';
import * as downloader from '../client/downloader';
import * as defs from '../definitions';
Expand All @@ -15,17 +14,16 @@ export const filterOutRootsWithClients = (
});
};

type StartHandler = (uri: vscode.Uri) => Promise<void>;

/**
* Handle the start lsp command.
*
* This will search for and list all Clojure project roots in the active workspace, allowing the user to pick the
* root they would like to start an LSP server under. All clojure files at and below this root will be served by
* this LSP client.
*/
const startHandler = async (
clients: defs.LSPClientMap,
handler: (uri: vscode.Uri) => Promise<void>
) => {
const startHandler = async (clients: defs.LSPClientMap, handler: StartHandler) => {
const document = vscode.window.activeTextEditor?.document;
if (!document || document.languageId !== 'clojure') {
return;
Expand Down Expand Up @@ -53,63 +51,54 @@ const startHandler = async (
await handler(selected_root);
};

const pickClient = async (
clients: defs.LSPClientMap
): Promise<undefined | [string, vscode_lsp.LanguageClient]> => {
const pickClient = async (clients: defs.LSPClientMap) => {
if (clients.size === 0) {
return;
}
if (clients.size === 1) {
return Array.from(clients.entries())[0];
return Array.from(clients.keys())[0];
}
const choices = Array.from(clients.keys()).map((uri) => {
return {
label: uri,
};
});
const selected_client = await vscode.window.showQuickPick(choices, { title: 'clojure-lsp' });
if (!selected_client) {
return;
}
return [selected_client.label, clients.get(selected_client.label)];
return selected_client?.label;
};

const stopClient = (clients: defs.LSPClientMap, id: string) => {
const client = clients.get(id);
return client?.stop().catch((err) => {
console.error(`Failed to stop client ${id}`, err);
});
};

const stopHandler = async (clients: defs.LSPClientMap) => {
const res = await pickClient(clients);
if (!res) {
const id = await pickClient(clients);
if (!id) {
return;
}
const [id, client] = res;
client?.stop().catch((err) => {
console.error(`Failed to stop client ${id}`, err);
});
stopClient(clients, id);
};

const restartHandler = async (
clients: defs.LSPClientMap,
startHandler: (uri: vscode.Uri) => Promise<void>
) => {
const res = await pickClient(clients);
if (!res) {
const id = await pickClient(clients);
if (!id) {
return;
}
const [id, client] = res;

await client?.stop().catch((err) => {
console.error(`Failed to stop client ${id}`, err);
});

await stopClient(clients, id);
clients.delete(id);

await startHandler(vscode.Uri.parse(id));
};

async function serverInfoHandler(clients: defs.LSPClientMap) {
const res = await pickClient(clients);
if (!res) {
return;
}
const [, client] = res;
async function showServerInfo(clients: defs.LSPClientMap, id: string) {
const client = clients.get(id);

const serverInfo = await api.getServerInfo(client);
const calvaSaysChannel = state.outputChannel();
Expand All @@ -119,68 +108,118 @@ async function serverInfoHandler(clients: defs.LSPClientMap) {
calvaSaysChannel.show(true);
}

async function openLogFileHandler(clients: defs.LSPClientMap) {
const res = await pickClient(clients);
if (!res) {
return;
}
const [, client] = res;
async function openLogFile(clients: defs.LSPClientMap, id: string) {
const client = clients.get(id);

const serverInfo = await api.getServerInfo(client);
const logPath = serverInfo['log-path'];
void vscode.window.showTextDocument(vscode.Uri.file(logPath));
}

function configureTraceLogLevelHandler() {
void vscode.commands.executeCommand('workbench.action.openSettings', 'clojure.trace.server');
}
const manageHandler = async (clients: defs.LSPClientMap, start: StartHandler) => {
const choice = await vscode.window.showQuickPick(
[
{
label: 'Start a clojure-lsp server',
value: '::start',
},

const showMenuHandler = async () => {
const items = [
{
label: 'Start',
description: 'Start a clojure-lsp server at a directory',
value: 'calva.clojureLsp.start',
},
{
label: 'Stop',
description: 'Stop a running clojure-lsp server',
value: 'calva.clojureLsp.stop',
},
{
label: 'Restart',
description: 'Restart a running clojure-lsp server',
value: 'calva.clojureLsp.restart',
},
{
label: 'Show server info',
description: 'Print clojure-lsp server info to `Calva says`',
value: 'calva.diagnostics.clojureLspServerInfo',
},
{
label: 'Open log',
description: 'Open the clojure-lsp log file',
value: 'calva.diagnostics.openClojureLspLogFile',
},
{
label: 'Open Trace Level Settings',
description: 'Opens the client/server trace level in VS Code Settings',
value: 'calva.diagnostics.showLspTraceLevelSettings',
},
];
{
label: 'Running Clients',
kind: vscode.QuickPickItemKind.Separator,
value: undefined,
},

...Array.from(clients.keys()).map((key) => {
return {
label: key,
value: key,
};
}),
],
{ title: 'clojure-lsp' }
);

const choice = await vscode.window.showQuickPick(items, { title: 'clojure-lsp' });
if (!choice) {
return;
}

await vscode.commands.executeCommand(choice.value);
if (choice.value === '::start') {
return startHandler(clients, start);
}

const action = await vscode.window.showQuickPick(
[
{
label: 'Stop',
value: '::stop',
},
{
label: 'Restart',
value: '::restart',
},
{
label: 'Show server info',
value: '::info',
},
{
label: 'Show server logs',
value: '::logs',
},
],
{ title: 'action' }
);
if (!action) {
return;
}

switch (action.value) {
case '::stop': {
stopClient(clients, choice.value);
return;
}
case '::restart': {
await stopClient(clients, choice.value);
clients.delete(choice.value);

await start(vscode.Uri.parse(choice.value));
return;
}
case '::info': {
showServerInfo(clients, choice.value);
return;
}
case '::logs': {
openLogFile(clients, choice.value);
return;
}
}
};

async function showServerInfoHandler(clients: defs.LSPClientMap) {
const id = await pickClient(clients);
if (!id) {
return;
}
return showServerInfo(clients, id);
}

async function openLogFileHandler(clients: defs.LSPClientMap) {
const id = await pickClient(clients);
if (!id) {
return;
}
return openLogFile(clients, id);
}

function configureTraceLogLevelHandler() {
void vscode.commands.executeCommand('workbench.action.openSettings', 'clojure.trace.server');
}

type RegisterCommandsParams = {
clients: defs.LSPClientMap;
context: vscode.ExtensionContext;
handleStartRequest: (uri: vscode.Uri) => Promise<void>;
handleStartRequest: StartHandler;
};
export const registerVSCodeCommands = (params: RegisterCommandsParams) => {
return [
Expand All @@ -198,13 +237,19 @@ export const registerVSCodeCommands = (params: RegisterCommandsParams) => {
);
}),

vscode.commands.registerCommand('calva.clojureLsp.manage', () => {
manageHandler(params.clients, params.handleStartRequest).catch((err) =>
console.error('Failed to run manage command', err)
);
}),

vscode.commands.registerCommand('calva.clojureLsp.download', async () => {
const version = await downloader.ensureLSPServer(params.context, true);
void vscode.window.showInformationMessage(`Downloaded clojure-lsp version: ${version}`);
}),

vscode.commands.registerCommand('calva.diagnostics.clojureLspServerInfo', () => {
serverInfoHandler(params.clients).catch((err) =>
showServerInfoHandler(params.clients).catch((err) =>
console.error('Failed to run server info command', err)
);
}),
Expand All @@ -219,9 +264,5 @@ export const registerVSCodeCommands = (params: RegisterCommandsParams) => {
'calva.diagnostics.showLspTraceLevelSettings',
configureTraceLogLevelHandler
),

vscode.commands.registerCommand('calva.clojureLsp.showClojureLspMenu', () => {
showMenuHandler().catch((err) => console.error('Failed to run lsp menu', err));
}),
];
};
2 changes: 1 addition & 1 deletion src/lsp/provider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ export const createClientProvider = (params: CreateClientProviderParams) => {
const clients = new Map<string, vscode_lsp.LanguageClient>();

const status_bar_item = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Left, 0);
status_bar_item.command = 'calva.clojureLsp.showClojureLspMenu';
status_bar_item.command = 'calva.clojureLsp.manage';

const config = vscode.workspace.getConfiguration('calva');

Expand Down

0 comments on commit 995b865

Please sign in to comment.