Skip to content

Commit 798245a

Browse files
committed
fixes #942
1 parent 09360a4 commit 798245a

3 files changed

Lines changed: 30 additions & 15 deletions

File tree

‎fastcore/editskill.py‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@
5050
5151
Prefer lnhash addresses when `exhash` is installed. The editor checks the hash against current content and rejects stale addresses. Plain line numbers are unverified and can shift after an edit. Re-view after each plain-line-number edit and apply multiple edits from bottom to top. Read `exhash.skill` for address formats and verified editing.
5252
53-
Section tokens identify sections in document outlines. In `1.6.|12|a3f2|,45|b1c3|`, `1.6.` is the section number. The rest is the lnhash range for its first and last lines. `d.at(token)` returns the section after checking its hash. `d.view(tok1, tok2)` prints the rendered text of both sections. Use the boundary range to edit the section: `file_exhash(path, ('12|a3f2|,45|b1c3|', 'c', new_text))`.
53+
Section tokens identify sections in document outlines. In `1.6.|12|Py|,45|HD|`, `1.6.` is the section number. The rest is the lnhash range for its first and last lines. `d.at(token)` returns the section after checking its hash. `d.view(tok1, tok2)` prints the rendered text of both sections. Use the boundary range to edit the section: `file_exhash(path, ('12|Py|,45|HD|', 'c', new_text))`.
5454
5555
Read `exhash.skill` before working through large Markdown, code, or notebook files, or documentation from a URL. It describes `open_doc` tree searches and link following, including the llms.txt workflow.
5656

‎fastcore/tools.py‎

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
55
Read `fastcore.editskill` for the editing toolkit's naming, parameter and workflow conventions. It exposes these tools alongside the notebook editors from `fastcore.nbio`.
66
7-
`line_hash`, `lnhash` and `lnhash_at` create [exhash](https://answerdotai.github.io/exhash) addresses without depending on the exhash package. Addresses use `lineno|hash|`. The hash is the low 16 bits of CRC32, formatted as four hexadecimal characters.
7+
`line_hash`, `lnhash` and `lnhash_at` create [exhash](https://answerdotai.github.io/exhash) addresses without depending on the exhash package. Addresses use `lineno|hash|`. The hash is the low 12 bits of CRC32, encoded as two Base64url characters (`A–Z`, `a–z`, `0–9`, `-`, `_`), high six bits first.
88
99
File editors take the path first and return a unified diff. An unchanged result returns `none: No changes.` Invalid edits return `error: ...`.
1010
@@ -152,8 +152,10 @@ def del_lines(
152152
def line_hash(
153153
line:str # Text to hash; when hashing a single line, omit its trailing newline
154154
)->str:
155-
"4-char hex hash of `line`"
156-
return f'{zlib.crc32(line.encode()) & 0xffff:04x}'
155+
"2-char Base64url hash of `line`"
156+
alphabet = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_'
157+
h = zlib.crc32(line.encode())
158+
return alphabet[(h>>6)&63] + alphabet[h&63]
157159

158160
def lnhash(
159161
lineno:int, # 1-based line number

‎nbs/12_tools.ipynb‎

Lines changed: 24 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -186,7 +186,18 @@
186186
"execution_count": null,
187187
"id": "8079ef9d",
188188
"metadata": {},
189-
"outputs": [],
189+
"outputs": [
190+
{
191+
"data": {
192+
"text/plain": [
193+
"'a-b\\nb a'"
194+
]
195+
},
196+
"execution_count": null,
197+
"metadata": {},
198+
"output_type": "execute_result"
199+
}
200+
],
190201
"source": [
191202
"res = str_replace('keep q\\nfix q\\nkeep q', 'q', 'y', re_filter='fix')\n",
192203
"test_eq(res, 'keep q\\nfix y\\nkeep q')\n",
@@ -371,7 +382,7 @@
371382
"metadata": {},
372383
"source": [
373384
"#| export\n",
374-
"`line_hash`, `lnhash` and `lnhash_at` create [exhash](https://answerdotai.github.io/exhash) addresses without depending on the exhash package. Addresses use `lineno|hash|`. The hash is the low 16 bits of CRC32, formatted as four hexadecimal characters."
385+
"`line_hash`, `lnhash` and `lnhash_at` create [exhash](https://answerdotai.github.io/exhash) addresses without depending on the exhash package. Addresses use `lineno|hash|`. The hash is the low 12 bits of CRC32, encoded as two Base64url characters (`A–Z`, `a–z`, `0–9`, `-`, `_`), high six bits first."
375386
]
376387
},
377388
{
@@ -385,8 +396,10 @@
385396
"def line_hash(\n",
386397
" line:str # Text to hash; when hashing a single line, omit its trailing newline\n",
387398
")->str:\n",
388-
" \"4-char hex hash of `line`\"\n",
389-
" return f'{zlib.crc32(line.encode()) & 0xffff:04x}'\n",
399+
" \"2-char Base64url hash of `line`\"\n",
400+
" alphabet = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_'\n",
401+
" h = zlib.crc32(line.encode())\n",
402+
" return alphabet[(h>>6)&63] + alphabet[h&63]\n",
390403
"\n",
391404
"def lnhash(\n",
392405
" lineno:int, # 1-based line number\n",
@@ -413,7 +426,7 @@
413426
{
414427
"data": {
415428
"text/plain": [
416-
"'2|54f0|'"
429+
"'2|Tw|'"
417430
]
418431
},
419432
"execution_count": null,
@@ -422,10 +435,10 @@
422435
}
423436
],
424437
"source": [
425-
"test_eq(line_hash('def foo(): pass'), '54f0') # same value the exhash Rust impl produces\n",
438+
"test_eq(line_hash('def foo(): pass'), 'Tw') # same value the exhash Rust impl produces\n",
426439
"s = 'a\\ndef foo(): pass\\nb'\n",
427-
"test_eq(lnhash_at(s, 2), '2|54f0|')\n",
428-
"test_eq(lnhash_at(s.splitlines(), 2), '2|54f0|')\n",
440+
"test_eq(lnhash_at(s, 2), '2|Tw|')\n",
441+
"test_eq(lnhash_at(s.splitlines(), 2), '2|Tw|')\n",
429442
"test_eq(lnhash_at(s, 2), lnhash(2, 'def foo(): pass'))\n",
430443
"lnhash_at(s, 2)"
431444
]
@@ -493,7 +506,7 @@
493506
{
494507
"data": {
495508
"text/plain": [
496-
"'/var/folders/51/b2_szf2945n072c0vj2cyty40000gn/T/tmpaax7zfjh/test.txt'"
509+
"'/var/folders/mv/nt5dfl8j0xbg7zkfw_sk_d8m0000gn/T/tmpxaep7ttt/test.txt'"
497510
]
498511
},
499512
"execution_count": null,
@@ -542,8 +555,8 @@
542555
{
543556
"data": {
544557
"text/plain": [
545-
"2|0463|beta\n",
546-
"3|d071|gamma"
558+
"2|Rj|beta\n",
559+
"3|Bx|gamma"
547560
]
548561
},
549562
"execution_count": null,

0 commit comments

Comments
 (0)