Repository: microsoft/vscode (TypeScript)
Date: 2021-10-25 20:23:23+00:00
Task type: Feature

Issue:
Multiple cursors + Word wrap
The current behaviour in VSCode with `"editor.wordWrap": "on" ` is like this:
![Image](https://cloud.githubusercontent.com/assets/5332158/19222557/a85d2168-8e31-11e6-985a-e328a6c3b11c.gif)

But I would prefer an option for this
![Image](https://cloud.githubusercontent.com/assets/5332158/20053063/ffbafc3a-a4bd-11e6-9f92-80733ca6c606.gif)

Note I used the gif from [here](https://github.com/SublimeTextIssues/Core/issues/1054) which I found while looking for a solution. 
Multiple cursors + Word wrap
The current behaviour in VSCode with `"editor.wordWrap": "on" ` is like this:
![Image](https://cloud.githubusercontent.com/assets/5332158/19222557/a85d2168-8e31-11e6-985a-e328a6c3b11c.gif)

But I would prefer an option for this
![Image](https://cloud.githubusercontent.com/assets/5332158/20053063/ffbafc3a-a4bd-11e6-9f92-80733ca6c606.gif)

Note I used the gif from [here](https://github.com/SublimeTextIssues/Core/issues/1054) which I found while looking for a solution. 


Issue discussion:
Since this would operate on the model (not the view model), this can be implemented from an extension.
Is anybody intending to do anything about this, extension or otherwise? @alexandrudima seems to imply that the current behavior is by design, but I believe it is literally useless. Additional cursors positioned in parts of the same wrapped line are placed "randomly" (depending on the view width) - I can't see how this behavior could be compatible with any legitimate use case of multiple cursor editing. 

I suggest this issue should be called a bug, unless a use case can be demonstrated that benefits from the current behavior.
I would say the current implementation is not just useless like @oliversturm points out, but outright dangerous: I have many times accidentally added some garbage in the wrapped lines which I have had to hunt for later on. It just happened for me again, which prompted to finally find out why this glaring bug hasn't been fixed already.

So even if there would be a use case for the current behavior, I would prefer it to be disabled by default to avoid hard-to-notice accidental edits.

I love the multi-cursor support in VS Code (I find new uses for ctrl+d all the time), but this wrapping behavior has caused me to a bit afraid to use it as much as before.

I guess this doesn't bite all users frequently, but I have my editor on a vertical monitor and have enabled wrapping and frequently edit code with too long lines, so I'm dealing with the wrapping hazard daily.
Agreed, this behavior is unexpected and often results in deletions or additions mid-line which I discover later during compiles.
Would also like to see the default behaviour reversed.
Since I couldn’t find an extension that provided this behavior, and @alexdima implied that it could be done through an extension, I implemented one.
I hope this is also useful to others: https://marketplace.visualstudio.com/items?itemName=MartinZimmermannApps.CursorColumnSelectOnTrueLines

Even if there is an extension that provides bindings for this now, I believe this is still a missing core feature.  
If this is the intended default behavior, so be it, but *at least* give us an option to change it, *please*?

Multi-cursor editing would be so much better if we could actually select the lines we want to!
@hediet Do the reassigned labels mean, you want a contribution for this issue? If so, I would like to grab it.
Should the behavior replace the old behavior, or should it be an option?


I think it makes sense to change the default behavior, but I would need to discuss that with the team.

It should be easy to come up with a PR though.
The workaround today is to define the following keybindings:
```
{ "key": "alt+cmd+up",   "command": "editor.action.insertCursorAbove", "when": "editorTextFocus", "args": { "logicalLine": true } },
{ "key": "alt+cmd+down", "command": "editor.action.insertCursorBelow", "when": "editorTextFocus", "args": { "logicalLine": true } },
```

This issue would be very easy to implement, as it would involve just changing the default of `logicalLine` from `false` to `true` here: https://github.com/microsoft/vscode/blob/1770223d16d8c52589028ba25fbfe3154959487e/src/vs/editor/contrib/multicursor/multicursor.ts#L123

Since this would operate on the model (not the view model), this can be implemented from an extension.
Is anybody intending to do anything about this, extension or otherwise? @alexandrudima seems to imply that the current behavior is by design, but I believe it is literally useless. Additional cursors positioned in parts of the same wrapped line are placed "randomly" (depending on the view width) - I can't see how this behavior could be compatible with any legitimate use case of multiple cursor editing. 

I suggest this issue should be called a bug, unless a use case can be demonstrated that benefits from the current behavior.
I would say the current implementation is not just useless like @oliversturm points out, but outright dangerous: I have many times accidentally added some garbage in the wrapped lines which I have had to hunt for later on. It just happened for me again, which prompted to finally find out why this glaring bug hasn't been fixed already.

So even if there would be a use case for the current behavior, I would prefer it to be disabled by default to avoid hard-to-notice accidental edits.

I love the multi-cursor support in VS Code (I find new uses for ctrl+d all the time), but this wrapping behavior has caused me to a bit afraid to use it as much as before.

I guess this doesn't bite all users frequently, but I have my editor on a vertical monitor and have enabled wrapping and frequently edit code with too long lines, so I'm dealing with the wrapping hazard daily.
Agreed, this behavior is unexpected and often results in deletions or additions mid-line which I discover later during compiles.
Would also like to see the default behaviour reversed.
Since I couldn’t find an extension that provided this behavior, and @alexdima implied that it could be done through an extension, I implemented one.
I hope this is also useful to others: https://marketplace.visualstudio.com/items?itemName=MartinZimmermannApps.CursorColumnSelectOnTrueLines

Even if there is an extension that provides bindings for this now, I believe this is still a missing core feature.  
If this is the intended default behavior, so be it, but *at least* give us an option to change it, *please*?

Multi-cursor editing would be so much better if we could actually select the lines we want to!
@hediet Do the reassigned labels mean, you want a contribution for this issue? If so, I would like to grab it.
Should the behavior replace the old behavior, or should it be an option?


I think it makes sense to change the default behavior, but I would need to discuss that with the team.

It should be easy to come up with a PR though.
The workaround today is to define the following keybindings:
```
{ "key": "alt+cmd+up",   "command": "editor.action.insertCursorAbove", "when": "editorTextFocus", "args": { "logicalLine": true } },
{ "key": "alt+cmd+down", "command": "editor.action.insertCursorBelow", "when": "editorTextFocus", "args": { "logicalLine": true } },
```

This issue would be very easy to implement, as it would involve just changing the default of `logicalLine` from `false` to `true` here: https://github.com/microsoft/vscode/blob/1770223d16d8c52589028ba25fbfe3154959487e/src/vs/editor/contrib/multicursor/multicursor.ts#L123


Solution patch:
diff --git a/src/vs/editor/contrib/multicursor/multicursor.ts b/src/vs/editor/contrib/multicursor/multicursor.ts
--- a/src/vs/editor/contrib/multicursor/multicursor.ts
+++ b/src/vs/editor/contrib/multicursor/multicursor.ts
@@ -70,7 +70,10 @@ export class InsertCursorAbove extends EditorAction {
 			return;
 		}
 
-		const useLogicalLine = (args && args.logicalLine === true);
+		let useLogicalLine = true;
+		if (args && args.logicalLine === false) {
+			useLogicalLine = false;
+		}
 		const viewModel = editor._getViewModel();
 
 		if (viewModel.cursorConfig.readOnly) {
@@ -120,7 +123,10 @@ export class InsertCursorBelow extends EditorAction {
 			return;
 		}
 
-		const useLogicalLine = (args && args.logicalLine === true);
+		let useLogicalLine = true;
+		if (args && args.logicalLine === false) {
+			useLogicalLine = false;
+		}
 		const viewModel = editor._getViewModel();
 
 		if (viewModel.cursorConfig.readOnly) {


Test patch:
diff --git a/src/vs/editor/contrib/multicursor/test/multicursor.test.ts b/src/vs/editor/contrib/multicursor/test/multicursor.test.ts
--- a/src/vs/editor/contrib/multicursor/test/multicursor.test.ts
+++ b/src/vs/editor/contrib/multicursor/test/multicursor.test.ts
@@ -16,6 +16,31 @@ import { IStorageService } from 'vs/platform/storage/common/storage';
 
 suite('Multicursor', () => {
 
+
+	test('issue #26393: Multiple cursors + Word wrap', () => {
+		withTestCodeEditor([
+			'a'.repeat(20),
+			'a'.repeat(20),
+		], { wordWrap: 'wordWrapColumn', wordWrapColumn: 10 }, (editor, viewModel) => {
+			let addCursorDownAction = new InsertCursorBelow();
+			addCursorDownAction.run(null!, editor, {});
+
+			assert.strictEqual(viewModel.getCursorStates().length, 2);
+
+			assert.strictEqual(viewModel.getCursorStates()[0].viewState.position.lineNumber, 1);
+			assert.strictEqual(viewModel.getCursorStates()[1].viewState.position.lineNumber, 3);
+
+			editor.setPosition({ lineNumber: 4, column: 1 });
+			let addCursorUpAction = new InsertCursorAbove();
+			addCursorUpAction.run(null!, editor, {});
+
+			assert.strictEqual(viewModel.getCursorStates().length, 2);
+
+			assert.strictEqual(viewModel.getCursorStates()[0].viewState.position.lineNumber, 4);
+			assert.strictEqual(viewModel.getCursorStates()[1].viewState.position.lineNumber, 2);
+		});
+	});
+
 	test('issue #2205: Multi-cursor pastes in reverse order', () => {
 		withTestCodeEditor([
 			'abc',