@oh-my-pi/hashline 17.0.2 → 17.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +4 -0
- package/package.json +1 -1
- package/src/tokenizer.ts +17 -4
package/CHANGELOG.md
CHANGED
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"type": "module",
|
|
3
3
|
"name": "@oh-my-pi/hashline",
|
|
4
|
-
"version": "17.0.
|
|
4
|
+
"version": "17.0.3",
|
|
5
5
|
"description": "Hashline: a compact, line-anchored patch language and applier. Pluggable FS/IO so it works over disk, in-memory, or any custom backend.",
|
|
6
6
|
"homepage": "https://omp.sh",
|
|
7
7
|
"author": "Can Boluk",
|
package/src/tokenizer.ts
CHANGED
|
@@ -40,6 +40,7 @@ const CHAR_HASH = 35;
|
|
|
40
40
|
const CHAR_TAB = 9;
|
|
41
41
|
const CHAR_SPACE = 32;
|
|
42
42
|
const CHAR_DOT = 46;
|
|
43
|
+
const CHAR_COMMA = 44;
|
|
43
44
|
const CHAR_HYPHEN = 45;
|
|
44
45
|
const CHAR_ELLIPSIS = 0x2026;
|
|
45
46
|
const CHAR_EQUALS = 61;
|
|
@@ -165,7 +166,7 @@ function scanRangeSeparator(line: string, index: number, end: number): number |
|
|
|
165
166
|
consumedSeparator = true;
|
|
166
167
|
continue;
|
|
167
168
|
}
|
|
168
|
-
if (code === CHAR_HYPHEN || code === CHAR_ELLIPSIS) {
|
|
169
|
+
if (code === CHAR_COMMA || code === CHAR_HYPHEN || code === CHAR_ELLIPSIS) {
|
|
169
170
|
cursor++;
|
|
170
171
|
consumedSeparator = true;
|
|
171
172
|
continue;
|
|
@@ -252,6 +253,17 @@ function consumeOptionalColon(line: string, index: number, end: number): number
|
|
|
252
253
|
cursor = skipStrayDot(line, cursor, end);
|
|
253
254
|
return cursor < end && line.charCodeAt(cursor) === CHAR_COLON ? skipWhitespace(line, cursor + 1, end) : cursor;
|
|
254
255
|
}
|
|
256
|
+
/**
|
|
257
|
+
* Recover local-model replace trailers that permute `:` and `=` as `:=:` or
|
|
258
|
+
* `=:`. The range has already been parsed, so these suffixes are unambiguous.
|
|
259
|
+
*/
|
|
260
|
+
function consumeReplaceColon(line: string, index: number, end: number): number {
|
|
261
|
+
const canonical = consumeOptionalColon(line, index, end);
|
|
262
|
+
if (canonical >= end || line.charCodeAt(canonical) !== CHAR_EQUALS) return canonical;
|
|
263
|
+
const afterEquals = skipWhitespace(line, canonical + 1, end);
|
|
264
|
+
if (afterEquals >= end || line.charCodeAt(afterEquals) !== CHAR_COLON) return canonical;
|
|
265
|
+
return skipWhitespace(line, afterEquals + 1, end);
|
|
266
|
+
}
|
|
255
267
|
|
|
256
268
|
function scanInsertTarget(line: string, index: number, end: number): TargetScan | null {
|
|
257
269
|
if (index >= end || line.charCodeAt(index) !== CHAR_DOT) return null;
|
|
@@ -341,7 +353,7 @@ function scanHunkAnchor(line: string, start: number, end: number): TargetScan |
|
|
|
341
353
|
if (range === null) return null;
|
|
342
354
|
return {
|
|
343
355
|
target: { kind: "replace", range: range.range },
|
|
344
|
-
nextIndex:
|
|
356
|
+
nextIndex: consumeReplaceColon(line, range.nextIndex, end),
|
|
345
357
|
};
|
|
346
358
|
}
|
|
347
359
|
// `delete_block N` — resolve N to a tree-sitter block range at apply time
|
|
@@ -356,12 +368,13 @@ function scanHunkAnchor(line: string, start: number, end: number): TargetScan |
|
|
|
356
368
|
if (next < end && line.charCodeAt(next) === CHAR_COLON) return null;
|
|
357
369
|
return { target: { kind: "delete_block", anchor: { line: anchor.line } }, nextIndex: next };
|
|
358
370
|
}
|
|
371
|
+
// `delete N.=M` — like `delete_block N`, takes no body and no trailing
|
|
372
|
+
// colon; a colon here falls through to contamination detection.
|
|
359
373
|
const deleteEnd = scanKeyword(line, cursor, end, HL_DELETE_KEYWORD);
|
|
360
374
|
if (deleteEnd !== null) {
|
|
361
375
|
const range = scanHeaderRange(line, deleteEnd, end, true);
|
|
362
376
|
if (range === null) return null;
|
|
363
|
-
|
|
364
|
-
next = skipStrayDot(line, next, end);
|
|
377
|
+
const next = skipStrayDot(line, range.nextIndex, end);
|
|
365
378
|
if (next < end && line.charCodeAt(next) === CHAR_COLON) return null;
|
|
366
379
|
return { target: { kind: "delete", range: range.range }, nextIndex: next };
|
|
367
380
|
}
|