Currently there is no easy way to draw a table. PhabricatorDaemonManagementStatusWorkflow draws a table in an ad-hoc way, but it would be useful to provide a more flexible mechanism to do so.
Details
- Reviewers
epriestley - Group Reviewers
Blessed Reviewers - Commits
- rPHU1fa58627e797: Add a `PhutilConsoleTable` class for drawing tables.
$table = id(new PhutilConsoleTable()) ->addColumn('foo', array('title' => 'Foo', 'align' => 'right')) ->addColumn('bar', array('title' => 'Foobar', 'align' => 'center')) ->addColumn('baz', array('title' => '日本語')) ->addRow(array('foo' => 12345, 'bar' => 'foo', 'baz' => 'baz')) ->addRow(array('foo' => '汉语漢語', 'bar' => '한국어조선말', 'baz' => 'ру́сский язы́к')) ->addRow(array('foo' => 'aaa', 'bar' => '✓✗', 'baz' => 'dddddddddddd')) ->addRow(array('foo' => '', 'bar' => '', 'baz' => '')); $table->setBorders(false)->draw(); echo "\n"; $table->setBorders(true)->draw();
Output
Diff Detail
- Repository
- rPHU libphutil
- Branch
- table
- Lint
Lint Passed - Unit
Tests Passed - Build Status
Buildable 1091 Build 1091: [Placeholder Plan] Wait for 30 Seconds
Event Timeline
Allow tables to have borders. For example:
============= | Foo | Bar | ------------- | bar | foo | =============
When borders are enabled, it might be nice to draw the + style tables like MySQL? I think they look pretty good and they're probably familiar to a lot of users.
+---+ | N | +---+ | 1 | | 2 | +---+
Major general issue is UTF8:
- UTF8 characters may contain multiple bytes. You can use phutil_utf8_strlen() to get the number of characters in a string.
- Some UTF8 characters take up two characters when displayed in a monospaced font. For example:
- ...you can use phutil_utf8_console_strlen() to get the number of monospaced characters a string requires to display.
- Since sprintf() can't handle any of this, you'll have to write your own padding stuff.
- Stuff like strrev() does not work in the general case.
Broadly:
- It might be nice to specify a maximum table width and a column to truncate if the width is exceeded (or truncation widths per columns?). This could be in v2 or something. We can usually figure out how many columns are available with phutil_console_get_terminal_width(). In particular, this would make tables like "your open tasks", "your open revisions", etc., behave better when you have a task or revision that someone typed a million pages into the title of.
- We could use this in some arc commands today -- notably, arc tasks does a (bad, nongeneral) job of this.
- This is definitely a good thing overall and will make numerous commands cleaner and/or more useful.
src/console/PhutilConsoleTable.php | ||
---|---|---|
28 | By convention, prefer to return $this; from set...() methods so they can be chained. | |
34 | Use phutil_utf8_console_strlen() to get the display width of a UTF8 string in a monospaced font. | |
95–111 | This won't do the right thing with multibyte and double-width characters. sprintf() probably can't be used anywhere in this. | |
138 | Won't work with UTF8, and not sure what the use case is? |
- Return $this.
- MySQL-style tables.
- Don't use strrev
- Minor fixes
- Minor tidying
- Refactoring. Improved unicode support.
Here's a revised usage example:
$table = id(new PhutilConsoleTable()) ->addColumn('foo', array('title' => 'Foo')) ->addColumn('bar', array('title' => 'Foobar')) ->addColumn('baz', array('title' => '日本語')) ->addData(array('foo' => 12345, 'bar' => 'foo', 'baz' => 'baz')) ->addData(array('foo' => '日本語', 'bar' => '日本語', 'baz' => '日本語')) ->addData(array('foo' => 'aaa', 'bar' => 'bbb', 'baz' => 'dddddddddddd')) ->setDrawBorders(true) ->draw();
Output
A more complicated example:
$table = id(new PhutilConsoleTable()) ->addColumn('foo', array('title' => 'Foo')) ->addColumn('bar', array('title' => 'Foobar')) ->addColumn('baz', array('title' => '日本語')) ->addData(array('foo' => 12345, 'bar' => 'foo', 'baz' => 'baz')) ->addData(array('foo' => '汉语漢語', 'bar' => '한국어조선말', 'baz' => 'ру́сский язы́к')) ->addData(array('foo' => 'aaa', 'bar' => '✓✗', 'baz' => 'dddddddddddd')) ->addData(array('foo' => '', 'bar' => '', 'baz' => '')); $table->setDrawBorders(false)->draw(); echo "\n"; $table->setDrawBorders(true)->draw();
Output
(Interestingly, it doesn't work properly with Russian characters. I think this is a bug with phutil_utf8_console_strlen?)
- Various minor improvements.
- Allow custom alignment.
- Fix line lengths.
- Fix encoding.
- Minor refactoring.
- Header row in bold.
- Add example usage.
- Minor formatting changes.
- Changed some methods from private to protected
- Rename method.
Three tiny stylistic nits -- any of these feel worth improving?
I'll see if I can fix phutil_utf8_console_strlen(), that does look like a bug.
src/console/PhutilConsoleTable.php | ||
---|---|---|
78 | Maybe addRow()? | |
94–96 | Maybe build the whole table, then write it out in one go, instead of writing it out bit-by-bit? | |
103 | Maybe just - (like MySQL), instead of =? |
D9546 should fix the combining characters in the russian strings, if you still have that test case handy.
src/console/PhutilConsoleTable.php | ||
---|---|---|
103 | I'm open to either, but I sort of prefer =. One reason is that I had considered having an addSeparator function which would insert a row of -. For example: +=====+=====+ + Foo | Bar | +=====+=====+ + foo | bar + + 1 | 2 + +-----|-----+ + foo | bar + +=====|=====+ |
Closed by commit rPHU1fa58627e797 (authored by @joshuaspence, committed by @epriestley).