/*
* TextUtilities.java - Various text functions
* Copyright (C) 1998, 2005 Slava Pestov
* :tabSize=4:indentSize=4:noTabs=false:
* :folding=explicit:collapseFolds=1:
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
package org.gjt.sp.jedit;
//{{{ Imports
import java.util.*;
import javax.swing.text.Segment;
import org.gjt.sp.jedit.buffer.JEditBuffer;
import org.gjt.sp.jedit.syntax.*;
import org.gjt.sp.util.StandardUtilities;
//}}}
/**
* Contains several text manipulation methods.
*
* <ul>
* <li>Bracket matching
* <li>Word start and end offset calculation
* <li>String comparison
* <li>Converting tabs to spaces and vice versa
* <li>Wrapping text
* <li>String case conversion
* </ul>
*
* @author Slava Pestov
* @version $Id$
*/
public class TextUtilities
{
// to avoid slowdown with large files; only scan 10000 lines either way
public static final int BRACKET_MATCH_LIMIT = 10000;
public static final int WHITESPACE = 0;
public static final int WORD_CHAR = 1;
public static final int SYMBOL = 2;
//{{{ getTokenAtOffset() method
/**
* Returns the token that contains the specified offset.
* @param tokens The token list
* @param offset The offset
* @since jEdit 4.0pre3
*/
public static Token getTokenAtOffset(Token tokens, int offset)
{
if(offset == 0 && tokens.id == Token.END)
return tokens;
for(;;)
{
if(tokens.id == Token.END)
throw new ArrayIndexOutOfBoundsException("offset > line length");
if(tokens.offset + tokens.length > offset)
return tokens;
else
tokens = tokens.next;
}
} //}}}
//{{{ getComplementaryBracket() method
/**
* Given an opening bracket, return the corresponding closing bracket
* and store true in <code>direction[0]</code>. Given a closing bracket,
* return the corresponding opening bracket and store false in
* <code>direction[0]</code>. Otherwise, return <code>\0</code>.
* @since jEdit 4.3pre2
*/
public static char getComplementaryBracket(char ch, boolean[] direction)
{
switch(ch)
{
case '(': if (direction != null) direction[0] = true; return ')';
case ')': if (direction != null) direction[0] = false; return '(';
case '[': if (direction != null) direction[0] = true; return ']';
case ']': if (direction != null) direction[0] = false; return '[';
case '{': if (direction != null) direction[0] = true; return '}';
case '}': if (direction != null) direction[0] = false; return '{';
case '<': if (direction != null) direction[0] = true; return '>';
case '>': if (direction != null) direction[0] = false; return '<';
case '«': if (direction != null) direction[0] = true; return '»';
case '»': if (direction != null) direction[0] = false; return '«';
case '‹': if (direction != null) direction[0] = true; return '›';
case '›': if (direction != null) direction[0] = false; return '‹';
case '⟨': if (direction != null) direction[0] = true; return '⟩';
case '⟩': if (direction != null) direction[0] = false; return '⟨';
case '⌈': if (direction != null) direction[0] = true; return '⌉';
case '⌉': if (direction != null) direction[0] = false; return '⌈';
case '⌊': if (direction != null) direction[0] = true; return '⌋';
case '⌋': if (direction != null) direction[0] = false; return '⌊';
case '⦇': if (direction != null) direction[0] = true; return '⦈';
case '⦈': if (direction != null) direction[0] = false; return '⦇';
case '⟦': if (direction != null) direction[0] = true; return '⟧';
case '⟧': if (direction != null) direction[0] = false; return '⟦';
case '⦃': if (direction != null) direction[0] = true; return '⦄';
case '⦄': if (direction != null) direction[0] = false; return '⦃';
default: return '\0';
}
} //}}}
//{{{ findMatchingBracket() method
/**
* Returns the offset of the bracket matching the one at the
* specified offset of the buffer, or -1 if the bracket is
* unmatched (or if the character is not a bracket).
* @param buffer The buffer
* @param line The line
* @param offset The offset within that line
* @since jEdit 2.6pre1
*/
public static int findMatchingBracket(JEditBuffer buffer, int line, int offset)
{
if(offset < 0 || offset >= buffer.getLineLength(line))
{
throw new ArrayIndexOutOfBoundsException(offset + ":"
+ buffer.getLineLength(line));
}
Segment lineText = new Segment();
buffer.getLineText(line,lineText);
char c = lineText.array[lineText.offset + offset];
// false - backwards, true - forwards
boolean[] direction = new boolean[1];
// corresponding character
char cprime = getComplementaryBracket(c,direction);
if( cprime == '\0' )
{ // c is no bracket
return -1;
}
// 1 because we've already 'seen' the first bracket
int count = 1;
DefaultTokenHandler tokenHandler = new DefaultTokenHandler();
buffer.markTokens(line,tokenHandler);
// Get the syntax token at 'offset'
// only tokens with the same type will be checked for
// the corresponding bracket
byte idOfBracket = getTokenAtOffset(tokenHandler.getTokens(),offset).id;
boolean haveTokens = true;
int startLine = line;
//{{{ Forward search
if(direction[0])
{
offset++;
for(;;)
{
for(int i = offset; i < lineText.count; i++)
{
char ch = lineText.array[lineText.offset + i];
if(ch == c)
{
if(!haveTokens)
{
tokenHandler.init();
buffer.markTokens(line,tokenHandler);
haveTokens = true;
}
if(getTokenAtOffset(tokenHandler.getTokens(),i).id == idOfBracket)
count++;
}
else if(ch == cprime)
{
if(!haveTokens)
{
tokenHandler.init();
buffer.markTokens(line,tokenHandler);
haveTokens = true;
}
if(getTokenAtOffset(tokenHandler.getTokens(),i).id == idOfBracket)
{
count--;
if(count == 0)
return buffer.getLineStartOffset(line) + i;
}
}
}
//{{{ Go on to next line
line++;
if(line >= buffer.getLineCount() || (line - startLine) > BRACKET_MATCH_LIMIT)
break;
buffer.getLineText(line,lineText);
offset = 0;
haveTokens = false;
//}}}
}
} //}}}
//{{{ Backward search
else
{
offset--;
for(;;)
{
for(int i = offset; i >= 0; i--)
{
char ch = lineText.array[lineText.offset + i];
if(ch == c)
{
if(!haveTokens)
{
tokenHandler.init();
buffer.markTokens(line,tokenHandler);
haveTokens = true;
}
if(getTokenAtOffset(tokenHandler.getTokens(),i).id == idOfBracket)
count++;
}
else if(ch == cprime)
{
if(!haveTokens)
{
tokenHandler.init();
buffer.markTokens(line,tokenHandler);
haveTokens = true;
}
if(getTokenAtOffset(tokenHandler.getTokens(),i).id == idOfBracket)
{
count--;
if(count == 0)
return buffer.getLineStartOffset(line) + i;
}
}
}
//{{{ Go on to previous line
line--;
if(line < 0 || (startLine - line) > BRACKET_MATCH_LIMIT)
break;
buffer.getLineText(line,lineText);
offset = lineText.count - 1;
haveTokens = false;
//}}}
}
} //}}}
// Nothing found
return -1;
} //}}}
//{{{ join() method
/** Similar to perl's join() method on lists,
* but works with all collections.
*
* @param c An iterable collection of Objects
* @param delim a string to put between each object
* @return a joined toString() representation of the collection
*
* @since jedit 4.3pre3
*/
public static String join(Collection<?> c, String delim)
{
StringBuilder retval = new StringBuilder();
Iterator<?> itr = c.iterator();
if (itr.hasNext())
retval.append( itr.next() );
else
return "";
while (itr.hasNext())
{
retval.append(delim);
retval.append(itr.next());
}
return retval.toString();
} //}}}
//{{{ findWordStart() methods
/**
* Locates the start of the word at the specified position.
* @param line The text
* @param pos The position
* @param noWordSep Characters that are non-alphanumeric, but
* should be treated as word characters anyway
*/
public static int findWordStart(String line, int pos, String noWordSep)
{
return findWordStart(line, pos, noWordSep, true, false);
}
/**
* Locates the start of the word at the specified position.
* @param line The text
* @param pos The position
* @param noWordSep Characters that are non-alphanumeric, but
* should be treated as word characters anyway
* @since jEdit 4.3pre15
*/
public static int findWordStart(CharSequence line,
int pos,
String noWordSep)
{
return findWordStart(line, pos, noWordSep, true, false, false);
}
/**
* Locates the start of the word at the specified position.
* @param line The text
* @param pos The position
* @param noWordSep Characters that are non-alphanumeric, but
* should be treated as word characters anyway
* @param joinNonWordChars Treat consecutive non-alphanumeric
* characters as one word
* @since jEdit 4.2pre5
*/
public static int findWordStart(String line, int pos, String noWordSep,
boolean joinNonWordChars)
{
return findWordStart(line,pos,noWordSep,joinNonWordChars,false);
}
/**
* Locates the start of the word at the specified position.
* @param line The text
* @param pos The position
* @param noWordSep Characters that are non-alphanumeric, but
* should be treated as word characters anyway
* @param joinNonWordChars Treat consecutive non-alphanumeric
* characters as one word
* @param eatWhitespace Include whitespace at start of word
* @since jEdit 4.1pre2
*/
public static int findWordStart(String line, int pos, String noWordSep,
boolean joinNonWordChars, boolean eatWhitespace)
{
return findWordStart(line, pos, noWordSep, joinNonWordChars,
false, eatWhitespace);
}
/**
* Locates the start of the word at the specified position.
* @param line The text
* @param pos The position
* @param noWordSep Characters that are non-alphanumeric, but
* should be treated as word characters anyway
* @param joinNonWordChars Treat consecutive non-alphanumeric
* characters as one word
* @param camelCasedWords Treat "camelCased" parts as words
* @param eatWhitespace Include whitespace at start of word
* @since jEdit 4.3pre10
*/
public static int findWordStart(String line, int pos, String noWordSep,
boolean joinNonWordChars, boolean camelCasedWords,
boolean eatWhitespace)
{
return findWordStart((CharSequence) line, pos, noWordSep,
joinNonWordChars, camelCasedWords,
eatWhitespace);
}
/**
* Locates the start of the word at the specified position.
* @param line The text
* @param pos The position
* @param noWordSep Characters that are non-alphanumeric, but
* should be treated as word characters anyway
* @param joinNonWordChars Treat consecutive non-alphanumeric
* characters as one word
* @param camelCasedWords Treat "camelCased" parts as words
* @param eatWhitespace Include whitespace at start of word
* @since jEdit 4.3pre15
*/
public static int findWordStart(CharSequence line,
int pos,
String noWordSep,
boolean joinNonWordChars,
boolean camelCasedWords,
boolean eatWhitespace)
{
return findWordStart(line, pos, noWordSep, joinNonWordChars, camelCasedWords, eatWhitespace, false);
}
/**
* Locates the start of the word at the specified position.
* @param line The text
* @param pos The position
* @param noWordSep Characters that are non-alphanumeric, but
* should be treated as word characters anyway
* @param joinNonWordChars Treat consecutive non-alphanumeric
* characters as one word
* @param camelCasedWords Treat "camelCased" parts as words
* @param eatWhitespace Include whitespace at start of word
* @param eatOnlyAfterWord Eat only whitespace after a word,
* in effect this finds actual word starts even if eating
* @since jEdit 4.4pre1
*/
public static int findWordStart(CharSequence line, int pos, String noWordSep,
boolean joinNonWordChars, boolean camelCasedWords,
boolean eatWhitespace, boolean eatOnlyAfterWord)
{
char ch = line.charAt(pos);
if(noWordSep == null)
noWordSep = "";
//{{{ the character under the cursor changes how we behave.
int type = getCharType(ch, noWordSep);
//}}}
for(int i = pos; i >= 0; i--)
{
char lastCh = ch;
ch = line.charAt(i);
switch(type)
{
//{{{ Whitespace...
case WHITESPACE:
// only select other whitespace in this case, unless eating only after words
if(Character.isWhitespace(ch))
break;
// word char or symbol; stop, unless eating only after words
else if (!eatOnlyAfterWord)
{
return i + 1;
}
// we have eaten after-word-whitespace and now continue until word start
else if (Character.isLetterOrDigit(ch) || noWordSep.indexOf(ch) != -1)
{
type = WORD_CHAR;
}
else
type = SYMBOL;
break; //}}}
//{{{ Word character...
case WORD_CHAR:
// stop at next last (in writing direction) upper case char if camel cased
// (don't stop at every upper case char, don't treat noWordSep as word chars)
if (camelCasedWords && Character.isUpperCase(ch) && !Character.isUpperCase(lastCh)
&& Character.isLetterOrDigit(lastCh))
{
return i;
}
// stop at next first (in writing direction) upper case char if camel cased
// (don't stop at every upper case char)
else if (camelCasedWords && !Character.isUpperCase(ch) && Character.isUpperCase(lastCh))
{
return i + 1;
}
// word char; keep going
else if(Character.isLetterOrDigit(ch) ||
noWordSep.indexOf(ch) != -1)
{
break;
}
// whitespace; include in word if eating, but not if only eating after word
else if(Character.isWhitespace(ch)
&& eatWhitespace && !eatOnlyAfterWord)
{
type = WHITESPACE;
break;
}
else
return i + 1; //}}}
//{{{ Symbol...
case SYMBOL:
if(!joinNonWordChars && pos != i)
return i + 1;
// whitespace; include in word if eating, but not if only eating after word
if(Character.isWhitespace(ch))
{
if(eatWhitespace && !eatOnlyAfterWord)
{
type = WHITESPACE;
break;
}
else
return i + 1;
}
else if(Character.isLetterOrDigit(ch) ||
noWordSep.indexOf(ch) != -1)
{
return i + 1;
}
else
{
break;
} //}}}
}
}
return 0;
} //}}}
//{{{ findWordEnd() methods
/**
* Locates the end of the word at the specified position.
* @param line The text
* @param pos The position
* @param noWordSep Characters that are non-alphanumeric, but
* should be treated as word characters anyway
*/
public static int findWordEnd(String line, int pos, String noWordSep)
{
return findWordEnd(line, pos, noWordSep, true);
}
/**
* Locates the end of the word at the specified position.
* @param line The text
* @param pos The position
* @param noWordSep Characters that are non-alphanumeric, but
* should be treated as word characters anyway
* @since jEdit 4.3pre15
*/
public static int findWordEnd(CharSequence line,
int pos,
String noWordSep)
{
return findWordEnd(line, pos, noWordSep, true, false, false);
}
/**
* Locates the end of the word at the specified position.
* @param line The text
* @param pos The position
* @param noWordSep Characters that are non-alphanumeric, but
* should be treated as word characters anyway
* @param joinNonWordChars Treat consecutive non-alphanumeric
* characters as one word
* @since jEdit 4.1pre2
*/
public static int findWordEnd(String line, int pos, String noWordSep,
boolean joinNonWordChars)
{
return findWordEnd(line,pos,noWordSep,joinNonWordChars,false);
}
/**
* Locates the end of the word at the specified position.
* @param line The text
* @param pos The position
* @param noWordSep Characters that are non-alphanumeric, but
* should be treated as word characters anyway
* @param joinNonWordChars Treat consecutive non-alphanumeric
* characters as one word
* @param eatWhitespace Include whitespace at end of word
* @since jEdit 4.2pre5
*/
public static int findWordEnd(String line, int pos, String noWordSep,
boolean joinNonWordChars, boolean eatWhitespace)
{
return findWordEnd(line, pos, noWordSep, joinNonWordChars,
false, eatWhitespace);
}
/**
* Locates the end of the word at the specified position.
* @param line The text
* @param pos The position
* @param noWordSep Characters that are non-alphanumeric, but
* should be treated as word characters anyway
* @param joinNonWordChars Treat consecutive non-alphanumeric
* characters as one word
* @param camelCasedWords Treat "camelCased" parts as words
* @param eatWhitespace Include whitespace at end of word
* @since jEdit 4.3pre10
*/
public static int findWordEnd(String line, int pos, String noWordSep,
boolean joinNonWordChars, boolean camelCasedWords,
boolean eatWhitespace)
{
return findWordEnd((CharSequence)line, pos, noWordSep,
joinNonWordChars, camelCasedWords,
eatWhitespace);
}
/**
* Locates the end of the word at the specified position.
* @param line The text
* @param pos The position
* @param noWordSep Characters that are non-alphanumeric, but
* should be treated as word characters anyway
* @param joinNonWordChars Treat consecutive non-alphanumeric
* characters as one word
* @param camelCasedWords Treat "camelCased" parts as words
* @param eatWhitespace Include whitespace at end of word
* @since jEdit 4.3pre15
*/
public static int findWordEnd(CharSequence line,
int pos,
String noWordSep,
boolean joinNonWordChars,
boolean camelCasedWords,
boolean eatWhitespace)
{
if(pos != 0)
pos--;
char ch = line.charAt(pos);
if(noWordSep == null)
noWordSep = "";
//{{{ the character under the cursor changes how we behave.
int type = getCharType(ch, noWordSep);
//}}}
for(int i = pos; i < line.length(); i++)
{
char lastCh = ch;
ch = line.charAt(i);
switch(type)
{
//{{{ Whitespace...
case WHITESPACE:
// only select other whitespace in this case
if(Character.isWhitespace(ch))
break;
else
return i; //}}}
//{{{ Word character...
case WORD_CHAR:
// stop at next last upper case char if camel cased
// (don't stop at every upper case char, don't treat noWordSep as word chars)
if (camelCasedWords && i > pos + 1 && !Character.isUpperCase(ch) && Character.isLetterOrDigit(ch)
&& Character.isUpperCase(lastCh))
{
return i - 1;
}
// stop at next first upper case char if camel caseg (don't stop at every upper case char)
else if (camelCasedWords && Character.isUpperCase(ch) && !Character.isUpperCase(lastCh))
{
return i;
}
else if(Character.isLetterOrDigit(ch) ||
noWordSep.indexOf(ch) != -1)
{
break;
}
// whitespace; include in word if eating
else if(Character.isWhitespace(ch)
&& eatWhitespace)
{
type = WHITESPACE;
break;
}
else
return i; //}}}
//{{{ Symbol...
case SYMBOL:
if(!joinNonWordChars && i != pos)
return i;
// if we see whitespace, set flag.
if(Character.isWhitespace(ch))
{
if(eatWhitespace)
{
type = WHITESPACE;
break;
}
else
return i;
}
else if(Character.isLetterOrDigit(ch) ||
noWordSep.indexOf(ch) != -1)
{
return i;
}
else
{
break;
} //}}}
}
}
return line.length();
} //}}}
//{{{ getCharType() method
/**
* Returns the type of the char.
*
* @param ch the character
* @param noWordSep Characters that are non-alphanumeric, but
* should be treated as word characters anyway, it must not be null
* @return the type of the char : {@link #WHITESPACE},
* {@link #WORD_CHAR}, {@link #SYMBOL}
* @since jEdit 4.4pre1
*/
public static int getCharType(char ch, String noWordSep)
{
int type;
if(Character.isWhitespace(ch))
type = WHITESPACE;
else if(Character.isLetterOrDigit(ch)
|| noWordSep.indexOf(ch) != -1)
type = WORD_CHAR;
else
type = SYMBOL;
return type;
} //}}}
//{{{ spacesToTabs() method
/**
* Converts consecutive spaces to tabs in the specified string.
* @param in The string
* @param tabSize The tab size
*/
public static String spacesToTabs(String in, int tabSize)
{
StringBuilder buf = new StringBuilder();
int width = 0;
int whitespace = 0;
for(int i = 0; i < in.length(); i++)
{
switch(in.charAt(i))
{
case ' ':
whitespace++;
width++;
break;
case '\t':
int tab = tabSize - (width % tabSize);
width += tab;
whitespace += tab;
break;
case '\n':
if(whitespace != 0)
{
buf.append(StandardUtilities
.createWhiteSpace(whitespace,tabSize,
width - whitespace));
}
whitespace = 0;
width = 0;
buf.append('\n');
break;
default:
if(whitespace != 0)
{
buf.append(StandardUtilities
.createWhiteSpace(whitespace,tabSize,
width - whitespace));
whitespace = 0;
}
buf.append(in.charAt(i));
width++;
break;
}
}
if(whitespace != 0)
{
buf.append(StandardUtilities.createWhiteSpace(whitespace,tabSize,
width - whitespace));
}
return buf.toString();
} //}}}
//{{{ tabsToSpaces() method
/**
* Converts tabs to consecutive spaces in the specified string.
* @param in The string
* @param tabSize The tab size
*/
public static String tabsToSpaces(String in, int tabSize)
{
StringBuilder buf = new StringBuilder();
int width = 0;
for(int i = 0; i < in.length(); i++)
{
switch(in.charAt(i))
{
case '\t':
int count = tabSize - (width % tabSize);
width += count;
while(--count >= 0)
buf.append(' ');
break;
case '\n':
width = 0;
buf.append(in.charAt(i));
break;
default:
width++;
buf.append(in.charAt(i));
break;
}
}
return buf.toString();
} //}}}
//{{{ format() method
/**
* Formats the specified text by merging and breaking lines to the
* specified width.
* @param text The text
* @param maxLineLength The maximum line length
* @param tabSize The tab size
*/
public static String format(String text, int maxLineLength, int tabSize)
{
StringBuilder buf = new StringBuilder();
int index = 0;
for(;;)
{
int newIndex = text.indexOf("\n\n",index);
if(newIndex == -1)
break;
formatParagraph(text.substring(index,newIndex),
maxLineLength,tabSize,buf);
buf.append("\n\n");
index = newIndex + 2;
}
if(index != text.length())
{
formatParagraph(text.substring(index),
maxLineLength,tabSize,buf);
}
return buf.toString();
} //}}}
//{{{ indexIgnoringWhitespace() method
/**
* Inverse of <code>ignoringWhitespaceIndex()</code>.
* @param str a string (not an empty string)
* @param index The index
* @return The number of non-whitespace characters that precede the index.
* @since jEdit 4.3pre2
*/
public static int indexIgnoringWhitespace(String str, int index)
{
int j = 0;
for(int i = 0; i < index; i++)
if(!Character.isWhitespace(str.charAt(i))) j++;
return j;
} //}}}
//{{{ ignoringWhitespaceIndex() method
/**
* Inverse of <code>indexIgnoringWhitespace()</code>.
* @param str a string (not an empty string)
* @param index The index
* @return The index into the string where the number of non-whitespace
* characters that precede the index is count.
* @since jEdit 4.3pre2
*/
public static int ignoringWhitespaceIndex(String str, int index)
{
int j = 0;
for(int i = 0;;i++)
{
if(!Character.isWhitespace(str.charAt(i))) j++;
if(j > index)
return i;
if(i == str.length() - 1)
return i + 1;
}
} //}}}
//{{{ getStringCase() methods
public static final int MIXED = 0;
public static final int LOWER_CASE = 1;
public static final int UPPER_CASE = 2;
public static final int TITLE_CASE = 3;
/**
* Returns if the specified string is all upper case, all lower case,
* or title case (first letter upper case, rest lower case).
* @param str The string
* @since jEdit 4.4pre1
*/
public static int getStringCase(CharSequence str)
{
if(str.length() == 0)
return MIXED;
int state = -1;
char ch = str.charAt(0);
if(Character.isLetter(ch))
{
if(Character.isUpperCase(ch))
state = UPPER_CASE;
else
state = LOWER_CASE;
}
for(int i = 1; i < str.length(); i++)
{
ch = str.charAt(i);
if(!Character.isLetter(ch))
continue;
switch(state)
{
case UPPER_CASE:
if(Character.isLowerCase(ch))
{
if(i == 1)
state = TITLE_CASE;
else
return MIXED;
}
break;
case LOWER_CASE:
case TITLE_CASE:
if(Character.isUpperCase(ch))
return MIXED;
break;
}
}
return state;
}
/**
* Returns if the specified string is all upper case, all lower case,
* or title case (first letter upper case, rest lower case).
* @param str The string
* @since jEdit 4.0pre1
*/
public static int getStringCase(String str)
{
return getStringCase((CharSequence) str);
} //}}}
//{{{ toTitleCase() method
/**
* Converts the specified string to title case, by capitalizing the
* first letter.
* @param str The string
* @since jEdit 4.0pre1
*/
public static String toTitleCase(String str)
{
if(str.length() == 0)
return str;
else
{
return Character.toUpperCase(str.charAt(0))
+ str.substring(1).toLowerCase();
}
} //}}}
//{{{ escapeText() method
/**
* Escapes a given string for use in a java.util.regex pattern.
* @since jEdit 4.5pre1
*/
public static String escapeText(String text)
{
// Make sure that every "\E" appearing in the text is escaped, and then
// surround it with the quotation tags \Q and \E.
String result = text.replace("\\E", "\\\\E");
return "\\Q" + result + "\\E";
} //}}}
//{{{ Private members
//{{{ formatParagraph() method
private static void formatParagraph(String text, int maxLineLength,
int tabSize, StringBuilder buf)
{
// align everything to paragraph's leading indent
int leadingWhitespaceCount = StandardUtilities.getLeadingWhiteSpace(text);
String leadingWhitespace = text.substring(0,leadingWhitespaceCount);
int leadingWhitespaceWidth = StandardUtilities.getLeadingWhiteSpaceWidth(text,tabSize);
buf.append(leadingWhitespace);
int lineLength = leadingWhitespaceWidth;
StringTokenizer st = new StringTokenizer(text);
while(st.hasMoreTokens())
{
String word = st.nextToken();
if(lineLength == leadingWhitespaceWidth)
{
// do nothing
}
else if(lineLength + word.length() + 1 > maxLineLength)
{
buf.append('\n');
buf.append(leadingWhitespace);
lineLength = leadingWhitespaceWidth;
}
else
{
buf.append(' ');
lineLength++;
}
buf.append(word);
lineLength += word.length();
}
} //}}}
//{{{ indexIgnoringWhitespace() method
public static void indexIgnoringWhitespace(String text, int maxLineLength,
int tabSize, StringBuffer buf)
{
// align everything to paragraph's leading indent
int leadingWhitespaceCount = StandardUtilities.getLeadingWhiteSpace(text);
String leadingWhitespace = text.substring(0,leadingWhitespaceCount);
int leadingWhitespaceWidth = StandardUtilities.getLeadingWhiteSpaceWidth(text,tabSize);
buf.append(leadingWhitespace);
int lineLength = leadingWhitespaceWidth;
StringTokenizer st = new StringTokenizer(text);
while(st.hasMoreTokens())
{
String word = st.nextToken();
if(lineLength == leadingWhitespaceWidth)
{
// do nothing
}
else if(lineLength + word.length() + 1 > maxLineLength)
{
buf.append('\n');
buf.append(leadingWhitespace);
lineLength = leadingWhitespaceWidth;
}
else
{
buf.append(' ');
lineLength++;
}
buf.append(word);
lineLength += word.length();
}
} //}}}
//}}}
}