mirror of
https://github.com/PowerShell/PSReadLine
synced 2026-06-08 12:12:13 +00:00
124 lines
4.5 KiB
C#
124 lines
4.5 KiB
C#
using System;
|
|
|
|
namespace Microsoft.PowerShell
|
|
{
|
|
public partial class PSConsoleReadLine
|
|
{
|
|
/// <summary>
|
|
/// Moves the cursor to the beginning of the first logical line
|
|
/// of a multi-line buffer.
|
|
/// </summary>
|
|
/// <param name="key" />
|
|
/// <param name="arg" />
|
|
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);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Moves the cursor to the beginning of the last logical logical line.
|
|
/// of a multi-line buffer.
|
|
/// </summary>
|
|
/// <param name="key" />
|
|
/// <param name="arg" />
|
|
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);
|
|
}
|
|
}
|
|
} |