*table.txt* Text table manipulation for Vim and Neovim ============================================================================== CONTENTS *table-contents* 1. Introduction ......................... |table-introduction| 2. Requirements ......................... |table-requirements| 3. Commands ............................. |table-commands| 4. Mappings ............................. |table-mappings| 5. Text Objects ......................... |table-text-objects| 6. Configuration ........................ |table-configuration| 7. Fixed-Width Columns .................. |table-fixed-width| 8. Styles ............................... |table-styles| 9. User Events .......................... |table-events| 10. Functions ........................... |table-functions| 11. Limitations ......................... |table-limitations| 12. License ............................. |table-license| ============================================================================== INTRODUCTION *table-introduction* table.vim provides text table manipulation for Vim and Neovim. It parses pipe-delimited tables and provides automatic alignment, navigation, text objects, and a split/floating window cell editor. Features: • Automatic alignment on pipe insertion • Auto-split multiline cells: inserting a pipe splits the entire cell (must be enabled with |auto_split_cell|) • Multiline cell support (optional) • Fixed-width columns with automatic wrapping • Cell editing in floating/split windows • Table sorting by rows or columns • Cell, row, and column text objects • Multiple built-in table styles (Markdown, Org, reStructuredText, Unicode) • Custom style support • Chunk processing for large tables • Context-aware keybindings Supported table styles: Markdown, Org-mode, reStructuredText, Unicode box-drawing characters (single and double), and custom styles. Table alignment processes only the lines around the cursor, as determined by the `chunk_size` option. This keeps operations fast, even for large tables. The |:Table-Complete| command processes the entire table regardless of chunk size. ============================================================================== REQUIREMENTS *table-requirements* - Vim 8.1 or later - Neovim 0.11.5 or later Table Detection ~ Tables must meet the following requirements to be detected and processed: - Be at least two lines in height - Separated by blank lines above and below (comment strings are acceptable) ============================================================================== COMMANDS *table-commands* *:Table* :Table [action] [args] Main command for table actions. Without arguments, lists available actions. Tab completion is available for all actions and arguments. Actions: :Table EditCell *:Table-EditCell* Edit current cell in a split window (Vim) or floating window (Neovim). Opens an auto-resizing window for editing cell content. Especially useful for multiline cells. The window closes and saves changes when you leave the window (WinLeave). User events |User-TableCellEditPre| and |User-TableCellEditPost| are fired for customization. Equivalent to the |(table_cell_edit)| mapping. Example: > :Table EditCell < :Table Complete *:Table-Complete* Complete table structure by adding missing borders, cells, and alignment rows. Fills in any gaps in the table structure. Note: This command processes the entire table regardless of |chunk_size|, which may be slow for very large tables. Equivalent to the |(table_complete)| mapping. Example: > :Table Complete < :Table Align *:Table-Align* Align table lines near the cursor, as determined by |chunk_size|. Adjusts column widths and formats borders. This is the same action triggered by auto-alignment on pipe insertion. Equivalent to the |(table_align)| mapping. Example: > :Table Align < :Table InsertRow *:Table-InsertRow* Insert a new empty row at the cursor position. Equivalent to the |(table_insert_row)| mapping. Example: > :Table InsertRow < :Table InsertCol *:Table-InsertCol* Insert a new empty column at the cursor position. Equivalent to the |(table_insert_column)| mapping. Example: > :Table InsertCol < :Table DeleteRow *:Table-DeleteRow* Delete the row at the cursor position. Equivalent to the |(table_delete_row)| mapping. Example: > :Table DeleteRow < :Table DeleteCol *:Table-DeleteCol* Delete the column at the cursor position. Equivalent to the |(table_delete_column)| mapping. Example: > :Table DeleteCol < :Table MoveRow {direction} *:Table-MoveRow* Move the current row up or down within the table. The cursor moves with the row to maintain position. Arguments: - up: Move row up (swap with previous row) - down: Move row down (swap with next row) Equivalent to the |(table_move_row_up)| and |(table_move_row_down)| mappings. Example: > :Table MoveRow up :Table MoveRow down < :Table MoveCol {direction} *:Table-MoveCol* Move the current column left or right within the table. The cursor moves with the column to maintain position. Column alignments and fixed widths are preserved during the move. Arguments: - left: Move column left (swap with previous column) - right: Move column right (swap with next column) Equivalent to the |(table_move_column_left)| and |(table_move_column_right)| mappings. Example: > :Table MoveCol left :Table MoveCol right < :Table ToDefault *:Table-ToDefault* Convert table to the 'default' style. Uses the |i_vertical| and |i_horizontal| characters from the current buffer configuration, with full borders and separators. Equivalent to the |(table_to_default)| mapping. Example: > :Table ToDefault < :Table ToStyle {style} *:Table-ToStyle* Convert table to specified style and updates the buffer's style setting to that style. Tab completion is available for style names, including registered custom styles. Example: > :Table ToStyle markdown :Table ToStyle rest :Table ToStyle single < :Table SortRows[!] {col_id} [flags] *:Table-SortRows* Sort table rows based on the values in the specified column. The header row (first row) is not sorted. Column IDs are 1-indexed. The optional ! suffix reverses the sort order. Flags: i - Case-insensitive alphabetical sort n - Numeric sort (converts values to numbers) f - Floating-point numeric sort c - Custom comparator (uses |SortComparator| option) Multiple flags can be combined, though typically only one sort type should be used at a time. Examples: > :Table SortRows 2 " Sort by column 2 (alphabetical) :Table SortRows! 1 " Reverse sort by column 1 :Table SortRows 3 n " Sort by column 3 (numeric) :Table SortRows 1 i " Case-insensitive sort by column 1 :Table SortRows 2 f " Float sort by column 2 :Table SortRows 1 c " Custom sort using SortComparator < :Table SortCols[!] {row_id} [flags] *:Table-SortCols* Sort all columns based on the values in the specified row. All rows, including the header, are reordered. Row IDs are 1-indexed. The optional ! suffix reverses the sort order. Flags are the same as |:Table-SortRows|: i, n, f, c Examples: > :Table SortCols 1 " Sort columns by row 1 values :Table SortCols! 2 n " Reverse numeric sort by row 2 < *:TableConfig* :TableConfig [subcommand] [args] Main command for runtime configuration of the current buffer. Without arguments, displays current configuration. Subcommands: :TableConfig Option [key] [value] *:TableConfig-Option* Get or set table options. Without arguments, lists all options. With only key, shows current value. With key and value, sets option. Options: - auto_split_cell: When true, inserting a pipe (|) in a multiline cell splits the entire cell across all lines (default: v:false) - i_vertical: Insert mode vertical separator character (default: '|') - i_horizontal: Insert mode horizontal border character (default: '-') - i_alignment: Insert mode alignment marker character (default: ':') - default_alignment: Default column alignment: 'left', 'center', or 'right' (or 'l', 'c', 'r') (default: 'left') - chunk_size: Lines to process around cursor [before, after] (default: [20, 20]) - multiline: Enable multiline cells (default: 'auto') Values: v:true, v:false, or 'auto'. When 'auto', automatically detects multiline rows based on table structure. - multiline_format: Multiline cell formatting mode (default: 'block_wrap') Values: 'align', 'wrap', 'block_align', 'block_wrap', 'paragraph_wrap' - SortComparator: Custom comparison function for sorting (default: empty) Examples: > :TableConfig Option default_alignment center :TableConfig Option multiline true :TableConfig Option multiline_format paragraph_wrap :TableConfig Option SortComparator {a, b -> len(a) < len(b)} < :TableConfig Style [name] *:TableConfig-Style* Get or set the current style. Without arguments, lists available styles. Built-in styles: default, markdown, org, rest, single, double Example: > :TableConfig Style markdown < :TableConfig StyleOption [key] [value] *:TableConfig-StyleOption* Get or set style options. Without arguments, lists all style options. Style options: - omit_left_border: Hide left border (default: false) - omit_right_border: Hide right border (default: false) - omit_top_border: Hide top separator (default: false) - omit_bottom_border: Hide bottom separator (default: false) - omit_separator_rows: Hide separator rows between data rows (default: false) Example: > :TableConfig StyleOption omit_left_border true < :TableConfig RegisterStyle [name] *:TableConfig-RegisterStyle* Save the current style configuration under a custom name. This will persist only for the current session; to use it regularly, add it to your vim/nvim configuration. Example: > :TableConfig Style markdown :TableConfig StyleOption omit_left_border true :TableConfig RegisterStyle minimal_markdown < *:TableOption* :TableOption [subcommand] [args] Deprecated: Use |:TableConfig| instead. ============================================================================== MAPPINGS *table-mappings* mappings are provided for table operations, navigation, and text objects. Default mappings are provided for auto-alignment, navigation, and text objects. These may be disabled by calling the config setup function with the disable_mappings option before the VimEnter event. For table actions (EditCell, Align, Complete, ToDefault, InsertRow, InsertCol, DeleteRow, DeleteCol, MoveRow, MoveCol), mappings are provided but not mapped by default. Context-Aware Mappings ~ All default mappings are mapped in a context-aware manner: they only activate when the cursor is on a table line. When not on a table, your existing key mappings are preserved and work normally. This means keys like , , , , , and text objects (tx, tr, tc, etc.) behave normally outside of tables. Suggested Keybindings ~ Suggested keybindings for table actions: > " Table actions nnoremap ta (table_align) nnoremap (table_complete) nnoremap td (table_to_default) nnoremap te (table_cell_edit) nnoremap tir (table_insert_row) nnoremap tic (table_insert_column) nnoremap tdr (table_delete_row) nnoremap tdc (table_delete_column) nnoremap tmk (table_move_row_up) nnoremap tmj (table_move_row_down) nnoremap tmh (table_move_column_left) nnoremap tml (table_move_column_right) < Table Operations ~ *(table_align)* (table_align) Align table at the current line. Adjusts column widths and formats borders. Available in normal mode. No default mapping *(table_align_if_not_escaped)* (table_align_if_not_escaped) Mapping for auto-alignment in insert mode. Aligns table after typing | unless the pipe character is escaped. Available in insert mode only. Default: | in insert mode (auto-aligns on typing) Note: This is an implementation detail. This map should be immediately preceded by a | insertion in order to work properly. It is not recommended to use this mapping directly. *(table_complete)* (table_complete) Complete table structure by adding borders and alignment rows. No default mapping *(table_to_default)* (table_to_default) Convert current table to default style. No default mapping *(table_cell_edit)* (table_cell_edit) Edit current cell in split window (Vim) or floating window (Neovim). Useful for multiline editing. Changes save on WinLeave. No default mapping *(table_insert_row)* (table_insert_row) Insert a new empty row at the cursor position. The cursor moves to the first cell of the new row. Available in normal mode. No default mapping *(table_insert_column)* (table_insert_column) Insert a new empty column at the cursor position. The cursor remains on the same cell in the new column. Available in normal mode. No default mapping *(table_delete_row)* (table_delete_row) Delete the row at the cursor position. The cursor moves to the row below (or the new last row if deleting the last row). Available in normal mode. No default mapping *(table_delete_column)* (table_delete_column) Delete the column at the cursor position. The cursor moves to the previous column (or stays on the first column if deleting the first column). Available in normal mode. No default mapping *(table_move_row_up)* (table_move_row_up) Move the current row up by swapping it with the row above. Available in normal mode. No default mapping *(table_move_row_down)* (table_move_row_down) Move the current row down by swapping it with the row below. Available in normal mode. No default mapping *(table_move_column_left)* (table_move_column_left) Move the current column left by swapping it with the column to the left. Available in normal mode. No default mapping *(table_move_column_right)* (table_move_column_right) Move the current column right by swapping it with the column to the right. Available in normal mode. No default mapping Navigation ~ *(table_next)* (table_next) Move to next cell, wrapping to next row at row end. Available in normal, visual, and insert modes. Default: (normal, visual) *(table_prev)* (table_prev) Move to previous cell, wrapping to previous row at row start. Available in normal, visual, and insert modes. Default: (normal, visual) *(table_move_left)* (table_move_left) Move to cell on the left. Available in normal, visual, and insert modes. Default: (normal, visual) *(table_move_right)* (table_move_right) Move to cell on the right. Available in normal, visual, and insert modes. Default: (normal, visual) *(table_move_up)* (table_move_up) Move to cell above. Available in normal, visual, and insert modes. Default: (normal, visual) *(table_move_down)* (table_move_down) Move to cell below. Available in normal, visual, and insert modes. Default: (normal, visual) Text Objects ~ *(table_cell_textobj)* tx Cell text object (half borders) *(table_inner_cell_textobj)* ix Inner cell (content only) *(table_around_cell_textobj)* ax Around cell (includes borders) *(table_row_textobj)* tr Row text object (half borders) *(table_inner_row_textobj)* ir Inner row (content only) *(table_around_row_textobj)* ar Around row (includes separators) *(table_column_textobj)* tc Column text object (half borders) *(table_inner_column_textobj)* ic Inner column (content only) *(table_around_column_textobj)* ac Around column (includes separators) Text objects work in visual and operator-pending modes. Examples: > dix Delete cell content yir Yank row dac Delete column 2dtc Delete two columns < ============================================================================== TEXT OBJECTS *table-text-objects* Text objects for cells, rows, and columns. Defined for visual and operator pending modes. "around" and "inner" variants select full borders or no borders, while default selects half borders. Cell Text Objects ~ tx Cell, including bottom-right borders. ax Around cell, including adjacent borders. ix Inner cell content, excluding borders. Row Text Objects ~ tr Row, including bottom separator. ar Around row, including adjacent separators. ir Inner row content, excluding separator lines. Column Text Objects ~ tc Column, including right separator. ac Around column, including adjacent separators. ic Inner column content, excluding separators. Counts ~ Text objects accept counts to select multiple adjacent items: > d2tx Delete current cell and next cell v3ir Select three rows y2ic Yank two columns < ============================================================================== CONFIGURATION *table-configuration* Configuration is buffer-local. Each buffer has independent settings that can be set via setup functions or modified at runtime with |:TableConfig|. Configuration Levels ~ Three levels of configuration exist, with each level overriding the previous: 1. Plugin defaults - Built-in defaults, never modified 2. User defaults - Set via |table#Setup()| in vimrc/init.lua, applied to all new buffers 3. Buffer-local - Set via |:TableConfig| or |table#SetBufferConfig()|. Overrides user defaults for specific buffers Configuration Functions ~ *table#Setup()* table#Setup({config}) Sets user defaults applied to all new buffers. The |disable_mappings| and |disable_ftplugins| options are only applicable before the VimEnter event. Other options can be changed any time and will apply to newly created buffers. Note: Buffer-local settings (ftplugin or |:TableConfig|) override these. Parameters: All parameters are optional. Only specify the settings you want to change from defaults. > { 'disable_mappings': v:false, 'disable_ftplugins': v:false, 'style': 'default', 'options': { 'auto_split_cell': false, 'multiline': 'auto', 'multiline_format': 'block_wrap', 'default_alignment': 'left', 'chunk_size': [20, 20], 'i_vertical': '|', 'i_horizontal': '-', 'i_alignment': ':' }, 'style_options': { 'omit_left_border': v:false, 'omit_right_border': v:false, 'omit_top_border': v:false, 'omit_bottom_border': v:false, 'omit_separator_rows': v:false } } < Example (VimScript): > " In vimrc call table#Setup({ \ 'style': 'markdown', \ 'options': {'default_alignment': 'center', 'multiline': v:true, 'multiline_format': 'paragraph_wrap'} \ }) < Example (Lua): > -- In init.lua require('table_vim').setup({ style = 'default', options = { multiline = true, multiline_format = 'paragraph_wrap', chunk_size = {20, 20} } }) < *table#SetBufferConfig()* table#SetBufferConfig({config}) Configure current buffer only. Use in ftplugin files to set per-filetype defaults, or call at runtime to override settings. Accepts same parameters as |table#Setup()|. Example: > " In after/ftplugin/markdown.vim call table#SetBufferConfig({'style': 'markdown'}) < Lua example: > -- In after/ftplugin/markdown.lua vim.fn['table#SetBufferConfig']({style = 'markdown'}) < *table#RestoreDefault()* table#RestoreDefault() Reset the current buffer to plugin defaults, ignoring both user defaults and buffer-local settings. Useful for debugging or reverting custom configurations. Table Options ~ *table-option-list* *auto_split_cell* auto_split_cell Type: Boolean Default: v:false (false) When enabled, inserting a pipe character (|) in a multiline cell automatically splits the entire cell across all lines at the same column position, not just the current line. This provides consistent cell structure when working with multiline tables. When disabled, inserting a pipe only affects the current line. This option only applies when |multiline| is enabled and you are working with multiline cells. > :TableConfig Option auto_split_cell true < *multiline* multiline Type: String Default: 'auto' Allow cells to contain newline characters. When enabled, cells can span multiple lines visually. Use the |:Table| EditCell command or press enter within cell content to create multiline cells. When disabled, newlines in cells will cause parsing issues. > :TableConfig Option multiline true < *multiline_format* multiline_format Type: String Default: 'block_wrap' Values: 'align', 'wrap', 'block_align', 'block_wrap', 'paragraph_wrap' Controls how multiline cell content is formatted when |multiline| is enabled. This option replaces the deprecated `preserve_indentation` and `wrap_lines` options. 'align' - Trim leading/trailing whitespace, no wrapping 'wrap' - Wrap lines independently of each other in fixed-width columns 'block_align' - Align text as a block based on column alignment 'block_wrap' - Align text as a block with independent line wrapping in fixed-width columns 'paragraph_wrap' - Keep paragraph structure in fixed-width columns, paragraphs are separated by blank lines *default_alignment* default_alignment Type: String Default: 'left' Values: 'left' (or 'l'), 'center' (or 'c'), 'right' (or 'r') Default alignment for columns without explicit alignment markers. This affects how cell content is padded when the table is aligned. > :TableConfig Option default_alignment center < *chunk_size* chunk_size Type: List [before, after] Default: [20, 20] Number of lines to process around the cursor for alignment operations. The first element specifies lines before the cursor, the second specifies lines after. Use [] to process the entire table, regardless of size. Smaller chunks improve performance for large tables but may not align the entire visible table. Increase if you have large tables and alignment doesn't cover enough rows. > :TableConfig Option chunk_size [20, 20] :TableConfig Option chunk_size [] < *i_vertical* i_vertical Type: String (single character) Default: '|' Vertical border character used when creating or converting tables to 'default' style. Must be different from |i_horizontal|. Note: Changing this does not affect existing tables until you convert them with |:Table| ToDefault. > :TableConfig Option i_vertical │ < *i_horizontal* i_horizontal Type: String (single character) Default: '-' Horizontal border character used when creating or converting tables to 'default' style. Must be different from |i_vertical|. Note: Changing this does not affect existing tables until you convert them with |:Table| ToDefault. > :TableConfig Option i_horizontal ─ < *i_alignment* i_alignment Type: String (single character) Default: ':' Alignment marker character. In alignment rows, this character indicates column alignment: at start for left, both sides for center, at end for right. Example alignment row: |:---:|---:|---| indicates center, right, left. > :TableConfig Option i_alignment : < *SortComparator* SortComparator Type: Funcref or Lambda Default: '' (empty) Custom comparison function for sorting tables. Used when the 'c' flag is passed to |:Table-SortRows| or |:Table-SortCols|. The function should be a 'less than' operator on two string arguments. It should return true if the first argument should come before the second in the sort order, and false otherwise. Example (VimScript): > " Sort by string length :TableConfig Option SortComparator {a, b -> len(a) < len(b)} :Table SortRows 1 c < Example (Lua): > -- In ftplugin or setup vim.fn['table#SetBufferConfig']({ options = { SortComparator = function(a, b) return #a < #b end } }) < Example (setup configuration): > " In vimrc call table#Setup({ \ 'options': { \ 'SortComparator': {a, b -> str2nr(a) < str2nr(b)} \ } \ }) < Style Options ~ *table-style-option-list* Style options control which borders are drawn. These are part of the style definition and can be modified per-buffer to create custom table appearances. *omit_left_border* omit_left_border Type: Boolean Default: v:false (false) Hide the leftmost vertical border. Useful for creating tables that sit flush with the left margin. > :TableConfig StyleOption omit_left_border true < *omit_right_border* omit_right_border Type: Boolean Default: v:false (false) Hide the rightmost vertical border. > :TableConfig StyleOption omit_right_border true < *omit_top_border* omit_top_border Type: Boolean Default: v:false (varies by style) Hide the top horizontal border (separator above the first row). The Markdown and Org styles have this set to true by default. > :TableConfig StyleOption omit_top_border true < *omit_bottom_border* omit_bottom_border Type: Boolean Default: v:false (varies by style) Hide the bottom horizontal border (separator below the last row). The Markdown and Org styles have this set to true by default. > :TableConfig StyleOption omit_bottom_border true < *omit_separator_rows* omit_separator_rows Type: Boolean Default: v:false (varies by style) Hide horizontal separators between data rows (but not the alignment row). The Markdown and Org styles have this set to true by default. > :TableConfig StyleOption omit_separator_rows true < Disable Options ~ *disable_mappings* disable_mappings Type: Boolean Default: v:false (false) Disable all default keybindings. Must be set before VimEnter event via |table#Setup()|. When disabled, you may create your own mappings using the || mappings. See |table-mappings| for list of default mappings. > call table#Setup({'disable_mappings': v:true}) < *disable_ftplugins* disable_ftplugins Type: Boolean Default: v:false (false) Disable built-in ftplugin configuration files for markdown, org, and rst file types. Use when you want uniform configuration across all file types. Can be set via |table#Setup()|. > call table#Setup({'disable_ftplugins': v:true}) < Per-Filetype Configuration ~ The plugin provides default ftplugin configuration for common formats: - ftplugin/markdown.vim - Markdown tables (no top/bottom borders) - ftplugin/org.vim - Org-mode tables (+ at intersections) - ftplugin/rst.vim - reStructuredText tables (= for header separator) These ftplugins automatically apply appropriate styles when editing files of these types. Use |disable_ftplugins| option to disable. To override or add custom ftplugin configurations, create your own ftplugin files in the after directory: > " ~/.vim/after/ftplugin/markdown.vim call table#SetBufferConfig({ \ 'style': 'markdown', \ 'options': {'default_alignment': 'center', 'multiline': v:true} \ }) < Neovim Lua Configuration ~ Global setup in init.lua: > require('table_vim').setup({ style = 'default', options = { multiline = true, default_alignment = 'center', chunk_size = {20, 20} } }) < Per-filetype configuration in after/ftplugin/markdown.lua: > vim.fn['table#SetBufferConfig']({ style = 'markdown', options = { multiline = true } }) < Runtime Configuration ~ Use |:TableConfig| to view or modify current buffer settings at runtime: > :TableConfig " Show current config :TableConfig Option default_alignment center " Set option :TableConfig Option multiline true " Enable multiline :TableConfig Style markdown " Change style :TableConfig StyleOption omit_left_border true " Modify style options < Changes via |:TableConfig| affect only the current buffer and do not persist across Vim sessions. Add to your vimrc/init.lua to make permanent. ============================================================================== FIXED-WIDTH COLUMNS *table-fixed-width* Fixed-width columns allow you to specify column widths using special alignment tags. Content exceeding the specified width automatically wraps to multiple lines within the cell when |multiline| is enabled with |multiline_format| set to 'wrap', 'paragraph_wrap' or 'block_wrap'. Tag Syntax ~ Fixed-width tags use the format: `<[alignment][width]>` Where: - alignment is one of: l (left), c (center), r (right) - width is a positive integer Examples: `` `` `` Usage ~ Place fixed-width tags in a special alignment row, typically the first or second row of your table. Each tag defines the width and alignment for its corresponding column: > | Description | Column 1 width | |--------------------|---------------------| | | | | Next col will wrap | This cell will wrap | < When the |multiline| and a suitable |multiline_format| is set, content exceeding the specified width will automatically wrap to multiple lines within the cell: > | Description | Column 1 | | | width | |--------------------|-----------| | | | | Next col will wrap | This cell | | | will wrap | < Configuration ~ Enable wrapping with fixed-width columns: > call table#Setup({ \ 'options': {'multiline': v:true, 'multiline_format': 'block_wrap'} \ }) < Or at runtime: > :TableConfig Option multiline true :TableConfig Option multiline_format block_wrap < ============================================================================== STYLES *table-styles* Styles control table border characters and visibility. Several built-in styles are provided. Built-in Styles ~ default - ASCII table with all borders: > |---------|---------| | Header1 | Header2 | |---------|---------| | Cell1 | Cell2 | |---------|---------| < markdown - Markdown tables (no top/bottom borders): > | Header1 | Header2 | |---------|---------| | Cell1 | Cell2 | < org - Org-mode tables (+ at intersections): > | Header1 | Header2 | |---------+---------| | Cell1 | Cell2 | < rest - reStructuredText tables (= for header separator): > +---------+---------+ | Header1 | Header2 | +=========+=========+ | Cell1 | Cell2 | +---------+---------+ < single - Unicode single-line box-drawing: > ┌─────────┬─────────┐ │ Header1 │ Header2 │ ├─────────┼─────────┤ │ Cell1 │ Cell2 │ └─────────┴─────────┘ < double - Unicode double-line box-drawing: > ╔═════════╦═════════╗ ║ Header1 ║ Header2 ║ ╠═════════╬═════════╣ ║ Cell1 ║ Cell2 ║ ╚═════════╩═════════╝ < Custom Styles ~ Create custom styles by modifying style options and registering: > :TableConfig Style markdown :TableConfig StyleOption omit_left_border true :TableConfig StyleOption omit_right_border true :TableConfig RegisterStyle minimal < Style options: - omit_left_border: Hide left border - omit_right_border: Hide right border - omit_top_border: Hide top separator - omit_bottom_border: Hide bottom separator - omit_separator_rows: Hide separators between data rows ============================================================================== USER EVENTS *table-events* User autocommands fired during cell editing. Event Data ~ Both events provide data via `args.data` in Lua autocommands or via the |g:table_cell_edit_data| global variable in Vimscript autocommands: - bufnr: Buffer number of cell edit window - winid: Window ID of cell edit window - table: Table object (internal details, advanced use cases) - cell_id: Cell identifier {row_id, col_id} Note: cell_id coordinates are 0-indexed and relative to the chunked table processed near the cursor (based on |chunk_size|), not absolute coordinates of the full table. In particular, the row_id indexes the row within the chunk. *User-TableCellEditPre* TableCellEditPre Fired after cell edit window is created and content loaded, before entering the window. Use cases: - Set buffer-local options or mappings - Initialize UI or tracking Example (Lua): > vim.api.nvim_create_autocmd('User', { pattern = 'TableCellEditPre', callback = function(args) -- Set filetype for syntax highlighting vim.bo[args.data.bufnr].filetype = 'markdown' -- Add buffer-local mapping 'q' to close vim.keymap.set('n', 'q', 'close', { buffer = args.data.bufnr }) end }) < Example (Vimscript): > autocmd User TableCellEditPre \ call setbufvar(g:table_cell_edit_data.bufnr, '&filetype', 'markdown') < *User-TableCellEditPost* TableCellEditPost Fired after window is closed but before saving buffer content to the table. Buffer can still be modified. Changes made here will be saved. Use cases: - Apply formatters to cell content - Validate cell content and show warnings/errors - Transform or normalize data *g:table_cell_edit_data* g:table_cell_edit_data Dictionary containing event data for cell editor events. Available in Vimscript autocommands for |User-TableCellEditPre| and |User-TableCellEditPost| events. Contains the same fields as Lua event data (see Event Data above). Note: cell_id[0] (row_id) is relative to the table chunk (see |chunk_size|), not absolute buffer line numbers. Example: > autocmd User TableCellEditPost \ if g:table_cell_edit_data.cell_id[1] == 0 | \ echom "Editing first column" | \ endif < ============================================================================== FUNCTIONS *table-functions* Public API functions for programmatic table manipulation. These functions can be called from scripts, mappings, or other plugins. *table#IsTable()* table#IsTable({linenr}) Return v:true if the line at {linenr} is part of a table, v:false otherwise. Useful for conditional logic in mappings or autocommands. Parameters: ~ {linenr} Line number to check (1-indexed) Returns: ~ v:true if line is part of a table, v:false otherwise Example: > if table#IsTable(line('.')) echo 'Cursor is on a table' endif < *table#Align()* table#Align({linenr}) Align the table at the given line number. Adjusts column widths and formats borders according to current buffer configuration. Processes lines according to |chunk_size| setting. Parameters: ~ {linenr} Line number within the table to align Example: > call table#Align(line('.')) < *table#AlignIfNotEscaped()* table#AlignIfNotEscaped() Align the table under the cursor only if the character before the cursor is not a backslash escape (\). Used internally for insert mode auto-align on typing |. This allows typing literal pipes with \|. Auto-split feature (disabled by default): When enabled, inserting a pipe character into a multiline cell automatically splits the entire cell at the cursor position across all lines in the cell. Enable with the |auto_split_cell| option. Should be called in insert mode via a mapping. Example: > inoremap table#IsTable(line('.')) ? \ "call table#AlignIfNotEscaped()" : "" < *table#Complete()* table#Complete({linenr}) Complete the table structure at the given line number. Adds missing borders, cells, and separators to create a well-formed table. Processes the entire table regardless of |chunk_size| setting. Parameters: ~ {linenr} Line number within the table to complete Example: > call table#Complete(line('.')) < *table#ToDefault()* table#ToDefault({linenr}) Convert the table at the given line to the 'default' style. Uses |i_vertical| and |i_horizontal| characters from current buffer config with full borders and separators. The buffer's style setting remains unchanged. Parameters: ~ {linenr} Line number within the table to convert Example: > call table#ToDefault(line('.')) < *table#ToStyle()* table#ToStyle({linenr}, {style_name}) Convert the table at the given line to the specified style and update the buffer's style setting to that style. Parameters: ~ {linenr} Line number within the table to convert {style_name} Name of the style to apply (e.g., 'markdown', 'org') Example: > call table#ToStyle(line('.'), 'markdown') < *table#CycleCursor()* table#CycleCursor({dir}, {count1}) Move the cursor to the next/previous cell, wrapping to the next/previous row at row boundaries. Useful for / navigation. Parameters: ~ {dir} Direction: 'forward' or 'backward' {count1} Number of cells to move (supports count prefix) Example: > nnoremap :call table#CycleCursor('forward', v:count1) < *table#MoveCursorCell()* table#MoveCursorCell({dir}, {count1}) Move the cursor in a specific direction within the table. Does not wrap at boundaries. Useful for directional navigation. Parameters: ~ {dir} Direction: 'left', 'right', 'up', or 'down' {count1} Number of cells to move (supports count prefix) Example: > nnoremap :call table#MoveCursorCell('right', v:count1) < *table#CellEditor()* table#CellEditor() Open a cell editor window for the cell at the current cursor position. Opens a split window in Vim or a floating window in Neovim for editing cell content. Especially useful for multiline cells. The window automatically closes and saves changes on WinLeave. User events |User-TableCellEditPre| and |User-TableCellEditPost| are fired for customization. Event data is accessible via |g:table_cell_edit_data| in Vimscript or via args.data in Lua. Example: > nnoremap te :call table#CellEditor() < *table#MoveRow()* table#MoveRow({direction}) Move the current row up or down within the table. The row is swapped with the adjacent row in the specified direction. Parameters: ~ {direction} Either 'up' or 'down' Example: > nnoremap tmk :call table#MoveRow('up') nnoremap tmj :call table#MoveRow('down') < *table#MoveColumn()* table#MoveColumn({direction}) Move the current column left or right within the table. The column is swapped with the adjacent column in the specified direction. Parameters: ~ {direction} Either 'left' or 'right' Example: > nnoremap tml :call table#MoveColumn('right') nnoremap tmh :call table#MoveColumn('left') < *table#Sort()* table#Sort({linenr}, {dim_kind}, {id}, {flags}) Sort table rows or columns programmatically. Low-level function for custom scripting. Parameters: ~ {linenr} Line number within the table {dim_kind} Either 'rows' or 'cols' {id} 0-indexed column ID (for rows) or row ID (for cols) {flags} List of flag characters: 'i', 'n', 'f', 'c', '!' Example: > " Sort rows by column 2 (0-indexed = 1), numeric call table#Sort(line('.'), 'rows', 1, ['n']) < ============================================================================== LIMITATIONS *table-limitations* Known limitations of table.vim: • No merged/spanning cells across columns or rows. Multiline rows are supported via the |multiline| option. • The |i_vertical| and |i_horizontal| characters must be different. Using the same character for both will cause parsing issues. • Tables must be separated by blank lines (comment chars from &commentstring are ok) above and below. Tables adjacent to other content may not be detected correctly. • Tables must span at least two lines to be recognized as tables. ============================================================================== LICENSE *table-license* This plugin is distributed under the Mozilla Public License Version 2.0. See the LICENSE file for details. ============================================================================== vim:tw=78:ts=8:ft=help:norl: