mirror of
https://github.com/l0ng-ai/openidea.git
synced 2026-11-14 16:07:52 +00:00
Double-clicking a file no editor understands (`.xlsx`, `.pdf`, ...) opened the read-only hex view, because the hex provider claims every binary file. Settings > Editor > File Types gains "Files opened in associated applications" (Office documents and PDFs by default); matching files open with their system application through a new `fs_open_with_system` command, which requires a trusted local project window and a file inside the project or one of its content roots. Remote windows and failed launches fall back to the existing viewers. External open handlers are a new workbench extension point asked before the file editor providers. Co-authored-by: panda-student <71381346+panda-student@users.noreply.github.com>
67 lines
2.0 KiB
TypeScript
67 lines
2.0 KiB
TypeScript
import { afterEach, describe, expect, it, vi } from "vitest";
|
|
import { openFileExternally, registerExternalFileOpenHandler, type ExternalFileOpenHandler } from "./contributions";
|
|
|
|
const disposers: Array<() => void> = [];
|
|
|
|
function register(handler: ExternalFileOpenHandler) {
|
|
const dispose = registerExternalFileOpenHandler(handler);
|
|
disposers.push(dispose);
|
|
return dispose;
|
|
}
|
|
|
|
afterEach(() => {
|
|
disposers.splice(0).forEach((dispose) => dispose());
|
|
vi.restoreAllMocks();
|
|
});
|
|
|
|
describe("external file openers", () => {
|
|
it("asks handlers in order and stops at the first that takes the file", async () => {
|
|
const calls: string[] = [];
|
|
register({
|
|
id: "second",
|
|
order: 20,
|
|
open: (p) => {
|
|
calls.push(`second:${p}`);
|
|
return false;
|
|
},
|
|
});
|
|
register({
|
|
id: "first",
|
|
order: 10,
|
|
open: (p) => {
|
|
calls.push(`first:${p}`);
|
|
return true;
|
|
},
|
|
});
|
|
register({
|
|
id: "never",
|
|
order: 30,
|
|
open: (p) => {
|
|
calls.push(`never:${p}`);
|
|
return true;
|
|
},
|
|
});
|
|
expect(await openFileExternally("/p/a.xlsx")).toBe(true);
|
|
expect(calls).toEqual(["first:/p/a.xlsx"]);
|
|
});
|
|
|
|
it("falls through when a handler declines or fails", async () => {
|
|
vi.spyOn(console, "warn").mockImplementation(() => {});
|
|
register({ id: "declines", order: 10, open: () => false });
|
|
register({ id: "fails", order: 20, open: () => Promise.reject(new Error("no association")) });
|
|
register({ id: "takes", order: 30, open: () => true });
|
|
expect(await openFileExternally("/p/a.xlsx")).toBe(true);
|
|
});
|
|
|
|
it("leaves the file to the editors without a handler", async () => {
|
|
expect(await openFileExternally("/p/a.ts")).toBe(false);
|
|
});
|
|
|
|
it("disposal removes a handler", async () => {
|
|
const dispose = register({ id: "only", open: () => true });
|
|
expect(await openFileExternally("/p/a.xlsx")).toBe(true);
|
|
dispose();
|
|
expect(await openFileExternally("/p/a.xlsx")).toBe(false);
|
|
});
|
|
});
|