commit 2941913ccc2ca1e5bd2f482c770407a712810c1b
parent a3b100ccaaa0f43113e0dab5ecf4e3b59db1ab17
Author: EinfachToll <istjanichtzufassen@googlemail.com>
Date: Fri, 6 Apr 2018 21:11:40 +0200
Add keys for motions between headers
Fix #462
Inspired by #23
Diffstat:
3 files changed, 146 insertions(+), 25 deletions(-)
diff --git a/autoload/vimwiki/base.vim b/autoload/vimwiki/base.vim
@@ -1365,15 +1365,7 @@ function! vimwiki#base#TO_header(inner, including_subheaders, count)
let current_line = line('.')
- " look for the header under which the cursor sits
- if current_line >= headers[-1][0]
- let current_header_index = len(headers) - 1
- else
- let current_header_index = -1
- while headers[current_header_index+1][0] <= current_line
- let current_header_index += 1
- endwhile
- endif
+ let current_header_index = s:current_header(headers, current_line)
if current_header_index < 0
return
@@ -1418,22 +1410,6 @@ function! vimwiki#base#TO_header(inner, including_subheaders, count)
endfunction
-function! s:get_another_header(headers, current_index, direction, operation)
- let current_level = a:headers[a:current_index][1]
- let index = a:current_index + a:direction
-
- while 1
- if index < 0 || index >= len(a:headers)
- return -1
- endif
- if eval('a:headers[index][1] ' . a:operation . ' current_level')
- return index
- endif
- let index += a:direction
- endwhile
-endfunction
-
-
" vimwiki#base#TO_table_cell
function! vimwiki#base#TO_table_cell(inner, visual) "{{{
if col('.') == col('$')-1
@@ -1713,6 +1689,93 @@ function! s:collect_headers()
endfunction
+function! s:current_header(headers, line_number)
+ if empty(a:headers)
+ return -1
+ endif
+
+ if a:line_number >= a:headers[-1][0]
+ return len(a:headers) - 1
+ endif
+
+ let current_header_index = -1
+ while a:headers[current_header_index+1][0] <= a:line_number
+ let current_header_index += 1
+ endwhile
+ return current_header_index
+endfunction
+
+
+function! s:get_another_header(headers, current_index, direction, operation)
+ if empty(a:headers) || a:current_index < 0
+ return -1
+ endif
+ let current_level = a:headers[a:current_index][1]
+ let index = a:current_index + a:direction
+
+ while 1
+ if index < 0 || index >= len(a:headers)
+ return -1
+ endif
+ if eval('a:headers[index][1] ' . a:operation . ' current_level')
+ return index
+ endif
+ let index += a:direction
+ endwhile
+endfunction
+
+
+function! vimwiki#base#goto_parent_header()
+ let headers = s:collect_headers()
+ let current_header_index = s:current_header(headers, line('.'))
+ let parent_header = s:get_another_header(headers, current_header_index, -1, '<')
+ if parent_header >= 0
+ call cursor(headers[parent_header][0], 1)
+ else
+ echo 'Vimwiki: no parent header found'
+ endif
+endfunction
+
+
+function! vimwiki#base#goto_next_header()
+ let headers = s:collect_headers()
+ let current_header_index = s:current_header(headers, line('.'))
+ if current_header_index >= 0 && current_header_index < len(headers) - 1
+ call cursor(headers[current_header_index + 1][0], 1)
+ else
+ echo 'Vimwiki: no next header found'
+ endif
+endfunction
+
+
+function! vimwiki#base#goto_prev_header()
+ let headers = s:collect_headers()
+ let current_header_index = s:current_header(headers, line('.'))
+ " if the cursor already was on a header, jump to the previous one
+ if current_header_index >= 1 && headers[current_header_index][0] == line('.')
+ let current_header_index -= 1
+ endif
+ if current_header_index >= 0
+ call cursor(headers[current_header_index][0], 1)
+ else
+ echom 'Vimwiki: no previous header found'
+ endif
+endfunction
+
+
+function! vimwiki#base#goto_sibling(direction)
+ let headers = s:collect_headers()
+ let current_header_index = s:current_header(headers, line('.'))
+ let next_potential_sibling = s:get_another_header(headers, current_header_index, a:direction, '<=')
+ if next_potential_sibling >= 0 && headers[next_potential_sibling][1] ==
+ \ headers[current_header_index][1]
+ call cursor(headers[next_potential_sibling][0], 1)
+ else
+ echo 'Vimwiki: no sibling header found'
+ endif
+endfunction
+
+
" a:create == 1: creates or updates TOC in current file
" a:create == 0: update if TOC exists
function! vimwiki#base#table_of_contents(create)
diff --git a/doc/vimwiki.txt b/doc/vimwiki.txt
@@ -325,6 +325,34 @@ NORMAL MODE *vimwiki-local-mappings*
To remap: >
:nmap -- <Plug>VimwikiRemoveHeaderLevel
<
+ *vimwiki_[[*
+[[ Go to the previous header in the buffer.
+ To remap: >
+ :nmap <- <Plug>VimwikiGoToPrevHeader
+<
+ *vimwiki_]]*
+]] Go to the next header in the buffer.
+ To remap: >
+ :nmap -> <Plug>VimwikiGoToNextHeader
+<
+ *vimwiki_[=*
+[= Go to the previous header which has the same level as
+ the header the cursor is currently under.
+ To remap: >
+ :nmap <= <Plug>VimwikiGoToPrevSiblingHeader
+<
+ *vimwiki_]=*
+]= Go to the next header which has the same level as the
+ header the cursor is currently under.
+ To remap: >
+ :nmap => <Plug>VimwikiGoToNextSiblingHeader
+<
+ *vimwiki_]u* *vimwiki_[u*
+]u [u Go one level up -- that is, to the parent header of
+ the header the cursor is currently under.
+ To remap: >
+ :nmap -^ <Plug>VimwikiGoToParentHeader
+<
*vimwiki_+*
+ Create and/or decorate links. Depending on the
context, this command will: convert words into
diff --git a/ftplugin/vimwiki.vim b/ftplugin/vimwiki.vim
@@ -662,6 +662,36 @@ endif
nnoremap <silent><buffer> <Plug>VimwikiRemoveHeaderLevel :
\<C-U>call vimwiki#base#RemoveHeaderLevel()<CR>
+if !hasmapto('<Plug>VimwikiGoToParentHeader')
+ nmap <silent><buffer> ]u <Plug>VimwikiGoToParentHeader
+ nmap <silent><buffer> [u <Plug>VimwikiGoToParentHeader
+endif
+nnoremap <silent><buffer> <Plug>VimwikiGoToParentHeader :
+ \<C-u>call vimwiki#base#goto_parent_header()<CR>
+
+if !hasmapto('<Plug>VimwikiGoToNextHeader')
+ nmap <silent><buffer> ]] <Plug>VimwikiGoToNextHeader
+endif
+nnoremap <silent><buffer> <Plug>VimwikiGoToNextHeader :
+ \<C-u>call vimwiki#base#goto_next_header()<CR>
+
+if !hasmapto('<Plug>VimwikiGoToPrevHeader')
+ nmap <silent><buffer> [[ <Plug>VimwikiGoToPrevHeader
+endif
+nnoremap <silent><buffer> <Plug>VimwikiGoToPrevHeader :
+ \<C-u>call vimwiki#base#goto_prev_header()<CR>
+
+if !hasmapto('<Plug>VimwikiGoToNextSiblingHeader')
+ nmap <silent><buffer> ]= <Plug>VimwikiGoToNextSiblingHeader
+endif
+nnoremap <silent><buffer> <Plug>VimwikiGoToNextSiblingHeader :
+ \<C-u>call vimwiki#base#goto_sibling(+1)<CR>
+
+if !hasmapto('<Plug>VimwikiGoToPrevSiblingHeader')
+ nmap <silent><buffer> [= <Plug>VimwikiGoToPrevSiblingHeader
+endif
+nnoremap <silent><buffer> <Plug>VimwikiGoToPrevSiblingHeader :
+ \<C-u>call vimwiki#base#goto_sibling(-1)<CR>
" }}}