/// <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> public static void Replace(int start, int length, string replacement) { if (start < 0 || start > _singleton._buffer.Length) { throw new ArgumentException(PSReadLineResources.StartOutOfRange, "start"); } if (length > (_singleton._buffer.Length - start)) { throw new ArgumentException(PSReadLineResources.ReplacementLengthTooBig, "length"); } _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; } _singleton.EndEditGroup(); _singleton.Render(); }
void UpdateHistoryFromFile(IEnumerable <string> historyLines, bool fromDifferentSession) { var sb = new StringBuilder(); foreach (var line in historyLines) { if (line.EndsWith("`")) { sb.Append(line, 0, line.Length - 1); sb.Append('\n'); } else if (sb.Length > 0) { sb.Append(line); var l = sb.ToString(); var editItems = new List <EditItem> { EditItemInsertString.Create(l, 0) }; MaybeAddToHistory(l, editItems, 1, /*readingHistoryFile*/ true, fromDifferentSession); sb.Clear(); } else { var editItems = new List <EditItem> { EditItemInsertString.Create(line, 0) }; MaybeAddToHistory(line, editItems, 1, /*readingHistoryFile*/ true, fromDifferentSession); } } }
/// <summary> /// Replaces the current character with the next character typed. /// </summary> private static void ReplaceCharInPlace(ConsoleKeyInfo?key, object arg) { var nextKey = ReadKey(); if (_singleton._buffer.Length > 0 && nextKey.KeyStr.Length == 1) { _singleton.StartEditGroup(); _singleton.SaveEditItem(EditItemDelete.Create( _singleton._buffer[_singleton._current].ToString(), _singleton._current, ReplaceCharInPlace, arg, moveCursorToEndWhenUndo: false)); _singleton.SaveEditItem(EditItemInsertString.Create(nextKey.KeyStr, _singleton._current)); _singleton.EndEditGroup(); _singleton._buffer[_singleton._current] = nextKey.KeyChar; _singleton.Render(); } else { Ding(); } }
/// <summary> /// Add a command to the history - typically used to restore /// history from a previous session. /// </summary> public static void AddToHistory(string command) { command = command.Replace("\r\n", "\n"); var editItems = new List <EditItem> { EditItemInsertString.Create(command, 0) }; _singleton.MaybeAddToHistory(command, editItems, 1, readingHistoryFile: false, fromDifferentSession: false); }
/// <summary> /// Add a command to the history - typically used to restore /// history from a previous session. /// </summary> public static void AddToHistory(string command) { command = command.Replace("\r\n", "\n"); var editItems = new List <EditItem> { EditItemInsertString.Create(command, 0) }; _singleton.MaybeAddToHistory(command, editItems, 1); }
/// <summary> /// Insert a string at the current position. Supports undo. /// </summary> /// <param name="s">String to insert</param> public static void Insert(string s) { _singleton.SaveEditItem(EditItemInsertString.Create(s, _singleton._current)); // Use Append if possible because Insert at end makes StringBuilder quite slow. if (_singleton._current == _singleton._buffer.Length) { _singleton._buffer.Append(s); } else { _singleton._buffer.Insert(_singleton._current, s); } _singleton._current += s.Length; _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(); } }
/// <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(); } }
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); } }