Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 38 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,42 @@
# vim-multimarkdown

An extension of Ben Williams's markdown syntax file to accommodate Fletcher
Penney's multimarkdown.
Penney's [multimarkdown](http://fletcherpenney.net/multimarkdown/).

## Table support

This plugin allows you to add columns and rows to a table, change the
justification, and format the table so all columns have the same width.
The functions for this are as follows:

| Operation | Command name | Default keybinding |
| :-------- | :------------ | :----------------- |
| Add a row above the current position | `:MmdTableAddRowAbove` | `<localleader>to` |
| Add a row below the current position | `:MmdTableAddRowBelow` | `<localleader>tO` |
| Add a column before the current position | `:MmdTableAddColBefore` | `<localleader>ti` |
| Add a column after the current position | `:MmdTableAddColAfter` | `<localleader>ta` |
| Remove the current table row | `:MmdTableDeleteRow` | `<localleader>tdd` |
| Remove the current table column | `:MmdTableDeleteCol` | `<localleader>tx` |
| Format the entire table | `:MmdTableFormat` | `<localleader>tgq` |
| Set column to justify left | `:MmdLeftJustifyCol` | `<localleader>tjl` |
| Set column to justify center | `:MmdCenterCol` | `<localleader>tjc` |
| Set column to justify right | `:MmdRightJustifyCol` | `<localleader>tjr` |
| Create a new table of the specified size | `:MmdTableCreate <rows> <cols>` | none |
| Go to a specific cell | `:MmdTableCell <row> <col>` | none |

## Keybindings

Because of the number of functions this plugin provides default keybindings.
If you don't want to use this then you can disable key mappings in your
`.vimrc` file like so:

```VimL
let g:vim_multimarkdown_map_keys = 0
```

and then map the keys yourself, for example:

```VimL
nnoremap <localleader>addcol :call g:AddTableColumnBefore()<CR>
```

Still in early, halfhearted development.
25 changes: 25 additions & 0 deletions ftplugin/mmd/keybindings.vim
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@

if !exists('g:vim_multimarkdown_map_keys')
let g:vim_multimarkdown_map_keys = 1
endif

" ---------------------
" table stuff
" ---------------------

if g:vim_multimarkdown_map_keys
" adding/removing cells
nnoremap <localleader>ti :MmdTableAddColBefore<CR>
nnoremap <localleader>ta :MmdTableAddColAfter<CR>
nnoremap <localleader>tO :MmdTableAddRowAbove<CR>
nnoremap <localleader>to :MmdTableAddRowBelow<CR>
nnoremap <localleader>tdd :MmdTableDeleteRow<CR>
nnoremap <localleader>tx :MmdTableDeleteCol<CR>

" table formatting
nnoremap <localleader>tgq :MmdTableFormat<CR>
nnoremap <localleader>tjl :MmdLeftJustifyCol<CR>
nnoremap <localleader>tjc :MmdCenterCol<CR>
nnoremap <localleader>tjr :MmdRightJustifyCol<CR>
endif

260 changes: 260 additions & 0 deletions ftplugin/mmd/tables.vim
Original file line number Diff line number Diff line change
@@ -0,0 +1,260 @@

" ---------------------
" internal module stuff
" ---------------------

function! s:IsTableRow(line)
return a:line =~# "^\|.*\|$"
endfunction

" clears out the contents of a row without affecting the columns
function! s:ClearRow(line)
return substitute(a:line, '[^|]', ' ', 'g')
endfunction

" returns the line of the header of the table
function! s:HeaderLine()
let winview = winsaveview()
normal! {
let linenum = line(".") + 1
call winrestview(winview)
return linenum
endfunction

" returns the last line of the table
function! s:TableEndLine()
let winview = winsaveview()
normal! }
let linenum = line(".") - 1
call winrestview(winview)
return linenum
endfunction

function! s:TableNumRows()
return s:TableEndLine() - s:HeaderLine() + 1
endfunction

function! s:TableNumCols()
return strlen(substitute(getline('.'), '[^|]', '', 'g')) - 1
endfunction

" returns the current row relative to the beginning of the table
function! s:CurrentRow()
return line(".") - s:HeaderLine() + 1
endfunction

function! s:CurrentCol()
return strlen(substitute(getline('.')[0:col('.')], '[^|]', '', 'g'))
endfunction

" returns the width of the column we are on
function! s:ColumnWidth()
let winview = winsaveview()
if getline('.')[col('.')-1] !=? '|'
normal! F|
endif
let colstart = col('.')
normal! f|
let colend = col('.')
call winrestview(winview)
return colend - colstart - 1
endfunction

" 1=left, 2=center, 3=right
function! s:ChangeJustification(col, justcode)
let winview = winsaveview()
call s:GotoCell(2, a:col)
let markerwidth = s:ColumnWidth() - 2
if a:justcode == 1
let juststr = ":" . repeat('-', markerwidth-1)
elseif a:justcode == 2
let juststr = ":" . repeat('-', markerwidth-2) . ":"
elseif a:justcode == 3
let juststr = repeat('-', markerwidth-1) . ":"
endif
execute "normal! ct| " . juststr . " "
call winrestview(winview)
endfunction

" ---------------------
" public stuff
" ---------------------

" creates a new table of the specified size
" there is 1 header row
function! s:CreateTable(numrows, numcols)
" create the header row
execute "normal! i" . repeat('| ', a:numcols) . "|"
normal! o
" just make everything left justified
execute "normal! i" . repeat('| :-- ', a:numcols) . "|"
"normal! o
" put in the rows
let i = 0
while i < a:numrows
call s:AddTableRowBelow()
let i += 1
endwhile
endfunction

" goes to a specific cell
function! s:GotoCell(row, col)
if !s:IsTableRow(getline('.'))
return
endif

" first move to the correct line
let destline = a:row + s:HeaderLine() - 1
execute "normal! " . destline . "G"
normal! 0

" now we move to the correct cell
if a:col > 1
execute "normal! " . (a:col-1) . "f|"
endif
normal! l
endfunction

function! s:AddTableRowBelow()
if !s:IsTableRow(getline('.'))
return
endif

normal! yyp
call setline('.', s:ClearRow(getline('.')))
endfunction

function! s:AddTableRowAbove()
if !s:IsTableRow(getline('.'))
return
endif

normal! kyyp
call setline('.', s:ClearRow(getline('.')))
endfunction

function! s:AddTableColumnBefore()
if !s:IsTableRow(getline('.'))
return
endif

let new_col = '|' . repeat(' ', s:ColumnWidth())
let curcol = s:CurrentCol()
let curline = 1
while curline <= s:TableNumRows()
call s:GotoCell(curline, curcol)
normal! F|
execute "normal! i" . new_col
let curline += 1
endwhile
endfunction

function! s:AddTableColumnAfter()
if !s:IsTableRow(getline('.'))
return
endif

let new_col = repeat(' ', s:ColumnWidth()) . '|'
let curcol = s:CurrentCol()
let curline = 1
while curline <= s:TableNumRows()
call s:GotoCell(curline, curcol)
normal! f|
execute "normal! a" . new_col
let curline += 1
endwhile
endfunction

function! s:DeleteTableRow()
if !s:IsTableRow(getline('.'))
return
endif

normal! dd
endfunction

function! s:DeleteTableColumn()
if !s:IsTableRow(getline('.'))
return
endif

let curcol = s:CurrentCol()
let curline = 1
while curline <= s:TableNumRows()
call s:GotoCell(curline, curcol)
normal! F|
normal! dt|
let curline += 1
endwhile
endfunction

function! s:FormatTable()
if !s:IsTableRow(getline('.'))
return
endif
" we need to figure out how many spaces are in each column
" and adjust all rows to contain that many spaces
let col = 1
while col <= s:TableNumCols()
" first figure out the largest column
let line = 1
let maxcolwidth = 0
while line <= s:TableNumRows()
call s:GotoCell(line, col)
let w = s:ColumnWidth()
if w > maxcolwidth
let maxcolwidth = w
endif
let line += 1
endwhile
" now pad each row in the column
let line = 1
while line <= s:TableNumRows()
call s:GotoCell(line, col)
let padlen = maxcolwidth - s:ColumnWidth() + 1
if padlen > 0
normal! t|
execute "normal! ct|" . repeat(' ', padlen)
endif
let line += 1
endwhile
let col += 1
endwhile
endfunction

" left justify the column we're in
function! s:LeftifyColumn()
call s:ChangeJustification(s:CurrentCol(), 1)
endfunction

" center justify the column we're in
function! s:CenterColumn()
call s:ChangeJustification(s:CurrentCol(), 2)
endfunction

" right justify the column we're in
function! s:RightifyColumn()
call s:ChangeJustification(s:CurrentCol(), 3)
endfunction


" ---------------------
" commands
" ---------------------

command! -nargs=+ MmdTableCreate call s:CreateTable(<f-args>)
command! -nargs=+ MmdTableCell call s:GotoCell(<f-args>)
command! MmdTableFormat call s:FormatTable()

command! MmdLeftJustifyCol call s:LeftifyColumn()
command! MmdRightJustifyCol call s:RightifyColumn()
command! MmdCenterCol call s:CenterColumn()

command! MmdTableAddRowBelow call s:AddTableRowBelow()
command! MmdTableAddRowAbove call s:AddTableRowAbove()
command! MmdTableAddColBefore call s:AddTableColumnBefore()
command! MmdTableAddColAfter call s:AddTableColumnAfter()

command! MmdTableDeleteRow call s:DeleteTableRow()
command! MmdTableDeleteCol call s:DeleteTableColumn()

12 changes: 12 additions & 0 deletions syntax/mmd.vim
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,9 @@ syn match mmdFootnoteMarker "\[^\S\+\]"
syn match mmdFootnoteIdentifier "\[^.\+\]:" contained
syn region mmdFootnoteText start="^\s\{0,3\}\[^.\+\]:[ \t]" end="^$" contains=mmdFootnoteIdentifier

" mmd table support
syn region mmdTable start=/\v^\|.+\|$/ end=/\v^$/

" Link definitions: [id]: URL (Optional Title)
" TODO handle automatic links without colliding with htmlTag (<URL>)
"syn region mkdLinkDef matchgroup=mkdDelimiter start="^ \{,3}\zs\[[^^#]" end="]:" oneline nextgroup=mkdLinkDefTarget skipwhite
Expand Down Expand Up @@ -162,6 +165,15 @@ HtmlHiLink mkdSourceDef Statement
HtmlHiLink mkdSource String
HtmlHiLink mkdLinkAttrib Function

<<<<<<< HEAD
=======
HtmlHiLink mmdEquation1 mmdMath
HtmlHiLink mmdEquation2 mmdMath
HtmlHiLink mmdMath Special

HtmlHiLink mmdTable Comment

>>>>>>> 1429db9... playing with syntax highlighting of tables
HtmlHiLink mkdDelimiter Delimiter

let b:current_syntax = "mmd"
Expand Down