зеркало из https://github.com/microsoft/DbgShell.git
Add CaStringUtil.IndentAndWrap swiss army knife function.
(not currently used anywhere)
This commit is contained in:
Родитель
f651cf18a2
Коммит
aefdc8a9b9
|
@ -626,6 +626,334 @@ namespace MS.Dbg
|
|||
return sb.ToString();
|
||||
}
|
||||
|
||||
[Flags]
|
||||
public enum IndentAndWrapOptions
|
||||
{
|
||||
Default = 0,
|
||||
NoWordBreaking = 0x01, // No characters (incl. spaces) are replaced with newlines
|
||||
TruncateInsteadOfWrap = 0x02,
|
||||
FirstLineAlreadyIndented = 0x04,
|
||||
DoNotIndentContinuationLines = 0x08, // Could also be named DoNotIndentWrapLines. Takes
|
||||
// precedence over AddLineLeadingSpaceToAddtlContinuationIndent.
|
||||
AddLineLeadingSpaceToAddtlContinuationIndent = 0x10, // TODO: could this result in a pathological situation if
|
||||
// leading space is longer than the entire outputWidth
|
||||
}
|
||||
|
||||
private const string c_PushAndReset = "\u009b56;0m";
|
||||
private const string c_StandalonePop = "\u009b57m";
|
||||
|
||||
public static string IndentAndWrap( string str,
|
||||
int outputWidth,
|
||||
IndentAndWrapOptions options,
|
||||
int indent,
|
||||
int addtlContinuationIndent )
|
||||
{
|
||||
bool truncate = 0 != (options & IndentAndWrapOptions.TruncateInsteadOfWrap);
|
||||
|
||||
int minContent = 2; // 1 char of content, and a newline char
|
||||
|
||||
if( truncate )
|
||||
{
|
||||
minContent = 3; // 1 char of content, 1 ellipsis char, and a newline char
|
||||
|
||||
if( addtlContinuationIndent != 0 )
|
||||
{
|
||||
throw new ArgumentException( "The combination of TruncateInsteadOfWrap and non-zero addtlContinuationIndent makes no sense." );
|
||||
}
|
||||
}
|
||||
|
||||
if( (indent + addtlContinuationIndent) > (outputWidth - minContent) )
|
||||
{
|
||||
throw new ArgumentOutOfRangeException(
|
||||
Util.Sprintf( "The outputWidth ({0}) should be somewhat larger than " +
|
||||
"the max possible indent ({1} + {2}).",
|
||||
outputWidth,
|
||||
indent,
|
||||
addtlContinuationIndent ),
|
||||
innerException: null );
|
||||
}
|
||||
|
||||
if( null == str )
|
||||
throw new ArgumentNullException( nameof( str ) );
|
||||
|
||||
StringBuilder sb = new StringBuilder( str.Length * 2 ); // just an estimate
|
||||
|
||||
int spaceToUse = outputWidth - indent - 1; // "- 1" because the newline actually uses a spot.
|
||||
|
||||
int srcIdx = 0;
|
||||
|
||||
int lastSpaceOrTabSrcIdx = -1;
|
||||
int lastSpaceOrTabDstIdx = -1;
|
||||
|
||||
// We may need to replace the last char of content (space or not) when
|
||||
// truncating (to put an ellipsis in its place).
|
||||
int lastContentDstIdx = -1;
|
||||
|
||||
bool inLeadingSpace = true;
|
||||
int leadingSpaceLen = 0;
|
||||
|
||||
// So that we don't need to inserts push/pops for plain text.
|
||||
bool haveSeenControlSequence = false;
|
||||
|
||||
bool pushInserted = false;
|
||||
|
||||
void _insertIndent( int numSpaces )
|
||||
{
|
||||
sb.Append( ' ', numSpaces );
|
||||
}
|
||||
|
||||
void _rememberLastSpaceOrTabIndexes()
|
||||
{
|
||||
lastSpaceOrTabSrcIdx = srcIdx;
|
||||
lastSpaceOrTabDstIdx = sb.Length;
|
||||
}
|
||||
|
||||
void _rememberLastContentIndex()
|
||||
{
|
||||
lastContentDstIdx = sb.Length;
|
||||
}
|
||||
|
||||
bool _weHaveConsumedAllAvailableOutputWidth()
|
||||
{
|
||||
return spaceToUse == 0;
|
||||
}
|
||||
|
||||
bool _backtrackToLastSpaceOrTab()
|
||||
{
|
||||
bool backtrackingAllowed = 0 == (options & IndentAndWrapOptions.NoWordBreaking);
|
||||
|
||||
if( backtrackingAllowed &&
|
||||
(lastSpaceOrTabSrcIdx > 0) ) // can't be 0, because we don't count leading space
|
||||
{
|
||||
Util.Assert( lastSpaceOrTabDstIdx >= 0 );
|
||||
srcIdx = lastSpaceOrTabSrcIdx;
|
||||
sb.Length = lastSpaceOrTabDstIdx;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool _stillInBounds()
|
||||
{
|
||||
return srcIdx < str.Length;
|
||||
}
|
||||
|
||||
// Returns true if srcIdx is still within the bounds of str.
|
||||
bool _consumeControlSequences()
|
||||
{
|
||||
while( _stillInBounds() && (str[ srcIdx ] == CSI) )
|
||||
{
|
||||
haveSeenControlSequence = true;
|
||||
int pastSeq = _SkipControlSequence( str, srcIdx ); // TODO: make _SkipControlSequence not assert if first char isn't CSI?
|
||||
sb.Append( str, srcIdx, pastSeq - srcIdx );
|
||||
srcIdx = pastSeq;
|
||||
}
|
||||
return _stillInBounds();
|
||||
}
|
||||
|
||||
void _saveAndResetSgrState()
|
||||
{
|
||||
if( haveSeenControlSequence && !pushInserted )
|
||||
{
|
||||
sb.Append( c_PushAndReset );
|
||||
pushInserted = true;
|
||||
}
|
||||
}
|
||||
|
||||
void _restoreSgrState()
|
||||
{
|
||||
if( haveSeenControlSequence )
|
||||
{
|
||||
Util.Assert( pushInserted );
|
||||
|
||||
sb.Append( c_StandalonePop );
|
||||
pushInserted = false;
|
||||
}
|
||||
}
|
||||
|
||||
void _completeLineAndIndent( int numSpaces, bool isWrap )
|
||||
{
|
||||
// Save the current SGR (color) state and (temporarily) reset to default,
|
||||
// if necessary.
|
||||
_saveAndResetSgrState();
|
||||
|
||||
sb.Append( '\n' );
|
||||
_insertIndent( numSpaces );
|
||||
|
||||
// Restore the SGR state.
|
||||
_restoreSgrState();
|
||||
|
||||
// Need to reset various counters/state:
|
||||
|
||||
spaceToUse = outputWidth - numSpaces - 1; // "- 1" because the newline actually uses a spot.
|
||||
|
||||
Util.Assert( !pushInserted );
|
||||
|
||||
lastSpaceOrTabSrcIdx = -1;
|
||||
lastSpaceOrTabDstIdx = -1;
|
||||
|
||||
// This should not be needed... but I'm doing it defensively.
|
||||
lastContentDstIdx = -1;
|
||||
|
||||
if( !isWrap )
|
||||
{
|
||||
// We're actually on the next line of input.
|
||||
inLeadingSpace = true;
|
||||
leadingSpaceLen = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void _appendContentChar( char c )
|
||||
{
|
||||
_rememberLastContentIndex();
|
||||
|
||||
if( Char.IsWhiteSpace( c ) )
|
||||
{
|
||||
if( !inLeadingSpace )
|
||||
{
|
||||
_rememberLastSpaceOrTabIndexes();
|
||||
}
|
||||
else
|
||||
{
|
||||
leadingSpaceLen++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
inLeadingSpace = false;
|
||||
}
|
||||
|
||||
sb.Append( c );
|
||||
spaceToUse--;
|
||||
}
|
||||
|
||||
// Returns 'true' if we actually found a newline; false if we hit the end of
|
||||
// the string first. Will preserve control sequences.
|
||||
bool _seekToNextLine()
|
||||
{
|
||||
while( _consumeControlSequences() )
|
||||
{
|
||||
char c = str[ srcIdx ];
|
||||
|
||||
if( c == '\r' )
|
||||
{
|
||||
// ignore it
|
||||
}
|
||||
else if( c == '\n' )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
srcIdx++;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
if( (options & IndentAndWrapOptions.FirstLineAlreadyIndented) == 0 )
|
||||
{
|
||||
_insertIndent( indent );
|
||||
}
|
||||
|
||||
while( _consumeControlSequences() )
|
||||
{
|
||||
// We consume control sequences in the "while" condition, so the
|
||||
// characters we consider here are purely content.
|
||||
|
||||
char c = str[ srcIdx ];
|
||||
|
||||
if( c == '\r' )
|
||||
{
|
||||
// ignore it
|
||||
}
|
||||
else if( c == '\n' )
|
||||
{
|
||||
// We consider the case of a newline char before the
|
||||
// _weHaveConsumedAllAvailableOutputWidth case, because the newline
|
||||
// does not consume available space (but rather resets it).
|
||||
|
||||
_completeLineAndIndent( indent, isWrap: false );
|
||||
}
|
||||
else if( _weHaveConsumedAllAvailableOutputWidth() )
|
||||
{
|
||||
// Need to decide where to put a newline... was there a space where we
|
||||
// could break up the line, or do we have to just chop right where we
|
||||
// are?
|
||||
|
||||
int totalIndent = indent;
|
||||
bool backtracked = false;
|
||||
|
||||
if( Char.IsWhiteSpace( c ) )
|
||||
{
|
||||
// So we can "backtrack" to it.
|
||||
_rememberLastSpaceOrTabIndexes();
|
||||
}
|
||||
|
||||
bool moreContentAfterTruncation = false;
|
||||
|
||||
if( truncate )
|
||||
{
|
||||
if( lastContentDstIdx == -1 )
|
||||
throw new Exception( "unexpected" );
|
||||
|
||||
// Note that we put the ellipsis /after/ resetting SGR (color)
|
||||
// state. This is a stylistic choice.
|
||||
|
||||
sb.Remove( lastContentDstIdx, 1 ); // make way for the ellipsis.
|
||||
|
||||
moreContentAfterTruncation = _seekToNextLine();
|
||||
|
||||
_saveAndResetSgrState();
|
||||
|
||||
sb.Append( (char) 0x2026 ); // ellipsis
|
||||
}
|
||||
else
|
||||
{
|
||||
bool doNotIndentContinuation = 0 != (options & IndentAndWrapOptions.DoNotIndentContinuationLines);
|
||||
|
||||
if( doNotIndentContinuation )
|
||||
totalIndent = 0;
|
||||
else
|
||||
totalIndent += addtlContinuationIndent;
|
||||
|
||||
// Could be a backtrack of 0 chars if the current char is a space.
|
||||
backtracked = _backtrackToLastSpaceOrTab();
|
||||
|
||||
if( !doNotIndentContinuation &&
|
||||
(options & IndentAndWrapOptions.AddLineLeadingSpaceToAddtlContinuationIndent) != 0 )
|
||||
{
|
||||
totalIndent += leadingSpaceLen;
|
||||
}
|
||||
}
|
||||
|
||||
if( !truncate || moreContentAfterTruncation )
|
||||
{
|
||||
_completeLineAndIndent( totalIndent, isWrap: !truncate );
|
||||
}
|
||||
else
|
||||
{
|
||||
// Don't forget the last POP.
|
||||
_restoreSgrState();
|
||||
}
|
||||
|
||||
if( !truncate && !backtracked )
|
||||
{
|
||||
// If we didn't backtrack, then we haven't yet accounted for the
|
||||
// current character--don't lose it!
|
||||
_appendContentChar( c );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_appendContentChar( c );
|
||||
}
|
||||
|
||||
srcIdx++;
|
||||
} // end while( still more str )
|
||||
|
||||
return sb.ToString();
|
||||
} // end _WordWrap()
|
||||
|
||||
|
||||
// TODO: theme support
|
||||
|
@ -800,6 +1128,60 @@ namespace MS.Dbg
|
|||
} // end class CaStringUtilStripTestCase
|
||||
|
||||
|
||||
private class CaStringUtilIndentAndWrapTestCase
|
||||
{
|
||||
public readonly string Input;
|
||||
public readonly int OutputWidth;
|
||||
public readonly IndentAndWrapOptions Options;
|
||||
public readonly int Indent;
|
||||
public readonly int AddtlContinuationIndent;
|
||||
|
||||
public readonly String ExpectedOutput;
|
||||
public readonly Type ExpectedExceptionType;
|
||||
|
||||
private CaStringUtilIndentAndWrapTestCase( string input,
|
||||
int outputWidth )
|
||||
{
|
||||
Input = input;
|
||||
OutputWidth = outputWidth;
|
||||
}
|
||||
|
||||
public CaStringUtilIndentAndWrapTestCase( string input,
|
||||
int outputWidth,
|
||||
string expectedOutput )
|
||||
: this( input, outputWidth )
|
||||
{
|
||||
ExpectedOutput = expectedOutput;
|
||||
}
|
||||
|
||||
public CaStringUtilIndentAndWrapTestCase( string input,
|
||||
int outputWidth,
|
||||
Type expectedExceptionType )
|
||||
: this( input, outputWidth )
|
||||
{
|
||||
ExpectedExceptionType = expectedExceptionType;
|
||||
}
|
||||
|
||||
/* public static string IndentAndWrap( string str,
|
||||
int outputWidth,
|
||||
IndentAndWrapOptions options,
|
||||
int indent,
|
||||
int addtlContinuationIndent ) */
|
||||
|
||||
public CaStringUtilIndentAndWrapTestCase( string input,
|
||||
int outputWidth,
|
||||
IndentAndWrapOptions options,
|
||||
int indent,
|
||||
int addtlContinuationIndent,
|
||||
string expectedOutput )
|
||||
: this( input, outputWidth, expectedOutput )
|
||||
{
|
||||
Options = options;
|
||||
Indent = indent;
|
||||
AddtlContinuationIndent = addtlContinuationIndent;
|
||||
}
|
||||
} // end class CaStringUtilIndentAndWrapTestCase
|
||||
|
||||
|
||||
|
||||
private static List< CaStringUtilLengthTestCase > sm_lengthTests = new List< CaStringUtilLengthTestCase >()
|
||||
|
@ -1255,6 +1637,140 @@ namespace MS.Dbg
|
|||
};
|
||||
|
||||
|
||||
private static List<CaStringUtilIndentAndWrapTestCase> sm_indentAndWrapTests = new List<CaStringUtilIndentAndWrapTestCase>()
|
||||
{
|
||||
/*
|
||||
*/
|
||||
new CaStringUtilIndentAndWrapTestCase( null,
|
||||
outputWidth: 4,
|
||||
typeof( ArgumentNullException ) ),
|
||||
|
||||
new CaStringUtilIndentAndWrapTestCase( "",
|
||||
outputWidth: 4,
|
||||
expectedOutput: "" ),
|
||||
|
||||
new CaStringUtilIndentAndWrapTestCase( "1 2 3 4 5 6 7 8 9",
|
||||
outputWidth: 4,
|
||||
expectedOutput: "1 2\n3 4\n5 6\n7 8\n9" ),
|
||||
|
||||
new CaStringUtilIndentAndWrapTestCase( " 1 2 3 4 5 6 7 8 9",
|
||||
outputWidth: 4,
|
||||
expectedOutput: " 1\n2 3\n4 5\n6 7\n8 9" ),
|
||||
|
||||
new CaStringUtilIndentAndWrapTestCase( "12 34 56 78 90",
|
||||
outputWidth: 4,
|
||||
expectedOutput: "12\n34\n56\n78\n90" ),
|
||||
|
||||
new CaStringUtilIndentAndWrapTestCase( " 12 34 56 78 90",
|
||||
outputWidth: 4,
|
||||
expectedOutput: " 12\n34\n56\n78\n90" ),
|
||||
|
||||
new CaStringUtilIndentAndWrapTestCase( "123 456 789 0ab",
|
||||
outputWidth: 4,
|
||||
expectedOutput: "123\n456\n789\n0ab" ),
|
||||
|
||||
new CaStringUtilIndentAndWrapTestCase( "1234 5678 90ab",
|
||||
outputWidth: 4,
|
||||
expectedOutput: "123\n4\n567\n8\n90a\nb" ),
|
||||
|
||||
new CaStringUtilIndentAndWrapTestCase( " 1 2 3 4 5 6 7 8 9",
|
||||
outputWidth: 4,
|
||||
options: IndentAndWrapOptions.AddLineLeadingSpaceToAddtlContinuationIndent,
|
||||
indent: 1,
|
||||
addtlContinuationIndent: 0,
|
||||
expectedOutput: " 1\n 2\n 3\n 4\n 5\n 6\n 7\n 8\n 9" ),
|
||||
|
||||
new CaStringUtilIndentAndWrapTestCase( "1 2 3 4 5 6 7 8 9",
|
||||
outputWidth: 4,
|
||||
options: IndentAndWrapOptions.Default,
|
||||
indent: 2,
|
||||
addtlContinuationIndent: 0,
|
||||
expectedOutput: " 1\n 2\n 3\n 4\n 5\n 6\n 7\n 8\n 9" ),
|
||||
|
||||
new CaStringUtilIndentAndWrapTestCase( " 1 2 3 4 5 6 7 8 9",
|
||||
outputWidth: 4,
|
||||
options: IndentAndWrapOptions.Default,
|
||||
indent: 2,
|
||||
addtlContinuationIndent: 0,
|
||||
expectedOutput: " \n 1\n 2\n 3\n 4\n 5\n 6\n 7\n 8\n 9" ),
|
||||
|
||||
new CaStringUtilIndentAndWrapTestCase( " 1 2 3 4 5 6 7 8 9",
|
||||
outputWidth: 4,
|
||||
options: IndentAndWrapOptions.NoWordBreaking,
|
||||
indent: 2,
|
||||
addtlContinuationIndent: 0,
|
||||
expectedOutput: " \n 1\n \n 2\n \n 3\n \n 4\n \n 5\n \n 6\n \n 7\n \n 8\n \n 9" ),
|
||||
|
||||
new CaStringUtilIndentAndWrapTestCase( "1 2 3 4 5 6 7 8 9",
|
||||
outputWidth: 4,
|
||||
options: IndentAndWrapOptions.FirstLineAlreadyIndented,
|
||||
indent: 2,
|
||||
addtlContinuationIndent: 0,
|
||||
expectedOutput: "1\n 2\n 3\n 4\n 5\n 6\n 7\n 8\n 9" ),
|
||||
|
||||
new CaStringUtilIndentAndWrapTestCase( "1 2\n3 4\n5 6\n7 8\n9",
|
||||
outputWidth: 4,
|
||||
options: IndentAndWrapOptions.Default,
|
||||
indent: 0,
|
||||
addtlContinuationIndent: 0,
|
||||
expectedOutput: "1 2\n3 4\n5 6\n7 8\n9" ),
|
||||
|
||||
new CaStringUtilIndentAndWrapTestCase( "1 2\n3 4\n5 6\n7 8\n9",
|
||||
outputWidth: 4,
|
||||
options: IndentAndWrapOptions.Default,
|
||||
indent: 1,
|
||||
addtlContinuationIndent: 0,
|
||||
expectedOutput: " 1\n 2\n 3\n 4\n 5\n 6\n 7\n 8\n 9" ),
|
||||
|
||||
new CaStringUtilIndentAndWrapTestCase( "1 2\n3 4\n5 6\n7 8\n9",
|
||||
outputWidth: 4,
|
||||
options: IndentAndWrapOptions.DoNotIndentContinuationLines,
|
||||
indent: 1,
|
||||
addtlContinuationIndent: 0,
|
||||
expectedOutput: " 1\n2\n 3\n4\n 5\n6\n 7\n8\n 9" ),
|
||||
|
||||
new CaStringUtilIndentAndWrapTestCase( " 1 2\n3 4\n5 6\n7 8\n9",
|
||||
outputWidth: 4,
|
||||
options: IndentAndWrapOptions.DoNotIndentContinuationLines |
|
||||
IndentAndWrapOptions.AddLineLeadingSpaceToAddtlContinuationIndent,
|
||||
indent: 1,
|
||||
addtlContinuationIndent: 0,
|
||||
expectedOutput: " 1\n2\n 3\n4\n 5\n6\n 7\n8\n 9" ),
|
||||
|
||||
new CaStringUtilIndentAndWrapTestCase( "1 2\n3 4\n5 6\n7 8\n9",
|
||||
outputWidth: 4,
|
||||
options: IndentAndWrapOptions.TruncateInsteadOfWrap,
|
||||
indent: 1,
|
||||
addtlContinuationIndent: 0,
|
||||
expectedOutput: " 1…\n 3…\n 5…\n 7…\n 9" ),
|
||||
|
||||
new CaStringUtilIndentAndWrapTestCase( "1 2\n\u009b91m3 4\n5 6\n7 8\u009bm\n9",
|
||||
outputWidth: 4,
|
||||
options: IndentAndWrapOptions.TruncateInsteadOfWrap,
|
||||
indent: 1,
|
||||
addtlContinuationIndent: 0,
|
||||
expectedOutput: $" 1…\n \u009b91m3{c_PushAndReset}…\n {c_StandalonePop}5{c_PushAndReset}…\n {c_StandalonePop}7\u009bm{c_PushAndReset}…\n {c_StandalonePop}9" ),
|
||||
};
|
||||
|
||||
|
||||
private static string _EscapeStringForDisplay( string s )
|
||||
{
|
||||
StringBuilder sb = new StringBuilder( s.Length * 2 );
|
||||
|
||||
foreach( char c in s )
|
||||
{
|
||||
if( c == CSI )
|
||||
sb.Append( @"\" ).Append( "u009b" );
|
||||
else if( c == '\r' )
|
||||
sb.Append( @"\" ).Append( 'r' );
|
||||
else if( c == '\n' )
|
||||
sb.Append( @"\" ).Append( 'n' );
|
||||
else
|
||||
sb.Append( c );
|
||||
}
|
||||
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
|
||||
public static void SelfTest()
|
||||
|
@ -1422,6 +1938,7 @@ namespace MS.Dbg
|
|||
}
|
||||
} // end foreach( testCase )
|
||||
|
||||
|
||||
if( 0 == stripFailures )
|
||||
{
|
||||
Console.WriteLine( "CaStringUtil StripControlSequences tests passed." );
|
||||
|
@ -1433,6 +1950,55 @@ namespace MS.Dbg
|
|||
|
||||
failures += stripFailures;
|
||||
|
||||
|
||||
int indentAndWrapFailures = 0;
|
||||
for( int i = 0; i < sm_indentAndWrapTests.Count; i++ )
|
||||
{
|
||||
var testCase = sm_indentAndWrapTests[ i ];
|
||||
try
|
||||
{
|
||||
string output = IndentAndWrap( testCase.Input,
|
||||
testCase.OutputWidth,
|
||||
testCase.Options,
|
||||
testCase.Indent,
|
||||
testCase.AddtlContinuationIndent );
|
||||
|
||||
if( 0 != String.CompareOrdinal( output, testCase.ExpectedOutput ) )
|
||||
{
|
||||
indentAndWrapFailures++;
|
||||
Console.WriteLine( "indentAndWrap test case {0} failed.\n Expected: {1}\n Actual: {2}\n",
|
||||
i,
|
||||
_EscapeStringForDisplay( testCase.ExpectedOutput ),
|
||||
_EscapeStringForDisplay( output ) );
|
||||
}
|
||||
}
|
||||
catch( Exception e )
|
||||
{
|
||||
if( e.GetType() != testCase.ExpectedExceptionType )
|
||||
{
|
||||
indentAndWrapFailures++;
|
||||
Console.WriteLine( "IndentAndWrap Test case {0} failed. Expected exception type: {1}, Actual: {2}.",
|
||||
i,
|
||||
null == testCase.ExpectedExceptionType ?
|
||||
"<none>" :
|
||||
testCase.ExpectedExceptionType.Name,
|
||||
e.GetType().Name );
|
||||
}
|
||||
}
|
||||
} // end foreach( testCase )
|
||||
|
||||
if( 0 == indentAndWrapFailures )
|
||||
{
|
||||
Console.WriteLine( "CaStringUtil IndentAndWrap tests passed." );
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine( "CaStringUtil IndentAndWrap tests failed ({0} failures).", indentAndWrapFailures );
|
||||
}
|
||||
|
||||
failures += indentAndWrapFailures;
|
||||
|
||||
|
||||
if( 0 == failures )
|
||||
{
|
||||
Console.WriteLine( "All CaStringUtil tests passed." );
|
||||
|
|
Загрузка…
Ссылка в новой задаче