/********************************************************************++
Copyright (c) Microsoft Corporation. All rights reserved.
--********************************************************************/
using System.Collections.Generic;
using System.Management.Automation.Language;
namespace Microsoft.PowerShell
{
public partial class PSConsoleReadLine
{
private char _lastWordDelimiter = char.MinValue;
private bool _shouldAppend = false;
///
/// Returns the position of the beginning of the next word as delimited by white space and delimiters.
///
private int ViFindNextWordPoint(string wordDelimiters)
{
return ViFindNextWordPoint(_current, wordDelimiters);
}
///
/// Returns the position of the beginning of the next word as delimited by white space and delimiters.
///
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 bool IsPastEndOfLine(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;
}
///
/// Returns true of the character at the given position is white space.
///
private bool IsWhiteSpace(int i)
{
return char.IsWhiteSpace(_buffer[i]);
}
///
/// Returns the beginning of the current/next word as defined by wordDelimiters and whitespace.
///
private int ViFindPreviousWordPoint(string wordDelimiters)
{
return ViFindPreviousWordPoint(_current, wordDelimiters);
}
///
/// Returns the beginning of the current/next word as defined by wordDelimiters and whitespace.
///
/// Current cursor location.
/// Characters used to deliminate words.
/// Location of the beginning of the previous word.
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);
}
///
/// Knowing that you're starting with a word, find the previous start of the next word.
///
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;
}
///
/// Returns true if the cursor is on a word delimiter
///
private bool IsDelimiter(int i, string wordDelimiters)
{
return wordDelimiters.IndexOf(_buffer[i]) >= 0;
}
///
/// Returns true if is in the set of .
///
private bool IsDelimiter(char c, string wordDelimiters)
{
foreach (char delimiter in wordDelimiters)
{
if (c == delimiter)
{
return true;
}
}
return false;
}
///
/// Returns the cursor position of the beginning of the previous word when starting on a delimiter
///
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);
}
///
/// Returns the cursor position of the beginning of the previous word when starting on white space
///
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));
}
///
/// Returns the cursor position of the previous word, ignoring all delimiters other what white space
///
private int ViFindPreviousGlob()
{
int i = _current;
if (i == 0)
{
return 0;
}
i--;
return ViFindPreviousGlob(i);
}
///
/// Returns the cursor position of the previous word from i, ignoring all delimiters other what white space
///
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);
}
///
/// Finds the next work, using only white space as the word delimiter.
///
private int ViFindNextGlob()
{
int i = _current;
return ViFindNextGlob(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;
}
///
/// Finds the end of the current/next word as defined by whitespace.
///
private int ViFindEndOfGlob()
{
return ViFindGlobEnd(_current);
}
///
/// Find the end of the current/next word as defined by wordDelimiters and whitespace.
///
private int ViFindNextWordEnd(string wordDelimiters)
{
int i = _current;
return ViFindNextWordEnd(i, wordDelimiters);
}
///
/// Find the end of the current/next word as defined by wordDelimiters and whitespace.
///
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;
}
///
/// Return the last character in a white space defined word after skipping contiguous white space.
///
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);
}
}
}