├── uiua-logo.png ├── .gitignore ├── .vscodeignore ├── .vscode ├── extensions.json ├── launch.json ├── tasks.json └── settings.json ├── tsconfig.json ├── README.md ├── .eslintrc.json ├── snippets └── uiua.json ├── language-configuration.json ├── license ├── src └── extension.ts ├── package.json └── syntaxes └── uiua.tmLanguage.json /uiua-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uiua-lang/uiua-vscode/HEAD/uiua-logo.png -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | out 2 | dist 3 | node_modules 4 | .vscode-test/ 5 | *.vsix 6 | *.exe 7 | uiua -------------------------------------------------------------------------------- /.vscodeignore: -------------------------------------------------------------------------------- 1 | .vscode/** 2 | .vscode-test/** 3 | src/** 4 | .gitignore 5 | .yarnrc 6 | vsc-extension-quickstart.md 7 | **/tsconfig.json 8 | **/.eslintrc.json 9 | **/*.map 10 | **/*.ts 11 | uiua.exe -------------------------------------------------------------------------------- /.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | // See http://go.microsoft.com/fwlink/?LinkId=827846 3 | // for the documentation about the extensions.json format 4 | "recommendations": [ 5 | "dbaeumer.vscode-eslint" 6 | ] 7 | } 8 | -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "0.2.0", 3 | "configurations": [ 4 | { 5 | "name": "Run Extension", 6 | "type": "extensionHost", 7 | "request": "launch", 8 | "args": [ 9 | "--extensionDevelopmentPath=${workspaceFolder}" 10 | ], 11 | "outFiles": [ 12 | "${workspaceFolder}/out/**/*.js" 13 | ], 14 | "preLaunchTask": "${defaultBuildTask}" 15 | } 16 | ] 17 | } -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "commonjs", 4 | "target": "ES2020", 5 | "outDir": "out", 6 | "lib": [ 7 | "ES2020" 8 | ], 9 | "moduleResolution": "Node", 10 | "sourceMap": true, 11 | "rootDir": "src", 12 | "strict": true, 13 | "noImplicitReturns": true, 14 | "noFallthroughCasesInSwitch": true, 15 | "noUnusedParameters": true, 16 | "types": [ 17 | "node" 18 | ], 19 | "skipLibCheck": true 20 | } 21 | } -------------------------------------------------------------------------------- /.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | // See https://go.microsoft.com/fwlink/?LinkId=733558 2 | // for the documentation about the tasks.json format 3 | { 4 | "version": "2.0.0", 5 | "tasks": [ 6 | { 7 | "type": "npm", 8 | "script": "watch", 9 | "problemMatcher": "$tsc-watch", 10 | "isBackground": true, 11 | "presentation": { 12 | "reveal": "never" 13 | }, 14 | "group": { 15 | "kind": "build", 16 | "isDefault": true 17 | } 18 | } 19 | ] 20 | } 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | VSCode language extension for [Uiua](https://uiua.org) ([GitHub](https://github.com/uiua-lang/uiua)). 2 | 3 | Requires Uiua to be [installed](https://uiua.org/install). 4 | 5 | Features 6 | - Syntax highlighting 7 | - Semantic highlighting 8 | - Formatting 9 | - On-type formatting 10 | - Snippets 11 | - Glyph and binding hover 12 | - Glyph and binding completion 13 | - Binding rename 14 | - Goto definition 15 | - Find references 16 | - Signature inlay hints 17 | - Macro expansion -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | // Place your settings in this file to overwrite default and user settings. 2 | { 3 | "files.exclude": { 4 | "out": false // set this to true to hide the "out" folder with the compiled JS files 5 | }, 6 | "search.exclude": { 7 | "out": true // set this to false to include "out" folder in search results 8 | }, 9 | // Turn off tsc task auto detection since we have the necessary tasks as npm scripts 10 | "typescript.tsc.autoDetect": "off" 11 | } -------------------------------------------------------------------------------- /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "root": true, 3 | "parser": "@typescript-eslint/parser", 4 | "parserOptions": { 5 | "ecmaVersion": 6, 6 | "sourceType": "module" 7 | }, 8 | "plugins": [ 9 | "@typescript-eslint" 10 | ], 11 | "rules": { 12 | "@typescript-eslint/naming-convention": "warn", 13 | "@typescript-eslint/semi": "warn", 14 | "curly": "warn", 15 | "eqeqeq": "warn", 16 | "no-throw-literal": "warn", 17 | "semi": "off" 18 | }, 19 | "ignorePatterns": [ 20 | "out", 21 | "dist", 22 | "**/*.d.ts" 23 | ] 24 | } 25 | -------------------------------------------------------------------------------- /snippets/uiua.json: -------------------------------------------------------------------------------- 1 | { 2 | "Experimental": { 3 | "prefix": "experimental", 4 | "body": [ 5 | "# Experimental!" 6 | ], 7 | "description": "Add an experimental semantic comment" 8 | }, 9 | "NoInline": { 10 | "prefix": "noinline", 11 | "body": [ 12 | "# No Inline!" 13 | ], 14 | "description": "Add a no inline semantic comment" 15 | }, 16 | "TrackCaller": { 17 | "prefix": "trackcaller", 18 | "body": [ 19 | "# Track Caller!" 20 | ], 21 | "description": "Add a track caller semantic comment" 22 | } 23 | } -------------------------------------------------------------------------------- /language-configuration.json: -------------------------------------------------------------------------------- 1 | { 2 | "comments": { 3 | "lineComment": "#" 4 | }, 5 | "brackets": [ 6 | [ 7 | "(", 8 | ")" 9 | ], 10 | [ 11 | "[", 12 | "]" 13 | ], 14 | [ 15 | "{", 16 | "}" 17 | ] 18 | ], 19 | "autoClosingPairs": [ 20 | [ 21 | "(", 22 | ")" 23 | ], 24 | [ 25 | "[", 26 | "]" 27 | ], 28 | [ 29 | "{", 30 | "}" 31 | ], 32 | [ 33 | "\"", 34 | "\"" 35 | ], 36 | ], 37 | "surroundingPairs": [ 38 | [ 39 | "(", 40 | ")" 41 | ], 42 | [ 43 | "[", 44 | "]" 45 | ], 46 | [ 47 | "{", 48 | "}" 49 | ], 50 | [ 51 | "\"", 52 | "\"" 53 | ], 54 | ], 55 | } -------------------------------------------------------------------------------- /license: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Kaikalii 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /src/extension.ts: -------------------------------------------------------------------------------- 1 | import { execSync } from 'child_process'; 2 | import * as vscode from 'vscode'; 3 | import { LanguageClientOptions } from 'vscode-languageclient'; 4 | import { LanguageClient, ServerOptions } from 'vscode-languageclient/node'; 5 | import { chmodSync, copyFileSync } from 'fs'; 6 | 7 | export function activate(context: vscode.ExtensionContext) { 8 | // Determine Uiua interpreter path 9 | var path = vscode.workspace.getConfiguration('uiua').get('executablePath'); 10 | path = path || (process.platform === 'win32' 11 | ? execSync('where uiua') 12 | : execSync('which uiua')).toString().trim(); 13 | // Copy the interpreter to the extension's folder 14 | var extensionPath = context.extensionPath; 15 | var runPath = extensionPath + '/uiua' + (process.platform === 'win32' ? '.exe' : ''); 16 | try { 17 | copyFileSync(path, runPath); 18 | if (process.platform !== 'win32') { 19 | chmodSync(runPath, 0o755); 20 | } 21 | } catch (e) { 22 | console.error('Failed to copy Uiua interpreter to extension folder: ', e); 23 | runPath = path; 24 | } 25 | 26 | // Start the language server 27 | let serverOptions: ServerOptions = { 28 | command: runPath, 29 | args: ['lsp'], 30 | options: {} 31 | }; 32 | let clientOptions: LanguageClientOptions = { 33 | documentSelector: [{ language: 'uiua' }] 34 | }; 35 | 36 | let client = new LanguageClient( 37 | 'Uiua', 38 | 'Uiua Language Server', 39 | serverOptions, 40 | clientOptions, 41 | true, 42 | ); 43 | client.start(); 44 | 45 | context.subscriptions.push( 46 | vscode.commands.registerCommand('uiua.run', async () => { 47 | const document = vscode.window.activeTextEditor?.document; 48 | document && await document.save().then(() => { 49 | const relativeFile = document.uri.fsPath; 50 | 51 | let process = new vscode.ProcessExecution(runPath, ["run", relativeFile]); 52 | 53 | const task = new vscode.Task({ type: "process" }, vscode.TaskScope.Workspace, "Uiua", "Uiua", process); 54 | // https://github.com/microsoft/vscode/issues/157756 55 | task.definition.command = "Uiua"; 56 | 57 | vscode.tasks.executeTask(task); 58 | }); 59 | }) 60 | ); 61 | } 62 | 63 | export function deactivate() { } 64 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "uiua-vscode", 3 | "displayName": "Uiua", 4 | "description": "Uiua language support", 5 | "repository": { 6 | "type": "git", 7 | "url": "https://github.com/uiua-lang/uiua-vscode" 8 | }, 9 | "version": "0.0.67", 10 | "license": "MIT", 11 | "publisher": "uiua-lang", 12 | "readme": "README.md", 13 | "engines": { 14 | "vscode": ">=1.0.0" 15 | }, 16 | "categories": [ 17 | "Programming Languages", 18 | "Snippets" 19 | ], 20 | "main": "./out/extension.js", 21 | "icon": "uiua-logo.png", 22 | "activationEvents": [], 23 | "contributes": { 24 | "languages": [ 25 | { 26 | "id": "uiua", 27 | "aliases": [ 28 | "Uiua", 29 | "uiua" 30 | ], 31 | "extensions": [ 32 | ".ua" 33 | ], 34 | "configuration": "./language-configuration.json" 35 | } 36 | ], 37 | "configurationDefaults": { 38 | "[uiua]": { 39 | "editor.semanticHighlighting.enabled": true, 40 | "editor.inlayHints.enabled": "on", 41 | "editor.fontFamily": "Uiua386Color, Uiua386, DejaVu Sans Mono, monospace", 42 | "editor.suggestFontSize": 16, 43 | "editor.unicodeHighlight.ambiguousCharacters": false, 44 | "editor.wordSeparators": "~@#$%^*()-=+[{]}\\|;:'\",.<>/?◠⌵+⌝’⍤∠˜◡⋯∩□⊓⊸⍩⌈⊛ℂ◇⊟◴∂♭⊙÷⍢↘.∵=η⍖⬚⌕⊢¤:⌊∧⊃⋅≥>⊕∘⊗∞∫⍚⊂▽⊣⧻≤<ₙ⦷≍↥∊↧◿ׯ¬≠⌅⤚⟜∨⤸,⋕⊜π⊡◌ⁿ⚂⇡𝄐/⍥☇↯⇌⍏↻⁅≡\\⊏˙△±∿⍆√?⧈-⨬⊞↙τ⸮⍉⍣⧅°⍜◰⊚◫⤙" 45 | }, 46 | "editor.semanticTokenColorCustomizations": { 47 | "rules": { 48 | "uiua_number": "#ea5", 49 | "noadic_function": "#ed5e6a", 50 | "monadic_function": "#95d16a", 51 | "dyadic_function": "#54b0fc", 52 | "triadic_function": "#8078f1", 53 | "tetradic_function": "#f576d8", 54 | "monadic_modifier": "#f0c36f", 55 | "dyadic_modifier": "#cc6be9", 56 | "triadic_modifier": "#40f0a0", 57 | "uiua_module": "#d7be8c" 58 | }, 59 | "[The Best Theme]": { 60 | "rules": { 61 | "uiua_string": "#20f9fc" 62 | } 63 | } 64 | } 65 | }, 66 | "configuration": { 67 | "type": "object", 68 | "title": "Uiua", 69 | "properties": { 70 | "uiua.executablePath": { 71 | "type": "string", 72 | "default": "", 73 | "description": "Path to the Uiua executable used by the Uiua extension. When empty, the extension will try to find the Uiua executable in your PATH environment variable.", 74 | "editPresentation": "singlelineText" 75 | }, 76 | "uiua.inlayHints.bindingSignatureHints": { 77 | "type": "boolean", 78 | "default": true, 79 | "description": "Show signature hints for bindings." 80 | }, 81 | "uiua.inlayHints.inlineSignatureHints": { 82 | "type": "boolean", 83 | "default": true, 84 | "description": "Show signature hints for inline functions." 85 | }, 86 | "uiua.inlayHints.inlineHintMinLength": { 87 | "type": "number", 88 | "default": 4, 89 | "description": "The minimum length of a function to show signature hints." 90 | }, 91 | "uiua.inlayHints.values": { 92 | "type": "boolean", 93 | "default": true, 94 | "description": "Show value hints on top-level expressions." 95 | }, 96 | "uiua.format.onTypeFormatting": { 97 | "type": "boolean", 98 | "default": true, 99 | "description": "Enable on-type formatting." 100 | }, 101 | "uiua.semanticHighlighting.customTokenTypes": { 102 | "type": "boolean", 103 | "default": true, 104 | "description": "Enable Uiua-specific token types for semantic highlighting which override default theme colors." 105 | } 106 | } 107 | }, 108 | "grammars": [ 109 | { 110 | "language": "uiua", 111 | "scopeName": "source.uiua", 112 | "path": "./syntaxes/uiua.tmLanguage.json" 113 | } 114 | ], 115 | "snippets": [ 116 | { 117 | "language": "uiua", 118 | "path": "./snippets/uiua.json" 119 | } 120 | ], 121 | "commands": [ 122 | { 123 | "title": "Run Uiua", 124 | "command": "uiua.run" 125 | } 126 | ], 127 | "keybindings": [ 128 | { 129 | "command": "uiua.run", 130 | "key": "F5", 131 | "when": "editorLangId == uiua" 132 | } 133 | ] 134 | }, 135 | "scripts": { 136 | "vscode:prepublish": "npm run compile", 137 | "compile": "tsc -p ./", 138 | "watch": "tsc -watch -p ./", 139 | "pretest": "npm run compile && npm run lint", 140 | "lint": "eslint src --ext ts" 141 | }, 142 | "dependencies": { 143 | "vscode-languageclient": "9.0.1" 144 | }, 145 | "devDependencies": { 146 | "@types/mocha": "^10.0.10", 147 | "@types/node": "^20.19.10", 148 | "@types/vscode": ">=1.0.0", 149 | "@typescript-eslint/eslint-plugin": "^8.18.0", 150 | "@typescript-eslint/parser": "^8.18.0", 151 | "@vscode/test-electron": "^2.4.1", 152 | "eslint": "^9.16.0", 153 | "glob": "^11.0.0", 154 | "mocha": "^11.0.1", 155 | "typescript": "^5.9.2" 156 | } 157 | } -------------------------------------------------------------------------------- /syntaxes/uiua.tmLanguage.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://raw.githubusercontent.com/martinring/tmlanguage/master/tmlanguage.json", 3 | "name": "Uiua", 4 | "firstLineMatch": "^#!/.*\\buiua\\b", 5 | "fileTypes": [ 6 | "ua" 7 | ], 8 | "patterns": [ 9 | { 10 | "include": "#comments" 11 | }, 12 | { 13 | "include": "#strings-multiline-format" 14 | }, 15 | { 16 | "include": "#strings-multiline" 17 | }, 18 | { 19 | "include": "#strings-format" 20 | }, 21 | { 22 | "include": "#strings-normal" 23 | }, 24 | { 25 | "include": "#characters" 26 | }, 27 | { 28 | "include": "#labels" 29 | }, 30 | { 31 | "include": "#module_delim" 32 | }, 33 | { 34 | "include": "#strand" 35 | }, 36 | { 37 | "include": "#stack" 38 | }, 39 | { 40 | "include": "#noadic" 41 | }, 42 | { 43 | "include": "#monadic" 44 | }, 45 | { 46 | "include": "#dyadic" 47 | }, 48 | { 49 | "include": "#mod1" 50 | }, 51 | { 52 | "include": "#mod2" 53 | }, 54 | { 55 | "include": "#idents" 56 | }, 57 | { 58 | "include": "#numbers" 59 | } 60 | ], 61 | "repository": { 62 | "idents": { 63 | "name": "variable.parameter.uiua", 64 | "match": "\\b[a-zA-Z]+['′″‴]*(₋?[₀₁₂₃₄₅₆₇₈₉⌞⌟]|,`?\\d+)*[!‼]*\\b" 65 | }, 66 | "comments": { 67 | "name": "comment.line.uiua", 68 | "match": "(#.*$|$[a-zA-Z]*)" 69 | }, 70 | "strings-normal": { 71 | "name": "constant.character.escape", 72 | "begin": "\"", 73 | "end": "\"", 74 | "patterns": [ 75 | { 76 | "name": "string.quoted", 77 | "match": "\\\\[\\\\\"0nrtW]" 78 | } 79 | ] 80 | }, 81 | "strings-format": { 82 | "name": "constant.character.escape", 83 | "begin": "\\$\"", 84 | "end": "\"", 85 | "patterns": [ 86 | { 87 | "name": "string.quoted", 88 | "match": "\\\\[\\\\\"0nrtW_]" 89 | }, 90 | { 91 | "name": "constant.numeric", 92 | "match": "(?≥+\\-×\\*÷%◿∨ⁿ↧↥∠ℂ≍⊟⊂⊏⊡↯↙↘↻⤸▽⌕⦷∊⨂⊥⍤]|(?