protected virtual Action <TextEditorData> GetInsertAction(Gdk.Key key, Gdk.ModifierType modifier) { return(ViActionMaps.GetInsertKeyAction(key, modifier) ?? ViActionMaps.GetDirectionKeyAction(key, modifier)); }
protected override void HandleKeypress(Gdk.Key key, uint unicodeKey, Gdk.ModifierType modifier) { // Reset on Esc, Ctrl-C, Ctrl-[ if (key == Gdk.Key.Escape) { if (currentMacro != null) { // Record Escapes into the macro since it actually does something ViMacro.KeySet toAdd = new ViMacro.KeySet(); toAdd.Key = key; toAdd.Modifiers = modifier; toAdd.UnicodeKey = unicodeKey; currentMacro.KeysPressed.Enqueue(toAdd); } Reset(string.Empty); return; } else if (((key == Gdk.Key.c || key == Gdk.Key.bracketleft) && (modifier & Gdk.ModifierType.ControlMask) != 0)) { Reset(string.Empty); if (currentMacro != null) { // Otherwise remove the macro from the pool macros.Remove(currentMacro.MacroCharacter); currentMacro = null; } return; } else if (currentMacro != null && !((char)unicodeKey == 'q' && modifier == Gdk.ModifierType.None)) { ViMacro.KeySet toAdd = new ViMacro.KeySet(); toAdd.Key = key; toAdd.Modifiers = modifier; toAdd.UnicodeKey = unicodeKey; currentMacro.KeysPressed.Enqueue(toAdd); } Action <TextEditorData> action = null; bool lineAction = false; switch (state) { case State.Unknown: Reset(string.Empty); goto case State.Normal; case State.Normal: if (((modifier & (Gdk.ModifierType.ControlMask)) == 0)) { if (key == Gdk.Key.Delete) { unicodeKey = 'x'; } switch ((char)unicodeKey) { case '?': case '/': case ':': state = State.Command; commandBuffer.Append((char)unicodeKey); Status = commandBuffer.ToString(); return; case 'A': RunAction(CaretMoveActions.LineEnd); goto case 'i'; case 'I': RunAction(CaretMoveActions.LineFirstNonWhitespace); goto case 'i'; case 'a': //use CaretMoveActions so that we can move past last character on line end RunAction(CaretMoveActions.Right); goto case 'i'; case 'i': Caret.Mode = CaretMode.Insert; Status = "-- INSERT --"; state = State.Insert; return; case 'R': Caret.Mode = CaretMode.Underscore; Status = "-- REPLACE --"; state = State.Replace; return; case 'V': Status = "-- VISUAL LINE --"; Data.SetSelectLines(Caret.Line, Caret.Line); state = State.VisualLine; return; case 'v': Status = "-- VISUAL --"; state = State.Visual; RunAction(ViActions.VisualSelectionFromMoveAction(ViActions.Right)); return; case 'd': Status = "d"; state = State.Delete; return; case 'y': Status = "y"; state = State.Yank; return; case 'Y': state = State.Yank; HandleKeypress(Gdk.Key.y, (int)'y', Gdk.ModifierType.None); return; case 'O': RunAction(ViActions.NewLineAbove); goto case 'i'; case 'o': RunAction(ViActions.NewLineBelow); goto case 'i'; case 'r': Caret.Mode = CaretMode.Underscore; Status = "-- REPLACE --"; state = State.WriteChar; return; case 'c': Caret.Mode = CaretMode.Insert; Status = "c"; state = State.Change; return; case 'x': if (Data.Caret.Column == Data.Document.GetLine(Data.Caret.Line).Length + 1) { return; } Status = string.Empty; if (!Data.IsSomethingSelected) { RunActions(SelectionActions.FromMoveAction(CaretMoveActions.Right), ClipboardActions.Cut); } else { RunAction(ClipboardActions.Cut); } ViActions.RetreatFromLineEnd(Data); return; case 'X': if (Data.Caret.Column == DocumentLocation.MinColumn) { return; } Status = string.Empty; if (!Data.IsSomethingSelected && 0 < Caret.Offset) { RunActions(SelectionActions.FromMoveAction(CaretMoveActions.Left), ClipboardActions.Cut); } else { RunAction(ClipboardActions.Cut); } return; case 'D': RunActions(SelectionActions.FromMoveAction(CaretMoveActions.LineEnd), ClipboardActions.Cut); return; case 'C': RunActions(SelectionActions.FromMoveAction(CaretMoveActions.LineEnd), ClipboardActions.Cut); goto case 'i'; case '>': Status = ">"; state = State.Indent; return; case '<': Status = "<"; state = State.Unindent; return; case 'n': Search(); return; case 'N': searchBackward = !searchBackward; Search(); searchBackward = !searchBackward; return; case 'p': PasteAfter(false); return; case 'P': PasteBefore(false); return; case 's': if (!Data.IsSomethingSelected) { RunAction(SelectionActions.FromMoveAction(CaretMoveActions.Right)); } RunAction(ClipboardActions.Cut); goto case 'i'; case 'S': if (!Data.IsSomethingSelected) { RunAction(SelectionActions.LineActionFromMoveAction(CaretMoveActions.LineEnd)); } else { Data.SetSelectLines(Data.MainSelection.Anchor.Line, Data.Caret.Line); } RunAction(ClipboardActions.Cut); goto case 'i'; case 'g': Status = "g"; state = State.G; return; case 'H': Caret.Line = System.Math.Max(DocumentLocation.MinLine, Editor.PointToLocation(0, Editor.LineHeight - 1).Line); return; case 'J': RunAction(ViActions.Join); return; case 'L': int line = Editor.PointToLocation(0, Editor.Allocation.Height - Editor.LineHeight * 2 - 2).Line; if (line < DocumentLocation.MinLine) { line = Document.LineCount; } Caret.Line = line; return; case 'M': line = Editor.PointToLocation(0, Editor.Allocation.Height / 2).Line; if (line < DocumentLocation.MinLine) { line = Document.LineCount; } Caret.Line = line; return; case '~': RunAction(ViActions.ToggleCase); return; case 'z': Status = "z"; state = State.Fold; return; case 'm': Status = "m"; state = State.Mark; return; case '`': Status = "`"; state = State.GoToMark; return; case '@': Status = "@"; state = State.PlayMacro; return; case 'q': if (currentMacro == null) { Status = "q"; state = State.NameMacro; return; } currentMacro = null; Reset("Macro Recorded"); return; case '*': SearchWordAtCaret(); return; } } action = ViActionMaps.GetNavCharAction((char)unicodeKey); if (action == null) { action = ViActionMaps.GetDirectionKeyAction(key, modifier); } if (action == null) { action = ViActionMaps.GetCommandCharAction((char)unicodeKey); } if (action != null) { RunAction(action); } //undo/redo may leave MD with a selection mode without activating visual mode CheckVisualMode(); return; case State.Delete: if (((modifier & (Gdk.ModifierType.ShiftMask | Gdk.ModifierType.ControlMask)) == 0 && unicodeKey == 'd')) { action = SelectionActions.LineActionFromMoveAction(CaretMoveActions.LineEnd); lineAction = true; } else { action = ViActionMaps.GetNavCharAction((char)unicodeKey); if (action == null) { action = ViActionMaps.GetDirectionKeyAction(key, modifier); } if (action != null) { action = SelectionActions.FromMoveAction(action); } } if (action != null) { if (lineAction) { RunActions(action, ClipboardActions.Cut, CaretMoveActions.LineFirstNonWhitespace); } else { RunActions(action, ClipboardActions.Cut); } Reset(""); } else { Reset("Unrecognised motion"); } return; case State.Yank: int offset = Caret.Offset; if (((modifier & (Gdk.ModifierType.ShiftMask | Gdk.ModifierType.ControlMask)) == 0 && unicodeKey == 'y')) { action = SelectionActions.LineActionFromMoveAction(CaretMoveActions.LineEnd); lineAction = true; } else { action = ViActionMaps.GetNavCharAction((char)unicodeKey); if (action == null) { action = ViActionMaps.GetDirectionKeyAction(key, modifier); } if (action != null) { action = SelectionActions.FromMoveAction(action); } } if (action != null) { RunAction(action); if (Data.IsSomethingSelected && !lineAction) { offset = Data.SelectionRange.Offset; } RunAction(ClipboardActions.Copy); Reset(string.Empty); } else { Reset("Unrecognised motion"); } Caret.Offset = offset; return; case State.Change: //copied from delete action if (((modifier & (Gdk.ModifierType.ShiftMask | Gdk.ModifierType.ControlMask)) == 0 && unicodeKey == 'c')) { action = SelectionActions.LineActionFromMoveAction(CaretMoveActions.LineEnd); lineAction = true; } else { action = ViActionMaps.GetEditObjectCharAction((char)unicodeKey); if (action == null) { action = ViActionMaps.GetDirectionKeyAction(key, modifier); } if (action != null) { action = SelectionActions.FromMoveAction(action); } } if (action != null) { if (lineAction) { RunActions(action, ClipboardActions.Cut, ViActions.NewLineAbove); } else { RunActions(action, ClipboardActions.Cut); } Status = "-- INSERT --"; state = State.Insert; Caret.Mode = CaretMode.Insert; } else { Reset("Unrecognised motion"); } return; case State.Insert: case State.Replace: action = GetInsertAction(key, modifier); if (action != null) { RunAction(action); } else if (unicodeKey != 0) { InsertCharacter(unicodeKey); } return; case State.VisualLine: if (key == Gdk.Key.Delete) { unicodeKey = 'x'; } switch ((char)unicodeKey) { case 'p': PasteAfter(true); return; case 'P': PasteBefore(true); return; } action = ViActionMaps.GetNavCharAction((char)unicodeKey); if (action == null) { action = ViActionMaps.GetDirectionKeyAction(key, modifier); } if (action == null) { action = ViActionMaps.GetCommandCharAction((char)unicodeKey); } if (action != null) { RunAction(SelectionActions.LineActionFromMoveAction(action)); return; } ApplyActionToSelection(modifier, unicodeKey); return; case State.Visual: if (key == Gdk.Key.Delete) { unicodeKey = 'x'; } switch ((char)unicodeKey) { case 'p': PasteAfter(false); return; case 'P': PasteBefore(false); return; } action = ViActionMaps.GetNavCharAction((char)unicodeKey); if (action == null) { action = ViActionMaps.GetDirectionKeyAction(key, modifier); } if (action == null) { action = ViActionMaps.GetCommandCharAction((char)unicodeKey); } if (action != null) { RunAction(ViActions.VisualSelectionFromMoveAction(action)); return; } ApplyActionToSelection(modifier, unicodeKey); return; case State.Command: switch (key) { case Gdk.Key.Return: case Gdk.Key.KP_Enter: Status = RunExCommand(commandBuffer.ToString()); commandBuffer.Length = 0; state = State.Normal; break; case Gdk.Key.BackSpace: case Gdk.Key.Delete: case Gdk.Key.KP_Delete: if (0 < commandBuffer.Length) { commandBuffer.Remove(commandBuffer.Length - 1, 1); Status = commandBuffer.ToString(); if (0 == commandBuffer.Length) { Reset(Status); } } break; default: if (unicodeKey != 0) { commandBuffer.Append((char)unicodeKey); Status = commandBuffer.ToString(); } break; } return; case State.WriteChar: if (unicodeKey != 0) { RunAction(SelectionActions.StartSelection); int roffset = Data.SelectionRange.Offset; InsertCharacter((char)unicodeKey); Reset(string.Empty); Caret.Offset = roffset; } else { Reset("Keystroke was not a character"); } return; case State.Indent: if (((modifier & (Gdk.ModifierType.ControlMask)) == 0 && unicodeKey == '>')) { RunAction(MiscActions.IndentSelection); Reset(""); return; } action = ViActionMaps.GetNavCharAction((char)unicodeKey); if (action == null) { action = ViActionMaps.GetDirectionKeyAction(key, modifier); } if (action != null) { RunActions(SelectionActions.FromMoveAction(action), MiscActions.IndentSelection); Reset(""); } else { Reset("Unrecognised motion"); } return; case State.Unindent: if (((modifier & (Gdk.ModifierType.ControlMask)) == 0 && ((char)unicodeKey) == '<')) { RunAction(MiscActions.RemoveIndentSelection); Reset(""); return; } action = ViActionMaps.GetNavCharAction((char)unicodeKey); if (action == null) { action = ViActionMaps.GetDirectionKeyAction(key, modifier); } if (action != null) { RunActions(SelectionActions.FromMoveAction(action), MiscActions.RemoveIndentSelection); Reset(""); } else { Reset("Unrecognised motion"); } return; case State.G: if (((modifier & (Gdk.ModifierType.ControlMask)) == 0)) { switch ((char)unicodeKey) { case 'g': Caret.Offset = 0; Reset(""); return; } } Reset("Unknown command"); return; case State.Mark: { char k = (char)unicodeKey; ViMark mark = null; if (!char.IsLetterOrDigit(k)) { Reset("Invalid Mark"); return; } if (marks.ContainsKey(k)) { mark = marks [k]; } else { mark = new ViMark(k); marks [k] = mark; } RunAction(mark.SaveMark); Reset(""); return; } case State.NameMacro: { char k = (char)unicodeKey; if (!char.IsLetterOrDigit(k)) { Reset("Invalid Macro Name"); return; } currentMacro = new ViMacro(k); currentMacro.KeysPressed = new Queue <ViMacro.KeySet> (); macros [k] = currentMacro; Reset(""); return; } case State.PlayMacro: { char k = (char)unicodeKey; if (k == '@') { k = macros_lastplayed; } if (macros.ContainsKey(k)) { Reset(""); macros_lastplayed = k; // FIXME play nice when playing macros from inside macros? ViMacro macroToPlay = macros [k]; foreach (ViMacro.KeySet keySet in macroToPlay.KeysPressed) { HandleKeypress(keySet.Key, keySet.UnicodeKey, keySet.Modifiers); // FIXME stop on errors? essential with multipliers and nowrapscan } /* Once all the keys have been played back, quickly exit. */ return; } else { Reset("Invalid Macro Name '" + k + "'"); return; } } case State.GoToMark: { char k = (char)unicodeKey; if (marks.ContainsKey(k)) { RunAction(marks [k].LoadMark); Reset(""); } else { Reset("Unknown Mark"); } return; } case State.Fold: if (((modifier & (Gdk.ModifierType.ControlMask)) == 0)) { switch ((char)unicodeKey) { case 'A': // Recursive fold toggle action = FoldActions.ToggleFoldRecursive; break; case 'C': // Recursive fold close action = FoldActions.CloseFoldRecursive; break; case 'M': // Close all folds action = FoldActions.CloseAllFolds; break; case 'O': // Recursive fold open action = FoldActions.OpenFoldRecursive; break; case 'R': // Expand all folds action = FoldActions.OpenAllFolds; break; case 'a': // Fold toggle action = FoldActions.ToggleFold; break; case 'c': // Fold close action = FoldActions.CloseFold; break; case 'o': // Fold open action = FoldActions.OpenFold; break; default: Reset("Unknown command"); break; } if (null != action) { RunAction(action); Reset(string.Empty); } } return; } }
protected virtual Action <TextEditorData> GetInsertAction(Key key, Xwt.ModifierKeys modifier) { return(ViActionMaps.GetInsertKeyAction(key, modifier) ?? ViActionMaps.GetDirectionKeyAction(key, modifier)); }