[m-rev.] for review: add string.format_table/2

Ian MacLarty maclarty at cs.mu.OZ.AU
Thu Feb 3 21:47:52 AEDT 2005


For review by anyone.

Estimated hours taken: 3
Branches: main

Add a function to the string module to generate a formatted text table.

library/string.m
	Add format_table/2 which generates a formatted text table from
	a list of columns.

tests/general/string_test.exp
tests/general/string_test.m
	Test the new function.

Index: library/string.m
===================================================================
RCS file: /home/mercury1/repository/mercury/library/string.m,v
retrieving revision 1.227
diff -u -r1.227 string.m
--- library/string.m	3 Feb 2005 09:06:36 -0000	1.227
+++ library/string.m	3 Feb 2005 10:43:14 -0000
@@ -667,6 +667,28 @@
 	;	c(char).
 
 %-----------------------------------------------------------------------------%
+
+:- type justified_column
+	--->	left(list(string))
+	;	right(list(string)).
+
+	% format_table(Columns, Seperator) = Table
+	% format_table/2 takes a list of columns and a column seperator
+	% and returns a formatted table, where each field in each column
+	% has been aligned and fields are seperated with Seperator.
+	% A newline character is inserted between each row.
+	%
+	% For example:
+	%
+	% format_table([right(["a", "bb", "ccc"]), left(["1", "22", "333"])], 
+	%   " * ")
+	% would return the table:
+	%   a * 1
+	%  bb * 22
+	% ccc * 333
+	%
+:- func string__format_table(list(justified_column), string) = string.
+
 %-----------------------------------------------------------------------------%
 
 :- implementation.
@@ -4616,6 +4638,61 @@
 	char_list_equal(Xs, Ys).
 
 %------------------------------------------------------------------------------%
+
+string__format_table(Columns, Seperator) = Table :-
+	MaxWidths = list.map(find_max_length, Columns),
+	PaddedColumns = list.map_corresponding(pad_column, MaxWidths, Columns),
+	(
+		PaddedColumns = [PaddedHead | PaddedTail],
+		Rows = list.foldl(list.map_corresponding(
+			string.join_rev_columns(
+				Seperator)), PaddedTail, PaddedHead)
+	;
+		PaddedColumns = [],
+		Rows = []
+	),
+	Table = string.join_list("\n", Rows).
+
+:- func join_rev_columns(string, string, string) = string.
+
+join_rev_columns(Seperator, Col1, Col2) = Col2 ++ Seperator ++ Col1.
+
+:- func find_max_length(justified_column) = int.
+
+find_max_length(left(Strings)) = MaxWidth :-
+	list.foldl(max_str_length, Strings, {0, ""}, {MaxWidth, _}).
+find_max_length(right(Strings)) = MaxWidth :-
+	list.foldl(max_str_length, Strings, {0, ""}, {MaxWidth, _}).
+
+:- func pad_column(int, justified_column) = list(string).
+
+pad_column(Width, left(Strings)) = list.map(string.rpad(' ', Width), Strings).
+pad_column(Width, right(Strings)) = list.map(string.lpad(' ', Width), Strings).
+
+:- func rpad(char, int, string) = string.
+
+rpad(Chr, N, Str) = string.pad_right(Str, Chr, N).
+
+:- func lpad(char, int, string) = string.
+
+lpad(Chr, N, Str) = string.pad_left(Str, Chr, N).
+
+:- pred max_str_length(string::in, {int, string}::in, {int, string}::out)
+	is det.
+
+max_str_length(Str, {PrevMaxLen, PrevMaxStr}, {MaxLen, MaxStr}) :-
+	Length = string.length(Str),
+	(
+		Length > PrevMaxLen
+	->
+		MaxLen = Length,
+		MaxStr = Str
+	;
+		MaxLen = PrevMaxLen,
+		MaxStr = PrevMaxStr
+	).
+
+%-----------------------------------------------------------------------------%
 
 :- end_module string.
 
Index: tests/general/string_test.exp
===================================================================
RCS file: /home/mercury1/repository/tests/general/string_test.exp,v
retrieving revision 1.2
diff -u -r1.2 string_test.exp
--- tests/general/string_test.exp	3 Feb 2005 09:06:37 -0000	1.2
+++ tests/general/string_test.exp	3 Feb 2005 10:41:44 -0000
@@ -14,3 +14,6 @@
 Five f's: fffff
 Five f's and five dots: fffff.....
 Five dashes, five f's and five dots: -----fffff.....
+aaa|1111111|  1,300,000.00
+b  |       |      9,999.00
+cc |    333|123,456,789.99
Index: tests/general/string_test.m
===================================================================
RCS file: /home/mercury1/repository/tests/general/string_test.m,v
retrieving revision 1.4
diff -u -r1.4 string_test.m
--- tests/general/string_test.m	3 Feb 2005 09:06:37 -0000	1.4
+++ tests/general/string_test.m	3 Feb 2005 10:41:13 -0000
@@ -56,7 +56,12 @@
 	{ string__pad_right(FiveFs, '.', 10, FsAndDots) },
 	write_message("Five f's and five dots: ", FsAndDots),
 	{ string__pad_left(FsAndDots, '-', 15, DashesFsAndDots) },
-	write_message("Five dashes, five f's and five dots: ", DashesFsAndDots),
+	write_message("Five dashes, five f's and five dots: ", 
+		DashesFsAndDots),
+	{ Table = string__format_table([left(["aaa", "b", "cc"]), 
+		right(["1111111", "", "333"]), right(["1,300,000.00", 
+		"9,999.00", "123,456,789.99"])], "|") ++ "\n" },
+	write_string(Table),
 	[].
 
 :- pred write_message(string, string, io__state, io__state).
--------------------------------------------------------------------------
mercury-reviews mailing list
post:  mercury-reviews at cs.mu.oz.au
administrative address: owner-mercury-reviews at cs.mu.oz.au
unsubscribe: Address: mercury-reviews-request at cs.mu.oz.au Message: unsubscribe
subscribe:   Address: mercury-reviews-request at cs.mu.oz.au Message: subscribe
--------------------------------------------------------------------------



More information about the reviews mailing list