factor / factor

Factor programming language
https://factorcode.org/
BSD 2-Clause "Simplified" License
1.62k stars 205 forks source link

Table alignment in prettyprint #1840

Open bjourne opened 7 years ago

bjourne commented 7 years ago

It would be cool if the prettyprint vocab supported aligning table columns. For example, here is how the code-room. word formats tables:

Optimized code:   56602 blocks 13,624 KB
Unoptimized code: 33316 blocks 4,428 KB
Inline caches:    4841 blocks  981 KB

But it would be cooler if the last two columns were right-aligned:

Optimized code:   56602 blocks 13,624 KB
Unoptimized code: 33316 blocks  4,428 KB
Inline caches:     4841 blocks    981 KB
mrjbq7 commented 6 years ago

It would be cool. We could probably annotate tables with column alignment, or maybe just assume values that start with a number should be right-aligned...

diff --git a/basis/strings/tables/tables.factor b/basis/strings/tables/tables.factor
index aa914885ef..aaf2a79646 100644
--- a/basis/strings/tables/tables.factor
+++ b/basis/strings/tables/tables.factor
@@ -1,6 +1,7 @@
 ! Copyright (C) 2009, 2010 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
-USING: kernel sequences fry math.order math.ranges splitting ;
+USING: ascii kernel sequences fry math.order math.ranges
+splitting ;
 IN: strings.tables

 <PRIVATE
@@ -8,8 +9,12 @@ IN: strings.tables
 : format-row ( seq -- seq )
     dup longest length '[ _ "" pad-tail ] map! ;

+: pad-column ( str n -- str' )
+    CHAR: \s pick ?first [ digit? ] [ f ] if*
+    [ pad-head ] [ pad-tail ] if ;
+
 : format-column ( seq -- seq )
-    dup longest length '[ _ CHAR: \s pad-tail ] map! ;
+    dup longest length '[ _ pad-column ] map! ;

 PRIVATE>
mrjbq7 commented 4 years ago

Another approach is to have a column alignment variable, maybe delegated from the prettyprinter:

diff --git a/basis/strings/tables/tables.factor b/basis/strings/tables/tables.factor
index aa914885ef..42f7792aa0 100644
--- a/basis/strings/tables/tables.factor
+++ b/basis/strings/tables/tables.factor
@@ -1,21 +1,39 @@
 ! Copyright (C) 2009, 2010 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
-USING: kernel sequences fry math.order math.ranges splitting ;
+USING: combinators fry kernel math.order math.ranges namespaces
+sequences sequences.extras splitting ;
 IN: strings.tables

+SYMBOLS: +left+ +center+ +right+ ;
+
+SYMBOL: column-alignment
+
 <PRIVATE

 : format-row ( seq -- seq )
     dup longest length '[ _ "" pad-tail ] map! ;

-: format-column ( seq -- seq )
+: align-left ( seq -- seq )
     dup longest length '[ _ CHAR: \s pad-tail ] map! ;

+: align-right ( seq -- seq )
+    dup longest length '[ _ CHAR: \s pad-head ] map! ;
+
+: align-center ( seq -- seq )
+    dup longest length '[ _ CHAR: \s pad-center ] map! ;
+
+: format-column ( seq i -- seq )
+    column-alignment get ?nth +left+ or {
+        { +left+ [ align-left ] }
+        { +right+ [ align-right ] }
+        { +center+ [ align-center ] }
+    } case ;
+
 PRIVATE>

 : format-table ( table -- seq )
     [ [ string-lines ] map format-row flip ] map concat flip
     [ { } ] [
-        [ but-last-slice [ format-column ] map! drop ] keep
+        [ format-column ] map-index!
         flip [ " " join ] map!
     ] if-empty ;

The benefit is that it won't auto-detect wrong cases like house numbers "123 Main St." or product codes or whatever.

IN: scratchpad { +left+ +center+ +right+ } column-alignment [
                   {
                      { "this is left" "that is center" "other is right" }
                      { "1" "2" "3" }
                      { "horse" "zebra" "giraffe" }
                   } format-table [ print ] each
               ] with-variable
this is left that is center other is right
1                  2                     3
horse            zebra             giraffe

Note: this patch won't apply cleanly at the moment because it relies on sequences.extras.