using System;
namespace Microsoft.PowerShell
{
public partial class PSConsoleReadLine
{
///
/// Moves the cursor to the beginning of the first logical line
/// of a multi-line buffer.
///
///
///
public void MoveToFirstLine(ConsoleKeyInfo? key = null, object arg = null)
{
if (!LineIsMultiLine())
{
Ding(key, arg);
return;
}
var currentLine = GetLogicalLineNumber();
var pos = ConvertOffsetToPoint(_singleton._current);
pos.Y -= currentLine -1;
var newCurrent = ConvertLineAndColumnToOffset(pos);
var position = GetBeginningOfLinePos(newCurrent);
_singleton.MoveCursor(position);
}
///
/// Moves the cursor to the beginning of the last logical logical line.
/// of a multi-line buffer.
///
///
///
public void MoveToLastLine(ConsoleKeyInfo? key = null, object arg = null)
{
var count = GetLogicalLineCount();
if (count == 1)
{
Ding(key, arg);
return;
}
var currentLine = GetLogicalLineNumber();
var pos = ConvertOffsetToPoint(_singleton._current);
pos.Y += (count - currentLine);
var newCurrent = ConvertLineAndColumnToOffset(pos);
var position = GetBeginningOfLinePos(newCurrent);
_singleton.MoveCursor(position);
}
private void ViMoveToLine(int lineOffset)
{
// When moving up or down in a buffer in VI mode
// the cursor wants to be positioned at a desired column number, which is:
// - either a specified column number, the 0-based offset from the start of the logical line.
// - or the end of the line
//
// Only one of those desired position is available at any given time.
//
// If the desired column number is specified, the cursor will be positioned at
// the specified offset in the target logical line, or at the end of the line as appropriate.
// The fact that a logical line is shorter than the desired column number *does not*
// change its value. If a subsequent move to another logical line is performed, the
// desired column number will take effect.
//
// If the desired column number is the end of the line, the cursor will be positioned at
// the end of the target logical line.
const int endOfLine = int.MaxValue;
_moveToLineCommandCount += 1;
// if this is the first "move to line" command
// record the desired column number from the current position
// on the logical line
if (_moveToLineCommandCount == 1 && _moveToLineDesiredColumn == -1)
{
var startOfLine = GetBeginningOfLinePos(_current);
_moveToLineDesiredColumn = _current - startOfLine;
}
// Nothing needs to be done when:
// - actually not moving the line, or
// - moving the line down when it's at the end of the last logical line.
if (lineOffset == 0 || (lineOffset > 0 && _current == _buffer.Length))
{
return;
}
int targetLineOffset;
var currentLineIndex = _singleton.GetLogicalLineNumber() - 1;
if (lineOffset < 0)
{
targetLineOffset = Math.Max(0, currentLineIndex + lineOffset);
}
else
{
var lastLineIndex = _singleton.GetLogicalLineCount() - 1;
targetLineOffset = Math.Min(lastLineIndex, currentLineIndex + lineOffset);
}
var startOfTargetLinePos = GetBeginningOfNthLinePos(targetLineOffset);
var endOfTargetLinePos = GetEndOfLogicalLinePos(startOfTargetLinePos);
var newCurrent = _moveToLineDesiredColumn == endOfLine
? endOfTargetLinePos
: Math.Min(startOfTargetLinePos + _moveToLineDesiredColumn, endOfTargetLinePos);
MoveCursor(newCurrent);
}
}
}