Skip to content

Commit 87de317

Browse files
committed
Add actions menu
1 parent a9d4288 commit 87de317

File tree

5 files changed

+136
-37
lines changed

5 files changed

+136
-37
lines changed

package.json

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -571,12 +571,26 @@
571571
"shortTitle": "Open Spelling Issues",
572572
"icon": "$(eye)"
573573
},
574+
{
575+
"command": "cSpell.openFileInfoView",
576+
"category": "Spell",
577+
"title": "Open Spell Checker File Information View",
578+
"shortTitle": "Open File Info",
579+
"icon": "$(eye)"
580+
},
574581
{
575582
"command": "cSpell.restart",
576583
"category": "Spell",
577584
"title": "Restart Spell Checker Server",
578585
"shortTitle": "Restart Spell Checker",
579586
"icon": "$(sync)"
587+
},
588+
{
589+
"command": "cspell.showActionsMenu",
590+
"category": "Spell",
591+
"title": "Show Spell Checker Actions Menu",
592+
"shortTitle": "Spell Checker Actions",
593+
"icon": "$(list-unordered)"
580594
}
581595
],
582596
"languages": [

packages/client/src/commands.mts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,7 +170,10 @@ export const commandHandlers = {
170170
'cSpell.hide': handlerResolvedLater,
171171
'cSpell.createCSpellTerminal': handlerResolvedLater,
172172

173+
'cspell.showActionsMenu': handlerResolvedLater,
174+
173175
'cSpell.openIssuesPanel': callCommand('cspell.issuesViewByFile.focus'),
176+
'cSpell.openFileInfoView': callCommand('cspell-info.infoView.focus'),
174177

175178
'cSpell.restart': handleRestart,
176179

packages/client/src/extension.mts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import { IssueTracker } from './issueTracker.mjs';
2323
import { activateFileIssuesViewer, activateIssueViewer } from './issueViewer/index.mjs';
2424
import { createLanguageStatus } from './languageStatus.mjs';
2525
import * as modules from './modules.mjs';
26+
import { registerActionsMenu } from './quickMenu.mjs';
2627
import { createTerminal, registerTerminalProfileProvider } from './repl/index.mjs';
2728
import type { ConfigTargetLegacy, CSpellSettings } from './settings/index.mjs';
2829
import * as settings from './settings/index.mjs';
@@ -58,11 +59,11 @@ export async function activate(context: ExtensionContext): Promise<ExtensionApi>
5859

5960
// Start the client.
6061
await client.start();
61-
const statusBar = initStatusBar(context, client);
62-
6362
const issueTracker = new IssueTracker(client);
6463
di.set('issueTracker', issueTracker);
6564

65+
const statusBar = initStatusBar(context, client);
66+
6667
function triggerGetSettings(delayInMs = 0) {
6768
setTimeout(triggerGetSettingsNow, delayInMs);
6869
}
@@ -130,6 +131,7 @@ export async function activate(context: ExtensionContext): Promise<ExtensionApi>
130131
*/
131132
vscode.workspace.onDidChangeConfiguration(handleOnDidChangeConfiguration),
132133
createLanguageStatus(),
134+
registerActionsMenu({ areIssuesVisible: () => decorator.visible }),
133135
);
134136

135137
await registerCspellInlineCompletionProviders(context.subscriptions).catch(() => undefined);

packages/client/src/quickMenu.mts

Lines changed: 111 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,46 +1,125 @@
1+
import { isDefined } from '@internal/common-utils';
12
import { createDisposableList } from 'utils-disposables';
2-
import type { Disposable, QuickPickItem, Uri } from 'vscode';
3+
import type { Disposable, QuickPickItem } from 'vscode';
34
import vscode from 'vscode';
45

5-
export function registerQuickMenu(): Disposable {
6+
import { knownCommands } from './commands.mjs';
7+
import { logErrors } from './util/errors.js';
8+
9+
export interface ActionsMenuOptions {
10+
areIssuesVisible: () => boolean;
11+
}
12+
13+
export function registerActionsMenu(options: ActionsMenuOptions): Disposable {
614
const dList = createDisposableList();
7-
dList.push(vscode.commands.registerCommand('cspell.quickMenu.show', quickPickMenu));
15+
dList.push(vscode.commands.registerCommand('cspell.showActionsMenu', () => quickPickMenu(options)));
816
return dList;
917
}
1018

11-
export class MessageItem implements QuickPickItem {
12-
label: string;
13-
description = '';
14-
detail: string;
19+
interface ActionMenuItem extends QuickPickItem {
20+
action?: (() => void | Promise<void>) | undefined;
21+
}
22+
23+
export class MenuItem implements ActionMenuItem {
24+
#action?: (() => void | Promise<void>) | undefined;
25+
kind?: QuickPickItem['kind'] | undefined;
26+
detail?: string | undefined;
27+
picked?: boolean | undefined;
28+
iconPath?: QuickPickItem['iconPath'] | undefined;
29+
alwaysShow?: boolean | undefined;
30+
buttons?: readonly vscode.QuickInputButton[] | undefined;
31+
constructor(
32+
public label: string,
33+
public description?: string,
34+
action?: (() => void | Promise<void>) | undefined,
35+
) {
36+
this.#action = action;
37+
}
38+
39+
action() {
40+
return this.#action?.();
41+
}
42+
}
1543

44+
export class CommandMenuItem extends MenuItem {
1645
constructor(
17-
public base: Uri,
18-
public message: string,
46+
readonly command: vscode.Command,
47+
public description?: string,
1948
) {
20-
this.label = message.replace(/\r?\n/g, ' ');
21-
this.detail = base.fsPath;
49+
super(command.title, description);
2250
}
51+
52+
async action() {
53+
await vscode.commands.executeCommand(this.command.command, ...(this.command.arguments || []));
54+
}
55+
}
56+
57+
async function quickPickMenu(options: ActionsMenuOptions) {
58+
const items: QuickPickItem[] = [
59+
menuItem('Item 1', 'Description for Item 1'),
60+
menuItem('Item 2', 'Description for Item 2'),
61+
{ label: '', kind: vscode.QuickPickItemKind.Separator },
62+
itemIssuesShowHide(options),
63+
menuItem({ label: '$(book) Dictionaries...' }),
64+
itemCommand({ title: '$(file) Show File Info...', command: knownCommands['cSpell.openFileInfoView'] }),
65+
itemCommand({ title: '$(console) Open Spell Checker REPL Console.', command: knownCommands['cSpell.createCSpellTerminal'] }),
66+
itemCommand({ title: '$(issues) Open Spelling Issues Panel.', command: 'cSpell.openIssuesPanel' }),
67+
itemSeparator(),
68+
itemCommand({
69+
title: '$(keyboard) Edit Keyboard Shortcuts...',
70+
command: 'workbench.action.openGlobalKeybindings',
71+
arguments: ['Spell:'],
72+
}),
73+
itemCommand({ title: '$(gear) Edit Settings...', command: 'workbench.action.openSettings', arguments: ['cSpell'] }),
74+
].filter(isDefined);
75+
const quickPick = vscode.window.createQuickPick<QuickPickItem>();
76+
quickPick.title = 'Spell Checker Actions Menu';
77+
quickPick.items = items;
78+
quickPick.onDidChangeSelection((selection) => {
79+
console.log('onDidChangeSelection', selection);
80+
});
81+
quickPick.onDidChangeActive((active) => {
82+
console.log('onDidChangeActive', active);
83+
});
84+
quickPick.onDidAccept(() => {
85+
console.log('onDidAccept', quickPick.activeItems);
86+
const item = quickPick.activeItems[0];
87+
if (item instanceof MenuItem && item.action) {
88+
logErrors(Promise.resolve(item.action()), 'quickPickMenu');
89+
}
90+
quickPick.dispose();
91+
});
92+
quickPick.onDidHide(() => {
93+
console.log('onDidHide');
94+
});
95+
quickPick.show();
96+
}
97+
98+
function menuItem(item: QuickPickItem): MenuItem;
99+
function menuItem(label: string, description?: string): MenuItem;
100+
function menuItem(labelOrItem: string | QuickPickItem, description?: string): MenuItem {
101+
if (typeof labelOrItem === 'string') return new MenuItem(labelOrItem, description);
102+
const item = new MenuItem(labelOrItem.label, labelOrItem.description);
103+
item.kind = labelOrItem.kind;
104+
item.iconPath = labelOrItem.iconPath;
105+
item.alwaysShow = labelOrItem.alwaysShow;
106+
item.buttons = labelOrItem.buttons;
107+
item.detail = labelOrItem.detail;
108+
item.picked = labelOrItem.picked;
109+
return item;
110+
}
111+
112+
function itemCommand(command: vscode.Command, description?: string) {
113+
return new CommandMenuItem(command, description);
114+
}
115+
116+
function itemSeparator(): QuickPickItem {
117+
return { label: '', kind: vscode.QuickPickItemKind.Separator };
23118
}
24119

25-
async function quickPickMenu() {
26-
// const items: QuickPickItem[] = [
27-
// { label: 'Item 1', description: 'Description for Item 1' },
28-
// { label: 'Item 2', description: 'Description for Item 2' },
29-
// { label: 'Item 3', description: 'Description for Item 3' },
30-
// ];
31-
// const quickPick = vscode.window.createQuickPick<QuickPickItem>();
32-
// quickPick.items = items;
33-
// quickPick.onDidChangeSelection((selection) => {
34-
// console.log('onDidChangeSelection', selection);
35-
// });
36-
// quickPick.onDidChangeActive((active) => {
37-
// console.log('onDidChangeActive', active);
38-
// });
39-
// quickPick.onDidAccept(() => {
40-
// console.log('onDidAccept');
41-
// });
42-
// quickPick.onDidHide(() => {
43-
// console.log('onDidHide');
44-
// });
45-
// quickPick.show();
120+
function itemIssuesShowHide(options: Pick<ActionsMenuOptions, 'areIssuesVisible'>) {
121+
const visible = options.areIssuesVisible();
122+
return visible
123+
? itemCommand({ title: '$(eye-closed) Hide Spelling Issues', command: 'cSpell.hide' })
124+
: itemCommand({ title: '$(eye) Show Spelling Issues', command: 'cSpell.show' });
46125
}

packages/client/src/statusbar.mts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,9 @@ import { window, workspace } from 'vscode';
66
import * as vscode from 'vscode';
77

88
import type { CSpellClient, ServerResponseIsSpellCheckEnabledForFile } from './client/index.mjs';
9+
import { knownCommands } from './commands.mjs';
10+
import { getIssueTracker } from './di.mjs';
911
import { getCSpellDiags } from './diags.mjs';
10-
import * as infoViewer from './infoViewer/index.js';
1112
import { sectionCSpell } from './settings/index.mjs';
1213

1314
const statusBarId = 'spell checker status id';
@@ -115,7 +116,7 @@ export function initStatusBar(context: ExtensionContext, client: CSpellClient):
115116
response.blockedReason && toolTip.appendMarkdown(`- ${response.blockedReason.message}\n`);
116117
toolTip.isTrusted = true;
117118
sbCheck.tooltip = toolTip;
118-
sbCheck.command = infoViewer.commandDisplayCSpellInfo;
119+
sbCheck.command = knownCommands['cspell.showActionsMenu'];
119120
sbCheck.show();
120121
}
121122
}
@@ -215,7 +216,7 @@ export function initStatusBar(context: ExtensionContext, client: CSpellClient):
215216
window.onDidChangeActiveTextEditor(onDidChangeActiveTextEditor),
216217
workspace.onDidChangeConfiguration(onDidChangeConfiguration),
217218
workspace.onDidCloseTextDocument(updateStatusBar),
218-
vscode.languages.onDidChangeDiagnostics(onDidChangeDiag),
219+
getIssueTracker().onDidChangeDiagnostics(onDidChangeDiag),
219220
sbCheck,
220221
);
221222

0 commit comments

Comments
 (0)