ace-panel.js 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283
  1. /**
  2. * 1.管理文件资源逻辑部分
  3. */
  4. const ace = Editor.require('packages://simple-code/panel/vs-panel/ace/ace.js');
  5. const settings_menu = Editor.require('packages://simple-code/panel/vs-panel/ace/ext-settings_menu.js');
  6. const prompt_ex = Editor.require('packages://simple-code/panel/vs-panel/ace/ext-prompt.js');
  7. const prsPath = Editor.Project && Editor.Project.path ? Editor.Project.path : Editor.remote.projectPath;
  8. class AcePanel{
  9. constructor(parent){
  10. this.parent = parent;
  11. this.initAce();
  12. this.initEvent()
  13. }
  14. initAce() {
  15. // 副级编辑器
  16. ace.config.set("basePath", Editor.url('packages://simple-code/ace/', 'utf8'));
  17. var editor = ace.edit(this.parent.$editorA);
  18. editor.setOptions({
  19. // 默认:false
  20. wrap: true, // 换行
  21. autoScrollEditorIntoView: false, // 自动滚动编辑器视图
  22. enableLiveAutocompletion: true, // 智能补全
  23. enableSnippets: true, // 启用代码段
  24. enableBasicAutocompletion: false, // 启用基本完成 不推荐使用
  25. });
  26. // 设置主题
  27. editor.setTheme("ace/theme/monokai");
  28. // 设置编辑语言
  29. editor.getSession().setMode("ace/mode/javascript");
  30. // 设置快捷键模式
  31. editor.setKeyboardHandler('ace/keyboard/sublime');
  32. editor.setReadOnly(false);
  33. editor.getSession().setTabSize(4);
  34. editor.setShowPrintMargin(false);
  35. this.ace_editor = editor;
  36. }
  37. initEvent(){
  38. // 设置面板改变的时候
  39. this.ace_editor.on("setOption", (e) => {
  40. this.parent.setOptions({ [e.name]: e.value });
  41. });
  42. }
  43. setMiniSearchBoxToTouchPos(width=150,isAutoHeight=0,isTextEditMode=0,isHidePopup=false)
  44. {
  45. this.setMiniSearchBox(this.parent.mouse_pos,width,isAutoHeight,isTextEditMode,isHidePopup)
  46. }
  47. // 设置迷你输入框大小
  48. setMiniSearchBox(pos,width=150,isAutoHeight=0,isTextEditMode=0,isHidePopup=false)
  49. {
  50. let box = document.getElementById('mini_prompt_box');
  51. let input = document.getElementById('mini_prompt_input');
  52. let popup = document.getElementById('mini_prompt_popup');
  53. if(!box || !input || !popup)
  54. {
  55. return;
  56. }
  57. if(pos) {
  58. let max_x = document.body.clientWidth - width-100;
  59. let x = pos.x>max_x ? max_x : pos.x - width*0.5;
  60. box.style.margin = `${pos.y-10}px auto auto ${x}px`
  61. };
  62. box.style['max-width'] = width+'px'
  63. popup.style['max-width'] = width+'px'
  64. if(isHidePopup) popup.style['display'] = 'none';
  65. if(isAutoHeight) {
  66. input.cmdLine.setOption("wrap", "free") // ace 编辑器选项
  67. input.cmdLine.setOption('maxLines',35)
  68. input.cmdLine.isEditorMode = true;
  69. }
  70. if(isTextEditMode) {
  71. input.cmdLine.setOption("wrap", "off") // ace 编辑器选项
  72. input.cmdLine.setOption('maxLines',35)
  73. input.cmdLine.setHighlightActiveLine(true);
  74. input.cmdLine.setShowPrintMargin(false);
  75. input.cmdLine.renderer.setShowGutter(true);
  76. input.cmdLine.renderer.setHighlightGutterLine(true);
  77. // input.cmdLine.setTheme("ace/theme/monokai");
  78. input.cmdLine.isEditorMode = true;
  79. }else{
  80. input.cmdLine.setShowPrintMargin(false);
  81. input.cmdLine.renderer.setShowGutter(false);
  82. input.cmdLine.renderer.setHighlightGutterLine(false);
  83. }
  84. input.cmdLine.resize()
  85. }
  86. /**
  87. * 打开下拉框, 例子: this.openSearchBox("",fileList,(data)=>{console.log(data.item)});
  88. * @param {string} msg 默认显示内容
  89. * @param {Function} itemList 搜索列表
  90. * @param {Function} onAccept 用户确认
  91. * @param {Function} onCompletionsFunc 修改搜索框时,通过该函数读取显示的实时显示的列表
  92. * @param {Function} onDone 窗口关闭,完成
  93. * @param {string} type 历史记录标记
  94. */
  95. openSearchBox(msg = "", itemList, onAccept, onCompletionsFunc,onDone,type='general') {
  96. let _this = this
  97. // 搜索记录
  98. let record = _this.parent.pro_cfg.search_record = _this.parent.pro_cfg.search_record || {}
  99. if(!record[type]){
  100. record[type] = []
  101. }
  102. // 打开个自定义 下拉 选项
  103. this.ace_editor.prompt(msg, {
  104. // 名字
  105. name: "searchFile",
  106. selection: [0, Number.MAX_VALUE],
  107. maxHistoryCount: itemList.length>200 ? 20 : 100,// 历史记录最大数量
  108. onAccept: function (data, label) {
  109. if (data.item && !onCompletionsFunc) this.addToHistory(data.item);
  110. onAccept(data, label);
  111. },
  112. addToHistory: function (item) {
  113. var history = this.history();
  114. history.unshift(item);
  115. delete item.message;
  116. for (var i = 1; i < history.length; i++) {
  117. if (history[i]["value"] == item.value) {
  118. history.splice(i, 1);
  119. break;
  120. }
  121. }
  122. if (this.maxHistoryCount > 0 && history.length > this.maxHistoryCount) {
  123. history.splice(history.length - 1, 1);
  124. }
  125. record[type] = history;
  126. },
  127. // 搜索文字蓝色高亮
  128. getPrefix: function (cmdLine) {
  129. var currentPos = cmdLine.getCursorPosition();
  130. var filterValue = cmdLine.getValue();
  131. return filterValue.substring(0, currentPos.column);
  132. },
  133. // 历史使用记录
  134. history: function () {
  135. let commands = JSON.parse(JSON.stringify(record[type] || []));
  136. for (let i = commands.length - 1; i >= 0; i--) {
  137. let isNot = true
  138. for (let n = 0; n < itemList.length; n++) {
  139. let now_item = itemList[n];
  140. if (commands[i].value == now_item.value) {
  141. isNot = false
  142. break;
  143. }
  144. }
  145. if (isNot) {
  146. commands = commands.slice(0, i);
  147. }
  148. }
  149. return commands
  150. },
  151. sortCompletions(completions, prefix) {
  152. if (prefix == "") return completions;
  153. prefix = prefix.toLowerCase();
  154. for (let i = 0; i < completions.length; i++) {
  155. let info = completions[i];
  156. let text = info.value.toLowerCase();
  157. let similar_count = 0;
  158. let start_pos = 999;
  159. let end_pos = 999;
  160. let break_tag = false;
  161. for (let n = 0; n < prefix.length; n++) {
  162. let char = prefix[n];
  163. let isFind = false;
  164. for (let n2 = n; n2 < text.length; n2++) {
  165. if (char == text[n2]) {
  166. if (start_pos == 999)
  167. start_pos = n2
  168. else if (!break_tag) end_pos = n2
  169. n = n2;
  170. similar_count++;
  171. isFind = true;
  172. break;
  173. } else {
  174. if (end_pos != 999) {
  175. break_tag = true;
  176. } else if (!break_tag) {
  177. start_pos = 999
  178. }
  179. }
  180. }
  181. if (!isFind) {
  182. break;
  183. }
  184. }
  185. if (end_pos == 999) start_pos = 999;
  186. let head_count = end_pos - start_pos;
  187. info.score = (_this.parent.SEARCH_SCORES[info.extname] || 70) + head_count * 10 + (start_pos != 999 ? start_pos * -10 : 0) + parseInt(similar_count / text.length * 30);
  188. }
  189. completions.sort((a, b) => b.score - a.score);
  190. return completions;
  191. },
  192. // 返回下拉列表命令
  193. getCompletions: onCompletionsFunc || function (cmdLine) {
  194. function getFilteredCompletions(commands, prefix) {
  195. var resultCommands = JSON.parse(JSON.stringify(commands));
  196. var filtered;
  197. ace.config.loadModule("ace/autocomplete", function (module) {
  198. filtered = new module.FilteredList(resultCommands);
  199. });
  200. return filtered.filterCompletions(resultCommands, prefix);
  201. }
  202. function getUniqueCommandList(commands, usedCommands) {
  203. if (!usedCommands || !usedCommands.length) {
  204. return commands;
  205. }
  206. var excludeCommands = [];
  207. usedCommands.forEach(function (item) {
  208. excludeCommands.push(item.value);
  209. });
  210. var resultCommands = [];
  211. commands.forEach(function (item) {
  212. if (excludeCommands.indexOf(item.value) === -1) {
  213. resultCommands.push(item);
  214. }
  215. });
  216. return resultCommands;
  217. }
  218. var prefix = this.getPrefix(cmdLine);
  219. var recentlyUsedCommands = getFilteredCompletions(this.history(), prefix);
  220. var otherCommands = getUniqueCommandList(itemList, recentlyUsedCommands);
  221. otherCommands = getFilteredCompletions(otherCommands, prefix);
  222. if (recentlyUsedCommands.length && otherCommands.length) {
  223. recentlyUsedCommands[0]["message"] = " Recently used";
  224. otherCommands[0]["message"] = " Other commands";
  225. }
  226. var completions = this.sortCompletions(recentlyUsedCommands.concat(otherCommands), prefix);
  227. return completions.length > 0 ? completions : [{
  228. value: "找不到命令...",
  229. error: 1
  230. }];
  231. }
  232. });
  233. }
  234. // 打开设置菜单
  235. openMenu() {
  236. // 打开配置面板
  237. if (!this.ace_editor.showSettingsMenu) {
  238. Editor.require('packages://simple-code/panel/vs-panel/ace/ext-settings_menu.js').init();
  239. }
  240. this.ace_editor.showSettingsMenu(this.parent.cfg);
  241. }
  242. }
  243. module.exports = AcePanel;