PageSourceSearch

https://bide.netlify.app/js/editor.js

js bide.netlify.app collected 2026-10-03 10:30:32 UTC 6,609 bytes, 301 lines download raw bytes

1// ============================================================
2// Browser VM IDE - Monaco Editor
3// ============================================================
4
5let editor = null;
6let currentFile = 'kernel.c';
7
8// ============================================================
9// Default files
10// ============================================================
11
12const defaultFiles = {
13  'kernel.c': `// MyOS kernel
14// This will eventually run on your virtual x86 machine.
15
16void kernel_main(void)
17{
18    // TODO: initialize the kernel
19
20    while (1) {
21        // Kernel loop
22    }
23}
24`,
25};
26
27// ============================================================
28// Initialize Monaco
29// ============================================================
30
31export function initializeEditor() {
32  return new Promise((resolve, reject) => {
33    if (typeof require === 'undefined') {
34      reject(new Error('Monaco loader was not found.'));
35
36      return;
37    }
38
39    require.config({
40      paths: {
41        vs: 'https://cdn.jsdelivr.net/npm/[email protected]/min/vs',
42      },
43    });
44
45    require(['vs/editor/editor.main'], () => {
46      try {
47        editor = monaco.editor.create(document.getElementById('editor'), {
48          value: defaultFiles[currentFile],
49
50          language: 'c',
51
52          theme: 'vs-dark',
53
54          automaticLayout: true,
55
56          minimap: {
57            enabled: true,
58          },
59
60          fontSize: 14,
61
62          fontFamily: "'Cascadia Code', 'Fira Code', Consolas, monospace",
63
64          tabSize: 4,
65
66          insertSpaces: true,
67
68          wordWrap: 'off',
69
70          smoothScrolling: true,
71
72          cursorBlinking: 'smooth',
73
74          renderWhitespace: 'selection',
75
76          scrollBeyondLastLine: false,
77
78          padding: {
79            top: 10,
80            bottom: 10,
81          },
82        });
83
84        resolve();
85      } catch (error) {
86        reject(error);
87      }
88    });
89  });
90}
91
92// ============================================================
93// Get editor
94// ============================================================
95
96export function getEditor() {
97  return editor;
98}
99
100// ============================================================
101// Get current code
102// ============================================================
103
104export function getCurrentCode() {
105  if (!editor) {
106    return '';
107  }
108
109  return editor.getValue();
110}
111
112// ============================================================
113// Set current file
114// ============================================================
115
116export function setCurrentFile(filename, contents = '') {
117  if (!editor) {
118    return;
119  }
120
121  currentFile = filename;
122
123  const language = getLanguageFromFilename(filename);
124
125  /*
126   * Monaco models let different files have
127   * different syntax highlighting.
128   */
129
130  const uri = monaco.Uri.parse(`file:///${encodeURIComponent(filename)}`);
131
132  let model = monaco.editor.getModel(uri);
133
134  if (!model) {
135    model = monaco.editor.createModel(contents, language, uri);
136  } else {
137    model.setValue(contents);
138  }
139
140  editor.setModel(model);
141
142  editor.focus();
143
144  updateTab(filename);
145}
146
147// ============================================================
148// Get current filename
149// ============================================================
150
151export function getCurrentFile() {
152  return currentFile;
153}
154
155// ============================================================
156// Change language
157// ============================================================
158
159function getLanguageFromFilename(filename) {
160  const lower = filename.toLowerCase();
161
162  if (lower.endsWith('.c')) {
163    return 'c';
164  }
165
166  if (lower.endsWith('.h')) {
167    return 'c';
168  }
169
170  if (lower.endsWith('.cpp')) {
171    return 'cpp';
172  }
173
174  if (lower.endsWith('.asm') || lower.endsWith('.s')) {
175    return 'plaintext';
176  }
177
178  if (lower.endsWith('.ld')) {
179    return 'plaintext';
180  }
181
182  if (lower.endsWith('.makefile')) {
183    return 'make';
184  }
185
186  if (filename === 'Makefile' || filename === 'makefile') {
187    return 'make';
188  }
189
190  if (lower.endsWith('.json')) {
191    return 'json';
192  }
193
194  if (lower.endsWith('.js')) {
195    return 'javascript';
196  }
197
198  if (lower.endsWith('.html')) {
199    return 'html';
200  }
201
202  if (lower.endsWith('.css')) {
203    return 'css';
204  }
205
206  if (lower.endsWith('.sh')) {
207    return 'shell';
208  }
209
210  return 'plaintext';
211}
212
213// ============================================================
214// Update editor tab
215// ============================================================
216
217function updateTab(filename) {
218  const tab = document.getElementById('currentFileTab');
219
220  if (!tab) {
221    return;
222  }
223
224  tab.textContent = filename;
225}
226
227// ============================================================
228// Set editor contents
229// ============================================================
230
231export function setEditorContents(contents) {
232  if (!editor) {
233    return;
234  }
235
236  editor.setValue(contents);
237}
238
239// ============================================================
240// Focus editor
241// ============================================================
242
243export function focusEditor() {
244  if (editor) {
245    editor.focus();
246  }
247}
248
249// ============================================================
250// Resize editor
251// ============================================================
252
253export function resizeEditor() {
254  if (editor) {
255    editor.layout();
256  }
257}
258
259// ============================================================
260// Add a file to Monaco
261// ============================================================
262
263export function createEditorModel(filename, contents = '') {
264  if (typeof monaco === 'undefined') {
265    return null;
266  }
267
268  const uri = monaco.Uri.parse(`file:///${encodeURIComponent(filename)}`);
269
270  const existing = monaco.editor.getModel(uri);
271
272  if (existing) {
273    existing.setValue(contents);
274
275    return existing;
276  }
277
278  return monaco.editor.createModel(
279    contents,
280    getLanguageFromFilename(filename),
281    uri
282  );
283}
284
285// ============================================================
286// Delete a Monaco model
287// ============================================================
288
289export function deleteEditorModel(filename) {
290  if (typeof monaco === 'undefined') {
291    return;
292  }
293
294  const uri = monaco.Uri.parse(`file:///${encodeURIComponent(filename)}`);
295
296  const model = monaco.editor.getModel(uri);
297
298  if (model) {
299    model.dispose();
300  }
301}

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.