Skip to content

Commit fe2f5bd

Browse files
authored
Merge pull request #1095 from python-cmd2/column_spacing
Made the amount of space between columns in a SimpleTable configurable
2 parents 77a6c22 + ecfecfd commit fe2f5bd

File tree

3 files changed

+37
-11
lines changed

3 files changed

+37
-11
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@
4545
* ipy command now includes all of `self.py_locals` in the IPython environment
4646
* Added `include_py` keyword parameter to `cmd2.Cmd.__init__()`. If `False`, then the `py` command will
4747
not be available. Defaults to `False`. `run_pyscript` is not affected by this parameter.
48+
* Made the amount of space between columns in a SimpleTable configurable
4849

4950
## 1.5.0 (January 31, 2021)
5051
* Bug Fixes

cmd2/table_creator.py

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -535,21 +535,27 @@ class SimpleTable(TableCreator):
535535
This class can be used to create the whole table at once or one row at a time.
536536
"""
537537

538-
# Spaces between cells
539-
INTER_CELL = 2 * SPACE
540-
541-
def __init__(self, cols: Sequence[Column], *, tab_width: int = 4, divider_char: Optional[str] = '-') -> None:
538+
def __init__(
539+
self, cols: Sequence[Column], *, column_spacing: int = 2, tab_width: int = 4, divider_char: Optional[str] = '-'
540+
) -> None:
542541
"""
543542
SimpleTable initializer
544543
545544
:param cols: column definitions for this table
545+
:param column_spacing: how many spaces to place between columns. Defaults to 2.
546546
:param tab_width: all tabs will be replaced with this many spaces. If a row's fill_char is a tab,
547547
then it will be converted to one space.
548548
:param divider_char: optional character used to build the header divider row. Set this to None if you don't
549549
want a divider row. Defaults to dash. (Cannot be a line breaking character)
550-
:raises: TypeError if fill_char is more than one character (not including ANSI style sequences)
551-
:raises: ValueError if text or fill_char contains an unprintable character
550+
:raises: ValueError if column_spacing is less than 0
551+
:raises: ValueError if tab_width is less than 1
552+
:raises: TypeError if divider_char is longer than one character
553+
:raises: ValueError if divider_char is an unprintable character
552554
"""
555+
if column_spacing < 0:
556+
raise ValueError("Column spacing cannot be less than 0")
557+
self.inter_cell = column_spacing * SPACE
558+
553559
if divider_char is not None:
554560
if len(ansi.strip_style(divider_char)) != 1:
555561
raise TypeError("Divider character must be exactly one character long")
@@ -562,13 +568,15 @@ def __init__(self, cols: Sequence[Column], *, tab_width: int = 4, divider_char:
562568
self.divider_char = divider_char
563569

564570
@classmethod
565-
def base_width(cls, num_cols: int) -> int:
571+
def base_width(cls, num_cols: int, *, column_spacing: int = 2) -> int:
566572
"""
567573
Utility method to calculate the display width required for a table before data is added to it.
568574
This is useful when determining how wide to make your columns to have a table be a specific width.
569575
570576
:param num_cols: how many columns the table will have
577+
:param column_spacing: how many spaces to place between columns. Defaults to 2.
571578
:return: base width
579+
:raises: ValueError if column_spacing is less than 0
572580
:raises: ValueError if num_cols is less than 1
573581
"""
574582
if num_cols < 1:
@@ -577,14 +585,14 @@ def base_width(cls, num_cols: int) -> int:
577585
data_str = SPACE
578586
data_width = ansi.style_aware_wcswidth(data_str) * num_cols
579587

580-
tbl = cls([Column(data_str)] * num_cols)
588+
tbl = cls([Column(data_str)] * num_cols, column_spacing=column_spacing)
581589
data_row = tbl.generate_data_row([data_str] * num_cols)
582590

583591
return ansi.style_aware_wcswidth(data_row) - data_width
584592

585593
def total_width(self) -> int:
586594
"""Calculate the total display width of this table"""
587-
base_width = self.base_width(len(self.cols))
595+
base_width = self.base_width(len(self.cols), column_spacing=ansi.style_aware_wcswidth(self.inter_cell))
588596
data_width = sum(col.width for col in self.cols)
589597
return base_width + data_width
590598

@@ -593,7 +601,7 @@ def generate_header(self) -> str:
593601
header_buf = io.StringIO()
594602

595603
# Create the header labels
596-
header = self.generate_row(inter_cell=self.INTER_CELL)
604+
header = self.generate_row(inter_cell=self.inter_cell)
597605
header_buf.write(header)
598606

599607
# Create the divider if necessary
@@ -617,7 +625,7 @@ def generate_data_row(self, row_data: Sequence[Any]) -> str:
617625
:param row_data: data with an entry for each column in the row
618626
:return: data row string
619627
"""
620-
return self.generate_row(row_data=row_data, inter_cell=self.INTER_CELL)
628+
return self.generate_row(row_data=row_data, inter_cell=self.inter_cell)
621629

622630
def generate_table(self, table_data: Sequence[Sequence[Any]], *, include_header: bool = True, row_spacing: int = 1) -> str:
623631
"""

tests/test_table_creator.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -338,6 +338,18 @@ def test_simple_table_creation():
338338
'Col 1 Row 2 Col 2 Row 2 '
339339
)
340340

341+
# Custom column spacing
342+
st = SimpleTable([column_1, column_2], column_spacing=5)
343+
table = st.generate_table(row_data)
344+
345+
assert table == (
346+
'Col 1 Col 2 \n'
347+
'-------------------------------------\n'
348+
'Col 1 Row 1 Col 2 Row 1 \n'
349+
'\n'
350+
'Col 1 Row 2 Col 2 Row 2 '
351+
)
352+
341353
# Custom divider
342354
st = SimpleTable([column_1, column_2], divider_char='─')
343355
table = st.generate_table(row_data)
@@ -404,6 +416,11 @@ def test_simple_table_creation():
404416
'Col 1 Row 2 Col 2 Row 2 '
405417
)
406418

419+
# Invalid column spacing
420+
with pytest.raises(ValueError) as excinfo:
421+
SimpleTable([column_1, column_2], column_spacing=-1)
422+
assert "Column spacing cannot be less than 0" in str(excinfo.value)
423+
407424
# Invalid divider character
408425
with pytest.raises(TypeError) as excinfo:
409426
SimpleTable([column_1, column_2], divider_char='too long')

0 commit comments

Comments
 (0)