Repository navigation
feat(reference): add edit, to replace, insert or delete a block - #70
Merged
Merged
Conversation
docs/editing-api.md sets out replace_block, insert_block and delete_block: a block named by its node path, where new and removed lines go, and the refusals, including a read-back of the result. tests/edit-cases/README.md gives the format of the cases that pin it, and both line-ending rules exempt that tree. Signed-off-by: Cameron Brooks <95648474+CameronBrooks11@users.noreply.github.com>
113 cases for replace, insert and delete and for every refusal, each refusal with an accepting control, written from docs/editing-api.md by an author who saw no implementation. The README logs what the author was given. Signed-off-by: Cameron Brooks <95648474+CameronBrooks11@users.noreply.github.com>
reference/blockspec/edit.py implements docs/editing-api.md and passes tests/edit-cases/ with no case changed. Each function reads its result back and refuses with a reason code when the new lines are not one block, another block reads differently, or a name would bind elsewhere. No function touches a <doc>.notes/ record. The README lists the reference's API. Signed-off-by: Cameron Brooks <95648474+CameronBrooks11@users.noreply.github.com>
Deleting a heading between a list and an indented fence keeps the block count a delete expects, while the list item takes in the fence line; only the per-block comparison refuses it. With that comparison disabled, this case is the one test that fails. Signed-off-by: Cameron Brooks <95648474+CameronBrooks11@users.noreply.github.com>
Deleting the last block can leave a line ending in a bare CR directly
above a kept blank line ending in LF. No bytes hold that pair as two
lines, so the blank line is lost; no block changes. The design now says
so, and a test pins delete_block("A.\r\rB.\n\n", [1]) == "A.\r\n".
Signed-off-by: Cameron Brooks <95648474+CameronBrooks11@users.noreply.github.com>
Signed-off-by: Cameron Brooks <95648474+CameronBrooks11@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This PR adds
blockspec.edit, so a program can change one block of a document without rewriting its lines itself (closes #69). The design is indocs/editing-api.md.replace_block(text, node, source, /),insert_block(text, source, /, *, before=None, after=None)anddelete_block(text, node, /). Each is a pure function from text to text. With neitherbefore=norafter=, an insert goes after the last block.[i], the pathparsereports. A caller holding a name resolves it withparse(text).resolve(name)["node"].nested-node. A whole list, quote or table can be replaced, inserted or deleted as one block, but no item or cell can. Writing inside a container means writing its prefixes, and §11.7's write-back shows how many of those lines draft 0 cannot write.bad-position,no-such-block,nested-node,not-one-block,changes-another-blockandrebinds-name, raised asEditRefused, aRefusal.<doc>.notes/records are never touched.Cases. The cases are in
tests/edit-cases/, notconformance/cases/, because §2 leaves editor behaviour unspecified. An author who worked from the design and SPEC alone, without the reference implementation, wrote 113 cases: 18 replace, 29 insert, 20 delete and 46 refusal, each refusal with a control. All passed on the first run with no case changed.docs/editing-api.mdwas clarified after the cases were written.tests/test_edit.pyadds 9 tests, including an insert into an empty file, which ends its line with LF.just checkexits 0, andjust testpasses 305.Two checks no case reaches. I mutated each refusal and checked that the file's hash differed every time:
Inserting inside a region. A block inserted between a region's markers joins that region, which is what the markers mean.
rebinds-namerefuses an edit that would make a name bind to something else. For example, inserting a block directly after a one-line marker would move the marker's name onto the new block.Signed-off-by: Cameron Brooks 95648474+CameronBrooks11@users.noreply.github.com