From c34ae7898442be053faa7c252b68d6a5daa740b6 Mon Sep 17 00:00:00 2001 From: Josh Mu Date: Sat, 27 Apr 2024 14:50:43 +1000 Subject: [PATCH] fix: rg menu actions resolved via app state machine, additional refactor also --- src/lib/context.ts | 13 ++++++++++++- src/lib/editorActions.ts | 9 ++++----- src/lib/editorContext.ts | 8 -------- src/lib/globalActions.ts | 26 +++++++++++++++++++++----- src/lib/periscope.ts | 13 ++++--------- src/lib/quickpickActions.ts | 10 +++++----- src/lib/ripgrep.ts | 6 ++++-- 7 files changed, 50 insertions(+), 35 deletions(-) delete mode 100644 src/lib/editorContext.ts diff --git a/src/lib/context.ts b/src/lib/context.ts index d570721..8876a91 100644 --- a/src/lib/context.ts +++ b/src/lib/context.ts @@ -7,6 +7,7 @@ import { initHighlightLineInstance } from '../utils/highlightLineDecorationType' // simple context for each invoke of periscope search let qp = vscode.window.createQuickPick(); // @see https://code.visualstudio.com/api/references/vscode-api#QuickPick let workspaceFolders = vscode.workspace.workspaceFolders; +let previousActiveEditor = vscode.window.activeTextEditor; let query = ''; let spawnRegistry: ChildProcessWithoutNullStreams[] = []; let config = getConfig(); @@ -17,23 +18,27 @@ let disposables: DisposablesMap = { rgMenuActions: [], query: [], }; +let appState = updateAppState('IDLE'); export const context = { resetContext, qp, workspaceFolders, + previousActiveEditor, query, spawnRegistry, config, rgMenuActionsSelected, highlightDecoration, - disposables + disposables, + appState }; // reset the context function resetContext() { context.qp = vscode.window.createQuickPick(); context.workspaceFolders = vscode.workspace.workspaceFolders; + context.previousActiveEditor = vscode.window.activeTextEditor; context.query = ''; context.spawnRegistry = []; context.config = getConfig(); @@ -44,4 +49,10 @@ function resetContext() { rgMenuActions: [], query: [], }; +} + +type AppState = 'IDLE' | 'SEARCHING' | 'FINISHED'; +export function updateAppState(state: AppState) { + if (context?.appState) {context.appState = state;} + return state; } \ No newline at end of file diff --git a/src/lib/editorActions.ts b/src/lib/editorActions.ts index 9670a9c..63b1c2a 100644 --- a/src/lib/editorActions.ts +++ b/src/lib/editorActions.ts @@ -1,13 +1,12 @@ import * as vscode from 'vscode'; import * as path from 'path'; -import { previousActiveEditor, updatePreviousActiveEditor } from './editorContext'; import { AllQPItemVariants, QPItemQuery } from '../types'; import { context as cx } from './context'; export function closePreviewEditor() { - if(previousActiveEditor) { + if(cx.previousActiveEditor) { vscode.commands.executeCommand('workbench.action.closeActiveEditor'); - updatePreviousActiveEditor(undefined); // prevent focus onDidHide + cx.previousActiveEditor = undefined; // prevent focus onDidHide } } @@ -92,8 +91,8 @@ export function handleNoResultsFound() { } export function showPreviewOfOriginDocument() { - if (!previousActiveEditor) {return;} - vscode.window.showTextDocument(previousActiveEditor.document, { + if (!cx.previousActiveEditor) {return;} + vscode.window.showTextDocument(cx.previousActiveEditor.document, { preserveFocus: true, preview: true }); diff --git a/src/lib/editorContext.ts b/src/lib/editorContext.ts deleted file mode 100644 index df0765c..0000000 --- a/src/lib/editorContext.ts +++ /dev/null @@ -1,8 +0,0 @@ -// lib/editorContext.ts -import * as vscode from 'vscode'; - -export let previousActiveEditor: vscode.TextEditor | undefined; - -export function updatePreviousActiveEditor(editor: vscode.TextEditor | undefined) { - previousActiveEditor = editor; -} diff --git a/src/lib/globalActions.ts b/src/lib/globalActions.ts index e75fb41..7d0003c 100644 --- a/src/lib/globalActions.ts +++ b/src/lib/globalActions.ts @@ -1,9 +1,8 @@ import * as vscode from 'vscode'; import * as path from 'path'; import { log } from "../utils/log"; -import { updatePreviousActiveEditor } from "./editorContext"; import { checkKillProcess } from "./ripgrep"; -import { context as cx } from './context'; +import { context as cx, updateAppState } from './context'; import { QPItemQuery } from '../types'; import { closePreviewEditor, setCursorPosition } from './editorActions'; @@ -44,17 +43,34 @@ export function confirm(payload: ConfirmPayload = {context: 'unknown'}) { }); } +// start periscope extension/search +export function start() { + log('start'); + cx.resetContext(); + setExtensionActiveContext(true); +} + +// end periscope extension export function finished() { + setExtensionActiveContext(false); + updateAppState('FINISHED'); checkKillProcess(); cx.highlightDecoration.remove(); - setActiveContext(false); disposeAll(); - updatePreviousActiveEditor(undefined); + cx.previousActiveEditor = undefined; log('finished'); } // create vscode context for the extension for targeted keybindings -export function setActiveContext(flag: boolean) { +/** + * eg: + * { + "key": "ctrl+\\", + "command": "periscope.openInHorizontalSplit", + "when": "periscopeActive" <<< this is the context + } + */ +export function setExtensionActiveContext(flag: boolean) { log(`setContext ${flag}`); vscode.commands.executeCommand('setContext', 'periscopeActive', flag); } diff --git a/src/lib/periscope.ts b/src/lib/periscope.ts index c8a62ec..ca8a7da 100644 --- a/src/lib/periscope.ts +++ b/src/lib/periscope.ts @@ -1,17 +1,10 @@ -import * as vscode from 'vscode'; -import { updatePreviousActiveEditor } from './editorContext'; -import { log } from '../utils/log'; import { context as cx } from './context'; import { onDidHide, setupQuickPickForQuery, setupRgMenuActions } from './quickpickActions'; -import { setActiveContext } from './globalActions'; +import { start } from './globalActions'; import { openInHorizontalSplit } from './editorActions'; function search() { - cx.resetContext(); - log('start'); - - setActiveContext(true); - updatePreviousActiveEditor(vscode.window.activeTextEditor); + start(); // if ripgrep actions are available then open preliminary quickpick const openRgMenuActions = cx.config.alwaysShowRgMenuActions && cx.config.rgMenuActions.length > 0; @@ -20,6 +13,8 @@ function search() { cx.disposables.general.push( cx.qp.onDidHide(onDidHide) ); + + // search logic is triggered from the QuickPick event handlers... cx.qp.show(); } diff --git a/src/lib/quickpickActions.ts b/src/lib/quickpickActions.ts index 20fe32d..0af89af 100644 --- a/src/lib/quickpickActions.ts +++ b/src/lib/quickpickActions.ts @@ -2,10 +2,9 @@ import * as vscode from 'vscode'; import { AllQPItemVariants, QPItemQuery, QPItemRgMenuAction } from "../types"; import { openNativeVscodeSearch, peekItem } from "./editorActions"; import { checkKillProcess, checkAndExtractRgFlagsFromQuery, rgSearch } from "./ripgrep"; -import { context as cx } from './context'; +import { context as cx, updateAppState } from './context'; import { getSelectedText } from "../utils/getSelectedText"; import { log } from '../utils/log'; -import { previousActiveEditor } from './editorContext'; import { confirm, finished } from './globalActions'; // update quickpick event listeners for the query @@ -99,10 +98,10 @@ function onDidTriggerItemButton(e: vscode.QuickPickItemButtonEvent { - if (code === 0 && searchResults.length) { + // we need to additionally check 'SEARCHING' state as the user might have cancelled the search but the process may still be running (eg: go back to the rg menu actions view) + if (code === 0 && searchResults.length && cx.appState === 'SEARCHING') { cx.qp.items = searchResults .map(searchResult => { // break the filename via regext ':line:col:'