diff --git a/src/background/config_rc.ts b/src/background/config_rc.ts index 13d92f38..6b0b6b64 100644 --- a/src/background/config_rc.ts +++ b/src/background/config_rc.ts @@ -49,7 +49,8 @@ export async function writeRc(conf: string, force = false, filename = "auto") { } else { path = filename } - return await Native.writerc(path, force, conf) + await Native.writerc(path, force, conf) + return path } export async function runRc(rc: string) { diff --git a/src/excmds.test.ts b/src/excmds.test.ts index b0bc5926..26f7d9ac 100644 --- a/src/excmds.test.ts +++ b/src/excmds.test.ts @@ -5,6 +5,7 @@ import * as Native from "@src/lib/native" import * as Messaging from "@src/lib/messaging" import * as DOM from "@src/lib/dom" import state from "@src/state" +import * as rc from "@src/background/config_rc" jest.mock("@src/lib/webext", () => ({ ...jest.requireActual("@src/lib/webext"), @@ -288,6 +289,32 @@ test.each(["mktridactylrc", "source"])( }, ) +test("`mktridactylrc` reports the written path", async () => { + jest.mocked(Native.nativegate).mockResolvedValue(true) + jest.mocked(rc.writeRc).mockResolvedValue("/tmp/tridactylrc") + + await backgroundExcmds.mktridactylrc() + + expect(Messaging.messageActiveTab).toHaveBeenCalledWith( + "excmd_content", + "fillcmdline_tmp", + [3000, "# RC written to /tmp/tridactylrc"], + ) +}) + +test.each([ + [1, /already exists.*-f/], + [2, /parent directory.*writable/], +])("`writerc` reports native error %i", async (code, error) => { + jest.mocked(browser.runtime.sendNativeMessage).mockResolvedValueOnce({ + code, + }) + + await expect( + Native.writerc("/tmp/tridactylrc", false, "secret config"), + ).rejects.toThrow(error) +}) + test.each([ ["guiset_quiet", ["gui", "none"], "0.1.1"], ["exclaim_quiet", [], "0"], diff --git a/src/excmds.ts b/src/excmds.ts index b0cb8933..70a1f72e 100644 --- a/src/excmds.ts +++ b/src/excmds.ts @@ -827,7 +827,7 @@ export async function nativeinstall() { With no arguments supplied the excmd will try to find an appropriate config path and write the rc file to there. Any argument given to the excmd excluding the `-f` flag will be treated as a path to write the rc - file to relative to the native messenger's location (`~/.local/share/tridactyl/`). By default, it silently refuses to overwrite existing files. + file to relative to the native messenger's location (`~/.local/share/tridactyl/`). By default, it refuses to overwrite existing files. The RC file will be split into sections that will be created if a config property is discovered within one of them: @@ -872,7 +872,8 @@ export async function mktridactylrc(...args: string[]) { return fillcmdline_tmp(3000, "# RC copied to clipboard") } if (!(await Native.nativegate("0.1.11", false))) throw new Error("`:mktridactylrc` requires the native messenger. Run `:nativeinstall` or use `:mktridactylrc --clipboard`.") - if (!(await rc.writeRc(conf, overwrite, file))) logger.error("Could not write RC file") + const path = await rc.writeRc(conf, overwrite, file) + await fillcmdline_tmp(3000, `# RC written to ${path}`) return conf } diff --git a/src/lib/native.ts b/src/lib/native.ts index 32cd239b..11573082 100644 --- a/src/lib/native.ts +++ b/src/lib/native.ts @@ -347,9 +347,20 @@ export async function write(file: string, content: string) { } export async function writerc(file: string, force: boolean, content: string) { - return sendNativeMsg("writerc", { file, force, content }).catch(e => { - throw new Error(`Failed to write '${content}' to '${file}'. ${e}`) - }) + const response = await sendNativeMsg("writerc", { file, force, content }) + if (response.code === 1) + throw new Error( + `RC file '${file}' already exists. Use :mktridactylrc -f to overwrite it.`, + ) + if (response.error || (response.code != null && response.code !== 0)) { + const error = + response.error || + (response.code === 2 + ? "check that its parent directory exists and is writable" + : `native messenger returned code ${response.code}`) + throw new Error(`Failed to write RC file '${file}': ${error}.`) + } + return response } export async function mkdir(dir: string, exist_ok: boolean) {