Skip to content

Commit e8ffd4e

Browse files
committed
rewire code to run with the new code editors, update user interface
1 parent 31c718c commit e8ffd4e

File tree

7 files changed

+150
-299
lines changed

7 files changed

+150
-299
lines changed

wasm/notebook/src/editor.js

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ CodeMirror.defineMode('notebook', function (config, _parserConfig) {
99
py: python,
1010
md: markdown,
1111
math: latex,
12-
'math-inline': latex,
1312
};
1413
return {
1514
startState() {
@@ -76,4 +75,17 @@ function selectBuffer(editor, buffers, name) {
7675
buffersList.appendChild(li);
7776
}
7877

79-
export { selectBuffer , openBuffer }
78+
function newBuf(buffers, buffersDropDown, buffersList, primaryEditor) {
79+
let name = prompt("Name your tab", "*scratch*");
80+
if (name == null) return;
81+
if (buffers.hasOwnProperty(name)) {
82+
alert("There's already a buffer by that name.");
83+
return;
84+
}
85+
openBuffer(buffers, name, "", "python", buffersDropDown, buffersList);
86+
selectBuffer(primaryEditor, buffers, name);
87+
let sel = buffersDropDown;
88+
sel.value = name;
89+
}
90+
91+
export { selectBuffer , openBuffer , newBuf }

wasm/notebook/src/index.ejs

Lines changed: 20 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -11,33 +11,36 @@
1111

1212
<body>
1313

14+
<div class="d-flex">
1415
<div class="header item-center">RustPython 🐍 😱 🤘</div>
16+
<div>
17+
<a class="mr-px-5" href="https://rustpython.github.io/2020/10/21/rustpython-notebook-details"> how to </a>
18+
<a href="https://github.com/RustPython/"> github</a>
19+
</div>
20+
</div>
21+
22+
1523

1624
<!-- navigation bar -->
1725
<div class="nav-bar">
1826
<div class="nav-bar-links d-flex">
27+
<a href="#" id="run-btn" class="bg-orange text-white mr-px-5">run &#9658; </a>
1928
<ul class="list-inline" id="buffers-list"></ul>
20-
<a href="#" id="new-tab" class="bg-light mr-px-5 text-black">+ new tab</a>
21-
<a href="#" id="run-btn" class="bg-orange text-white">run &#9658; </a>
22-
</div>
23-
24-
<div class="item-center">
25-
<a href="#">coding mode</a>
26-
<select id="buffers-selection"></select>
27-
</div>
28-
29-
<div class="text-right">
30-
<a href="https://github.com/RustPython/"> github</a>
29+
<a href="#" id="new-tab" class="bg-light mr-px-5 text-black">new tab</a>
30+
<a href="#" id="split-view" class="bg-light mr-px-5 text-black">split view</a>
31+
<a href="#" id="reader-mode" class="bg-light mr-px-5 text-black">reader mode</a>
3132
</div>
3233
</div>
3334

3435
<!-- code editor and output display -->
3536
<!-- split view -->
3637
<div class="split-view full-height">
37-
<div id="primary-editor" class="border-right"></div>
38-
<div id="secondary-editor" class="d-none"></div>
38+
<div id="primary-editor"></div>
39+
<div id="secondary-editor" class="d-none">
40+
<select class="item-right" id="buffers-selection"></select>
41+
</div>
3942

40-
<div id="rp-notebook">loading python in your browser...</div>
43+
<div class="border-left" id="rp-notebook">loading python in your browser...</div>
4144
</div>
4245

4346
<!-- popup forms -->
@@ -53,19 +56,9 @@
5356
</div>
5457

5558
<!-- errors and keyboard shortcuts -->
56-
<div class="split-view">
57-
<div>
58-
<div class="header">Error(s):</div>
59-
<div id="error"></div>
60-
</div>
61-
<div class="gray">
62-
<div class="header">Keyboard Shortcuts:</div>
63-
<div>
64-
<div>Run code: 'Ctrl-Enter' or 'Cmd-Enter'</div>
65-
<div>Decrease Indent: 'Shift-Tab' </div>
66-
<div>Toggle comment: 'Ctrl-/' or 'Cmd-/'</div>
67-
</div>
68-
</div>
59+
<div>
60+
<div class="header">Error(s):</div>
61+
<div id="error"></div>
6962
</div>
7063
</body>
7164

wasm/notebook/src/index.js

Lines changed: 92 additions & 94 deletions
Original file line numberDiff line numberDiff line change
@@ -10,19 +10,17 @@ import 'codemirror/mode/markdown/markdown';
1010
import 'codemirror/mode/stex/stex';
1111
import 'codemirror/addon/comment/comment';
1212
import 'codemirror/lib/codemirror.css';
13-
import 'codemirror/theme/base16-dark.css';
13+
import 'codemirror/theme/ayu-mirage.css';
1414

1515
// copied from the iodide project
1616
// https://github.com/iodide-project/iodide/blob/master/src/editor/iomd-tools/iomd-parser.js
1717
import { iomdParser } from './parse';
18-
import { runPython , runJS, renderMarkdown , renderMath } from './process';
19-
import { genericFetch , injectJS } from './utils';
20-
import { selectBuffer , openBuffer } from './editor'
18+
import { runPython, runJS, addCSS, renderMarkdown, renderMath } from './process';
19+
import { injectJS } from './utils';
20+
import { selectBuffer, openBuffer , newBuf } from './editor';
21+
2122
let rp;
2223

23-
const error = document.getElementById('error');
24-
const notebook = document.getElementById('rp-notebook');
25-
let buffers = {};
2624
// A dependency graph that contains any wasm must be imported asynchronously.
2725
import('rustpython')
2826
.then((rustpy) => {
@@ -36,6 +34,47 @@ import('rustpython')
3634
document.getElementById('error').textContent = e;
3735
});
3836

37+
const error = document.getElementById('error');
38+
const notebook = document.getElementById('rp-notebook');
39+
40+
// Code Editors
41+
// There is a primary and secondary code editor
42+
// By default only the primary is visible.
43+
// When clicking coding mode, secondary editor is visible
44+
// Each editor can display multiple documents and doc types.
45+
// the default created ones are main /python/js/css
46+
// user has the option to add their own document. By default it is python
47+
// adapted/inspired from https://codemirror.net/demo/buffers.html
48+
49+
const primaryEditor = CodeMirror(document.getElementById("primary-editor"), { theme: "ayu-mirage", lineNumbers: true , lineWrapping: true , indentUnit: 4 });
50+
const secondaryEditor = CodeMirror(document.getElementById("secondary-editor"), { lineNumbers: true , lineWrapping: true , indentUnit: 4 });
51+
52+
const buffers = {};
53+
const buffersList = document.getElementById("buffers-list");
54+
const buffersDropDown = document.getElementById("buffers-selection");
55+
56+
openBuffer(buffers, "main", "# Write python code or use code blocks that start with %%py, %%js, %%md %%math.", "notebook", buffersDropDown, buffersList);
57+
openBuffer(buffers, "python", "# Python code goes here", "python", buffersDropDown, buffersList);
58+
openBuffer(buffers, "js", "// Javascript code go here", "javascript", buffersDropDown, buffersList);
59+
openBuffer(buffers, "css", "/* CSS code goes here. */", "css", buffersDropDown, buffersList);
60+
61+
selectBuffer(primaryEditor, buffers, "main");
62+
selectBuffer(secondaryEditor, buffers, "main");
63+
64+
CodeMirror.on(buffersList, "click", function (e) {
65+
selectBuffer(primaryEditor, buffers, e.target.dataset.language);
66+
});
67+
68+
CodeMirror.on(buffersDropDown, "change", function () {
69+
selectBuffer(secondaryEditor, buffers, buffersDropDown.options[buffersDropDown.selectedIndex].value);
70+
});
71+
72+
document.getElementById('new-tab').addEventListener('click', function () {
73+
newBuf(buffers, buffersDropDown, buffersList, primaryEditor);
74+
});
75+
76+
77+
3978
function onReady() {
4079
/* By default the notebook has the keyword "loading"
4180
once python and doc is ready:
@@ -48,31 +87,45 @@ function onReady() {
4887
notebook.innerHTML = '';
4988
}
5089

90+
// on click, parse the code
91+
document
92+
.getElementById('run-btn')
93+
.addEventListener('click', parseCodeFromEditor);
94+
5195
// Parses what is the code editor
5296
// either runs python or renders math or markdown
5397
function parseCodeFromEditor() {
54-
55-
let test = primaryEditor.getValue();
56-
// Clean the console and errors
98+
99+
// Clean the console and errors
57100
notebook.innerHTML = '';
58101
error.textContent = '';
59102

60-
// Read javascript code from the jsEditor
61-
// Injsect JS into DOM, so that functions can be called from python
62-
// let js_code = jsEditor.getValue();
63-
// injectJS(js_code);
103+
let css_code = buffers["css"].getValue();
104+
addCSS(css_code);
105+
console.log(css_code);
64106

65-
// gets the code from code editor
66-
// let python_code = pyEditor.getValue();
107+
// Read javascript code from the jsEditor
108+
// Inject JS into DOM, so that functions can be called from python
109+
// if there is an edit
110+
// detect and inject js code
111+
let js_code = buffers["js"].getValue();
112+
injectJS(js_code);
113+
console.log(js_code);
114+
115+
// add loop and if conditions
116+
let python_code = buffers["python"].getValue();
117+
runPython(python_code, notebook, error);
118+
119+
// gets code from main editor
120+
let main_code = buffers["main"].getValue();
67121
/*
68122
Split code into chunks.
69123
Uses %%keyword or %% keyword as separator
70124
Returned object has:
71125
- chunkContent, chunkType, chunkId,
72126
- evalFlags, startLine, endLine
73127
*/
74-
let python_code = "print('hello world')";
75-
let parsed_code = iomdParser(python_code);
128+
let parsed_code = iomdParser(main_code);
76129
parsed_code.forEach(async (chunk) => {
77130
// For each type of chunk, do somthing
78131
// so far have py for python, md for markdown and math for math ;p
@@ -92,98 +145,43 @@ function parseCodeFromEditor() {
92145
notebook.innerHTML += renderMarkdown(content);
93146
break;
94147
case 'math':
95-
notebook.innerHTML += renderMath(content, true);
148+
notebook.innerHTML += renderMath(content);
96149
break;
97150
default:
98151
// do nothing when we see an unknown chunk for now
99152
}
100153
});
101154
}
102155

103-
// on click, parse the code
104-
document
105-
.getElementById('run-btn')
106-
.addEventListener('click', parseCodeFromEditor);
156+
107157

108158
// import button
109159
// show a url input + fetch button
110160
// takes a url where there is raw code
111-
document.getElementById('popup-import').addEventListener('click', async function () {
112-
const url = document.getElementById('popup-url').value;
113-
const type = document.getElementById('popup').dataset.type;
114-
const code = await genericFetch(url , type);
115-
switch (type) {
116-
case '':
117-
case 'py':
118-
pyEditor.setValue(code);
119-
break;
120-
case 'js':
121-
jsEditor.setValue(code);
122-
break;
123-
default:
124-
//do nothing
125-
}
126-
127-
});
161+
// document.getElementById('popup-import').addEventListener('click', async function () {
162+
// const url = document.getElementById('popup-url').value;
163+
// const type = document.getElementById('popup').dataset.type;
164+
// const code = await genericFetch(url, type);
165+
// switch (type) {
166+
// case '':
167+
// case 'py':
168+
// pyEditor.setValue(code);
169+
// break;
170+
// case 'js':
171+
// jsEditor.setValue(code);
172+
// break;
173+
// default:
174+
// //do nothing
175+
// }
128176

129-
// document.getElementById('import-js-library').addEventListener('click' , function() {
130-
// updatePopup('javascript', 'URL/CDN of the Javascript library');
131-
// });
177+
// });
132178

133179
// document.getElementById('import-code').addEventListener('click' , function() {
134180
// updatePopup('python', 'URL (raw text format)');
135181
// });
136182

137-
document.getElementById('new-tab').addEventListener('click' , function() {
138-
newBuf();
139-
});
140-
141-
// Tabbed Navigation
142-
document.addEventListener('click', ({ target: { dataset: { id = '' } } }) => {
143-
if (id.length > 0) {
144-
document.querySelectorAll('.tab').forEach(t => t.classList.add('d-none'));
145-
document.querySelector(`#${id}`).classList.remove('d-none');
146-
}
147-
});
148-
149-
// function updatePopup(type, message) {
150-
// document.getElementById('popup').dataset.type = type ;
151-
// document.getElementById('popup-header').textContent = message;
152-
// }
153-
154-
let buffersList = document.getElementById("buffers-list");
155183

156-
CodeMirror.on(buffersList, "click", function(e) {
157-
selectBuffer(primaryEditor, buffers, e.target.dataset.language);
158-
});
159-
160-
let buffersDropDown = document.getElementById("buffers-selection");
161-
CodeMirror.on(buffersDropDown, "change", function() {
162-
selectBuffer(secondaryEditor, buffers, buffersDropDown.options[buffersDropDown.selectedIndex].value);
163-
});
164184

165-
166-
function newBuf() {
167-
let name = prompt("Name for the buffer", "*scratch*");
168-
if (name == null) return;
169-
if (buffers.hasOwnProperty(name)) {
170-
alert("There's already a buffer by that name.");
171-
return;
172-
}
173-
openBuffer(buffers, name, "", "javascript" , buffersDropDown , buffersList);
174-
selectBuffer( primaryEditor , buffers, name);
175-
let sel = buffersDropDown;
176-
sel.value = name;
177-
}
178-
179-
180-
openBuffer(buffers, "main", "", "notebook" , buffersDropDown , buffersList);
181-
openBuffer(buffers, "python", "# Python code goes here", "python" , buffersDropDown , buffersList);
182-
openBuffer(buffers, "js", "// Javascript goes here", "javascript" , buffersDropDown , buffersList);
183-
openBuffer(buffers, "css", "/* CSS goes here */", "css" , buffersDropDown , buffersList);
184-
185-
186-
var primaryEditor = CodeMirror(document.getElementById("primary-editor"), {lineNumbers: true});
187-
selectBuffer(primaryEditor, buffers, "main");
188-
var secondaryEditor = CodeMirror(document.getElementById("secondary-editor"), {lineNumbers: true});
189-
selectBuffer(secondaryEditor, buffers, "main");
185+
document.getElementById('split-view').addEventListener('click', function() {
186+
document.getElementById('secondary-editor').classList.remove('d-none');
187+
});

0 commit comments

Comments
 (0)