keybinding-vim.js 56 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758
  1. ace.define("ace/keyboard/vim/registers",["require","exports","module"], function(require, exports, module) {
  2. "never use strict";
  3. module.exports = {
  4. _default: {
  5. text: "",
  6. isLine: false
  7. }
  8. };
  9. });
  10. ace.define("ace/keyboard/vim/maps/util",["require","exports","module","ace/keyboard/vim/registers","ace/lib/dom"], function(require, exports, module) {
  11. var registers = require("../registers");
  12. var dom = require("../../../lib/dom");
  13. dom.importCssString('.insert-mode .ace_cursor{\
  14. border-left: 2px solid #333333;\
  15. }\
  16. .ace_dark.insert-mode .ace_cursor{\
  17. border-left: 2px solid #eeeeee;\
  18. }\
  19. .normal-mode .ace_cursor{\
  20. border: 0!important;\
  21. background-color: red;\
  22. opacity: 0.5;\
  23. }', 'vimMode');
  24. module.exports = {
  25. onVisualMode: false,
  26. onVisualLineMode: false,
  27. currentMode: 'normal',
  28. noMode: function(editor) {
  29. editor.unsetStyle('insert-mode');
  30. editor.unsetStyle('normal-mode');
  31. if (editor.commands.recording)
  32. editor.commands.toggleRecording(editor);
  33. editor.setOverwrite(false);
  34. },
  35. insertMode: function(editor) {
  36. this.currentMode = 'insert';
  37. editor.setStyle('insert-mode');
  38. editor.unsetStyle('normal-mode');
  39. editor.setOverwrite(false);
  40. editor.keyBinding.$data.buffer = "";
  41. editor.keyBinding.$data.vimState = "insertMode";
  42. this.onVisualMode = false;
  43. this.onVisualLineMode = false;
  44. if(this.onInsertReplaySequence) {
  45. editor.commands.macro = this.onInsertReplaySequence;
  46. editor.commands.replay(editor);
  47. this.onInsertReplaySequence = null;
  48. this.normalMode(editor);
  49. } else {
  50. editor._emit("changeStatus");
  51. if(!editor.commands.recording)
  52. editor.commands.toggleRecording(editor);
  53. }
  54. },
  55. normalMode: function(editor) {
  56. this.currentMode = 'normal';
  57. editor.unsetStyle('insert-mode');
  58. editor.setStyle('normal-mode');
  59. editor.clearSelection();
  60. var pos;
  61. if (!editor.getOverwrite()) {
  62. pos = editor.getCursorPosition();
  63. if (pos.column > 0)
  64. editor.navigateLeft();
  65. }
  66. editor.setOverwrite(true);
  67. editor.keyBinding.$data.buffer = "";
  68. editor.keyBinding.$data.vimState = "start";
  69. this.onVisualMode = false;
  70. this.onVisualLineMode = false;
  71. editor._emit("changeStatus");
  72. if (editor.commands.recording) {
  73. editor.commands.toggleRecording(editor);
  74. return editor.commands.macro;
  75. }
  76. else {
  77. return [];
  78. }
  79. },
  80. visualMode: function(editor, lineMode) {
  81. if (
  82. (this.onVisualLineMode && lineMode)
  83. || (this.onVisualMode && !lineMode)
  84. ) {
  85. this.normalMode(editor);
  86. return;
  87. }
  88. editor.setStyle('insert-mode');
  89. editor.unsetStyle('normal-mode');
  90. editor._emit("changeStatus");
  91. if (lineMode) {
  92. this.onVisualLineMode = true;
  93. } else {
  94. this.onVisualMode = true;
  95. this.onVisualLineMode = false;
  96. }
  97. },
  98. getRightNthChar: function(editor, cursor, ch, n) {
  99. var line = editor.getSession().getLine(cursor.row);
  100. var matches = line.substr(cursor.column + 1).split(ch);
  101. return n < matches.length ? matches.slice(0, n).join(ch).length : null;
  102. },
  103. getLeftNthChar: function(editor, cursor, ch, n) {
  104. var line = editor.getSession().getLine(cursor.row);
  105. var matches = line.substr(0, cursor.column).split(ch);
  106. return n < matches.length ? matches.slice(-1 * n).join(ch).length : null;
  107. },
  108. toRealChar: function(ch) {
  109. if (ch.length === 1)
  110. return ch;
  111. if (/^shift-./.test(ch))
  112. return ch[ch.length - 1].toUpperCase();
  113. else
  114. return "";
  115. },
  116. copyLine: function(editor) {
  117. var pos = editor.getCursorPosition();
  118. editor.selection.moveTo(pos.row, pos.column);
  119. editor.selection.selectLine();
  120. registers._default.isLine = true;
  121. registers._default.text = editor.getCopyText().replace(/\n$/, "");
  122. editor.selection.moveTo(pos.row, pos.column);
  123. }
  124. };
  125. });
  126. ace.define("ace/keyboard/vim/maps/motions",["require","exports","module","ace/keyboard/vim/maps/util","ace/search","ace/range"], function(require, exports, module) {
  127. "use strict";
  128. var util = require("./util");
  129. var keepScrollPosition = function(editor, fn) {
  130. var scrollTopRow = editor.renderer.getScrollTopRow();
  131. var initialRow = editor.getCursorPosition().row;
  132. var diff = initialRow - scrollTopRow;
  133. fn && fn.call(editor);
  134. editor.renderer.scrollToRow(editor.getCursorPosition().row - diff);
  135. };
  136. function Motion(m) {
  137. if (typeof m == "function") {
  138. var getPos = m;
  139. m = this;
  140. } else {
  141. var getPos = m.getPos;
  142. }
  143. m.nav = function(editor, range, count, param) {
  144. var a = getPos(editor, range, count, param, false);
  145. if (!a)
  146. return;
  147. editor.selection.moveTo(a.row, a.column);
  148. };
  149. m.sel = function(editor, range, count, param) {
  150. var a = getPos(editor, range, count, param, true);
  151. if (!a)
  152. return;
  153. editor.selection.selectTo(a.row, a.column);
  154. };
  155. return m;
  156. }
  157. var nonWordRe = /[\s.\/\\()\"'-:,.;<>~!@#$%^&*|+=\[\]{}`~?]/;
  158. var wordSeparatorRe = /[.\/\\()\"'-:,.;<>~!@#$%^&*|+=\[\]{}`~?]/;
  159. var whiteRe = /\s/;
  160. var StringStream = function(editor, cursor) {
  161. var sel = editor.selection;
  162. this.range = sel.getRange();
  163. cursor = cursor || sel.selectionLead;
  164. this.row = cursor.row;
  165. this.col = cursor.column;
  166. var line = editor.session.getLine(this.row);
  167. var maxRow = editor.session.getLength();
  168. this.ch = line[this.col] || '\n';
  169. this.skippedLines = 0;
  170. this.next = function() {
  171. this.ch = line[++this.col] || this.handleNewLine(1);
  172. return this.ch;
  173. };
  174. this.prev = function() {
  175. this.ch = line[--this.col] || this.handleNewLine(-1);
  176. return this.ch;
  177. };
  178. this.peek = function(dir) {
  179. var ch = line[this.col + dir];
  180. if (ch)
  181. return ch;
  182. if (dir == -1)
  183. return '\n';
  184. if (this.col == line.length - 1)
  185. return '\n';
  186. return editor.session.getLine(this.row + 1)[0] || '\n';
  187. };
  188. this.handleNewLine = function(dir) {
  189. if (dir == 1){
  190. if (this.col == line.length)
  191. return '\n';
  192. if (this.row == maxRow - 1)
  193. return '';
  194. this.col = 0;
  195. this.row ++;
  196. line = editor.session.getLine(this.row);
  197. this.skippedLines++;
  198. return line[0] || '\n';
  199. }
  200. if (dir == -1) {
  201. if (this.row === 0)
  202. return '';
  203. this.row --;
  204. line = editor.session.getLine(this.row);
  205. this.col = line.length;
  206. this.skippedLines--;
  207. return '\n';
  208. }
  209. };
  210. this.debug = function() {
  211. console.log(line.substring(0, this.col)+'|'+this.ch+'\''+this.col+'\''+line.substr(this.col+1));
  212. };
  213. };
  214. var Search = require("../../../search").Search;
  215. var search = new Search();
  216. function find(editor, needle, dir) {
  217. search.$options.needle = needle;
  218. search.$options.backwards = dir == -1;
  219. return search.find(editor.session);
  220. }
  221. var Range = require("../../../range").Range;
  222. var LAST_SEARCH_MOTION = {};
  223. module.exports = {
  224. "w": new Motion(function(editor) {
  225. var str = new StringStream(editor);
  226. if (str.ch && wordSeparatorRe.test(str.ch)) {
  227. while (str.ch && wordSeparatorRe.test(str.ch))
  228. str.next();
  229. } else {
  230. while (str.ch && !nonWordRe.test(str.ch))
  231. str.next();
  232. }
  233. while (str.ch && whiteRe.test(str.ch) && str.skippedLines < 2)
  234. str.next();
  235. str.skippedLines == 2 && str.prev();
  236. return {column: str.col, row: str.row};
  237. }),
  238. "W": new Motion(function(editor) {
  239. var str = new StringStream(editor);
  240. while(str.ch && !(whiteRe.test(str.ch) && !whiteRe.test(str.peek(1))) && str.skippedLines < 2)
  241. str.next();
  242. if (str.skippedLines == 2)
  243. str.prev();
  244. else
  245. str.next();
  246. return {column: str.col, row: str.row};
  247. }),
  248. "b": new Motion(function(editor) {
  249. var str = new StringStream(editor);
  250. str.prev();
  251. while (str.ch && whiteRe.test(str.ch) && str.skippedLines > -2)
  252. str.prev();
  253. if (str.ch && wordSeparatorRe.test(str.ch)) {
  254. while (str.ch && wordSeparatorRe.test(str.ch))
  255. str.prev();
  256. } else {
  257. while (str.ch && !nonWordRe.test(str.ch))
  258. str.prev();
  259. }
  260. str.ch && str.next();
  261. return {column: str.col, row: str.row};
  262. }),
  263. "B": new Motion(function(editor) {
  264. var str = new StringStream(editor);
  265. str.prev();
  266. while(str.ch && !(!whiteRe.test(str.ch) && whiteRe.test(str.peek(-1))) && str.skippedLines > -2)
  267. str.prev();
  268. if (str.skippedLines == -2)
  269. str.next();
  270. return {column: str.col, row: str.row};
  271. }),
  272. "e": new Motion(function(editor) {
  273. var str = new StringStream(editor);
  274. str.next();
  275. while (str.ch && whiteRe.test(str.ch))
  276. str.next();
  277. if (str.ch && wordSeparatorRe.test(str.ch)) {
  278. while (str.ch && wordSeparatorRe.test(str.ch))
  279. str.next();
  280. } else {
  281. while (str.ch && !nonWordRe.test(str.ch))
  282. str.next();
  283. }
  284. str.ch && str.prev();
  285. return {column: str.col, row: str.row};
  286. }),
  287. "E": new Motion(function(editor) {
  288. var str = new StringStream(editor);
  289. str.next();
  290. while(str.ch && !(!whiteRe.test(str.ch) && whiteRe.test(str.peek(1))))
  291. str.next();
  292. return {column: str.col, row: str.row};
  293. }),
  294. "l": {
  295. nav: function(editor) {
  296. var pos = editor.getCursorPosition();
  297. var col = pos.column;
  298. var lineLen = editor.session.getLine(pos.row).length;
  299. if (lineLen && col !== lineLen)
  300. editor.navigateRight();
  301. },
  302. sel: function(editor) {
  303. var pos = editor.getCursorPosition();
  304. var col = pos.column;
  305. var lineLen = editor.session.getLine(pos.row).length;
  306. if (lineLen && col !== lineLen) //In selection mode you can select the newline
  307. editor.selection.selectRight();
  308. }
  309. },
  310. "h": {
  311. nav: function(editor) {
  312. var pos = editor.getCursorPosition();
  313. if (pos.column > 0)
  314. editor.navigateLeft();
  315. },
  316. sel: function(editor) {
  317. var pos = editor.getCursorPosition();
  318. if (pos.column > 0)
  319. editor.selection.selectLeft();
  320. }
  321. },
  322. "H": {
  323. nav: function(editor) {
  324. var row = editor.renderer.getScrollTopRow();
  325. editor.moveCursorTo(row);
  326. },
  327. sel: function(editor) {
  328. var row = editor.renderer.getScrollTopRow();
  329. editor.selection.selectTo(row);
  330. }
  331. },
  332. "M": {
  333. nav: function(editor) {
  334. var topRow = editor.renderer.getScrollTopRow();
  335. var bottomRow = editor.renderer.getScrollBottomRow();
  336. var row = topRow + ((bottomRow - topRow) / 2);
  337. editor.moveCursorTo(row);
  338. },
  339. sel: function(editor) {
  340. var topRow = editor.renderer.getScrollTopRow();
  341. var bottomRow = editor.renderer.getScrollBottomRow();
  342. var row = topRow + ((bottomRow - topRow) / 2);
  343. editor.selection.selectTo(row);
  344. }
  345. },
  346. "L": {
  347. nav: function(editor) {
  348. var row = editor.renderer.getScrollBottomRow();
  349. editor.moveCursorTo(row);
  350. },
  351. sel: function(editor) {
  352. var row = editor.renderer.getScrollBottomRow();
  353. editor.selection.selectTo(row);
  354. }
  355. },
  356. "k": {
  357. nav: function(editor) {
  358. editor.navigateUp();
  359. },
  360. sel: function(editor) {
  361. editor.selection.selectUp();
  362. }
  363. },
  364. "j": {
  365. nav: function(editor) {
  366. editor.navigateDown();
  367. },
  368. sel: function(editor) {
  369. editor.selection.selectDown();
  370. }
  371. },
  372. "i": {
  373. param: true,
  374. sel: function(editor, range, count, param) {
  375. switch (param) {
  376. case "w":
  377. editor.selection.selectWord();
  378. break;
  379. case "W":
  380. editor.selection.selectAWord();
  381. break;
  382. case "(":
  383. case "{":
  384. case "[":
  385. var cursor = editor.getCursorPosition();
  386. var end = editor.session.$findClosingBracket(param, cursor, /paren/);
  387. if (!end)
  388. return;
  389. var start = editor.session.$findOpeningBracket(editor.session.$brackets[param], cursor, /paren/);
  390. if (!start)
  391. return;
  392. start.column ++;
  393. editor.selection.setSelectionRange(Range.fromPoints(start, end));
  394. break;
  395. case "'":
  396. case '"':
  397. case "/":
  398. var end = find(editor, param, 1);
  399. if (!end)
  400. return;
  401. var start = find(editor, param, -1);
  402. if (!start)
  403. return;
  404. editor.selection.setSelectionRange(Range.fromPoints(start.end, end.start));
  405. break;
  406. }
  407. }
  408. },
  409. "a": {
  410. param: true,
  411. sel: function(editor, range, count, param) {
  412. switch (param) {
  413. case "w":
  414. editor.selection.selectAWord();
  415. break;
  416. case "W":
  417. editor.selection.selectAWord();
  418. break;
  419. case ")":
  420. case "}":
  421. case "]":
  422. param = editor.session.$brackets[param];
  423. case "(":
  424. case "{":
  425. case "[":
  426. var cursor = editor.getCursorPosition();
  427. var end = editor.session.$findClosingBracket(param, cursor, /paren/);
  428. if (!end)
  429. return;
  430. var start = editor.session.$findOpeningBracket(editor.session.$brackets[param], cursor, /paren/);
  431. if (!start)
  432. return;
  433. end.column ++;
  434. editor.selection.setSelectionRange(Range.fromPoints(start, end));
  435. break;
  436. case "'":
  437. case "\"":
  438. case "/":
  439. var end = find(editor, param, 1);
  440. if (!end)
  441. return;
  442. var start = find(editor, param, -1);
  443. if (!start)
  444. return;
  445. end.column ++;
  446. editor.selection.setSelectionRange(Range.fromPoints(start.start, end.end));
  447. break;
  448. }
  449. }
  450. },
  451. "f": new Motion({
  452. param: true,
  453. handlesCount: true,
  454. getPos: function(editor, range, count, param, isSel, isRepeat) {
  455. if (param == "space") param = " ";
  456. if (!isRepeat)
  457. LAST_SEARCH_MOTION = {ch: "f", param: param};
  458. var cursor = editor.getCursorPosition();
  459. var column = util.getRightNthChar(editor, cursor, param, count || 1);
  460. if (typeof column === "number") {
  461. cursor.column += column + (isSel ? 2 : 1);
  462. return cursor;
  463. }
  464. }
  465. }),
  466. "F": new Motion({
  467. param: true,
  468. handlesCount: true,
  469. getPos: function(editor, range, count, param, isSel, isRepeat) {
  470. if (param == "space") param = " ";
  471. if (!isRepeat)
  472. LAST_SEARCH_MOTION = {ch: "F", param: param};
  473. var cursor = editor.getCursorPosition();
  474. var column = util.getLeftNthChar(editor, cursor, param, count || 1);
  475. if (typeof column === "number") {
  476. cursor.column -= column + 1;
  477. return cursor;
  478. }
  479. }
  480. }),
  481. "t": new Motion({
  482. param: true,
  483. handlesCount: true,
  484. getPos: function(editor, range, count, param, isSel, isRepeat) {
  485. if (param == "space") param = " ";
  486. if (!isRepeat)
  487. LAST_SEARCH_MOTION = {ch: "t", param: param};
  488. var cursor = editor.getCursorPosition();
  489. var column = util.getRightNthChar(editor, cursor, param, count || 1);
  490. if (isRepeat && column == 0 && !(count > 1))
  491. var column = util.getRightNthChar(editor, cursor, param, 2);
  492. if (typeof column === "number") {
  493. cursor.column += column + (isSel ? 1 : 0);
  494. return cursor;
  495. }
  496. }
  497. }),
  498. "T": new Motion({
  499. param: true,
  500. handlesCount: true,
  501. getPos: function(editor, range, count, param, isSel, isRepeat) {
  502. if (param == "space") param = " ";
  503. if (!isRepeat)
  504. LAST_SEARCH_MOTION = {ch: "T", param: param};
  505. var cursor = editor.getCursorPosition();
  506. var column = util.getLeftNthChar(editor, cursor, param, count || 1);
  507. if (isRepeat && column == 0 && !(count > 1))
  508. var column = util.getLeftNthChar(editor, cursor, param, 2);
  509. if (typeof column === "number") {
  510. cursor.column -= column;
  511. return cursor;
  512. }
  513. }
  514. }),
  515. ";": new Motion({
  516. handlesCount: true,
  517. getPos: function(editor, range, count, param, isSel) {
  518. var ch = LAST_SEARCH_MOTION.ch;
  519. if (!ch)
  520. return;
  521. return module.exports[ch].getPos(
  522. editor, range, count, LAST_SEARCH_MOTION.param, isSel, true
  523. );
  524. }
  525. }),
  526. ",": new Motion({
  527. handlesCount: true,
  528. getPos: function(editor, range, count, param, isSel) {
  529. var ch = LAST_SEARCH_MOTION.ch;
  530. if (!ch)
  531. return;
  532. var up = ch.toUpperCase();
  533. ch = ch === up ? ch.toLowerCase() : up;
  534. return module.exports[ch].getPos(
  535. editor, range, count, LAST_SEARCH_MOTION.param, isSel, true
  536. );
  537. }
  538. }),
  539. "^": {
  540. nav: function(editor) {
  541. editor.navigateLineStart();
  542. },
  543. sel: function(editor) {
  544. editor.selection.selectLineStart();
  545. }
  546. },
  547. "$": {
  548. handlesCount: true,
  549. nav: function(editor, range, count, param) {
  550. if (count > 1) {
  551. editor.navigateDown(count-1);
  552. }
  553. editor.navigateLineEnd();
  554. },
  555. sel: function(editor, range, count, param) {
  556. if (count > 1) {
  557. editor.selection.moveCursorBy(count-1, 0);
  558. }
  559. editor.selection.selectLineEnd();
  560. }
  561. },
  562. "0": new Motion(function(ed) {
  563. return {row: ed.selection.lead.row, column: 0};
  564. }),
  565. "G": {
  566. nav: function(editor, range, count, param) {
  567. if (!count && count !== 0) { // Stupid JS
  568. count = editor.session.getLength();
  569. }
  570. editor.gotoLine(count);
  571. },
  572. sel: function(editor, range, count, param) {
  573. if (!count && count !== 0) { // Stupid JS
  574. count = editor.session.getLength();
  575. }
  576. editor.selection.selectTo(count, 0);
  577. }
  578. },
  579. "g": {
  580. param: true,
  581. nav: function(editor, range, count, param) {
  582. switch(param) {
  583. case "m":
  584. console.log("Middle line");
  585. break;
  586. case "e":
  587. console.log("End of prev word");
  588. break;
  589. case "g":
  590. editor.gotoLine(count || 0);
  591. case "u":
  592. editor.gotoLine(count || 0);
  593. case "U":
  594. editor.gotoLine(count || 0);
  595. }
  596. },
  597. sel: function(editor, range, count, param) {
  598. switch(param) {
  599. case "m":
  600. console.log("Middle line");
  601. break;
  602. case "e":
  603. console.log("End of prev word");
  604. break;
  605. case "g":
  606. editor.selection.selectTo(count || 0, 0);
  607. }
  608. }
  609. },
  610. "o": {
  611. nav: function(editor, range, count, param) {
  612. count = count || 1;
  613. var content = "";
  614. while (0 < count--)
  615. content += "\n";
  616. if (content.length) {
  617. editor.navigateLineEnd()
  618. editor.insert(content);
  619. util.insertMode(editor);
  620. }
  621. }
  622. },
  623. "O": {
  624. nav: function(editor, range, count, param) {
  625. var row = editor.getCursorPosition().row;
  626. count = count || 1;
  627. var content = "";
  628. while (0 < count--)
  629. content += "\n";
  630. if (content.length) {
  631. if(row > 0) {
  632. editor.navigateUp();
  633. editor.navigateLineEnd()
  634. editor.insert(content);
  635. } else {
  636. editor.session.insert({row: 0, column: 0}, content);
  637. editor.navigateUp();
  638. }
  639. util.insertMode(editor);
  640. }
  641. }
  642. },
  643. "%": new Motion(function(editor){
  644. var brRe = /[\[\]{}()]/g;
  645. var cursor = editor.getCursorPosition();
  646. var ch = editor.session.getLine(cursor.row)[cursor.column];
  647. if (!brRe.test(ch)) {
  648. var range = find(editor, brRe);
  649. if (!range)
  650. return;
  651. cursor = range.start;
  652. }
  653. var match = editor.session.findMatchingBracket({
  654. row: cursor.row,
  655. column: cursor.column + 1
  656. });
  657. return match;
  658. }),
  659. "{": new Motion(function(ed) {
  660. var session = ed.session;
  661. var row = session.selection.lead.row;
  662. while(row > 0 && !/\S/.test(session.getLine(row)))
  663. row--;
  664. while(/\S/.test(session.getLine(row)))
  665. row--;
  666. return {column: 0, row: row};
  667. }),
  668. "}": new Motion(function(ed) {
  669. var session = ed.session;
  670. var l = session.getLength();
  671. var row = session.selection.lead.row;
  672. while(row < l && !/\S/.test(session.getLine(row)))
  673. row++;
  674. while(/\S/.test(session.getLine(row)))
  675. row++;
  676. return {column: 0, row: row};
  677. }),
  678. "ctrl-d": {
  679. nav: function(editor, range, count, param) {
  680. editor.selection.clearSelection();
  681. keepScrollPosition(editor, editor.gotoPageDown);
  682. },
  683. sel: function(editor, range, count, param) {
  684. keepScrollPosition(editor, editor.selectPageDown);
  685. }
  686. },
  687. "ctrl-u": {
  688. nav: function(editor, range, count, param) {
  689. editor.selection.clearSelection();
  690. keepScrollPosition(editor, editor.gotoPageUp);
  691. },
  692. sel: function(editor, range, count, param) {
  693. keepScrollPosition(editor, editor.selectPageUp);
  694. }
  695. },
  696. "`": new Motion({
  697. param: true,
  698. handlesCount: true,
  699. getPos: function(editor, range, count, param, isSel) {
  700. var s = editor.session;
  701. var marker = s.vimMarkers && s.vimMarkers[param];
  702. if (marker) {
  703. return marker.getPosition();
  704. }
  705. }
  706. }),
  707. "'": new Motion({
  708. param: true,
  709. handlesCount: true,
  710. getPos: function(editor, range, count, param, isSel) {
  711. var s = editor.session;
  712. var marker = s.vimMarkers && s.vimMarkers[param];
  713. if (marker) {
  714. var pos = marker.getPosition();
  715. var line = editor.session.getLine(pos.row);
  716. pos.column = line.search(/\S/);
  717. if (pos.column == -1)
  718. pos.column = line.length;
  719. return pos;
  720. }
  721. },
  722. isLine: true
  723. })
  724. };
  725. module.exports.backspace = module.exports.left = module.exports.h;
  726. module.exports.space = module.exports['return'] = module.exports.right = module.exports.l;
  727. module.exports.up = module.exports.k;
  728. module.exports.down = module.exports.j;
  729. module.exports.pagedown = module.exports["ctrl-d"];
  730. module.exports.pageup = module.exports["ctrl-u"];
  731. module.exports.home = module.exports["0"];
  732. module.exports.end = module.exports["$"];
  733. });
  734. ace.define("ace/keyboard/vim/maps/operators",["require","exports","module","ace/keyboard/vim/maps/util","ace/keyboard/vim/registers","ace/range"], function(require, exports, module) {
  735. "use strict";
  736. var util = require("./util");
  737. var registers = require("../registers");
  738. var Range = require("../../../range").Range;
  739. module.exports = {
  740. "d": {
  741. selFn: function(editor, range, count, param) {
  742. registers._default.text = editor.getCopyText();
  743. registers._default.isLine = util.onVisualLineMode;
  744. if(util.onVisualLineMode)
  745. editor.removeLines();
  746. else
  747. editor.session.remove(range);
  748. util.normalMode(editor);
  749. },
  750. fn: function(editor, range, count, param) {
  751. count = count || 1;
  752. switch (param) {
  753. case "d":
  754. registers._default.text = "";
  755. registers._default.isLine = true;
  756. for (var i = 0; i < count; i++) {
  757. editor.selection.selectLine();
  758. registers._default.text += editor.getCopyText();
  759. var selRange = editor.getSelectionRange();
  760. if (!selRange.isMultiLine()) {
  761. var row = selRange.start.row - 1;
  762. var col = editor.session.getLine(row).length
  763. selRange.setStart(row, col);
  764. editor.session.remove(selRange);
  765. editor.selection.clearSelection();
  766. break;
  767. }
  768. editor.session.remove(selRange);
  769. editor.selection.clearSelection();
  770. }
  771. registers._default.text = registers._default.text.replace(/\n$/, "");
  772. break;
  773. default:
  774. if (range) {
  775. editor.selection.setSelectionRange(range);
  776. registers._default.text = editor.getCopyText();
  777. registers._default.isLine = false;
  778. editor.session.remove(range);
  779. editor.selection.clearSelection();
  780. }
  781. }
  782. }
  783. },
  784. "c": {
  785. selFn: function(editor, range, count, param) {
  786. editor.session.remove(range);
  787. util.insertMode(editor);
  788. },
  789. fn: function(editor, range, count, param) {
  790. count = count || 1;
  791. switch (param) {
  792. case "c":
  793. editor.$blockScrolling++;
  794. editor.selection.$moveSelection(function() {
  795. editor.selection.moveCursorBy(count - 1, 0);
  796. });
  797. var rows = editor.$getSelectedRows();
  798. range = new Range(rows.first, 0, rows.last, Infinity);
  799. editor.session.remove(range);
  800. editor.$blockScrolling--;
  801. util.insertMode(editor);
  802. break;
  803. default:
  804. if (range) {
  805. editor.session.remove(range);
  806. util.insertMode(editor);
  807. }
  808. }
  809. }
  810. },
  811. "y": {
  812. selFn: function(editor, range, count, param) {
  813. registers._default.text = editor.getCopyText();
  814. registers._default.isLine = util.onVisualLineMode;
  815. editor.selection.clearSelection();
  816. util.normalMode(editor);
  817. },
  818. fn: function(editor, range, count, param) {
  819. count = count || 1;
  820. if (param && param.isLine)
  821. param = "y";
  822. switch (param) {
  823. case "y":
  824. var pos = editor.getCursorPosition();
  825. editor.selection.selectLine();
  826. for (var i = 0; i < count - 1; i++) {
  827. editor.selection.moveCursorDown();
  828. }
  829. registers._default.text = editor.getCopyText().replace(/\n$/, "");
  830. editor.selection.clearSelection();
  831. registers._default.isLine = true;
  832. editor.moveCursorToPosition(pos);
  833. break;
  834. default:
  835. if (range) {
  836. var pos = editor.getCursorPosition();
  837. editor.selection.setSelectionRange(range);
  838. registers._default.text = editor.getCopyText();
  839. registers._default.isLine = false;
  840. editor.selection.clearSelection();
  841. editor.moveCursorTo(pos.row, pos.column);
  842. }
  843. }
  844. }
  845. },
  846. ">": {
  847. selFn: function(editor, range, count, param) {
  848. count = count || 1;
  849. for (var i = 0; i < count; i++) {
  850. editor.indent();
  851. }
  852. util.normalMode(editor);
  853. },
  854. fn: function(editor, range, count, param) {
  855. count = parseInt(count || 1, 10);
  856. switch (param) {
  857. case ">":
  858. var pos = editor.getCursorPosition();
  859. editor.selection.selectLine();
  860. for (var i = 0; i < count - 1; i++) {
  861. editor.selection.moveCursorDown();
  862. }
  863. editor.indent();
  864. editor.selection.clearSelection();
  865. editor.moveCursorToPosition(pos);
  866. editor.navigateLineEnd();
  867. editor.navigateLineStart();
  868. break;
  869. }
  870. }
  871. },
  872. "<": {
  873. selFn: function(editor, range, count, param) {
  874. count = count || 1;
  875. for (var i = 0; i < count; i++) {
  876. editor.blockOutdent();
  877. }
  878. util.normalMode(editor);
  879. },
  880. fn: function(editor, range, count, param) {
  881. count = count || 1;
  882. switch (param) {
  883. case "<":
  884. var pos = editor.getCursorPosition();
  885. editor.selection.selectLine();
  886. for (var i = 0; i < count - 1; i++) {
  887. editor.selection.moveCursorDown();
  888. }
  889. editor.blockOutdent();
  890. editor.selection.clearSelection();
  891. editor.moveCursorToPosition(pos);
  892. editor.navigateLineEnd();
  893. editor.navigateLineStart();
  894. break;
  895. }
  896. }
  897. }
  898. };
  899. });
  900. "use strict"
  901. ace.define("ace/keyboard/vim/maps/aliases",["require","exports","module"], function(require, exports, module) {
  902. module.exports = {
  903. "x": {
  904. operator: {
  905. ch: "d",
  906. count: 1
  907. },
  908. motion: {
  909. ch: "l",
  910. count: 1
  911. }
  912. },
  913. "X": {
  914. operator: {
  915. ch: "d",
  916. count: 1
  917. },
  918. motion: {
  919. ch: "h",
  920. count: 1
  921. }
  922. },
  923. "D": {
  924. operator: {
  925. ch: "d",
  926. count: 1
  927. },
  928. motion: {
  929. ch: "$",
  930. count: 1
  931. }
  932. },
  933. "C": {
  934. operator: {
  935. ch: "c",
  936. count: 1
  937. },
  938. motion: {
  939. ch: "$",
  940. count: 1
  941. }
  942. },
  943. "s": {
  944. operator: {
  945. ch: "c",
  946. count: 1
  947. },
  948. motion: {
  949. ch: "l",
  950. count: 1
  951. }
  952. },
  953. "S": {
  954. operator: {
  955. ch: "c",
  956. count: 1
  957. },
  958. param: "c"
  959. }
  960. };
  961. });
  962. ace.define("ace/keyboard/vim/commands",["require","exports","module","ace/lib/lang","ace/keyboard/vim/maps/util","ace/keyboard/vim/maps/motions","ace/keyboard/vim/maps/operators","ace/keyboard/vim/maps/aliases","ace/keyboard/vim/registers"], function(require, exports, module) {
  963. "never use strict";
  964. var lang = require("../../lib/lang");
  965. var util = require("./maps/util");
  966. var motions = require("./maps/motions");
  967. var operators = require("./maps/operators");
  968. var alias = require("./maps/aliases");
  969. var registers = require("./registers");
  970. var NUMBER = 1;
  971. var OPERATOR = 2;
  972. var MOTION = 3;
  973. var ACTION = 4;
  974. var HMARGIN = 8; // Minimum amount of line separation between margins;
  975. var repeat = function repeat(fn, count, args) {
  976. while (0 < count--)
  977. fn.apply(this, args);
  978. };
  979. var ensureScrollMargin = function(editor) {
  980. var renderer = editor.renderer;
  981. var pos = renderer.$cursorLayer.getPixelPosition();
  982. var top = pos.top;
  983. var margin = HMARGIN * renderer.layerConfig.lineHeight;
  984. if (2 * margin > renderer.$size.scrollerHeight)
  985. margin = renderer.$size.scrollerHeight / 2;
  986. if (renderer.scrollTop > top - margin) {
  987. renderer.session.setScrollTop(top - margin);
  988. }
  989. if (renderer.scrollTop + renderer.$size.scrollerHeight < top + margin + renderer.lineHeight) {
  990. renderer.session.setScrollTop(top + margin + renderer.lineHeight - renderer.$size.scrollerHeight);
  991. }
  992. };
  993. var actions = exports.actions = {
  994. "z": {
  995. param: true,
  996. fn: function(editor, range, count, param) {
  997. switch (param) {
  998. case "z":
  999. editor.renderer.alignCursor(null, 0.5);
  1000. break;
  1001. case "t":
  1002. editor.renderer.alignCursor(null, 0);
  1003. break;
  1004. case "b":
  1005. editor.renderer.alignCursor(null, 1);
  1006. break;
  1007. case "c":
  1008. editor.session.onFoldWidgetClick(range.start.row, {domEvent:{target :{}}});
  1009. break;
  1010. case "o":
  1011. editor.session.onFoldWidgetClick(range.start.row, {domEvent:{target :{}}});
  1012. break;
  1013. case "C":
  1014. editor.session.foldAll();
  1015. break;
  1016. case "O":
  1017. editor.session.unfold();
  1018. break;
  1019. }
  1020. }
  1021. },
  1022. "r": {
  1023. param: true,
  1024. fn: function(editor, range, count, param) {
  1025. if (param && param.length) {
  1026. if (param.length > 1)
  1027. param = param == "return" ? "\n" : param == "tab" ? "\t" : param;
  1028. repeat(function() { editor.insert(param); }, count || 1);
  1029. editor.navigateLeft();
  1030. }
  1031. }
  1032. },
  1033. "R": {
  1034. fn: function(editor, range, count, param) {
  1035. util.insertMode(editor);
  1036. editor.setOverwrite(true);
  1037. }
  1038. },
  1039. "~": {
  1040. fn: function(editor, range, count) {
  1041. repeat(function() {
  1042. var range = editor.selection.getRange();
  1043. if (range.isEmpty())
  1044. range.end.column++;
  1045. var text = editor.session.getTextRange(range);
  1046. var toggled = text.toUpperCase();
  1047. if (toggled != text)
  1048. editor.session.replace(range, toggled);
  1049. else if (text.toLowerCase() != text)
  1050. editor.session.replace(range, text.toLowerCase())
  1051. else
  1052. editor.navigateRight();
  1053. }, count || 1);
  1054. }
  1055. },
  1056. "*": {
  1057. fn: function(editor, range, count, param) {
  1058. editor.selection.selectWord();
  1059. editor.findNext();
  1060. ensureScrollMargin(editor);
  1061. var r = editor.selection.getRange();
  1062. editor.selection.setSelectionRange(r, true);
  1063. }
  1064. },
  1065. "#": {
  1066. fn: function(editor, range, count, param) {
  1067. editor.selection.selectWord();
  1068. editor.findPrevious();
  1069. ensureScrollMargin(editor);
  1070. var r = editor.selection.getRange();
  1071. editor.selection.setSelectionRange(r, true);
  1072. }
  1073. },
  1074. "m": {
  1075. param: true,
  1076. fn: function(editor, range, count, param) {
  1077. var s = editor.session;
  1078. var markers = s.vimMarkers || (s.vimMarkers = {});
  1079. var c = editor.getCursorPosition();
  1080. if (!markers[param]) {
  1081. markers[param] = editor.session.doc.createAnchor(c);
  1082. }
  1083. markers[param].setPosition(c.row, c.column, true);
  1084. }
  1085. },
  1086. "n": {
  1087. fn: function(editor, range, count, param) {
  1088. var options = editor.getLastSearchOptions();
  1089. options.backwards = false;
  1090. options.start = null;
  1091. editor.selection.moveCursorRight();
  1092. editor.selection.clearSelection();
  1093. editor.findNext(options);
  1094. ensureScrollMargin(editor);
  1095. var r = editor.selection.getRange();
  1096. r.end.row = r.start.row;
  1097. r.end.column = r.start.column;
  1098. editor.selection.setSelectionRange(r, true);
  1099. }
  1100. },
  1101. "N": {
  1102. fn: function(editor, range, count, param) {
  1103. var options = editor.getLastSearchOptions();
  1104. options.backwards = true;
  1105. options.start = null;
  1106. editor.findPrevious(options);
  1107. ensureScrollMargin(editor);
  1108. var r = editor.selection.getRange();
  1109. r.end.row = r.start.row;
  1110. r.end.column = r.start.column;
  1111. editor.selection.setSelectionRange(r, true);
  1112. }
  1113. },
  1114. "v": {
  1115. fn: function(editor, range, count, param) {
  1116. editor.selection.selectRight();
  1117. util.visualMode(editor, false);
  1118. },
  1119. acceptsMotion: true
  1120. },
  1121. "V": {
  1122. fn: function(editor, range, count, param) {
  1123. var row = editor.getCursorPosition().row;
  1124. editor.selection.moveTo(row, 0);
  1125. editor.selection.selectLineEnd();
  1126. editor.selection.visualLineStart = row;
  1127. util.visualMode(editor, true);
  1128. },
  1129. acceptsMotion: true
  1130. },
  1131. "Y": {
  1132. fn: function(editor, range, count, param) {
  1133. util.copyLine(editor);
  1134. }
  1135. },
  1136. "p": {
  1137. fn: function(editor, range, count, param) {
  1138. var defaultReg = registers._default;
  1139. editor.setOverwrite(false);
  1140. if (defaultReg.isLine) {
  1141. var pos = editor.getCursorPosition();
  1142. pos.column = editor.session.getLine(pos.row).length;
  1143. var text = lang.stringRepeat("\n" + defaultReg.text, count || 1);
  1144. editor.session.insert(pos, text);
  1145. editor.moveCursorTo(pos.row + 1, 0);
  1146. }
  1147. else {
  1148. editor.navigateRight();
  1149. editor.insert(lang.stringRepeat(defaultReg.text, count || 1));
  1150. editor.navigateLeft();
  1151. }
  1152. editor.setOverwrite(true);
  1153. editor.selection.clearSelection();
  1154. }
  1155. },
  1156. "P": {
  1157. fn: function(editor, range, count, param) {
  1158. var defaultReg = registers._default;
  1159. editor.setOverwrite(false);
  1160. if (defaultReg.isLine) {
  1161. var pos = editor.getCursorPosition();
  1162. pos.column = 0;
  1163. var text = lang.stringRepeat(defaultReg.text + "\n", count || 1);
  1164. editor.session.insert(pos, text);
  1165. editor.moveCursorToPosition(pos);
  1166. }
  1167. else {
  1168. editor.insert(lang.stringRepeat(defaultReg.text, count || 1));
  1169. }
  1170. editor.setOverwrite(true);
  1171. editor.selection.clearSelection();
  1172. }
  1173. },
  1174. "J": {
  1175. fn: function(editor, range, count, param) {
  1176. var session = editor.session;
  1177. range = editor.getSelectionRange();
  1178. var pos = {row: range.start.row, column: range.start.column};
  1179. count = count || range.end.row - range.start.row;
  1180. var maxRow = Math.min(pos.row + (count || 1), session.getLength() - 1);
  1181. range.start.column = session.getLine(pos.row).length;
  1182. range.end.column = session.getLine(maxRow).length;
  1183. range.end.row = maxRow;
  1184. var text = "";
  1185. for (var i = pos.row; i < maxRow; i++) {
  1186. var nextLine = session.getLine(i + 1);
  1187. text += " " + /^\s*(.*)$/.exec(nextLine)[1] || "";
  1188. }
  1189. session.replace(range, text);
  1190. editor.moveCursorTo(pos.row, pos.column);
  1191. }
  1192. },
  1193. "u": {
  1194. fn: function(editor, range, count, param) {
  1195. count = parseInt(count || 1, 10);
  1196. for (var i = 0; i < count; i++) {
  1197. editor.undo();
  1198. }
  1199. editor.selection.clearSelection();
  1200. }
  1201. },
  1202. "ctrl-r": {
  1203. fn: function(editor, range, count, param) {
  1204. count = parseInt(count || 1, 10);
  1205. for (var i = 0; i < count; i++) {
  1206. editor.redo();
  1207. }
  1208. editor.selection.clearSelection();
  1209. }
  1210. },
  1211. ":": {
  1212. fn: function(editor, range, count, param) {
  1213. var val = ":";
  1214. if (count > 1)
  1215. val = ".,.+" + count + val;
  1216. if (editor.showCommandLine)
  1217. editor.showCommandLine(val);
  1218. }
  1219. },
  1220. "/": {
  1221. fn: function(editor, range, count, param) {
  1222. if (editor.showCommandLine)
  1223. editor.showCommandLine("/");
  1224. }
  1225. },
  1226. "?": {
  1227. fn: function(editor, range, count, param) {
  1228. if (editor.showCommandLine)
  1229. editor.showCommandLine("?");
  1230. }
  1231. },
  1232. ".": {
  1233. fn: function(editor, range, count, param) {
  1234. util.onInsertReplaySequence = inputBuffer.lastInsertCommands;
  1235. var previous = inputBuffer.previous;
  1236. if (previous) // If there is a previous action
  1237. inputBuffer.exec(editor, previous.action, previous.param);
  1238. }
  1239. },
  1240. "ctrl-x": {
  1241. fn: function(editor, range, count, param) {
  1242. editor.modifyNumber(-(count || 1));
  1243. }
  1244. },
  1245. "ctrl-a": {
  1246. fn: function(editor, range, count, param) {
  1247. editor.modifyNumber(count || 1);
  1248. }
  1249. }
  1250. };
  1251. var inputBuffer = exports.inputBuffer = {
  1252. accepting: [NUMBER, OPERATOR, MOTION, ACTION],
  1253. currentCmd: null,
  1254. currentCount: "",
  1255. pendingCount: "",
  1256. status: "",
  1257. operator: null,
  1258. motion: null,
  1259. lastInsertCommands: [],
  1260. push: function(editor, ch, keyId) {
  1261. var status = this.status;
  1262. var isKeyHandled = true;
  1263. this.idle = false;
  1264. var wObj = this.waitingForParam;
  1265. if (/^numpad\d+$/i.test(ch))
  1266. ch = ch.substr(6);
  1267. if (wObj) {
  1268. this.exec(editor, wObj, ch);
  1269. }
  1270. else if (!(ch === "0" && !this.currentCount.length) &&
  1271. (/^\d+$/.test(ch) && this.isAccepting(NUMBER))) {
  1272. this.currentCount += ch;
  1273. this.currentCmd = NUMBER;
  1274. this.accepting = [NUMBER, OPERATOR, MOTION, ACTION];
  1275. }
  1276. else if (!this.operator && this.isAccepting(OPERATOR) && operators[ch]) {
  1277. this.operator = {
  1278. ch: ch,
  1279. count: this.getCount()
  1280. };
  1281. this.currentCmd = OPERATOR;
  1282. this.accepting = [NUMBER, MOTION, ACTION];
  1283. this.exec(editor, { operator: this.operator });
  1284. }
  1285. else if (motions[ch] && this.isAccepting(MOTION)) {
  1286. this.currentCmd = MOTION;
  1287. var ctx = {
  1288. operator: this.operator,
  1289. motion: {
  1290. ch: ch,
  1291. count: this.getCount()
  1292. }
  1293. };
  1294. if (motions[ch].param)
  1295. this.waitForParam(ctx);
  1296. else
  1297. this.exec(editor, ctx);
  1298. }
  1299. else if (alias[ch] && this.isAccepting(MOTION)) {
  1300. alias[ch].operator.count = this.getCount();
  1301. this.exec(editor, alias[ch]);
  1302. }
  1303. else if (actions[ch] && this.isAccepting(ACTION)) {
  1304. var actionObj = {
  1305. action: {
  1306. fn: actions[ch].fn,
  1307. count: this.getCount()
  1308. }
  1309. };
  1310. if (actions[ch].param) {
  1311. this.waitForParam(actionObj);
  1312. }
  1313. else {
  1314. this.exec(editor, actionObj);
  1315. }
  1316. if (actions[ch].acceptsMotion)
  1317. this.idle = false;
  1318. }
  1319. else if (this.operator) {
  1320. this.operator.count = this.getCount();
  1321. this.exec(editor, { operator: this.operator }, ch);
  1322. }
  1323. else {
  1324. isKeyHandled = ch.length == 1;
  1325. this.reset();
  1326. }
  1327. if (this.waitingForParam || this.motion || this.operator) {
  1328. this.status += ch;
  1329. } else if (this.currentCount) {
  1330. this.status = this.currentCount;
  1331. } else if (this.status) {
  1332. this.status = "";
  1333. }
  1334. if (this.status != status)
  1335. editor._emit("changeStatus");
  1336. return isKeyHandled;
  1337. },
  1338. waitForParam: function(cmd) {
  1339. this.waitingForParam = cmd;
  1340. },
  1341. getCount: function() {
  1342. var count = this.currentCount || this.pendingCount;
  1343. this.currentCount = "";
  1344. this.pendingCount = count;
  1345. return count && parseInt(count, 10);
  1346. },
  1347. exec: function(editor, action, param) {
  1348. var m = action.motion;
  1349. var o = action.operator;
  1350. var a = action.action;
  1351. if (!param)
  1352. param = action.param;
  1353. if (o) {
  1354. this.previous = {
  1355. action: action,
  1356. param: param
  1357. };
  1358. }
  1359. if (o && !editor.selection.isEmpty()) {
  1360. if (operators[o.ch].selFn) {
  1361. operators[o.ch].selFn(editor, editor.getSelectionRange(), o.count, param);
  1362. this.reset();
  1363. }
  1364. return;
  1365. }
  1366. else if (!m && !a && o && param) {
  1367. operators[o.ch].fn(editor, null, o.count, param);
  1368. this.reset();
  1369. }
  1370. else if (m) {
  1371. var run = function(fn) {
  1372. if (fn && typeof fn === "function") { // There should always be a motion
  1373. if (m.count && !motionObj.handlesCount)
  1374. repeat(fn, m.count, [editor, null, m.count, param]);
  1375. else
  1376. fn(editor, null, m.count, param);
  1377. }
  1378. };
  1379. var motionObj = motions[m.ch];
  1380. var selectable = motionObj.sel;
  1381. if (!o) {
  1382. if ((util.onVisualMode || util.onVisualLineMode) && selectable)
  1383. run(motionObj.sel);
  1384. else
  1385. run(motionObj.nav);
  1386. }
  1387. else if (selectable) {
  1388. repeat(function() {
  1389. run(motionObj.sel);
  1390. operators[o.ch].fn(editor, editor.getSelectionRange(),
  1391. o.count, motionObj.param ? motionObj : param);
  1392. }, o.count || 1);
  1393. }
  1394. this.reset();
  1395. }
  1396. else if (a) {
  1397. a.fn(editor, editor.getSelectionRange(), a.count, param);
  1398. this.reset();
  1399. }
  1400. handleCursorMove(editor);
  1401. },
  1402. isAccepting: function(type) {
  1403. return this.accepting.indexOf(type) !== -1;
  1404. },
  1405. reset: function() {
  1406. this.operator = null;
  1407. this.motion = null;
  1408. this.currentCount = "";
  1409. this.pendingCount = "";
  1410. this.status = "";
  1411. this.accepting = [NUMBER, OPERATOR, MOTION, ACTION];
  1412. this.idle = true;
  1413. this.waitingForParam = null;
  1414. }
  1415. };
  1416. function setPreviousCommand(fn) {
  1417. inputBuffer.previous = { action: { action: { fn: fn } } };
  1418. }
  1419. exports.coreCommands = {
  1420. start: {
  1421. exec: function start(editor) {
  1422. util.insertMode(editor);
  1423. setPreviousCommand(start);
  1424. }
  1425. },
  1426. startBeginning: {
  1427. exec: function startBeginning(editor) {
  1428. editor.navigateLineStart();
  1429. util.insertMode(editor);
  1430. setPreviousCommand(startBeginning);
  1431. }
  1432. },
  1433. stop: {
  1434. exec: function stop(editor) {
  1435. inputBuffer.reset();
  1436. util.onVisualMode = false;
  1437. util.onVisualLineMode = false;
  1438. inputBuffer.lastInsertCommands = util.normalMode(editor);
  1439. }
  1440. },
  1441. append: {
  1442. exec: function append(editor) {
  1443. var pos = editor.getCursorPosition();
  1444. var lineLen = editor.session.getLine(pos.row).length;
  1445. if (lineLen)
  1446. editor.navigateRight();
  1447. util.insertMode(editor);
  1448. setPreviousCommand(append);
  1449. }
  1450. },
  1451. appendEnd: {
  1452. exec: function appendEnd(editor) {
  1453. editor.navigateLineEnd();
  1454. util.insertMode(editor);
  1455. setPreviousCommand(appendEnd);
  1456. }
  1457. }
  1458. };
  1459. var handleCursorMove = exports.onCursorMove = function(editor, e) {
  1460. if (util.currentMode === 'insert' || handleCursorMove.running)
  1461. return;
  1462. else if(!editor.selection.isEmpty()) {
  1463. handleCursorMove.running = true;
  1464. if (util.onVisualLineMode) {
  1465. var originRow = editor.selection.visualLineStart;
  1466. var cursorRow = editor.getCursorPosition().row;
  1467. if(originRow <= cursorRow) {
  1468. var endLine = editor.session.getLine(cursorRow);
  1469. editor.selection.moveTo(originRow, 0);
  1470. editor.selection.selectTo(cursorRow, endLine.length);
  1471. } else {
  1472. var endLine = editor.session.getLine(originRow);
  1473. editor.selection.moveTo(originRow, endLine.length);
  1474. editor.selection.selectTo(cursorRow, 0);
  1475. }
  1476. }
  1477. handleCursorMove.running = false;
  1478. return;
  1479. }
  1480. else {
  1481. if (e && (util.onVisualLineMode || util.onVisualMode)) {
  1482. editor.selection.clearSelection();
  1483. util.normalMode(editor);
  1484. }
  1485. handleCursorMove.running = true;
  1486. var pos = editor.getCursorPosition();
  1487. var lineLen = editor.session.getLine(pos.row).length;
  1488. if (lineLen && pos.column === lineLen)
  1489. editor.navigateLeft();
  1490. handleCursorMove.running = false;
  1491. }
  1492. };
  1493. });
  1494. ace.define("ace/keyboard/vim",["require","exports","module","ace/keyboard/vim/commands","ace/keyboard/vim/maps/util","ace/lib/useragent"], function(require, exports, module) {
  1495. "use strict";
  1496. var cmds = require("./vim/commands");
  1497. var coreCommands = cmds.coreCommands;
  1498. var util = require("./vim/maps/util");
  1499. var useragent = require("../lib/useragent");
  1500. var startCommands = {
  1501. "i": {
  1502. command: coreCommands.start
  1503. },
  1504. "I": {
  1505. command: coreCommands.startBeginning
  1506. },
  1507. "a": {
  1508. command: coreCommands.append
  1509. },
  1510. "A": {
  1511. command: coreCommands.appendEnd
  1512. },
  1513. "ctrl-f": {
  1514. command: "gotopagedown"
  1515. },
  1516. "ctrl-b": {
  1517. command: "gotopageup"
  1518. }
  1519. };
  1520. exports.handler = {
  1521. $id: "ace/keyboard/vim",
  1522. handleMacRepeat: function(data, hashId, key) {
  1523. if (hashId == -1) {
  1524. data.inputChar = key;
  1525. data.lastEvent = "input";
  1526. } else if (data.inputChar && data.$lastHash == hashId && data.$lastKey == key) {
  1527. if (data.lastEvent == "input") {
  1528. data.lastEvent = "input1";
  1529. } else if (data.lastEvent == "input1") {
  1530. return true;
  1531. }
  1532. } else {
  1533. data.$lastHash = hashId;
  1534. data.$lastKey = key;
  1535. data.lastEvent = "keypress";
  1536. }
  1537. },
  1538. updateMacCompositionHandlers: function(editor, enable) {
  1539. var onCompositionUpdateOverride = function(text) {
  1540. if (util.currentMode !== "insert") {
  1541. var el = this.textInput.getElement();
  1542. el.blur();
  1543. el.focus();
  1544. el.value = text;
  1545. } else {
  1546. this.onCompositionUpdateOrig(text);
  1547. }
  1548. };
  1549. var onCompositionStartOverride = function(text) {
  1550. if (util.currentMode === "insert") {
  1551. this.onCompositionStartOrig(text);
  1552. }
  1553. };
  1554. if (enable) {
  1555. if (!editor.onCompositionUpdateOrig) {
  1556. editor.onCompositionUpdateOrig = editor.onCompositionUpdate;
  1557. editor.onCompositionUpdate = onCompositionUpdateOverride;
  1558. editor.onCompositionStartOrig = editor.onCompositionStart;
  1559. editor.onCompositionStart = onCompositionStartOverride;
  1560. }
  1561. } else {
  1562. if (editor.onCompositionUpdateOrig) {
  1563. editor.onCompositionUpdate = editor.onCompositionUpdateOrig;
  1564. editor.onCompositionUpdateOrig = null;
  1565. editor.onCompositionStart = editor.onCompositionStartOrig;
  1566. editor.onCompositionStartOrig = null;
  1567. }
  1568. }
  1569. },
  1570. handleKeyboard: function(data, hashId, key, keyCode, e) {
  1571. if (hashId !== 0 && (!key || keyCode == -1))
  1572. return null;
  1573. var editor = data.editor;
  1574. var vimState = data.vimState || "start";
  1575. if (hashId == 1)
  1576. key = "ctrl-" + key;
  1577. if (key == "ctrl-c") {
  1578. if (!useragent.isMac && editor.getCopyText()) {
  1579. editor.once("copy", function() {
  1580. if (vimState == "start")
  1581. coreCommands.stop.exec(editor);
  1582. else
  1583. editor.selection.clearSelection();
  1584. });
  1585. return {command: "null", passEvent: true};
  1586. }
  1587. return {command: coreCommands.stop};
  1588. } else if ((key == "esc" && hashId === 0) || key == "ctrl-[") {
  1589. return {command: coreCommands.stop};
  1590. } else if (vimState == "start") {
  1591. if (useragent.isMac && this.handleMacRepeat(data, hashId, key)) {
  1592. hashId = -1;
  1593. key = data.inputChar;
  1594. }
  1595. if (hashId == -1 || hashId == 1 || hashId === 0 && key.length > 1) {
  1596. if (cmds.inputBuffer.idle && startCommands[key])
  1597. return startCommands[key];
  1598. var isHandled = cmds.inputBuffer.push(editor, key);
  1599. if (!isHandled && hashId !== -1)
  1600. return;
  1601. return {command: "null", passEvent: !isHandled};
  1602. } else if (key == "esc" && hashId === 0) {
  1603. return {command: coreCommands.stop};
  1604. }
  1605. else if (hashId === 0 || hashId == 4) {
  1606. return {command: "null", passEvent: true};
  1607. }
  1608. } else {
  1609. if (key == "ctrl-w") {
  1610. return {command: "removewordleft"};
  1611. }
  1612. }
  1613. },
  1614. attach: function(editor) {
  1615. editor.on("click", exports.onCursorMove);
  1616. if (util.currentMode !== "insert")
  1617. cmds.coreCommands.stop.exec(editor);
  1618. editor.$vimModeHandler = this;
  1619. this.updateMacCompositionHandlers(editor, true);
  1620. },
  1621. detach: function(editor) {
  1622. editor.removeListener("click", exports.onCursorMove);
  1623. util.noMode(editor);
  1624. util.currentMode = "normal";
  1625. this.updateMacCompositionHandlers(editor, false);
  1626. },
  1627. actions: cmds.actions,
  1628. getStatusText: function() {
  1629. if (util.currentMode == "insert")
  1630. return "INSERT";
  1631. if (util.onVisualMode)
  1632. return (util.onVisualLineMode ? "VISUAL LINE " : "VISUAL ") + cmds.inputBuffer.status;
  1633. return cmds.inputBuffer.status;
  1634. }
  1635. };
  1636. exports.onCursorMove = function(e) {
  1637. cmds.onCursorMove(e.editor, e);
  1638. exports.onCursorMove.scheduled = false;
  1639. };
  1640. });