aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ftplugin/rst_tables.vim52
-rw-r--r--src/base.vim5
-rw-r--r--src/rst_tables.py47
-rw-r--r--tests/fixtures/reflow.txt14
-rw-r--r--tests/test_rst_tables.py59
5 files changed, 168 insertions, 9 deletions
diff --git a/ftplugin/rst_tables.vim b/ftplugin/rst_tables.vim
index 1077557..ae0979a 100644
--- a/ftplugin/rst_tables.vim
+++ b/ftplugin/rst_tables.vim
@@ -19,6 +19,7 @@ let loaded_rst_tables_ftplugin = 1
python << endpython
import vim
import re
+import textwrap
from vim_bridge import bridged
@@ -191,6 +192,24 @@ def get_column_widths(table):
return widths
+def get_column_widths_from_border_spec(slice):
+ border = None
+ for row in slice:
+ if line_is_separator(row):
+ border = row.strip()
+ break
+
+ if border is None:
+ raise RuntimeError('Cannot reflow this table. Top table border not found.')
+
+ left = right = None
+ if border[0] == '+':
+ left = 1
+ if border[-1] == '+':
+ right = -1
+ return map(lambda drawing: max(0, len(drawing) - 2), border[left:right].split('+'))
+
+
def pad_fields(row, widths):
"""Pads fields of the given row, so each field lines up nicely with the
others.
@@ -207,11 +226,22 @@ def pad_fields(row, widths):
return new_row
-def draw_table(table):
+def reflow_row_contents(row, widths):
+ new_row = []
+ for i, field in enumerate(row):
+ wrapped_lines = textwrap.wrap(field.replace('\n', ' '), widths[i])
+ new_row.append("\n".join(wrapped_lines))
+ return new_row
+
+
+def draw_table(table, manual_widths=None):
if table == []:
return []
- col_widths = get_column_widths(table)
+ if manual_widths is None:
+ col_widths = get_column_widths(table)
+ else:
+ col_widths = manual_widths
# Reserve room for the spaces
sep_col_widths = map(lambda x: x + 2, col_widths)
@@ -222,6 +252,9 @@ def draw_table(table):
first = True
for row in table:
+ if manual_widths:
+ row = reflow_row_contents(row, manual_widths)
+
row_lines = split_row_into_lines(row)
# draw the lines (num_lines) for this row
@@ -247,12 +280,25 @@ def reformat_table():
slice = draw_table(table)
vim.current.buffer[upper - 1:lower] = slice
+
+@bridged
+def reflow_table():
+ upper, lower = get_table_bounds()
+ slice = vim.current.buffer[upper - 1:lower]
+ widths = get_column_widths_from_border_spec(slice)
+ table = parse_table(slice)
+ slice = draw_table(table, widths)
+ vim.current.buffer[upper - 1:lower] = slice
+
endpython
" Add mappings, unless the user didn't want this.
" The default mapping is registered, unless the user remapped it already.
if !exists("no_plugin_maps") && !exists("no_rst_table_maps")
if !hasmapto('ReformatTable(')
- noremap <silent> <leader><leader>f :call ReformatTable()<CR>
+ noremap <silent> <leader><leader>c :call ReformatTable()<CR>
+ endif
+ if !hasmapto('ReflowTable(')
+ noremap <silent> <leader><leader>f :call ReflowTable()<CR>
endif
endif
diff --git a/src/base.vim b/src/base.vim
index 46bdb05..037a9dd 100644
--- a/src/base.vim
+++ b/src/base.vim
@@ -24,6 +24,9 @@ endpython
" The default mapping is registered, unless the user remapped it already.
if !exists("no_plugin_maps") && !exists("no_rst_table_maps")
if !hasmapto('ReformatTable(')
- noremap <silent> <leader><leader>f :call ReformatTable()<CR>
+ noremap <silent> <leader><leader>c :call ReformatTable()<CR>
+ endif
+ if !hasmapto('ReflowTable(')
+ noremap <silent> <leader><leader>f :call ReflowTable()<CR>
endif
endif
diff --git a/src/rst_tables.py b/src/rst_tables.py
index f689b35..1d4b04b 100644
--- a/src/rst_tables.py
+++ b/src/rst_tables.py
@@ -1,5 +1,6 @@
import vim
import re
+import textwrap
from vim_bridge import bridged
@@ -172,6 +173,24 @@ def get_column_widths(table):
return widths
+def get_column_widths_from_border_spec(slice):
+ border = None
+ for row in slice:
+ if line_is_separator(row):
+ border = row.strip()
+ break
+
+ if border is None:
+ raise RuntimeError('Cannot reflow this table. Top table border not found.')
+
+ left = right = None
+ if border[0] == '+':
+ left = 1
+ if border[-1] == '+':
+ right = -1
+ return map(lambda drawing: max(0, len(drawing) - 2), border[left:right].split('+'))
+
+
def pad_fields(row, widths):
"""Pads fields of the given row, so each field lines up nicely with the
others.
@@ -188,11 +207,22 @@ def pad_fields(row, widths):
return new_row
-def draw_table(table):
+def reflow_row_contents(row, widths):
+ new_row = []
+ for i, field in enumerate(row):
+ wrapped_lines = textwrap.wrap(field.replace('\n', ' '), widths[i])
+ new_row.append("\n".join(wrapped_lines))
+ return new_row
+
+
+def draw_table(table, manual_widths=None):
if table == []:
return []
- col_widths = get_column_widths(table)
+ if manual_widths is None:
+ col_widths = get_column_widths(table)
+ else:
+ col_widths = manual_widths
# Reserve room for the spaces
sep_col_widths = map(lambda x: x + 2, col_widths)
@@ -203,6 +233,9 @@ def draw_table(table):
first = True
for row in table:
+ if manual_widths:
+ row = reflow_row_contents(row, manual_widths)
+
row_lines = split_row_into_lines(row)
# draw the lines (num_lines) for this row
@@ -227,3 +260,13 @@ def reformat_table():
table = parse_table(slice)
slice = draw_table(table)
vim.current.buffer[upper - 1:lower] = slice
+
+
+@bridged
+def reflow_table():
+ upper, lower = get_table_bounds()
+ slice = vim.current.buffer[upper - 1:lower]
+ widths = get_column_widths_from_border_spec(slice)
+ table = parse_table(slice)
+ slice = draw_table(table, widths)
+ vim.current.buffer[upper - 1:lower] = slice
diff --git a/tests/fixtures/reflow.txt b/tests/fixtures/reflow.txt
new file mode 100644
index 0000000..f1dbc1e
--- /dev/null
+++ b/tests/fixtures/reflow.txt
@@ -0,0 +1,14 @@
+This is paragraph text *before* the table.
+
++==========+==========================+
+| Column 1 | Column 2 |
++==========+================================================================================================+
+| Foo | Put two (or more) spaces as a field separator. |
++----------+------------------------------------------------------------------------------------------------+
+| Bar | Even very very long lines like these are fine, as long as you do not put in line endings here. |
++----------+------------------------------------------------------------------------------------------------+
+| Qux | This is the last line. |
++----------+------------------------------------------------------------------------------------------------+
+
+This is paragraph text *after* the table, with
+a line ending.
diff --git a/tests/test_rst_tables.py b/tests/test_rst_tables.py
index 7d72e25..a86e401 100644
--- a/tests/test_rst_tables.py
+++ b/tests/test_rst_tables.py
@@ -21,9 +21,10 @@ import unittest
# Load test subjects
from rst_tables import get_table_bounds, reformat_table, parse_table, \
- draw_table, table_line, get_column_widths, \
- pad_fields, unify_table, join_rows, \
- partition_raw_lines, split_row_into_lines
+ reflow_table, draw_table, table_line, get_column_widths, \
+ get_column_widths_from_border_spec, pad_fields, unify_table, \
+ join_rows, partition_raw_lines, split_row_into_lines, \
+ reflow_row_contents
class TestRSTTableFormatter(unittest.TestCase):
@@ -210,6 +211,13 @@ class TestRSTTableFormatter(unittest.TestCase):
get_column_widths([['Foo\nBar\nQux',
'This\nis\nreally\nneat!']]))
+ def testGetColumnWidthsFromBorderSpec(self):
+ input = ['+====+=====+==+=======+',
+ '| xx | xxx | | xxxxx |',
+ '+====+=====+==+=======+']
+ self.assertEquals([2, 3, 0, 5],
+ get_column_widths_from_border_spec(input))
+
def testPadFields(self):
table = [['Name', 'Type', 'Description'],
['Lollypop', 'Candy', 'Yummy'],
@@ -222,6 +230,23 @@ class TestRSTTableFormatter(unittest.TestCase):
for input, expect in zip(table, expected_padding):
self.assertEquals(expect, pad_fields(input, widths))
+ def testReflowRowContentsWithEnoughWidth(self):
+ input = ['Foo\nbar', 'This line\nis spread\nout over\nfour lines.']
+ expect = ['Foo bar', 'This line is spread out over four lines.']
+ self.assertEquals(expect, reflow_row_contents(input, [99,99]))
+
+ def testReflowRowContentsWithWrapping(self):
+ input = ['Foo\nbar', 'This line\nis spread\nout over\nfour lines.']
+ expect = ['Foo bar', 'This line is spread\nout over four lines.']
+ self.assertEquals(expect, reflow_row_contents(input, [10,20]))
+
+ input = ['Foo\nbar', 'This line\nis spread\nout over\nfour lines.']
+ expect = ['Foo bar', 'This\nline\nis\nspread\nout\nover\nfour\nlines.']
+ self.assertEquals(expect, reflow_row_contents(input, [10,6]))
+
+ def testReflowRowContentsWithoutRoom(self):
+ #self.assertEquals(expect, reflow_row_contents(input))
+ pass
def testDrawTable(self):
self.assertEquals([], draw_table([]))
@@ -236,6 +261,7 @@ class TestRSTTableFormatter(unittest.TestCase):
'+-----+----+'],
draw_table([['Foo', 'Mu'], ['x', 'y']]))
+
def testCreateTable(self):
self.load_fixture_in_vim('default')
expect = """\
@@ -278,3 +304,30 @@ a line ending.
+----------------+---------------------------------------------------------------+
""".rstrip().split('\n')
self.assertEquals(expect, draw_table(parse_table(raw_lines)))
+
+ def testReflowTable(self):
+ self.load_fixture_in_vim('reflow')
+ expect = """\
+This is paragraph text *before* the table.
+
++==========+==========================+
+| Column 1 | Column 2 |
++==========+==========================+
+| Foo | Put two (or more) spaces |
+| | as a field separator. |
++----------+--------------------------+
+| Bar | Even very very long |
+| | lines like these are |
+| | fine, as long as you do |
+| | not put in line endings |
+| | here. |
++----------+--------------------------+
+| Qux | This is the last line. |
++----------+--------------------------+
+
+This is paragraph text *after* the table, with
+a line ending.
+""".split('\n')
+ reflow_table()
+ self.assertEquals(expect, vim.current.buffer)
+