Created
April 6, 2018 19:02
-
-
Save markscottwright/db42ff5848b105f33a996c6d60787acd to your computer and use it in GitHub Desktop.
How to format a org-mode style table in Vim
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# how to format a table in VIM | |
function! Strip(input_string) | |
return substitute(a:input_string, '^\s*\(.\{-}\)\s*$', '\1', '') | |
endfunction | |
function! GetFields(line_num) | |
let cur_line = Strip(getline(a:line_num)) | |
let maybe_padded = split(cur_line, "|") | |
let fields = [] | |
for f in maybe_padded | |
let fields = add(fields, Strip(f)) | |
endfor | |
return fields | |
endfunction | |
function! GetWidths(line_num) | |
let widths = [] | |
for field in GetFields(a:line_num) | |
let widths = add(widths, strlen(field)) | |
endfor | |
return widths | |
endfunction | |
function! IsHeaderSeparator(line_num) | |
return Strip(getline(a:line_num)) =~ "^|[-|+]*$" | |
endfunction | |
function! IsTableLine(line_num) | |
return Strip(getline(a:line_num)) =~ "^|" | |
endfunction | |
function! IsNumericString(s) | |
let numeric = a:s =~ "^[0-9]*$" | |
return numeric | |
endfunction | |
function! GetIsNumeric(start_line_num, end_line_num) | |
let is_numeric = [] | |
for line_num in range(a:start_line_num, a:end_line_num) | |
if IsHeaderSeparator(line_num) | |
let is_numeric = [] | |
continue | |
endif | |
let new_is_numeric = [] | |
let fields = GetFields(line_num) | |
for field_num in range(max([len(fields), len(is_numeric)])) | |
let field_numeric_so_far = get(is_numeric, field_num, 1) | |
let this_field_is_numeric = field_num >= len(fields) | |
\ || IsNumericString(fields[field_num]) | |
echom this_field_is_numeric | |
let new_is_numeric = add(new_is_numeric, | |
\ this_field_is_numeric && field_numeric_so_far) | |
echom join(new_is_numeric) | |
endfor | |
let is_numeric = new_is_numeric | |
endfor | |
return is_numeric | |
endfunction | |
function! GetMaxWidths(start_line_num, end_line_num) | |
let max_widths = [] | |
let line_num = a:start_line_num | |
while line_num <= a:end_line_num | |
if !IsHeaderSeparator(line_num) | |
let widths = GetWidths(line_num) | |
let new_max_widths = [] | |
for col_num in range(max([len(widths), len(max_widths)])) | |
let max_col_width = max([get(widths, col_num, 0), get(max_widths, col_num, 0)]) | |
let new_max_widths = add(new_max_widths, max_col_width) | |
endfor | |
let max_widths = new_max_widths | |
endif | |
let line_num = line_num + 1 | |
endwhile | |
return max_widths | |
endfunction | |
function! FindFirstLine(cur_line) | |
let start_line = a:cur_line | |
while start_line > 0 && IsTableLine(start_line) | |
let start_line = start_line - 1 | |
endwhile | |
if start_line != a:cur_line | |
let start_line = start_line + 1 | |
endif | |
return start_line | |
endfunction | |
function! FindLastLine(cur_line) | |
let end_line = a:cur_line | |
while end_line <= line('$') && IsTableLine(end_line) | |
let end_line = end_line + 1 | |
endwhile | |
if end_line != a:cur_line | |
let end_line = end_line - 1 | |
endif | |
return end_line | |
endfunction | |
function! FormatTable() | |
let cur_line = line('.') | |
let start_line = FindFirstLine(cur_line) | |
let end_line = FindLastLine(cur_line) | |
let max_widths = GetMaxWidths(start_line, end_line) | |
if len(max_widths) < 1 | |
echom "No table found" | |
return | |
endif | |
let is_numeric = GetIsNumeric(start_line, end_line) | |
echom join(is_numeric) | |
for line_num in range(start_line, end_line) | |
if IsHeaderSeparator(line_num) | |
let padded_fields = [] | |
for field_num in range(len(max_widths)) | |
let padded_fields = add(padded_fields, repeat("-", max_widths[field_num]+2)) | |
endfor | |
call setline(line_num, "|" . join(padded_fields, "+") . "|") | |
else | |
let padded_fields = [] | |
let fields = GetFields(line_num) | |
for field_num in range(len(max_widths)) | |
if is_numeric[field_num] | |
let fmt_string = " %" . max_widths[field_num] . "s " | |
else | |
let fmt_string = " %-" . max_widths[field_num]. "s " | |
endif | |
if field_num < len(fields) | |
let padded_fields = add(padded_fields, printf(fmt_string, fields[field_num])) | |
else | |
let padded_fields = add(padded_fields, printf(fmt_string, "")) | |
endif | |
endfor | |
call setline(line_num, "|" . join(padded_fields, "|") . "|") | |
endif | |
endfor | |
endfunction |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment