]> git.madduck.net Git - etc/vim.git/commitdiff

madduck's git repository

Every one of the projects in this repository is available at the canonical URL git://git.madduck.net/madduck/pub/<projectpath> — see each project's metadata for the exact URL.

All patches and comments are welcome. Please squash your changes to logical commits before using git-format-patch and git-send-email to patches@git.madduck.net. If you'd read over the Git project's submission guidelines and adhered to them, I'd be especially grateful.

SSH access, as well as push access can be individually arranged.

If you use my repositories frequently, consider adding the following snippet to ~/.gitconfig and using the third clone URL listed for each project:

[url "git://git.madduck.net/madduck/"]
  insteadOf = madduck:

Merge pull request #84 from cirosantilli/setex-tests
authorCiro Santilli <ciro.santilli@gmail.com>
Tue, 8 Jul 2014 06:53:19 +0000 (08:53 +0200)
committerCiro Santilli <ciro.santilli@gmail.com>
Tue, 8 Jul 2014 06:53:19 +0000 (08:53 +0200)
Add Setex examples to the multiple headers test.

README.md
after/ftplugin/mkd.vim
ftplugin/mkd.vim
test/table_format.md [new file with mode: 0644]

index 24c5c6c041a6a1e8b9a7d909f7cadf9ab00d3aa6..18044db9d042181c4871062592ec5f78936dfefa 100644 (file)
--- a/README.md
+++ b/README.md
@@ -6,12 +6,15 @@ Syntax highlighting, matching rules and mappings for [the original Markdown](htt
 
 If you use [Vundle](https://github.com/gmarik/vundle), add the following line to your `~/.vimrc`:
 
-    Bundle 'plasticboy/vim-markdown'
+    Plugin 'godlygeek/tabular'
+    Plugin 'plasticboy/vim-markdown'
 
-And then run inside Vim:
+The `tabular` plugin come *before* `vim-markdown`.
+
+Then run inside Vim:
 
     :so ~/.vimrc
-    :BundleInstall
+    :PluginInstall
 
 If you use [Pathogen](https://github.com/tpope/vim-pathogen), do this:
 
@@ -69,14 +72,39 @@ The following work on normal and visual modes:
 
 ## Commands
 
-The following commands currently only work for atx style headers (`#`). Pull request are welcome to extend them to Setext style headers (`===`).
+- `:HeaderDecrease`:
+
+    Decrease level of all headers in buffer: `h2` to `h1`, `h3` to `h2`, etc.
+
+    If range is given, only operate in the range.
+
+    If an `h1` would be decreased, abort.
+
+    For simplicity of implementation, Setex headers are converted to Atx.
+
+- `:HeaderIncrease`: Analogous to `:HeaderDecrease`, but increase levels instead.
+
+- `:SetexToAtx`:
+
+    Convert all Setex style headers in buffer to Atx.
+
+    If a range is given, e.g. hit `:` from visual mode, only operate on the range.
+
+- `:TableFormat`: Format the table under the cursor [like this](http://www.cirosantilli.com/markdown-styleguide/#tables).
+
+    Requires [Tabular](https://github.com/godlygeek/tabular).
+
+    The input table *must* already have a separator line as the second line of the table.
+    That line only needs to contain the correct pipes `|`, nothing else is required.
 
 - `:Toc`: create a quickfix vertical window navigable table of contents with the headers.
 
     Hit `<Enter>` on a line to jump to the corresponding line of the markdown file.
 
 - `:Toch`: Same as `:Toc` but in an horizontal window.
+
 - `:Toct`: Same as `:Toc` but in a new tab.
+
 - `:Tocv`: Same as `:Toc` for symmetry with `:Toch` and `Tocv`.
 
 ## Credits
index 26ccb23b885f4b37ccdf76597927970b58a6c2ca..6026ae8b05204cd695557b5077ed7601e6dcafa3 100644 (file)
@@ -36,7 +36,7 @@ func! Foldexpr_markdown(lnum)
 endfunc
 
 
-if !exists("g:vim_markdown_folding_disabled")
+if !get(g:, "vim_markdown_folding_disabled", 0)
   setlocal foldexpr=Foldexpr_markdown(v:lnum)
   setlocal foldmethod=expr
 
index 9c07714882e876a5ad041c13cf8ecd9fa90a917a..36d0b0816ce3ebdde05c7141afdafa3f59cabc47 100644 (file)
 
 " For each level, contains the regexp that matches at that level only.
 let s:levelRegexpDict = {
-    \ 1: '\v^(\s*#[^#]|.+\n\=+$)',
-    \ 2: '\v^(\s*##[^#]|.+\n-+$)',
-    \ 3: '\v^\s*###[^#]',
-    \ 4: '\v^\s*####[^#]',
-    \ 5: '\v^\s*#####[^#]',
-    \ 6: '\v^\s*######[^#]'
+    \ 1: '\v^(#[^#]|.+\n\=+$)',
+    \ 2: '\v^(##[^#]|.+\n-+$)',
+    \ 3: '\v^###[^#]',
+    \ 4: '\v^####[^#]',
+    \ 5: '\v^#####[^#]',
+    \ 6: '\v^######[^#]'
 \ }
 
 " Maches any header level of any type.
@@ -60,7 +60,7 @@ let s:levelRegexpDict = {
 " This could be deduced from `s:levelRegexpDict`, but it is more
 " efficient to have a single regexp for this.
 "
-let s:headersRegexp = '\v^(\s*#|.+\n(\=+|-+)$)'
+let s:headersRegexp = '\v^(#|.+\n(\=+|-+)$)'
 
 " Returns the line number of the first header before `line`, called the
 " current header.
@@ -300,7 +300,14 @@ function! s:Markdown_Toc(...)
     else
         let l:window_type = 'vertical'
     endif
-    silent vimgrep '^#' %
+
+    try
+        silent vimgrep /\(^\S.*\(\n[=-]\+\)\@=\|^#\+\)/ %
+    catch /E480/
+        echom "Toc: No headers."
+        return
+    endtry
+
     if l:window_type ==# 'horizontal'
         copen
     elseif l:window_type ==# 'vertical'
@@ -314,13 +321,23 @@ function! s:Markdown_Toc(...)
     set modifiable
     %s/\v^([^|]*\|){2,2} #//
     for i in range(1, line('$'))
-        let l:line = getline(i)
-        let l:header =  matchstr(l:line, '^#*')
-        let l:length = len(l:header)
-        let l:line = substitute(l:line, '\v^#*[ ]*', '', '')
-        let l:line = substitute(l:line, '\v[ ]*#*$', '', '')
-        let l:line = repeat(' ', (2 * l:length)) . l:line
-        call setline(i, l:line)
+        " this is the quickfix data for the current item
+        let d = getqflist()[i-1]
+        " atx headers
+        if match(d.text, "^#") > -1
+            let l:level = len(matchstr(d.text, '#*', 'g'))-1
+            let d.text = substitute(d.text, '\v^#*[ ]*', '', '')
+            let d.text = substitute(d.text, '\v[ ]*#*$', '', '')
+        " setex headers
+        else
+            let l:next_line = getbufline(bufname(d.bufnr), d.lnum+1)
+            if match(l:next_line, "=") > -1
+                let l:level = 0
+            elseif match(l:next_line, "-") > -1
+                let l:level = 1
+            endif
+        endif
+        call setline(i, repeat('  ', l:level). d.text)
     endfor
     set nomodified
     set nomodifiable
@@ -341,6 +358,59 @@ function! s:MapNormVis(rhs,lhs)
     execute 'vn <buffer><silent> ' . a:rhs . ' <esc>:call <sid>VisMove(''' . a:lhs . ''')<cr>'
 endfunction
 
+" Convert Setex headers in range `line1 .. line2` to Atx.
+" Returns the number of conversions.
+function! s:SetexToAtx(line1, line2)
+    let l:originalNumLines = line('$')
+    execute 'silent! ' . a:line1 . ',' . a:line2 . 'substitute/\v(.*\S.*)\n\=+$/# \1/'
+    execute 'silent! ' . a:line1 . ',' . a:line2 . 'substitute/\v(.*\S.*)\n-+$/## \1/'
+    return l:originalNumLines - line('$')
+endfunction
+
+" If `a:1` is 0, decrease the level of all headers in range `line1 .. line2`.
+" Otherwise, increase the level. `a:1` defaults to `0`.
+function! s:HeaderDecrease(line1, line2, ...)
+    if a:0 > 0
+        let l:increase = a:1
+    else
+        let l:increase = 0
+    endif
+    if l:increase
+        let l:forbiddenLevel = 6
+        let l:replaceLevels = [5, 1]
+        let l:levelDelta = 1
+    else
+        let l:forbiddenLevel = 1
+        let l:replaceLevels = [2, 6]
+        let l:levelDelta = -1
+    endif
+    for l:line in range(a:line1, a:line2)
+        if join(getline(l:line, l:line + 1), "\n") =~ s:levelRegexpDict[l:forbiddenLevel]
+            echomsg 'There is an h' . l:forbiddenLevel . ' at line ' . l:line . '. Aborting.'
+            return
+        endif
+    endfor
+    let l:numSubstitutions = s:SetexToAtx(a:line1, a:line2)
+    for l:level in range(replaceLevels[0], replaceLevels[1], -l:levelDelta)
+        execute 'silent! ' . a:line1 . ',' . (a:line2 - l:numSubstitutions) . 'substitute/' . s:levelRegexpDict[l:level] . '/' . repeat('#', l:level + l:levelDelta) . '\1/g'
+    endfor
+endfunction
+
+" Format table under cursor.
+" Depends on Tabularize.
+function! s:TableFormat()
+  let l:pos = getpos('.')
+  normal! {
+  " Search instead of `normal! j` because of the table at beginning of file edge case.
+  call search('|')
+  normal! j
+  " Remove everything that is not a pipe othewise well formated tables would grow
+  " because of addition of 2 spaces on the separator line by Tabularize /|.
+  s/[^|]//g
+  Tabularize /|
+  s/ /-/g
+  call setpos('.', l:pos)
+endfunction
 
 call <sid>MapNormVis('<Plug>(Markdown_MoveToNextHeader)', '<sid>Markdown_MoveToNextHeader')
 call <sid>MapNormVis('<Plug>(Markdown_MoveToPreviousHeader)', '<sid>Markdown_MoveToPreviousHeader')
@@ -351,23 +421,26 @@ call <sid>MapNormVis('<Plug>(Markdown_MoveToParentHeader)', '<sid>Markdown_MoveT
 " Menmonic: Current
 call <sid>MapNormVis('<Plug>(Markdown_MoveToCurHeader)', '<sid>Markdown_MoveToCurHeader')
 
-if ! exists('g:vim_markdown_no_default_key_mappings')
-\ || !g:vim_markdown_no_default_key_mappings
-    nmap ]] <Plug>(Markdown_MoveToNextHeader)
-    nmap [[ <Plug>(Markdown_MoveToPreviousHeader)
-    nmap ][ <Plug>(Markdown_MoveToNextSiblingHeader)
-    nmap [] <Plug>(Markdown_MoveToPreviousSiblingHeader)
-    nmap ]u <Plug>(Markdown_MoveToParentHeader)
-    nmap ]c <Plug>(Markdown_MoveToCurHeader)
+if !get(g:, 'vim_markdown_no_default_key_mappings', 0)
+    nmap <buffer> ]] <Plug>(Markdown_MoveToNextHeader)
+    nmap <buffer> [[ <Plug>(Markdown_MoveToPreviousHeader)
+    nmap <buffer> ][ <Plug>(Markdown_MoveToNextSiblingHeader)
+    nmap <buffer> [] <Plug>(Markdown_MoveToPreviousSiblingHeader)
+    nmap <buffer> ]u <Plug>(Markdown_MoveToParentHeader)
+    nmap <buffer> ]c <Plug>(Markdown_MoveToCurHeader)
 
-    vmap ]] <Plug>(Markdown_MoveToNextHeader)
-    vmap [[ <Plug>(Markdown_MoveToPreviousHeader)
-    vmap ][ <Plug>(Markdown_MoveToNextSiblingHeader)
-    vmap [] <Plug>(Markdown_MoveToPreviousSiblingHeader)
-    vmap ]u <Plug>(Markdown_MoveToParentHeader)
-    vmap ]c <Plug>(Markdown_MoveToCurHeader)
+    vmap <buffer> ]] <Plug>(Markdown_MoveToNextHeader)
+    vmap <buffer> [[ <Plug>(Markdown_MoveToPreviousHeader)
+    vmap <buffer> ][ <Plug>(Markdown_MoveToNextSiblingHeader)
+    vmap <buffer> [] <Plug>(Markdown_MoveToPreviousSiblingHeader)
+    vmap <buffer> ]u <Plug>(Markdown_MoveToParentHeader)
+    vmap <buffer> ]c <Plug>(Markdown_MoveToCurHeader)
 endif
 
+command! -buffer -range=% HeaderDecrease call s:HeaderDecrease(<line1>, <line2>)
+command! -buffer -range=% HeaderIncrease call s:HeaderDecrease(<line1>, <line2>, 1)
+command! -buffer -range=% SetexToAtx call s:SetexToAtx(<line1>, <line2>)
+command! -buffer TableFormat call s:TableFormat()
 command! -buffer Toc call s:Markdown_Toc()
 command! -buffer Toch call s:Markdown_Toc('horizontal')
 command! -buffer Tocv call s:Markdown_Toc('vertical')
diff --git a/test/table_format.md b/test/table_format.md
new file mode 100644 (file)
index 0000000..3b617f0
--- /dev/null
@@ -0,0 +1,17 @@
+| normal |no space|  2 spaces  ||
+| - |-|  --- ||
+| normal |no space|  2 spaces  ||
+
+The table above is the first thing in the file.
+
+The following table is already well formatted. It should not be modified:
+
+| a | b |
+|---|---|
+| c | d |
+
+The following table is the last thing in the file:
+
+| normal |no space|  2 spaces  ||
+| - |-|  --- ||
+| normal |no space|  2 spaces  ||