'use strict'; DS.ready(function() { DS.page.registerTaskTool('code', function() { var themes = ['vs', '3024-day', '3024-night', 'abcdef', 'ambiance', 'base16-dark', 'bespin', 'base16-light', 'blackboard', 'cobalt', 'colorforth', 'dracula', 'duotone-dark', 'duotone-light', 'eclipse', 'elegant', 'erlang-dark', // 'gruvbox-dark', 'hopscotch', 'icecoder', 'isotope', 'lesser-dark', 'liquibyte', 'material', 'mbo', 'mdn-like', 'midnight', 'monokai', 'neat', 'neo', 'night', 'oceanic-next', 'panda-syntax', 'paraiso-dark', 'paraiso-light', 'pastel-on-dark', 'railscasts', 'rubyblue', 'seti', 'shadowfox', 'solarized', 'the-matrix', 'tmrw-night-bright', 'tmrw-night-eighties', 'ttcn', 'twilight', 'vibrant-ink', 'xq-dark', 'xq-light', 'yeti', 'zenburn', ]; var self = this; var cmStyle = document.createElement('style'); cmStyle.type = 'text/css'; var rootWidget; var editor; var $menuTheme; var $menuSize; var topMenuTheme; var topMenuSize; var topMenuRun; var topMenuDebugRun; var topMenuDebugStop; var topMenuDebugStep; var topMenuDebugNext; var topMenuDebugFinish; var topMenuDebugContinue; var idTask; var userTheme; var debugOutput; var debugInput; var localsWnd = null; var UpdateBreakpoints; var formatFragment = function(code, baseIndent) { return (code); }; var Tokenize = function(streamOfText) { streamOfText += '\n'; var streamOfTokens = []; var cur = 0; var PushTok = function(lexeme, tokenClass) { // console.log(lexeme); streamOfTokens.push({ lexeme: lexeme, tokenClass: tokenClass ? tokenClass : lexeme }); }; var ReadOneline = function() { var start = cur; var len = 0; while (streamOfText[cur] != '\n' && streamOfText[cur] != '\r' && streamOfText.length > cur) { ++len; ++cur; } var str = streamOfText.substr(start, len); // memcpy(str, start, sizeof(char)* len); // str[len] = 0; if (streamOfText[start + 2] == '!' || streamOfText[start + 2] == '*') { // PushTok(start[3] == '<' ? LTYPE_COMMENT_ONELINE_BACK : LTYPE_COMMENT_ONELINE, str + (start[3] == '<' ? 4 : 3)); PushTok(str, 'COMMENT'); } return (cur - 1); }; var ReadMultiline = function() { var start = cur; var len = 0; while (streamOfText[cur] && streamOfText[cur + 1] && !(streamOfText[cur] == '*' && streamOfText[cur + 1] == '/')) { ++len; ++cur; } var str = streamOfText.substr(start, len + 2); if (streamOfText[start + 2] == '!' || streamOfText[start + 2] == '*') { // PushTok(str.substr(3), 'COMMENT'); PushTok(str, 'COMMENT'); } ++cur; // return(cur + 1); }; var ReadInt = function() { var start = cur; var len = 0; while (streamOfText[cur].charCodeAt(0) >= '0'.charCodeAt(0) && streamOfText[cur].charCodeAt(0) <= '9'.charCodeAt(0)) { ++len; ++cur; } PushTok(streamOfText.substr(start, len), 'INT'); --cur; }; var ReadSym = function() { var start = cur; var len = 0; var ccode; while ((ccode = streamOfText[cur].charCodeAt(0)) && ((ccode >= '0'.charCodeAt(0) && ccode <= '9'.charCodeAt(0)) || (ccode >= 'a'.charCodeAt(0) && ccode <= 'z'.charCodeAt(0)) || (ccode >= 'A'.charCodeAt(0) && ccode <= 'Z'.charCodeAt(0)) || (ccode == '_'.charCodeAt(0)))) { ++len; ++cur; } var str = streamOfText.substr(start, len); var found = false; /*for(var i = 0, l = sizeof(g_pszKeyWords) / sizeof(g_pszKeyWords[0]); i < l; ++i) { if(!strcmp(g_pszKeyWords[i], str)) { PushTok(LTYPE_KW, str); found = true; break; } }*/ if (!found) { PushTok(str, 'IDENTIFIER'); } --cur; }; var ReadSym2 = function() { ++cur; var start = cur; var len = 0; while (streamOfText[cur] != '"' && streamOfText.length > cur) { ++len; ++cur; } var str = []; var szSrc = start; for (var i = 0; i < len; ++i) { if (streamOfText[szSrc] == '\\') { ++szSrc; switch (streamOfText[szSrc]) { case '"': case '\'': case '\\': case '/': str.push(streamOfText[szSrc]); break; case 'b': str.push('\b'); break; case 'f': str.push('\f'); break; case 'n': str.push('\n'); break; case 'r': str.push('\r'); break; case 't': str.push('\t'); break; } } else { str.push(streamOfText[szSrc]); } ++szSrc; } //memcpy(str, start, sizeof(char)* len); PushTok(str.join(''), 'CONSTANT'); // return(cur); }; while (streamOfText[cur]) { // console.log(cur, streamOfText[cur]); switch (streamOfText[cur]) { case ' ': case '\t': case '\n': case '\r': // Skip it break; case '(': PushTok("("); break; case ')': PushTok(")"); break; case '{': PushTok("{"); break; case '}': PushTok("}"); break; case ':': PushTok(":"); break; case '/': if (streamOfText[cur + 1] == '/') { ReadOneline(); } else if (streamOfText[cur + 1] == '*') { ReadMultiline(); } else { PushTok("/"); } break; case ',': PushTok(","); break; case '"': ReadSym2(); break; default: var ccode = streamOfText[cur].charCodeAt(0); if (ccode >= '0'.charCodeAt(0) && ccode <= '9'.charCodeAt(0)) { ReadInt(); break; } if ( (ccode >= 'a'.charCodeAt(0) && ccode <= 'z'.charCodeAt(0)) || (ccode >= 'A'.charCodeAt(0) && ccode <= 'Z'.charCodeAt(0)) || (ccode == '_'.charCodeAt(0))) { ReadSym(); break; } //fprintf(stderr, "Unexpected token '%c'\n", *cur); //return(false); } ++cur; } return (streamOfTokens); }; var VisualizeSpaces = function(d) { d = d.replace(/\n/g, '↵\n'); d = d.replace(/ /g, '˽'); return (d); }; var folders = ['Header Files', 'Source Files']; var isDebugging = false; this.testCode = function() { var err = []; editor.foreach(function(file) { // console.log(file); if (file.name.substr(-2) == '.c' || file.name.substr(-2) == '.h' || file.name.substr(-4) == '.cpp' || file.name.substr(-4) == '.hpp') { var code = file.content.split('\n'); if (file.name.substr(-2) == '.h' || file.name.substr(-4) == '.hpp') { if (code[0].substr(0, 7) != '#ifndef' || code[1].substr(0, 7) != '#define') { err.push(['Ожидался Header guards', file.name, 1]); } } var tcPrev = 0; for (var i = 0, l = code.length; i < l; ++i) { var str = code[i]; var pFound = false; for (var j = 0, jl = str.length; j < jl; ++j) { if (/\s/.test(str[j])) { continue; } if (pFound) { if (str.substr(j, 7) == 'include' && /\.(c|cpp)["\>]/.test(str.substr(j + 7))) { err.push(['Включать можно только заголовочные файлы', file.name, i + 1]); } break; } if (str[j] == '#') { pFound = true; } } var tc = 0; for (var j = 0, jl = str.length; j < jl; ++j) { if (str[j] == '\t') { ++tc; } else if (str[j] == ' ') { err.push(['Выравнивание должно выполняться табуляцией', file.name, i + 1]); break; } else { break; } } // console.log(tc); if (Math.abs(tc - tcPrev) > 1) { // err.push(['Количество отступов в соседних строках не должно отличаться больше чем на 1', file.name, i + 1]); } tcPrev = tc; /* var bFound = false; var cFound = false; var inDC = false; var inSC = false; for(var j = 0, jl = str.length; j < jl; ++j){ if(str[j] == '"'){ inDC = !inDC; } if(inDC){ continue; } if(str[j] == '\''){ inSC = !inSC; } if(inSC){ continue; } if(!bFound && (str[j] == '{' || str[j] == '}')){ bFound = true; } else if(str[j] != '\t' && str[j] != ' '){ cFound = true; } } if(bFound && cFound){ err.push(['Фигурная скобка должна быть на отдельной строке', file.name, i + 1]); } */ } var lexs = Tokenize(file.content); console.log(lexs); var validClass = null; var countOpenBraces = 0; var structUnionsCount = 0; for (var i = 0, l = lexs.length; i < l; ++i) { var lex = lexs[i]; if (lex.tokenClass == 'IDENTIFIER' && i + 2 < l && (lexs[i + 2].tokenClass == '{' || lexs[i + 2].tokenClass == ':')) { var className = lexs[i + 1].lexeme; if (lex.lexeme == 'class') { if (file.name != className + '.h' && file.name != className + '.hpp') { err.push(['Класс ' + className + ' должен быть описать в файлах ' + className + '.h и ' + className + '.cpp', file.name, 0]); } else { validClass = className; } } else if (lex.lexeme == 'struct' || lex.lexeme == 'union' || lex.lexeme == 'enum') { ++structUnionsCount; } // console.error(className); } if (lex.tokenClass == '{') { ++countOpenBraces; } } if (validClass && (countOpenBraces - structUnionsCount) > 1) { err.push(['Методы класса ' + validClass + ' должны быть реализованы в файле ' + validClass + '.cpp', file.name, 0]); } } }); return (err.length ? err : null); }; var PromptTestRun = function(reallyPrompt) { var RunWithInput = function(input) { DS.progressWindow('Выполнение...'); editor.saveAll(function() { var test = self.testCode(); if (test) { var msg = []; for (var i = 0, l = test.length; i < l; ++i) { msg.push(test[i][1] + ':' + test[i][2] + ' - ' + test[i][0]); } DS.invokeEvent('arm/error', msg.join("\n")); DS.progressWindow(); DS.msg('Найдены ошибки оформления кода', 'red'); return; } DS.ARM.runTaskWithInput(idTask, input, function(d) { console.warn(d); DS.progressWindow(); if (d.success) { DS.invokeEvent('arm/info', 'Вывод программы\n' + '---------------\n' + VisualizeSpaces(d.data.test_run_text) + '\n' + '---------------\n' + 'Код возврата: ' + d.data.exit_code + '\n'); } }); }); }; var input = DS.page.getTaskField('test-input') || ''; if (input && !reallyPrompt) { RunWithInput(input); DS.msg('Для установки входных данных удерживайте Shift при нажатии'); return; } var wnd = DS.create({ DStype: 'window', position: 'auto', destroyOnClose: true, reqWidth: 600, items: [ ['title', 'Запуск', '->', { DStype: 'window-button-close' }], { DStype: 'form-panel', items: [{ DStype: 'list-layout', items: [{ DStype: 'textarea', editor: false, label: 'Входные данные', 'class': 'monotype code', name: 'input_data' }, { DStype: 'column-layout', items: [{ DStype: 'button', label: 'Запуск!', listeners: { click: function() { var $form = this.getForm(); var data = $form.getFields(); DS.page.setTaskField('test-input', data.input_data); $form.parent().close(); RunWithInput(data.input_data); } } }, { DStype: 'button', label: 'Отладка', listeners: { click: function() { var $form = this.getForm(); var data = $form.getFields(); DS.page.setTaskField('test-input', data.input_data); $form.parent().close(); // RunWithInput(data.input_data); self.saveAll(function() { if (data.input_data.length) { DS.ARM.debugStartWithInput(idTask, data.input_data, function(d) {}); } else { DS.ARM.debugStart(idTask, function(d) {}); } }); } } }] }] }] } ] }).open(); wnd.find('form-panel')[0].setFields({ input_data: input }); }; var initWidget = function(element) { rootWidget = DS.create({ DStype: 'list-layout', renderTo: element // ,blockstyle: 'position: relative;height: 100%;overflow: hidden;' , wrapClass: 'code-base', items: [{ DStype: 'div' // ,blockstyle: 'position: absolute; top: 30px; left: 0; bottom: 30px; right: 0;' , blockstyle: 'position: absolute; top: 0; left: 0; bottom: 30px; right: 0;', items: [{ DStype: 'div' // ,blockstyle: 'background-color: rgba(0,255,0,0.3);position: absolute;top: 0; left: 0; width: 300px; bottom: 0' , id: 'editor_area_left', items: [{ DStype: 'tree', root: 'Проект' // ,editable: true , name: 'files_tree', items: [], listeners: { click: function(data) { data = DS.gel(data.object).getData(); if (data.isFile) { editor.openFile(data.id); } // console.warn(data); } }, menuObj: DS.create({ DStype: 'menu', display: false, items: [{ text: _('Добавить новый файл'), name: 'add', listeners: { click: function(o) { var data = DS.gel(this.parent().obj).getData(); if (data.isFolder) { var folderId = data.id.substr(2); DS.create({ DStype: 'window', position: 'auto', destroyOnClose: true, reqWidth: 300, items: [ ['title', { DStype: 'html', html: 'Новый файл' }, '->', { DStype: 'window-button-close' }], { DStype: 'form-panel', items: [{ DStype: 'list-layout', items: [{ DStype: 'combo', label: 'Раздел', items: (function() { var items = []; for (var i = 0, l = folders.length; i < l; ++i) { items.push({ text: folders[i], value: i }); } return (items); })(), value: folderId, name: 'folder' }, { DStype: 'textfield', label: 'Имя файла', name: 'filename' }, { DStype: 'button', label: 'Добавить', listeners: { click: function() { var form = this.getForm(); var data = form.getFields(); var bad = false; data.filename = data.filename.trim(); if (!data.filename) { form.find('=filename')[0].AddError('Необходимо ввести имя файла'); bad = true; } if (data.folder === '') { form.find('=folder')[0].AddError('Необходимо выбрать раздел'); bad = true; } if (!bad) { var cont = ''; if (data.filename.substr(-2) == '.h' || data.filename.substr(-4) == '.hpp') { var len = 1; if (data.filename.substr(-1) == 'p') { len = 3; } editor.createFile(data.filename.substr(0, data.filename.length - len) + 'cpp', -1, '#include "' + data.filename + '"\n\n', true); var ident = '__' + data.filename.substr(0, data.filename.length - len).replace(/[^a-zA-Z0-9]/g, '_').toUpperCase() + '_H'; cont = '#ifndef ' + ident + '\n#define ' + ident + '\n\n\n\n#endif\n'; } editor.createFile(data.filename, data.folder, cont, true); form.parent().close(); } } } }] }] } ] }).open(); } } } }, '-', { text: _('Копировать'), name: 'copy', listeners: { click: function(o) { var data = DS.gel(this.parent().obj).getData(); var fileId = data.id; DS.create({ DStype: 'window', position: 'auto', destroyOnClose: true, reqWidth: 300, items: [ ['title', { DStype: 'html', html: 'Скопировать' }, '->', { DStype: 'window-button-close' }], { DStype: 'form-panel', items: [{ DStype: 'list-layout', items: [{ DStype: 'textfield', label: 'Имя файла', name: 'filename' }, { DStype: 'button', label: 'Сохранить', listeners: { click: function() { var form = this.getForm(); var data = form.getFields(); var bad = false; data.filename = data.filename.trim(); if (!data.filename) { form.find('=filename')[0].AddError('Необходимо ввести имя файла'); bad = true; } if (!editor.cloneFile(fileId, data.filename)) { form.find('=filename')[0].AddError('Файл с таким именем уже существует'); bad = true; } if (!bad) { form.parent().close(); } } } }] }] } ] }).open().find('form-panel')[0].setFields({ filename: editor.getFileName(fileId) }); } } }, { text: _('Переименовать'), name: 'ren', listeners: { click: function(o) { var data = DS.gel(this.parent().obj).getData(); var fileId = data.id; DS.create({ DStype: 'window', position: 'auto', destroyOnClose: true, reqWidth: 300, items: [ ['title', { DStype: 'html', html: 'Переименовать' }, '->', { DStype: 'window-button-close' }], { DStype: 'form-panel', items: [{ DStype: 'list-layout', items: [{ DStype: 'textfield', label: 'Имя файла', name: 'filename' }, { DStype: 'button', label: 'Сохранить', listeners: { click: function() { var form = this.getForm(); var data = form.getFields(); var bad = false; data.filename = data.filename.trim(); if (!data.filename) { form.find('=filename')[0].AddError('Необходимо ввести имя файла'); bad = true; } if (!editor.renameFile(fileId, data.filename)) { form.find('=filename')[0].AddError('Файл с таким именем уже существует'); bad = true; } if (!bad) { form.parent().close(); } } } }] }] } ] }).open().find('form-panel')[0].setFields({ filename: editor.getFileName(fileId) }); } } }, { text: _('Удалить'), name: 'del', listeners: { click: function(o) { var data = DS.gel(this.parent().obj).getData(); DS.confirm('Вы действительно хотите удалить этот файл? Это действие нельзя отменить.', function() { editor.removeFile(data.id); }); console.warn(data); } } }] }) }] }, { DStype: 'div' // ,blockstyle: 'background-color: rgba(0,0,255,0.3);position: absolute;top: 0; left: 300px; width: 10px; bottom: 0; cursor: ew-resize;' , id: 'editor_area_drag' }, { DStype: 'div', blockstyle: 'position: absolute;top: 6px; left: 210px; right: 0; bottom: 0', id: 'editor_area_right', items: [{ DStype: 'div', blockstyle: 'position: absolute; top: 0; left: 0; height: 30px; right: 0;', name: 'tabs_header' /* ,items: [ '
main.cpp*
' ,'
main.cpp
' ,'
main.h
' ] */ }, { DStype: 'div', blockstyle: 'position: absolute; top: 30px; left: 0; bottom: 0; right: 0;' // background-color: rgba(255,0,0,0.3); , name: 'tabs_code', items: ['Выберите файл или создайте новый'] }] }] }, { DStype: 'div', blockstyle: 'top: auto;bottom: 0;', wrapClass: 'menu-wrapper' // ,name: 'tabs_code' , items: ['
Debug
'] }, { DStype: 'div', blockstyle: 'height: 300px; bottom: 24px;', wrapClass: 'debug-window' // ,name: 'tabs_code' , items: ['
', '', '
', ''] }] }); debugOutput = DS.q('.debug-log', rootWidget.getObject())[0]; (function() { var isResising = false; var mposX = 0; var dposX = 0; var divLeft = DS.gid('element-editor_area_left'); var divDrag = DS.gid('element-editor_area_drag'); var divRight = DS.gid('element-editor_area_right'); DS.addEvent(divDrag, 'mousedown', function(event) { isResising = true; console.log(event); mposX = event.clientX; dposX = parseInt(DS.css(divDrag, 'left')); event.stopPropagation(); }); DS.addEvent(window, 'mouseup', function(event) { isResising = false; }); DS.addEvent(window, 'mousemove', function(event) { if (isResising) { var left = (event.clientX - mposX + dposX); if (left < 100) { left = 100; } if (left > 600) { left = 600; } DS.css(divDrag, 'left', left + 'px'); DS.css(divLeft, 'width', left + 'px'); DS.css(divRight, 'left', (left + 10) + 'px'); document.getSelection().removeAllRanges(); } }); })(); (function() { var isResising = false; var mposX = 0; var dposX = 0; var divLeft = DS.q('.debug-window', rootWidget.getObject())[0]; var divDrag = DS.q('.window-drag', divLeft)[0]; // var divRight = DS.gid('element-editor_area_right'); DS.addEvent(divDrag, 'mousedown', function(event) { isResising = true; console.log(event); mposX = -event.clientY; dposX = parseInt(DS.css(divLeft, 'height')); event.stopPropagation(); }); DS.addEvent(window, 'mouseup', function(event) { isResising = false; }); DS.addEvent(window, 'mousemove', function(event) { if (isResising) { var left = (-event.clientY - mposX + dposX); if (left < 100) { left = 100; } if (left > 600) { left = 600; } // DS.css(divDrag, 'left', left+'px'); DS.css(divLeft, 'height', left + 'px'); // DS.css(divRight, 'left', (left + 10)+'px'); document.getSelection().removeAllRanges(); } }); })(); (function() { var btnDebug = DS.q('.bbar-debug', rootWidget.getObject())[0]; var divWindow = DS.q('.debug-window', rootWidget.getObject())[0]; debugInput = DS.q('.debug-input', rootWidget.getObject())[0]; debugInput.disabled = true; // var divDrag = DS.q('.window-drag', divLeft)[0]; DS.addEvent(debugInput, 'keypress', function(e) { if (e.keyCode == DS.KEY.ENTER) { DS.ARM.debugInput(debugInput.value + '\n', function(d) { if (d.success) { var span = document.createElement('span'); span.innerText = debugInput.value; span.className = '-user-input'; debugOutput.appendChild(span); debugOutput.appendChild(document.createElement('br')); debugInput.value = ''; debugOutput.scrollTop = debugOutput.scrollTopMax; } }); } }); DS.addEvent(btnDebug, 'click', function() { divWindow.classList.add('-show'); }); DS.addEvent(window, 'click', function(e) { var el = e.target; while (el) { if (el == divWindow || el == btnDebug) { return; } el = el.parentNode; } divWindow.classList.remove('-show'); console.warn(e); }); })(); }; var initEditor = function() { editor = new(function() { var files = []; var tabs = []; var activeTab = -1; window.tabs = tabs; var tabs_header = rootWidget.find('=tabs_header')[0].getObject(); var tabs_code = rootWidget.find('=tabs_code')[0].getObject(); this.createFile = function(name, folder, content, open, noUpdate) { for (var i = 0, l = files.length; i < l; ++i) { if (files[i] && files[i].name == name) { DS.msg('Файл с таким именем уже существует', 'red'); return; } } if (folder < 0) { folder = 1; var ext = name.substr(name.lastIndexOf('.') + 1); switch (ext) { case 'h': case 'hpp': folder = 0; break; } } files.push({ name: name, folder: folder, content: formatFragment(content) }); if (open) { this.openFile(files.length - 1, true); } if (!noUpdate) { this.updateFilesTree(); } }; this.updateFilesTree = function() { var _folders = []; for (var i = 0, l = folders.length; i < l; ++i) { _folders.push({ title: folders[i], opened: true, menuconf: DS.util.htmlescape(DS.JSON.encode({ _default: false, add: true })), data: { isFolder: true, id: 'f_' + i }, items: [] }); } for (var i = 0, l = files.length; i < l; ++i) { var file = files[i]; if (file) { _folders[file.folder].items.push({ title: file.name, menuconf: DS.util.htmlescape(DS.JSON.encode({ _default: false, del: true, ren: true, copy: true })), data: { isFile: true, id: i }, items: [] }); } } var edt = rootWidget.find('=files_tree')[0]; edt.config._savedItems = _folders; edt = edt.reRender(); edt.parent().childrens[0] = edt; }; var makeMarker = function() { var marker = document.createElement("div"); marker.style.color = "rgb(255, 0, 0)"; marker.style.fontSize = "24px"; marker.style.position = "absolute"; marker.style.top = "-7px"; marker.style.left = "-30px"; marker.innerHTML = "●"; return (marker); }; this.openFile = function(id, doSave) { for (var i = 0, l = tabs.length; i < l; ++i) { if (tabs[i] && tabs[i].fileId == id) { this.activateTab(i); return; } } var elTab = document.createElement('div'); //
main.cpp*
elTab.className = 'editor_tab'; elTab.appendChild(document.createTextNode(files[id].name + ' ')); var cls = document.createElement('i'); elTab.appendChild(cls); DS.addEvent(elTab, 'click', (function(tid) { return (function() { this.activateTab(tid); }.bind(this)); }.bind(this))(tabs.length)); DS.addEvent(cls, 'click', (function(tid) { return (function(e) { this.closeTab(tid); e.stopPropagation(); }.bind(this)); }.bind(this))(tabs.length), true); tabs_header.appendChild(elTab); var div = document.createElement('div'); div.style.cssText = 'position: absolute; top: 0; left: 0; right: 0; bottom: 0;'; tabs_code.appendChild(div); var edt = CodeMirror(div, { mode: "text/x-csrc", indentWithTabs: true, lineNumbers: true, indentUnit: 4, lineWiseCopyCut: true, resetSelectionOnContextMenu: false, styleActiveLine: true, matchBrackets: true, autoEnabled: true, foldGutter: true, scrollPastEnd: true, highlightSelectionMatches: true, gutters: ["CodeMirror-linenumbers", "breakpoints", "codeflow", "CodeMirror-lint-markers", "CodeMirror-foldgutter"], extraKeys: { "Ctrl-Space": "autocomplete", "Ctrl-D": function(cm) { console.warn(cm); var selectedText = cm.getSelection(); // Need to grab the Active Selection if (selectedText) { var head = cm.getCursor('head'); var anchor = cm.getCursor('anchor'); cm.replaceSelection(selectedText + selectedText); cm.focus(); cm.setSelection(head, anchor); } else { window.cm = cm; var cursor = cm.getCursor(); selectedText = cm.getLine(cursor.line); var oldLine = cursor.line; var oldCh = cursor.ch; cursor.ch = selectedText.length; cm.replaceSelection('\n' + selectedText); cm.focus(); cm.setCursor(oldLine, oldCh); } } /* ,"'('": function(cm) { cm.autoFormat(cm, '('); }, "')'": function(cm) { cm.autoFormat(cm, ')'); }, "'\''": function(cm) { cm.autoFormat(cm, '\''); }, "'\"'": function(cm) { cm.autoFormat(cm, '\"'); }, "'{'": function(cm) { cm.autoFormat(cm, '{'); }, "'['": function(cm) { cm.autoFormat(cm, '['); }, "']'": function(cm) { cm.autoFormat(cm, ']'); }, */ /* "Enter": function(cm) { cm.autoFormat(cm, '13'); }, "Backspace": function(cm) { cm.autoFormat(cm, '12'); }, */ /* "Ctrl-D": function(cm) { cm.autoFormat(cm, 'CtrlD'); }, */ /* "Ctrl-Up": function(cm) { cm.autoFormat(cm, 'CtrlUp'); }, "Ctrl-Down": function(cm) { cm.autoFormat(cm, 'CtrlDown'); }, */ /* "Shift-Ctrl-Down": function(cm) { cm.autoFormat(cm, 'CtrlShiftDown'); } */ }, value: formatFragment(files[id].content), theme: userTheme || 'vs' // ,lint: true , lint: { getAnnotations: function(code, updateLinting, options) { //debugger; var listFiles = []; for (var i = 0, l = tabs.length; i < l; ++i) { if (tabs[i]) { files[tabs[i].fileId].content = tabs[i].editor.getValue() } } for (var i = 0, l = files.length; i < l; ++i) { if (files[i]) { listFiles.push([files[i].name, files[i].content]); } } DS.ARM.getCodeLint(idTask, files[id].name, listFiles, function(d) { if (d.success) { var list = []; for (var i = 0, l = d.data.length; i < l; ++i) { var el = d.data[i]; list.push({ from: CodeMirror.Pos(el[2] - 1, el[3] - 1), to: CodeMirror.Pos(el[4] - 1, el[5]), message: el[1], severity: el[0] == 0 ? 'warning' : 'error' }); // [0/1 (w/e), "msg", LineFrom, CharFrom, LineTo, CharTo] } updateLinting(list); } }); // console.info(code, options); // DS.ARM.getCodeLint // updateLinting([{from: CodeMirror.Pos(1, 1),to: CodeMirror.Pos(1, 7),message: 'error',severity:'warning'}]); // var found =[]; // var start_line = 3, end_line = 3, start_char = 2, end_char = 5; // found.push({ // from: CodeMirror.Pos(start_line - 1, start_char), // to: CodeMirror.Pos(end_line - 1, end_char), // message: 'error' // }); // console.error(found); // window.updateLinting = updateLinting; // window.found = found; // window.cm = cm; // updateLinting(cm, found); }, 'async': true } }); edt.on('change', (function(tid) { return (function(e) { this.updateTabs(); }.bind(this)); }.bind(this))(tabs.length)); (function(canPaste) { edt.on('paste', function(o, e) { // console.error('cmpaste', e); // console.warn(e.clipboardData.getData('text/plain')); // console.warn(e.clipboardData.getData('text/html')); if (!canPaste(e.clipboardData.getData('text/plain')) && !canPaste(e.clipboardData.getData('text/html'), true)) { e.preventDefault(); DS.msg('Вставка запрещена', 'red'); return (false); } }); edt.on('drop', function(o, e) { // console.warn(e, q, w); /* console.warn(e); e.preventDefault(); return(false); */ if (!canPaste(e.dataTransfer.getData('text/plain')) && !canPaste(e.clipboardData.getData('text/html'), true)) { e.preventDefault(); DS.msg('Вставка запрещена', 'red'); return (false); } }); })(DS.page.cb.canPaste); edt.on('copy', function(o, e) { // console.warn(e, q, w); DS.page.cb.onCopy(e.target.value); // lastCopied = e.target.value; }); edt.on('cut', function(o, e) { //DS.alert(e.target.value, 'cut'); // lastCopied = e.target.value; DS.page.cb.onCopy(e.target.value); }); edt.on('save', (function(tid) { return (function(d) { var cm = d.cm; var content = files[tabs[tid].fileId].content = cm.getValue(); cm.doc.markClean(); this.updateTabs(); this.onSave && this.onSave(files[tabs[tid].fileId].name, content, d.cb); }.bind(this)); }.bind(this))(tabs.length)); edt.on("gutterClick", (function(tid) { return (function(cm, n, gutter) { if (gutter != 'CodeMirror-linenumbers') { return; } var info = cm.lineInfo(n); // console.warn(info.gutterMarkers); cm.setGutterMarker(n, "breakpoints", info.gutterMarkers && info.gutterMarkers.breakpoints ? null : makeMarker()); // cm.setGutterMarker(n, "codeflow", info.gutterMarkers ? null : makeMarker2()); if (isDebugging) { DS.ARM.debugToggleBreakpoint(files[tabs[tid].fileId].name, n + 1, function(d) { UpdateBreakpoints(); }); } }); })(tabs.length)); tabs.push({ fileId: id, elTab: elTab, elTabContent: div, editor: edt }); // window.edt = edt; this.activateTab(tabs.length - 1); if (doSave) { // edt.doc.changeGeneration(true); this.onSave && this.onSave(files[tabs[tabs.length - 1].fileId].name, files[tabs[tabs.length - 1].fileId].content); } }; this.activateTab = function(id) { activeTab = id; this.updateTabs(); var cm = tabs[activeTab].editor; cm.refresh(); // load editor }; this.getFileName = function(id) { return (files[id] && files[id].name); }; this.removeFile = function(id) { if (!files[id]) { return; } for (var i = 0, l = tabs.length; i < l; ++i) { if (tabs[i] && tabs[i].fileId == id) { this.closeTab(i); break; } } this.onRemove(files[id].name); files[id] = false; this.updateFilesTree(); } this.renameFile = function(id, new_name) { if (!files[id]) { return (false); } for (var i = 0, l = files.length; i < l; ++i) { if (files[i] && files[i].name == new_name) { DS.msg('Файл с таким именем уже существует', 'red'); return (false); } } this.onRename(files[id].name, new_name); files[id].name = new_name; this.updateTabs(); this.updateFilesTree(); return (true); }; this.cloneFile = function(id, new_name) { if (!files[id]) { return (false); } for (var i = 0, l = files.length; i < l; ++i) { if (files[i] && files[i].name == new_name) { DS.msg('Файл с таким именем уже существует', 'red'); return (false); } } this.createFile(new_name, files[id].folder, files[id].content, true); return (true) }; this.closeTab = function(id) { if (activeTab == id) { activeTab = -1; } var fn = function() { tabs_header.removeChild(tabs[id].elTab); tabs_code.removeChild(tabs[id].elTabContent); tabs[id] = false; this.updateTabs(); }.bind(this); if (!tabs[id].editor.doc.isClean()) { DS.confirm('Имеются несохраненные изменения. Закрыть?', fn); } else { fn(); } }; this.updateTabs = function() { for (var i = 0, l = tabs.length; i < l; ++i) { var tab = tabs[i]; if (tab) { DS.util[!tab.editor.doc.isClean() ? 'addClass' : 'removeClass'](tab.elTab, 'changed'); DS.util[i == activeTab ? 'addClass' : 'removeClass'](tab.elTab, 'active'); DS.css(tab.elTabContent, 'display', [i == activeTab ? 'block' : 'none']); tab.elTab.firstChild.textContent = files[tab.fileId].name + (!tab.editor.doc.isClean() ? '*' : '') + ' '; } } }; this.setTheme = function(theme) { for (var i = 0, l = tabs.length; i < l; ++i) { tabs[i] && tabs[i].editor.setOption('theme', theme); } userTheme = theme; }; this.saveAll = function(cb) { var count = tabs.length; if (!count) { cb && cb(); return; } for (var i = 0, l = count; i < l; ++i) { if (tabs[i] && !tabs[i].editor.doc.isClean()) { CodeMirror.signal(tabs[i].editor, 'save', { cm: tabs[i].editor, cb: function() { if (!--count) { cb && cb(); } } }); } else { if (!--count) { cb && cb(); } } } }; this.closeAll = function() { for (var i = 0, l = tabs.length; i < l; ++i) { tabs[i] && this.closeTab(i); } }; this.clear = function() { this.closeAll(); tabs = []; files = []; this.updateFilesTree(); }; this.refresh = function() { for (var i = 0, l = tabs.length; i < l; ++i) { tabs[i] && tabs[i].editor.refresh(); } }; this.foreach = function(cb) { for (var i = 0, l = files.length; i < l; ++i) { files[i] && cb(files[i]); } }; this.onSave = function(name, code, cb) { DS.ARM.saveTaskFile(idTask, name, code, function(d) { if (d.success) { DS.msg('Файл ' + DS.util.htmlescape(name) + ' успешно сохранен', 'green'); } else { DS.msg('Не удалось сохранить файл ' + DS.util.htmlescape(name), 'red'); } cb && cb(d); }); }; /* this.getCM = function(tab){ return(tabs[tab].editor); }; */ this.onRemove = function(name) { DS.ARM.removeTaskFile(idTask, name, function(d) { if (d.success) { DS.msg('Файл ' + DS.util.htmlescape(name) + ' успешно удален', 'green'); } else { DS.msg('Не удалось удалить файл ' + DS.util.htmlescape(name), 'red'); } }); }; this.onRename = function(old_name, new_name) { DS.ARM.renameTaskFile(idTask, old_name, new_name, function(d) { if (d.success) { DS.msg('Файл ' + DS.util.htmlescape(name) + ' успешно переименован', 'green'); } else { DS.msg('Не удалось переименовать файл ' + DS.util.htmlescape(name), 'red'); } }); }; this.getBreakPoints = function() { var bps = {}; for (var i = 0, l = tabs.length; i < l; ++i) { if (tabs[i]) { var cm = tabs[i].editor; var fileName = files[tabs[i].fileId].name; for (var j = 0;; ++j) { var line = cm.lineInfo(j); if (!line) { break; } if (line.gutterMarkers && line.gutterMarkers.breakpoints) { if (!(fileName in bps)) { bps[fileName] = []; } bps[fileName].push(line.line + 1); } } } } return (bps); }; this.setBreakPoints = function(bps) { for (var i = 0, l = tabs.length; i < l; ++i) { if (tabs[i]) { var cm = tabs[i].editor; for (var j = 0;; ++j) { var line = cm.lineInfo(j); if (!line) { break; } if (line.gutterMarkers && line.gutterMarkers.breakpoints) { cm.setGutterMarker(line.line, "breakpoints", null); } } } } for (var file in bps) { var cm = null; for (var i = 0, l = tabs.length; i < l; ++i) { if (tabs[i] && files[tabs[i].fileId].name == file) { cm = tabs[i].editor; break; } } if (cm) { var lines = bps[file]; for (var i = 0, l = lines.length; i < l; ++i) { cm.setGutterMarker(lines[i] - 1, "breakpoints", makeMarker()); } } } /* for(var i = 0, l = tabs.length; i < l; ++i){ if(tabs[i]){ var cm = tabs[i].editor; cm.refresh(); } } */ }; var makeMarker2 = function() { var marker = document.createElement("div"); marker.style.color = "rgb(255, 179, 0)"; marker.style.fontSize = "21px"; marker.style.position = "absolute"; marker.style.top = "-9px"; marker.style.left = "-27px"; marker.innerHTML = "❱"; // color: rgb(255, 179, 0); font-size: 21px; position: absolute; top: -9px; left: -27px; return (marker); }; var _runlineEditor = null; var _runlineNo = -1; this.setRunLine = function(file, line) { if (_runlineEditor) { // _runlineEditor _runlineEditor.setGutterMarker(_runlineNo, "codeflow", null); } var idFile = -1; for (var i = 0, l = files.length; i < l; ++i) { if (files[i].name == file) { idFile = i; break; } } if (idFile >= 0) { this.openFile(idFile); for (var i = 0, l = tabs.length; i < l; ++i) { if (tabs[i] && tabs[i].fileId == idFile) { var cm = tabs[i].editor; _runlineEditor = cm; _runlineNo = parseInt(line); cm.setGutterMarker(_runlineNo, "codeflow", makeMarker2()); return; } } // var info = cm.lineInfo(n); // console.warn(info.gutterMarkers); // cm.setGutterMarker(n, "breakpoints", info.gutterMarkers && info.gutterMarkers.breakpoints ? null : makeMarker()); // editor } }; })(); }; this.setRunLine = function(file, line) { editor.setRunLine(file, line); }; this.getTitle = function() { return ('Исходный код'); // tab title }; var fnModeChange = function() { var isDark = DS.page.userPrefs.get('arm/darkMode'); userTheme = DS.page.userPrefs.get('task/codeTheme/' + (isDark ? 'dark' : 'bright')) || (isDark ? 'cobalt' : 'vs'); if ($menuTheme) { var list = $menuTheme.find('checkbox'); for (var i = 0, l = list.length; i < l; ++i) { list[i].checked(false); } editor.setTheme(userTheme); list = $menuTheme.find('topmenu-item'); for (var i = 0, l = list.length; i < l; ++i) { if (list[i].config.text == userTheme) { list[i].find('checkbox')[0].checked(true); break; } } } }; var IsButtonEnabled = function(b) { return (topMenuDebugNext && !DS.util.hasClass(topMenuDebugNext, '-disabled')); } var HandleHotkey = function(e) { if (e.key == 'F5') { if (e.ctrlKey) { if (IsButtonEnabled(topMenuRun)) { PromptTestRun(e.shiftKey); } } else if (IsButtonEnabled(topMenuDebugRun)) { if (e.shiftKey) { PromptTestRun(e.shiftKey); } else { topMenuDebugRun.click(); } } else { if (e.shiftKey) { if (IsButtonEnabled(topMenuDebugStop)) { topMenuDebugStop.click(); } } else { if (IsButtonEnabled(topMenuDebugContinue)) { topMenuDebugContinue.click(); } } } } else if (e.key == 'F10') { if (IsButtonEnabled(topMenuDebugNext)) { topMenuDebugNext.click(); } } else if (e.key == 'F11') { if (e.shiftKey) { if (IsButtonEnabled(topMenuDebugFinish)) { topMenuDebugFinish.click(); } } else { if (IsButtonEnabled(topMenuDebugStep)) { topMenuDebugStep.click(); } } } }; var EnableButton = function(b, yesNo) { if (b) { DS.util[yesNo ? 'removeClass' : 'addClass'](b, '-disabled'); } } UpdateBreakpoints = function() { DS.ARM.debugListBreakpoints(function(d) { if (d.success) { editor.setBreakPoints(d.data); } }); }; var self = this; var _curFrameFile = null; var _curFrameFunc = null; var _watchLocalState = {}; var _states = { hidden: new function() { this.on = function() { isDebugging = false; DS.page.topMenu.removeButton(topMenuDebugStep); topMenuDebugStep = null; DS.page.topMenu.removeButton(topMenuDebugNext); topMenuDebugNext = null; DS.page.topMenu.removeButton(topMenuDebugFinish); topMenuDebugFinish = null; DS.page.topMenu.removeButton(topMenuDebugContinue); topMenuDebugContinue = null; DS.page.topMenu.removeButton(topMenuDebugStop); topMenuDebugStop = null; DS.page.topMenu.removeButton(topMenuRun); topMenuRun = null; DS.page.topMenu.removeButton(topMenuDebugRun); topMenuDebugRun = null; DS.removeEvent(window, 'keyup', HandleHotkey); localsWnd.close(); }; this.off = function() { topMenuRun = DS.page.topMenu.addButton(' Запуск'); DS.addEvent(topMenuRun, 'click', function(e) { PromptTestRun(e.shiftKey); }); topMenuRun.title = '[Ctrl+F5]'; DS.addEvent(window, 'keyup', HandleHotkey); topMenuDebugRun = DS.page.topMenu.addButton(' Отладка'); topMenuDebugRun.title = '[F5]'; DS.addEvent(topMenuDebugRun, 'click', function(e) { debugOutput.innerHTML = ''; if (e.shiftKey) { PromptTestRun(e.shiftKey); } else { self.saveAll(function() { DS.ARM.debugStart(idTask, editor.getBreakPoints(), function(d) { if (d.success) { // SetState(); UpdateBreakpoints(); } }); }); } }); if (!topMenuDebugNext) { topMenuDebugNext = DS.page.topMenu.addButton(''); DS.addEvent(topMenuDebugNext, 'click', function(e) { DS.ARM.debugNext(function(d) {}); }); topMenuDebugNext.title = 'Шаг с обходом [F10]'; EnableButton(topMenuDebugNext, false); } if (!topMenuDebugStep) { topMenuDebugStep = DS.page.topMenu.addButton(''); DS.addEvent(topMenuDebugStep, 'click', function(e) { DS.ARM.debugStep(function(d) {}); }); topMenuDebugStep.title = 'Шаг с заходом [F11]'; EnableButton(topMenuDebugStep, false); } if (!topMenuDebugFinish) { topMenuDebugFinish = DS.page.topMenu.addButton(''); DS.addEvent(topMenuDebugFinish, 'click', function(e) { DS.ARM.debugFinish(function(d) {}); }); topMenuDebugFinish.title = 'Выход [Shift+F11]'; EnableButton(topMenuDebugFinish, false); } if (!topMenuDebugContinue) { topMenuDebugContinue = DS.page.topMenu.addButton(''); DS.addEvent(topMenuDebugContinue, 'click', function(e) { DS.ARM.debugContinue(function(d) {}); }); topMenuDebugContinue.title = 'Продолжить [F5]'; EnableButton(topMenuDebugContinue, false); } if (!topMenuDebugStop) { topMenuDebugStop = DS.page.topMenu.addButton(''); DS.addEvent(topMenuDebugStop, 'click', function(e) { DS.ARM.debugEnd(function(d) { // if(d.success){ // onDebugStarted(); // } }); }); topMenuDebugStop.title = 'Остановить [Shift+F5]'; EnableButton(topMenuDebugStop, false); } isDebugging = true; }; }, stopped: new function() { this.on = function() { EnableButton(topMenuRun, true); EnableButton(topMenuDebugRun, true); localsWnd.close(); _curFrameFile = null; _curFrameFunc = null; _watchLocalState = {}; }; this.off = function() { EnableButton(topMenuRun, false); EnableButton(topMenuDebugRun, false); localsWnd.open(); }; }, running: new function() { this.on = function() { debugInput.disabled = false; EnableButton(topMenuDebugStop, true); DS.q('.debug-window', rootWidget.getObject())[0].classList.add('-show'); }; this.off = function() { debugInput.disabled = true; EnableButton(topMenuDebugStop, false); }; }, paused: new function() { this.on = function() { EnableButton(topMenuDebugNext, true); EnableButton(topMenuDebugStep, true); EnableButton(topMenuDebugContinue, true); // EnableButton(topMenuDebugFinish, true); EnableButton(topMenuDebugStop, true); }; this.off = function() { editor.setRunLine(null); EnableButton(topMenuDebugNext, false); EnableButton(topMenuDebugStep, false); EnableButton(topMenuDebugContinue, false); EnableButton(topMenuDebugFinish, false); EnableButton(topMenuDebugStop, false); }; } }; var _currentState = null; var SetState = function(s) { if (_currentState) { if (_currentState[0] == s) { return; } _currentState[1].off(); } console.info('State: ' + (_currentState ? _currentState[0] : 'null') + ' -> ' + s); if (!(s in _states)) { throw 'Unknown state ' + s; } _currentState = [s, _states[s]]; _currentState[1].on(); }; var onDebugOutput = function(d) { if ( /* d.data[0][0] == 'CONSOLE' || */ d.data[0][0] == 'STDOUT' || d.data[0][0] == 'STDERR') { debugOutput.appendChild(document.createTextNode(d.data[0][1])); debugOutput.scrollTop = debugOutput.scrollTopMax; } else if (d.data[0][0] == 'CONSOLE') { var i = document.createElement('i'); i.innerText = d.data[0][1]; debugOutput.appendChild(i); debugOutput.scrollTop = debugOutput.scrollTopMax; } console.log('onDebugOutput', d); }; var onDebugStarted = function() { DS.page.topMenu.removeButton(topMenuDebugRun); topMenuDebugRun = null; topMenuDebugStop = DS.page.topMenu.addButton(' Остановить'); DS.addEvent(topMenuDebugStop, 'click', function(e) { DS.ARM.debugEnd(function(d) { // if(d.success){ // onDebugStarted(); // } }); }); // var topMenuDebugStep; // var topMenuDebugNext; // var topMenuDebugFinish; }; var onDebugStopped = function(d) { console.log('onDebugStopped', d); // debugInput.disabled = true; SetState('paused'); }; var onDebugRunning = function(d) { console.log('onDebugRunning', d); SetState('running'); // editor.setRunLine(null); // debugInput.disabled = false; // DS.page.topMenu.removeButton(topMenuDebugStep); // topMenuDebugStep = null; // DS.page.topMenu.removeButton(topMenuDebugNext); // topMenuDebugNext = null; // DS.page.topMenu.removeButton(topMenuDebugFinish); // topMenuDebugFinish = null; // DS.page.topMenu.removeButton(topMenuDebugContinue); // topMenuDebugContinue = null; }; var onDebugExited = function(d) { console.log('onDebugExited', d); SetState('stopped'); }; var onDebugFrameChanged = function(d) { console.log('onDebugFrameChanged', d); if (d.data[0]) { editor.setRunLine(d.data[0].file, d.data[0].line - 1); EnableButton(topMenuDebugFinish, d.data[0].func != 'main'); var locals = d.data[0].locals; var grid = localsWnd.find('grid')[0]; var oldStore = grid.config.store; var store = []; for (var i = 0, l = locals.length; i < l; ++i) { var loc = locals[i]; loc.__hidden = (oldStore.length == locals.length) ? (oldStore[i].__hidden) : (loc.level != 0); store.push(loc); } grid.config.store = store; grid.render(); } }; // var onAuthorized = function(){ // DS.ARM.debugQueryState(); // }; var onDisconnected = function() { onDebugExited(); }; var _hasFiles = false; // Initialize all required stuff, use `element` as render root this.initialize = function(element) { idTask = DS.page.getTaskField('id'); CodeMirror.commands.save = function(editor) { CodeMirror.signal(editor, 'save', { cm: editor, cb: function() {} }); }; element.classList.add('-debugger'); document.body.appendChild(cmStyle); initWidget(element); initEditor(); //cobalt var isDark = DS.page.userPrefs.get('arm/darkMode'); userTheme = DS.page.userPrefs.get('task/codeTheme/' + (isDark ? 'dark' : 'bright')) || (isDark ? 'cobalt' : 'vs'); var menuItems = []; for (var i = 0, l = themes.length; i < l; ++i) { menuItems.push({ text: themes[i], icon: { DStype: 'checkbox', value: userTheme == themes[i] }, listeners: { click: function() { var list = this.find('!checkbox'); for (var j = 0, jl = list.length; j < jl; ++j) { list[j].checked(false); } var cb = this.find('checkbox')[0]; var isDark = DS.page.userPrefs.get('arm/darkMode'); DS.page.userPrefs.set('task/codeTheme/' + (isDark ? 'dark' : 'bright'), this.config.text); DS.page.userPrefs.save(); cb.checked(true); editor.setTheme(this.config.text); } } }); } DS.addEvent(DS, 'darkmode/deactivate', fnModeChange); DS.addEvent(DS, 'darkmode/activate', fnModeChange); $menuTheme = DS.create({ DStype: 'topmenu', items: menuItems }); var userSize = DS.page.userPrefs.get('task/codeTheme/size') || 13; cmStyle.innerHTML = '.CodeMirror{font-size: ' + userSize + 'px}'; menuItems = []; for (var i = 12; i <= 36; ++i) { menuItems.push({ text: i, icon: { DStype: 'checkbox', value: userSize == i }, listeners: { click: function() { var list = this.find('!checkbox'); for (var j = 0, jl = list.length; j < jl; ++j) { list[j].checked(false); } var cb = this.find('checkbox')[0]; DS.page.userPrefs.set('task/codeTheme/size', this.config.text); DS.page.userPrefs.save(); cb.checked(true); cmStyle.innerHTML = '.CodeMirror{font-size: ' + this.config.text + 'px}'; editor && editor.refresh(); } } }); } $menuSize = DS.create({ DStype: 'topmenu', items: menuItems }); DS.ARM.getTaskFiles(idTask, function(d) { if (d.success) { if (localStorage.getItem('IMPORT') && localStorage.getItem('IMPORT_ENTER')) { localStorage.setItem('IMPORT_ENTER', false); for (var i = 0, l = d.data.length; i < l; ++i) { DS.ARM.removeTaskFile(idTask, d.data[i].name, function() {}); } d.data = DS.JSON.decode(localStorage.getItem('IMPORT')); } for (var i = 0, l = d.data.length; i < l; ++i) { _hasFiles = true; editor.createFile(d.data[i].name, -1, d.data[i].file, false, true); DS.ARM.saveTaskFile(idTask, d.data[i].name, d.data[i].file, function() {}); editor.updateFilesTree(); } } }); // editor.createFile('main.cpp', 0, 'void main(){}', false, true); // editor.createFile('main.h', 1, '#ifndef _MAIN_H_'); DS.addEvent(DS, 'msg/' + ARMmessage.DBG_OUTPUT, onDebugOutput); DS.addEvent(DS, 'msg/' + ARMmessage.DBG_STOPPED, onDebugStopped); DS.addEvent(DS, 'msg/' + ARMmessage.DBG_RUNNING, onDebugRunning); DS.addEvent(DS, 'msg/' + ARMmessage.DBG_EXITED, onDebugExited); DS.addEvent(DS, 'msg/' + ARMmessage.DBG_FRAME_CHANGED, onDebugFrameChanged); // DS.addEvent(DS, 'arm/authorized', onAuthorized); DS.addEvent(DS, 'ws/disconnected', onDisconnected); localsWnd = DS.create({ DStype: 'window' // ,destroyOnClose: true , reqWidth: 600, items: [ ['title', 'Locals'], { DStype: 'grid', 'class': 'debugger-watch', store: [ /*{ name: 'argc' ,value: '0' ,type: 'int' ,level: 0 ,__hidden: false } ,{ name: 'argv' ,value: '0x0000000000000000' ,type: 'char**' ,level: 0 ,__hidden: false } ,{ name: '' ,value: '' ,type: 'char*' ,level: 1 ,__hidden: true } ,{ name: 'blendDesc' ,value: '' ,type: 'GXBlendDesc' ,level: 0 ,__hidden: false } ,{ name: 'useAlphaToCoverage' ,value: '0' ,type: 'int' ,level: 1 ,__hidden: true } ,{ name: 'useIndependentBlend' ,value: '0' ,type: 'int' ,level: 1 ,__hidden: true } ,{ name: 'renderTarget' ,value: '0x0000002f2bb3f318' ,type: 'GXBlendDesc::GXBlendRTdesc[8]' ,level: 1 ,__hidden: true } ,{ name: '[0]' ,value: '' ,type: 'GXBlendDesc::GXBlendRTdesc' ,level: 2 ,__hidden: true } ,{ name: 'useBlend' ,value: '1' ,type: 'int' ,level: 3 ,__hidden: true } ,{ name: 'blendSrcColor' ,value: 'GXBLEND_SRC_ALPHA (5)' ,type: 'GXBLEND' ,level: 3 ,__hidden: true } ,{ name: 'blendDstColor' ,value: 'GXBLEND_INV_SRC_ALPHA (6)' ,type: 'GXBLEND' ,level: 3 ,__hidden: true } ,{ name: 'blendOpColor' ,value: 'GXBLEND_OP_ADD (1)' ,type: 'GXBLEND_OP' ,level: 3 ,__hidden: true } ,{ name: 'blendSrcAlpha' ,value: 'GXBLEND_SRC_ALPHA (5)' ,type: 'GXBLEND' ,level: 3 ,__hidden: true } ,{ name: 'blendDstAlpha' ,value: 'GXBLEND_INV_SRC_ALPHA (6)' ,type: 'GXBLEND' ,level: 3 ,__hidden: true } ,{ name: 'blendOpAlpha' ,value: 'GXBLEND_OP_ADD (1)' ,type: 'GXBLEND_OP' ,level: 3 ,__hidden: true } ,{ name: 'u8RenderTargetWriteMask' ,value: '15 \'\\xf\'' ,type: 'unsigned char' ,level: 3 ,__hidden: true } ,{ name: '[1]' ,value: '' ,type: 'GXBlendDesc::GXBlendRTdesc' ,level: 2 ,__hidden: true } ,{ name: 'useBlend' ,value: '0' ,type: 'int' ,level: 3 ,__hidden: true } ,{ name: 'blendSrcColor' ,value: 'GXBLEND_ONE (2)' ,type: 'GXBLEND' ,level: 3 ,__hidden: true } ,{ name: 'blendDstColor' ,value: 'GXBLEND_ZERO (1)' ,type: 'GXBLEND' ,level: 3 ,__hidden: true } ,{ name: 'blendOpColor' ,value: 'GXBLEND_OP_ADD (1)' ,type: 'GXBLEND_OP' ,level: 3 ,__hidden: true } ,{ name: 'blendSrcAlpha' ,value: 'GXBLEND_ONE (2)' ,type: 'GXBLEND' ,level: 3 ,__hidden: true } ,{ name: 'blendDstAlpha' ,value: 'GXBLEND_ZERO (1)' ,type: 'GXBLEND' ,level: 3 ,__hidden: true } ,{ name: 'blendOpAlpha' ,value: 'GXBLEND_OP_ADD (1)' ,type: 'GXBLEND_OP' ,level: 3 ,__hidden: true } ,{ name: 'u8RenderTargetWriteMask' ,value: '15 \'\\xf\'' ,type: 'unsigned char' ,level: 3 ,__hidden: true } ,{ name: '[2]' ,value: '' ,type: 'GXBlendDesc::GXBlendRTdesc' ,level: 2 ,__hidden: true } ,{ name: 'useBlend' ,value: '0' ,type: 'int' ,level: 3 ,__hidden: true } ,{ name: 'blendSrcColor' ,value: 'GXBLEND_ONE (2)' ,type: 'GXBLEND' ,level: 3 ,__hidden: true } ,{ name: 'blendDstColor' ,value: 'GXBLEND_ZERO (1)' ,type: 'GXBLEND' ,level: 3 ,__hidden: true } ,{ name: 'blendOpColor' ,value: 'GXBLEND_OP_ADD (1)' ,type: 'GXBLEND_OP' ,level: 3 ,__hidden: true } ,{ name: 'blendSrcAlpha' ,value: 'GXBLEND_ONE (2)' ,type: 'GXBLEND' ,level: 3 ,__hidden: true } ,{ name: 'blendDstAlpha' ,value: 'GXBLEND_ZERO (1)' ,type: 'GXBLEND' ,level: 3 ,__hidden: true } ,{ name: 'blendOpAlpha' ,value: 'GXBLEND_OP_ADD (1)' ,type: 'GXBLEND_OP' ,level: 3 ,__hidden: true } ,{ name: 'u8RenderTargetWriteMask' ,value: '15 \'\\xf\'' ,type: 'unsigned char' ,level: 3 ,__hidden: true } ,{ name: '[3]' ,value: '' ,type: 'GXBlendDesc::GXBlendRTdesc' ,level: 2 ,__hidden: true } ,{ name: 'useBlend' ,value: '0' ,type: 'int' ,level: 3 ,__hidden: true } ,{ name: 'blendSrcColor' ,value: 'GXBLEND_ONE (2)' ,type: 'GXBLEND' ,level: 3 ,__hidden: true } ,{ name: 'blendDstColor' ,value: 'GXBLEND_ZERO (1)' ,type: 'GXBLEND' ,level: 3 ,__hidden: true } ,{ name: 'blendOpColor' ,value: 'GXBLEND_OP_ADD (1)' ,type: 'GXBLEND_OP' ,level: 3 ,__hidden: true } ,{ name: 'blendSrcAlpha' ,value: 'GXBLEND_ONE (2)' ,type: 'GXBLEND' ,level: 3 ,__hidden: true } ,{ name: 'blendDstAlpha' ,value: 'GXBLEND_ZERO (1)' ,type: 'GXBLEND' ,level: 3 ,__hidden: true } ,{ name: 'blendOpAlpha' ,value: 'GXBLEND_OP_ADD (1)' ,type: 'GXBLEND_OP' ,level: 3 ,__hidden: true } ,{ name: 'u8RenderTargetWriteMask' ,value: '15 \'\\xf\'' ,type: 'unsigned char' ,level: 3 ,__hidden: true } ,{ name: '[4]' ,value: '' ,type: 'GXBlendDesc::GXBlendRTdesc' ,level: 2 ,__hidden: true } ,{ name: 'useBlend' ,value: '0' ,type: 'int' ,level: 3 ,__hidden: true } ,{ name: 'blendSrcColor' ,value: 'GXBLEND_ONE (2)' ,type: 'GXBLEND' ,level: 3 ,__hidden: true } ,{ name: 'blendDstColor' ,value: 'GXBLEND_ZERO (1)' ,type: 'GXBLEND' ,level: 3 ,__hidden: true } ,{ name: 'blendOpColor' ,value: 'GXBLEND_OP_ADD (1)' ,type: 'GXBLEND_OP' ,level: 3 ,__hidden: true } ,{ name: 'blendSrcAlpha' ,value: 'GXBLEND_ONE (2)' ,type: 'GXBLEND' ,level: 3 ,__hidden: true } ,{ name: 'blendDstAlpha' ,value: 'GXBLEND_ZERO (1)' ,type: 'GXBLEND' ,level: 3 ,__hidden: true } ,{ name: 'blendOpAlpha' ,value: 'GXBLEND_OP_ADD (1)' ,type: 'GXBLEND_OP' ,level: 3 ,__hidden: true } ,{ name: 'u8RenderTargetWriteMask' ,value: '15 \'\\xf\'' ,type: 'unsigned char' ,__hidden: true } ,{ name: '[5]' ,value: '' ,type: 'GXBlendDesc::GXBlendRTdesc' ,level: 2 ,__hidden: true } ,{ name: 'useBlend' ,value: '0' ,type: 'int' ,level: 3 ,__hidden: true } ,{ name: 'blendSrcColor' ,value: 'GXBLEND_ONE (2)' ,type: 'GXBLEND' ,level: 3 ,__hidden: true } ,{ name: 'blendDstColor' ,value: 'GXBLEND_ZERO (1)' ,type: 'GXBLEND' ,level: 3 ,__hidden: true } ,{ name: 'blendOpColor' ,value: 'GXBLEND_OP_ADD (1)' ,type: 'GXBLEND_OP' ,level: 3 ,__hidden: true } ,{ name: 'blendSrcAlpha' ,value: 'GXBLEND_ONE (2)' ,type: 'GXBLEND' ,level: 3 ,__hidden: true } ,{ name: 'blendDstAlpha' ,value: 'GXBLEND_ZERO (1)' ,type: 'GXBLEND' ,level: 3 ,__hidden: true } ,{ name: 'blendOpAlpha' ,value: 'GXBLEND_OP_ADD (1)' ,type: 'GXBLEND_OP' ,level: 3 ,__hidden: true } ,{ name: 'u8RenderTargetWriteMask' ,value: '15 \'\\xf\'' ,type: 'unsigned char' ,level: 3 ,__hidden: true } ,{ name: '[6]' ,value: '' ,type: 'GXBlendDesc::GXBlendRTdesc' ,level: 2 ,__hidden: true } ,{ name: 'useBlend' ,value: '0' ,type: 'int' ,level: 3 ,__hidden: true } ,{ name: 'blendSrcColor' ,value: 'GXBLEND_ONE (2)' ,type: 'GXBLEND' ,level: 3 ,__hidden: true } ,{ name: 'blendDstColor' ,value: 'GXBLEND_ZERO (1)' ,type: 'GXBLEND' ,level: 3 ,__hidden: true } ,{ name: 'blendOpColor' ,value: 'GXBLEND_OP_ADD (1)' ,type: 'GXBLEND_OP' ,level: 3 ,__hidden: true } ,{ name: 'blendSrcAlpha' ,value: 'GXBLEND_ONE (2)' ,type: 'GXBLEND' ,level: 3 ,__hidden: true } ,{ name: 'blendDstAlpha' ,value: 'GXBLEND_ZERO (1)' ,type: 'GXBLEND' ,level: 3 ,__hidden: true } ,{ name: 'blendOpAlpha' ,value: 'GXBLEND_OP_ADD (1)' ,type: 'GXBLEND_OP' ,level: 3 ,__hidden: true } ,{ name: 'u8RenderTargetWriteMask' ,value: '15 \'\\xf\'' ,type: 'unsigned char' ,level: 3 ,__hidden: true } ,{ name: '[7]' ,value: '' ,type: 'GXBlendDesc::GXBlendRTdesc' ,level: 2 ,__hidden: true } ,{ name: 'useBlend' ,value: '0' ,type: 'int' ,level: 3 ,__hidden: true } ,{ name: 'blendSrcColor' ,value: 'GXBLEND_ONE (2)' ,type: 'GXBLEND' ,level: 3 ,__hidden: true } ,{ name: 'blendDstColor' ,value: 'GXBLEND_ZERO (1)' ,type: 'GXBLEND' ,level: 3 ,__hidden: true } ,{ name: 'blendOpColor' ,value: 'GXBLEND_OP_ADD (1)' ,type: 'GXBLEND_OP' ,level: 3 ,__hidden: true } ,{ name: 'blendSrcAlpha' ,value: 'GXBLEND_ONE (2)' ,type: 'GXBLEND' ,level: 3 ,__hidden: true } ,{ name: 'blendDstAlpha' ,value: 'GXBLEND_ZERO (1)' ,type: 'GXBLEND' ,level: 3 ,__hidden: true } ,{ name: 'blendOpAlpha' ,value: 'GXBLEND_OP_ADD (1)' ,type: 'GXBLEND_OP' ,level: 3 ,__hidden: true } ,{ name: 'u8RenderTargetWriteMask' ,value: '15 \'\\xf\'' ,type: 'unsigned char' ,level: 3 ,__hidden: true } ,{ name: 'i' ,value: '4' ,type: 'unsigned int' ,level: 0 ,__hidden: false }*/ ], fields: [{ header: 'Name', dataIndex: 'name', width: '20%', renderer: function(d, row, j) { var grid = this; var store = this.config.store; var hasNestedRows = store.length > j + 1 && store[j + 1].level > row.level; var isCollapsed = hasNestedRows && store[j + 1].__hidden; var imgUrl = 'url(' + DS.config.img_url + 'tree-button-' + (isCollapsed ? 'open' : 'close') + '.png)'; var df = document.createDocumentFragment(); for (var i = 0; i < row.level; ++i) { var spacer = document.createElement('div'); spacer.className = '-collapse-button-spacer'; df.appendChild(spacer); } var div = document.createElement('div'); if (hasNestedRows) { div.style.backgroundImage = imgUrl; div.className = '-collapse-button'; DS.addEvent(div, 'click', function() { var lvl = row.level; var newState = !store[j + 1].__hidden; for (var i = j + 1, l = store.length; i < l; ++i) { if (store[i].level <= lvl) { break; } if (newState || store[i].level == lvl + 1) { store[i].__hidden = newState; } } grid.render(); }); } else { div.className = '-collapse-button-spacer'; } df.appendChild(div); var t = document.createTextNode(d); df.appendChild(t); // return(df); var div = document.createElement('div'); div.appendChild(df); div.className = '-debugger-cell'; div.title = div.textContent; return (div); } }, { header: 'Value', dataIndex: 'value', renderer: function(d, row, j) { var store = this.config.store; var hasNestedRows = store.length > j + 1 && store[j + 1].level > row.level; var text = [d]; if (hasNestedRows) { var lvl = row.level; text.push(' {'); var countFields = 0; for (var i = j + 1, l = store.length; i < l; ++i) { if (store[i].level <= lvl) { break; } if (store[i].level == lvl + 1) { if (countFields > 3) { text.push(', ...'); break; } if (countFields) { text.push(', '); } if (store[i].name.length) { text.push(store[i].name); text.push('='); } text.push(store[i].value); if (i + 1 < l && store[i].level + 1 == store[i + 1].level) { text.push(store[i].value.length ? ' {...}' : '{...}'); } ++countFields; } } text.push('}'); } var div = document.createElement('div'); div.appendChild(document.createTextNode(text.join(''))); div.className = '-debugger-cell'; div.title = div.textContent; return (div); // return(document.createTextNode(text.join(''))); return (document.createTextNode(text.join(''))); } }, { header: 'Type', dataIndex: 'type', width: '15%', renderer: function(d) { var div = document.createElement('div'); div.appendChild(document.createTextNode(d)); div.className = '-debugger-cell'; div.title = div.textContent; return (div); } }] } ] }); SetState('hidden'); window.editor = editor; }; // close task, finish all tasks and network queries, then run callback this.shutdown = function(callback) { DS.removeEvent(DS, 'msg/' + ARMmessage.DBG_OUTPUT, onDebugOutput); DS.removeEvent(DS, 'msg/' + ARMmessage.DBG_STOPPED, onDebugStopped); DS.removeEvent(DS, 'msg/' + ARMmessage.DBG_RUNNING, onDebugRunning); DS.removeEvent(DS, 'msg/' + ARMmessage.DBG_EXITED, onDebugExited); DS.removeEvent(DS, 'msg/' + ARMmessage.DBG_FRAME_CHANGED, onDebugFrameChanged); // DS.removeEvent(DS, 'arm/authorized', onAuthorized); DS.removeEvent(DS, 'ws/disconnected', onDisconnected); DS.removeEvent(DS, 'darkmode/deactivate', fnModeChange); DS.removeEvent(DS, 'darkmode/activate', fnModeChange); $menuSize.remove(); $menuTheme.remove(); DS.ARM.debugEnd(function() { SetState('hidden'); localsWnd.remove(); editor.saveAll(function() { editor.closeAll(); document.body.removeChild(cmStyle); rootWidget.remove(); callback(); }); }); }; // called after page show this.show = function() { topMenuTheme = DS.page.topMenu.addButton('Тема'); $menuTheme.attach(topMenuTheme, 'click'); topMenuSize = DS.page.topMenu.addButton('Шрифт'); $menuSize.attach(topMenuSize, 'click'); SetState('stopped'); /* topMenuRun = DS.page.topMenu.addButton(' Запуск'); DS.addEvent(topMenuRun, 'click', function(e){ PromptTestRun(e.shiftKey); }); topMenuRun.title = 'F5'; DS.addEvent(window, 'keyup', HandleF5); */ if (!DS.page.getTaskField('is_code_available') && !_hasFiles) { DS.alert('Редактирование кода будет доступно после того, как предыдущая задача будет сдана'); } }; // called before page hide this.hide = function() { DS.page.topMenu.removeButton(topMenuTheme); DS.page.topMenu.removeButton(topMenuSize); DS.ARM.debugEnd(function() { SetState('hidden'); }); }; this.getScripts = function() { return (['CodeMirror/lib/codemirror.js', 'CodeMirror/mode/clike/clike.js', 'CodeMirror/addon/hint/show-hint.js', 'CodeMirror/addon/hint/anyword-hint.js', 'CodeMirror/addon/edit/matchbrackets.js', 'CodeMirror/addon/edit/auto-format.js', 'CodeMirror/addon/lint/lint.js', 'CodeMirror/addon/fold/brace-fold.js', 'CodeMirror/addon/fold/foldcode.js', 'CodeMirror/addon/fold/foldgutter.js', 'CodeMirror/addon/search/match-highlighter.js', 'CodeMirror/addon/scroll/scrollpastend.js', ]); }; this.getStyles = function() { var list = ['CodeMirror/lib/codemirror.css', 'CodeMirror/addon/hint/show-hint.css', 'CodeMirror/addon/lint/lint.css', 'css/modules/task-code.css', 'CodeMirror/addon/fold/foldgutter.css', ]; for (var i = 0, l = themes.length; i < l; ++i) { if (themes[i] != 'default') { list.push('CodeMirror/theme/' + themes[i] + '.css'); } } return ({ both: list, light: [ // 'css/modules/task-light.css' 'css/modules/task-code-dark.css' ], dark: [] }); }; this.saveAll = function(cb) { editor.saveAll(cb); }; }); });