diff --git a/autoload/nuwiki/commands.vim b/autoload/nuwiki/commands.vim index ba8dee0..99c5730 100644 --- a/autoload/nuwiki/commands.vim +++ b/autoload/nuwiki/commands.vim @@ -1025,10 +1025,22 @@ function! nuwiki#commands#smart_tab() abort if l:target_idx < len(l:starts) return "\call nuwiki#commands#_table_jump_to_cell(" . line('.') . ", " . l:target_idx . ")\" endif - " Past the final cell → add a fresh row below, cursor in its first cell. + " Past the final cell. Prefer cycling into the next existing row (skipping + " any separator row); only insert a fresh row when we're already on the + " table's last row. + let l:row = line('.') + let [l:s_row, l:e_row] = s:find_table_range(l:row) + let l:next = l:row + 1 + while l:next <= l:e_row + let [l:_, l:next_cells] = s:parse_table_row(getline(l:next)) + if !s:is_sep_row(l:next_cells) + return "\call nuwiki#commands#_table_jump_to_cell(" . l:next . ", 1)\" + endif + let l:next += 1 + endwhile let l:indent = matchstr(l:line, '^\s*') let l:cursor_col = len(l:indent) + 2 - return "\call nuwiki#commands#_table_insert_row_below(" . line('.') . ", " . l:cursor_col . ")\" + return "\call nuwiki#commands#_table_insert_row_below(" . l:row . ", " . l:cursor_col . ")\" endfunction function! nuwiki#commands#smart_shift_tab() abort diff --git a/lua/nuwiki/commands.lua b/lua/nuwiki/commands.lua index 0134d52..a6f9e73 100644 --- a/lua/nuwiki/commands.lua +++ b/lua/nuwiki/commands.lua @@ -826,16 +826,32 @@ function M.smart_tab() if start <= col + 1 then current_idx = i end end local target_idx = current_idx + 1 - if target_idx >= #cell_starts then + if target_idx < #cell_starts then return string.format( - 'lua require("nuwiki.commands")._table_insert_row_below(%d)', - row + 'lua require("nuwiki.commands")._table_jump_to_cell(%d, %d)', + row, + target_idx ) end + -- Past the final cell. Prefer cycling into the next existing row + -- (skipping any separator); only insert a fresh row when we're on the + -- table's last row. + local _, e_row = find_table_range(row) + local next_row = row + 1 + while next_row <= e_row do + local _, next_cells = parse_table_row(vim.fn.getline(next_row)) + if not is_separator_row(next_cells) then + return string.format( + 'lua require("nuwiki.commands")._table_jump_to_cell(%d, %d)', + next_row, + 1 + ) + end + next_row = next_row + 1 + end return string.format( - 'lua require("nuwiki.commands")._table_jump_to_cell(%d, %d)', - row, - target_idx + 'lua require("nuwiki.commands")._table_insert_row_below(%d)', + row ) end diff --git a/scripts/test-keymaps-vim.vim b/scripts/test-keymaps-vim.vim index 844d1b9..328f6bd 100644 --- a/scripts/test-keymaps-vim.vim +++ b/scripts/test-keymaps-vim.vim @@ -197,6 +197,18 @@ call s:run('tab.next_cell_in_table', { \ 'keys': "A\x\", \ 'expect_lines': ['| a | b |', '|x | |'], \ }) +call s:run('tab.cycles_to_next_row_when_not_last', { + \ 'lines': ['| a | b |', '|---|---|', '| c | d |'], + \ 'cursor': [1, 7], + \ 'keys': "i\x\", + \ 'expect_lines': ['| a | b |', '|---|---|', '|x c | d |'], + \ }) +call s:run('tab.inserts_row_only_when_on_last_row', { + \ 'lines': ['| a | b |', '|---|---|', '| c | d |'], + \ 'cursor': [3, 7], + \ 'keys': "i\x\", + \ 'expect_lines': ['| a | b |', '|---|---|', '| c | d |', '|x | |'], + \ }) call s:run('tab.from_first_cell_moves_to_second', { \ 'lines': ['| a | b |'], \ 'cursor': [1, 3], diff --git a/scripts/test-keymaps.lua b/scripts/test-keymaps.lua index beee0c7..db7c62a 100644 --- a/scripts/test-keymaps.lua +++ b/scripts/test-keymaps.lua @@ -454,6 +454,21 @@ vim.defer_fn(function() expect_lines = { '| a |x b |' }, wait_ms = 100, }) + run('tab.cycles_to_next_row_when_not_last', { + lines = { '| a | b |', '|---|---|', '| c | d |' }, + cursor = { 1, 6 }, -- inside last cell of header row + keys = 'ix', + -- Past the final cell of row 1: skip separator, land in first cell of row 3. + expect_lines = { '| a | b |', '|---|---|', '|x c | d |' }, + wait_ms = 100, + }) + run('tab.inserts_row_only_when_on_last_row', { + lines = { '| a | b |', '|---|---|', '| c | d |' }, + cursor = { 3, 6 }, -- inside last cell of last data row + keys = 'ix', + expect_lines = { '| a | b |', '|---|---|', '| c | d |', '|x | |' }, + wait_ms = 100, + }) run('shift_tab.prev_cell_in_table', { lines = { '| a | b |' }, cursor = { 1, 6 }, -- inside cell `b`