Files

460 lines
13 KiB
C#

/********************************************************************++
Copyright (c) Microsoft Corporation. All rights reserved.
--********************************************************************/
namespace Microsoft.PowerShell
{
public partial class PSConsoleReadLine
{
private char _lastWordDelimiter = char.MinValue;
private bool _shouldAppend;
/// <summary>
/// Returns the position of the beginning of the next word as delimited by white space and delimiters.
/// </summary>
private int ViFindNextWordPoint(string wordDelimiters)
{
return ViFindNextWordPoint(_current, wordDelimiters);
}
/// <summary>
/// Returns the position of the beginning of the next word as delimited by white space and delimiters.
/// </summary>
private int ViFindNextWordPoint(int i, string wordDelimiters)
{
if (IsAtEndOfLine(i))
{
return i;
}
if (InWord(i, wordDelimiters))
{
return ViFindNextWordFromWord(i, wordDelimiters);
}
if (IsDelimiter(i, wordDelimiters))
{
return ViFindNextWordFromDelimiter(i, wordDelimiters);
}
return ViFindNextWordFromWhiteSpace(i, wordDelimiters);
}
private int ViFindNextWordFromWhiteSpace(int i, string wordDelimiters)
{
while (!IsAtEndOfLine(i) && IsWhiteSpace(i))
{
i++;
}
return i;
}
private int ViFindNextWordFromDelimiter(int i, string wordDelimiters)
{
while (!IsAtEndOfLine(i) && IsDelimiter(i, wordDelimiters))
{
i++;
}
if (IsAtEndOfLine(i))
{
if (IsDelimiter(i, wordDelimiters))
{
_shouldAppend = true;
return i + 1;
}
return i;
}
while (!IsAtEndOfLine(i) && IsWhiteSpace(i))
{
i++;
}
return i;
}
private bool IsAtEndOfLine(int i)
{
return i >= (_buffer.Length - 1);
}
private int ViFindNextWordFromWord(int i, string wordDelimiters)
{
while (!IsAtEndOfLine(i) && InWord(i, wordDelimiters))
{
i++;
}
if (IsAtEndOfLine(i) && InWord(i, wordDelimiters))
{
_shouldAppend = true;
return i + 1;
}
if (IsDelimiter(i, wordDelimiters))
{
_lastWordDelimiter = _buffer[i];
return i;
}
while (!IsAtEndOfLine(i) && IsWhiteSpace(i))
{
i++;
}
if (IsAtEndOfLine(i) && !InWord(i, wordDelimiters))
{
return i + 1;
}
_lastWordDelimiter = _buffer[i-1];
return i;
}
/// <summary>
/// Returns true of the character at the given position is white space.
/// </summary>
private bool IsWhiteSpace(int i)
{
// Treat just beyond the end of buffer as whitespace because
// it looks like whitespace to the user even though they haven't
// entered a character yet.
return i >= _buffer.Length || char.IsWhiteSpace(_buffer[i]);
}
/// <summary>
/// Returns the beginning of the current/next word as defined by wordDelimiters and whitespace.
/// </summary>
private int ViFindPreviousWordPoint(string wordDelimiters)
{
return ViFindPreviousWordPoint(_current, wordDelimiters);
}
/// <summary>
/// Returns the beginning of the current/previous word as defined by wordDelimiters and whitespace.
/// </summary>
/// <param name="i">Current cursor location.</param>
/// <param name="wordDelimiters">Characters used to delimit words.</param>
/// <returns>Location of the beginning of the previous word.</returns>
private int ViFindPreviousWordPoint(int i, string wordDelimiters)
{
if (i == 0)
{
return i;
}
if (IsWhiteSpace(i))
{
return FindPreviousWordFromWhiteSpace(i, wordDelimiters);
}
else if (InWord(i, wordDelimiters))
{
return FindPreviousWordFromWord(i, wordDelimiters);
}
return FindPreviousWordFromDelimiter(i, wordDelimiters);
}
/// <summary>
/// Knowing that you're starting with a word, find the previous start of the next word.
/// </summary>
private int FindPreviousWordFromWord(int i, string wordDelimiters)
{
i--;
if (InWord(i, wordDelimiters))
{
while (i > 0 && InWord(i, wordDelimiters))
{
i--;
}
if (i == 0 && InWord(i, wordDelimiters))
{
return i;
}
return i + 1;
}
if (IsWhiteSpace(i))
{
while (i > 0 && IsWhiteSpace(i))
{
i--;
}
if (i == 0)
{
return i;
}
if (InWord(i, wordDelimiters) && InWord(i-1, wordDelimiters))
{
return FindPreviousWordFromWord(i, wordDelimiters);
}
if (IsDelimiter(i - 1, wordDelimiters))
{
FindPreviousWordFromDelimiter(i, wordDelimiters);
}
return i;
}
while (i > 0 && IsDelimiter(i, wordDelimiters))
{
i--;
}
if (i == 0 && IsDelimiter(i, wordDelimiters))
{
return i;
}
return i + 1;
}
/// <summary>
/// Returns true if the cursor is on a word delimiter
/// </summary>
private bool IsDelimiter(int i, string wordDelimiters)
{
return wordDelimiters.IndexOf(_buffer[i]) >= 0;
}
/// <summary>
/// Returns true if <paramref name="c"/> is in the set of <paramref name="wordDelimiters"/>.
/// </summary>
private bool IsDelimiter(char c, string wordDelimiters)
{
foreach (char delimiter in wordDelimiters)
{
if (c == delimiter)
{
return true;
}
}
return false;
}
/// <summary>
/// Returns the cursor position of the beginning of the previous word when starting on a delimiter
/// </summary>
private int FindPreviousWordFromDelimiter(int i, string wordDelimiters)
{
i--;
if (IsDelimiter(i, wordDelimiters))
{
while (i > 0 && IsDelimiter(i, wordDelimiters))
{
i--;
}
if (i == 0 && !IsDelimiter(i, wordDelimiters))
{
return i + 1;
}
if (!IsWhiteSpace(i))
{
return i + 1;
}
return i;
}
return ViFindPreviousWordPoint(i, wordDelimiters);
}
/// <summary>
/// Returns the cursor position of the beginning of the previous word when starting on white space
/// </summary>
private int FindPreviousWordFromWhiteSpace(int i, string wordDelimiters)
{
while (IsWhiteSpace(i) && i > 0)
{
i--;
}
int j = i - 1;
if (j < 0 || !InWord(i, wordDelimiters) || char.IsWhiteSpace(_buffer[j]))
{
return i;
}
return ViFindPreviousWordPoint(i, wordDelimiters);
}
/// <summary>
/// Returns the cursor position of the previous word from i, ignoring all delimiters other what white space
/// </summary>
private int ViFindPreviousGlob(int i)
{
if (i <= 0)
{
return 0;
}
if (!IsWhiteSpace(i))
{
while (i > 0 && !IsWhiteSpace(i))
{
i--;
}
if (!IsWhiteSpace(i))
{
return i;
}
return i + 1;
}
while (i > 0 && IsWhiteSpace(i))
{
i--;
}
if (i == 0)
{
return i;
}
return ViFindPreviousGlob(i);
}
private int ViFindNextGlob(int i)
{
if (i >= _buffer.Length)
{
return i;
}
while (!IsAtEndOfLine(i) && !IsWhiteSpace(i))
{
i++;
}
if (IsAtEndOfLine(i) && !IsWhiteSpace(i))
{
return i + 1;
}
while (!IsAtEndOfLine(i) && IsWhiteSpace(i))
{
i++;
}
if (IsAtEndOfLine(i) && IsWhiteSpace(i))
{
return i + 1;
}
return i;
}
/// <summary>
/// Finds the end of the current/next word as defined by whitespace.
/// </summary>
private int ViFindEndOfGlob()
{
return ViFindGlobEnd(_current);
}
/// <summary>
/// Find the end of the current/next word as defined by wordDelimiters and whitespace.
/// </summary>
private int ViFindNextWordEnd(string wordDelimiters)
{
int i = _current;
return ViFindNextWordEnd(i, wordDelimiters);
}
/// <summary>
/// Find the end of the current/next word as defined by wordDelimiters and whitespace.
/// </summary>
private int ViFindNextWordEnd(int i, string wordDelimiters)
{
if (IsAtEndOfLine(i))
{
return i;
}
if (IsDelimiter(i, wordDelimiters) && !IsDelimiter(i + 1, wordDelimiters))
{
i++;
if (IsAtEndOfLine(i))
{
return i;
}
}
else if (InWord(i, wordDelimiters) && !InWord(i + 1, wordDelimiters))
{
i++;
if (IsAtEndOfLine(i))
{
return i;
}
}
while (!IsAtEndOfLine(i) && IsWhiteSpace(i))
{
i++;
}
if (IsAtEndOfLine(i))
{
return i;
}
if (IsDelimiter(i, wordDelimiters))
{
while (!IsAtEndOfLine(i) && IsDelimiter(i, wordDelimiters))
{
i++;
}
if (!IsDelimiter(i, wordDelimiters))
{
return i - 1;
}
}
else
{
while (!IsAtEndOfLine(i) && InWord(i, wordDelimiters))
{
i++;
}
if (!InWord(i, wordDelimiters))
{
return i - 1;
}
}
return i;
}
/// <summary>
/// Return the last character in a white space defined word after skipping contiguous white space.
/// </summary>
private int ViFindGlobEnd(int i)
{
if (IsAtEndOfLine(i))
{
return i;
}
i++;
if (IsAtEndOfLine(i))
{
return i;
}
while (!IsAtEndOfLine(i) && IsWhiteSpace(i))
{
i++;
}
if (IsAtEndOfLine(i))
{
return i;
}
while (!IsAtEndOfLine(i) && !IsWhiteSpace(i))
{
i++;
}
if (IsWhiteSpace(i))
{
return i - 1;
}
return i;
}
private int ViFindEndOfPreviousGlob()
{
int i = _current;
return ViFindEndOfPreviousGlob(i);
}
private int ViFindEndOfPreviousGlob(int i)
{
if (IsWhiteSpace(i))
{
while (i > 0 && IsWhiteSpace(i))
{
i--;
}
return i;
}
while (i > 0 && !IsWhiteSpace(i))
{
i--;
}
return ViFindEndOfPreviousGlob(i);
}
}
}