Skip to content

Add auto-lists #53

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
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
66 changes: 66 additions & 0 deletions ftplugin/markdown.vim
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,70 @@ else
let b:undo_ftplugin = "setl cms< com< fo< flp<"
endif

" Markdown auto lists
" BUG: If the cursor is on a list item at `col('$') - 1`, then a new list item
" will be added on a new line instead of splitting the line
function! AutoMDList()
let line=getline('.')

" Potential unordered list match
let umatches=matchstr(line, '^[*+-]')

" Potential ordered list match
let omatches=matchstr(line, '^\d\+\.')

if empty(umatches) && empty(omatches)
" TODO: Handle the case where a list item spans over several lines.
"
" In that case, a new list item needs to be added.
"
" I don't know (yet) how to do this without going up a line in a loop and
" checking if it's the first line of the list item (that is a terrible
" solution!!)

" If the user is not in a list, use the default behaviour for <CR>
call feedkeys("\<CR>", "n")
elseif empty(omatches)
" The case of an unordered list

if !empty(matchstr(line, '^[*+-]\s\?$'))
" If the user is on a blank list item (i.e.: "- ") and presses <CR>, end
" the list...
exec ':normal! cc' | call feedkeys("\<CR>", "n")
elseif col('.') == len(getline('.'))
" ...otherwise, if the cursor is at the end of the line, add a list
" item...

exec ':normal! o' . umatches . ' ' | exec ':startinsert!'
else
" ...and if the cursor is in the middle of a line, use the default
" behaviour for <CR>
call feedkeys("\<CR>", "n")
endif
elseif empty(umatches)
" The case of an ordered list

if !empty(matchstr(line, '^\d\+\.\s\?$'))
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could that make use of formatlistpat instead (set to ^\\s*\\d\\+\\.\\s\\+\\\|^[-*+]\\s\\+ by the plugin).

" If the user is on a blank list item (i.e.: "42. ") and presses <CR>,
" end the list...
exec ':normal! cc' | call feedkeys("\<CR>", "n")
elseif col('.') == len(getline('.'))
" ...otherwise, if the cursor is at the end of the line, increment the list item number...
let l:nln=omatches + 1

" ...and add a new item
exec ':normal! o' . l:nln . '. ' | exec ':startinsert!'
else
" ...and if the cursor is in the middle of a line, use the default
" behaviour for <CR>
call feedkeys("\<CR>", "n")
endif
endif

return
endf

" Remap <CR> for all .md files
au BufEnter *.md inoremap <buffer> <CR> <C-o>:call AutoMDList()<CR>
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That should probably be a FileType autocommand instead, and match markdown.
It is rather tricky to setup the CR mapping, because existing maps should get handled / forwarded.
Take a look at how endwise handles it. I have just submitted a PR to improve upon it: https://github.com/tpope/vim-endwise/pull/50/files


" vim:set sw=2: