Change:
VSCode Version: 0.10.11 OS Version: OS X 10.10.5 Steps to Reproduce: a long line of text that wraps in the editor the cursor on the first line and press Cmd-Option-Down (on OS X). This creates a second cursor on the next visual line, which means it is somewhere on the same logical line depending on how the text is wrapped. When creating multiple cursors on adjacent lines, often it is to perform the same edit on multiple (logical) lines that are aligned with each other. The current behavior having the second cursor appear instead at some situation-specific place on the same logical line throws a wrench in this workflow. I can't think of a good situation where it makes sense (though I do realize it is consistent with pressing the down arrow without cmd-option) Definitions: a logical line is a line in the file on disk. A visual line is a line in the editor. A logical line may span multiple visual lines when there is wrapping.

Discussion:
export class CursorMoveCommands { <del> public static addCursorDown(context: CursorContext, cursors: CursorState[]): CursorState[] { </del> <ins> public static addCursorDown(context: CursorContext, cursors: CursorState[], useLogicalLine: boolean): CursorState[] { </ins> let result: CursorState[] = [], resultLen = 0; <del> for (let i = 0, len = cursors.length; i < len; i++) { const cursor = cursors[i]; result[resultLen++] = new CursorState(cursor.modelState, cursor.viewState); result[resultLen++] = CursorState.fromViewState(MoveOperations.translateDown(context.config, context.viewModel, cursor.viewState)); </del> <ins> if (useLogicalLine) { for (let i = 0, len = cursors.length; i < len; i++) { const cursor = cursors[i]; result[resultLen++] = new CursorState(cursor.modelState, cursor.viewState); result[resultLen++] = CursorState.fromModelState(MoveOperations.translateDown(context.config, context.model, cursor.modelState)); } } else { for (let i = 0, len = cursors.length; i < len; i++) { const cursor = cursors[i]; result[resultLen++] = new CursorState(cursor.modelState, cursor.viewState); result[resultLen++] = CursorState.fromViewState(MoveOperations.translateDown(context.config, context.viewModel, cursor.viewState)); } </ins> } return result; } <del> public static addCursorUp(context: CursorContext, cursors: CursorState[]): CursorState[] { </del> <ins> public static addCursorUp(context: CursorContext, cursors: CursorState[], useLogicalLine: boolean): CursorState[] { </ins> let result: CursorState[] = [], resultLen = 0; <del> for (let i = 0, len = cursors.length; i < len; i++) { const cursor = cursors[i]; result[resultLen++] = new CursorState(cursor.modelState, cursor.viewState); result[resultLen++] = CursorState.fromViewState(MoveOperations.translateUp(context.config, context.viewModel, cursor.viewState)); </del> <ins> if (useLogicalLine) { for (let i = 0, len = cursors.length; i < len; i++) { const cursor = cursors[i]; result[resultLen++] = new CursorState(cursor.modelState, cursor.viewState); result[resultLen++] = CursorState.fromModelState(MoveOperations.translateUp(context.config, context.model, cursor.modelState)); } } else { for (let i = 0, len = cursors.length; i < len; i++) { const cursor = cursors[i]; result[resultLen++] = new CursorState(cursor.modelState, cursor.viewState); result[resultLen++] = CursorState.fromViewState(MoveOperations.translateUp(context.config, context.viewModel, cursor.viewState)); } </ins> } return result; }

import { ICodeEditor } from 'vs/editor/browser/editorBrowser'; export class InsertCursorAbove extends EditorAction { constructor() { super({ id: 'editor.action.insertCursorAbove',

cursors.setStates( args.source, CursorChangeReason.Explicit, <del> CursorMoveCommands.addCursorUp(context, cursors.getAll()) </del> <ins> CursorMoveCommands.addCursorUp(context, cursors.getAll(), useLogicalLine) </ins> ); cursors.reveal(true, RevealTarget.TopMost, ScrollType.Smooth); } } export class InsertCursorBelow extends EditorAction { constructor() { super({ id: 'editor.action.insertCursorBelow',

} public run(accessor: ServicesAccessor, editor: ICodeEditor, args: any): void { <ins> const useLogicalLine = (args && args.logicalLine === true); </ins> const cursors = editor._getCursors(); const context = cursors.context;

cursors.setStates( args.source, CursorChangeReason.Explicit, <del> CursorMoveCommands.addCursorDown(context, cursors.getAll()) </del> <ins> CursorMoveCommands.addCursorDown(context, cursors.getAll(), useLogicalLine) </ins> ); cursors.reveal(true, RevealTarget.BottomMost, ScrollType.Smooth); }