[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