public ModeInsert(IVimHost host, IVimMode previousMode, AbstractVimEditionInsertText causedEdition) { _insertArea = new VimSpan(host.CurrentPosition, host.CurrentPosition); this.Host = host; this.CausedEdition = causedEdition; this.PreviousMode = previousMode; }
protected override void OnBeforeInsert(Interfaces.IVimHost host) { VimPoint from = host.CurrentPosition; // when cursor is at the end of line, nothing to delete if (from.Y == host.CurrentLineEndPosition.Y) { return; } VimPoint to = new VimPoint(from.X, Math.Min(from.Y + this.Repeat - 1, host.CurrentLineEndPosition.Y - 1)); VimSpan span = new VimSpan(from, to).GetClosedEnd(); VimRegister.YankRangeToDefaultRegister(host, span); host.DeleteRange(span); }
public override bool Apply(Interfaces.IVimHost host) { if (host.IsCurrentPositionAtEndOfLine()) { return true; } VimPoint from = host.CurrentPosition; VimPoint to = new VimPoint(from.X, Math.Min(from.Y + this.Repeat - 1, host.CurrentLineEndPosition.Y - 1)); VimSpan span = new VimSpan(from, to).GetClosedEnd(); VimRegister.YankRangeToDefaultRegister(host, span); host.DeleteRange(span); return true; }
public override bool Apply(Interfaces.IVimHost host) { VimPoint from = host.CurrentPosition; VimPoint to = this.Motion.Move(host); VimSpan span = null; if (from.CompareTo(to) <= 0) { span = new VimSpan(from, to); } else { span = new VimSpan(to, from); } host.FormatLineRange(span); return true; }
protected override void OnBeforeInsert(Interfaces.IVimHost host) { if (this.Repeat == 1) { VimRegister.YankLineToDefaultRegister(host, new VimSpan(host.CurrentPosition, host.CurrentPosition)); host.DeleteLine(); host.OpenLineAbove(); } else { VimPoint from = host.CurrentPosition; int dst_line = Math.Min(from.X + this.Repeat - 1, host.TextLineCount - 1); VimPoint to = new VimPoint(dst_line, 0); VimSpan span = new VimSpan(from, to); VimRegister.YankLineToDefaultRegister(host, span); host.DeleteLineRange(span); // here will result in a annoying thing, you need to undo 2 times to undo this edition // not worth to fix it, too complex for this single one thing to do a big change host.OpenLineAbove(); } }
public override bool Apply(Interfaces.IVimHost host) { // in yank, we need not to move cursor to new moved position VimPoint bak = host.CurrentPosition; VimPoint from = bak; VimPoint to = null; for (int i = 0; i < this.Repeat; i++) { to = this.Motion.Move(host); } VimSpan span = null; if (from.CompareTo(to) > 0) { span = new VimSpan(to, from); } else { span = new VimSpan(from, to); if (this.Motion is Interfaces.IVimMotionNextWord) { // "dw" on the last word of the line deletes to the end of the line if (host.IsCurrentPositionAtStartOfLineText()) { host.CaretUp(); host.MoveToEndOfLine(); span = new VimSpan(from, host.CurrentPosition); } } else if (this.Motion is Interfaces.IVimMotionEndOfWord) { span = span.GetClosedEnd(); } else if (this.Motion is Interfaces.IVimMotionEndOfLine) { // '$' in range edition is a close end span while range edition operates on open end spans, // so a manual compensation is needed span = span.GetClosedEnd(); } else if (this.Motion is Interfaces.IVimMotionSearchCharInLine) { span = span.GetClosedEnd(); } } if (this.Motion is Interfaces.IVimMotionSearchCharInLine) { if (span.Start.CompareTo(span.End) == 0) { // may be search successfully, but most of time, it reflects a failure, so do nothing for simplification // TODO can find a better way to handle this class of motion failure? return false; } } host.MoveCursor(bak); if (this.Motion is Interfaces.IVimMotionBetweenLines) { from = new VimPoint(span.Start.X, 0); to = host.GetLineEndPosition(span.End.X); span = new VimSpan(from, to); _register.Remember(host.GetText(span), true, host); } else { _register.Remember(host.GetText(span), false, host); } return true; }
public override bool Apply(Interfaces.IVimHost host) { VimPoint from = host.CurrentPosition; VimPoint to = null; for (int i = 0; i < this.Repeat; i++) { to = this.Motion.Move(host); } VimSpan span = null; if (from.CompareTo(to) > 0) { span = new VimSpan(to, from); } else { span = new VimSpan(from, to); if (this.Motion is Interfaces.IVimMotionNextWord) { if (host.IsCurrentPositionAtStartOfLineText()) { if (from.X < host.CurrentPosition.X) { // "dw" on the last word of the line deletes to the end of the line host.CaretUp(); host.MoveToEndOfLine(); if (from.CompareTo(host.CurrentPosition) >= 0) { // delete action begins at the line end // adjust the cursor to one left char before the end of the line host.CaretLeft(); return true; } span = new VimSpan(from, host.CurrentPosition); } } } else if (this.Motion is Interfaces.IVimMotionEndOfWord) { span = span.GetClosedEnd(); } else if (this.Motion is Interfaces.IVimMotionEndOfLine) { // '$' in range edition is a close end span while range edition operates on open end spans, // so a manual compensation is needed span = span.GetClosedEnd(); } else if (this.Motion is Interfaces.IVimMotionSearchCharInLine) { span = span.GetClosedEnd(); } } if (this.Motion is Interfaces.IVimMotionSearchCharInLine) { if (span.Start.CompareTo(span.End) == 0) { // may be search successfully, but most of time, it reflects a failure, so do nothing for simplification // TODO can find a better way to handle this class of motion failure? return false; } } if (this.Motion is IVimMotionBetweenLines) { VimRegister.YankLineToDefaultRegister(host, span); host.DeleteLineRange(span); } else { VimRegister.YankRangeToDefaultRegister(host, span); host.DeleteRange(span); } if (host.IsCurrentPositionAtEndOfLine()) { // adjust the cursor to one left char before the end of the line host.CaretLeft(); } return true; }
/// <summary> /// mayby too dedicated to VS's editor /// </summary> /// <param name="args"></param> public virtual void KeyDown(VimKeyEventArgs args) { // important for dealing some unexpected scene bool is_unsupported_key_last_input = false; if (_activeNoneCharKeyInput != NoneCharKeyInputType.None) { if (_activeNoneCharKeyInput == NoneCharKeyInputType.Unsupport) { is_unsupported_key_last_input = true; } else { // extends edition region regarding to last supported special key input if (this.Host.CurrentPosition.CompareTo(_insertArea.End) > 0) { // Key.Enter or Key.Tab _insertArea = _insertArea.ExtendEndTo(this.Host.CurrentPosition); } else { // Key.Backspace if (this.Host.CurrentPosition.CompareTo(_insertArea.Start) > 0) { // still in original insert area _insertArea = _insertArea.ExtendEndTo(this.Host.CurrentPosition); } } } _activeNoneCharKeyInput = NoneCharKeyInputType.None; } if (args.KeyInput.Value.Length == 1) { // KeyDown event is fired up before text's change, so the real position after input should be one char right by current. VimPoint previous_pos = this.Host.CurrentPosition; VimPoint next_pos = new VimPoint(previous_pos.X, previous_pos.Y + 1); if (!is_unsupported_key_last_input) { if (_insertArea.End.CompareTo(previous_pos) <= 0) { // previous_pos may bigger than _insertArea.End in some cases // in normally char input typing, simply extends insert area's end to current position _insertArea = _insertArea.ExtendEndTo(next_pos); } else { // Key.Backspace can invalidate current insert area, so need to renew it _insertArea = new VimSpan(previous_pos, next_pos); } } else { _insertArea = new VimSpan(previous_pos, next_pos); } } else if (args.KeyInput.Value == VimKeyInput.Escape) { if (!is_unsupported_key_last_input) { // Escape after normal key/char input, do some extra checks if (this.Host.CurrentPosition.CompareTo(_insertArea.End) != 0) { // you can't expect to get precise input text here, because everything is under control, but something wrong happened // so we reset the insert area _insertArea = new VimSpan(this.Host.CurrentPosition, this.Host.CurrentPosition); } } this.CausedEdition.Text = this.Host.GetText(_insertArea); this.Host.CurrentMode = PreviousMode; this.Host.DismissDisplayWindows(); // keep consistency with Vim new MotionCaretLeft(this.Host, 1).Move(this.Host); args.Handled = true; } else { _activeNoneCharKeyInput = NoneCharKeyInputType.None; if (this.Host.CurrentPosition.CompareTo(_insertArea.End) == 0) { // speical key input happens at the end of text input area, // we think it's a valid input, save it as a active special key input, // and in the next loop, to deal with it if (args.KeyInput.Value == VimKeyInput.Enter) { _activeNoneCharKeyInput = NoneCharKeyInputType.Enter; } else if (args.KeyInput.Value == VimKeyInput.Tab) { _activeNoneCharKeyInput = NoneCharKeyInputType.Tab; } else if (args.KeyInput.Value == VimKeyInput.Backspace) { _activeNoneCharKeyInput = NoneCharKeyInputType.Backspace; } else { _activeNoneCharKeyInput = NoneCharKeyInputType.Unsupport; } } } }