Skip to content
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

feature/tab-list-nesting #113

Merged
merged 7 commits into from
Aug 8, 2020
Merged
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
58 changes: 41 additions & 17 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,13 +67,14 @@ Thank you for making this plugin better!
<li><a href="#table-of-contents">Table of Contents</a></li>
<li><a href="#install">Install</a></li>
<li><a href="#quick-start">Quick start</a></li>
<li><a href="#examples">Examples</a><details><summary>show 22 items</summary><ul>
<li><a href="#examples">Examples</a><details><summary>show 23 items</summary><ul>
<li><a href="#folds">Folds</a></li>
<li><a href="#insert-mode-fragment-completion">Insert mode fragment completion</a></li>
<li><a href="#dead-link-detection">Dead link detection</a></li>
<li><a href="#insert-fenced-code-block">Insert fenced code block</a></li>
<li><a href="#insert-kbdkbd-shortcut">Insert <code>&lt;kbd&gt;&lt;/kbd&gt;</code> shortcut</a></li>
<li><a href="#inserting-list-items">Inserting list items</a></li>
<li><a href="#indenting--unindenting-numbered-list-items">Indenting / unindenting numbered list items</a></li>
<li><a href="#toggling-lines-from--to-task-items">Toggling lines from / to task items</a></li>
<li><a href="#toggling-lines-from--to-list-items">Toggling lines from / to list items</a></li>
<li><a href="#toggling-lines-from--to-checklist-items">Toggling lines from / to checklist items</a></li>
Expand All @@ -91,7 +92,7 @@ Thank you for making this plugin better!
<li><a href="#open-toc-using-fzf-instead-of-quickfix-window">Open TOC using fzf instead of quickfix window</a></li>
<li><a href="#using-the-menu">Using the menu</a></li>
</ul></details></li>
<li><a href="#gmkdxsettings"><code>g:mkdx#settings</code></a><details><summary>show 43 items</summary><ul>
<li><a href="#gmkdxsettings"><code>g:mkdx#settings</code></a><details><summary>show 44 items</summary><ul>
<li><a href="#gmkdxsettingsgf_on_steroids"><code>g:mkdx#settings.gf_on_steroids</code></a></li>
<li><a href="#gmkdxsettingslinksexternalenable"><code>g:mkdx#settings.links.external.enable</code></a></li>
<li><a href="#gmkdxsettingslinksexternaltimeout"><code>g:mkdx#settings.links.external.timeout</code></a></li>
Expand All @@ -117,8 +118,9 @@ Thank you for making this plugin better!
<li><a href="#gmkdxsettingstableheader_divider"><code>g:mkdx#settings.table.header_divider</code></a></li>
<li><a href="#gmkdxsettingstabledivider"><code>g:mkdx#settings.table.divider</code></a></li>
<li><a href="#gmkdxsettingstablealign"><code>g:mkdx#settings.table.align</code></a></li>
<li><a href="#gmkdxsettingsentershift"><code>g:mkdx#settings.enter.shift</code></a></li>
<li><a href="#gmkdxsettingstabenable"><code>g:mkdx#settings.tab.enable</code></a></li>
<li><a href="#gmkdxsettingsenterenable"><code>g:mkdx#settings.enter.enable</code></a></li>
<li><a href="#gmkdxsettingsentershift"><code>g:mkdx#settings.enter.shift</code></a></li>
<li><a href="#gmkdxsettingsentero"><code>g:mkdx#settings.enter.o</code></a></li>
<li><a href="#gmkdxsettingsentershifto"><code>g:mkdx#settings.enter.shifto</code></a></li>
<li><a href="#gmkdxsettingsentermalformed"><code>g:mkdx#settings.enter.malformed</code></a></li>
Expand Down Expand Up @@ -342,6 +344,19 @@ previous indentation level.
" :h mkdx-function-shift-enter-handler
```

## Indenting / unindenting numbered list items

![mkdx indent/unindent list items](doc/gifs/indent-unindent-list-items.gif)

Numbered list items will be renumbered upon indenting / unindenting. The algorithm for this is still pretty basic
but attempts to ensure correct nesting. This feature uses <kbd>tab</kbd> and <kbd>shift</kbd>+<kbd>tab</kbd>
to indent and unindent respectively.

```viml
" :h mkdx-mapping-list-items
" :h mkdx-function-indent-handler
```

## Toggling lines from / to task items

![mkdx toggle checkbox line](doc/gifs/vim-mkdx-toggle-checkbox-line.gif)
Expand Down Expand Up @@ -1085,6 +1100,25 @@ let g:mkdx#settings = { 'table': { 'align': {
\ 'default': 'center' } } }
```

## `g:mkdx#settings.tab.enable`

This setting is enabled by default, when enabled, pressing <kbd>tab</kbd> and <kbd>shift</kbd>+<kbd>tab</kbd> on numbered
list items will indent / unindent them and also renumber the list accordingly.

## `g:mkdx#settings.enter.enable`

This setting enables auto-appending list items when you are editing a markdown list.
When <kbd>enter</kbd> is pressed, a function is executed to detect wether or not to insert a new list item
or just do a regular enter. unordered lists and numbered lists are both handled correctly.

**NOTE:** When this setting is enabled, mkdx will execute a `setlocal formatoptions-=r` to prevent duplicate list markers from being inserted.
This setting is [auto updated](#gmkdxsettingsauto_updateenable) when available.

```viml
" :h mkdx-setting-enter-enable
let g:mkdx#settings = { 'enter': { 'enable': 1 } }
```

## `g:mkdx#settings.enter.shift`

When enabled, pressing <kbd>shift</kbd>+<kbd>enter</kbd> will indent the next line upto the level of the text on the current line.
Expand Down Expand Up @@ -1139,20 +1173,6 @@ This can usually be fixed by setting them manually for your emulator, included f
:let g:mkdx#settings = { 'enter': { 'shift': 0 } }
```

## `g:mkdx#settings.enter.enable`

This setting enables auto-appending list items when you are editing a markdown list.
When <kbd>enter</kbd> is pressed, a function is executed to detect wether or not to insert a new list item
or just do a regular enter. unordered lists and numbered lists are both handled correctly.

**NOTE:** When this setting is enabled, mkdx will execute a `setlocal formatoptions-=r` to prevent duplicate list markers from being inserted.
This setting is [auto updated](#gmkdxsettingsauto_updateenable) when available.

```viml
" :h mkdx-setting-enter-enable
let g:mkdx#settings = { 'enter': { 'enable': 1 } }
```

## `g:mkdx#settings.enter.o`

This setting overwrites normal mode `o` in markdown files and causes `o` to work like pressing `<enter>` at the end of the line
Expand Down Expand Up @@ -1424,6 +1444,8 @@ To prevent mapping of a key from happening, see: [unmapping functionality](#unma
|<kbd>#</kbd> handler|insert|<kbd>#</kbd>|`<Plug>(mkdx-link-compl)`|
|Jump to file|normal|<kbd>g</kbd><kbd>f</kbd>|`<Plug>(mkdx-gf)`|
|Open external file|normal|<kbd>g</kbd><kbd>x</kbd>|`<Plug>(mkdx-gx)`|
|Indent numbered list item|<kbd>tab</kbd>|`<Plug>(mkdx-indent)`|
|Unindent numbered list item|<kbd>shift</kbd>+<kbd>tab</kbd>|`<Plug>(mkdx-unindent)`|

## Remapping functionality

Expand Down Expand Up @@ -1471,6 +1493,8 @@ nmap <leader>= <Nop>
vmap <leader>= <Nop>
```

If you only want to do this for markdown files, refer to the previous snippet using the `au` command.

The mappings are checked using the value of [`g:mkdx#settings.map.prefix`](#gmkdxsettingsmapprefix) so you may need to check its value first
by running the following: `:echo g:mkdx#settings.map.prefix`. A better way to prevent mkdx from mapping keys is by remapping `<Plug>` mappings.

Expand Down
107 changes: 107 additions & 0 deletions autoload/mkdx.vim
Original file line number Diff line number Diff line change
Expand Up @@ -1686,6 +1686,113 @@ fun! mkdx#ShiftOHandler()
startinsert!
endfun

fun! s:util.UpdateNumberedList()
let lnum = line('.')
let num_pat = '^>\? *[0-9.]\+'
let result = []

while (indent(lnum) > 0)
let lnum -= 1
endwhile

if (match(getline(lnum), num_pat) > -1)
let start_lnum = lnum
let end_lnum = lnum
let indent_size = s:sw()

while (nextnonblank(start_lnum - 1) == start_lnum - 1)
let start_lnum -= 1
endwhile

while (nextnonblank(end_lnum + 1) == end_lnum + 1)
let end_lnum += 1
endwhile

for lnum in range(start_lnum, end_lnum)
let raw_line = getline(lnum)
let line = substitute(raw_line, '^ *>', '', '')
let depth = len(get(matchlist(line, '^ *'), 0, '')) / indent_size
let line = substitute(line, '^ *', '', '')
let prev = get(result, -1)
let has_prev = type(prev) == type({})
let nums = []

if (match(line, num_pat) > -1)
if (has_prev)
let depth = min([depth, prev.depth + 1])
let nums = copy(prev.nums)

if depth > prev.depth
call add(nums, 1)
elseif depth < prev.depth
let nums = nums[0:depth]
let nums[depth] += 1
elseif depth == prev.depth
let nums[depth] += 1
endif
else
call add(nums, 1)
endif

call add(result, {
\ 'quoted': match(raw_line, '^ *>') > -1,
\ 'lnum': lnum,
\ 'depth': depth,
\ 'lines': [line],
\ 'nums': nums
\ })
elseif (has_prev)
call add(prev.lines, line)
endif
endfor
endif

for item in result
let indent = repeat(' ', s:sw() * item.depth)
let quote = item.quoted ? '> ' : ''
let lnum = item.lnum
let line = substitute(item.lines[0], num_pat, join(item.nums, '.') . '.', '')

call setline(lnum, quote . indent . line)

if (len(item.lines) > 1)
let sp_pat = '^>\? *\(\([0-9.]\+\|[' . join(g:mkdx#settings.tokens.enter, '') . ']\)\( \[.\]\)\? \|\[.\]\)'
let item_syms = get(matchlist(line, sp_pat), 1, '')
let inline_indent = repeat(' ', len(item_syms))

for inline_line in item.lines[1:]
let lnum += 1
call setline(lnum, quote . indent . inline_indent . inline_line)
endfor
endif
endfor

return result
endfun

fun! mkdx#IndentHandler(nested)
let line = getline('.')
let quote = get(matchlist(line, '^ *>'), 0, '')

if (!empty(quote))
let line = substitute(line, quote, '', '')
call setline('.', line)
endif

if a:nested
normal! >>
else
normal! <<
endif

if (!empty(quote))
let line = quote . getline('.')
call setline('.', line)
endif

call s:util.UpdateNumberedList()
endfun

fun! mkdx#ShiftEnterHandler()
if (!g:mkdx#settings.enter.shift) | return "\n" | endif
let rem = matchlist(getline('.'), '^\(> *\)\? *\(\%([0-9.]\+\|[' . join(g:mkdx#settings.tokens.enter, '') . ']\)\%( \+\[.\]\)\? *\|\[.\] *\)')
Expand Down
Binary file added doc/gifs/indent-unindent-list-items.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
39 changes: 36 additions & 3 deletions doc/mkdx.txt
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ Settings `.......................................................` |mkdx-setting
tokens.list `.....................................` |mkdx-setting-tokens-list|
table.header_divider `...................` |mkdx-setting-table-header-divider|
table.divider `.................................` |mkdx-setting-table-divider|
tab.enable `.......................................` |mkdx-setting-tab-enable|
enter.enable `...................................` |mkdx-setting-enter-enable|
enter.shift `.....................................` |mkdx-setting-enter-shift|
enter.o `.............................................` |mkdx-setting-enter-o|
Expand Down Expand Up @@ -153,6 +154,8 @@ Plugs `.............................................................` |mkdx-plug
<Plug>(mkdx-fence-backtick) `.....................` |mkdx-plug-fence-backtick|
<Plug>(mkdx-gf) `.............................................` |mkdx-plug-gf|
<Plug>(mkdx-gx) `.............................................` |mkdx-plug-gx|
<Plug>(mkdx-indent) `.....................................` |mkdx-plug-indent|
<Plug>(mkdx-unindent) `.................................` |mkdx-plug-unindent|

*mkdx-toc-mappings*
Mappings `.......................................................` |mkdx-mappings|
Expand Down Expand Up @@ -213,6 +216,7 @@ Functions `.....................................................` |mkdx-function
mkdx#WrapStrike() `..............................` |mkdx-function-wrap-strike|
mkdx#gf() `...............................................` |mkdx-function-gf|
mkdx#MaybeRestoreVisual() `.............` |mkdx-function-maybe-restore-visual|
mkdx#IndentHandler() `........................` |mkdx-function-indent-handler|

*mkdx-toc-errors*
Errors `...........................................................` |mkdx-errors|
Expand Down Expand Up @@ -637,7 +641,7 @@ being compared. This means column names are case-insensitive.
==============================================================================
`g:mkdx#settings.enter.enable = 1` *mkdx-setting-enter-enable*

When pressing <enter> in insert mode, this handles appending of new list items
When pressing <Cr> in insert mode, this handles appending of new list items
in lists. See |mkdx-setting-tokens-list| for a list of supported list tokens.
Examples can be found at |mkdx-function-enter-handler|.

Expand All @@ -647,6 +651,12 @@ The overrides include:
`setlocal formatoptions-=r`
`setlocal autoindent`

==============================================================================
`g:mkdx#settings.tab.enable = 1` *mkdx-setting-tab-enable*

When enabled, pressing <Tab> and <S-Tab> will indent / unindent lines and
additionally renumber numbered list items.

==============================================================================
`g:mkdx#settings.enter.shift = 0` *mkdx-setting-enter-shift*

Expand Down Expand Up @@ -1262,6 +1272,16 @@ using {repeat.vim} by Tim Pope (https://github.com/tpope/vim-repeat).

`:<C-U>call mkdx#gf('x')<Cr>`

==============================================================================
<Plug>(mkdx-indent) *mkdx-plug-indent*

`:call mkdx#IndentHandler(1)<Cr>`

==============================================================================
<Plug>(mkdx-unindent) *mkdx-plug-unindent*

`:call mkdx#IndentHandler(0)<Cr>`

==============================================================================
MAPPINGS *mkdx-mappings*

Expand Down Expand Up @@ -1463,17 +1483,24 @@ visual selection. This function restores visual selection if

==============================================================================
List items *mkdx-mapping-list-items*
`o` and <Cr>
`o`, `O`, <Cr>, <S-Cr>, <Tab> and <S-Tab>

When editing a list in markdown, pressing either <enter> in insert mode or `o`
in normal mode will insert a new list item below the current item. All items
in normal mode will insert a new list item below the current item. When
`O` is pressed, an item will be added above the current list item. All items
following the newly added item are incremented accordingly. The following
patterns are identified as list tokens:

- Any number of spaces followed by dot separated numbers. (`'^ \+[0-9.]\+'`)
- Any token present in |mkdx-setting-tokens-list|
- All of the above, but inside a quoted block e.g: `> 1. list item`

When pressing <S-Cr> with |mkdx-setting-enter-shift| enabled, a new line
of the current list item is created. This allows creating inline list items.

When pressing <Tab> or <S-Tab> on a numbered list, the list will be reindented
accordingly.

For examples, see |mkdx-function-enter-handler| and
|mkdx-function-shift-enter-handler|.

Expand Down Expand Up @@ -2343,6 +2370,12 @@ mkdx#MaybeRestoreVisual() *mkdx-function-maybe-restore-visual*
When |mkdx-setting-restore-visual| is enabled, this function restores the last
visual selection.

mkdx#IndentHandler({indent}) *mkdx-function-indent-handler*

When {indent} is nonzero, indents as usual, otherwise unindents as usual.
Additionally, when indenting / unindenting within a numbered list, the
list will be renumbered accordingly.

==============================================================================
|ERRORS| *mkdx-errors*

Expand Down
18 changes: 18 additions & 0 deletions ftplugin/markdown/mkdx.vim
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ let s:defaults = {
\ 'restore_visual': 1,
\ 'gf_on_steroids': 0,
\ 'enter': { 'enable': 1, 'shift': 0, 'malformed': 1, 'o': 1, 'shifto': 1 },
\ 'tab': { 'enable': 1 },
\ 'map': { 'prefix': '<leader>', 'enable': 1 },
\ 'tokens': { 'enter': ['-', '*', '>'], 'bold': '**', 'italic': '*',
\ 'list': '-', 'fence': '', 'header': '#', 'strike': '' },
Expand Down Expand Up @@ -101,6 +102,8 @@ inoremap <silent> <Plug>(mkdx-fence-backtick) <C-R>=mkdx#InsertFenced
inoremap <silent> <Plug>(mkdx-ctrl-n-compl) <C-R>=mkdx#InsertCtrlNHandler()<Cr>
inoremap <silent> <Plug>(mkdx-ctrl-p-compl) <C-R>=mkdx#InsertCtrlPHandler()<Cr>
inoremap <expr> <silent> <Plug>(mkdx-link-compl) mkdx#CompleteLink()
noremap <silent> <Plug>(mkdx-indent) :call mkdx#IndentHandler(1)<Cr>
noremap <silent> <Plug>(mkdx-unindent) :call mkdx#IndentHandler(0)<Cr>

if (g:mkdx#settings.links.fragment.complete)
setlocal completefunc=mkdx#Complete
Expand Down Expand Up @@ -187,6 +190,21 @@ if g:mkdx#settings.map.enable == 1
endif
endif

if (g:mkdx#settings.tab.enable)
if (!hasmapto('<Plug>(mkdx-indent)', 'n'))
nmap <buffer><silent> <Tab> <Plug>(mkdx-indent)
endif
if (!hasmapto('<Plug>(mkdx-indent', 'v'))
vmap <buffer><silent> <Tab> <Plug>(mkdx-indent)
endif
if (!hasmapto('<Plug>(mkdx-unindent)', 'n'))
nmap <buffer><silent> <S-Tab> <Plug>(mkdx-unindent)
endif
if (!hasmapto('<Plug>(mkdx-unindent', 'v'))
vmap <buffer><silent> <S-Tab> <Plug>(mkdx-unindent)
endif
endif

if (g:mkdx#settings.enter.enable)
setlocal formatoptions-=r
setlocal autoindent
Expand Down
Loading