refactor(edit): removed unsupported ignore-case and multiline sed flags

- Removed `i` and `m` from the Atom sed schema and docs, so sed now accepts only `pat`, `rep`, `g`, and `F` options.
- Updated `SedSpec` parsing and serialization to drop ignore-case and multiline handling.
- Adjusted regex construction to apply sed replacements using only global and literal flags.
This commit is contained in:
can1357
2026-04-26 14:56:16 +02:00
parent 37a8203f94
commit 93ea938375
2 changed files with 6 additions and 18 deletions
+5 -15
View File
@@ -12,7 +12,7 @@
* { path, loc: "5th", pre: [...], splice: [...], post: [...] }
* { path, loc: "$", pre: [...] } // prepend to file
* { path, loc: "$", post: [...] } // append to file
* { path, loc: "$", sed: { pat, rep, g?, F?, i?, m? } } // sed on every line
* { path, loc: "$", sed: { pat, rep, g?, F? } } // sed on every line
*
* `splice: []` on a single-anchor locator deletes that line. `splice:[""]` preserves
* a blank line. Line ranges are not supported.
@@ -72,8 +72,6 @@ export const atomEditSchema = Type.Object(
rep: Type.String({ description: "replacement text" }),
g: Type.Optional(Type.Boolean({ description: "global replace", default: false })),
F: Type.Optional(Type.Boolean({ description: "literal replace", default: false })),
i: Type.Optional(Type.Boolean({ description: "ignore case", default: false })),
m: Type.Optional(Type.Boolean({ description: "multiline mode (^ and $ match line boundaries)", default: false })),
},
{
additionalProperties: false,
@@ -110,11 +108,9 @@ export type AtomEdit =
| { op: "sed_file"; spec: SedSpec; expression: string };
export interface SedSpec {
multiline: boolean;
pattern: string;
replacement: string;
global: boolean;
ignoreCase: boolean;
literal: boolean;
}
@@ -270,7 +266,7 @@ function extractAnchorContentHint(raw: string): string | undefined {
function parseSedSpec(input: unknown, editIndex: number): SedSpec {
if (input === null || typeof input !== "object" || Array.isArray(input)) {
throw new Error(`Edit ${editIndex}: sed must be an object with shape {pat, rep, g?, F?, i?, m?}.`);
throw new Error(`Edit ${editIndex}: sed must be an object with shape {pat, rep, g?, F?}.`);
}
const obj = input as Record<string, unknown>;
const pat = obj.pat;
@@ -286,7 +282,7 @@ function parseSedSpec(input: unknown, editIndex: number): SedSpec {
if (typeof rep !== "string") {
throw new Error(`Edit ${editIndex}: sed.rep must be a string.`);
}
const readBool = (key: "g" | "F" | "i" | "m", defaultValue: boolean): boolean => {
const readBool = (key: "g" | "F", defaultValue: boolean): boolean => {
const v = obj[key];
if (v === undefined) return defaultValue;
if (typeof v !== "boolean") {
@@ -296,21 +292,17 @@ function parseSedSpec(input: unknown, editIndex: number): SedSpec {
};
const global = readBool("g", false);
const literal = readBool("F", false);
const ignoreCase = readBool("i", false);
const multiline = readBool("m", false);
return { pattern: pat, replacement: rep, global, literal, ignoreCase, multiline };
return { pattern: pat, replacement: rep, global, literal };
}
function formatSedExpression(spec: SedSpec): string {
const obj: { pat: string; rep: string; g?: boolean; F?: boolean; i?: boolean; m?: boolean } = {
const obj: { pat: string; rep: string; g?: boolean; F?: boolean } = {
pat: spec.pattern,
rep: spec.replacement,
};
// Only emit non-default flags so error messages stay compact (g defaults false).
if (spec.global) obj.g = true;
if (spec.literal) obj.F = true;
if (spec.ignoreCase) obj.i = true;
if (spec.multiline) obj.m = true;
return JSON.stringify(obj);
}
@@ -335,8 +327,6 @@ function applySedToLine(
}
let flags = "";
if (spec.global) flags += "g";
if (spec.ignoreCase) flags += "i";
if (spec.multiline) flags += "m";
let re: RegExp | undefined;
let compileError: string | undefined;
try {
@@ -14,13 +14,11 @@ Verbs:
- `splice: […]`: lines are spliced in at the anchor.
- `pre: […]`: prepend before the anchor (or at BOF if `loc=$`)
- `post: […]`: append after the anchor (or at EOF if `loc=$`)
- `sed: { pat, rep, g?, F?, i?, m? }` — structured find/replace on the anchor line. **Prefer this over `splice` for token-level changes**
- `sed: { pat, rep, g?, F? }` — structured find/replace on the anchor line. **Prefer this over `splice` for token-level changes**
- `pat`: pattern to find (regex by default)
- `rep`: replacement (regex back-refs like `$1`, `$&` available)
- `g`: global — replace every occurrence (default `false`; pass `true` to replace all)
- `F`: literal — treat `pat` as a literal substring (no regex). Use this whenever `pat` contains `||`, `.`, `(`, `?`, `\`, etc. you mean literally.
- `i`: ignore case
- `m`: multiline — `^` and `$` match line boundaries
You **MUST** keep `pat` as short as possible.
Combination rules: