From 5be3d432df2edcdcc603baa9f46a50eccca2500f Mon Sep 17 00:00:00 2001 From: Corwin Marsh Date: Fri, 3 Apr 2026 12:42:46 -0700 Subject: [PATCH 1/2] feat: add preview-by-default setting --- README.md | 4 + package.json | 5 ++ src/commands/openOil.ts | 11 ++- src/test/extension.test.ts | 152 ++++++++++++++++++++++++++++++++++++- src/utils/settings.ts | 5 ++ 5 files changed, 175 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 89961d5..88f23ca 100644 --- a/README.md +++ b/README.md @@ -179,6 +179,10 @@ The alternate confirmation dialog provides a QuickPick interface where you can: - Type `N` to cancel and discard changes - Press `Esc` or click outside to cancel +## Default Preview + +You can enable preview automatically when opening oil by setting `"oil-code.previewByDefault": true`. + ## Other great extensions - [vsnetrw](https://github.com/danprince/vsnetrw): Another great option for a split file explorer. diff --git a/package.json b/package.json index 6cbaaca..14a4a59 100644 --- a/package.json +++ b/package.json @@ -170,6 +170,11 @@ "type": "boolean", "default": false, "description": "Enable alternate confirmation dialog for file operations. When enabled, uses a QuickPick interface instead of the default modal confirmation dialog. Default is false." + }, + "oil-code.previewByDefault": { + "type": "boolean", + "default": false, + "description": "Enable preview automatically when opening oil. Default is false." } } } diff --git a/src/commands/openOil.ts b/src/commands/openOil.ts index 8023498..4117fa0 100644 --- a/src/commands/openOil.ts +++ b/src/commands/openOil.ts @@ -3,11 +3,15 @@ import * as vscode from "vscode"; import { oilFileProvider } from "../providers/providers"; import { initOilStateWithPath, initOilState } from "../state/initState"; import { setOilState } from "../state/oilState"; -import { checkAndDisableAutoSave } from "../utils/settings"; +import { + checkAndDisableAutoSave, + getPreviewByDefaultSetting, +} from "../utils/settings"; import { logger } from "../logger"; import { openParent } from "./openParent"; import { positionCursorOnFile } from "../utils/oilUtils"; import { resetPreviewState } from "../state/previewState"; +import { preview } from "./preview"; export async function openOil(atPath?: string | undefined) { logger.trace("Opening oil file..."); @@ -39,6 +43,11 @@ export async function openOil(atPath?: string | undefined) { // Position cursor on the active file if it exists positionCursorOnFile(editor, activeFile); + + if (getPreviewByDefaultSetting()) { + await preview(true); + } + await checkAndDisableAutoSave(); } catch (error) { vscode.window.showErrorMessage(`Failed to open oil file: ${error}`); diff --git a/src/test/extension.test.ts b/src/test/extension.test.ts index 0894f58..513f4aa 100644 --- a/src/test/extension.test.ts +++ b/src/test/extension.test.ts @@ -39,23 +39,37 @@ async function cleanupTestDir() { } } +async function setPreviewByDefault(enabled: boolean) { + await vscode.workspace + .getConfiguration("oil-code") + .update( + "previewByDefault", + enabled, + vscode.ConfigurationTarget.Global + ); +} + suite("oil.code", () => { // Setup and teardown for Sinon stubs let showWarningMessageStub: sinon.SinonStub; let executeCommandSpy: sinon.SinonStub; - setup(() => { + setup(async () => { + await cleanupTestDir(); + // Stub vscode.window.showWarningMessage to automatically return a response // This avoids blocking dialogs during tests showWarningMessageStub = sinon.stub(vscode.window, "showWarningMessage"); // Default to "Yes" response for dialogs showWarningMessageStub.resolves("Yes"); + await setPreviewByDefault(false); }); teardown(async () => { // Restore the original methods after each test showWarningMessageStub.restore(); executeCommandSpy?.restore(); + await setPreviewByDefault(false); await vscode.commands.executeCommand("oil-code.close"); await sleep(100); @@ -656,6 +670,142 @@ suite("oil.code", () => { }); }); + test("Preview does not open by default when disabled", async () => { + const fileUri = vscode.Uri.joinPath( + vscode.workspace.workspaceFolders![0].uri, + "oil-file.md" + ); + await vscode.workspace.fs.writeFile(fileUri, Buffer.from("test", "utf-8")); + + const fileDoc = await vscode.workspace.openTextDocument(fileUri); + await vscode.window.showTextDocument(fileDoc); + + await vscode.commands.executeCommand("oil-code.open"); + await waitForDocumentText(["/000 ../", "/001 oil-file.md"]); + await sleep(200); + + const previewEditor = vscode.window.visibleTextEditors.find( + (editor) => editor.document.uri.scheme === "oil-preview" + ); + + assert.ok(!previewEditor, "Preview editor unexpectedly opened"); + assert.strictEqual( + vscode.window.tabGroups.all.at(1)?.tabs.length ?? 0, + 0, + "Preview tab unexpectedly opened" + ); + }); + + test("Preview opens by default when enabled", async () => { + const testContent = `# Oil FileThis${newline}is a test file for Oil Code extension.`; + const fileUri = vscode.Uri.joinPath( + vscode.workspace.workspaceFolders![0].uri, + "oil-file.md" + ); + await setPreviewByDefault(true); + await vscode.workspace.fs.writeFile(fileUri, Buffer.from(testContent, "utf-8")); + + const fileDoc = await vscode.workspace.openTextDocument(fileUri); + await vscode.window.showTextDocument(fileDoc); + + await vscode.commands.executeCommand("oil-code.open"); + await waitForDocumentText(["/000 ../", "/001 oil-file.md"]); + + await waitFor(() => { + const previewTab = vscode.window.tabGroups.all.at(1)?.tabs.at(0); + assert.ok(previewTab, "Preview tab not found"); + assert.strictEqual( + (previewTab.input as vscode.TabInputText).uri.toString(), + "oil-preview://oil-preview/oil-file.md" + ); + const previewEditor = vscode.window.visibleTextEditors.find( + (editor) => + editor.document.uri.toString() === + "oil-preview://oil-preview/oil-file.md" + ); + assert.ok(previewEditor, "No editor found for the preview tab"); + assert.strictEqual( + previewEditor.document.getText(), + testContent, + "Preview content does not match expected content" + ); + }); + }); + + test("Preview by default updates during directory navigation", async () => { + const testContent = `# Oil FileThis${newline}is a test file for Oil Code extension.`; + await setPreviewByDefault(true); + await vscode.workspace.fs.createDirectory( + vscode.Uri.joinPath(vscode.workspace.workspaceFolders![0].uri, "oil-dir") + ); + + const fileUri = vscode.Uri.joinPath( + vscode.workspace.workspaceFolders![0].uri, + "oil-dir", + "oil-file1.md" + ); + await vscode.workspace.fs.writeFile(fileUri, Buffer.from(testContent, "utf-8")); + await vscode.workspace.fs.writeFile( + vscode.Uri.joinPath( + vscode.workspace.workspaceFolders![0].uri, + "oil-dir", + "oil-file2.md" + ), + Buffer.from(testContent, "utf-8") + ); + + const fileDoc = await vscode.workspace.openTextDocument(fileUri); + await vscode.window.showTextDocument(fileDoc); + + await vscode.commands.executeCommand("oil-code.open"); + await waitForDocumentText([ + "/000 ../", + "/001 oil-file1.md", + "/002 oil-file2.md", + ]); + + await waitFor(() => { + const previewEditor = vscode.window.visibleTextEditors.find( + (editor) => + editor.document.uri.toString() === + "oil-preview://oil-preview/oil-file1.md" + ); + assert.ok(previewEditor, "No editor found for the preview tab"); + assert.strictEqual( + previewEditor.document.getText(), + testContent, + "Preview content does not match expected content" + ); + }); + + const editor = vscode.window.activeTextEditor; + assert.ok(editor, "No active editor"); + editor.selection = new vscode.Selection(0, 0, 0, 0); + + await vscode.commands.executeCommand("oil-code.select"); + + await waitForDocumentText(["/000 ../", "/003 oil-dir/"]); + + await waitFor(() => { + const previewTab = vscode.window.tabGroups.all.at(1)?.tabs.at(0); + assert.ok(previewTab, "Preview tab not found"); + assert.strictEqual( + (previewTab.input as vscode.TabInputText).uri.toString(), + "oil-preview://oil-preview/oil-dir" + ); + const previewEditor = vscode.window.visibleTextEditors.find( + (editor) => + editor.document.uri.toString() === "oil-preview://oil-preview/oil-dir" + ); + assert.ok(previewEditor, "No editor found for the preview tab"); + assert.strictEqual( + previewEditor.document.getText(), + ["/000 ../", "/001 oil-file1.md", "/002 oil-file2.md"].join(newline), + "Preview content does not match expected content" + ); + }); + }); + test("Preview directory and file", async () => { const testContent = `# Oil FileThis${newline}is a test file for Oil Code extension.`; await vscode.workspace.fs.createDirectory( diff --git a/src/utils/settings.ts b/src/utils/settings.ts index 17edb07..c915dae 100644 --- a/src/utils/settings.ts +++ b/src/utils/settings.ts @@ -25,6 +25,11 @@ export function getEnableAlternateConfirmationSetting(): boolean { return config.get("enableAlternateConfirmation") || false; } +export function getPreviewByDefaultSetting(): boolean { + const config = vscode.workspace.getConfiguration("oil-code"); + return config.get("previewByDefault") || false; +} + let restoreAutoSave = false; export async function checkAndDisableAutoSave() { From 5b4202b17b0833a66848b8833b9eb23497e17ef7 Mon Sep 17 00:00:00 2001 From: Corwin Marsh Date: Fri, 3 Apr 2026 12:44:44 -0700 Subject: [PATCH 2/2] chore: ignore .DS_Store --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 0b60dfa..cdba367 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,4 @@ dist node_modules .vscode-test/ *.vsix +.DS_Store \ No newline at end of file