From 0fca2379790e80b7de402847477bb212ce568945 Mon Sep 17 00:00:00 2001 From: Steven Hugg Date: Sun, 15 Jan 2017 23:47:12 -0500 Subject: [PATCH] SourceFile object; moved styles to css/codemirror.css --- css/codemirror.css | 67 ++++++++++++++++++++++ index.html | 5 +- src/ui.js | 119 +++++++++++++++++++++++---------------- src/worker/workermain.js | 42 ++++++++------ 4 files changed, 166 insertions(+), 67 deletions(-) diff --git a/css/codemirror.css b/css/codemirror.css index df7de562..f49af69d 100644 --- a/css/codemirror.css +++ b/css/codemirror.css @@ -347,3 +347,70 @@ div.CodeMirror-dragcursors { /* Help users use markselection to safely style text background */ span.CodeMirror-selectedtext { background: none; } + +/****************************************************************/ +/* Based on mbonaci's Brackets mbo theme */ +/* https://github.com/mbonaci/global/blob/master/Mbo.tmTheme */ +/* Create your own: http://tmtheme-editor.herokuapp.com */ +/****************************************************************/ + +.cm-s-mbo.CodeMirror { background: #2c2c2c; color: #ffffec; } +.cm-s-mbo div.CodeMirror-selected { background: #716C62; } +.cm-s-mbo .CodeMirror-line::selection, .cm-s-mbo .CodeMirror-line > span::selection, .cm-s-mbo .CodeMirror-line > span > span::selection { background: rgba(113, 108, 98, .99); } +.cm-s-mbo .CodeMirror-line::-moz-selection, .cm-s-mbo .CodeMirror-line > span::-moz-selection, .cm-s-mbo .CodeMirror-line > span > span::-moz-selection { background: rgba(113, 108, 98, .99); } +.cm-s-mbo .CodeMirror-gutters { background: #4e4e4e; border-right: 0px; } +.cm-s-mbo .CodeMirror-guttermarker { color: white; } +.cm-s-mbo .CodeMirror-guttermarker-subtle { color: grey; } +.cm-s-mbo .CodeMirror-linenumber { color: #dadada; } +.cm-s-mbo .CodeMirror-cursor { border-left: 1px solid #ffffec; } + +.cm-s-mbo span.cm-comment { color: #95958a; } +.cm-s-mbo span.cm-atom { color: #00a8c6; } +.cm-s-mbo span.cm-number { color: #00a8c6; } + +.cm-s-mbo span.cm-property, .cm-s-mbo span.cm-attribute { color: #9ddfe9; } +.cm-s-mbo span.cm-keyword { color: #ffb928; } +.cm-s-mbo span.cm-string { color: #ffcf6c; } +.cm-s-mbo span.cm-string.cm-property { color: #ffffec; } + +.cm-s-mbo span.cm-variable { color: #ffffec; } +.cm-s-mbo span.cm-variable-2 { color: #00a8c6; } +.cm-s-mbo span.cm-variable-3 { color: #ffb928; } +.cm-s-mbo span.cm-def { color: #ffff88; } +.cm-s-mbo span.cm-bracket { color: #fffffc; font-weight: bold; } +.cm-s-mbo span.cm-tag { color: #9ddfe9; } +.cm-s-mbo span.cm-link { color: #f54b07; } +.cm-s-mbo span.cm-error { border-bottom: #636363; color: #ffffec; } +.cm-s-mbo span.cm-qualifier { color: #ffffec; } + +.cm-s-mbo .CodeMirror-activeline-background { background: #494b41; } +.cm-s-mbo .CodeMirror-matchingbracket { color: #33ff33 !important; } +.cm-s-mbo .CodeMirror-matchingtag { background: rgba(255, 255, 255, .37); } + +/****************************************************************/ + +.cm-s-cobalt.CodeMirror { background: #002240; color: white; } +.cm-s-cobalt div.CodeMirror-selected { background: #b36539; } +.cm-s-cobalt .CodeMirror-line::selection, .cm-s-cobalt .CodeMirror-line > span::selection, .cm-s-cobalt .CodeMirror-line > span > span::selection { background: rgba(179, 101, 57, .99); } +.cm-s-cobalt .CodeMirror-line::-moz-selection, .cm-s-cobalt .CodeMirror-line > span::-moz-selection, .cm-s-cobalt .CodeMirror-line > span > span::-moz-selection { background: rgba(179, 101, 57, .99); } +.cm-s-cobalt .CodeMirror-gutters { background: #002240; border-right: 1px solid #aaa; } +.cm-s-cobalt .CodeMirror-guttermarker { color: #ffee80; } +.cm-s-cobalt .CodeMirror-guttermarker-subtle { color: #d0d0d0; } +.cm-s-cobalt .CodeMirror-linenumber { color: #d0d0d0; } +.cm-s-cobalt .CodeMirror-cursor { border-left: 1px solid white; } + +.cm-s-cobalt span.cm-comment { color: #ccc; } +.cm-s-cobalt span.cm-atom { color: #845dc4; } +.cm-s-cobalt span.cm-number, .cm-s-cobalt span.cm-attribute { color: #ff80e1; } +.cm-s-cobalt span.cm-keyword { color: #ffee80; } +.cm-s-cobalt span.cm-string { color: #3ad900; } +.cm-s-cobalt span.cm-meta { color: #ff9d00; } +.cm-s-cobalt span.cm-variable-2, .cm-s-cobalt span.cm-tag { color: #9effff; } +.cm-s-cobalt span.cm-variable-3, .cm-s-cobalt span.cm-def { color: white; } +.cm-s-cobalt span.cm-bracket { color: #d8d8d8; } +.cm-s-cobalt span.cm-builtin, .cm-s-cobalt span.cm-special { color: #ff9e59; } +.cm-s-cobalt span.cm-link { color: #845dc4; } +.cm-s-cobalt span.cm-error { color: #9d1e15; } + +.cm-s-cobalt .CodeMirror-activeline-background { background: #003399; } +.cm-s-cobalt .CodeMirror-matchingbracket { outline:1px solid grey;color:white !important; } diff --git a/index.html b/index.html index b8a4f792..bf283dc9 100644 --- a/index.html +++ b/index.html @@ -257,10 +257,11 @@ canvas.pixelated { + + - - + diff --git a/src/ui.js b/src/ui.js index 3a99936e..8abbc776 100644 --- a/src/ui.js +++ b/src/ui.js @@ -61,31 +61,64 @@ var FileStore = function(storage, prefix) { } } +var SourceFile = function(lines, text) { + lines = lines || []; + this.text = text; + this.offset2line = {}; + this.line2offset = {}; + for (var info of lines) { + if (info.offset >= 0) { + this.offset2line[info.offset] = info.line; + this.line2offset[info.line] = info.offset; + } + } + this.findLineForOffset = function(PC) { + if (this.offset2line) { + for (var i=0; i<256; i++) { + var line = this.offset2line[PC]; + if (line >= 0) { + return line; + } + PC--; + } + } + return 0; + } +} + +var TOOL_TO_SOURCE_STYLE = { + 'dasm': '6502', + 'acme': '6502', + 'cc65': 'text/x-csrc', + 'ca65': '6502', + 'z80asm': 'z80', + 'sdasz80': 'z80', + 'sdcc': 'text/x-csrc', +} + var worker = new Worker("./src/worker/workermain.js"); var current_output = null; var current_preset_index = -1; // TODO: use URL var current_preset_id = null; -var offset2line = null; -var line2offset = null; +var assemblyfile = null; +var sourcefile = null; var pcvisits; var trace_pending_at_pc; var store; -var CODE = 'code1'; var editor = CodeMirror(document.getElementById('editor'), { - mode: '6502', theme: 'mbo', lineNumbers: true, + matchBrackets: true, tabSize: 8, gutters: ["CodeMirror-linenumbers", "gutter-offset", "gutter-bytes", "gutter-clock", "gutter-info"], }); var disasmview = CodeMirror(document.getElementById('disassembly'), { - mode: '6502', + mode: 'z80', theme: 'cobalt', tabSize: 8, readOnly: true, - styleActiveLine: true, - gutters: ["gutter-offset", "gutter-bytes", "gutter-clock", "gutter-info"], + styleActiveLine: true }); editor.on('changes', function(ed, changeobj) { @@ -111,10 +144,13 @@ function updatePreset(current_preset_id, text) { } } -function loadCode(text) { +function loadCode(text, fileid) { editor.setValue(text); current_output = null; setCode(text); + setLastPreset(fileid); + var tool = platform.getToolForFilename(fileid); + editor.setOption("mode", tool && TOOL_TO_SOURCE_STYLE[tool]); } function loadFile(fileid, filename, index) { @@ -122,8 +158,7 @@ function loadFile(fileid, filename, index) { current_preset_index = index; var text = store.loadFile(fileid)|| ""; if (text) { - loadCode(text); - setLastPreset(fileid); + loadCode(text, fileid); } else if (!text && index >= 0) { filename += ".a"; console.log("Loading preset", fileid, filename, index, PRESETS[index]); @@ -131,14 +166,12 @@ function loadFile(fileid, filename, index) { console.log("Fetching", filename); $.get( filename, function( text ) { console.log("GET",text.length,'bytes'); - loadCode(text); - setLastPreset(fileid); + loadCode(text, fileid); }, 'text'); } } else { $.get( "presets/"+platform_id+"/skeleton.a", function( text ) { - loadCode(text); - setLastPreset(fileid); + loadCode(text, fileid); updatePreset(fileid, text); }, 'text'); } @@ -294,6 +327,10 @@ function arrayCompare(a,b) { worker.onmessage = function(e) { // errors? var toolbar = $("#controls_top"); + sourcefile = new SourceFile(e.data.lines); + if (e.data.asmlines) { + assemblyfile = new SourceFile(e.data.asmlines, e.data.intermediate.listing); + } if (e.data.errors.length > 0) { toolbar.addClass("has-errors"); editor.clearGutter("gutter-info"); @@ -333,14 +370,10 @@ worker.onmessage = function(e) { editor.clearGutter("gutter-bytes"); editor.clearGutter("gutter-offset"); editor.clearGutter("gutter-clock"); - offset2line = {}; - line2offset = {}; for (var info of e.data.lines) { if (info.offset >= 0) { var textel = document.createTextNode(hex(info.offset,4)); editor.setGutterMarker(info.line-1, "gutter-offset", textel); - offset2line[info.offset] = info.line; - line2offset[info.line] = info.offset; } if (info.insns) { var insnstr = info.insns.length > 8 ? ("...") : info.insns; @@ -363,19 +396,6 @@ worker.onmessage = function(e) { trace_pending_at_pc = null; } -function findLineForOffset(PC) { - if (offset2line) { - for (var i=0; i<256; i++) { - var line = offset2line[PC]; - if (line >= 0) { - return line; - } - PC--; - } - } - return 0; -} - function setCurrentLine(line) { editor.setSelection({line:line,ch:0}, {line:line-1,ch:0}, {scroll:true}); } @@ -437,7 +457,7 @@ function setupBreakpoint() { platform.setupDebug(function(state) { lastDebugState = state; var PC = state.c.PC; - var line = findLineForOffset(PC); + var line = sourcefile.findLineForOffset(PC); if (line >= 0) { console.log("BREAKPOINT", hex(PC), line); setCurrentLine(line); @@ -477,7 +497,7 @@ function getCurrentLine() { function runToCursor() { setupBreakpoint(); - var line = getCurrentLine(); + var line = sourcefile.getCurrentLine(); var pc = line2offset[line]; if (pc >= 0) { console.log("Run to", line, pc.toString(16)); @@ -691,16 +711,29 @@ function showLoopTimingForCurrentLine() { } */ +function jumpToLine(ed, i) { + var t = ed.charCoords({line: i, ch: 0}, "local").top; + var middleHeight = ed.getScrollerElement().offsetHeight / 2; + ed.scrollTo(null, t - middleHeight - 5); +} + function updateDisassembly() { var div = $("#disassembly"); if (div.is(':visible')) { - disasmview.clearGutter("gutter-info"); - disasmview.clearGutter("gutter-bytes"); - disasmview.clearGutter("gutter-offset"); - disasmview.clearGutter("gutter-clock"); var state = lastDebugState || platform.saveState(); var mem = state.b; var pc = state.c.PC; + if (assemblyfile && assemblyfile.text) { + disasmview.setValue(assemblyfile.text); + if (platform.getDebugCallback()) { + var lineno = assemblyfile.findLineForOffset(pc); + if (lineno) { + disasmview.setCursor(lineno-1, 0); + jumpToLine(disasmview, lineno-1); + } + } + return; + } var gutters = []; var selline = 0; // TODO: not perfect disassembler @@ -711,7 +744,7 @@ function updateDisassembly() { var disasm = platform.disassemble(mem, start, end, pcvisits); var s = ""; for (a in disasm) { - var srclinenum = offset2line[a]; + var srclinenum = sourcefile.offset2line[a]; if (srclinenum) { var srcline = editor.getLine(srclinenum-1); if (srcline && srcline.trim().length) { @@ -728,16 +761,8 @@ function updateDisassembly() { } var text = disassemble(pc-96, pc) + disassemble(pc, pc+96); disasmview.setValue(text); - /* - for (var i=0; i