dedaa7d05cfbb43c14d427c0278b4429e40ee901c3d77cd048e952ae0c35a5d03f2f9d4a11cd113d964678d14f2b60b8c0d3129371af903c7fc880fe270a62 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443
  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 { EditorAction, EditorCommand, registerEditorAction, registerEditorCommand } from '../../../browser/editorExtensions.js';
  6. import { ReplaceCommand } from '../../../common/commands/replaceCommand.js';
  7. import { EditorOptions } from '../../../common/config/editorOptions.js';
  8. import { CursorState } from '../../../common/cursorCommon.js';
  9. import { WordOperations } from '../../../common/cursor/cursorWordOperations.js';
  10. import { getMapForWordSeparators } from '../../../common/core/wordCharacterClassifier.js';
  11. import { Position } from '../../../common/core/position.js';
  12. import { Range } from '../../../common/core/range.js';
  13. import { Selection } from '../../../common/core/selection.js';
  14. import { EditorContextKeys } from '../../../common/editorContextKeys.js';
  15. import { ILanguageConfigurationService } from '../../../common/languages/languageConfigurationRegistry.js';
  16. import * as nls from '../../../../nls.js';
  17. import { CONTEXT_ACCESSIBILITY_MODE_ENABLED } from '../../../../platform/accessibility/common/accessibility.js';
  18. import { ContextKeyExpr } from '../../../../platform/contextkey/common/contextkey.js';
  19. import { IsWindowsContext } from '../../../../platform/contextkey/common/contextkeys.js';
  20. export class MoveWordCommand extends EditorCommand {
  21. constructor(opts) {
  22. super(opts);
  23. this._inSelectionMode = opts.inSelectionMode;
  24. this._wordNavigationType = opts.wordNavigationType;
  25. }
  26. runEditorCommand(accessor, editor, args) {
  27. if (!editor.hasModel()) {
  28. return;
  29. }
  30. const wordSeparators = getMapForWordSeparators(editor.getOption(119 /* EditorOption.wordSeparators */));
  31. const model = editor.getModel();
  32. const selections = editor.getSelections();
  33. const result = selections.map((sel) => {
  34. const inPosition = new Position(sel.positionLineNumber, sel.positionColumn);
  35. const outPosition = this._move(wordSeparators, model, inPosition, this._wordNavigationType);
  36. return this._moveTo(sel, outPosition, this._inSelectionMode);
  37. });
  38. model.pushStackElement();
  39. editor._getViewModel().setCursorStates('moveWordCommand', 3 /* CursorChangeReason.Explicit */, result.map(r => CursorState.fromModelSelection(r)));
  40. if (result.length === 1) {
  41. const pos = new Position(result[0].positionLineNumber, result[0].positionColumn);
  42. editor.revealPosition(pos, 0 /* ScrollType.Smooth */);
  43. }
  44. }
  45. _moveTo(from, to, inSelectionMode) {
  46. if (inSelectionMode) {
  47. // move just position
  48. return new Selection(from.selectionStartLineNumber, from.selectionStartColumn, to.lineNumber, to.column);
  49. }
  50. else {
  51. // move everything
  52. return new Selection(to.lineNumber, to.column, to.lineNumber, to.column);
  53. }
  54. }
  55. }
  56. export class WordLeftCommand extends MoveWordCommand {
  57. _move(wordSeparators, model, position, wordNavigationType) {
  58. return WordOperations.moveWordLeft(wordSeparators, model, position, wordNavigationType);
  59. }
  60. }
  61. export class WordRightCommand extends MoveWordCommand {
  62. _move(wordSeparators, model, position, wordNavigationType) {
  63. return WordOperations.moveWordRight(wordSeparators, model, position, wordNavigationType);
  64. }
  65. }
  66. export class CursorWordStartLeft extends WordLeftCommand {
  67. constructor() {
  68. super({
  69. inSelectionMode: false,
  70. wordNavigationType: 0 /* WordNavigationType.WordStart */,
  71. id: 'cursorWordStartLeft',
  72. precondition: undefined
  73. });
  74. }
  75. }
  76. export class CursorWordEndLeft extends WordLeftCommand {
  77. constructor() {
  78. super({
  79. inSelectionMode: false,
  80. wordNavigationType: 2 /* WordNavigationType.WordEnd */,
  81. id: 'cursorWordEndLeft',
  82. precondition: undefined
  83. });
  84. }
  85. }
  86. export class CursorWordLeft extends WordLeftCommand {
  87. constructor() {
  88. var _a;
  89. super({
  90. inSelectionMode: false,
  91. wordNavigationType: 1 /* WordNavigationType.WordStartFast */,
  92. id: 'cursorWordLeft',
  93. precondition: undefined,
  94. kbOpts: {
  95. kbExpr: ContextKeyExpr.and(EditorContextKeys.textInputFocus, (_a = ContextKeyExpr.and(CONTEXT_ACCESSIBILITY_MODE_ENABLED, IsWindowsContext)) === null || _a === void 0 ? void 0 : _a.negate()),
  96. primary: 2048 /* KeyMod.CtrlCmd */ | 15 /* KeyCode.LeftArrow */,
  97. mac: { primary: 512 /* KeyMod.Alt */ | 15 /* KeyCode.LeftArrow */ },
  98. weight: 100 /* KeybindingWeight.EditorContrib */
  99. }
  100. });
  101. }
  102. }
  103. export class CursorWordStartLeftSelect extends WordLeftCommand {
  104. constructor() {
  105. super({
  106. inSelectionMode: true,
  107. wordNavigationType: 0 /* WordNavigationType.WordStart */,
  108. id: 'cursorWordStartLeftSelect',
  109. precondition: undefined
  110. });
  111. }
  112. }
  113. export class CursorWordEndLeftSelect extends WordLeftCommand {
  114. constructor() {
  115. super({
  116. inSelectionMode: true,
  117. wordNavigationType: 2 /* WordNavigationType.WordEnd */,
  118. id: 'cursorWordEndLeftSelect',
  119. precondition: undefined
  120. });
  121. }
  122. }
  123. export class CursorWordLeftSelect extends WordLeftCommand {
  124. constructor() {
  125. var _a;
  126. super({
  127. inSelectionMode: true,
  128. wordNavigationType: 1 /* WordNavigationType.WordStartFast */,
  129. id: 'cursorWordLeftSelect',
  130. precondition: undefined,
  131. kbOpts: {
  132. kbExpr: ContextKeyExpr.and(EditorContextKeys.textInputFocus, (_a = ContextKeyExpr.and(CONTEXT_ACCESSIBILITY_MODE_ENABLED, IsWindowsContext)) === null || _a === void 0 ? void 0 : _a.negate()),
  133. primary: 2048 /* KeyMod.CtrlCmd */ | 1024 /* KeyMod.Shift */ | 15 /* KeyCode.LeftArrow */,
  134. mac: { primary: 512 /* KeyMod.Alt */ | 1024 /* KeyMod.Shift */ | 15 /* KeyCode.LeftArrow */ },
  135. weight: 100 /* KeybindingWeight.EditorContrib */
  136. }
  137. });
  138. }
  139. }
  140. // Accessibility navigation commands should only be enabled on windows since they are tuned to what NVDA expects
  141. export class CursorWordAccessibilityLeft extends WordLeftCommand {
  142. constructor() {
  143. super({
  144. inSelectionMode: false,
  145. wordNavigationType: 3 /* WordNavigationType.WordAccessibility */,
  146. id: 'cursorWordAccessibilityLeft',
  147. precondition: undefined
  148. });
  149. }
  150. _move(_, model, position, wordNavigationType) {
  151. return super._move(getMapForWordSeparators(EditorOptions.wordSeparators.defaultValue), model, position, wordNavigationType);
  152. }
  153. }
  154. export class CursorWordAccessibilityLeftSelect extends WordLeftCommand {
  155. constructor() {
  156. super({
  157. inSelectionMode: true,
  158. wordNavigationType: 3 /* WordNavigationType.WordAccessibility */,
  159. id: 'cursorWordAccessibilityLeftSelect',
  160. precondition: undefined
  161. });
  162. }
  163. _move(_, model, position, wordNavigationType) {
  164. return super._move(getMapForWordSeparators(EditorOptions.wordSeparators.defaultValue), model, position, wordNavigationType);
  165. }
  166. }
  167. export class CursorWordStartRight extends WordRightCommand {
  168. constructor() {
  169. super({
  170. inSelectionMode: false,
  171. wordNavigationType: 0 /* WordNavigationType.WordStart */,
  172. id: 'cursorWordStartRight',
  173. precondition: undefined
  174. });
  175. }
  176. }
  177. export class CursorWordEndRight extends WordRightCommand {
  178. constructor() {
  179. var _a;
  180. super({
  181. inSelectionMode: false,
  182. wordNavigationType: 2 /* WordNavigationType.WordEnd */,
  183. id: 'cursorWordEndRight',
  184. precondition: undefined,
  185. kbOpts: {
  186. kbExpr: ContextKeyExpr.and(EditorContextKeys.textInputFocus, (_a = ContextKeyExpr.and(CONTEXT_ACCESSIBILITY_MODE_ENABLED, IsWindowsContext)) === null || _a === void 0 ? void 0 : _a.negate()),
  187. primary: 2048 /* KeyMod.CtrlCmd */ | 17 /* KeyCode.RightArrow */,
  188. mac: { primary: 512 /* KeyMod.Alt */ | 17 /* KeyCode.RightArrow */ },
  189. weight: 100 /* KeybindingWeight.EditorContrib */
  190. }
  191. });
  192. }
  193. }
  194. export class CursorWordRight extends WordRightCommand {
  195. constructor() {
  196. super({
  197. inSelectionMode: false,
  198. wordNavigationType: 2 /* WordNavigationType.WordEnd */,
  199. id: 'cursorWordRight',
  200. precondition: undefined
  201. });
  202. }
  203. }
  204. export class CursorWordStartRightSelect extends WordRightCommand {
  205. constructor() {
  206. super({
  207. inSelectionMode: true,
  208. wordNavigationType: 0 /* WordNavigationType.WordStart */,
  209. id: 'cursorWordStartRightSelect',
  210. precondition: undefined
  211. });
  212. }
  213. }
  214. export class CursorWordEndRightSelect extends WordRightCommand {
  215. constructor() {
  216. var _a;
  217. super({
  218. inSelectionMode: true,
  219. wordNavigationType: 2 /* WordNavigationType.WordEnd */,
  220. id: 'cursorWordEndRightSelect',
  221. precondition: undefined,
  222. kbOpts: {
  223. kbExpr: ContextKeyExpr.and(EditorContextKeys.textInputFocus, (_a = ContextKeyExpr.and(CONTEXT_ACCESSIBILITY_MODE_ENABLED, IsWindowsContext)) === null || _a === void 0 ? void 0 : _a.negate()),
  224. primary: 2048 /* KeyMod.CtrlCmd */ | 1024 /* KeyMod.Shift */ | 17 /* KeyCode.RightArrow */,
  225. mac: { primary: 512 /* KeyMod.Alt */ | 1024 /* KeyMod.Shift */ | 17 /* KeyCode.RightArrow */ },
  226. weight: 100 /* KeybindingWeight.EditorContrib */
  227. }
  228. });
  229. }
  230. }
  231. export class CursorWordRightSelect extends WordRightCommand {
  232. constructor() {
  233. super({
  234. inSelectionMode: true,
  235. wordNavigationType: 2 /* WordNavigationType.WordEnd */,
  236. id: 'cursorWordRightSelect',
  237. precondition: undefined
  238. });
  239. }
  240. }
  241. export class CursorWordAccessibilityRight extends WordRightCommand {
  242. constructor() {
  243. super({
  244. inSelectionMode: false,
  245. wordNavigationType: 3 /* WordNavigationType.WordAccessibility */,
  246. id: 'cursorWordAccessibilityRight',
  247. precondition: undefined
  248. });
  249. }
  250. _move(_, model, position, wordNavigationType) {
  251. return super._move(getMapForWordSeparators(EditorOptions.wordSeparators.defaultValue), model, position, wordNavigationType);
  252. }
  253. }
  254. export class CursorWordAccessibilityRightSelect extends WordRightCommand {
  255. constructor() {
  256. super({
  257. inSelectionMode: true,
  258. wordNavigationType: 3 /* WordNavigationType.WordAccessibility */,
  259. id: 'cursorWordAccessibilityRightSelect',
  260. precondition: undefined
  261. });
  262. }
  263. _move(_, model, position, wordNavigationType) {
  264. return super._move(getMapForWordSeparators(EditorOptions.wordSeparators.defaultValue), model, position, wordNavigationType);
  265. }
  266. }
  267. export class DeleteWordCommand extends EditorCommand {
  268. constructor(opts) {
  269. super(opts);
  270. this._whitespaceHeuristics = opts.whitespaceHeuristics;
  271. this._wordNavigationType = opts.wordNavigationType;
  272. }
  273. runEditorCommand(accessor, editor, args) {
  274. const languageConfigurationService = accessor.get(ILanguageConfigurationService);
  275. if (!editor.hasModel()) {
  276. return;
  277. }
  278. const wordSeparators = getMapForWordSeparators(editor.getOption(119 /* EditorOption.wordSeparators */));
  279. const model = editor.getModel();
  280. const selections = editor.getSelections();
  281. const autoClosingBrackets = editor.getOption(5 /* EditorOption.autoClosingBrackets */);
  282. const autoClosingQuotes = editor.getOption(8 /* EditorOption.autoClosingQuotes */);
  283. const autoClosingPairs = languageConfigurationService.getLanguageConfiguration(model.getLanguageId()).getAutoClosingPairs();
  284. const viewModel = editor._getViewModel();
  285. const commands = selections.map((sel) => {
  286. const deleteRange = this._delete({
  287. wordSeparators,
  288. model,
  289. selection: sel,
  290. whitespaceHeuristics: this._whitespaceHeuristics,
  291. autoClosingDelete: editor.getOption(6 /* EditorOption.autoClosingDelete */),
  292. autoClosingBrackets,
  293. autoClosingQuotes,
  294. autoClosingPairs,
  295. autoClosedCharacters: viewModel.getCursorAutoClosedCharacters()
  296. }, this._wordNavigationType);
  297. return new ReplaceCommand(deleteRange, '');
  298. });
  299. editor.pushUndoStop();
  300. editor.executeCommands(this.id, commands);
  301. editor.pushUndoStop();
  302. }
  303. }
  304. export class DeleteWordLeftCommand extends DeleteWordCommand {
  305. _delete(ctx, wordNavigationType) {
  306. const r = WordOperations.deleteWordLeft(ctx, wordNavigationType);
  307. if (r) {
  308. return r;
  309. }
  310. return new Range(1, 1, 1, 1);
  311. }
  312. }
  313. export class DeleteWordRightCommand extends DeleteWordCommand {
  314. _delete(ctx, wordNavigationType) {
  315. const r = WordOperations.deleteWordRight(ctx, wordNavigationType);
  316. if (r) {
  317. return r;
  318. }
  319. const lineCount = ctx.model.getLineCount();
  320. const maxColumn = ctx.model.getLineMaxColumn(lineCount);
  321. return new Range(lineCount, maxColumn, lineCount, maxColumn);
  322. }
  323. }
  324. export class DeleteWordStartLeft extends DeleteWordLeftCommand {
  325. constructor() {
  326. super({
  327. whitespaceHeuristics: false,
  328. wordNavigationType: 0 /* WordNavigationType.WordStart */,
  329. id: 'deleteWordStartLeft',
  330. precondition: EditorContextKeys.writable
  331. });
  332. }
  333. }
  334. export class DeleteWordEndLeft extends DeleteWordLeftCommand {
  335. constructor() {
  336. super({
  337. whitespaceHeuristics: false,
  338. wordNavigationType: 2 /* WordNavigationType.WordEnd */,
  339. id: 'deleteWordEndLeft',
  340. precondition: EditorContextKeys.writable
  341. });
  342. }
  343. }
  344. export class DeleteWordLeft extends DeleteWordLeftCommand {
  345. constructor() {
  346. super({
  347. whitespaceHeuristics: true,
  348. wordNavigationType: 0 /* WordNavigationType.WordStart */,
  349. id: 'deleteWordLeft',
  350. precondition: EditorContextKeys.writable,
  351. kbOpts: {
  352. kbExpr: EditorContextKeys.textInputFocus,
  353. primary: 2048 /* KeyMod.CtrlCmd */ | 1 /* KeyCode.Backspace */,
  354. mac: { primary: 512 /* KeyMod.Alt */ | 1 /* KeyCode.Backspace */ },
  355. weight: 100 /* KeybindingWeight.EditorContrib */
  356. }
  357. });
  358. }
  359. }
  360. export class DeleteWordStartRight extends DeleteWordRightCommand {
  361. constructor() {
  362. super({
  363. whitespaceHeuristics: false,
  364. wordNavigationType: 0 /* WordNavigationType.WordStart */,
  365. id: 'deleteWordStartRight',
  366. precondition: EditorContextKeys.writable
  367. });
  368. }
  369. }
  370. export class DeleteWordEndRight extends DeleteWordRightCommand {
  371. constructor() {
  372. super({
  373. whitespaceHeuristics: false,
  374. wordNavigationType: 2 /* WordNavigationType.WordEnd */,
  375. id: 'deleteWordEndRight',
  376. precondition: EditorContextKeys.writable
  377. });
  378. }
  379. }
  380. export class DeleteWordRight extends DeleteWordRightCommand {
  381. constructor() {
  382. super({
  383. whitespaceHeuristics: true,
  384. wordNavigationType: 2 /* WordNavigationType.WordEnd */,
  385. id: 'deleteWordRight',
  386. precondition: EditorContextKeys.writable,
  387. kbOpts: {
  388. kbExpr: EditorContextKeys.textInputFocus,
  389. primary: 2048 /* KeyMod.CtrlCmd */ | 20 /* KeyCode.Delete */,
  390. mac: { primary: 512 /* KeyMod.Alt */ | 20 /* KeyCode.Delete */ },
  391. weight: 100 /* KeybindingWeight.EditorContrib */
  392. }
  393. });
  394. }
  395. }
  396. export class DeleteInsideWord extends EditorAction {
  397. constructor() {
  398. super({
  399. id: 'deleteInsideWord',
  400. precondition: EditorContextKeys.writable,
  401. label: nls.localize('deleteInsideWord', "Delete Word"),
  402. alias: 'Delete Word'
  403. });
  404. }
  405. run(accessor, editor, args) {
  406. if (!editor.hasModel()) {
  407. return;
  408. }
  409. const wordSeparators = getMapForWordSeparators(editor.getOption(119 /* EditorOption.wordSeparators */));
  410. const model = editor.getModel();
  411. const selections = editor.getSelections();
  412. const commands = selections.map((sel) => {
  413. const deleteRange = WordOperations.deleteInsideWord(wordSeparators, model, sel);
  414. return new ReplaceCommand(deleteRange, '');
  415. });
  416. editor.pushUndoStop();
  417. editor.executeCommands(this.id, commands);
  418. editor.pushUndoStop();
  419. }
  420. }
  421. registerEditorCommand(new CursorWordStartLeft());
  422. registerEditorCommand(new CursorWordEndLeft());
  423. registerEditorCommand(new CursorWordLeft());
  424. registerEditorCommand(new CursorWordStartLeftSelect());
  425. registerEditorCommand(new CursorWordEndLeftSelect());
  426. registerEditorCommand(new CursorWordLeftSelect());
  427. registerEditorCommand(new CursorWordStartRight());
  428. registerEditorCommand(new CursorWordEndRight());
  429. registerEditorCommand(new CursorWordRight());
  430. registerEditorCommand(new CursorWordStartRightSelect());
  431. registerEditorCommand(new CursorWordEndRightSelect());
  432. registerEditorCommand(new CursorWordRightSelect());
  433. registerEditorCommand(new CursorWordAccessibilityLeft());
  434. registerEditorCommand(new CursorWordAccessibilityLeftSelect());
  435. registerEditorCommand(new CursorWordAccessibilityRight());
  436. registerEditorCommand(new CursorWordAccessibilityRightSelect());
  437. registerEditorCommand(new DeleteWordStartLeft());
  438. registerEditorCommand(new DeleteWordEndLeft());
  439. registerEditorCommand(new DeleteWordLeft());
  440. registerEditorCommand(new DeleteWordStartRight());
  441. registerEditorCommand(new DeleteWordEndRight());
  442. registerEditorCommand(new DeleteWordRight());
  443. registerEditorAction(DeleteInsideWord);