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

Julien Fischer juliensf at cs.mu.OZ.AU
Sun Mar 13 15:41:23 AEDT 2005


On Sat, 12 Mar 2005, Ian MacLarty wrote:

> 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.
>
Just put a temporary section at the top of the NEWS file on the main
branch. e.g. Changes since 0.12 fork, and put any changes there.  I'll
clean it all up closer to the 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
s/seperating/separating/

> 	type after format_table function, since poly_type is after
> 	the format function.
It would be clearer to just say that you have rearranged this items
so that they are now in top-down order.

>
> 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.
I think that you should be able to insert a hyphen between the two parts
of the word in this case.  (Perhaps, make this an optional argument).


> +	% Multiple successive whitespaces are also replaced with one space.
> +	%
I suggest:

	Sequences of whitspace characters are replaced by a single 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).
> +
I suggest renaming this predicate break_up_reversed_string.

> +break_up_rev(Str, N, Prev) = Strs :-
> +	(
> +		string.length(Str) =< N
It may be worth keeping track of the length of the strings as you go,
rather than recomputing it all the time.

> +	->
> +		Strs = [Str | Prev]
> +	;
> +		string.split(Str, N, Left, Right),
> +		Strs = break_up_rev(Right, N, [Left | Prev])
> +	).

Julien.
--------------------------------------------------------------------------
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