@oh-my-pi/hashline 17.3.2 → 17.3.4
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 +6 -0
- package/package.json +3 -3
- package/src/tokenizer.ts +39 -0
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,12 @@
|
|
|
2
2
|
|
|
3
3
|
## [Unreleased]
|
|
4
4
|
|
|
5
|
+
## [17.3.3] - 2026-08-14
|
|
6
|
+
|
|
7
|
+
### Fixed
|
|
8
|
+
|
|
9
|
+
- Recovered dangling range separators in hunk headers (`PUT 244.=:`, `CUT 5.=`) as single-line ranges (`N.=N`) instead of rejecting the header as an orphan payload line.
|
|
10
|
+
|
|
5
11
|
## [17.3.0] - 2026-08-13
|
|
6
12
|
|
|
7
13
|
### Fixed
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"type": "module",
|
|
3
3
|
"name": "@oh-my-pi/hashline",
|
|
4
|
-
"version": "17.3.
|
|
4
|
+
"version": "17.3.4",
|
|
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",
|
|
@@ -33,8 +33,8 @@
|
|
|
33
33
|
"fmt": "biome format --write ."
|
|
34
34
|
},
|
|
35
35
|
"dependencies": {
|
|
36
|
-
"@oh-my-pi/pi-natives": "17.3.
|
|
37
|
-
"@oh-my-pi/pi-utils": "17.3.
|
|
36
|
+
"@oh-my-pi/pi-natives": "17.3.4",
|
|
37
|
+
"@oh-my-pi/pi-utils": "17.3.4"
|
|
38
38
|
},
|
|
39
39
|
"devDependencies": {
|
|
40
40
|
"@types/bun": "^1.3.14"
|
package/src/tokenizer.ts
CHANGED
|
@@ -182,6 +182,37 @@ function scanRangeSeparator(line: string, index: number, end: number): number |
|
|
|
182
182
|
return cursor;
|
|
183
183
|
}
|
|
184
184
|
|
|
185
|
+
/**
|
|
186
|
+
* Recover a dangling range separator: the run after `N` contains at least one
|
|
187
|
+
* non-whitespace separator char but no end number (`244.=:`, `5-`, `12.. @reg`).
|
|
188
|
+
* Models write this intending an open range; it collapses to `N.=N`. Returns
|
|
189
|
+
* the index past the run only when what follows is `:`, `@`, or end-of-header —
|
|
190
|
+
* anything else keeps the header on the strict rejection path.
|
|
191
|
+
*/
|
|
192
|
+
function scanDanglingSeparator(line: string, index: number, end: number): number | null {
|
|
193
|
+
let cursor = index;
|
|
194
|
+
let sawSeparatorChar = false;
|
|
195
|
+
while (cursor < end) {
|
|
196
|
+
const code = line.charCodeAt(cursor);
|
|
197
|
+
if (code === CHAR_HYPHEN || code === CHAR_DOT || code === CHAR_EQUALS || code === CHAR_ELLIPSIS) {
|
|
198
|
+
sawSeparatorChar = true;
|
|
199
|
+
cursor++;
|
|
200
|
+
continue;
|
|
201
|
+
}
|
|
202
|
+
if (isWhitespaceCode(code)) {
|
|
203
|
+
cursor++;
|
|
204
|
+
continue;
|
|
205
|
+
}
|
|
206
|
+
break;
|
|
207
|
+
}
|
|
208
|
+
if (!sawSeparatorChar) return null;
|
|
209
|
+
if (cursor < end) {
|
|
210
|
+
const code = line.charCodeAt(cursor);
|
|
211
|
+
if (code !== CHAR_COLON && code !== CHAR_AT) return null;
|
|
212
|
+
}
|
|
213
|
+
return cursor;
|
|
214
|
+
}
|
|
215
|
+
|
|
185
216
|
function scanHeaderRange(line: string, index = 0, end = trimEndIndex(line), allowSingle = false): RangeScan | null {
|
|
186
217
|
const numberStart = skipWhitespace(line, index, end);
|
|
187
218
|
const start = scanLineNumber(line, numberStart, end);
|
|
@@ -189,6 +220,14 @@ function scanHeaderRange(line: string, index = 0, end = trimEndIndex(line), allo
|
|
|
189
220
|
const afterFirst = scanRangeSeparator(line, start.nextIndex, end);
|
|
190
221
|
if (afterFirst === null) {
|
|
191
222
|
if (!allowSingle) return null;
|
|
223
|
+
const dangling = scanDanglingSeparator(line, start.nextIndex, end);
|
|
224
|
+
if (dangling !== null) {
|
|
225
|
+
return {
|
|
226
|
+
range: { start: { line: start.line }, end: { line: start.line } },
|
|
227
|
+
nextIndex: dangling,
|
|
228
|
+
hadSeparator: true,
|
|
229
|
+
};
|
|
230
|
+
}
|
|
192
231
|
return {
|
|
193
232
|
range: { start: { line: start.line }, end: { line: start.line } },
|
|
194
233
|
nextIndex: skipWhitespace(line, start.nextIndex, end),
|