public void HandleControlSequence(ControlSequence seq) { switch (seq.Type) { case ControlSequenceType.Home: { var diff = CurrentEditor.MoveHome(); terminal.CursorBackward(diff); } break; case ControlSequenceType.End: { var diff = CurrentEditor.MoveEnd(); terminal.CursorForward(diff); } break; case ControlSequenceType.LeftArrow: if (CurrentEditor.MoveCharacterBackward()) { terminal.CursorBackward(); } break; case ControlSequenceType.RightArrow: if (CurrentEditor.MoveCharacterForward()) { terminal.CursorForward(); } break; case ControlSequenceType.UpArrow: { if (mode == Mode.UserInput) { break; } if (!history.HasMoved) { history.SetCurrentCommand(CurrentEditor.Value); } var prev = history.PreviousCommand(); if (prev != null) { var len = CurrentEditor.Position; CurrentEditor.SetValue(prev); terminal.CursorBackward(len); terminal.ClearToTheEndOfLine(); terminal.Write(CurrentEditor.Value); } } break; case ControlSequenceType.DownArrow: { if (mode == Mode.UserInput) { break; } var cmd = history.NextCommand(); if (cmd != null) { var len = CurrentEditor.Position; CurrentEditor.SetValue(cmd); terminal.CursorBackward(len); terminal.ClearToTheEndOfLine(); terminal.Write(CurrentEditor.Value); } } break; case ControlSequenceType.Backspace: if (CurrentEditor.RemovePreviousCharacter()) { terminal.CursorBackward(); if (mode == Mode.Command || mode == Mode.UserInput) { terminal.ClearToTheEndOfLine(); terminal.WriteNoMove(CurrentEditor.ToString(CurrentEditor.Position)); } else if (mode == Mode.Search) { SearchPrompt.Recreate(terminal); history.Reset(); var result = history.ReverseSearch(search.Value); terminal.WriteNoMove(result, SearchPrompt.Skip); } } break; case ControlSequenceType.Delete: if (CurrentEditor.RemoveNextCharacter()) { if (mode == Mode.Command || mode == Mode.UserInput) { terminal.ClearToTheEndOfLine(); terminal.WriteNoMove(CurrentEditor.ToString(CurrentEditor.Position)); } else if (mode == Mode.Search) { SearchPrompt.Recreate(terminal); history.Reset(); var result = history.ReverseSearch(search.Value); terminal.WriteNoMove(result, SearchPrompt.Skip); } } break; case ControlSequenceType.CtrlLeftArrow: { var diff = CurrentEditor.MoveWordBackward(); terminal.CursorBackward(diff); } break; case ControlSequenceType.CtrlRightArrow: { var diff = CurrentEditor.MoveWordForward(); terminal.CursorForward(diff); } break; case ControlSequenceType.Ctrl: switch ((char)seq.Argument) { case 'c': if (mode == Mode.Command) { terminal.CursorForward(CurrentEditor.MoveEnd()); terminal.Write("^C"); terminal.NewLine(); } else { mode = Mode.Command; terminal.ClearLine(); } search.Clear(); command.Clear(); NormalPrompt.Write(terminal); history.Reset(); break; case 'r': if (mode == Mode.UserInput) { break; } else if (mode == Mode.Command) { mode = Mode.Search; terminal.CursorBackward(command.MoveHome()); terminal.ClearLine(); search.SetValue(string.Empty); command.Clear(); CurrentPrompt.Write(terminal); } else if (mode == Mode.Search) { if (search.Value != string.Empty) { var result = history.ReverseSearch(search.Value); terminal.CursorForward(SearchPrompt.Skip); terminal.ClearToTheEndOfLine(); terminal.WriteNoMove(result); terminal.CursorBackward(SearchPrompt.Skip); } } break; case 'w': { var diff = CurrentEditor.RemoveWord(); if (diff > 0) { terminal.CursorBackward(diff); if (mode == Mode.Command || mode == Mode.UserInput) { terminal.ClearToTheEndOfLine(); terminal.WriteNoMove(CurrentEditor.ToString(CurrentEditor.Position)); } else if (mode == Mode.Search) { SearchPrompt.Recreate(terminal); history.Reset(); var result = history.ReverseSearch(search.Value); terminal.WriteNoMove(result); } } } break; case 'k': CurrentEditor.RemoveToTheEnd(); if (mode == Mode.Command || mode == Mode.UserInput) { terminal.ClearToTheEndOfLine(); } else if (mode == Mode.Search) { SearchPrompt.Recreate(terminal); history.Reset(); var result = history.ReverseSearch(search.Value); terminal.WriteNoMove(result); } break; default: break; } break; case ControlSequenceType.Esc: if (mode == Mode.Search) { search.Clear(); command.SetValue(history.CurrentCommand ?? string.Empty); mode = Mode.Command; terminal.ClearLine(); NormalPrompt.Write(terminal); terminal.Write(command.Value); } break; case ControlSequenceType.Tab: if (mode == Mode.UserInput) { break; } else if (mode == Mode.Search) { mode = Mode.Command; CurrentEditor.SetValue(history.CurrentCommand); terminal.ClearLine(); CurrentPrompt.Write(terminal); terminal.Write(CurrentEditor.Value); } else if (mode == Mode.Command) { var sugs = handler.SuggestionNeeded(CurrentEditor.Value); var preparedBaseString = PreprocessSuggestionsInput(CurrentEditor.Value); var commonPrefix = Helper.CommonPrefix(sugs, preparedBaseString); var prefix = String.IsNullOrEmpty(commonPrefix) ? CurrentEditor.Value : commonPrefix; if (sugs.Length == 0) { break; } if (!tabTabMode || sugs.Length == 1) { tabTabMode = true; terminal.CursorBackward(CurrentEditor.Position); terminal.ClearToTheEndOfLine(); CurrentEditor.SetValue(prefix); } else if (tabTabMode) { terminal.NewLine(); var splitPoint = prefix.LastIndexOf(" ", StringComparison.Ordinal); foreach (var sug in sugs) { terminal.WriteRaw(string.Format(" {0}\r\n", sug.Substring(splitPoint + 1))); } CurrentEditor.SetValue(prefix); NormalPrompt.Write(terminal); } if (sugs.Length == 1 && sugs[0][sugs[0].Length - 1] != DirectorySeparatorChar) { CurrentEditor.InsertCharacter(' '); } terminal.Write(CurrentEditor.Value); return; } break; case ControlSequenceType.Enter: var wasInSearchMode = false; if (mode == Mode.Search) { mode = Mode.Command; command.SetValue(history.CurrentCommand ?? string.Empty); search.Clear(); terminal.ClearLine(); wasInSearchMode = true; } else { terminal.CursorForward(CurrentEditor.MoveEnd()); terminal.NewLine(); } if (CurrentEditor.Value != string.Empty) { if (wasInSearchMode) { NormalPrompt.Write(terminal); terminal.Write(command.Value); terminal.NewLine(); } var cmd = CurrentEditor.Value; while (true) { var interaction = handler.HandleCommand(cmd, null); if (interaction != null && interaction.QuitEnvironment) { terminal.Stop(); return; } CurrentEditor.Clear(); if (interaction != null && interaction.CommandToExecute != null) { cmd = interaction.CommandToExecute; terminal.Write(cmd); terminal.NewLine(); (interaction as CommandInteraction).Clear(); } else { break; } } } NormalPrompt.Write(terminal); if (CurrentEditor.Length > 0) { terminal.Write(CurrentEditor.Value); } history.Reset(); break; default: break; } tabTabMode = false; }