Add -e/--edit flag: open config file in $EDITOR

New module src/editor.ts handles the flag end-to-end:

  - editorCommand(editor, path) returns the sh -c argv that lets the
    shell tokenize multi-word $EDITOR values like 'code --wait'.
    Extracted so editor.test.ts can verify construction without
    actually launching an editor.
  - editConfig(path) checks $EDITOR is set, checks the target file
    exists, spawns 'sh -c <editor> "$@" -- <path>' with stdio
    inherited, and exits with the editor's status code.

Refuses (CliError -> exit 2) when:
  - $EDITOR is unset or empty.
  - The target config file doesn't exist. (Same recovery hint as
    elsewhere: 'run move once or reinstall'.)

src/cli.ts adds the flag to the parser and printHelp(). src/move.ts
dispatches it after --version and before config-load. Resolution
mirrors the loader: --config <path> wins, else defaultConfigPath().

8 new tests in src/editor.test.ts cover the pure helper and both
refusal paths; the spawn success path is verified via manual
'EDITOR=true move -e' (would otherwise kill the test process).

README Usage block, Configuration section (new Editing subsection),
and Files table all updated to match.
This commit is contained in:
2026-06-17 22:20:27 -05:00
parent cc7a487aca
commit 10dcc1791a
5 changed files with 229 additions and 1 deletions
+7
View File
@@ -9,6 +9,9 @@
*
* -h, --help Prints `printHelp()` to stdout; entry exits 0.
* -v, --version Prints `move <VERSION>` to stdout; entry exits 0.
* -e, --edit Open the active config file in `$EDITOR`.
* Refuses if the file doesn't exist; refuses if
* `$EDITOR` is unset.
* -C, --config <path> Override the default config-file path.
* -m, --move-interval Idle time (seconds) before a sweep fires.
* -c, --check-interval Cursor poll cadence (seconds).
@@ -37,6 +40,7 @@ import { CliError } from "./errors.ts";
export interface ParsedCliArgs {
help: boolean;
version: boolean;
edit: boolean;
config: string | undefined;
moveInterval: number | undefined; // seconds
checkInterval: number | undefined; // seconds
@@ -78,6 +82,7 @@ export function parseCliArgs(): ParsedCliArgs {
options: {
help: { type: "boolean", short: "h" },
version: { type: "boolean", short: "v" },
edit: { type: "boolean", short: "e" },
config: { type: "string", short: "C" },
"move-interval": { type: "string", short: "m" },
"check-interval": { type: "string", short: "c" },
@@ -99,6 +104,7 @@ export function parseCliArgs(): ParsedCliArgs {
return {
help: Boolean(values.help),
version: Boolean(values.version),
edit: Boolean(values.edit),
config: values.config as string | undefined,
moveInterval: parsePositiveNumber("move-interval", values["move-interval"] as string | undefined),
checkInterval: parsePositiveNumber("check-interval", values["check-interval"] as string | undefined),
@@ -140,6 +146,7 @@ nudging the mouse cursor after a configurable idle period.
Options:
-h, --help Show this help and exit.
-v, --version Print version and exit.
-e, --edit Open the config file in $EDITOR and exit.
-C, --config <path> Load defaults from a JSON config file.
Default path: ${cfgPath}
-m, --move-interval <seconds> Idle time before a sweep fires. Default: ${moveDefaultSec}.