/// <summary> /// Delete to the end of the line. /// </summary> public static void DeleteToEnd(ConsoleKeyInfo?key = null, object arg = null) { if (_singleton._current >= _singleton._buffer.Length) { Ding(); return; } var lineCount = _singleton.GetLogicalLineCount(); var lineIndex = _singleton.GetLogicalLineNumber() - 1; if (TryGetArgAsInt(arg, out var requestedLineCount, 1)) { var targetLineIndex = lineIndex + requestedLineCount - 1; if (targetLineIndex >= lineCount) { targetLineIndex = lineCount - 1; } var startPosition = _singleton._current; var endPosition = GetEndOfNthLogicalLinePos(targetLineIndex); var length = endPosition - startPosition + 1; if (length > 0) { _clipboard.Record(_singleton._buffer, startPosition, length); _singleton.SaveEditItem(EditItemDelete.Create( _clipboard, _singleton._current, DeleteToEnd, arg)); _singleton._buffer.Remove(_singleton._current, length); // the cursor will go back one character, unless at the beginning of the line var endOfLineCursorPos = GetEndOfLogicalLinePos(_singleton._current) - 1; var beginningOfLinePos = GetBeginningOfLinePos(_singleton._current); _singleton._current = Math.Max( beginningOfLinePos, Math.Min(_singleton._current, endOfLineCursorPos)); _singleton.Render(); } } }
/// <summary> /// Joins the current line and the next line. /// </summary> public static void ViJoinLines(ConsoleKeyInfo?key = null, object arg = null) { _singleton.MoveToEndOfPhrase(); if (_singleton.IsAtEndOfLine(_singleton._current)) { Ding(); } else { _singleton._buffer[_singleton._current] = ' '; _singleton._groupUndoHelper.StartGroup(ViJoinLines, arg); _singleton.SaveEditItem(EditItemDelete.Create("\n", _singleton._current)); _singleton.SaveEditItem(EditItemInsertChar.Create(' ', _singleton._current)); _singleton._groupUndoHelper.EndGroup(); _singleton.Render(); } }
/// <summary> /// Delete the character under the cursor. /// </summary> public static void DeleteChar(ConsoleKeyInfo?key = null, object arg = null) { if (_singleton._visualSelectionCommandCount > 0) { int start, length; _singleton.GetRegion(out start, out length); Delete(start, length); return; } if (_singleton._buffer.Length > 0 && _singleton._current < _singleton._buffer.Length) { _singleton.SaveEditItem( EditItemDelete.Create(new string(_singleton._buffer[_singleton._current], 1), _singleton._current)); _singleton._buffer.Remove(_singleton._current, 1); _singleton.Render(); } }
/// <summary> /// Delete to the end of the line. /// </summary> public static void DeleteToEnd(ConsoleKeyInfo?key = null, object arg = null) { if (_singleton._current >= _singleton._buffer.Length) { Ding(); return; } _singleton._clipboard = _singleton._buffer.ToString(_singleton._current, _singleton._buffer.Length - _singleton._current); _singleton.SaveEditItem(EditItemDelete.Create( _singleton._clipboard, _singleton._current, DeleteToEnd, arg )); _singleton._buffer.Remove(_singleton._current, _singleton._buffer.Length - _singleton._current); _singleton._current = _singleton._buffer.Length - 1; _singleton.Render(); }
/// <summary> /// Replaces the current character with the next character typed. /// </summary> private static void ReplaceCharInPlace(ConsoleKeyInfo?key, object arg) { ConsoleKeyInfo nextKey = ReadKey(); if (_singleton._buffer.Length > 0 && nextKey.KeyChar > 0 && nextKey.Key != ConsoleKey.Escape && nextKey.Key != ConsoleKey.Enter) { _singleton.StartEditGroup(); _singleton.SaveEditItem(EditItemDelete.Create(_singleton._buffer[_singleton._current].ToString(), _singleton._current)); _singleton.SaveEditItem(EditItemInsertString.Create(nextKey.KeyChar.ToString(), _singleton._current)); _singleton.EndEditGroup(); _singleton._buffer[_singleton._current] = nextKey.KeyChar; _singleton.Render(); } else { Ding(); } }
private void Kill(int start, int length, bool prepend) { if (length > 0) { var killText = _buffer.ToString(start, length); SaveEditItem(EditItemDelete.Create(killText, start)); _buffer.Remove(start, length); _current = start; Render(); if (_killCommandCount > 0) { if (prepend) { _killRing[_killIndex] = killText + _killRing[_killIndex]; } else { _killRing[_killIndex] += killText; } } else { if (_killRing.Count < Options.MaximumKillRingCount) { _killRing.Add(killText); _killIndex = _killRing.Count - 1; } else { _killIndex += 1; if (_killIndex == _killRing.Count) { _killIndex = 0; } _killRing[_killIndex] = killText; } } } _killCommandCount += 1; }
/// <summary> /// Replace current buffer with the selected list item text. /// The replacement is done in a way that allows further selection updates for the same list view /// to override the previous update in the undo/redo stack, so that 'undo' always get back to the /// original user input that triggers the current list view. /// </summary> private static void ReplaceSelection(string selectedItemText) { var insertStringItem = EditItemInsertString.Create(selectedItemText, position: 0); insertStringItem.Replaceable = true; if (_singleton.IsLastEditItemReplaceable) { _singleton.SaveEditItem(insertStringItem); _singleton._buffer.Clear(); _singleton._buffer.Append(selectedItemText); _singleton._current = selectedItemText.Length; _singleton.Render(); return; } bool useEditGroup = _singleton._editGroupStart == -1; if (useEditGroup) { _singleton.StartEditGroup(); } var str = _singleton._buffer.ToString(); _singleton.SaveEditItem(EditItemDelete.Create(str, position: 0)); _singleton._buffer.Clear(); _singleton.SaveEditItem(insertStringItem); _singleton._buffer.Append(selectedItemText); _singleton._current = selectedItemText.Length; if (useEditGroup) { _singleton.EndEditGroup(); // Instigator is needed for VI undo _singleton.Render(); } }
/// <summary> /// Replace some text at the given position. Supports undo. /// </summary> /// <param name="start">The start position to replace</param> /// <param name="length">The length to replace</param> /// <param name="replacement">The replacement text</param> /// <param name="instigator">The action that initiated the replace (used for undo)</param> /// <param name="instigatorArg">The argument to the action that initiated the replace (used for undo)</param> public static void Replace(int start, int length, string replacement, Action <ConsoleKeyInfo?, object> instigator = null, object instigatorArg = null) { if (start < 0 || start > _singleton._buffer.Length) { throw new ArgumentException(PSReadLineResources.StartOutOfRange, nameof(start)); } if (length > (_singleton._buffer.Length - start) || length < 0) { throw new ArgumentException(PSReadLineResources.ReplacementLengthInvalid, nameof(length)); } bool useEditGroup = (_singleton._editGroupStart == -1); if (useEditGroup) { _singleton.StartEditGroup(); } var str = _singleton._buffer.ToString(start, length); _singleton.SaveEditItem(EditItemDelete.Create(str, start)); _singleton._buffer.Remove(start, length); if (replacement != null) { _singleton.SaveEditItem(EditItemInsertString.Create(replacement, start)); _singleton._buffer.Insert(start, replacement); _singleton._current = start + replacement.Length; } else { _singleton._current = start; } if (useEditGroup) { _singleton.EndEditGroup(instigator, instigatorArg); // Instigator is needed for VI undo _singleton.Render(); } }
/// <summary> /// Invert the case of the current character and move to the next one. /// </summary> public static void InvertCase(ConsoleKeyInfo?key = null, object arg = null) { if (_singleton._current >= _singleton._buffer.Length) { Ding(); return; } int qty = arg as int? ?? 1; for (; qty > 0 && _singleton._current < _singleton._buffer.Length; qty--) { char c = _singleton._buffer[_singleton._current]; if (Char.IsLetter(c)) { char newChar = Char.IsUpper(c) ? Char.ToLower(c, CultureInfo.CurrentCulture) : char.ToUpper(c, CultureInfo.CurrentCulture); EditItem delEditItem = EditItemDelete.Create( c.ToString(), _singleton._current, InvertCase, arg, moveCursorToEndWhenUndo: false); EditItem insEditItem = EditItemInsertChar.Create(newChar, _singleton._current); _singleton.SaveEditItem(GroupedEdit.Create(new List <EditItem> { delEditItem, insEditItem }, InvertCase, arg )); _singleton._buffer[_singleton._current] = newChar; } _singleton.MoveCursor(Math.Min(_singleton._current + 1, _singleton._buffer.Length)); } _singleton.Render(); }
/// <summary> /// Deletes text from the cursor position to the specified end position /// but does not put the deleted text in the kill ring. /// </summary> /// <param name="endPosition">0-based offset to one character past the end of the text.</param> private static void ForwardDeleteImpl(int endPosition, Action <ConsoleKeyInfo?, object> instigator) { var current = _singleton._current; var buffer = _singleton._buffer; if (buffer.Length > 0 && current < endPosition) { int length = endPosition - current; var str = buffer.ToString(current, length); _singleton.SaveEditItem( EditItemDelete.Create( str, current, instigator, instigatorArg: null, !InViEditMode())); buffer.Remove(current, length); _singleton.Render(); } }
/// <summary> /// Swap the current character and the one before it. /// </summary> public static void SwapCharacters(ConsoleKeyInfo?key = null, object arg = null) { if (_singleton._current <= 0 || _singleton._current >= _singleton._buffer.Length) { Ding(); return; } char current = _singleton._buffer[_singleton._current]; char previous = _singleton._buffer[_singleton._current - 1]; _singleton.StartEditGroup(); _singleton.SaveEditItem(EditItemDelete.Create(_singleton._buffer.ToString(_singleton._current - 1, 2), _singleton._current - 1)); _singleton.SaveEditItem(EditItemInsertChar.Create(current, _singleton._current - 1)); _singleton.SaveEditItem(EditItemInsertChar.Create(previous, _singleton._current)); _singleton.EndEditGroup(); _singleton._buffer[_singleton._current] = previous; _singleton._buffer[_singleton._current - 1] = current; _singleton._current = Math.Min(_singleton._current + 1, _singleton._buffer.Length - 1); _singleton.PlaceCursor(); _singleton.Render(); }
/// <summary> /// Delete to the end of the word. /// </summary> public static void ViDeleteEndOfGlob(ConsoleKeyInfo?key = null, object arg = null) { int qty = (arg is int) ? (int)arg : 1; int endPoint = _singleton._current; for (int i = 0; i < qty; i++) { endPoint = _singleton.ViFindGlobEnd(endPoint); } _singleton.SaveToClipboard(_singleton._current, 1 + endPoint - _singleton._current); _singleton.SaveEditItem(EditItemDelete.Create( _singleton._clipboard, _singleton._current, ViDeleteEndOfGlob, arg )); _singleton._buffer.Remove(_singleton._current, 1 + endPoint - _singleton._current); if (_singleton._current >= _singleton._buffer.Length) { _singleton._current = _singleton._buffer.Length - 1; } _singleton.Render(); }
private void DeleteCharImpl(bool orExit) { if (_visualSelectionCommandCount > 0) { int start, length; GetRegion(out start, out length); Delete(start, length); return; } if (_buffer.Length > 0) { if (_current < _buffer.Length) { SaveEditItem(EditItemDelete.Create(new string(_buffer[_current], 1), _current)); _buffer.Remove(_current, 1); Render(); } } else if (orExit) { throw new ExitException(); } }
private static void ViReplaceUntilEsc(ConsoleKeyInfo?key, object arg) { if (_singleton._current >= _singleton._buffer.Length) { Ding(); return; } int startingCursor = _singleton._current; StringBuilder deletedStr = new StringBuilder(); ConsoleKeyInfo nextKey = ReadKey(); while (!nextKey.EqualsNormalized(Keys.Escape) && !nextKey.EqualsNormalized(Keys.Enter)) { if (nextKey.EqualsNormalized(Keys.Backspace)) { if (_singleton._current == startingCursor) { Ding(); } else { if (deletedStr.Length == _singleton._current - startingCursor) { _singleton._buffer[_singleton._current - 1] = deletedStr[deletedStr.Length - 1]; deletedStr.Remove(deletedStr.Length - 1, 1); } else { _singleton._buffer.Remove(_singleton._current - 1, 1); } _singleton._current--; _singleton.Render(); } } else { if (_singleton._current >= _singleton._buffer.Length) { _singleton._buffer.Append(nextKey.KeyChar); } else { deletedStr.Append(_singleton._buffer[_singleton._current]); _singleton._buffer[_singleton._current] = nextKey.KeyChar; } _singleton._current++; _singleton.Render(); } nextKey = ReadKey(); } if (_singleton._current > startingCursor) { _singleton.StartEditGroup(); string insStr = _singleton._buffer.ToString(startingCursor, _singleton._current - startingCursor); _singleton.SaveEditItem(EditItemDelete.Create(deletedStr.ToString(), startingCursor)); _singleton.SaveEditItem(EditItemInsertString.Create(insStr, startingCursor)); _singleton.EndEditGroup(); } if (nextKey.EqualsNormalized(Keys.Enter)) { ViAcceptLine(nextKey); } }