From 5bb406ce8a61a504839cb7faa644fb2e560f6ab7 Mon Sep 17 00:00:00 2001 From: Ciro Duran Santillli Date: Thu, 25 Apr 2013 16:24:53 +0200 Subject: [PATCH] working on visual mode, slight behavior change to make jumps more logical --- ftplugin/mkd.vim | 278 +++++++++++++++++++++++++++-------------------- 1 file changed, 160 insertions(+), 118 deletions(-) diff --git a/ftplugin/mkd.vim b/ftplugin/mkd.vim index 0f5d82d..c859565 100644 --- a/ftplugin/mkd.vim +++ b/ftplugin/mkd.vim @@ -1,166 +1,208 @@ -"TODO get working on visual mode - -"- if inside a header -" goes to the nearest head before current position -" returns its initial hashes (#) -"- else -" goes to beginning of document -" returns '' +"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() - if search( '^#', 'bcW' ) != 0 - return matchstr( getline('.'), '\v^#+' ) + let l:lineNum = b:Markdown_GetLineNumCurHeader() + if l:lineNum != 0 + cal cursor( l:lineNum, 1 ) el - norm! gg ec 'outside any header' - return '' + "norm! gg en -endf - -"same as `b:Markdown_GoCurHeader`:function: but does not change cursor position -fu! b:Markdown_GetHashesCurHeader() - let line = search( '\v^#', 'nW' ) != 0 - retu matchstr( getline(line) '\v^#+' ) + retu l:lineNum endf "goes to next header of any level -"returns its hashes +" +"if no there are no more headers print a warning fu! b:Markdown_GoNextHeader() - if search( '\v^#', 'W' ) != 0 - return matchstr( getline('.'), '\v^#+' ) - el + if search( s:headerExpr, 'W' ) == 0 "norm! G - ec 'no more headers' - return '' + ec 'no next header' en endf "goes to previous header of any level " -"if there is no previous header, only print a warning -" -"if the cursor is not exactly at the header, -"it goes to exactly the header. So this could be used -"if you want to go to the current header line. +"if it does not exist, print a warning fu! b:Markdown_GoPreviousHeader() - if search( '^#', 'bW' ) != 0 - return matchstr( getline('.'), '\v^#+' ) - el + 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 - ec 'no more headers' - return '' + cal setpos('.',l:oldPos) + ec 'no previous header' en endf -"if already at top level, go to beginning of buffer +"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:hashes = b:Markdown_GoCurHeader() + let l:oldPos = getpos('.') + let l:hashes = b:Markdown_GoCurHeaderGetHashes() if len( l:hashes ) > 1 cal search( '^' . l:hashes[1:] . '[^#]', 'b' ) el - norm! gg + cal setpos('.',l:oldPos) + ec 'already at top level' en endf -fu! b:Markdown_GoNextHeaderSameLevel() - - let l:hashes = b:Markdown_GoCurHeader() - - "go to next occurrence of that number of hashes - cal search( '^' . l:hashes . '[^#]', 'W' ) - -endf - "if no more next siblings, print error message and do nothing. fu! b:Markdown_GoNextSiblingHeader() - - let l:hashes = b:Markdown_GoCurHeader() + let l:oldPos = getpos('.') + let l:hashes = b:Markdown_GoCurHeaderGetHashes() + let l:noSibling = 0 if l:hashes ==# '' - retu - en - - let l:nhashes = len(l:hashes) - if l:nhashes == 1 - "special case, just add the largest possible value - let l:nextLowerLevelLine = line('$') + 1 + let l:noSibling = 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 + 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, 0 ) - el - ec 'no more siblings' + cal cursor( l:nextSameLevelLine, 1 ) + el + let l:noSibling = 1 + en en -endf - -fu! b:Markdown_GoPreviousHeaderSameLevel() - - let l:hashes = b:Markdown_GoCurHeader() - - "go to next occurrence of that number of hashes - cal search( '^' . l:hashes . '[^#]', 'bW' ) - + 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:hashes = b:Markdown_GoCurHeader() + let l:oldPos = getpos('.') + let l:hashes = b:Markdown_GoCurHeaderGetHashes() + let l:noSibling = 0 if l:hashes ==# '' - retu - en - - let l:nhashes = len(l:hashes) - if l:nhashes == 1 - "special case, just add the largest possible value - let l:prevLowerLevelLine = -1 + let l:noSibling = 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 + 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, 0 ) - el - ec 'no more siblings' + 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 -"mnemonics: ']' next (like a right arrow) -nn ]] :cal b:Markdown_GoNextHeader() -"vnoremap ]] /^#:nohlgv - -"mnemonics: '[' next (like a left arrow) -nn ][ :cal b:Markdown_GoNextSiblingHeader() -"vnoremap ][ :cal b:Markdown_GoNextHeaderSameLevel() - -nn [] :cal b:Markdown_GoPreviousSiblingHeader() +"wrapper to do move commands in visual mode +fu! s:VisMove(f) + norm! gv + cal function(a:f)() +endf -nn [[ :cal b:Markdown_GoPreviousHeader() -"vnoremap [[ ?^#:nohlgv +"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 -"go up one level. Menmonic: Up. -nn ]u :cal b:Markdown_GoHeaderUp() +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' ) -- 2.39.2