|
|
“Replacement for Frontier's string.wrap function” |
|||
| From: | Seth Dillingham | In Response To: | Top of Thread. |
| Date Posted: | Sunday, March 19, 2006 11:18:44 PM | Replies: | 0 |
| Enclosures: | None. | ||
Frontier's string.wrap is a nearly useless verb, and is weird because it does the opposite of what its name suggests: it actually unwraps a wrapped string. In other words, you pass in a message, like an email with hard returns at the end of every line, and it strips out the hard returns within the paragraphs and leaves the double-spaced paragraphs alone.
So, string.wrap( "arbrcr\rd" ) returns "a b cr\rd".
I'm rewriting it in a way that maintains backwards compatibility but adds the following features:
The first version is script-based, just because it's a little easier to write. When I know it is correct, I'm going to port it to the kernel.
It seems to be working correctly for me, but I'd really appreciate it if a few more people would look it over before I kernelize it! Post your comments here, or send them to me in email.
First, of course, you need the script. You can , or just copy-and-paste it (from the very end of this page) into your own copy of Frontier. Testing instructions follow:
Note that the current version returns a string with mac line endings.
Period. It wouldn't be difficult to use the current platform's endings, or
to let you specify which line endings to use when you call the script, but
this is good enough for now. (If you're on windows, run the results through
string.replaceAll( wrapped, cr, "r\n" ) after calling
workspace.stringWrap()).
«2006/03/19 by Seth Dillingham.
«Description:
«Re-wrap a string to any maximum width-per-line.
«2+ returns in a row are treated as a paragraph break and are maintained.
«Optionally indents all lines in a paragraph according to the indentation of the first line of that paragraph.
«Parameters:
«s [string]: the string to be re-wrapped
«maxWidth [number]: (infinity) the maximum width of each line in the final output
«flKeepIndent [boolean]: (false) should all lines in a paragraph have the same indent as the first line?
«Return:
«[string]: the re-wrapped string
«Errors:
«
«Revisions:
«
«~~~~~~~~~~~~~~~~~~~~~~~~
on stringWrap( s, maxWidth = infinity, flKeepIndent = false ) {
local ( tabSpaces = 4 );
local ( i = 1, ct = 0 );
local ( lastspace = 0 );
local ( sz = 0, indentsz = 0 );
local ( nextline = "", nextSpace = "", indent = "" );
local ( output = "" );
on addBlankLines( ixStart ) {
local ( ix, ctFound = 0 );
for ( ix = ixStart to sz ) {
if ( s[ ix ] == cr ) {
ctFound++}
else {
break}};
if ( ix < sz ) {
output = output + string.filledString( indent + cr, ctfound );};
i = i + ctFound;
return ix};
on getIndent( ixStart ) {
local ( ix = ixStart );
local ( isz = 0 );
while ( ix <= sz ) {
case s[ ix ] {
' ' {
ix++;
isz++};
tab {
ix++;
isz = isz + ( tabSpaces - ( isz % tabSpaces ) )}}
else {
break}};
indentsz = isz;
indent = string.mid( s, ixStart, ix - ixStart );
lastSpace = ix - 1;
return ix};
on addWordToNextLine( ) {
local ( nextwhite = lastspace );
while ( i <= sz ) {
case s[ i ] {
' ';
tab;
cr;
lf {
nextwhite = i;
break}}
else {
i++}};
if ( ct + ( i - lastspace - 1 ) > maxWidth ) {
if ( ct > indentsz ) { // ct has one or more words, so we don't include this word
i = lastSpace + 1;
return false}};
nextline = nextline + ( nextspace + string.mid( s, lastspace + 1, i - lastspace - 1 ) );
ct = ct + ( i - lastspace - 1 );
lastspace = nextwhite;
return ( i < sz )};
on skipAllWhitespace( ixStart ) {
local ( ix = ixStart );
while ( ix < sz ) {
case s[ ix ] {
' ';
cr;
lf;
tab {
ix++}}
else {
break}};
return ix};
on addSpaceToNextLine( startIx, adrFlParaBreak ) {
local ( ix = startix );
local ( ctSpaces = 0, space = "" );
while ( ( ix < sz ) and ( ct < maxWidth ) ) {
case s[ ix ] {
' ' {
ix++;
ctSpaces++;
space = space + ' ';};
cr {
if ( s[ ix + 1 ] == cr ) {
adrFlParaBreak^ = true;
i = ix;
return false}
else { // skip remaining white space
if ( ctSpaces == 0 ) { // add one space if nothing else was found yet
ix++;
ctSpaces++;
space = space + ' '};
ix = skipAllWhitespace( ix )}};
tab {
ix++;
ctSpaces = ctSpaces + ( tabSpaces - ( ct + ctSpaces ) % tabSpaces );
space = space + tab}}
else {
break}};
if ( ( ( ix <= sz ) and ( s[ ix ] == cr ) ) or ( ct >= maxWidth ) ) { // skip remaining white space
while ( ix < sz ) {
case s[ ix ] {
' ';
tab {
ix++};
cr {
if ( s[ ix + 1 ] == cr ) {
adrFlParaBreak^ = true;
i = ix;
return false}
else {
break}}}
else {
break}}};
if ( ct + ctSpaces >= maxWidth ) {
nextSpace = ""; // FIX ME ?
i = ix;
return false}
else {
lastspace = ix - 1;
nextSpace = space;
ct = ct + ctSpaces;
i = ix;
return true}};
on getNextLine() {
local ( flParaBreak = false );
nextline = indent;
nextspace = "";
ct = indentsz;
loop {
if ( not addWordToNextLine( ) ) {
break};
if ( not addSpaceToNextLine( i, @flParaBreak ) ) {
break}};
output = output + ( nextline + cr );;
if ( i >= sz ) {
return false}
else {
return not flParaBreak}};
on getNextParagraph() {
i = getIndent( i );
loop {
if ( not getNextLine() ) {
if ( i >= sz ) {
return false}
else {
break}}};
addBlankLines( ++i );
return true};
bundle { // init
if ( maxWidth < 1 ) {
ScriptError( "maxWidth must be greater than or equal to 1" )};
s = string.replaceAll( string.replaceAll( s, "r\n", cr ), lf, cr );
sz = sizeof( s )};
loop {
if ( not getNextParagraph() ) {
break};
if ( i >= sz ) {
break}};
return output};
bundle { // test code
local ( wrapWidth = 60 );
local ( unwrapped, wrapped );
unwrapped = clipboard.getValue( stringType );
wrapped = stringWrap( unwrapped, wrapWidth, true );
clipboard.putValue( wrapped )}
«wp.newTextObject( wrapped, @temp.wrapped )
«window.open( @temp.wrapped )
There are no trackbacks.
|
TruerWords
is Seth Dillingham's personal web site. Truer words were never spoken. |