gui-cs / Terminal.Gui

Cross Platform Terminal UI toolkit for .NET
MIT License
9.57k stars 682 forks source link

TextView: Additional Move method proposals #897

Open blakepell opened 4 years ago

blakepell commented 4 years ago

With the update merged that added two public methods to the TextView for MoveHome and MoveEnd I would like to propose the following:

  1. The existing MoveUp() and MoveDown() methods be changed from private to public.
  2. Add MoveRight() and MoveLeft() public methods that allow programmatic moving of the cursor to the right and left (with an overload for each that will specify whether the cursor should go the next or previous lines if at EOL or BOL respectively or stop at the line barrier).

With the 2nd item the code in ProcessKey() that handles Key.CursorRight and Key.CursorLeft can then call MoveRight() and MoveLeft() with the option to move lines when at EOL or BOL.

The only thing I waffled on was whether MoveRight() and MoveLeft() should move the cursor to a different line or not by default without specifying. I don't really have a strong opinion either way.

I went ahead and coded this so you see what I'm proposing.

https://github.com/blakepell/gui.cs/commit/90497f72a33e60bceeb2dac6b6f7e6cd87ec92b7#diff-d62dd6237dd225328a492cfce16930be

BDisp commented 4 years ago

@blakepell I think it's a good idea. In my opinion I would make the bool moveLineIfEol = true and bool moveLineIfBol = true parameters as true by default. Thus there is no need to pass a parameter value to theMoveRight and MoveLeft methods if their parameters values are true and you don't need this:

        public void MoveRight ()
        {
            MoveRight (false);
        }

        public void MoveLeft ()
        {
            MoveLeft (false);
        }
blakepell commented 4 years ago

Thank you for the feedback. After thinking about it more I totally agree with you, I'll update my example.

blakepell commented 3 years ago

I made the change to have move line option be the default, updated the commit link.

tig commented 3 years ago

@blakepell you still interested in this? wanna submit a PR?

blakepell commented 3 years ago

@tig Definitely, I'll rebase my branch this weekend and make sure it's still in working order then submit a PR.

tig commented 1 year ago

I think this issue was addressed with the KeyBinding stuff added in and around #1566 and #1548.

void Initialize ()
        {
            CanFocus = true;
            Used = true;

            model.LinesLoaded += Model_LinesLoaded;
            historyText.ChangeText += HistoryText_ChangeText;

            Initialized += TextView_Initialized;

            // Things this view knows how to do
            AddCommand (Command.PageDown, () => { ProcessPageDown (); return true; });
            AddCommand (Command.PageDownExtend, () => { ProcessPageDownExtend (); return true; });
            AddCommand (Command.PageUp, () => { ProcessPageUp (); return true; });
            AddCommand (Command.PageUpExtend, () => { ProcessPageUpExtend (); return true; });
            AddCommand (Command.LineDown, () => { ProcessMoveDown (); return true; });
            AddCommand (Command.LineDownExtend, () => { ProcessMoveDownExtend (); return true; });
            AddCommand (Command.LineUp, () => { ProcessMoveUp (); return true; });
            AddCommand (Command.LineUpExtend, () => { ProcessMoveUpExtend (); return true; });
            AddCommand (Command.Right, () => ProcessMoveRight ());
            AddCommand (Command.RightExtend, () => { ProcessMoveRightExtend (); return true; });
            AddCommand (Command.Left, () => ProcessMoveLeft ());
            AddCommand (Command.LeftExtend, () => { ProcessMoveLeftExtend (); return true; });
            AddCommand (Command.DeleteCharLeft, () => { ProcessDeleteCharLeft (); return true; });
            AddCommand (Command.StartOfLine, () => { ProcessMoveStartOfLine (); return true; });
            AddCommand (Command.StartOfLineExtend, () => { ProcessMoveStartOfLineExtend (); return true; });
            AddCommand (Command.DeleteCharRight, () => { ProcessDeleteCharRight (); return true; });
            AddCommand (Command.EndOfLine, () => { ProcessMoveEndOfLine (); return true; });
            AddCommand (Command.EndOfLineExtend, () => { ProcessMoveEndOfLineExtend (); return true; });
            AddCommand (Command.CutToEndLine, () => { KillToEndOfLine (); return true; });
            AddCommand (Command.CutToStartLine, () => { KillToStartOfLine (); return true; });
            AddCommand (Command.Paste, () => { ProcessPaste (); return true; });
            AddCommand (Command.ToggleExtend, () => { ToggleSelecting (); return true; });
            AddCommand (Command.Copy, () => { ProcessCopy (); return true; });
            AddCommand (Command.Cut, () => { ProcessCut (); return true; });
            AddCommand (Command.WordLeft, () => { ProcessMoveWordBackward (); return true; });
            AddCommand (Command.WordLeftExtend, () => { ProcessMoveWordBackwardExtend (); return true; });
            AddCommand (Command.WordRight, () => { ProcessMoveWordForward (); return true; });
            AddCommand (Command.WordRightExtend, () => { ProcessMoveWordForwardExtend (); return true; });
            AddCommand (Command.KillWordForwards, () => { ProcessKillWordForward (); return true; });
            AddCommand (Command.KillWordBackwards, () => { ProcessKillWordBackward (); return true; });
            AddCommand (Command.NewLine, () => ProcessReturn ());
            AddCommand (Command.BottomEnd, () => { MoveBottomEnd (); return true; });
            AddCommand (Command.BottomEndExtend, () => { MoveBottomEndExtend (); return true; });
            AddCommand (Command.TopHome, () => { MoveTopHome (); return true; });
            AddCommand (Command.TopHomeExtend, () => { MoveTopHomeExtend (); return true; });
            AddCommand (Command.SelectAll, () => { ProcessSelectAll (); return true; });
            AddCommand (Command.ToggleOverwrite, () => { ProcessSetOverwrite (); return true; });
            AddCommand (Command.EnableOverwrite, () => { SetOverwrite (true); return true; });
            AddCommand (Command.DisableOverwrite, () => { SetOverwrite (false); return true; });
            AddCommand (Command.Tab, () => ProcessTab ());
            AddCommand (Command.BackTab, () => ProcessBackTab ());
            AddCommand (Command.NextView, () => ProcessMoveNextView ());
            AddCommand (Command.PreviousView, () => ProcessMovePreviousView ());
            AddCommand (Command.Undo, () => { UndoChanges (); return true; });
            AddCommand (Command.Redo, () => { RedoChanges (); return true; });
            AddCommand (Command.DeleteAll, () => { DeleteAll (); return true; });
            AddCommand (Command.Accept, () => {
                ContextMenu.Position = new Point (CursorPosition.X - leftColumn + 2, CursorPosition.Y - topRow + 2);
                ShowContextMenu ();
                return true;
            });

            // Default keybindings for this view
            AddKeyBinding (Key.PageDown, Command.PageDown);
            AddKeyBinding (Key.V | Key.CtrlMask, Command.PageDown);

            AddKeyBinding (Key.PageDown | Key.ShiftMask, Command.PageDownExtend);

            AddKeyBinding (Key.PageUp, Command.PageUp);
            AddKeyBinding (((int)'V' + Key.AltMask), Command.PageUp);

            AddKeyBinding (Key.PageUp | Key.ShiftMask, Command.PageUpExtend);

            AddKeyBinding (Key.N | Key.CtrlMask, Command.LineDown);
            AddKeyBinding (Key.CursorDown, Command.LineDown);

            AddKeyBinding (Key.CursorDown | Key.ShiftMask, Command.LineDownExtend);

            AddKeyBinding (Key.P | Key.CtrlMask, Command.LineUp);
            AddKeyBinding (Key.CursorUp, Command.LineUp);

            AddKeyBinding (Key.CursorUp | Key.ShiftMask, Command.LineUpExtend);

            AddKeyBinding (Key.F | Key.CtrlMask, Command.Right);
            AddKeyBinding (Key.CursorRight, Command.Right);

            AddKeyBinding (Key.CursorRight | Key.ShiftMask, Command.RightExtend);

            AddKeyBinding (Key.B | Key.CtrlMask, Command.Left);
            AddKeyBinding (Key.CursorLeft, Command.Left);

            AddKeyBinding (Key.CursorLeft | Key.ShiftMask, Command.LeftExtend);

            AddKeyBinding (Key.Delete, Command.DeleteCharLeft);
            AddKeyBinding (Key.Backspace, Command.DeleteCharLeft);

            AddKeyBinding (Key.Home, Command.StartOfLine);
            AddKeyBinding (Key.A | Key.CtrlMask, Command.StartOfLine);

            AddKeyBinding (Key.Home | Key.ShiftMask, Command.StartOfLineExtend);

            AddKeyBinding (Key.DeleteChar, Command.DeleteCharRight);
            AddKeyBinding (Key.D | Key.CtrlMask, Command.DeleteCharRight);

            AddKeyBinding (Key.End, Command.EndOfLine);
            AddKeyBinding (Key.E | Key.CtrlMask, Command.EndOfLine);

            AddKeyBinding (Key.End | Key.ShiftMask, Command.EndOfLineExtend);

            AddKeyBinding (Key.K | Key.CtrlMask, Command.CutToEndLine); // kill-to-end
            AddKeyBinding (Key.DeleteChar | Key.CtrlMask | Key.ShiftMask, Command.CutToEndLine); // kill-to-end

            AddKeyBinding (Key.K | Key.AltMask, Command.CutToStartLine); // kill-to-start
            AddKeyBinding (Key.Backspace | Key.CtrlMask | Key.ShiftMask, Command.CutToStartLine); // kill-to-start

            AddKeyBinding (Key.Y | Key.CtrlMask, Command.Paste); // Control-y, yank
            AddKeyBinding (Key.Space | Key.CtrlMask, Command.ToggleExtend);

            AddKeyBinding (((int)'C' + Key.AltMask), Command.Copy);
            AddKeyBinding (Key.C | Key.CtrlMask, Command.Copy);

            AddKeyBinding (((int)'W' + Key.AltMask), Command.Cut);
            AddKeyBinding (Key.W | Key.CtrlMask, Command.Cut);
            AddKeyBinding (Key.X | Key.CtrlMask, Command.Cut);

            AddKeyBinding (Key.CursorLeft | Key.CtrlMask, Command.WordLeft);
            AddKeyBinding ((Key)((int)'B' + Key.AltMask), Command.WordLeft);

            AddKeyBinding (Key.CursorLeft | Key.CtrlMask | Key.ShiftMask, Command.WordLeftExtend);

            AddKeyBinding (Key.CursorRight | Key.CtrlMask, Command.WordRight);
            AddKeyBinding ((Key)((int)'F' + Key.AltMask), Command.WordRight);

            AddKeyBinding (Key.CursorRight | Key.CtrlMask | Key.ShiftMask, Command.WordRightExtend);
            AddKeyBinding (Key.DeleteChar | Key.CtrlMask, Command.KillWordForwards); // kill-word-forwards
            AddKeyBinding (Key.Backspace | Key.CtrlMask, Command.KillWordBackwards); // kill-word-backwards

            AddKeyBinding (Key.Enter, Command.NewLine);
            AddKeyBinding (Key.End | Key.CtrlMask, Command.BottomEnd);
            AddKeyBinding (Key.End | Key.CtrlMask | Key.ShiftMask, Command.BottomEndExtend);
            AddKeyBinding (Key.Home | Key.CtrlMask, Command.TopHome);
            AddKeyBinding (Key.Home | Key.CtrlMask | Key.ShiftMask, Command.TopHomeExtend);
            AddKeyBinding (Key.T | Key.CtrlMask, Command.SelectAll);
            AddKeyBinding (Key.InsertChar, Command.ToggleOverwrite);
            AddKeyBinding (Key.Tab, Command.Tab);
            AddKeyBinding (Key.BackTab | Key.ShiftMask, Command.BackTab);

            AddKeyBinding (Key.Tab | Key.CtrlMask, Command.NextView);
            AddKeyBinding (Application.AlternateForwardKey, Command.NextView);

            AddKeyBinding (Key.Tab | Key.CtrlMask | Key.ShiftMask, Command.PreviousView);
            AddKeyBinding (Application.AlternateBackwardKey, Command.PreviousView);

            AddKeyBinding (Key.Z | Key.CtrlMask, Command.Undo);
            AddKeyBinding (Key.R | Key.CtrlMask, Command.Redo);

            AddKeyBinding (Key.G | Key.CtrlMask, Command.DeleteAll);
            AddKeyBinding (Key.D | Key.CtrlMask | Key.ShiftMask, Command.DeleteAll);

            currentCulture = Thread.CurrentThread.CurrentUICulture;

            ContextMenu = new ContextMenu () { MenuItems = BuildContextMenuBarItem () };
            ContextMenu.KeyChanged += ContextMenu_KeyChanged;

            AddKeyBinding (ContextMenu.Key, Command.Accept);
        }

@blakepell can you confirm?