Skip to content

Commit

Permalink
fix(vim/#1633): Visual-block I and A implementation (#3011)
Browse files Browse the repository at this point in the history
__Issue:__ `I` and `A` in visual-block mode should allow inserting, or appending, characters across all linewise selections in the visual block

__Fix:__ Implement using our in-progress multi-cursor support:

![2021-01-19 12 02 59](https://user-images.githubusercontent.com/13532591/105086839-7746a700-5a4e-11eb-9a44-c984d27ae6bc.gif)

Functionally, this should behave the same as `<c-v>`+`I`/`A`, but show all insertions during the gesture (as opposed to Vim, which would only show a single insertion, and then propagate them on the `<esc>` press).

A baby step towards snippets & multiple cursors

Fixes #1633 
Related #1551
  • Loading branch information
bryphe authored Jan 19, 2021
1 parent 81d162b commit 9f92267
Show file tree
Hide file tree
Showing 17 changed files with 255 additions and 57 deletions.
1 change: 1 addition & 0 deletions CHANGES_CURRENT.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

- #3008 - SCM: Fix index-out-of-bound exception when rendering diff markers
- #3007 - Extensions: Show 'missing dependency' activation error to user
- #3011 - Vim: Visual Block - Handle 'I' and 'A' in visual block mode (fixes #1633)

### Performance

Expand Down
12 changes: 6 additions & 6 deletions bench.esy.lock/index.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 6 additions & 6 deletions esy.lock/index.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 6 additions & 6 deletions integrationtest.esy.lock/index.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -243,7 +243,7 @@
"esy-skia": "*",
"esy-tree-sitter": "^1.4.1",
"isolinear": "^3.0.0",
"libvim": "8.10869.83",
"libvim": "8.10869.85",
"ocaml": "4.10.0",
"reason-native-crash-utils": "onivim/reason-native-crash-utils#38c8f00",
"reason-fzy": "bryphe/reason-fzy#ab172e1",
Expand Down
12 changes: 6 additions & 6 deletions release.esy.lock/index.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 4 additions & 2 deletions src/Feature/Editor/Editor.re
Original file line number Diff line number Diff line change
Expand Up @@ -1623,7 +1623,8 @@ let moveScreenLines = (~position, ~count, editor) => {
);
};

let mouseDown = (~time, ~pixelX, ~pixelY, editor) => {
let mouseDown = (~altKey, ~time, ~pixelX, ~pixelY, editor) => {
ignore(altKey);
ignore(time);
let bytePosition: BytePosition.t =
Slow.pixelPositionToBytePosition(
Expand Down Expand Up @@ -1673,7 +1674,8 @@ let getCharacterUnderMouse = editor => {
});
};

let mouseUp = (~time, ~pixelX, ~pixelY, editor) => {
let mouseUp = (~altKey, ~time, ~pixelX, ~pixelY, editor) => {
ignore(altKey);
ignore(pixelX);
ignore(pixelY);

Expand Down
7 changes: 5 additions & 2 deletions src/Feature/Editor/Editor.rei
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ let getCharacterAtPosition:
(~position: CharacterPosition.t, t) => option(Uchar.t);
let getPrimaryCursor: t => CharacterPosition.t;
let getPrimaryCursorByte: t => BytePosition.t;
let cursors: t => list(BytePosition.t);
let getVisibleView: t => int;
let getTotalHeightInPixels: t => int;
let getTotalWidthInPixels: t => float;
Expand Down Expand Up @@ -116,8 +117,10 @@ let setMinimap: (~enabled: bool, ~maxColumn: int, t) => t;
let isMinimapEnabled: t => bool;

// Mouse interactions
let mouseDown: (~time: Revery.Time.t, ~pixelX: float, ~pixelY: float, t) => t;
let mouseUp: (~time: Revery.Time.t, ~pixelX: float, ~pixelY: float, t) => t;
let mouseDown:
(~altKey: bool, ~time: Revery.Time.t, ~pixelX: float, ~pixelY: float, t) => t;
let mouseUp:
(~altKey: bool, ~time: Revery.Time.t, ~pixelX: float, ~pixelY: float, t) => t;
let mouseMove: (~time: Revery.Time.t, ~pixelX: float, ~pixelY: float, t) => t;
let mouseEnter: t => t;
let mouseLeave: t => t;
Expand Down
8 changes: 4 additions & 4 deletions src/Feature/Editor/Feature_Editor.re
Original file line number Diff line number Diff line change
Expand Up @@ -99,12 +99,12 @@ let update = (editor, msg) => {
| HorizontalScrollbarMouseRelease
| VerticalScrollbarMouseRelease
| VerticalScrollbarMouseDown => (editor, Nothing)
| EditorMouseDown({time, pixelX, pixelY}) => (
editor |> Editor.mouseDown(~time, ~pixelX, ~pixelY),
| EditorMouseDown({altKey, time, pixelX, pixelY}) => (
editor |> Editor.mouseDown(~altKey, ~time, ~pixelX, ~pixelY),
Nothing,
)
| EditorMouseUp({time, pixelX, pixelY}) => (
editor |> Editor.mouseUp(~time, ~pixelX, ~pixelY),
| EditorMouseUp({altKey, time, pixelX, pixelY}) => (
editor |> Editor.mouseUp(~altKey, ~time, ~pixelX, ~pixelY),
Nothing,
)
| InlineElementSizeChanged({key, line, uniqueId, height}) => (
Expand Down
2 changes: 2 additions & 0 deletions src/Feature/Editor/Msg.re
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ type t =
| PreviewChanged(bool)
| EditorMouseEnter
| EditorMouseDown({
altKey: bool,
time: [@opaque] Revery.Time.t,
pixelX: float,
pixelY: float,
Expand All @@ -33,6 +34,7 @@ type t =
pixelY: float,
})
| EditorMouseUp({
altKey: bool,
time: [@opaque] Revery.Time.t,
pixelX: float,
pixelY: float,
Expand Down
36 changes: 24 additions & 12 deletions src/Feature/Editor/SurfaceView.re
Original file line number Diff line number Diff line change
Expand Up @@ -139,14 +139,18 @@ let%component make =
let onMouseDown = (evt: NodeEvents.mouseButtonEventParams) => {
getMaybeLocationFromMousePosition(evt.mouseX, evt.mouseY)
|> Option.iter(((pixelX, pixelY, time)) => {
dispatch(Msg.EditorMouseDown({time, pixelX, pixelY}))
dispatch(
Msg.EditorMouseDown({altKey: evt.ctrlKey, time, pixelX, pixelY}),
)
});
};

let onMouseUp = (evt: NodeEvents.mouseButtonEventParams) => {
getMaybeLocationFromMousePosition(evt.mouseX, evt.mouseY)
|> Option.iter(((pixelX, pixelY, time)) => {
dispatch(Msg.EditorMouseUp({time, pixelX, pixelY}))
dispatch(
Msg.EditorMouseUp({altKey: evt.ctrlKey, time, pixelX, pixelY}),
)
});
};

Expand All @@ -165,6 +169,23 @@ let%component make =
)
|> Option.value(~default=React.empty);

let cursors =
Editor.cursors(editor)
|> List.filter_map(pos => Editor.byteToCharacter(pos, editor))
|> List.map(cursorPosition => {
<CursorView
config
editor
editorFont
mode
cursorPosition
isActiveSplit
windowIsFocused
colors
/>
})
|> React.listToElement;

<View
onBoundingBoxChanged={bbox => maybeBbox := Some(bbox)}
style={Styles.bufferViewClipped(
Expand Down Expand Up @@ -248,15 +269,6 @@ let%component make =
/>
{lensElements |> React.listToElement}
yankHighlightElement
<CursorView
config
editor
editorFont
mode
cursorPosition
isActiveSplit
windowIsFocused
colors
/>
cursors
</View>;
};
2 changes: 2 additions & 0 deletions src/reason-libvim/GlobalState.re
Original file line number Diff line number Diff line change
Expand Up @@ -36,3 +36,5 @@ let screenPositionMotion:

let toggleComments: ref(option(array(string) => array(string))) =
ref(None);

let additionalCursors: ref(list(BytePosition.t)) = ref([]);
33 changes: 28 additions & 5 deletions src/reason-libvim/Vim.re
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,7 @@ let runWith = (~context: Context.t, f) => {
GlobalState.screenPositionMotion := Some(context.screenCursorMotion);
GlobalState.effects := [];
GlobalState.toggleComments := Some(context.toggleComments);
GlobalState.additionalCursors := [];

let mode = f();

Expand All @@ -191,22 +192,30 @@ let runWith = (~context: Context.t, f) => {
GlobalState.toggleComments := None;

let newBuf = Buffer.getCurrent();
let newMode = Mode.current();
//let newMode = Mode.current();
let newModified = Buffer.isModified(newBuf);
let newLineEndings = Buffer.getLineEndings(newBuf);

// Apply additional cursors
let mode =
switch (mode) {
| Mode.Insert({cursors}) =>
Mode.Insert({cursors: cursors @ GlobalState.additionalCursors^})
| mode => mode
};

BufferInternal.checkCurrentBufferForUpdate();

if (newMode != prevMode) {
if (newMode == CommandLine) {
if (mode != prevMode) {
if (mode == CommandLine) {
Event.dispatch(
CommandLineInternal.getState(),
Listeners.commandLineEnter,
);
} else if (prevMode == CommandLine) {
Event.dispatch((), Listeners.commandLineLeave);
};
} else if (newMode == CommandLine) {
} else if (mode == CommandLine) {
Event.dispatch(
CommandLineInternal.getState(),
Listeners.commandLineUpdate,
Expand Down Expand Up @@ -513,6 +522,17 @@ let _onToggleComments = (buf: Buffer.t, startLine: int, endLine: int) => {
|> Option.value(~default=currentLines);
};

let _onCursorAdd = (oneBasedLine: int, column: int) => {
GlobalState.additionalCursors :=
[
BytePosition.{
line: LineNumber.ofOneBased(oneBasedLine),
byte: ByteIndex.ofInt(column),
},
...GlobalState.additionalCursors^,
];
};

let _onGetChar = mode => {
let mode' =
switch (mode) {
Expand Down Expand Up @@ -567,6 +587,7 @@ let init = () => {
Callback.register("lv_onToggleComments", _onToggleComments);
Callback.register("lv_onGetChar", _onGetChar);
Callback.register("lv_onOutput", _onOutput);
Callback.register("lv_onCursorAdd", _onCursorAdd);

Native.vimInit();

Expand All @@ -581,7 +602,9 @@ let inputCommon = (~inputFn, ~context=Context.current(), v: string) => {
() => {
// Special auto-closing pairs handling...

let runCursor = cursor => {
let runCursor = (cursor: BytePosition.t) => {
let lineNumber = EditorCoreTypes.LineNumber.toOneBased(cursor.line);
Undo.saveRegion(lineNumber - 1, lineNumber + 1);
Cursor.set(cursor);
if (Mode.current() |> Mode.isInsert) {
let position: BytePosition.t = Cursor.get();
Expand Down
Loading

0 comments on commit 9f92267

Please sign in to comment.