protected override void OnPreviewKeyDown(KeyEventArgs e) { if (_suggestionList.IsVisible && e.Key.In(Key.Tab, Key.Enter, Key.Return)) { var selectedItem = (Suggestion)_suggestionList.SelectedItem; if (selectedItem != null) { var selectedText = selectedItem.Completion; var index = CaretIndex; Text = Text.Insert(CaretIndex, selectedText); CaretIndex = index + selectedText.Length; } HideSuggestionList(); e.Handled = true; return; } if (e.Key == Key.Escape) { HideSuggestionList(); e.Handled = true; } if (ShouldShowSuggestionList(e)) { SyntaxParser.FindSuggestions(Text, SelectionStart); ShowSuggestionList(); e.Handled = true; } if (e.Key == Key.Tab && e.KeyboardDevice.Modifiers == ModifierKeys.Shift) { // with selected text if (SelectedText != string.Empty) { string[] lines = SelectedText.SplitLines(); for (int ii = 0; ii < lines.Length; ii++) { if (lines[ii].StartsWith(Tab)) { lines[ii] = lines[ii].Substring(Tab.Length); } else { lines[ii] = lines[ii].TrimStart(' '); } } SelectedText = String.Join(Environment.NewLine, lines); } else { var index = CaretIndex; var lastLine = Text.LastIndexOf(Environment.NewLine, index, StringComparison.Ordinal); if (lastLine == -1) { lastLine = Text.Length - 1; } var startLine = Text.IndexOf(Environment.NewLine, lastLine, StringComparison.Ordinal); if (startLine != -1) { startLine += Environment.NewLine.Length; } else { startLine = 0; } // find empty spaces var spaces = 0; for (var i = startLine; i < Text.Length - 1; i++) { if (Text[i] == ' ') { spaces++; } else { break; } } if (spaces > TabSize) { spaces = TabSize; } Text = Text.Remove(startLine, spaces); // set position of caret if (index >= startLine + spaces) { CaretIndex = index - spaces; } else if (index >= startLine && index < startLine + spaces) { CaretIndex = startLine; } else { CaretIndex = index; } } e.Handled = true; } // tab if (e.Key == Key.Tab && e.KeyboardDevice.Modifiers == ModifierKeys.None) { if (SelectedText == string.Empty) { var caretPosition = CaretIndex; Text = Text.Insert(caretPosition, Tab); CaretIndex = caretPosition + TabSize; } else { if (!SelectedText.Contains(Environment.NewLine)) { SelectedText = Tab; } else { SelectedText = Tab + SelectedText.Replace(Environment.NewLine, Environment.NewLine + Tab); } } e.Handled = true; } // enter respects indenting if (e.Key == Key.Return) { var index = CaretIndex; var lastLine = Text.LastIndexOf(Environment.NewLine, index, StringComparison.Ordinal); var spaces = 0; if (lastLine != -1) { var line = Text.Substring(lastLine, Text.Length - lastLine); var startLine = line.IndexOf(Environment.NewLine, StringComparison.Ordinal); if (startLine != -1) { line = line.Substring(startLine).TrimStart('\r', '\n'); } foreach (var c in line) { if (c == ' ') { spaces++; } else { break; } } } Text = Text.Insert(index, Environment.NewLine + new String(' ', spaces)); CaretIndex = index + Environment.NewLine.Length + spaces; e.Handled = true; } base.OnPreviewKeyDown(e); }