PageRenderTime 31ms CodeModel.GetById 41ms RepoModel.GetById 0ms app.codeStats 0ms

/vendor/pqb/filemanager-laravel/public/filemanager/scripts/CodeMirror/keymap/emacs.js

https://gitlab.com/hatemdigify/digifyblog
JavaScript | 405 lines | 341 code | 58 blank | 6 comment | 112 complexity | 5dd76136dd50082ee7a16d9f833595a9 MD5 | raw file
  1. (function(mod) {
  2. if (typeof exports == "object" && typeof module == "object") // CommonJS
  3. mod(require("../lib/codemirror"));
  4. else if (typeof define == "function" && define.amd) // AMD
  5. define(["../lib/codemirror"], mod);
  6. else // Plain browser env
  7. mod(CodeMirror);
  8. })(function(CodeMirror) {
  9. "use strict";
  10. var Pos = CodeMirror.Pos;
  11. function posEq(a, b) { return a.line == b.line && a.ch == b.ch; }
  12. // Kill 'ring'
  13. var killRing = [];
  14. function addToRing(str) {
  15. killRing.push(str);
  16. if (killRing.length > 50) killRing.shift();
  17. }
  18. function growRingTop(str) {
  19. if (!killRing.length) return addToRing(str);
  20. killRing[killRing.length - 1] += str;
  21. }
  22. function getFromRing(n) { return killRing[killRing.length - (n ? Math.min(n, 1) : 1)] || ""; }
  23. function popFromRing() { if (killRing.length > 1) killRing.pop(); return getFromRing(); }
  24. var lastKill = null;
  25. function kill(cm, from, to, mayGrow, text) {
  26. if (text == null) text = cm.getRange(from, to);
  27. if (mayGrow && lastKill && lastKill.cm == cm && posEq(from, lastKill.pos) && cm.isClean(lastKill.gen))
  28. growRingTop(text);
  29. else
  30. addToRing(text);
  31. cm.replaceRange("", from, to, "+delete");
  32. if (mayGrow) lastKill = {cm: cm, pos: from, gen: cm.changeGeneration()};
  33. else lastKill = null;
  34. }
  35. // Boundaries of various units
  36. function byChar(cm, pos, dir) {
  37. return cm.findPosH(pos, dir, "char", true);
  38. }
  39. function byWord(cm, pos, dir) {
  40. return cm.findPosH(pos, dir, "word", true);
  41. }
  42. function byLine(cm, pos, dir) {
  43. return cm.findPosV(pos, dir, "line", cm.doc.sel.goalColumn);
  44. }
  45. function byPage(cm, pos, dir) {
  46. return cm.findPosV(pos, dir, "page", cm.doc.sel.goalColumn);
  47. }
  48. function byParagraph(cm, pos, dir) {
  49. var no = pos.line, line = cm.getLine(no);
  50. var sawText = /\S/.test(dir < 0 ? line.slice(0, pos.ch) : line.slice(pos.ch));
  51. var fst = cm.firstLine(), lst = cm.lastLine();
  52. for (;;) {
  53. no += dir;
  54. if (no < fst || no > lst)
  55. return cm.clipPos(Pos(no - dir, dir < 0 ? 0 : null));
  56. line = cm.getLine(no);
  57. var hasText = /\S/.test(line);
  58. if (hasText) sawText = true;
  59. else if (sawText) return Pos(no, 0);
  60. }
  61. }
  62. function bySentence(cm, pos, dir) {
  63. var line = pos.line, ch = pos.ch;
  64. var text = cm.getLine(pos.line), sawWord = false;
  65. for (;;) {
  66. var next = text.charAt(ch + (dir < 0 ? -1 : 0));
  67. if (!next) { // End/beginning of line reached
  68. if (line == (dir < 0 ? cm.firstLine() : cm.lastLine())) return Pos(line, ch);
  69. text = cm.getLine(line + dir);
  70. if (!/\S/.test(text)) return Pos(line, ch);
  71. line += dir;
  72. ch = dir < 0 ? text.length : 0;
  73. continue;
  74. }
  75. if (sawWord && /[!?.]/.test(next)) return Pos(line, ch + (dir > 0 ? 1 : 0));
  76. if (!sawWord) sawWord = /\w/.test(next);
  77. ch += dir;
  78. }
  79. }
  80. function byExpr(cm, pos, dir) {
  81. var wrap;
  82. if (cm.findMatchingBracket && (wrap = cm.findMatchingBracket(pos, true))
  83. && wrap.match && (wrap.forward ? 1 : -1) == dir)
  84. return dir > 0 ? Pos(wrap.to.line, wrap.to.ch + 1) : wrap.to;
  85. for (var first = true;; first = false) {
  86. var token = cm.getTokenAt(pos);
  87. var after = Pos(pos.line, dir < 0 ? token.start : token.end);
  88. if (first && dir > 0 && token.end == pos.ch || !/\w/.test(token.string)) {
  89. var newPos = cm.findPosH(after, dir, "char");
  90. if (posEq(after, newPos)) return pos;
  91. else pos = newPos;
  92. } else {
  93. return after;
  94. }
  95. }
  96. }
  97. // Prefixes (only crudely supported)
  98. function getPrefix(cm, precise) {
  99. var digits = cm.state.emacsPrefix;
  100. if (!digits) return precise ? null : 1;
  101. clearPrefix(cm);
  102. return digits == "-" ? -1 : Number(digits);
  103. }
  104. function repeated(cmd) {
  105. var f = typeof cmd == "string" ? function(cm) { cm.execCommand(cmd); } : cmd;
  106. return function(cm) {
  107. var prefix = getPrefix(cm);
  108. f(cm);
  109. for (var i = 1; i < prefix; ++i) f(cm);
  110. };
  111. }
  112. function findEnd(cm, by, dir) {
  113. var pos = cm.getCursor(), prefix = getPrefix(cm);
  114. if (prefix < 0) { dir = -dir; prefix = -prefix; }
  115. for (var i = 0; i < prefix; ++i) {
  116. var newPos = by(cm, pos, dir);
  117. if (posEq(newPos, pos)) break;
  118. pos = newPos;
  119. }
  120. return pos;
  121. }
  122. function move(by, dir) {
  123. var f = function(cm) {
  124. cm.extendSelection(findEnd(cm, by, dir));
  125. };
  126. f.motion = true;
  127. return f;
  128. }
  129. function killTo(cm, by, dir) {
  130. kill(cm, cm.getCursor(), findEnd(cm, by, dir), true);
  131. }
  132. function addPrefix(cm, digit) {
  133. if (cm.state.emacsPrefix) {
  134. if (digit != "-") cm.state.emacsPrefix += digit;
  135. return;
  136. }
  137. // Not active yet
  138. cm.state.emacsPrefix = digit;
  139. cm.on("keyHandled", maybeClearPrefix);
  140. cm.on("inputRead", maybeDuplicateInput);
  141. }
  142. var prefixPreservingKeys = {"Alt-G": true, "Ctrl-X": true, "Ctrl-Q": true, "Ctrl-U": true};
  143. function maybeClearPrefix(cm, arg) {
  144. if (!cm.state.emacsPrefixMap && !prefixPreservingKeys.hasOwnProperty(arg))
  145. clearPrefix(cm);
  146. }
  147. function clearPrefix(cm) {
  148. cm.state.emacsPrefix = null;
  149. cm.off("keyHandled", maybeClearPrefix);
  150. cm.off("inputRead", maybeDuplicateInput);
  151. }
  152. function maybeDuplicateInput(cm, event) {
  153. var dup = getPrefix(cm);
  154. if (dup > 1 && event.origin == "+input") {
  155. var one = event.text.join("\n"), txt = "";
  156. for (var i = 1; i < dup; ++i) txt += one;
  157. cm.replaceSelection(txt);
  158. }
  159. }
  160. function addPrefixMap(cm) {
  161. cm.state.emacsPrefixMap = true;
  162. cm.addKeyMap(prefixMap);
  163. cm.on("keyHandled", maybeRemovePrefixMap);
  164. cm.on("inputRead", maybeRemovePrefixMap);
  165. }
  166. function maybeRemovePrefixMap(cm, arg) {
  167. if (typeof arg == "string" && (/^\d$/.test(arg) || arg == "Ctrl-U")) return;
  168. cm.removeKeyMap(prefixMap);
  169. cm.state.emacsPrefixMap = false;
  170. cm.off("keyHandled", maybeRemovePrefixMap);
  171. cm.off("inputRead", maybeRemovePrefixMap);
  172. }
  173. // Utilities
  174. function setMark(cm) {
  175. cm.setCursor(cm.getCursor());
  176. cm.setExtending(!cm.getExtending());
  177. cm.on("change", function() { cm.setExtending(false); });
  178. }
  179. function clearMark(cm) {
  180. cm.setExtending(false);
  181. cm.setCursor(cm.getCursor());
  182. }
  183. function getInput(cm, msg, f) {
  184. if (cm.openDialog)
  185. cm.openDialog(msg + ": <input type=\"text\" style=\"width: 10em\"/>", f, {bottom: true});
  186. else
  187. f(prompt(msg, ""));
  188. }
  189. function operateOnWord(cm, op) {
  190. var start = cm.getCursor(), end = cm.findPosH(start, 1, "word");
  191. cm.replaceRange(op(cm.getRange(start, end)), start, end);
  192. cm.setCursor(end);
  193. }
  194. function toEnclosingExpr(cm) {
  195. var pos = cm.getCursor(), line = pos.line, ch = pos.ch;
  196. var stack = [];
  197. while (line >= cm.firstLine()) {
  198. var text = cm.getLine(line);
  199. for (var i = ch == null ? text.length : ch; i > 0;) {
  200. var ch = text.charAt(--i);
  201. if (ch == ")")
  202. stack.push("(");
  203. else if (ch == "]")
  204. stack.push("[");
  205. else if (ch == "}")
  206. stack.push("{");
  207. else if (/[\(\{\[]/.test(ch) && (!stack.length || stack.pop() != ch))
  208. return cm.extendSelection(Pos(line, i));
  209. }
  210. --line; ch = null;
  211. }
  212. }
  213. function quit(cm) {
  214. cm.execCommand("clearSearch");
  215. clearMark(cm);
  216. }
  217. // Actual keymap
  218. var keyMap = CodeMirror.keyMap.emacs = {
  219. "Ctrl-W": function(cm) {kill(cm, cm.getCursor("start"), cm.getCursor("end"));},
  220. "Ctrl-K": repeated(function(cm) {
  221. var start = cm.getCursor(), end = cm.clipPos(Pos(start.line));
  222. var text = cm.getRange(start, end);
  223. if (!/\S/.test(text)) {
  224. text += "\n";
  225. end = Pos(start.line + 1, 0);
  226. }
  227. kill(cm, start, end, true, text);
  228. }),
  229. "Alt-W": function(cm) {
  230. addToRing(cm.getSelection());
  231. clearMark(cm);
  232. },
  233. "Ctrl-Y": function(cm) {
  234. var start = cm.getCursor();
  235. cm.replaceRange(getFromRing(getPrefix(cm)), start, start, "paste");
  236. cm.setSelection(start, cm.getCursor());
  237. },
  238. "Alt-Y": function(cm) {cm.replaceSelection(popFromRing(), "around", "paste");},
  239. "Ctrl-Space": setMark, "Ctrl-Shift-2": setMark,
  240. "Ctrl-F": move(byChar, 1), "Ctrl-B": move(byChar, -1),
  241. "Right": move(byChar, 1), "Left": move(byChar, -1),
  242. "Ctrl-D": function(cm) { killTo(cm, byChar, 1); },
  243. "Delete": function(cm) { killTo(cm, byChar, 1); },
  244. "Ctrl-H": function(cm) { killTo(cm, byChar, -1); },
  245. "Backspace": function(cm) { killTo(cm, byChar, -1); },
  246. "Alt-F": move(byWord, 1), "Alt-B": move(byWord, -1),
  247. "Alt-D": function(cm) { killTo(cm, byWord, 1); },
  248. "Alt-Backspace": function(cm) { killTo(cm, byWord, -1); },
  249. "Ctrl-N": move(byLine, 1), "Ctrl-P": move(byLine, -1),
  250. "Down": move(byLine, 1), "Up": move(byLine, -1),
  251. "Ctrl-A": "goLineStart", "Ctrl-E": "goLineEnd",
  252. "End": "goLineEnd", "Home": "goLineStart",
  253. "Alt-V": move(byPage, -1), "Ctrl-V": move(byPage, 1),
  254. "PageUp": move(byPage, -1), "PageDown": move(byPage, 1),
  255. "Ctrl-Up": move(byParagraph, -1), "Ctrl-Down": move(byParagraph, 1),
  256. "Alt-A": move(bySentence, -1), "Alt-E": move(bySentence, 1),
  257. "Alt-K": function(cm) { killTo(cm, bySentence, 1); },
  258. "Ctrl-Alt-K": function(cm) { killTo(cm, byExpr, 1); },
  259. "Ctrl-Alt-Backspace": function(cm) { killTo(cm, byExpr, -1); },
  260. "Ctrl-Alt-F": move(byExpr, 1), "Ctrl-Alt-B": move(byExpr, -1),
  261. "Shift-Ctrl-Alt-2": function(cm) {
  262. cm.setSelection(findEnd(cm, byExpr, 1), cm.getCursor());
  263. },
  264. "Ctrl-Alt-T": function(cm) {
  265. var leftStart = byExpr(cm, cm.getCursor(), -1), leftEnd = byExpr(cm, leftStart, 1);
  266. var rightEnd = byExpr(cm, leftEnd, 1), rightStart = byExpr(cm, rightEnd, -1);
  267. cm.replaceRange(cm.getRange(rightStart, rightEnd) + cm.getRange(leftEnd, rightStart) +
  268. cm.getRange(leftStart, leftEnd), leftStart, rightEnd);
  269. },
  270. "Ctrl-Alt-U": repeated(toEnclosingExpr),
  271. "Alt-Space": function(cm) {
  272. var pos = cm.getCursor(), from = pos.ch, to = pos.ch, text = cm.getLine(pos.line);
  273. while (from && /\s/.test(text.charAt(from - 1))) --from;
  274. while (to < text.length && /\s/.test(text.charAt(to))) ++to;
  275. cm.replaceRange(" ", Pos(pos.line, from), Pos(pos.line, to));
  276. },
  277. "Ctrl-O": repeated(function(cm) { cm.replaceSelection("\n", "start"); }),
  278. "Ctrl-T": repeated(function(cm) {
  279. var pos = cm.getCursor();
  280. if (pos.ch < cm.getLine(pos.line).length) pos = Pos(pos.line, pos.ch + 1);
  281. var from = cm.findPosH(pos, -2, "char");
  282. var range = cm.getRange(from, pos);
  283. if (range.length != 2) return;
  284. cm.setSelection(from, pos);
  285. cm.replaceSelection(range.charAt(1) + range.charAt(0), null, "+transpose");
  286. }),
  287. "Alt-C": repeated(function(cm) {
  288. operateOnWord(cm, function(w) {
  289. var letter = w.search(/\w/);
  290. if (letter == -1) return w;
  291. return w.slice(0, letter) + w.charAt(letter).toUpperCase() + w.slice(letter + 1).toLowerCase();
  292. });
  293. }),
  294. "Alt-U": repeated(function(cm) {
  295. operateOnWord(cm, function(w) { return w.toUpperCase(); });
  296. }),
  297. "Alt-L": repeated(function(cm) {
  298. operateOnWord(cm, function(w) { return w.toLowerCase(); });
  299. }),
  300. "Alt-;": "toggleComment",
  301. "Ctrl-/": repeated("undo"), "Shift-Ctrl--": repeated("undo"),
  302. "Ctrl-Z": repeated("undo"), "Cmd-Z": repeated("undo"),
  303. "Shift-Alt-,": "goDocStart", "Shift-Alt-.": "goDocEnd",
  304. "Ctrl-S": "findNext", "Ctrl-R": "findPrev", "Ctrl-G": quit, "Shift-Alt-5": "replace",
  305. "Alt-/": "autocomplete",
  306. "Ctrl-J": "newlineAndIndent", "Enter": false, "Tab": "indentAuto",
  307. "Alt-G": function(cm) {cm.setOption("keyMap", "emacs-Alt-G");},
  308. "Ctrl-X": function(cm) {cm.setOption("keyMap", "emacs-Ctrl-X");},
  309. "Ctrl-Q": function(cm) {cm.setOption("keyMap", "emacs-Ctrl-Q");},
  310. "Ctrl-U": addPrefixMap
  311. };
  312. CodeMirror.keyMap["emacs-Ctrl-X"] = {
  313. "Tab": function(cm) {
  314. cm.indentSelection(getPrefix(cm, true) || cm.getOption("indentUnit"));
  315. },
  316. "Ctrl-X": function(cm) {
  317. cm.setSelection(cm.getCursor("head"), cm.getCursor("anchor"));
  318. },
  319. "Ctrl-S": "save", "Ctrl-W": "save", "S": "saveAll", "F": "open", "U": repeated("undo"), "K": "close",
  320. "Delete": function(cm) { kill(cm, cm.getCursor(), bySentence(cm, cm.getCursor(), 1), true); },
  321. auto: "emacs", nofallthrough: true, disableInput: true
  322. };
  323. CodeMirror.keyMap["emacs-Alt-G"] = {
  324. "G": function(cm) {
  325. var prefix = getPrefix(cm, true);
  326. if (prefix != null && prefix > 0) return cm.setCursor(prefix - 1);
  327. getInput(cm, "Goto line", function(str) {
  328. var num;
  329. if (str && !isNaN(num = Number(str)) && num == num|0 && num > 0)
  330. cm.setCursor(num - 1);
  331. });
  332. },
  333. auto: "emacs", nofallthrough: true, disableInput: true
  334. };
  335. CodeMirror.keyMap["emacs-Ctrl-Q"] = {
  336. "Tab": repeated("insertTab"),
  337. auto: "emacs", nofallthrough: true
  338. };
  339. var prefixMap = {"Ctrl-G": clearPrefix};
  340. function regPrefix(d) {
  341. prefixMap[d] = function(cm) { addPrefix(cm, d); };
  342. keyMap["Ctrl-" + d] = function(cm) { addPrefix(cm, d); };
  343. prefixPreservingKeys["Ctrl-" + d] = true;
  344. }
  345. for (var i = 0; i < 10; ++i) regPrefix(String(i));
  346. regPrefix("-");
  347. });