Compare commits

...

24 commits

Author SHA1 Message Date
Carlos Zamora 314d70cd69 update with upstream changes and address some missed feedback from Dustin 2021-09-23 16:03:01 -07:00
Carlos Zamora 5070c2ca64 Merge branch 'main' into dev/cazamor/spec-ks/mark-mode 2021-09-23 13:26:20 -07:00
Carlos Zamora 246583b78d exclude vsdx from spell checker 2020-08-04 13:42:44 -07:00
Carlos Zamora e2cad94ce3 address zadji comments 2020-08-04 11:15:15 -07:00
Carlos Zamora 7e46f8b841 Y-Beam Mockups and Design 2020-07-17 16:14:55 -07:00
Carlos Zamora ecc88d1859 merge main branch 2020-07-14 11:46:13 -07:00
Carlos Zamora 0b58885e66 merge master + fix spelling 2020-07-14 11:36:53 -07:00
Carlos Zamora db0e1d359c update with meeting results 2020-06-26 15:52:37 -07:00
Carlos Zamora dcc27b681f update date and misspelling 2020-06-23 16:11:40 -07:00
Carlos Zamora dbf1e4e763 better images and structure 2020-06-23 16:10:37 -07:00
Carlos Zamora dd0720e919 remove 'hold' mode 2020-06-23 16:10:37 -07:00
Carlos Zamora 8e1cebd41b whoops. Forgot to save haha 2020-06-23 16:09:44 -07:00
Carlos Zamora f23c033798 add mouse interaction + corner cases 2020-06-23 16:09:44 -07:00
Carlos Zamora 29b00b973e Introduce Mark Mode Spec (add-on) 2020-06-23 16:09:16 -07:00
Carlos Zamora 3af5ae6b59 update default bindings 2020-06-23 16:04:39 -07:00
Carlos Zamora de8dc2f253 Merge branch 'master' into dev/cazamor/spec-keyboard-selection 2020-06-23 15:56:50 -07:00
Carlos Zamora 81c5a7c810 Merge branch 'master' into dev/cazamor/spec-keyboard-selection 2020-06-23 11:43:48 -07:00
Carlos Zamora f71275c8c0 PR changes 2020-06-19 14:18:08 -07:00
Carlos Zamora 23b425eaae remove mark mode for separate PR (easier discussion) 2020-06-19 14:18:07 -07:00
Carlos Zamora de95782692 more mark mode details. Added responses to PR feedback into the spec 2020-06-19 14:18:07 -07:00
Carlos Zamora 4f38557626 include 'shift' in keybindings 2020-06-19 14:18:07 -07:00
Carlos Zamora 67c6334cd3 Updated to reflect Keybinding Args change 2020-06-19 14:18:07 -07:00
Carlos Zamora bc668e0cbd PR changes (first of many) 2020-06-19 14:18:07 -07:00
Carlos Zamora 51e8b1a34e Keyboard Selection Spec 2020-06-19 14:18:07 -07:00
8 changed files with 84 additions and 11 deletions

View file

@ -76,4 +76,5 @@ SUMS$
^src/types/ut_types/UtilsTests.cpp$
^\.github/actions/spelling/
^\.gitignore$
\.vsdx$
^\XamlStyler.json$

View file

@ -376,6 +376,7 @@ conwinuserrefs
coord
coordnew
COPYCOLOR
copymode
CORESYSTEM
cotaskmem
countof

View file

@ -1,7 +1,7 @@
---
author: Carlos Zamora @carlos-zamora
created on: 2019-08-30
last updated: 2021-09-17
last updated: 2021-09-23
issue id: 715
---
@ -9,18 +9,25 @@ issue id: 715
## Abstract
This spec describes a new set of non-configurable keybindings that allows the user to update a selection without the use of a mouse or stylus.
This spec describes a new set of key bindings that allows the user to create and update a selection without the use of a mouse or stylus.
## Inspiration
ConHost allows the user to modify a selection using the keyboard. Holding `Shift` allows the user to move the second selection endpoint in accordance with the arrow keys. The selection endpoint updates by one cell per key event, allowing the user to refine the selected region.
Mark mode allows the user to create a selection using only the keyboard, then edit it as mentioned above.
### Creating a selection
Mark Mode is a ConHost feature that allows the user to create a selection using only the keyboard. In CMD, pressing <kbd>ctrl+m</kbd> enters mark mode. The current cursor position becomes a selection endpoint. The user can use the arrow keys to move that endpoint. While the user then holds <kbd>shift</kbd>, the selection endpoint ('start') is anchored to it's current position, and the arrow keys move the other selection endpoint ('end').
Additionally, pressing <kbd>shift+arrow</kbd> also initiates a selection, but it anchors the first selection endpoint to the cursor position.
Other terminal emulators have different approaches to this feature. iTerm2, for example, has Copy Mode (documentation [linked here](https://iterm2.com/documentation-copymode.html)). Here, <kbd>cmd+shift+c</kbd> makes the current cursor position become a selection endpoint. The arrow keys can be used to move that endpoint. However, unlike Mark Mode, a key binding <kbd>c+space</kbd> is used to change the start/stop selecting. The first time it's pressed, the 'start' endpoint is anchored. The second time it's pressed, the 'end' endpoint is set. After this, you can still move a cursor, but the selection persists until a new selection is created (either by pressing the key binding again, or using the mouse).
Though tmux is not a terminal emulator, it does also have Copy Mode that behaves fairly similarly to that of iTerm2's.
## Solution Design
The fundamental solution design for keyboard selection is that the responsibilities between the Terminal Control and Terminal Core must be very distinct. The Terminal Control is responsible for handling user interaction and directing the Terminal Core to update the selection. The Terminal Core will need to update the selection according to the preferences of the Terminal Control.
The fundamental solution design for keyboard selection is that the responsibilities between the Terminal Control and Terminal Core must be very distinct. The Terminal Control is responsible for handling user interaction and directing the Terminal Core to update the selection. The Terminal Core will need to update the selection according to the direction of the Terminal Control. Terminal Core maintains the state of the selection.
Relatively recently, TerminalControl was split into `TerminalControl`, `ControlInteractivity`, and `ControlCore`. Changes made to `ControlInteractivity`, `ControlCore`, and below propagate functionality to all consumers, meaning that the WPF terminal would benefit from these changes with no additional work required.
@ -110,10 +117,65 @@ For `SelectionExpansion = Buffer`, the selection endpoint will be moved to the b
**NOTE**: In all cases, horizontal movements attempting to move past the left/right viewport boundaries result in a wrap. Vertical movements attempting to move past the top/bottom viewport boundaries will scroll such that the selection is at the edge of the screen. Vertical movements attempting to move past the top/bottom buffer boundaries will be clamped to be within buffer boundaries.
Every combination of the `SelectionDirection` and `SelectionExpansion` will map to a keybinding. These pairings are shown below in the UI/UX Design --> Keybindings section.
**NOTE**: If `copyOnSelect` is enabled, we need to make sure we **DO NOT** update the clipboard on every change in selection. The user must explicitly choose to copy the selected text from the buffer.
### Copy Mode
Copy Mode is a mode where the user can create and modify a selection using only the keyboard. The following flowchart covers how the new `copymode()` action works:
![Copy Mode Flowchart][images/CopyModeFlowchart.png]
**NOTE**: `copyMode()` refers to the action, whereas `updateSelection()` refers to the underlying function that is being called in the code.
If a selection is not active, a "start" and "end" selection point is created at the cursor position. `updateSelection()` calls then move "start" and "end" together as one position. This position will be denoted with a "y-beam".
![Y-Beam Example][images/Y-Beam.png]
If a selection is active, `copyMode` leaves the selection untouched, all subsequent `updateSelection()` calls move "start". The y-beam is then cut vertically in half, where one half is drawn on the "start" endpoint, and the other half is drawn on the "end" endpoint. Since the user is moving "start", only the half-y-beam is drawn on the "start" endpoint.
![Separated Y-Beam Example][images/Half-Y-Beam.png]
**NOTE:** Both half y-beams could have been presented as shown in the image below. This idea was omitted because then there is no indication for which half y-beam is currently focused.
![Both Separated Y-Beams Example][images/Split-Y-Beam.png]
Invoking `copyMode()` again, will then anchor "start" (meaning that it will be kept in place). Subsequent `updateSelection()` calls move the "end" selection point. As before, the half-y-beam is only drawn on the "end" to denote that this is the endpoint that is being moved.
Invoking `copyMode()` essentially cycles between which selection point is targeted. The half-y-beam is drawn on the targeted endpoint.
#### Block Selection
A user can normally create a block selection by holding <kbd>alt</kbd> then creating a selection.
If the user is in Copy Mode, and desires to make a block selection, they can use the `toggleBlockSelection()` action. `toggleBlockSelection()` takes an existing selection, and transforms it into a block selection (or vice-versa).
All selections created in Copy Mode will have block selection disabled by default.
#### Rendering during Copy Mode
Since we are just moving the selection endpoints, rendering the selection rects should operate normally. We need to ensure that we still scroll when we move a selection point past the top/bottom of the viewport.
In ConHost, output would be paused when a selection was present. Windows Terminal does not pause the output when a selection is present, however, it does not scroll to the new output.
#### Interaction with CopyOnSelect
If `copyOnSelect` is enabled, the selection is copied when the selection operation is "complete". Thus, the selection is copied when the `copy` keybinding is used or the selection is copied using the mouse.
#### Interaction with Mouse Selection
If a selection exists, the user is basically already in Copy Mode. The user should be modifying the "end" endpoint of the selection when using the `updateSelection()` bindings. The existing selection should not be cleared (contrary to prior behavior). However, the half-y-beam will not be drawn. Once the user presses the `copyMode` or `moveSelectionPoint` keybinding, the half-y-beam is drawn on the targeted endpoint (which will then be "start").
During Copy Mode, if the user attempts to create a selection using the mouse, any existing selections are cleared and the mouse creates a selection normally. However, contrary to prior behavior, the user will still be in Copy Mode. The target endpoint being modified in Copy Mode, however, will be the "end" endpoint of the selection, instead of the cursor (as explained earlier in the flowchart).
#### Exiting Copy Mode
The user exits copy mode when the selection is cleared. Thus, the user can press...
- the `ESC` key
- the `copy()` action (which also copies the contents of the selection to the user's clipboard)
- keys that generate input and clear a selection
In all of these cases, the selection will be cleared.
If `copyOnSelect` is enabled, `ESC` is interpreted as "cancelling" the selection, so nothing is copied. Keys that generate input are also interpreted as "cancelling" the selection. Only the `copy` keybinding or copying using the mouse is considered "completing" the selection operation, and copying the content to the clipboard.
**NOTE** - Related to #3884:
If the user has chosen to have selections persist after a copy operation, the selection created by Copy Mode is treated no differently than one created with the mouse. The selection will persist after a copy operation. However, if the user exits Copy Mode in any of the other situations, the selection is cleared.
## UI/UX Design
@ -122,11 +184,17 @@ Every combination of the `SelectionDirection` and `SelectionExpansion` will map
There will only be 1 new command that needs to be added:
| Action | Keybinding Args | Description |
|--|--|--|
| `selectAll` | | Select the entire text buffer.
| `selectAll` | | Select the entire text buffer. |
| `copyMode` | | Cycle the selection point targeted by `moveSelectionPoint`. If no selection exists, a selection is created at the cursor. |
| `toggleBlockSelection` | | Transform the existing selection between a block selection and a line selection. |
By default, the following key binding will be set:
```JS
{ "command": "selectAll", "keys": "ctrl+shift+a" },
// Copy Mode
{ "command": "copyMode", "keys": "ctrl+shift+m" },
{ "command": "toggleBlockSelection", "keys": "alt+shift+m" },
```
## Capabilities
@ -151,20 +219,23 @@ N/A
### Performance, Power, and Efficiency
N/A
## Potential Issues
### Grapheme Clusters
When grapheme cluster support is inevitably added to the Text Buffer, moving by "cell" is expected to move by "character" or "cluster". This is similar to how wide glyphs are handled today. Either all of it is selected, or none of it.
### Circling the buffer
As usual, if the buffer is circling, the selection should be updated to follow the content (and "scroll up" appropriately).
In the event that one endpoint "scrolls" off the buffer, we must clamp "start" to the buffer origin. Conversely, in the event that both endpoints "scroll" off the buffer, the selection must be considered cleared.
## Future considerations
### Word Selection Wrap
At the time of writing this spec, expanding or moving by word is interrupted by the beginning or end of the line, regardless of the wrap flag being set. In the future, selection and the accessibility models will respect the wrap flag on the text buffer.
## Mark Mode
This functionality will be expanded to create a feature similar to Mark Mode. This will allow a user to create a selection using only the keyboard.
## Resources

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 88 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 88 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 88 KiB