UnoCode: the VS Code-class editor
A full code workbench that runs on the machine itself, in the shape of Visual Studio Code: an activity bar and side bar, tabbed editors with a minimap, a command palette, an integrated terminal - and extensions. Colour themes, languages, syntax grammars and snippets are the same file formats Visual Studio Code uses, so a theme or a snippet file written for VS Code works here unchanged.
The five keys worth learning
Everything in UnoCode is a command, and every command is in one searchable list. If you remember nothing else, remember the first line:
| Key | What it does |
|---|---|
| Ctrl+Shift+P | The command palette - every command, searchable, with its keyboard shortcut beside it |
| Ctrl+P | Go to a file in the open folder |
| Ctrl+B | Show or hide the side bar |
| Ctrl+` | The integrated terminal (type help) |
| Ctrl+, | Open settings.json |
theme. Each row shows the command's title, its id in grey, and its keyboard shortcut on the right. The second row is contributed by an extension - the palette does not distinguish between a built-in command and one an extension registered, because nothing else in UnoCode does either.If the palette can find it, a key can be bound to it and an extension can call it. That is the whole design: nothing is wired to a key directly, so anything can be rebound.
The editor
Open a file from the Explorer, with Ctrl+P, or by typing
open SDK\SAMPLE.C in the terminal. Each file gets a tab; the breadcrumb bar above the text
shows where it came from.
The editing keys are the ones you already know - arrows and Home/End/PgUp/PgDn to move, Shift+movement to select, Ctrl+X/C/V/A, Ctrl+Z to undo - plus the ones that make an editor worth using:
Multiple cursors
Ctrl+Alt+Down adds a cursor on the next line, Ctrl+D adds one at the next match of what is selected, and everything you type then happens at all of them at once. Esc collapses back to one.
Find and replace
Ctrl+F finds, Ctrl+H replaces, and the three small toggles switch on case sensitivity, whole-word matching and regular expressions. The match count is live.
Whole lines
Alt+Up/Down moves the current line, Shift+Alt+Down copies it down, Ctrl+Shift+K deletes it, and Ctrl+/ comments or uncomments the selection in the language's own comment syntax.
It closes what you open
Type ( and you get () with the cursor between them; type the closing one and the cursor steps over it rather than doubling it. Enter keeps the indentation, and opens a block out onto its own lines.
0 of 11) and the case / whole-word / regular-expression toggles. Every match in the file is highlighted as you type, not just the next one.Suggestions
Ctrl+Space asks for suggestions, and they appear as you type. They come from four places at once and are ranked together: the language's keywords, every distinct word already in the file (which is what makes completion useful in a language nothing knows about), snippets, and anything an extension offers.
S are snippets contributed by an installed extension - unoapp expands to a skeleton app - and the rows marked k are the language's own keywords. Accept with Tab or Enter.The integrated terminal
Ctrl+` opens a panel at the bottom with Problems,
Output and Terminal tabs. The terminal is UnoCode's own small shell -
UnoDOS has no shell process for it to host - so help lists exactly what it has, and a word it
does not know is an error rather than a silent nothing.
help and ext. It can list and change directories, read and copy files, search the folder, open and run files, read and write settings, switch the theme, run any UnoCode command by id, and evaluate a JavaScript expression in the same interpreter the extensions run in.Two of its commands are worth knowing about:
run fileruns a.UNOapp, or wraps a.PYfile for the Python runtime and runs that - the same thing F5 does to the file you are editing.js expressionevaluates JavaScript in the extension host itself, which is how you find out what an extension is actually doing.
Colour themes
Six themes are built in - Dark+, Light+, Monokai, Solarized Dark, High Contrast and UnoDOS Blue - and more arrive as extensions. Ctrl+K then Ctrl+T, or Preferences: Color Theme in the palette, switches between them; your choice is saved.
A theme file is a Visual Studio Code theme file, unchanged:
{
"name": "Nord",
"type": "dark",
"colors": {
"editor.background": "#2E3440",
"editor.foreground": "#D8DEE9",
"activityBar.background": "#3B4252",
"statusBar.background": "#3B4252"
},
"tokenColors": [
{ "scope": "comment",
"settings": { "foreground": "#616E88", "fontStyle": "italic" } },
{ "scope": ["keyword", "storage"],
"settings": { "foreground": "#81A1C1" } }
]
}
Two rules make writing one by hand reasonable. A colour key UnoCode does not know is ignored, so a theme written for a newer editor still loads; and a key you leave out is worked out from the ones you set, so a theme with three colours in it still renders a complete, coherent workbench.
Extensions
An extension is a folder. Copy it onto the disk under EXT and UnoCode finds it at startup -
on any drive, so an extension on a USB stick needs no installing.
Three of the four kinds of extension need no programming whatever - they are JSON files that describe something:
A theme
One colour-theme file and a manifest naming it. No code runs, ever.
A language
An id, the file extensions it claims and its comment syntax - and UnoCode knows a new language.
A grammar
A TextMate-style file of patterns that colours that language. Same shape as VS Code's.
Snippets
A map of short prefixes to the text they expand to, offered in the suggestion list.
The manifest is package.json, with VS Code's keys:
{
"name": "nord",
"displayName": "Nord Theme",
"description": "An arctic, north-bluish colour theme.",
"version": "1.0.0",
"publisher": "you",
// no "main", so no code ever runs for this extension
"contributes": {
"themes": [
{ "label": "Nord", "uiTheme": "vs-dark", "path": "THEMES/NORD.JSN" }
]
}
}
The fourth kind runs JavaScript. An extension with a main gets a real
programming interface - commands, messages, quick picks, the active editor and its text, settings, files,
and events when a document is opened, changed or saved:
var vscode = require('vscode');
function activate(context) {
vscode.commands.registerCommand('hello.sayHello', function () {
var ed = vscode.window.activeTextEditor;
vscode.window.showInformationMessage(
'Hello from an extension - ' + (ed ? ed.document.fileName : 'no editor'));
});
// completions, offered only in C files
vscode.languages.registerCompletionItemProvider('c', {
provideCompletionItems: function (document, position) {
return [{ label: 'uno_fs_read', detail: 'UnoDOS',
insertText: 'uno_fs_read(vol, name, buf, max)' }];
}
});
vscode.workspace.onDidSaveTextDocument(function (doc) {
console.log('saved: ' + doc.fileName);
});
}
exports.activate = activate;
One thing about the interface is deliberately different from Visual Studio Code, and it is stated
rather than hidden: require() resolves 'vscode' and nothing else, because there
is no package manager to resolve anything else against.
async/await work. That was not true at first - the interpreter had no microtask queue, so the calls returned an object with a .then() on it and the manual said so. It has one now, and await genuinely suspends, so an extension written the way a VS Code extension is written behaves the way it expects.Language servers
UnoCode contains a Language Server Protocol client: a server per language, spoken to in JSON-RPC over pipes, feeding diagnostics, completions, hover, go-to-definition, find-references, rename and format back into the editor. It is configured from settings, one command line per language, and an empty command switches one off.
Two decisions in the client are worth knowing if you are reading the source. It syncs the whole document after a pause in typing rather than sending incremental edits, because incremental sync means client and server each keep a copy and one mis-ranged edit makes them diverge silently. And a server that dies is restarted with a widening delay and has its documents re-opened on the replacement, because a language server exiting is ordinary rather than exceptional.
Settings and keyboard shortcuts
Both are files, both are yours to edit, and both are the formats Visual Studio Code uses - including its habit of allowing comments and trailing commas in them.
| File | What it is |
|---|---|
UNOCODE\SETTINGS.JSN | Settings, as a flat map of dotted keys. Ctrl+, opens it. |
UNOCODE\KEYBIND.JSN | Keyboard shortcuts. Preferences: Open Keyboard Shortcuts (JSON) writes the whole shipped keymap into it the first time, so changing one binding does not start with guessing what a key is called. |
// UnoCode settings. Comments and trailing commas are allowed.
{
"editor.fontSize": 15,
"editor.tabSize": 4,
"editor.insertSpaces": true,
"editor.minimap.enabled": true,
"editor.renderWhitespace": "boundary",
"workbench.colorTheme": "Nord",
"files.trimTrailingWhitespace": true,
}
A keybinding is { "key", "command", "when" }. when is a real condition -
editorTextFocus, editorHasSelection, terminalFocus and the rest,
combined with !, && and || - so the same key can do
different things in different places. A command written with a leading - removes a shipped
binding. Yours win over an extension's, which win over the defaults.
SETTINGS.JSN is settings.json, key for key.What it does not do
Honestly, so you are not looking for them:
- No word wrap. Long lines scroll sideways.
- No language server runs on this machine, so there is no hover documentation, no go-to-definition and no rename-across-a-project here. UnoCode has a language-server client - see Language servers below - but a server is a separate program, and pc64 has no way to start one. Completions come from the language's keywords, the words already in the file and any snippets, which is what you get.
- Source Control tracks your unsaved edits against the file as it was opened, and marks changed lines in the gutter. There is no repository on this machine and it says so rather than pretending.
- Function keys depend on the keyboard. PS/2 keyboards deliver them; USB keyboards do not, in this build. Every default shortcut is a Ctrl chord for that reason, and nothing needs an F-key.
For extension authors
The complete file formats - the manifest keys, the theme colour keys, the grammar model and its one
documented difference from TextMate, the settings table and the whole JavaScript interface - are in
pc64/unocode/UNOCODE.md in the source tree, beside the three sample extensions the disk
ships: a theme, a language with a grammar and snippets, and one with code in it.