diff --git a/nvim/ftplugin/markdown.vim b/nvim/ftplugin/markdown.vim new file mode 100644 index 0000000..435b64e --- /dev/null +++ b/nvim/ftplugin/markdown.vim @@ -0,0 +1,66 @@ +" Table cell jumps without table mode ([| ]| {| }|) +function! s:CellMaps() + nmap [ (table-mode-motion-left) + nmap ] (table-mode-motion-right) + nmap { (table-mode-motion-up) + nmap } (table-mode-motion-down) +endfunction +call s:CellMaps() +" Leaving table mode unmaps them, so restore +augroup markdown_cell_maps + autocmd! * + autocmd User TableModeDisabled if &filetype ==# 'markdown' | call s:CellMaps() | endif +augroup END + +" T{h,j,k,l} and jump one cell +nmap Th (table-mode-motion-left) +nmap Tj (table-mode-motion-down) +nmap Tk (table-mode-motion-up) +nmap Tl (table-mode-motion-right) +nmap (table-mode-motion-left) +nmap (table-mode-motion-down) +nmap (table-mode-motion-up) +nmap (table-mode-motion-right) + +" x toggles a checkbox; adds one to plain lines and list items +lua << EOF +local function toggle(lnum) + local line = vim.fn.getline(lnum) + local indent, marker, state, rest = line:match('^(%s*)([-*+] )%[([ xX])%] ?(.*)$') + if not indent then + indent, marker, state, rest = line:match('^(%s*)(%d+[.)] )%[([ xX])%] ?(.*)$') + end + if indent then + state = state == ' ' and 'x' or ' ' + else + indent, marker, rest = line:match('^(%s*)([-*+] )(.*)$') + if not indent then + indent, marker, rest = line:match('^(%s*)(%d+[.)] )(.*)$') + end + if not indent then + indent, rest = line:match('^(%s*)(.*)$') + marker = '- ' + end + state = ' ' + end + vim.fn.setline(lnum, indent .. marker .. '[' .. state .. '] ' .. rest) +end +vim.keymap.set('n', 'x', function() toggle(vim.fn.line('.')) end, + { buffer = true, desc = 'Toggle checkbox' }) +vim.keymap.set('x', 'x', function() + local a, b = vim.fn.line('v'), vim.fn.line('.') + for l = math.min(a, b), math.max(a, b) do toggle(l) end + vim.api.nvim_feedkeys(vim.keycode(''), 'n', false) +end, { buffer = true, desc = 'Toggle checkboxes' }) + +-- Shift+arrows jump cells on table rows, keep their default elsewhere +for key, dir in pairs({ Left = 'left', Down = 'down', Up = 'up', Right = 'right' }) do + vim.keymap.set('n', '(md-S-' .. key .. ')', '', { buffer = true }) + vim.keymap.set('n', '', function() + if vim.fn.getline('.'):match('^%s*|') then + return '(table-mode-motion-' .. dir .. ')' + end + return '(md-S-' .. key .. ')' + end, { buffer = true, expr = true, remap = true, desc = 'Table cell or default' }) +end +EOF diff --git a/nvim/init.vim b/nvim/init.vim index d86d424..ee0e32f 100644 --- a/nvim/init.vim +++ b/nvim/init.vim @@ -92,6 +92,12 @@ Plug 'pangloss/vim-javascript' " Tex Plug 'lervag/vimtex' +" Markdown +Plug 'nvim-tree/nvim-web-devicons' +Plug 'MeanderingProgrammer/render-markdown.nvim' +Plug 'dhruvasagar/vim-table-mode' +Plug 'stevearc/conform.nvim' + "Go Plug 'fatih/vim-go' @@ -498,5 +504,45 @@ try catch " Ignore non existing file endtry +" Markdown +if !exists('g:vscode') +" Table mode under T (t is TextWrapToggle) +let g:table_mode_corner = '|' " GFM-valid delimiter row +let g:table_mode_map_prefix = 'T' +let g:table_mode_tableize_d_map = 'Td' + +lua << EOF +-- Only tables and checkboxes; everything else stays plain markdown +local off = { enabled = false } +require('render-markdown').setup({ + -- gutter signs open the signcolumn after wrapped tables are sized -> overflow + sign = off, + heading = off, code = off, dash = off, bullet = off, quote = off, link = off, + html = off, latex = off, yaml = off, inline_highlight = off, + checkbox = { unchecked = { icon = '󰄱 ' }, checked = { icon = '󰱒 ' } }, +}) +vim.keymap.set('n', 'mr', 'RenderMarkdown toggle', { desc = 'Toggle render markdown' }) + +-- Prettier aligns tables on save; :FormatToggle disables it per buffer +require('conform').setup({ + formatters_by_ft = { markdown = { 'prettier' } }, + formatters = { + prettier = { prepend_args = { '--prose-wrap', 'preserve', '--print-width', '120' } }, + }, + -- async: Node startup can be slow, don't block :w + format_after_save = function(bufnr) + if vim.g.disable_autoformat or vim.b[bufnr].disable_autoformat then return end + return {} + end, +}) +vim.api.nvim_create_user_command('FormatToggle', function() + vim.b.disable_autoformat = not vim.b.disable_autoformat + print('Format on save ' .. (vim.b.disable_autoformat and 'off' or 'on')) +end, {}) +vim.keymap.set('n', 'F', function() require('conform').format({ async = true }) end, + { desc = 'Format document' }) +EOF +endif + let g:tex_flavor = "latex" autocmd FileType yaml setlocal ts=2 sts=2 sw=2 expandtab