# Is there something like a "draft context" but for buffer content?

**URL:** <https://discuss.kakoune.com/t/is-there-something-like-a-draft-context-but-for-buffer-content/871>\
**Category:** Help\
**Tags:** buffer\
**Created:** [February 1, 2020, 1:04pm UTC](https://discuss.kakoune.com/t/is-there-something-like-a-draft-context-but-for-buffer-content/871 "2020-02-01T13:04:07Z")\
**Posts on this page:** 2\
**Page:** 1

<div class="post-metadata">

**Author:** ![Screwtapello](https://discuss.kakoune.com/user_avatar/discuss.kakoune.com/screwtapello/32/12_2.png) [@Screwtapello](https://discuss.kakoune.com/u/Screwtapello)\
**Post date:** [February 1, 2020, 1:04pm UTC](https://discuss.kakoune.com/t/is-there-something-like-a-draft-context-but-for-buffer-content/871/1 "2020-02-01T13:04:07Z")

</div>

# The problem

I’ve been experimenting with a plugin to assist with local editing of GitHub wikis. The special rules for GitHub wikis are:

- nearly every supported markup syntax adds support for MediaWiki-style links, so you can link to a paged named “Foo” with `[[Foo]]`
- When you create a page named “Eval / Exec”, the page content is stored in a file named `Eval---Exec.md`
  - that is, spaces and slashes are replaced with hyphens
  - there may be other replaced characters too

- `[[Eval / Exec]]` and `[[Eval/ /Exec]]` and `[[Eval---Exec]]` all link to the same page

So when the user tries to follow a `[[Some Page]]` link, I have to map that into `Some-Page.md`, then tell Kakoune to edit the resulting file. Simple!

However, it gets more complicated. For example, while GitHub squashes unsafe characters to hyphens, the Python-Markdown wiki link extension [squashes (only) spaces to underscores](https://github.com/Python-Markdown/markdown/blob/master/markdown/extensions/wikilinks.py#L26), and other wiki systems probably use other schemes, so I’d like to make the pattern and the replacement configurable.

# Attempt 1

My first idea was to make a regex option for “unsafe character pattern”, and a string option for “unsafe character replacement”, and then my code would use `sed` to process the page name and produce a filename for Kakoune to edit. However, a Kakoune regex option validates against _Kakoune’s_ regex syntax, not sed’s, and it felt silly to have Kakoune (a mighty text-processing tool) shell out to a simple text-processing tool just to do a search-and-replace.

# Attempt 2

My second idea was to have the “squash unsafe characters” option be a _command_ rather than a pattern and a replacement, and I’d use it something like this:

```
# kakrc
set global wiki_squash_unsafe_characters "exec s[<space>/]<ret>c-<ret>"

# in my plugin
eval -draft %opt{wiki_squash_unsafe_characters}
wiki-edit-page-named %val{selection}

```

…except that the `wiki_squash_unsafe_characters` command modifies the buffer! So let’s put an undo after it:

```
eval -draft %opt{wiki_squash_unsafe_characters}
wiki-edit-page-named %val{selection}
exec u

```

…except that `wiki-edit-page-named` is going to _change_ which buffer is active, and the undo is going to go to the wrong buffer! That’s OK, we can work with that:

```
eval -save-regs b %{
    reg b %val{buffile}
    eval -draft %opt{wiki_squash_unsafe_characters}
    wiki-edit-page-named %val{selection}
    exec -buffer %reg{b} u
}

```

…except that it’s possible to have a page name _without_ any unsafe characters, like `[[Home]]`, in which case `wiki_squash_unsafe_characters` is going to throw an error. Well, we can fix that with a `try` command:

```
eval -save-regs b %{
    reg b %val{buffile}

    try %{
        eval -draft %opt{wiki_squash_unsafe_characters}
        wiki-edit-page-named %val{selection}
        exec -buffer %reg{b} u
    } catch %{
        wiki-edit-page-named %val{selection}
    }
}

```

…and that works. Unfortunately, it means that `wiki_squash_unsafe_characters` must do exactly one undoable operation, no more or less, and it means that any legitimate errors in `wiki-edit-page-named` will become very difficult to debug, and leave the buffer in an inconsistent state (with the squash action not undone).

# What (I think) I want, option 1

There should be something that’s like `eval -draft`, but it restores buffer content afterward, or copies the buffer into a temporary scratch buffer or something. If such an option existed — let’s call it `-scratch` — my code could look like this:

```
evaluate-commands -scratch %{
    try %{ eval -draft %opt{wiki_squash_unsafe_characters} }
    wiki-edit-page-named %val{selection}
}

```

Much simpler, and more reliable!

# What (I think) I want, option 2

Alternatively, and perhaps simpler to implement, would be a way to navigate through the history tree to a specific point. `<u>` and `<U>` step along one branch of the undo tree, while `<a-u>` and `<a-U>` step between branches, but imagine there was some other binding like `<c-a-u>` that took you straight to the history node whose number was given by the count. Then my code could look like this:

```
eval -save-regs bh %{
    reg b %val{buffile}
    reg h %val{history_id}

    try %{ eval -draft %opt{wiki_squash_unsafe_characters} }
    wiki-edit-page-named %val{selection}
    exec -buffer %reg{b} %reg{h} <c-a-u>
}

```

Not quite as clean as the previous idea, but still nicer than what I’m using currently.

# Conclusion

Are there any Kakoune features I’ve missed that would help me out with this? Is there a better approach I could be taking?

---

<div class="post-metadata">

**Author:** ![prion](https://discuss.kakoune.com/user_avatar/discuss.kakoune.com/prion/32/404_2.png) [@prion](https://discuss.kakoune.com/u/prion)\
**Post date:** [February 2, 2020, 10:44pm UTC](https://discuss.kakoune.com/t/is-there-something-like-a-draft-context-but-for-buffer-content/871/2 "2020-02-02T22:44:23Z")

</div>

I also think Kakoune would benefit from having better ways to view the history tree, which would also require new commands to navigate it.

But WRT to option one I can’t think of any reason you can’t do this with existing commands, even though a built in short cut might be nice. Just open a scratch buffer with `:edit -scratch` and copy the pre-edit line to it.

But an easier solution is just to copy the edit to a register and evaluate it’s contents after the undo.

```auto
eval -draft %opt{wiki_squash_unsafe_characters}
# this can all be done in eval -draft command but wrote it out explicitly here to demonstrate
reg m %val{selection}
exec u
# navigate to the edited line that was saved to a register.
exec ': wiki-edit-page-named %reg{m}

```
