6382c8f31670e96c6504e89bfabc07a75cc858dee2f9fe7ac58aac90f2bc31d3fdf3b7c9152a0a6cdf35181d9f382fb6d612cac01f3547b428b75b08905f5f 33 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643
  1. /*---------------------------------------------------------------------------------------------
  2. * Copyright (c) Microsoft Corporation. All rights reserved.
  3. * Licensed under the MIT License. See License.txt in the project root for license information.
  4. *--------------------------------------------------------------------------------------------*/
  5. import * as types from '../../../base/common/types.js';
  6. import { CursorState, SingleCursorState } from '../cursorCommon.js';
  7. import { MoveOperations } from './cursorMoveOperations.js';
  8. import { WordOperations } from './cursorWordOperations.js';
  9. import { Position } from '../core/position.js';
  10. import { Range } from '../core/range.js';
  11. export class CursorMoveCommands {
  12. static addCursorDown(viewModel, cursors, useLogicalLine) {
  13. const result = [];
  14. let resultLen = 0;
  15. for (let i = 0, len = cursors.length; i < len; i++) {
  16. const cursor = cursors[i];
  17. result[resultLen++] = new CursorState(cursor.modelState, cursor.viewState);
  18. if (useLogicalLine) {
  19. result[resultLen++] = CursorState.fromModelState(MoveOperations.translateDown(viewModel.cursorConfig, viewModel.model, cursor.modelState));
  20. }
  21. else {
  22. result[resultLen++] = CursorState.fromViewState(MoveOperations.translateDown(viewModel.cursorConfig, viewModel, cursor.viewState));
  23. }
  24. }
  25. return result;
  26. }
  27. static addCursorUp(viewModel, cursors, useLogicalLine) {
  28. const result = [];
  29. let resultLen = 0;
  30. for (let i = 0, len = cursors.length; i < len; i++) {
  31. const cursor = cursors[i];
  32. result[resultLen++] = new CursorState(cursor.modelState, cursor.viewState);
  33. if (useLogicalLine) {
  34. result[resultLen++] = CursorState.fromModelState(MoveOperations.translateUp(viewModel.cursorConfig, viewModel.model, cursor.modelState));
  35. }
  36. else {
  37. result[resultLen++] = CursorState.fromViewState(MoveOperations.translateUp(viewModel.cursorConfig, viewModel, cursor.viewState));
  38. }
  39. }
  40. return result;
  41. }
  42. static moveToBeginningOfLine(viewModel, cursors, inSelectionMode) {
  43. const result = [];
  44. for (let i = 0, len = cursors.length; i < len; i++) {
  45. const cursor = cursors[i];
  46. result[i] = this._moveToLineStart(viewModel, cursor, inSelectionMode);
  47. }
  48. return result;
  49. }
  50. static _moveToLineStart(viewModel, cursor, inSelectionMode) {
  51. const currentViewStateColumn = cursor.viewState.position.column;
  52. const currentModelStateColumn = cursor.modelState.position.column;
  53. const isFirstLineOfWrappedLine = currentViewStateColumn === currentModelStateColumn;
  54. const currentViewStatelineNumber = cursor.viewState.position.lineNumber;
  55. const firstNonBlankColumn = viewModel.getLineFirstNonWhitespaceColumn(currentViewStatelineNumber);
  56. const isBeginningOfViewLine = currentViewStateColumn === firstNonBlankColumn;
  57. if (!isFirstLineOfWrappedLine && !isBeginningOfViewLine) {
  58. return this._moveToLineStartByView(viewModel, cursor, inSelectionMode);
  59. }
  60. else {
  61. return this._moveToLineStartByModel(viewModel, cursor, inSelectionMode);
  62. }
  63. }
  64. static _moveToLineStartByView(viewModel, cursor, inSelectionMode) {
  65. return CursorState.fromViewState(MoveOperations.moveToBeginningOfLine(viewModel.cursorConfig, viewModel, cursor.viewState, inSelectionMode));
  66. }
  67. static _moveToLineStartByModel(viewModel, cursor, inSelectionMode) {
  68. return CursorState.fromModelState(MoveOperations.moveToBeginningOfLine(viewModel.cursorConfig, viewModel.model, cursor.modelState, inSelectionMode));
  69. }
  70. static moveToEndOfLine(viewModel, cursors, inSelectionMode, sticky) {
  71. const result = [];
  72. for (let i = 0, len = cursors.length; i < len; i++) {
  73. const cursor = cursors[i];
  74. result[i] = this._moveToLineEnd(viewModel, cursor, inSelectionMode, sticky);
  75. }
  76. return result;
  77. }
  78. static _moveToLineEnd(viewModel, cursor, inSelectionMode, sticky) {
  79. const viewStatePosition = cursor.viewState.position;
  80. const viewModelMaxColumn = viewModel.getLineMaxColumn(viewStatePosition.lineNumber);
  81. const isEndOfViewLine = viewStatePosition.column === viewModelMaxColumn;
  82. const modelStatePosition = cursor.modelState.position;
  83. const modelMaxColumn = viewModel.model.getLineMaxColumn(modelStatePosition.lineNumber);
  84. const isEndLineOfWrappedLine = viewModelMaxColumn - viewStatePosition.column === modelMaxColumn - modelStatePosition.column;
  85. if (isEndOfViewLine || isEndLineOfWrappedLine) {
  86. return this._moveToLineEndByModel(viewModel, cursor, inSelectionMode, sticky);
  87. }
  88. else {
  89. return this._moveToLineEndByView(viewModel, cursor, inSelectionMode, sticky);
  90. }
  91. }
  92. static _moveToLineEndByView(viewModel, cursor, inSelectionMode, sticky) {
  93. return CursorState.fromViewState(MoveOperations.moveToEndOfLine(viewModel.cursorConfig, viewModel, cursor.viewState, inSelectionMode, sticky));
  94. }
  95. static _moveToLineEndByModel(viewModel, cursor, inSelectionMode, sticky) {
  96. return CursorState.fromModelState(MoveOperations.moveToEndOfLine(viewModel.cursorConfig, viewModel.model, cursor.modelState, inSelectionMode, sticky));
  97. }
  98. static expandLineSelection(viewModel, cursors) {
  99. const result = [];
  100. for (let i = 0, len = cursors.length; i < len; i++) {
  101. const cursor = cursors[i];
  102. const startLineNumber = cursor.modelState.selection.startLineNumber;
  103. const lineCount = viewModel.model.getLineCount();
  104. let endLineNumber = cursor.modelState.selection.endLineNumber;
  105. let endColumn;
  106. if (endLineNumber === lineCount) {
  107. endColumn = viewModel.model.getLineMaxColumn(lineCount);
  108. }
  109. else {
  110. endLineNumber++;
  111. endColumn = 1;
  112. }
  113. result[i] = CursorState.fromModelState(new SingleCursorState(new Range(startLineNumber, 1, startLineNumber, 1), 0, new Position(endLineNumber, endColumn), 0));
  114. }
  115. return result;
  116. }
  117. static moveToBeginningOfBuffer(viewModel, cursors, inSelectionMode) {
  118. const result = [];
  119. for (let i = 0, len = cursors.length; i < len; i++) {
  120. const cursor = cursors[i];
  121. result[i] = CursorState.fromModelState(MoveOperations.moveToBeginningOfBuffer(viewModel.cursorConfig, viewModel.model, cursor.modelState, inSelectionMode));
  122. }
  123. return result;
  124. }
  125. static moveToEndOfBuffer(viewModel, cursors, inSelectionMode) {
  126. const result = [];
  127. for (let i = 0, len = cursors.length; i < len; i++) {
  128. const cursor = cursors[i];
  129. result[i] = CursorState.fromModelState(MoveOperations.moveToEndOfBuffer(viewModel.cursorConfig, viewModel.model, cursor.modelState, inSelectionMode));
  130. }
  131. return result;
  132. }
  133. static selectAll(viewModel, cursor) {
  134. const lineCount = viewModel.model.getLineCount();
  135. const maxColumn = viewModel.model.getLineMaxColumn(lineCount);
  136. return CursorState.fromModelState(new SingleCursorState(new Range(1, 1, 1, 1), 0, new Position(lineCount, maxColumn), 0));
  137. }
  138. static line(viewModel, cursor, inSelectionMode, _position, _viewPosition) {
  139. const position = viewModel.model.validatePosition(_position);
  140. const viewPosition = (_viewPosition
  141. ? viewModel.coordinatesConverter.validateViewPosition(new Position(_viewPosition.lineNumber, _viewPosition.column), position)
  142. : viewModel.coordinatesConverter.convertModelPositionToViewPosition(position));
  143. if (!inSelectionMode || !cursor.modelState.hasSelection()) {
  144. // Entering line selection for the first time
  145. const lineCount = viewModel.model.getLineCount();
  146. let selectToLineNumber = position.lineNumber + 1;
  147. let selectToColumn = 1;
  148. if (selectToLineNumber > lineCount) {
  149. selectToLineNumber = lineCount;
  150. selectToColumn = viewModel.model.getLineMaxColumn(selectToLineNumber);
  151. }
  152. return CursorState.fromModelState(new SingleCursorState(new Range(position.lineNumber, 1, selectToLineNumber, selectToColumn), 0, new Position(selectToLineNumber, selectToColumn), 0));
  153. }
  154. // Continuing line selection
  155. const enteringLineNumber = cursor.modelState.selectionStart.getStartPosition().lineNumber;
  156. if (position.lineNumber < enteringLineNumber) {
  157. return CursorState.fromViewState(cursor.viewState.move(cursor.modelState.hasSelection(), viewPosition.lineNumber, 1, 0));
  158. }
  159. else if (position.lineNumber > enteringLineNumber) {
  160. const lineCount = viewModel.getLineCount();
  161. let selectToViewLineNumber = viewPosition.lineNumber + 1;
  162. let selectToViewColumn = 1;
  163. if (selectToViewLineNumber > lineCount) {
  164. selectToViewLineNumber = lineCount;
  165. selectToViewColumn = viewModel.getLineMaxColumn(selectToViewLineNumber);
  166. }
  167. return CursorState.fromViewState(cursor.viewState.move(cursor.modelState.hasSelection(), selectToViewLineNumber, selectToViewColumn, 0));
  168. }
  169. else {
  170. const endPositionOfSelectionStart = cursor.modelState.selectionStart.getEndPosition();
  171. return CursorState.fromModelState(cursor.modelState.move(cursor.modelState.hasSelection(), endPositionOfSelectionStart.lineNumber, endPositionOfSelectionStart.column, 0));
  172. }
  173. }
  174. static word(viewModel, cursor, inSelectionMode, _position) {
  175. const position = viewModel.model.validatePosition(_position);
  176. return CursorState.fromModelState(WordOperations.word(viewModel.cursorConfig, viewModel.model, cursor.modelState, inSelectionMode, position));
  177. }
  178. static cancelSelection(viewModel, cursor) {
  179. if (!cursor.modelState.hasSelection()) {
  180. return new CursorState(cursor.modelState, cursor.viewState);
  181. }
  182. const lineNumber = cursor.viewState.position.lineNumber;
  183. const column = cursor.viewState.position.column;
  184. return CursorState.fromViewState(new SingleCursorState(new Range(lineNumber, column, lineNumber, column), 0, new Position(lineNumber, column), 0));
  185. }
  186. static moveTo(viewModel, cursor, inSelectionMode, _position, _viewPosition) {
  187. const position = viewModel.model.validatePosition(_position);
  188. const viewPosition = (_viewPosition
  189. ? viewModel.coordinatesConverter.validateViewPosition(new Position(_viewPosition.lineNumber, _viewPosition.column), position)
  190. : viewModel.coordinatesConverter.convertModelPositionToViewPosition(position));
  191. return CursorState.fromViewState(cursor.viewState.move(inSelectionMode, viewPosition.lineNumber, viewPosition.column, 0));
  192. }
  193. static simpleMove(viewModel, cursors, direction, inSelectionMode, value, unit) {
  194. switch (direction) {
  195. case 0 /* CursorMove.Direction.Left */: {
  196. if (unit === 4 /* CursorMove.Unit.HalfLine */) {
  197. // Move left by half the current line length
  198. return this._moveHalfLineLeft(viewModel, cursors, inSelectionMode);
  199. }
  200. else {
  201. // Move left by `moveParams.value` columns
  202. return this._moveLeft(viewModel, cursors, inSelectionMode, value);
  203. }
  204. }
  205. case 1 /* CursorMove.Direction.Right */: {
  206. if (unit === 4 /* CursorMove.Unit.HalfLine */) {
  207. // Move right by half the current line length
  208. return this._moveHalfLineRight(viewModel, cursors, inSelectionMode);
  209. }
  210. else {
  211. // Move right by `moveParams.value` columns
  212. return this._moveRight(viewModel, cursors, inSelectionMode, value);
  213. }
  214. }
  215. case 2 /* CursorMove.Direction.Up */: {
  216. if (unit === 2 /* CursorMove.Unit.WrappedLine */) {
  217. // Move up by view lines
  218. return this._moveUpByViewLines(viewModel, cursors, inSelectionMode, value);
  219. }
  220. else {
  221. // Move up by model lines
  222. return this._moveUpByModelLines(viewModel, cursors, inSelectionMode, value);
  223. }
  224. }
  225. case 3 /* CursorMove.Direction.Down */: {
  226. if (unit === 2 /* CursorMove.Unit.WrappedLine */) {
  227. // Move down by view lines
  228. return this._moveDownByViewLines(viewModel, cursors, inSelectionMode, value);
  229. }
  230. else {
  231. // Move down by model lines
  232. return this._moveDownByModelLines(viewModel, cursors, inSelectionMode, value);
  233. }
  234. }
  235. case 4 /* CursorMove.Direction.PrevBlankLine */: {
  236. if (unit === 2 /* CursorMove.Unit.WrappedLine */) {
  237. return cursors.map(cursor => CursorState.fromViewState(MoveOperations.moveToPrevBlankLine(viewModel.cursorConfig, viewModel, cursor.viewState, inSelectionMode)));
  238. }
  239. else {
  240. return cursors.map(cursor => CursorState.fromModelState(MoveOperations.moveToPrevBlankLine(viewModel.cursorConfig, viewModel.model, cursor.modelState, inSelectionMode)));
  241. }
  242. }
  243. case 5 /* CursorMove.Direction.NextBlankLine */: {
  244. if (unit === 2 /* CursorMove.Unit.WrappedLine */) {
  245. return cursors.map(cursor => CursorState.fromViewState(MoveOperations.moveToNextBlankLine(viewModel.cursorConfig, viewModel, cursor.viewState, inSelectionMode)));
  246. }
  247. else {
  248. return cursors.map(cursor => CursorState.fromModelState(MoveOperations.moveToNextBlankLine(viewModel.cursorConfig, viewModel.model, cursor.modelState, inSelectionMode)));
  249. }
  250. }
  251. case 6 /* CursorMove.Direction.WrappedLineStart */: {
  252. // Move to the beginning of the current view line
  253. return this._moveToViewMinColumn(viewModel, cursors, inSelectionMode);
  254. }
  255. case 7 /* CursorMove.Direction.WrappedLineFirstNonWhitespaceCharacter */: {
  256. // Move to the first non-whitespace column of the current view line
  257. return this._moveToViewFirstNonWhitespaceColumn(viewModel, cursors, inSelectionMode);
  258. }
  259. case 8 /* CursorMove.Direction.WrappedLineColumnCenter */: {
  260. // Move to the "center" of the current view line
  261. return this._moveToViewCenterColumn(viewModel, cursors, inSelectionMode);
  262. }
  263. case 9 /* CursorMove.Direction.WrappedLineEnd */: {
  264. // Move to the end of the current view line
  265. return this._moveToViewMaxColumn(viewModel, cursors, inSelectionMode);
  266. }
  267. case 10 /* CursorMove.Direction.WrappedLineLastNonWhitespaceCharacter */: {
  268. // Move to the last non-whitespace column of the current view line
  269. return this._moveToViewLastNonWhitespaceColumn(viewModel, cursors, inSelectionMode);
  270. }
  271. default:
  272. return null;
  273. }
  274. }
  275. static viewportMove(viewModel, cursors, direction, inSelectionMode, value) {
  276. const visibleViewRange = viewModel.getCompletelyVisibleViewRange();
  277. const visibleModelRange = viewModel.coordinatesConverter.convertViewRangeToModelRange(visibleViewRange);
  278. switch (direction) {
  279. case 11 /* CursorMove.Direction.ViewPortTop */: {
  280. // Move to the nth line start in the viewport (from the top)
  281. const modelLineNumber = this._firstLineNumberInRange(viewModel.model, visibleModelRange, value);
  282. const modelColumn = viewModel.model.getLineFirstNonWhitespaceColumn(modelLineNumber);
  283. return [this._moveToModelPosition(viewModel, cursors[0], inSelectionMode, modelLineNumber, modelColumn)];
  284. }
  285. case 13 /* CursorMove.Direction.ViewPortBottom */: {
  286. // Move to the nth line start in the viewport (from the bottom)
  287. const modelLineNumber = this._lastLineNumberInRange(viewModel.model, visibleModelRange, value);
  288. const modelColumn = viewModel.model.getLineFirstNonWhitespaceColumn(modelLineNumber);
  289. return [this._moveToModelPosition(viewModel, cursors[0], inSelectionMode, modelLineNumber, modelColumn)];
  290. }
  291. case 12 /* CursorMove.Direction.ViewPortCenter */: {
  292. // Move to the line start in the viewport center
  293. const modelLineNumber = Math.round((visibleModelRange.startLineNumber + visibleModelRange.endLineNumber) / 2);
  294. const modelColumn = viewModel.model.getLineFirstNonWhitespaceColumn(modelLineNumber);
  295. return [this._moveToModelPosition(viewModel, cursors[0], inSelectionMode, modelLineNumber, modelColumn)];
  296. }
  297. case 14 /* CursorMove.Direction.ViewPortIfOutside */: {
  298. // Move to a position inside the viewport
  299. const result = [];
  300. for (let i = 0, len = cursors.length; i < len; i++) {
  301. const cursor = cursors[i];
  302. result[i] = this.findPositionInViewportIfOutside(viewModel, cursor, visibleViewRange, inSelectionMode);
  303. }
  304. return result;
  305. }
  306. default:
  307. return null;
  308. }
  309. }
  310. static findPositionInViewportIfOutside(viewModel, cursor, visibleViewRange, inSelectionMode) {
  311. const viewLineNumber = cursor.viewState.position.lineNumber;
  312. if (visibleViewRange.startLineNumber <= viewLineNumber && viewLineNumber <= visibleViewRange.endLineNumber - 1) {
  313. // Nothing to do, cursor is in viewport
  314. return new CursorState(cursor.modelState, cursor.viewState);
  315. }
  316. else {
  317. let newViewLineNumber;
  318. if (viewLineNumber > visibleViewRange.endLineNumber - 1) {
  319. newViewLineNumber = visibleViewRange.endLineNumber - 1;
  320. }
  321. else if (viewLineNumber < visibleViewRange.startLineNumber) {
  322. newViewLineNumber = visibleViewRange.startLineNumber;
  323. }
  324. else {
  325. newViewLineNumber = viewLineNumber;
  326. }
  327. const position = MoveOperations.vertical(viewModel.cursorConfig, viewModel, viewLineNumber, cursor.viewState.position.column, cursor.viewState.leftoverVisibleColumns, newViewLineNumber, false);
  328. return CursorState.fromViewState(cursor.viewState.move(inSelectionMode, position.lineNumber, position.column, position.leftoverVisibleColumns));
  329. }
  330. }
  331. /**
  332. * Find the nth line start included in the range (from the start).
  333. */
  334. static _firstLineNumberInRange(model, range, count) {
  335. let startLineNumber = range.startLineNumber;
  336. if (range.startColumn !== model.getLineMinColumn(startLineNumber)) {
  337. // Move on to the second line if the first line start is not included in the range
  338. startLineNumber++;
  339. }
  340. return Math.min(range.endLineNumber, startLineNumber + count - 1);
  341. }
  342. /**
  343. * Find the nth line start included in the range (from the end).
  344. */
  345. static _lastLineNumberInRange(model, range, count) {
  346. let startLineNumber = range.startLineNumber;
  347. if (range.startColumn !== model.getLineMinColumn(startLineNumber)) {
  348. // Move on to the second line if the first line start is not included in the range
  349. startLineNumber++;
  350. }
  351. return Math.max(startLineNumber, range.endLineNumber - count + 1);
  352. }
  353. static _moveLeft(viewModel, cursors, inSelectionMode, noOfColumns) {
  354. return cursors.map(cursor => CursorState.fromViewState(MoveOperations.moveLeft(viewModel.cursorConfig, viewModel, cursor.viewState, inSelectionMode, noOfColumns)));
  355. }
  356. static _moveHalfLineLeft(viewModel, cursors, inSelectionMode) {
  357. const result = [];
  358. for (let i = 0, len = cursors.length; i < len; i++) {
  359. const cursor = cursors[i];
  360. const viewLineNumber = cursor.viewState.position.lineNumber;
  361. const halfLine = Math.round(viewModel.getLineContent(viewLineNumber).length / 2);
  362. result[i] = CursorState.fromViewState(MoveOperations.moveLeft(viewModel.cursorConfig, viewModel, cursor.viewState, inSelectionMode, halfLine));
  363. }
  364. return result;
  365. }
  366. static _moveRight(viewModel, cursors, inSelectionMode, noOfColumns) {
  367. return cursors.map(cursor => CursorState.fromViewState(MoveOperations.moveRight(viewModel.cursorConfig, viewModel, cursor.viewState, inSelectionMode, noOfColumns)));
  368. }
  369. static _moveHalfLineRight(viewModel, cursors, inSelectionMode) {
  370. const result = [];
  371. for (let i = 0, len = cursors.length; i < len; i++) {
  372. const cursor = cursors[i];
  373. const viewLineNumber = cursor.viewState.position.lineNumber;
  374. const halfLine = Math.round(viewModel.getLineContent(viewLineNumber).length / 2);
  375. result[i] = CursorState.fromViewState(MoveOperations.moveRight(viewModel.cursorConfig, viewModel, cursor.viewState, inSelectionMode, halfLine));
  376. }
  377. return result;
  378. }
  379. static _moveDownByViewLines(viewModel, cursors, inSelectionMode, linesCount) {
  380. const result = [];
  381. for (let i = 0, len = cursors.length; i < len; i++) {
  382. const cursor = cursors[i];
  383. result[i] = CursorState.fromViewState(MoveOperations.moveDown(viewModel.cursorConfig, viewModel, cursor.viewState, inSelectionMode, linesCount));
  384. }
  385. return result;
  386. }
  387. static _moveDownByModelLines(viewModel, cursors, inSelectionMode, linesCount) {
  388. const result = [];
  389. for (let i = 0, len = cursors.length; i < len; i++) {
  390. const cursor = cursors[i];
  391. result[i] = CursorState.fromModelState(MoveOperations.moveDown(viewModel.cursorConfig, viewModel.model, cursor.modelState, inSelectionMode, linesCount));
  392. }
  393. return result;
  394. }
  395. static _moveUpByViewLines(viewModel, cursors, inSelectionMode, linesCount) {
  396. const result = [];
  397. for (let i = 0, len = cursors.length; i < len; i++) {
  398. const cursor = cursors[i];
  399. result[i] = CursorState.fromViewState(MoveOperations.moveUp(viewModel.cursorConfig, viewModel, cursor.viewState, inSelectionMode, linesCount));
  400. }
  401. return result;
  402. }
  403. static _moveUpByModelLines(viewModel, cursors, inSelectionMode, linesCount) {
  404. const result = [];
  405. for (let i = 0, len = cursors.length; i < len; i++) {
  406. const cursor = cursors[i];
  407. result[i] = CursorState.fromModelState(MoveOperations.moveUp(viewModel.cursorConfig, viewModel.model, cursor.modelState, inSelectionMode, linesCount));
  408. }
  409. return result;
  410. }
  411. static _moveToViewPosition(viewModel, cursor, inSelectionMode, toViewLineNumber, toViewColumn) {
  412. return CursorState.fromViewState(cursor.viewState.move(inSelectionMode, toViewLineNumber, toViewColumn, 0));
  413. }
  414. static _moveToModelPosition(viewModel, cursor, inSelectionMode, toModelLineNumber, toModelColumn) {
  415. return CursorState.fromModelState(cursor.modelState.move(inSelectionMode, toModelLineNumber, toModelColumn, 0));
  416. }
  417. static _moveToViewMinColumn(viewModel, cursors, inSelectionMode) {
  418. const result = [];
  419. for (let i = 0, len = cursors.length; i < len; i++) {
  420. const cursor = cursors[i];
  421. const viewLineNumber = cursor.viewState.position.lineNumber;
  422. const viewColumn = viewModel.getLineMinColumn(viewLineNumber);
  423. result[i] = this._moveToViewPosition(viewModel, cursor, inSelectionMode, viewLineNumber, viewColumn);
  424. }
  425. return result;
  426. }
  427. static _moveToViewFirstNonWhitespaceColumn(viewModel, cursors, inSelectionMode) {
  428. const result = [];
  429. for (let i = 0, len = cursors.length; i < len; i++) {
  430. const cursor = cursors[i];
  431. const viewLineNumber = cursor.viewState.position.lineNumber;
  432. const viewColumn = viewModel.getLineFirstNonWhitespaceColumn(viewLineNumber);
  433. result[i] = this._moveToViewPosition(viewModel, cursor, inSelectionMode, viewLineNumber, viewColumn);
  434. }
  435. return result;
  436. }
  437. static _moveToViewCenterColumn(viewModel, cursors, inSelectionMode) {
  438. const result = [];
  439. for (let i = 0, len = cursors.length; i < len; i++) {
  440. const cursor = cursors[i];
  441. const viewLineNumber = cursor.viewState.position.lineNumber;
  442. const viewColumn = Math.round((viewModel.getLineMaxColumn(viewLineNumber) + viewModel.getLineMinColumn(viewLineNumber)) / 2);
  443. result[i] = this._moveToViewPosition(viewModel, cursor, inSelectionMode, viewLineNumber, viewColumn);
  444. }
  445. return result;
  446. }
  447. static _moveToViewMaxColumn(viewModel, cursors, inSelectionMode) {
  448. const result = [];
  449. for (let i = 0, len = cursors.length; i < len; i++) {
  450. const cursor = cursors[i];
  451. const viewLineNumber = cursor.viewState.position.lineNumber;
  452. const viewColumn = viewModel.getLineMaxColumn(viewLineNumber);
  453. result[i] = this._moveToViewPosition(viewModel, cursor, inSelectionMode, viewLineNumber, viewColumn);
  454. }
  455. return result;
  456. }
  457. static _moveToViewLastNonWhitespaceColumn(viewModel, cursors, inSelectionMode) {
  458. const result = [];
  459. for (let i = 0, len = cursors.length; i < len; i++) {
  460. const cursor = cursors[i];
  461. const viewLineNumber = cursor.viewState.position.lineNumber;
  462. const viewColumn = viewModel.getLineLastNonWhitespaceColumn(viewLineNumber);
  463. result[i] = this._moveToViewPosition(viewModel, cursor, inSelectionMode, viewLineNumber, viewColumn);
  464. }
  465. return result;
  466. }
  467. }
  468. export var CursorMove;
  469. (function (CursorMove) {
  470. const isCursorMoveArgs = function (arg) {
  471. if (!types.isObject(arg)) {
  472. return false;
  473. }
  474. const cursorMoveArg = arg;
  475. if (!types.isString(cursorMoveArg.to)) {
  476. return false;
  477. }
  478. if (!types.isUndefined(cursorMoveArg.select) && !types.isBoolean(cursorMoveArg.select)) {
  479. return false;
  480. }
  481. if (!types.isUndefined(cursorMoveArg.by) && !types.isString(cursorMoveArg.by)) {
  482. return false;
  483. }
  484. if (!types.isUndefined(cursorMoveArg.value) && !types.isNumber(cursorMoveArg.value)) {
  485. return false;
  486. }
  487. return true;
  488. };
  489. CursorMove.description = {
  490. description: 'Move cursor to a logical position in the view',
  491. args: [
  492. {
  493. name: 'Cursor move argument object',
  494. description: `Property-value pairs that can be passed through this argument:
  495. * 'to': A mandatory logical position value providing where to move the cursor.
  496. \`\`\`
  497. 'left', 'right', 'up', 'down', 'prevBlankLine', 'nextBlankLine',
  498. 'wrappedLineStart', 'wrappedLineEnd', 'wrappedLineColumnCenter'
  499. 'wrappedLineFirstNonWhitespaceCharacter', 'wrappedLineLastNonWhitespaceCharacter'
  500. 'viewPortTop', 'viewPortCenter', 'viewPortBottom', 'viewPortIfOutside'
  501. \`\`\`
  502. * 'by': Unit to move. Default is computed based on 'to' value.
  503. \`\`\`
  504. 'line', 'wrappedLine', 'character', 'halfLine'
  505. \`\`\`
  506. * 'value': Number of units to move. Default is '1'.
  507. * 'select': If 'true' makes the selection. Default is 'false'.
  508. `,
  509. constraint: isCursorMoveArgs,
  510. schema: {
  511. 'type': 'object',
  512. 'required': ['to'],
  513. 'properties': {
  514. 'to': {
  515. 'type': 'string',
  516. 'enum': ['left', 'right', 'up', 'down', 'prevBlankLine', 'nextBlankLine', 'wrappedLineStart', 'wrappedLineEnd', 'wrappedLineColumnCenter', 'wrappedLineFirstNonWhitespaceCharacter', 'wrappedLineLastNonWhitespaceCharacter', 'viewPortTop', 'viewPortCenter', 'viewPortBottom', 'viewPortIfOutside']
  517. },
  518. 'by': {
  519. 'type': 'string',
  520. 'enum': ['line', 'wrappedLine', 'character', 'halfLine']
  521. },
  522. 'value': {
  523. 'type': 'number',
  524. 'default': 1
  525. },
  526. 'select': {
  527. 'type': 'boolean',
  528. 'default': false
  529. }
  530. }
  531. }
  532. }
  533. ]
  534. };
  535. /**
  536. * Positions in the view for cursor move command.
  537. */
  538. CursorMove.RawDirection = {
  539. Left: 'left',
  540. Right: 'right',
  541. Up: 'up',
  542. Down: 'down',
  543. PrevBlankLine: 'prevBlankLine',
  544. NextBlankLine: 'nextBlankLine',
  545. WrappedLineStart: 'wrappedLineStart',
  546. WrappedLineFirstNonWhitespaceCharacter: 'wrappedLineFirstNonWhitespaceCharacter',
  547. WrappedLineColumnCenter: 'wrappedLineColumnCenter',
  548. WrappedLineEnd: 'wrappedLineEnd',
  549. WrappedLineLastNonWhitespaceCharacter: 'wrappedLineLastNonWhitespaceCharacter',
  550. ViewPortTop: 'viewPortTop',
  551. ViewPortCenter: 'viewPortCenter',
  552. ViewPortBottom: 'viewPortBottom',
  553. ViewPortIfOutside: 'viewPortIfOutside'
  554. };
  555. /**
  556. * Units for Cursor move 'by' argument
  557. */
  558. CursorMove.RawUnit = {
  559. Line: 'line',
  560. WrappedLine: 'wrappedLine',
  561. Character: 'character',
  562. HalfLine: 'halfLine'
  563. };
  564. function parse(args) {
  565. if (!args.to) {
  566. // illegal arguments
  567. return null;
  568. }
  569. let direction;
  570. switch (args.to) {
  571. case CursorMove.RawDirection.Left:
  572. direction = 0 /* Direction.Left */;
  573. break;
  574. case CursorMove.RawDirection.Right:
  575. direction = 1 /* Direction.Right */;
  576. break;
  577. case CursorMove.RawDirection.Up:
  578. direction = 2 /* Direction.Up */;
  579. break;
  580. case CursorMove.RawDirection.Down:
  581. direction = 3 /* Direction.Down */;
  582. break;
  583. case CursorMove.RawDirection.PrevBlankLine:
  584. direction = 4 /* Direction.PrevBlankLine */;
  585. break;
  586. case CursorMove.RawDirection.NextBlankLine:
  587. direction = 5 /* Direction.NextBlankLine */;
  588. break;
  589. case CursorMove.RawDirection.WrappedLineStart:
  590. direction = 6 /* Direction.WrappedLineStart */;
  591. break;
  592. case CursorMove.RawDirection.WrappedLineFirstNonWhitespaceCharacter:
  593. direction = 7 /* Direction.WrappedLineFirstNonWhitespaceCharacter */;
  594. break;
  595. case CursorMove.RawDirection.WrappedLineColumnCenter:
  596. direction = 8 /* Direction.WrappedLineColumnCenter */;
  597. break;
  598. case CursorMove.RawDirection.WrappedLineEnd:
  599. direction = 9 /* Direction.WrappedLineEnd */;
  600. break;
  601. case CursorMove.RawDirection.WrappedLineLastNonWhitespaceCharacter:
  602. direction = 10 /* Direction.WrappedLineLastNonWhitespaceCharacter */;
  603. break;
  604. case CursorMove.RawDirection.ViewPortTop:
  605. direction = 11 /* Direction.ViewPortTop */;
  606. break;
  607. case CursorMove.RawDirection.ViewPortBottom:
  608. direction = 13 /* Direction.ViewPortBottom */;
  609. break;
  610. case CursorMove.RawDirection.ViewPortCenter:
  611. direction = 12 /* Direction.ViewPortCenter */;
  612. break;
  613. case CursorMove.RawDirection.ViewPortIfOutside:
  614. direction = 14 /* Direction.ViewPortIfOutside */;
  615. break;
  616. default:
  617. // illegal arguments
  618. return null;
  619. }
  620. let unit = 0 /* Unit.None */;
  621. switch (args.by) {
  622. case CursorMove.RawUnit.Line:
  623. unit = 1 /* Unit.Line */;
  624. break;
  625. case CursorMove.RawUnit.WrappedLine:
  626. unit = 2 /* Unit.WrappedLine */;
  627. break;
  628. case CursorMove.RawUnit.Character:
  629. unit = 3 /* Unit.Character */;
  630. break;
  631. case CursorMove.RawUnit.HalfLine:
  632. unit = 4 /* Unit.HalfLine */;
  633. break;
  634. }
  635. return {
  636. direction: direction,
  637. unit: unit,
  638. select: (!!args.select),
  639. value: (args.value || 1)
  640. };
  641. }
  642. CursorMove.parse = parse;
  643. })(CursorMove || (CursorMove = {}));