*! Help file for linewrap.ado version 2.0 written by Mead Over & Joao Pedro Azevedo (mover@cgdev.org) 3Jun2023

help for linewrapVersion 2.0 3Jun2023, requires Stata 14

Title

linewrap -- Split a long string into shorter strings
and, optionally, display them

Syntax

linewrap
,
longstring(text)
[options]

Options

longstring(text) A long text string to be chopped into lines of text.

continue When the option longstring(text) is empty,
linewrap's default behavior is to exit displaying an error message.
To enable linewrap to continue execution even when
longstring(text) is empty, specify the option continue.

Lines of equal length
maxlength(integer) Each line will be either exactly or
approximately the same length, with the length controlled by this option.
This is the default.
If this maximum line length is omitted,
the default maximum line length is 79 UNICODE characters.

square Each line before the last is chopped at exactly
maxlength(integer) characters. If this option is omitted
the default behavior is to wrap the long string at spaces, in order to avoid
splitting individual words.

stack In addition to returning each line of text in its own
macro, concatenate the lines into a single local macro.
This option is useful for constructing a graph title or legend for example.
See examples 3 and 4.

Wrap lines at one or more specific characters
parse("pchars") By specifying one or more parsing characters,
the user can wrap the text on those characters as well as on spaces.

lastpchar When multiple parse characters are specified in option
parse("pchars"), this option generates longer wrapped lines.

A line for each word
words This option is an alternative to the default
maxlength(integer) option. With words specified,
linewrap chops the long string into Stata "word"s, which
are defined by the spaces in the input string. Unlike the programmer's
command tokenize, linewrap only uses blanks to define words,
not other user specified characters such as commas or semi-colons.
Multiple spaces are treated as a single space.

A line for each character
characters This option is a second alternative to the default
maxlength(integer) option. With characters specified,
linewrap chops the long string into individual Unicode characters.
Multiple spaces are treated as a single space.

Display the wrapped text
display Display the wrapped lines in the results window
and print them in the output log. If this option is omitted, linewrap
only returns the separate lines in the r() space

linenumbers Number the displayed lines. Only relevant if
option display is also specified

title(string) Optionally display a title before
displaying any other output

Change the names of returned macros
name(string) Allows the user to assign the names of the local macros
containing the text segments that are returned by linewrap.

add Add the stored results to results previously stored in Stata's
stored results space.
Sequential executions of linewrap with distinctly specified name(string) options
- and without intervening Stata programs that clear the return space
- will accumulate the differently named local macros in the return space.
See examples 2, 3
and 4

replace Obsolete option.

Description

linewrap chops a long text string into a set of shorter "lines"
and returns them in Stata's r() space in macros named
r(line1), r(line2), r(line3), ... r(line1n),
where n, the total number of lines, is returned as macro
r(nlines). The display option causes
linewrap to display the wrapped text, line by line.

The user feeds linewrap a text string via the option longstring(text).
The text string can be thousands of characters long. (Type display c(macrolen)
at the Stata prompt to see the maximum number of characters for your version of Stata.)
If there are embedded single or double quotation marks, be sure to enclose
the entire string in
compound double quotes.

Without options, linewrap wraps the longstring(text)
into lines of approximately 79 characters in length, breaking each line
at the last blank space before the 79'th character. Character strings longer
than 79 characters (or longer than the user specified maxlength(integer))
are presented in their entirety as a single "line". By adding the square option,
the user can require the lines to break exactly at maxlength(integer)
characters, regardless of blank space.

The words option specifies that the lines into which the long character
string is apportioned are "words", defined by the blanks. Each line containing
a single word can be of any length.

Option parse("pchars") enables linewrap to break the long
string into lines of text at the specified characters as well as spaces.
When one character is specified, the line wraps at either the last
occurence of the character in the line or the last occuring space
in the line, whichever occurs earlier.
When several characters are specified, the last occurrences of all the
characters are compared to find which of these occurs first in the line.
The line is then wrapped at either the first of these last occurences
or at the last blank space, whichever occurs earlier in the line.
The option lastpchar slightly alters this behavior to select
which of the last occurences occurs last in the line and then wrap the line
at the last of these last occurences or at the last blank space,
whichever occurs earlier. See example 5 below.

name(string) is a programmer's option.
The name(string) option allows the user to specify the names of the local macros
containing the text segments that are returned by linewrap.
This capability enables a programmer to accumulate these lines of text
over several executions of linewrap.
Use the name(string) option together with the add option
to accumulate the returned segments of text in Stata's return space.
Thus, after several sequential executions of linewrap,
provided other commands do not touch the return space,
all the generated text segments are available there
and are distinguishable by their different user-assigned name(string) options.

Examples

Example 1 Single execution

. linewrap, longstr(Four score and seven years ago our fathers brought
forth on this continent, a new nation, conceived in Liberty, and dedicated to
the proposition that all men are created equal.
The quick red fox jumped over the lazy dog.)
title(Example with default maxlength of 79) display linenumbers

Produces output:

Example with default maxlength of 79:

1 2 3 4 5 6 7
1234567890123456789012345678901234567890123456789012345678901234567890123456789

1 Four score and seven years ago our fathers brought forth on this continent, a
2 new nation, conceived in Liberty, and dedicated to the proposition that all
3 men are created equal. The quick red fox jumped over the lazy dog.

. return list

Produces output:

macros:
r(strlen) : "220"
r(nlines) : "3"
r(line3) : "men are created equal. The quick red fox jumped over the lazy dog."
r(line2) : "new nation, conceived in Liberty, and dedicated to the proposition that all"
r(line1) : "Four score and seven years ago our fathers brought forth on this continent, a"

Example 2 Sequential execution, accumulating text in stored results

Example using the name(string) option in order to preserve return list
accross several sequential executions of linewrap.
Note that the option add is specified on the second execution.

. linewrap, longstr(We the People of the United States, in Order to form
a more perfect Union, establish Justice, insure domestic Tranquility, provide for
the common defence, promote the general Welfare, and secure the Blessings of Liberty
to ourselves and our Posterity, do ordain and establish this Constitution for the
United States of America.) max(40) name(first_)

. linewrap, longstr(Four score and seven years ago our fathers brought
forth on this continent, a new nation, conceived in Liberty, and dedicated to
the proposition that all men are created equal.
The quick red fox jumped over the lazy dog.) name(second_) add

. return list

Produces output:

macros:
r(strlen_first_) : "327"
r(nlines_first_) : "9"
r(first_9) : "the United States of America."
r(first_8) : "and establish this Constitution for"
r(first_7) : "ourselves and our Posterity, do ordain"
r(first_6) : "and secure the Blessings of Liberty to"
r(first_5) : "defence, promote the general Welfare,"
r(first_4) : "Tranquility, provide for the common"
r(first_3) : "establish Justice, insure domestic"
r(first_2) : "Order to form a more perfect Union,"
r(first_1) : "We the People of the United States, in"
r(strlen_second_) : "220"
r(nlines_second_) : "3"
r(second_3) : "men are created equal. The quick red fox jumped over the lazy dog."
r(second_2) : "new nation, conceived in Liberty, and dedicated to the proposition that all"
r(second_1) : "Four score and seven years ago our fathers brought forth on this continent, a"

Example 3 Titles for a bar graph

But suppose the user would like to construct a vertical bar graph
in which each bar has a horizontal label that is vertically stacked.
A discussion on Statalist
points out that
Stata's graph bar does not offer an option to
stack the lines of a horizontal bar label vertically.
This program linewrap can fill this gap.

Here's the use case offered by Sergiy Radyakin.

. sysuse auto, clear
(1978 Automobile Data)

. linewrap , longstring(`"very poor, but not as bad as the other guys"') maxlength(15) stack name(firstbar)

. linewrap , longstring(`"somewhat better, though still far from perfect"') maxlength(15) stack name(secondbar) add

. return list

macros:
r(strlen_secondbar) : "46"
r(nlines_secondbar) : "4"
r(secondbar) : " "somewhat" "better," "though still" "far from perfect""
r(secondbar4) : "far from perfect"
r(secondbar3) : "though still"
r(secondbar2) : "better,"
r(secondbar1) : "somewhat"
r(strlen_firstbar) : "43"
r(nlines_firstbar) : "4"
r(firstbar) : " "very poor," "but not as" "bad as the" "other guys""
r(firstbar4) : "other guys"
r(firstbar3) : "bad as the"
r(firstbar2) : "but not as"
r(firstbar1) : "very poor,"

. graph bar price if rep78<3, over(rep78, relabel(1 `"`r(firstbar)'"' 2 `"`r(secondbar)'"' )) ///
title("Using -linewrap- to stack graph labels") name(better2, replace)

Example 4 Unicode (e.g. Chinese) character titles for a bar graph

Roy Zhong initiated this
thread
on Statalist by asking how to make a vertical bar graph,
with a vertical title for each bar
such that each line of the title is a single Chinese character.
Here is his example data:

clear
input double 系数 str15 行业
.363 "农业采矿业"
.203 "制造业"
.307 "建筑业"
.501 "低端服务业"
.6 "高端服务业"
.543 "社会服务业"
end

label var 系数 "Variable name"
label var 行业 "Bar label"

To try the following examples, copy and paste the above lines into Stata.

One simple work-around with graph bar (asis) would be a graph
with vertical bars and horizontal bar labels
like that produced by this command:

*	Vertical bars with horizontal labels
graph bar (asis) 系数, over(行业) ytitle("系数") name(vbarhlbl, replace)

But if the number of characters in the bar labels were greater, the bar labels
produced by the above command would overlap.
Another work-around would be a graph with horizontal bars and horizontal bar labels
like this:

*	Horizontal bars with horizontal labels
graph hbar (asis) 系数, over(行业) ytitle("系数") name(hbarhlbl, replace)

The horizontal bar option would frequently be the best choice for this situation.
But suppose the user would like to break bar labels into single character pieces
and stack them vertically as in example 3.

To set up the graph, the following loop applies linewrap with the
options name(string) and (after the first time through the loop)
(opt add) sequentially to each of the labels. Each execution of
linewrap stores in local macro named opt_i the stacked label for bar number -i-.
Then the local macro opt_relabel accumulates the expression which will supply
the code for graph bar's option
over(varname, relabel(`opt_relabel')).

*	Vertical bars with vertical single-character labels
foreach obs of numlist 1/`=_N' {
local lbl = 行业[`obs']
linewrap ,longstr(`"`lbl'"') characters stack name(obs`obs') `add'
local add add
local lbl

local thislbl = `"`obs' `"`r(obs`obs')'"'"'
local opt_relabel = `"`opt_relabel'"' + " " + `"`thislbl'"'
}

*	Now we can construct the vertical bar graph with the vertical labels
graph bar (asis) 系数, over(行业, relabel(`opt_relabel')) ytitle("系数") name(vbarvlbl, replace)

Like Example 3, this example uses graph bar's
suboption relabel(# "text" ...). Without linewrap,
the user can construct the syntax for this suboption manually.
However, in this case manual construction of the suboption syntax would be tedious,
as shown by displaying the text of the syntax with the following command.

*	The syntax for graph bar's relabel() option:

display `"`opt_relabel'"'

1 `" "农" "业" "采" "矿" "业""' 2 `" "制" "造" "业""' 3 `" "建" "筑" "业""' 4 `" "低" "端" "服" "务" "业""' 5 `" "高" "端" "服" "务" "业""' 6 `" "社" "会" "服" "务" "业""'

Example 5	Using option parse("pchars") to break lines at specific characters

With the option parse(","), linewrap parses the text on commas as well as on spaces.
Any line shorter than the maximum line length is wrapped at a comma.

. linewrap, longstr(We the People of the United States, in Order to form
a more perfect Union, establish Justice, insure domestic Tranquility, provide for
the common defence, promote the general Welfare, and secure the Blessings of Liberty
to ourselves and our Posterity, do ordain and establish this Constitution for the
United States of America.) display title(Example parsing on commas) linenumbers parse(",")

Example parsing on commas

1 2 3 4 5 6 7
1234567890123456789012345678901234567890123456789012345678901234567890123456789

1 We the People of the United States, in Order to form a more perfect Union,
2 establish Justice, insure domestic Tranquility, provide for the common
3 defence, promote the general Welfare,
4 and secure the Blessings of Liberty to ourselves and our Posterity,
5 do ordain and establish this Constitution for the United States of America.

The drafters of the US constitution followed the practice of capitalizing
important nouns. When we explicitly specify these capital letters
with the option parse("UJTWBLPC"), each line of the wrapped text begins
with one of these capital letters.

. linewrap, longstr(We the People of the United States, in Order to form
a more perfect Union, establish Justice, insure domestic Tranquility, provide for
the common defence, promote the general Welfare, and secure the Blessings of Liberty
to ourselves and our Posterity, do ordain and establish this Constitution for the
United States of America.) display title(Example parsing on capital letters)
linenumbers parse("UJTWBLPC")

Example parsing on capital letters

1 2 3 4 5 6 7
1234567890123456789012345678901234567890123456789012345678901234567890123456789

1 We the
2 People of the United States, in Order to form a more perfect
3 Union, establish
4 Justice, insure domestic
5 Tranquility, provide for the common defence, promote the general
6 Welfare, and secure the
7 Blessings of
8 Liberty to ourselves and our
9 Posterity, do ordain and establish this
10 Constitution for the
11 United States of America.

Adding the option lastpchar directs linewrap to break the line
at the last of the specified characters rather than the first.

. linewrap, longstr(We the People of the United States, in Order to form
a more perfect Union, establish Justice, insure domestic Tranquility, provide for
the common defence, promote the general Welfare, and secure the Blessings of Liberty
to ourselves and our Posterity, do ordain and establish this Constitution for the
United States of America.) display title(Example parsing on capital letters, with option -lastpchar-)
linenumbers parse("UJTWBLPC") lastpchar

Example parsing on capital letters, with option -lastpchar-

1 2 3 4 5 6 7
1234567890123456789012345678901234567890123456789012345678901234567890123456789

1 We the People of the United States, in Order to form a more perfect
2 Union, establish Justice, insure domestic
3 Tranquility, provide for the common defence, promote the general
4 Welfare, and secure the Blessings of Liberty to ourselves and our
5 Posterity, do ordain and establish this Constitution for the
6 United States of America.

The option parse("pchars") is useful for wrapping a file path
on folder delimiters.

. linewrap,
longstr("C:\Users\Mead\Documents\Work_Files\H\Methods_Data/STATA_Pgms/MeadFiles/skunkworx")
display title(Example parsing a filepath) linenumbers parse("/\") maxlength(20)

Example parsing a filepath

1 2
12345678901234567890

1 C:\Users\Mead
2 \Documents
3 \Work_Files\H
4 \Methods_Data
5 /STATA_Pgms
6 /MeadFiles
7 /skunkworx

Authors

Mead Over, Senior Fellow, Center for Global Development

Joao Pedro Azevedo, Lead Economist, World Bank

Email: MOver@CGDev.Org if you observe any problems.