Repository: alexhsamuel/ntab

Issue:
pretty-print a row
Print  a row with one field on each line.


Discussion:

Patch:
diff --git a/ntab/fmt.py b/ntab/fmt.py
new file mode 100644
index 0000000..7c047c4
--- /dev/null
+++ b/ntab/fmt.py
@@ -0,0 +1,22 @@
+from   __future__ import absolute_import, division, print_function, unicode_literals
+
+import six
+
+from   .lib.text import palide
+
+#-------------------------------------------------------------------------------
+
+def format_row(row, width=80, max_name_width=32):
+    """
+    @rtype
+      Generator of lines.
+    """
+    vals = row.__dict__
+    name_width = min(max_name_width, max( len(n) for n in vals ))
+    for name, val in six.iteritems(vals):
+        yield "{}: {}".format(
+            palide(name, name_width),
+            palide(str(val), width - name_width - 2)
+        )
+
+
diff --git a/ntab/html.py b/ntab/html.py
index 9ca4ccb..37c25a4 100644
--- a/ntab/html.py
+++ b/ntab/html.py
@@ -82,7 +82,7 @@ def _render(table, css_class="tab-table", max_rows=None):
     yield "<thead>"
     yield "<tr>"
     for name, width in zip(names, widths):
-        yield "<th>{}</th>".format(elide(name, max(width, 8)))
+        yield "<th>{}</th>".format(elide(name, max(width, 8), elide_pos=0.7))
     yield "</tr>"
     yield "</thead>"
     yield "<tbody>"
diff --git a/ntab/lib/text.py b/ntab/lib/text.py
index 8ad3e4b..0812d61 100644
--- a/ntab/lib/text.py
+++ b/ntab/lib/text.py
@@ -27,14 +27,18 @@ def pad(string, length, pad=" ", pos=1.0):
     if left > 0:
         string = pad * (left // pad_len) + pad[: left % pad_len] + string
     if right > 0:
-        string = string + pad[-(right % pad_len) :] + pad * (right // pad_len)
+        string = (
+            string 
+            + pad[pad_len - (right % pad_len) :] 
+            + pad * (right // pad_len)
+        )
     return string
 
 
 _pad = pad
 
 
-def elide(string, length, ellipsis=u"\u2026", pos=0.7):
+def elide(string, length, ellipsis=u"\u2026", pos=1.0):
     """
     Elides characters if necessary to fit `string` in `length` characters.
 
@@ -63,7 +67,7 @@ def elide(string, length, ellipsis=u"\u2026", pos=0.7):
 
 
 def palide(string, length, ellipsis=u"\u2026", pad=" ", pad_pos=1.0, 
-           elide_pos=0.7):
+           elide_pos=1.0):
     """
     A combination of `elide` and `pad`.
     """
diff --git a/ntab/tab.py b/ntab/tab.py
index 5b569b5..010dcb1 100644
--- a/ntab/tab.py
+++ b/ntab/tab.py
@@ -13,7 +13,7 @@ import numpy as np
 import six
 import sys
 
-from   . import nplib
+from   . import fmt, nplib
 from   .lib import *
 
 #-------------------------------------------------------------------------------
@@ -181,11 +181,22 @@ class Row(object):
         )
 
     
+    def __str__(self):
+        return "\n".join(fmt.format_row(self))
+
+
     @property
-    def __index__(self):
+    def __idx__(self):
         return self.__idx
 
 
+    # FIXME: Potentially sketchy.
+    @property
+    def __dict__(self):
+        return odict(
+            (n, a[self.__idx]) for n, a in six.iteritems(self.__arrs) )
+
+
 
 class RowsProxy(collections.Sequence):
     # FIXME: Allow modifying values in rows (i.e. mutable rows)?


Test patch:
diff --git a/ntab/lib/test/test_text.py b/ntab/lib/test/test_text.py
new file mode 100644
index 0000000..aff5323
--- /dev/null
+++ b/ntab/lib/test/test_text.py
@@ -0,0 +1,120 @@
+from   __future__ import absolute_import, division, print_function, unicode_literals
+
+import pytest
+
+from   ntab.lib.text import *
+
+#-------------------------------------------------------------------------------
+
+def test_pad_length():
+    assert pad("hello",  0) == "hello"
+    assert pad("hello",  4) == "hello"
+    assert pad("hello",  5) == "hello"
+    assert pad("hello",  6) == "hello "
+    assert pad("hello", 10) == "hello     "
+    assert pad("hello", length=10) == "hello     "
+
+    assert pad("", 0) == ""
+    assert pad("", 5) == "     "
+
+
+def test_pad_pad():
+    assert pad("hello", 4, "x") == "hello"
+    assert pad("hello", 6, "x") == "hellox"
+    assert pad("hello", 9, "x") == "helloxxxx"
+    assert pad("hello", 8, "o") == "helloooo"
+    assert pad("hello", 8, "-") == "hello---"
+    assert pad("hello", pad="-", length=8) == "hello---"
+    assert pad("hello", 8, "-=") == "hello=-="
+    assert pad("hello", 12, ".!.") == "hello..!..!."
+
+
+def test_pad_left():
+    assert pad("hello",  4, pos=0 ) == "hello"
+    assert pad("hello", 10, pos=1 ) == "hello     "
+    assert pad("hello", 10, pos=0 ) == "     hello"
+    assert pad("hello", 10, pos=0, pad="/") == "/////hello"
+
+
+# FIXME: Test center().
+
+def test_elide_default():
+    assert elide("I am a duck.",  8) == u"I am a \u2026"
+    assert elide("I am a duck.", 14) == "I am a duck."
+
+
+def test_elide_length():
+    assert elide("Hello, world!", 15, "...") == "Hello, world!"
+    assert elide("Hello, world!", 13, "...") == "Hello, world!"
+    assert elide("Hello, world!", 12, "...") == "Hello, wo..."
+    assert elide("Hello, world!", 11, "...") == "Hello, w..."
+    assert elide("Hello, world!", 10, "...") == "Hello, ..."
+    assert elide("Hello, world!",  5, "...") == "He..."
+
+    assert elide("foo", 3, "...") == "foo"
+    assert elide("fool", 3, "...") == "..."
+
+
+def test_elide_ellipsis():
+    assert elide("Hello, world!", 10, "...") == "Hello, ..."
+    assert elide("Hello, world!", 10, ".." ) == "Hello, w.."
+    assert elide("Hello, world!", 10, "*"  ) == "Hello, wo*"
+    assert elide("Hello, world!", 10, ""   ) == "Hello, wor"
+
+    assert elide("Hello, world!", ellipsis="*", length=10) == "Hello, wo*"
+
+
+def test_elide_position():
+    assert elide("Hello, world!", 10, "...", 1.0) == "Hello, ..."
+    assert elide("Hello, world!", 10, "...", 0.7) == "Hello...d!"
+    assert elide("Hello, world!", 10, "...", 0.5) == "Hell...ld!"
+    assert elide("Hello, world!", 10, "...", 0.4) == "Hel...rld!"
+    assert elide("Hello, world!", 10, "...", 0.0) == "... world!"
+
+    assert elide(
+        "Hello, world!", pos=0.4, length=10, ellipsis="..") == "Hel..orld!"
+
+
+def test_palide_length():
+    assert palide("Hello, world!",  3, "...") == "..."
+    assert palide("Hello, world!", 10, "...") == "Hello, ..."
+    assert palide("Hello, world!", 11, "...") == "Hello, w..."
+    assert palide("Hello, world!", 13, "...") == "Hello, world!"
+    assert palide("Hello, world!", 14, "...") == "Hello, world! "
+    assert palide("Hello, world!", 20, "...") == "Hello, world!       "
+
+
+def test_palide_ellipsis():
+    assert palide("Hello, world!", 10, "~~~~~") == "Hello~~~~~"
+    assert palide("Hello, world!", 10, "..."  ) == "Hello, ..."
+    assert palide("Hello, world!", 10, ".."   ) == "Hello, w.."
+    assert palide("Hello, world!", 10, ""     ) == "Hello, wor"
+
+
+def test_palide_pad():
+    assert palide("Hello, world!", 13, pad="x") == "Hello, world!"
+    assert palide("Hello, world!", 18, pad="x") == "Hello, world!xxxxx"
+    assert palide("Hello, world!", 18, pad="!") == "Hello, world!!!!!!"
+
+
+def test_palide_position():
+    assert palide("Hello, world!", 11, "..", elide_pos=0.0) == "..o, world!"
+    assert palide("Hello, world!", 11, "..", elide_pos=0.6) == "Hello..rld!"
+    assert palide("Hello, world!", 11, "..", elide_pos=0.8) == "Hello, ..d!"
+
+
+def test_palide_args():
+    assert palide(
+        ellipsis="-//-", 
+        length=20,
+        pad="x",
+        elide_pos=0.4,
+        string="The quick brown fox jumped over the lazy dogs.",
+        ) == "The qu-//-lazy dogs."
+
+
+def test_palide_default():
+    assert palide("I am a duck.",  8) == u"I am a \u2026"
+    assert palide("I am a duck.", 14) == "I am a duck.  "
+
+