From: Ben Williams Date: Wed, 25 Sep 2013 13:49:20 +0000 (-0400) Subject: Merge branch 'mappings' of https://github.com/cirosantilli/vim-markdown into cirosant... X-Git-Url: https://git.madduck.net/etc/vim.git/commitdiff_plain/b91f1039e1ea91d681628d8bf73d46d48430d76f?hp=ce737b0660a0b6d8cc3bf94438e2c74642c96670 Merge branch 'mappings' of https://github.com/cirosantilli/vim-markdown into cirosantilli-mappings --- diff --git a/README.md b/README.md index 2d7e587..550707f 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Markdown Vim Mode -Syntax highlighting and matching rules for [Markdown](http://daringfireball.net/projects/markdown/). +Syntax highlighting, matching rules and mappings for [Markdown](http://daringfireball.net/projects/markdown/). ## Installation @@ -26,6 +26,17 @@ Add the following line to your `.vimrc` to disable folding. let g:vim_markdown_folding_disabled=1 ``` +## Mappings + +the following work on normal and visual modes: + +- `]]`: go to next header +- `[[`: go to previous header +- `][`: go to next sibling header if any +- `[]`: go to previous sibling header if any +- `]c`: go to Current header +- `]u`: go to parent header (Up) + ## License The MIT License (MIT) diff --git a/ftplugin/mkd.vim b/ftplugin/mkd.vim new file mode 100644 index 0000000..c859565 --- /dev/null +++ b/ftplugin/mkd.vim @@ -0,0 +1,208 @@ +"TODO print messages when on visual mode. I only see VISUAL, not the messages. + +"this is how you should view things: +" +" |BUFFER +" | +" |outside any header +" | +"a-+# a +" | +" |inside a +" | +"a-+ +"b-+## b +" | +" |inside b +" | +"b-+ +"c-+### c +" | +" |inside c +" | +"c-+ +"d-|# d +" | +" |inside d +" | +"d-+ + +let s:headerExpr = '\v^#' + +"0 if not found +fu! b:Markdown_GetLineNumCurHeader() + retu search( s:headerExpr, 'bcnW' ) +endf + +"- if inside a header goes to it +" returns its hashes +"- if on top level outside any headers, +" print a warning +" return '' +fu! b:Markdown_GoCurHeaderGetHashes() + let l:lineNum = b:Markdown_GetLineNumCurHeader() + if l:lineNum != 0 + cal cursor( l:lineNum, 1 ) + retu matchstr( getline( lineNum ), '\v^#+' ) + el + retu '' + en +endf + +"- if inside a header goes to it +" returns its line number +"- if on top level outside any headers, +" print a warning +" return 0 +fu! b:Markdown_GoCurHeader() + let l:lineNum = b:Markdown_GetLineNumCurHeader() + if l:lineNum != 0 + cal cursor( l:lineNum, 1 ) + el + ec 'outside any header' + "norm! gg + en + retu l:lineNum +endf + +"goes to next header of any level +" +"if no there are no more headers print a warning +fu! b:Markdown_GoNextHeader() + if search( s:headerExpr, 'W' ) == 0 + "norm! G + ec 'no next header' + en +endf + +"goes to previous header of any level +" +"if it does not exist, print a warning +fu! b:Markdown_GoPreviousHeader() + let l:oldPos = getpos('.') + let l:curHeaderLineNumber = b:Markdown_GoCurHeader() + if l:curHeaderLineNumber == 0 + cal setpos('.',l:oldPos) + en + if search( s:headerExpr, 'bW' ) == 0 + "norm! gg + cal setpos('.',l:oldPos) + ec 'no previous header' + en +endf + +"goes to previous header of any level +" +"if it exists, return its lines number +" +"otherwise, print a warning and return 0 +fu! b:Markdown_GoHeaderUp() + let l:oldPos = getpos('.') + let l:hashes = b:Markdown_GoCurHeaderGetHashes() + if len( l:hashes ) > 1 + cal search( '^' . l:hashes[1:] . '[^#]', 'b' ) + el + cal setpos('.',l:oldPos) + ec 'already at top level' + en +endf + +"if no more next siblings, print error message and do nothing. +fu! b:Markdown_GoNextSiblingHeader() + let l:oldPos = getpos('.') + let l:hashes = b:Markdown_GoCurHeaderGetHashes() + let l:noSibling = 0 + + if l:hashes ==# '' + let l:noSibling = 1 + el + let l:nhashes = len(l:hashes) + if l:nhashes == 1 + "special case, just add the largest possible value + let l:nextLowerLevelLine = line('$') + 1 + el + let l:nextLowerLevelLine = search( '\v^#{1,' . ( l:nhashes - 1 ) . '}[^#]' , 'nW' ) + en + + let l:nextSameLevelLine = search( '\v^' . l:hashes . '[^#]', 'nW' ) + if ( + \ l:nextSameLevelLine > 0 + \ && + \ ( + \ l:nextLowerLevelLine == 0 + \ || + \ l:nextLowerLevelLine > l:nextSameLevelLine + \ ) + \ ) + cal cursor( l:nextSameLevelLine, 1 ) + el + let l:noSibling = 1 + en + en + + if l:noSibling + cal setpos('.',l:oldPos) + ec 'no next sibling' + en +endf + +"if no more next siblings, print error message and do nothing. +fu! b:Markdown_GoPreviousSiblingHeader() + let l:oldPos = getpos('.') + let l:hashes = b:Markdown_GoCurHeaderGetHashes() + let l:noSibling = 0 + + if l:hashes ==# '' + let l:noSibling = 1 + el + let l:nhashes = len(l:hashes) + if l:nhashes == 1 + "special case, just add the largest possible value + let l:prevLowerLevelLine = -1 + el + let l:prevLowerLevelLine = search( '\v^#{1,' . ( l:nhashes - 1 ) . '}[^#]' , 'bnW' ) + en + + let l:prevSameLevelLine = search( '\v^' . l:hashes . '[^#]', 'bnW' ) + if ( + \ l:prevSameLevelLine > 0 + \ && + \ ( + \ l:prevLowerLevelLine == 0 + \ || + \ l:prevLowerLevelLine < l:prevSameLevelLine + \ ) + \ ) + cal cursor( l:prevSameLevelLine, 1 ) + el + let l:noSibling = 1 + en + en + + if l:noSibling + cal setpos('.',l:oldPos) + ec 'no previous sibling' + en + +endf + +"wrapper to do move commands in visual mode +fu! s:VisMove(f) + norm! gv + cal function(a:f)() +endf + +"map in both normal and visual modes +fu! s:MapNormVis(rhs,lhs) + exe 'nn ' . a:rhs . ' :cal ' . a:lhs . '()' + exe 'vn ' . a:rhs . ' :cal VisMove(''' . a:lhs . ''')' +endf + +cal MapNormVis( ']]', 'b:Markdown_GoNextHeader' ) +cal MapNormVis( '[[', 'b:Markdown_GoPreviousHeader' ) +cal MapNormVis( '][', 'b:Markdown_GoNextSiblingHeader' ) +cal MapNormVis( '[]', 'b:Markdown_GoPreviousSiblingHeader' ) +"menmonic: Up +cal MapNormVis( ']u', 'b:Markdown_GoHeaderUp' ) +"menmonic: Current +cal MapNormVis( ']c', 'b:Markdown_GoCurHeader' )