summaryrefslogtreecommitdiff
path: root/doc/forum/navigation_of_wiki_pages_on_local_filesystem_with_vim.mdwn
blob: fd9f67ee4ca7fce2815e04172a0648f6b4a0ddd0 (plain)

I wrote a vim function to help me navigate the wiki when I'm editing it. It extends the 'gf' (goto file) functionality. Once installed, you place the cursor on a wiki page name and press 'gf' (without the quotes); if the file exists, it gets loaded.

This function takes into account the ikiwiki linking rules when deciding which file to go to.

'gf' gets in the way when there are directories with the same name of a wiki page. The function below doesn't implement the linking rules properly (test the link (ignoring case), if there is no match ascend the dir. hierarchy and start over, until we reach the root of the wiki). I'm rewriting it to follow these rules properly

I think the page for [[LinkingRules|ikiwiki/subpage/linkingrules]] should say that ikiwiki ascends the dir. hierarchy when looking for a wikilink, not that it descends it. Am I correct? --[[jerojasro]]

Conventionally, the root directory is considered to be lower than other directories, so I think the current wording is correct. --[[Joey]]

let me know what you think

    " NOTE: the root of the wiki is considered the first directory that contains a
    " .ikiwiki folder, except $HOME/.ikiwiki (the usual ikiwiki libdir)

That's not going to work in all situations; for example, with an ikiwiki which uses git as the backend, the normal setup is that one has

  • a bare git repository
  • a git repository which ikiwiki builds the wiki from (which has a .ikiwiki directory in it)
  • an additional git repository cloned from the bare repository, which is used for making changes from the command-line rather than the web. It is this repository in which one would be editing files with vim, and this repository does not have a .ikiwiki directory in it. It does have a .git directory in the root, however, so I suppose you could use that as a method of detection of a root directory, but of course that would only work for git repositories.

-- [[KathrynAndersen]]

You are completely right; all of my wikis are compiled both locally and remotely, and so the local repo also has a .ikiwiki folder. And that's not the "usual" setup.

checking for a .git dir would not work when the wiki's source files aren't located at the root of the repo.

So, besides of doing a touch .ikiwiki at the root of the wiki in your local repo, do you see any alternative?

-- [[jerojasro]] To enable this functionality, paste the code below in your .vim/ftplugin/ikiwiki.vim file

" returns the directory which can be considered the root of the wiki the
" current buffer belongs to, or an empty string if we are not inside an
" ikiwiki wiki
"
" NOTE: the root of the wiki is considered the first directory that contains a
" .ikiwiki folder, except $HOME/.ikiwiki (the usual ikiwiki libdir)
"
" if you can think of a better heuristic to get ikiwiki's root, let me know!
function! GetWikiRootDir()
  let check_str = '%:p:h'
  let pos_wiki_root = expand(check_str)
  while pos_wiki_root != '/'
    if isdirectory(pos_wiki_root . '/.ikiwiki') && pos_wiki_root != $HOME
      return pos_wiki_root
    endif
    let check_str = check_str . ':h'
    let pos_wiki_root = expand(check_str)
  endwhile
  if isdirectory('/.ikiwiki')
    return '/'
  endif
  return ''
endfunction

" This function searches for a .mdwn file (<a:name>.mdwn) using the ikiwiki
" WikiLink rules and returns its full path.
"
" The rules are the following
"
" if the filename starts with '/', use as base dir the root directory of the
" wiki
"
" if not:
"
" try first ./<bufname>/<a:name>.mdwn
" then for  ./<a:name>.mdwn
" then for  <root_of_wiki>/<a:name>.mdwn
"
" return the first one that exists
"
" the base path (. above) is the directory that contains the current buffer
"
function! FileForWikiLink(name)
  let target_fname=a:name . ".mdwn"
  let wikiroot_dir = GetWikiRootDir()
  if match(target_fname, '^/') >= 0
    return wikiroot_dir . target_fname
  endif
  let subdir_file = expand('%:p:r') . "/" . target_fname
  let currdir_file = expand('%:p:h') . "/" . target_fname
  let wikiroot_file = wikiroot_dir . "/" . target_fname
  if filewritable(subdir_file)
    return subdir_file
  endif
  if filewritable(currdir_file)
    return currdir_file
  endif
  if filewritable(wikiroot_file)
    return wikiroot_file
  endif
  return a:name
endfunction

setlocal includeexpr=FileForWikiLink(v:fname)