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

Ian MacLarty maclarty at cs.mu.OZ.AU
Sat Mar 12 19:43:51 AEDT 2005


How do I adjust the NEWS file for this?  I don't want to include this in
the 0.12 release, but it should go in the news for the 0.13 release.

For review by anyone.

Estimated hours taken: 2
Branches: main

Add string.word_wrap/2 which breaks a string into multiple lines, preserving
whole words where possible.

library/string.m
	Add string.word_wrap/2.
	
	Also remove inconsistent seperating lines and move justified_column
	type after format_table function, since poly_type is after 
	the format function.
	
tests/general/string_test.exp
tests/general/string_test.m
	Test string.word_wrap/2.

Index: library/string.m
===================================================================
RCS file: /home/mercury1/repository/mercury/library/string.m,v
retrieving revision 1.230
diff -u -r1.230 string.m
--- library/string.m	28 Feb 2005 03:39:38 -0000	1.230
+++ library/string.m	12 Mar 2005 08:28:23 -0000
@@ -670,20 +670,12 @@
 :- pred string__format(string::in, list(string__poly_type)::in, string::out)
 	is det.
 
-%------------------------------------------------------------------------------%
-
 :- type string__poly_type
 	--->	f(float)
 	;	i(int)
 	;	s(string)
 	;	c(char).
 
-%-----------------------------------------------------------------------------%
-
-:- type justified_column
-	--->	left(list(string))
-	;	right(list(string)).
-
 	% format_table(Columns, Separator) = Table
 	% format_table/2 takes a list of columns and a column separator
 	% and returns a formatted table, where each field in each column
@@ -703,6 +695,19 @@
 	%
 :- func string__format_table(list(justified_column), string) = string.
 
+:- type justified_column
+	--->	left(list(string))
+	;	right(list(string)).
+
+	% word_wrap(Str, N) = Wrapped.
+	% Wrapped is Str with newlines inserted between words so that at most 
+	% N characters appear on a line and each line contains as many
+	% whole words as possible.  If any one word exceeds N characters in 
+	% length then it will be broken over two (or more) lines. 
+	% Multiple successive whitespaces are also replaced with one space.
+	%
+:- func string__word_wrap(string, int) = string.
+
 %-----------------------------------------------------------------------------%
 
 :- implementation.
@@ -4714,6 +4719,66 @@
 
 %-----------------------------------------------------------------------------%
 
+string__word_wrap(Str, N) = Wrapped :-
+	Words = string.words(char.is_whitespace, Str),
+	string.word_wrap_2(Words, 1, N, [], Wrapped).
+
+:- pred word_wrap_2(list(string)::in, int::in, int::in, list(string)::in,
+	string::out) is det.
+
+word_wrap_2([], _, _, RevStrs, string.join_list("", list.reverse(RevStrs))).
+word_wrap_2([Word | Words], Col, N, Prev, Wrapped) :-
+	WordLen = string.length(Word),
+	(
+		Col = 1, WordLen < N
+	->
+		word_wrap_2(Words, Col + WordLen, N, [Word | Prev], Wrapped)
+	;
+		Col + 1 + WordLen < N
+	->
+		word_wrap_2(Words, Col + WordLen + 1, N, [Word, " " | Prev], 
+			Wrapped)
+	;
+		Col + 1 + WordLen = N
+	->
+		word_wrap_2(Words, 1, N, ["\n", Word, " " | Prev], Wrapped)
+	;
+		(
+			Col = 1, WordLen > N
+		->
+			%
+			% Break up words that are too big to fit on a line.
+			%
+			RevPieces = break_up_rev(Word, N, []),
+			(
+				RevPieces = [LastPiece | _]
+			;
+				RevPieces = [],
+				error("string__word_wrap_2: no pieces")
+			),
+			PiecesStr = string.join_list("\n", list.reverse(
+				RevPieces)),
+			word_wrap_2(Words, string.length(LastPiece), N, 
+				[PiecesStr | Prev], Wrapped)
+		;
+			word_wrap_2([Word | Words], 1, N, ["\n" | Prev], 
+			Wrapped)
+		)
+	).
+
+:- func break_up_rev(string, int, list(string)) = list(string).
+
+break_up_rev(Str, N, Prev) = Strs :-
+	(
+		string.length(Str) =< N
+	->
+		Strs = [Str | Prev]
+	;
+		string.split(Str, N, Left, Right),
+		Strs = break_up_rev(Right, N, [Left | Prev])
+	).
+
+%-----------------------------------------------------------------------------%
 :- end_module string.
 
 %------------------------------------------------------------------------------%
Index: tests/general/string_test.exp
===================================================================
RCS file: /home/mercury1/repository/tests/general/string_test.exp,v
retrieving revision 1.3
diff -u -r1.3 string_test.exp
--- tests/general/string_test.exp	4 Feb 2005 05:55:16 -0000	1.3
+++ tests/general/string_test.exp	12 Mar 2005 08:31:50 -0000
@@ -17,3 +17,22 @@
 aaa|1111111|  1,300,000.00
 b  |       |      9,999.00
 cc |    333|123,456,789.99
+
+Wrapped string:
+-aaaaaaaaa
+aaaaaaaaaa
+a- bbbbb
+bbb b
+ccccc c c
+c cccc c
+c c c
+ccccc ccc
+cccc c
+ccc ccc
+ccc
+-ddddddddd
+dddddddddd
+dddddddddd
+dddddddddd
+dddddddddd
+ddddd- eee
Index: tests/general/string_test.m
===================================================================
RCS file: /home/mercury1/repository/tests/general/string_test.m,v
retrieving revision 1.5
diff -u -r1.5 string_test.m
--- tests/general/string_test.m	4 Feb 2005 05:55:16 -0000	1.5
+++ tests/general/string_test.m	12 Mar 2005 08:30:08 -0000
@@ -62,6 +62,13 @@
 		right(["1111111", "", "333"]), right(["1,300,000.00", 
 		"9,999.00", "123,456,789.99"])], "|") ++ "\n" },
 	write_string(Table),
+	{ Wrapped = string.word_wrap("-aaaaaaaaaaaaaaaaaaaa-  bbbbb bbb  b\t"
+		++ " ccccc c c c   cccc c c c c ccccc ccc cccc c  ccc ccc ccc "
+		++ "-dddddddddddddddddddddddddddddddddddddddddddddddddddddd-"
+		++ "                                                    eee",
+		10) },
+	write_string("\nWrapped string:\n"),
+	write_string(Wrapped),
 	[].
 
 :- 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