Has anyone made a wiki in Kakoune?

Kakoune itself already has a wiki on GitHub, I’m talking about a wiki actually inside Kakoune itself. I imagine the features would be something like:

  • In normal mode, hitting Enter when the primary cursor is on text inside double-square-brackets would open the corresponding file - so if the cursor was on [[New York]] and I hit Enter, Kakoune would open/switch to New York.md in the same directory.
  • Autocompleting based on filenames, so if New York.md exists and I type [[N in insert mode, [[New York]] is a completion.
  • A “what links here” feature, which would basically be :grep "\[\[%var{bufname}\]\]" except also trimming the file extension.
  • A “broken links” feature that finds all the links that don’t have a corresponding file.
  • A “orphan pages” feature that finds all the pages that nobody links to.
  • For bonus points, support page templates, so if I follow a link [[City:New York]] and City:New York.md doesn’t exist, the new page will start as a copy of City:template.md rather than as a blank document.
    • Template pages don’t count as orphan pages.

I’m cool with other wiki-link syntaxes, it’s just that the double-square-brackets thing happens to be supported by Python Markdown so I’m used to it.

I would like this, also.

As a suggestion, if anybody is interested in implementing such a thing: AsciiDoc for my blog and writing (well, except I keep not writing), and since AsciiDoc allows definition of new macros, it should be easy to make wiki:SomePage[].

When I was a Vim user I did not use wiki plugins. Instead I’ve used gf feature, that selected path under cursor and jumed to the file, as well as tag files for jumping to sections. Kakoune has builtin tag support, and has gf which can be made a bit smarter and recursive like this.

This allows having files in a tree (or not) structure, with headings accessed via tags (maybe one could define a grep function that will act like gf but for headers) and we basically can use any markup language for making our own wikis.

That’s what I did in Vim. But I’ve decided to go org mode for this task in the end.

Kinda, it’s pretty basic tho

1 Like

I looked at Teddys’ wiki plugin, and while it’s cool, it seems to require configuring A Specific Wiki Path. I’d like to have any directory be a potential wiki, so I’ve started my own thing.

I would like it to be adaptable to different markup formats and link syntaxes (like AsciiDoc, ReST, etc.) and different ways of mapping page names to file paths (which characters are disallowed, whether they’re escaped or just flattened) but Kakoune is really not built for… plugability, so at least for starters I’ve decided to restrict myself to just GitHub-style wikis, and just MediaWiki-style links as described in the first post.

Currently, if you follow the example config in the README, if you edit a Markdown file and a Home.md file exists in the same directory, it maps <ret> to : wiki-follow-link, so you can hit Enter on a link to open the file it links to (again, as described in the first post).

Next, I wanted to tackle completion.

Attempt 1: static_words

I tried generating a list of page names, and inserting them into the static_words option. I immediately hit a problem: it’s easy to add items with set -add, but you can’t easily remove or update items.

Attempt 2: links in a completions option

Kakoune’s built for this kind of custom completion stuff, so we should have all the parts we need:

# Declare a completions option, and always use it
declare-option completions wiki_completions
set-option -add global completers option=wiki_completions

# while the user is typing in insert mode...
hook global InsertIdle .* %{
    eval -draft %{
        try %{
            # Move the cursor to the beginning of the previous [[, if any.
            exec <space><a-t>[hH<a-k>\[\[<ret>

            # Set up completions that include the [[
            set window wiki_completions \
                "%val{cursor_line}.%val{cursor_column}@%val{timestamp}" \
                "[[New York]]||[[New York]]" "[[London]]||[[London]]"
        } catch %{
            # No [[ before the cursor, clear out stale completions
            set window wiki_completions
        }
    }
}

If I stick that in a file and start Kakoune, it mostly works. If I just start typing, I get no completions, and the moment I type [[ I get the two completions and I can cycle through them. If I type L (the first letter of “London”) then “New York” gets removed from the completion list as I would expect.

However, if I type l, I would expect the same effect. Instead, the completion list now contains “file” and “automatically”, the two words in the default scratch buffer message containing “l”. If I then type “o” (or “d” or “n”) the scratch-buffer completions vanish and I’m back to “London” as expected.

I accept that Kakoune has a bunch of completions engines going on, and it might not always display completions in the order I expect, but I’m surprised that valid completions are sometimes hidden. Is this a bug, or some quirk of Kakoune’s design I haven’t fully appreciated yet?

EDIT: I found a workaround: if I install the completer with:

set-option global completers option=wiki_completions %opt{completers}

(that is, if I manually put my completer first, instead of using -add to put it last) then my completions always appear. The other completions don’t appear, but I don’t care about them as much since these completions are more specific. Other people might have multiple completion sources they care about, so maybe this behaviour still needs to be changed… but I’m OK with it for now.

1 Like

My wiki plugin now properly supports masked links (where [[custom text|SomePage]] displays “custom text” in the rendered document, but links to “SomePage”).

  • Hitting Enter on a masked link (still) takes you to the correct target document.
  • When typing a masked link, we only try to complete the text after the previous |, not all the way back to the opening [.
  • When typing any kind of link, masked links in other documents no longer break the completion engine.

In addition, we previously assumed that the link target had the same format as the current buffer - if you were editing SomePage.md and followed a link to “AnotherPage”, we would try to edit AnotherPage.md. Now we try all the extensions GitHub supports until we find one that results in a file that exists, or fall back to .md if none of them exist.

This afternoon I spent some time using the plugin to sketch out world-building notes for a role-playing game I want to run, and the biggest frustration I had was getting side-tracked by ideas rather than wrestling with the tool. I consider that a success, but I’ll keep using it for a while to see what other awkwardness I encounter.

2 Likes