Skip to content

Commit

Permalink
feat: improved rg menu actions
Browse files Browse the repository at this point in the history
  • Loading branch information
joshmu committed Mar 31, 2023
1 parent 00af391 commit 13002db
Show file tree
Hide file tree
Showing 4 changed files with 85 additions and 44 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ This extension contributes the following settings:
* `rgOptions`: Additional options to pass to the 'rg' command, you can view all options in your terminal via 'rg --help'.
* `rgGlobExcludes`: Additional glob paths to exclude from the 'rg' search, eg: '__/dist/__'.
* `addSrcPaths`: Additional source paths to include in the rg search. You may want to add this as a workspace specific setting.
* `rgMenuActions`: Create menu items which can be selected prior to any query, these items will be added to the ripgrep command to generate the results. Eg: Add `-t js` as a menu option to only show javascript files in the results.
* `rgMenuActions`: Create menu items which can be selected prior to any query, these items will be added to the ripgrep command to generate the results. Eg: Add `{ label: "JS/TS", value: "--type-add 'jsts:*.{js|ts|tsx|jsx}' -t jsts" },` as a menu option to only show js & ts files in the results.
* `startFolderDisplayDepth`: The folder depth to display in the results before '...'.
* `endFolderDisplayDepth`: The folder depth to display in the results after '...'.
* `enableGotoNativeSearch`: If true, then swap to native vscode search if the custom suffix is entered using the current query.
Expand Down
15 changes: 13 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -58,9 +58,20 @@
"type": "array",
"default": [],
"items": {
"type": "string"
"type": "object",
"properties": {
"label": {
"type": "string",
"description": "The label of the menu item to display in the menu."
},
"value": {
"type": "string",
"description": "The value of ripgrep options you would like to include."
}
},
"required": ["value"]
},
"description": "Create menu items which can be selected prior to any query, these items will be added to the ripgrep command to generate the results. Eg: Add `-t js` as a menu option to only show javascript files in the results."
"description": "Create menu items which can be selected prior to any query, these items will be added to the ripgrep command to generate the results. Eg: Add `{ label: \"JS/TS\", value: \"--type-add 'jsts:*.{js|ts|tsx|jsx}' -t jsts\" },` as a menu option to only show js & ts files in the results."
},
"periscope.startFolderDisplayDepth": {
"type": "number",
Expand Down
110 changes: 70 additions & 40 deletions src/periscope.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,11 @@ import { getConfig } from './utils/getConfig';
import { getSelectedText } from './utils/getSelectedText';
import { highlightDecorationType } from './utils/decorationType';

export interface QuickPickItemCustom extends vscode.QuickPickItem {
export interface QPItemDefault extends vscode.QuickPickItem {
_type: 'QuickPickItemDefault'
}
export interface QPItemQuery extends vscode.QuickPickItem {
_type: 'QuickPickItemQuery'
// custom payload
data: {
filePath: string
Expand All @@ -14,17 +18,26 @@ export interface QuickPickItemCustom extends vscode.QuickPickItem {
rawResult: string
}
}
export interface QPItemRgMenuAction extends vscode.QuickPickItem {
_type: 'QuickPickItemRgMenuAction'
// custom payload
data: {
rgOption: string
}
}

type AllQPItemVariants = QPItemDefault | QPItemQuery | QPItemRgMenuAction;

export const periscope = () => {
let activeEditor: vscode.TextEditor | undefined;
let quickPick: vscode.QuickPick<vscode.QuickPickItem | QuickPickItemCustom>;
let qp: vscode.QuickPick<AllQPItemVariants>;
let workspaceFolders = vscode.workspace.workspaceFolders;
let query = '';
let highlightDecoration = highlightDecorationType();

let spawnProcess: ChildProcessWithoutNullStreams | undefined;
let config = getConfig();
let rgMenuActionsSelected: string[] = [];
let disposables: vscode.Disposable[] = [];

function register() {
setActiveContext(true);
Expand All @@ -33,40 +46,56 @@ export const periscope = () => {
workspaceFolders = vscode.workspace.workspaceFolders;
activeEditor = vscode.window.activeTextEditor;
// @see https://code.visualstudio.com/api/references/vscode-api#QuickPick
quickPick = vscode.window.createQuickPick();

quickPick.placeholder = '🫧';
qp = vscode.window.createQuickPick();

// if ripgrep actions are available then open preliminary quickpick
config.rgMenuActions.length ? setupRgMenuActions(quickPick) : setupQuickPickForQuery(quickPick);
const rgMenuActionsExist = config.rgMenuActions.length > 0;
rgMenuActionsExist ? setupRgMenuActions(qp) : setupQuickPickForQuery(qp);

quickPick.onDidHide(onDidHide);
quickPick.show();
disposables.push(
qp.onDidHide(onDidHide)
);
qp.show();
}

// when ripgrep actions are available show preliminary quickpick for those options to add to the query
function setupRgMenuActions(quickPick: vscode.QuickPick<vscode.QuickPickItem | QuickPickItemCustom>) {
quickPick.canSelectMany = true;

function setupRgMenuActions(qp: vscode.QuickPick<AllQPItemVariants>) {
qp.placeholder = '🫧 Rg Menu Actions (Space key to check/uncheck, Enter key to continue)';
qp.canSelectMany = true;

// add items from the config
quickPick.items = config.rgMenuActions.map(item => ({
label: item,
}));
qp.items = config.rgMenuActions.map(({value, label}) => ({
_type: 'QuickPickItemRgMenuAction',
label: label || value,
description: label ? value : undefined,
data: {
rgOption: value,
}
})
);

quickPick.onDidAccept(() => {
rgMenuActionsSelected = quickPick.selectedItems.map(item => item.label);
setupQuickPickForQuery(quickPick);
});
function next() {
rgMenuActionsSelected = (qp.selectedItems as QPItemRgMenuAction[]).map(item => item.data.rgOption);
setupQuickPickForQuery(qp as vscode.QuickPick<QPItemQuery>);
}

disposables.push(
qp.onDidTriggerButton(next),
qp.onDidAccept(next)
);
}

// update quickpick event listeners for the query
function setupQuickPickForQuery(quickPick: vscode.QuickPick<vscode.QuickPickItem | QuickPickItemCustom>) {
quickPick.items = [];
quickPick.canSelectMany = false;
quickPick.value = getSelectedText();
quickPick.onDidChangeValue(onDidChangeValue);
quickPick.onDidChangeActive(onDidChangeActive);
quickPick.onDidAccept(onDidAccept);
function setupQuickPickForQuery(qp: vscode.QuickPick<AllQPItemVariants>) {
qp.placeholder = '🫧';
qp.items = [];
qp.canSelectMany = false;
qp.value = getSelectedText();
disposables.push(
qp.onDidChangeValue(onDidChangeValue),
qp.onDidChangeActive(onDidChangeActive),
qp.onDidAccept(onDidAccept)
);
}

// create vscode context for the extension for targeted keybindings
Expand Down Expand Up @@ -94,13 +123,13 @@ export const periscope = () => {

search(value);
} else {
quickPick.items = [];
qp.items = [];
}
}

// when item is 'FOCUSSED'
function onDidChangeActive(items: readonly (vscode.QuickPickItem | QuickPickItemCustom)[]) {
peekItem(items as readonly QuickPickItemCustom[]);
function onDidChangeActive(items: readonly AllQPItemVariants[]) {
peekItem(items as readonly QPItemQuery[]);
}

// when item is 'SELECTED'
Expand All @@ -110,7 +139,7 @@ export const periscope = () => {

// when prompt is 'CANCELLED'
function onDidHide() {
if (!quickPick.selectedItems[0]) {
if (!qp.selectedItems[0]) {
if (activeEditor) {
vscode.window.showTextDocument(
activeEditor.document,
Expand All @@ -123,7 +152,7 @@ export const periscope = () => {
}

function search(value: string) {
quickPick.busy = true;
qp.busy = true;
const rgCmd = rgCommand(value);
console.log('PERISCOPE: rgCmd:', rgCmd);

Expand All @@ -143,7 +172,7 @@ export const periscope = () => {
return;
}
if (code === 0 && searchResultLines.length) {
quickPick.items = searchResultLines
qp.items = searchResultLines
.map(searchResult => {
// break the filename via regext ':line:col:'
const [filePath, linePos, colPos, ...textResult] =
Expand All @@ -163,7 +192,7 @@ export const periscope = () => {
searchResult
);
})
.filter(Boolean) as QuickPickItemCustom[];
.filter(Boolean) as QPItemQuery[];
} else if (code === 127) {
vscode.window.showErrorMessage(
`Periscope: Exited with code ${code}, ripgrep not found.`
Expand All @@ -175,7 +204,7 @@ export const periscope = () => {
} else {
vscode.window.showErrorMessage(`Ripgrep exited with code ${code}`);
}
quickPick.busy = false;
qp.busy = false;
});
}

Expand Down Expand Up @@ -215,7 +244,7 @@ export const periscope = () => {
return `rg '${value}' ${rgFlags.join(' ')}`;
}

function peekItem(items: readonly QuickPickItemCustom[]) {
function peekItem(items: readonly QPItemQuery[]) {
if (items.length === 0) {
return;
}
Expand All @@ -234,13 +263,12 @@ export const periscope = () => {
})
.then(editor => {
setPos(editor, linePos, colPos);

});
});
}

function accept() {
const currentItem = quickPick.selectedItems[0] as QuickPickItemCustom;
const currentItem = qp.selectedItems[0] as QPItemQuery;
if (!currentItem.data) {
return;
}
Expand All @@ -249,7 +277,7 @@ export const periscope = () => {
vscode.workspace.openTextDocument(filePath).then(document => {
vscode.window.showTextDocument(document).then(editor => {
setPos(editor, linePos, colPos);
quickPick.dispose();
qp.dispose();
});
});
}
Expand Down Expand Up @@ -282,8 +310,9 @@ export const periscope = () => {
linePos: number,
colPos: number,
rawResult?: string
): QuickPickItemCustom {
): QPItemQuery {
return {
_type: 'QuickPickItemQuery',
label: fileContents?.trim(),
data: {
filePath,
Expand Down Expand Up @@ -345,13 +374,14 @@ export const periscope = () => {
});

// close extension down
quickPick.hide();
qp.hide();
}

function finished() {
checkKillProcess();
highlightDecoration.remove();
setActiveContext(false);
disposables.forEach(d => d.dispose());
console.log('PERISCOPE: finished');
}

Expand Down
2 changes: 1 addition & 1 deletion src/utils/getConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ export function getConfig() {
]),
addSrcPaths: vsConfig.get<string[]>('addSrcPaths', []),
rgGlobExcludes: vsConfig.get<string[]>('rgGlobExcludes', []),
rgMenuActions: vsConfig.get<string[]>('rgMenuActions', []),
rgMenuActions: vsConfig.get<{label?: string, value: string}[]>('rgMenuActions', []),
startFolderDisplayDepth: vsConfig.get<number>('startFolderDisplayDepth', 1),
endFolderDisplayDepth: vsConfig.get<number>('endFolderDisplayDepth', 4),
enableGotoNativeSearch: vsConfig.get<boolean>(
Expand Down

0 comments on commit 13002db

Please sign in to comment.