简体   繁体   中英

Automatically align markdown tables using lua in Neovim

I am using vim-easy-align plugin and full lua configuration for my Neovim

This is how we can auto align the markdown tables for every '|'we type using vim-tabular in VimScript

inoremap <silent> <Bar>   <Bar><Esc>:call <SID>align()<CR>a

function! s:align()
  let p = '^\s*|\s.*\s|\s*$'
  if exists(':Tabularize') && getline('.') =~# '^\s*|' && (getline(line('.')-1) =~# p || getline(line('.')+1) =~# p)
    let column = strlen(substitute(getline('.')[0:col('.')],'[^|]','','g'))
    let position = strlen(matchstr(getline('.')[0:col('.')],'.*|\s*\zs.*'))
    Tabularize/|/l1
    normal! 0
    call search(repeat('[^|]*|',column).'\s\{-\}'.repeat('.',position),'ce',line('.'))
  endif
endfunction

Source: Tim Pope's Gist

I want something like the above but for vim-easy-align and in Lua

This is the best I could do

local set_cursor_to_nth_bar = function (row, count)
    local line = vim.api.nvim_buf_get_lines(0, row, row + 1, false)[1]
    local cur_bar_count = 0
    local cur_col = 0 -- will be the col of the cursor + 1 by the end of the loop
    while cur_bar_count < count do
        cur_col = line:find('|', cur_col + 1)
        cur_bar_count = cur_bar_count + 1
    end
    vim.api.nvim_win_set_cursor(0, {row + 1, cur_col})
    vim.cmd [[startinsert!]]
end

local on_bar_inserted = function ()
    local pos = vim.api.nvim_win_get_cursor(0)
    local row = pos[1] - 1
    local col = pos[2]
    local before_line = vim.api.nvim_get_current_line()
    -- record the number of bars in the line prior to the cursor
    local _, pre_bar_count = before_line:sub(0, col):gsub("|", "|")

    -- insert the |
    vim.api.nvim_buf_set_text(0, row, col, row, col, { '|' })

    -- Easy Align markdown table
    vim.cmd [[ stopinsert ]]
    vim.cmd [[ normal! vip ]] -- visually select the paragraph
    vim.api.nvim_feedkeys('ga*|', 'v', false) -- EasyAlign all |s in the paragraph -- ga = keymap for <Plug>(EasyAlign)

    -- place the cursor at the end of the entered | (pre_bar_count + 1)
    -- we need to schedule this since the above nvim_feedkeys need to trigger EasyAlign and it needs to
    -- update text before we try to set the cursor in the right place
    vim.schedule(
        function ()
            set_cursor_to_nth_bar(row, pre_bar_count + 1)
        end
    )
end

-- set ga as keymap for EasyAlign in normal and visual models
vim.keymap.set('n', 'ga', '<Plug>(EasyAlign)', { desc = "Align", noremap = false })
vim.keymap.set('x', 'ga', '<Plug>(EasyAlign)', { desc = "Align", noremap = false })

local align_group = vim.api.nvim_create_augroup('AlignMDTable', { clear = true })
vim.api.nvim_create_autocmd('FileType', {
    callback = function()
        vim.keymap.set('i', '<Bar>', on_bar_inserted, { desc = "Align Tables", silent = true })
    end,
    group = align_group,
    pattern = "markdown",
})

I think this could be improved. Especially this part, where we are having to use nvim_feedkeys and ga the keymap for <Plug>(EasyAlign)

    -- Easy Align markdown table
    vim.cmd [[ stopinsert ]]
    vim.cmd [[ normal! vip ]] -- visually select the paragraph
    vim.api.nvim_feedkeys('ga*|', 'v', false) -- EasyAlign all |s in the paragraph -- ga = keymap for <Plug>(EasyAlign)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM