From 2aac76d168a6620b8fad9d890f21d4a3c25ae3cd Mon Sep 17 00:00:00 2001 From: Radon Rosborough Date: Sat, 20 Feb 2021 12:13:23 -0800 Subject: [PATCH] Validate all language configs with JSON Schema --- langs/c++.yaml | 2 + langs/c.yaml | 2 + langs/cat.yaml | 5 +- langs/clojure.yaml | 2 + langs/dart.yaml | 2 + langs/elixir.yaml | 2 + langs/elm.yaml | 2 + langs/erlang.yaml | 2 + langs/fortran.yaml | 2 + langs/go.yaml | 2 + langs/haskell.yaml | 2 + langs/java.yaml | 2 + langs/julia.yaml | 2 + langs/lua.yaml | 2 + langs/mariadb.yaml | 2 + langs/mysql.yaml | 2 + langs/objectivec++.yaml | 2 + langs/objectivec.yaml | 2 + langs/ocaml.yaml | 2 + langs/php.yaml | 2 + langs/postgresql.yaml | 2 + langs/powershell.yaml | 2 + langs/reasonml.yaml | 2 + langs/ruby.yaml | 2 + langs/rust.yaml | 2 + langs/sqlite.yaml | 2 + langs/swift.yaml | 2 + langs/tex.yaml | 2 + langs/vimscript.yaml | 2 + package.json | 1 + tools/config.js | 8 + tools/jsonschema.yaml | 899 ++++++++++++++++++++++++++++++++++++++++ yarn.lock | 5 + 33 files changed, 971 insertions(+), 3 deletions(-) create mode 100644 tools/jsonschema.yaml diff --git a/langs/c++.yaml b/langs/c++.yaml index d7ddcc1..895c640 100644 --- a/langs/c++.yaml +++ b/langs/c++.yaml @@ -89,6 +89,8 @@ lsp: echo '-Wall -Wextra' | sed -E 's/\s+/\n/g' > compile_flags.txt start: | clangd + code: "TODO" + item: "TODO" skip: - lsp diff --git a/langs/c.yaml b/langs/c.yaml index ae1ac9d..1880bbb 100644 --- a/langs/c.yaml +++ b/langs/c.yaml @@ -67,6 +67,8 @@ lsp: echo '-Wall -Wextra' | sed -E 's/\s+/\n/g' > compile_flags.txt start: | clangd + code: "TODO" + item: "TODO" skip: - lsp diff --git a/langs/cat.yaml b/langs/cat.yaml index 0a6185c..2fad37d 100644 --- a/langs/cat.yaml +++ b/langs/cat.yaml @@ -40,9 +40,8 @@ install: } repl.start({prompt: "cat> ", eval: (cmd, context, filename, callback) => callback(null, ce.eval(cmd))}); - manual: - - | - git clone https://github.com/cdiggins/cat-language "${pkg}/opt/cat" + manual: | + git clone https://github.com/cdiggins/cat-language "${pkg}/opt/cat" repl: | cat-lang diff --git a/langs/clojure.yaml b/langs/clojure.yaml index f505727..7838a7b 100644 --- a/langs/clojure.yaml +++ b/langs/clojure.yaml @@ -60,6 +60,8 @@ scope: lsp: start: | clojure-lsp + code: "TODO" + item: "TODO" skip: - lsp diff --git a/langs/dart.yaml b/langs/dart.yaml index cab1620..f5281e7 100644 --- a/langs/dart.yaml +++ b/langs/dart.yaml @@ -20,6 +20,8 @@ lsp: dart /usr/lib/dart/bin/snapshots/analysis_server.dart.snapshot --lsp disableDynamicRegistration: true lang: "dart" + code: "TODO" + item: "TODO" skip: - lsp diff --git a/langs/elixir.yaml b/langs/elixir.yaml index cce2dd6..75e36f8 100644 --- a/langs/elixir.yaml +++ b/langs/elixir.yaml @@ -44,6 +44,8 @@ scope: lsp: start: | /opt/elixir-ls/language_server.sh + code: "TODO" + item: "TODO" skip: - lsp diff --git a/langs/elm.yaml b/langs/elm.yaml index 5cdf05e..d974792 100644 --- a/langs/elm.yaml +++ b/langs/elm.yaml @@ -49,6 +49,8 @@ lsp: cp /opt/elm/elm.json elm.json start: | elm-language-server --stdio + code: "TODO" + item: "TODO" skip: - lsp diff --git a/langs/erlang.yaml b/langs/erlang.yaml index 2e76a31..13dd33e 100644 --- a/langs/erlang.yaml +++ b/langs/erlang.yaml @@ -53,6 +53,8 @@ scope: lsp: start: | erlang_ls + code: "TODO" + item: "TODO" skip: - lsp diff --git a/langs/fortran.yaml b/langs/fortran.yaml index e6872d0..5dca9ab 100644 --- a/langs/fortran.yaml +++ b/langs/fortran.yaml @@ -29,6 +29,8 @@ run: | lsp: start: | fortls + code: "TODO" + item: "TODO" skip: - lsp diff --git a/langs/go.yaml b/langs/go.yaml index 67e79ef..8dda88d 100644 --- a/langs/go.yaml +++ b/langs/go.yaml @@ -48,6 +48,8 @@ format: lsp: start: | gopls + code: "TODO" + item: "TODO" skip: - lsp diff --git a/langs/haskell.yaml b/langs/haskell.yaml index 91c8be6..39a7408 100644 --- a/langs/haskell.yaml +++ b/langs/haskell.yaml @@ -67,6 +67,8 @@ lsp: haskell-language-server-wrapper --lsp init: languageServerHaskell: {} + code: "TODO" + item: "TODO" skip: - lsp diff --git a/langs/java.yaml b/langs/java.yaml index 7c98753..28d434f 100644 --- a/langs/java.yaml +++ b/langs/java.yaml @@ -151,6 +151,8 @@ lsp: enabled: true trace: server: "off" + code: "TODO" + item: "TODO" skip: - lsp diff --git a/langs/julia.yaml b/langs/julia.yaml index 9f9f866..6072bb9 100644 --- a/langs/julia.yaml +++ b/langs/julia.yaml @@ -33,6 +33,8 @@ lsp: start: | JULIA_DEPOT_PATH=:/opt/julia-language-server julia -e 'using LanguageServer; run(LanguageServerInstance(stdin, stdout))' config: null + code: "TODO" + item: "TODO" skip: - lsp diff --git a/langs/lua.yaml b/langs/lua.yaml index 211fbeb..e33070b 100644 --- a/langs/lua.yaml +++ b/langs/lua.yaml @@ -29,6 +29,8 @@ scope: lsp: start: | java -cp /opt/emmylua/EmmyLua.jar com.tang.vscode.MainKt + code: "TODO" + item: "TODO" skip: - lsp diff --git a/langs/mariadb.yaml b/langs/mariadb.yaml index f70d310..17b21e0 100644 --- a/langs/mariadb.yaml +++ b/langs/mariadb.yaml @@ -47,6 +47,8 @@ run: | lsp: start: | sqls + code: "TODO" + item: "TODO" skip: - lsp diff --git a/langs/mysql.yaml b/langs/mysql.yaml index 4f39c1c..74f0dd9 100644 --- a/langs/mysql.yaml +++ b/langs/mysql.yaml @@ -38,6 +38,8 @@ run: | lsp: start: | sqls + code: "TODO" + item: "TODO" skip: - lsp diff --git a/langs/objectivec++.yaml b/langs/objectivec++.yaml index 8ce8a7d..f97db77 100644 --- a/langs/objectivec++.yaml +++ b/langs/objectivec++.yaml @@ -46,6 +46,8 @@ lsp: (gnustep-config --objc-flags && gnustep-config --base-libs) | sed -E 's/\s+/\n/g' > compile_flags.txt start: | clangd + code: "TODO" + item: "TODO" skip: - lsp diff --git a/langs/objectivec.yaml b/langs/objectivec.yaml index f4f6002..7ff9140 100644 --- a/langs/objectivec.yaml +++ b/langs/objectivec.yaml @@ -45,6 +45,8 @@ lsp: (gnustep-config --objc-flags && gnustep-config --base-libs) | sed -E 's/\s+/\n/g' > compile_flags.txt start: | clangd + code: "TODO" + item: "TODO" skip: - lsp diff --git a/langs/ocaml.yaml b/langs/ocaml.yaml index ec598e5..fd3e20c 100644 --- a/langs/ocaml.yaml +++ b/langs/ocaml.yaml @@ -41,6 +41,8 @@ lsp: start: | ocamllsp lang: "ocaml" + code: "TODO" + item: "TODO" skip: - lsp diff --git a/langs/php.yaml b/langs/php.yaml index 0f490d4..92c5bad 100644 --- a/langs/php.yaml +++ b/langs/php.yaml @@ -33,6 +33,8 @@ scope: lsp: start: | intelephense --stdio + code: "TODO" + item: "TODO" skip: - lsp diff --git a/langs/postgresql.yaml b/langs/postgresql.yaml index d73ffa5..c0c20e7 100644 --- a/langs/postgresql.yaml +++ b/langs/postgresql.yaml @@ -42,6 +42,8 @@ run: | lsp: start: | sqls + code: "TODO" + item: "TODO" skip: - lsp diff --git a/langs/powershell.yaml b/langs/powershell.yaml index db6a710..915be28 100644 --- a/langs/powershell.yaml +++ b/langs/powershell.yaml @@ -41,6 +41,8 @@ scope: lsp: start: | pwsh -NoLogo -NoProfile -Command "/opt/powershell-editor-services/PowerShellEditorServices/Start-EditorServices.ps1 -BundledModulesPath /opt/powershell-editor-services -LogPath '$PWD/.powershell-editor-services/lsp.log' -SessionDetailsPath '$PWD/.powershell-editor-services/session.json' -FeatureFlags @() -AdditionalModules @() -HostName Riju -HostProfileId 'riju' -HostVersion 0.0 -Stdio -LogLevel Normal" + code: "TODO" + item: "TODO" skip: - repl diff --git a/langs/reasonml.yaml b/langs/reasonml.yaml index e8aaede..12662e9 100644 --- a/langs/reasonml.yaml +++ b/langs/reasonml.yaml @@ -54,6 +54,8 @@ lsp: cp -a /opt/reasonml/skel/* ./ start: | reason-language-server + code: "TODO" + item: "TODO" skip: - lsp diff --git a/langs/ruby.yaml b/langs/ruby.yaml index 728559b..b82065b 100644 --- a/langs/ruby.yaml +++ b/langs/ruby.yaml @@ -54,6 +54,8 @@ pkg: lsp: start: | solargraph stdio + code: "TODO" + item: "TODO" skip: - repl diff --git a/langs/rust.yaml b/langs/rust.yaml index 3586807..3ebb0d1 100644 --- a/langs/rust.yaml +++ b/langs/rust.yaml @@ -36,6 +36,8 @@ run: | lsp: start: | rls + code: "TODO" + item: "TODO" skip: - lsp diff --git a/langs/sqlite.yaml b/langs/sqlite.yaml index 5567898..03d0f06 100644 --- a/langs/sqlite.yaml +++ b/langs/sqlite.yaml @@ -34,6 +34,8 @@ run: | lsp: start: | sqls -config /opt/sqlite/sqls.yml + code: "TODO" + item: "TODO" skip: - lsp diff --git a/langs/swift.yaml b/langs/swift.yaml index 7131796..8ad5c07 100644 --- a/langs/swift.yaml +++ b/langs/swift.yaml @@ -28,6 +28,8 @@ run: | lsp: start: | sourcekit-lsp + code: "TODO" + item: "TODO" skip: - lsp diff --git a/langs/tex.yaml b/langs/tex.yaml index 98bb873..e329833 100644 --- a/langs/tex.yaml +++ b/langs/tex.yaml @@ -56,6 +56,8 @@ lsp: start: | digestif lang: "tex" + code: "TODO" + item: "TODO" skip: - lsp diff --git a/langs/vimscript.yaml b/langs/vimscript.yaml index 28d09da..d0aa5f1 100644 --- a/langs/vimscript.yaml +++ b/langs/vimscript.yaml @@ -31,6 +31,8 @@ scope: lsp: start: | vim-language-server --stdio + code: "TODO" + item: "TODO" skip: - lsp diff --git a/package.json b/package.json index 0bbd4c6..273156a 100644 --- a/package.json +++ b/package.json @@ -20,6 +20,7 @@ "express-ws": "^4.0.0", "file-loader": "^6.2.0", "historic-readline": "^1.0.8", + "jsonschema": "^1.4.0", "lodash": "^4.17.20", "monaco-editor": "0.20.0", "monaco-editor-webpack-plugin": "1.9.0", diff --git a/tools/config.js b/tools/config.js index 07b01a0..694af9c 100644 --- a/tools/config.js +++ b/tools/config.js @@ -1,6 +1,7 @@ import { promises as fs } from "fs"; import path from "path"; +import { validate as validateJSONSchema } from "jsonschema"; import YAML from "yaml"; // The build scripts in the language configs assume a specific build @@ -12,6 +13,12 @@ import YAML from "yaml"; // directory also starts out empty // * we are using bash with 'set -euxo pipefail' +async function readJSONSchemaFromDisk() { + return YAML.parse(await fs.readFile("tools/jsonschema.yaml", "utf-8")); +} + +const jsonSchemaPromise = readJSONSchemaFromDisk(); + // Return a list of the IDs of all the configured languages. Each such // ID can be passed to readLangConfig. export async function getLangs() { @@ -85,6 +92,7 @@ export async function readLangConfig(lang) { const langConfig = YAML.parse( await fs.readFile(`langs/${lang}.yaml`, "utf-8") ); + validateJSONSchema(langConfig, await jsonSchemaPromise, { throwAll: true }); if (langConfig.id !== lang) { throw new Error( `lang config id ${langConfig.id} doesn't match expected ${lang}` diff --git a/tools/jsonschema.yaml b/tools/jsonschema.yaml new file mode 100644 index 0000000..bba6589 --- /dev/null +++ b/tools/jsonschema.yaml @@ -0,0 +1,899 @@ +# https://json-schema.org/draft/2019-09/json-schema-validation.html +# https://tools.ietf.org/html/draft-handrews-json-schema-02 + +$schema: "http://json-schema.org/draft/2019-09/schema#" +type: object +additionalProperties: false +required: [id, name, main, template, run] +properties: + + id: + title: "Canonical language ID" + description: | + This is a short unique identifier for the language. It should be + the full name, unabbreviated, but stripped of punctuation + (except pluses) and all lowercase. ASCII only. The canonical + language ID appears in URLs, e.g. . + + Canonical language IDs shouldn't include version numbers, and + they should not reference the implementation or compiler being + used. They should refer only to the abstract language being + implemented, e.g. 'python' instead of 'python3' or 'cpython'. In + some cases such as 'parser3', the language name actually does + include a version number, but this is unusual. + type: string + pattern: "^[a-z0-9+]+$" + examples: + - "python" + - "c++" + - "x86" + - "objectivec" + - "fsharp" + aliases: + title: "Language ID aliases" + description: | + Aliases are basically non-canonical language IDs. Specifying an + alias 'python3' for language 'python', for example, will set up + a URL redirect from to + . Typically, common extensions are + set up as aliases as well, such as 'py' for 'python'. (But only + one language can have a given alias, so if there is a conflict + then resolve it in favor of the more popular/recognized + language.) + type: array + items: + type: string + minLength: 1 + name: + title: "Language display name" + description: | + Human-readable, properly punctuated, canonical version of the + language name. Like 'id', the 'name' shouldn't include version + numbers or reference the implementation or compiler. The display + name is basically just a prettier version of the canonical + identifier. However, display names can use the full space of + Unicode, so foreign programming languages should be rendered in + their native alphabets. + type: string + minLength: 1 + examples: + - "Python" + - "C++" + - "x86" + - "Objective-C" + - "F#" + monacoLang: + title: "Monaco language ID" + description: | + Language ID to pass to Monaco for syntax highlighting, see: + . + + This is optional because most languages don't have syntax + highlighting support yet. + type: string + pattern: "^[a-z0-9-]+$" + examples: + - python + - cpp + - objective-c + + info: + type: object + additionalProperties: false + required: + - year + - desc + - ext + - web + - category + - mode + - platform + - syntax + - typing + - paradigm + - usage + properties: + impl: + title: "Implementation name" + description: | + If there are multiple available implementations of the + language runtime or compiler, the name of the one used on + Riju. + type: string + minLength: 1 + examples: + - "CPython" + - "GNU Bash" + - "ATS2/Postiats" + - "Pandoc" + version: + title: "Language version" + description: | + Major version of the language, if there are multiple. This + is not the full version number, which might change every + time a language is rebuilt. It only applies to the case + where there are meaningfully different dialects of a + language with distinct, widely recognizable version numbers. + type: string + minLength: 1 + examples: + - "Python 3" + - "C++20" + - "COBOL 2014" + year: + title: "Year of initial release" + description: | + The year when the language was first available in some form. + This information is frequently available on Wikipedia in the + sidebar. + type: integer + minimum: 1900 + maximum: 2100 + desc: + title: "Language description" + description: | + One-sentence description of the distinguishing features of + the language. Typically can be copied from Wikipedia or the + programming language's website. No trailing period. + type: string + pattern: "[^.]$" + examples: + - "Interpreted, high-level, general-purpose programming language" + - "Compiler for Clojure that targets JavaScript" + - "Popular RISC architecture used in mobile devices" + - "Two-dimensional esoteric programming language invented in 1993 by Chris Pressey with the goal of being as difficult to compile as possible" + ext: + definitions: + ext: + title: "File extension" + description: | + A file extension used for files written in the given + language (no leading period). The list should typically + include the file extension used for 'main', although it + may not in extreme cases (e.g. Confluence, which + *really* doesn't have a standard extension). + type: string + pattern: "^[a-zA-Z0-9]+$" + examples: + - py + - cljs + - chef + - S + anyOf: + - ref: "#/properties/info/properties/ext/definitions/ext" + - type: array + items: + ref: "#/properties/info/properties/ext/definitions/ext" + web: + type: object + additionalProperties: false + required: [source] + properties: + wiki: + title: "Link to Wikipedia" + description: | + The language's Wikipedia page, if it has one. + type: string + pattern: "^https://en\\.wikipedia\\.org/wiki/[^/]+$" + examples: + - "https://en.wikipedia.org/wiki/Python_(programming_language)" + - "https://en.wikipedia.org/wiki/C%2B%2B" + - "https://en.wikipedia.org/wiki/ARM_architecture" + - "https://en.wikipedia.org/wiki/Confluence_(software)" + esolang: + title: "Link to Esolang wiki" + description: | + The language's page on the Esolang wiki, if it has one. + type: string + pattern: "^https://esolangs\\.org/wiki/[^/]+$" + examples: + - "https://esolangs.org/wiki/Binary_lambda_calculus" + home: + title: "Link to official website" + description: | + The language's official website, if it has one. Note + that oftentimes ancient languages such as C and C++ will + not have an official website. (An official website for a + specific compiler or implementation of a language is not + the same as an official website for the language as a + whole; see the 'impl' key.) + type: string + pattern: "^https?://" + examples: + - "https://www.python.org/" + - "https://tromp.github.io/cl/Binary_lambda_calculus.html" + - "https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/windows-commands" + impl: + title: "Link to implementation website" + description: | + The website for the particular implementation Riju uses + for a language, if there is one. This shouldn't be a + GitHub link (see the 'source' key for that). + type: string + pattern: "^https?://" + examples: + - "https://gcc.gnu.org/" + - "https://sourceforge.net/projects/gnucobol/" + - "https://kiyuko.org/software/beef" + - "https://www.ioccc.org/2012/tromp/hint.html" + source: + definitions: + source: + title: "Link to language source code" + description: | + Link to GitHub, SourceForge, etc. for the language + implementation used on Riju. This can very + occasionally be omitted in cases of freely available + proprietary languages on Riju, such as Cmd. + type: string + pattern: "^https?://" + examples: + - "https://github.com/python/cpython" + - "https://sourceforge.net/p/gnucobol/_list/svn" + - "https://jmvdveer.home.xs4all.nl/en.algol-68-genie.html" + - "http://search.cpan.org/author/SMUELLER/Acme-Chef/" + anyOf: + - ref: "#/properties/info/properties/web/properties/source/definitions/source" + - const: null + category: + definitions: + category: + anyOf: + - const: assembly + description: | + An assembly language. + examples: + - "x86" + - "arm" + - "battlestar" + - const: config + description: | + A language for writing configuration files. + examples: + - "json" + - "yaml" + - "dhall" + - const: database + description: | + A database scripting language. + examples: + - "sqlite" + - "mongodb" + - "redis" + - const: editor + description: | + A text editor scripting language. + examples: + - "emacslisp" + - "vimscript" + - "teco" + - const: esoteric + description: | + An esoteric programming language. + examples: + - "brainf" + - "befunge" + - "chef" + - "blc" + - const: general + description: | + A general-purpose programming language. This + category fits most languages that are not obviously + something special. + examples: + - "python" + - "racket" + - "ceylon" + - "mumps" + - const: markup + description: | + A language for typesetting text as opposed to data + manipulation or more general programming facilities. + examples: + - "markdown" + - "org" + - "tex" + - const: pure + description: | + A language for pure data manipulation, with no + input/output facilities. + examples: + - "cat" + - const: shell + description: | + A shell-scripting language. + examples: + - "bash" + - "fish" + - "cmd" + - const: tool + description: | + The control language for a command-line utility. + examples: + - "sed" + - "awk" + - "jq" + anyOf: + - ref: "#/properties/info/properties/category/definitions/category" + - array: + items: + ref: "#/properties/info/properties/category/definitions/category" + mode: + definitions: + mode: + anyOf: + - const: compiled + description: | + A language whose programs *can* be compiled to an + executable. Data manipulation and markup languages + are neither compiled nor interpreted: Although they + produce a compiled artifact, it is not an + executable. + examples: + - "c" + - "coffeescript" + - const: interpreted + description: | + A language whose programs *can* be run without a + preliminary compilation step. + anyOf: + - ref: "#/properties/info/properties/mode/definitions/mode" + - array: + items: + ref: "#/properties/info/properties/mode/definitions/mode" + platform: + definitions: + platform: + anyOf: + - const: bf + description: | + A language that compiles to Brainfuck or runs under + the Brainfuck model of execution. + examples: + - "brainf" + - "ook" + - "pikachu" + - const: clr + description: | + A language that runs on the Common Language Runtime + (CLR). + examples: + - "csharp" + - "boo" + - "entropy" + - "visualbasic" + - const: js + description: | + A language that is part of the JavaScript/Node.js + ecosystem. + examples: + - "javascript" + - "clojurescript" + - "haxe" + - const: jvm + description: | + A language that runs on the Java Virtual Machine + (JVM). + examples: + - "java" + - "clojure" + - "groovy" + - const: python + description: | + A language that is part of the Python ecosystem. + examples: + - "python" + - "hy" + - "bython" + - const: windows + description: | + A language that is clearly tied to the Windows + "ecosystem" (or as some people might say, the + Windows "hazardous waste zone"). + examples: + - "cmd" + anyOf: + - ref: "#/properties/info/properties/platform/definitions/platform" + - array: + items: + ref: "#/properties/info/properties/platform/definitions/platform" + syntax: + definitions: + syntax: + anyOf: + # TODO: fill in documentation + - const: assembly + - const: basic + - const: c + - const: golf + - const: haskell + - const: lisp + - const: pascal + - const: python + - const: text + - const: tokens + + - const: 2d + - const: column + - const: extensible + - const: foreign + - const: symbol + - const: whitespace + anyOf: + - ref: "#/properties/info/properties/syntax/definitions/syntax" + - array: + items: + ref: "#/properties/info/properties/syntax/definitions/syntax" + typing: + definitions: + typing: + anyOf: + - const: static + - const: dynamic + + - const: theorem + + - const: float + - const: integer + - const: lambda + - const: string + - const: weak + anyOf: + - ref: "#/properties/info/properties/typing/definitions/typing" + - array: + items: + ref: "#/properties/info/properties/typing/definitions/typing" + paradigm: + definitions: + paradigm: + anyOf: + - const: array + - const: declarative + - const: functional + - const: imperative + - const: oo + - const: stack + - const: turing + anyOf: + - ref: "#/properties/info/properties/paradigm/definitions/paradigm" + - array: + items: + ref: "#/properties/info/properties/paradigm/definitions/paradigm" + usage: + definitions: + usage: + anyOf: + - const: abandoned + - const: personal + - const: popular + anyOf: + - ref: "#/properties/info/properties/usage/definitions/usage" + - array: + items: + ref: "#/properties/info/properties/usage/definitions/usage" + + # TODO: fill in documentation + install: + type: object + additionalProperties: false + properties: + prepare: + type: object + additionalProperties: false + properties: + apt: + type: array + items: + type: string + minLength: 1 + npm: + type: array + items: + type: string + minLength: 1 + opam: + type: array + items: + type: string + minLength: 1 + manual: + type: string + minLength: 1 + apt: + type: array + items: + type: string + minLength: 1 + riju: + type: array + items: + type: string + minLength: 1 + npm: + type: array + items: + anyOf: + - type: string + minLength: 1 + - type: object + additionalProperties: false + required: [name, arg] + properties: + name: + type: string + minLength: 1 + arg: + type: string + minLength: 1 + pip: + type: array + items: + type: string + minLength: 1 + gem: + type: array + items: + type: string + minLength: 1 + cpan: + type: array + items: + type: string + minLength: 1 + opam: + type: array + items: + anyOf: + - type: string + minLength: 1 + - type: object + additionalProperties: false + required: [name, binaries] + properties: + name: + type: string + minLength: 1 + source: + type: string + minLength: 1 + binaries: + type: array + items: + type: string + minLength: 1 + files: + type: object + scripts: + type: object + manual: + type: string + minLength: 1 + deb: + type: array + items: + type: string + pattern: "\\.deb$" + depends: + type: object + additionalProperties: false + properties: + strip: + type: array + items: + type: string + minLength: 1 + unpin: + type: array + items: + type: string + minLength: 1 + disallowCI: + type: boolean + default: false + + daemon: + title: "Persistent background daemon" + description: | + Shell command to run in the background when opening a new + language session, for example to set up a daemon in the case + that the language operates using a client-server model. You + might think this would be used for database languages, but + typically we start the database in the "run" command since we + want to kick it over every time the code is run. Currently it + has no uses; the keyword was introduced while investigating + whether Dockerfile could be supported on Riju. + type: string + minLength: 1 + setup: + title: "Initial setup command" + description: | + Shell command to run synchronously when opening a new language + session, before allowing any further operations to proceed. This + should have no chance of failing. + + The typical usage of this command is to copy a previously + prepared skeleton directory into the new session folder. + type: string + minLength: 1 + + repl: + title: "REPL command" + description: | + Shell command to run an interactive session with the language + interpreter, with no input loaded from the 'main' file. + type: string + minLength: 1 + input: + title: "REPL input for 'repl' and 'runrepl' tests" + description: | + By default the 'repl' and 'runrepl' tests operate by entering + '123 * 234' into the REPL and sending a newline, expecting to + receive '28782' as output. This key, if specified, overrides the + input value. + + This value can be multiline if multiple lines need to be entered + into the REPL to perform a calculation. A line can be of the + form 'DELAY: n' where n is an integer, to insert a delay of n + seconds before sending the next line of input. + + This can be overridden further by the 'runReplInput' key. + type: string + minLength: 1 + default: | + 123 * 234 + output: + title: "Expected REPL output for 'repl' and 'runrepl' tests" + description: | + See the 'input' detail for more context. This key overrides the + expected output string for the 'repl' and 'runrepl' tests. It + can be multiline to expect multiple lines of output. + type: string + minLength: 1 + default: | + 28782 + + main: + title: "Filename in which to write user code for execution" + description: | + Name of file to write user code. This can include path + separators if needed, although it's uncommon. Typically it's + just 'main' (or 'Main') with a standard file extension, + depending on the conventions of the language. + + Occasionally languages (mostly shells, but there are some other + hacks related to variable scoping) won't be able to load code + from an arbitrary file properly, and you have to set a main + filename that corresponds to a profile or 'rc' file. + type: string + minLength: 1 + examples: + - "main.py" + - "Main.java" + - "src/Main.purs" + - ".zshrc" + template: + title: 'Default user code printing "Hello, world!"' + description: | + Default code to populate in the Riju code editor. When run, this + should print exactly the text "Hello, world!" with a trailing + newline, to stdout. If that's not feasible for whatever reason, + it should do the most similar thing that can be managed. + type: string + minLength: 1 + prefix: + title: "Code to prepend to user code before running" + description: | + If this is provided, then its value (plus a following newline) + is silently prepended to the user-submitted code before it is + written to the 'main' file. This can be used to configure the + environment in ways that can't be done via environment variables + or command-line options, and which would not normally be needed + except to account for the Riju environment. + type: string + minLength: 1 + suffix: + title: "Code to append to user code before running" + description: | + If this is provided, then its value (plus a preceding newline) + is silently appended to the user-submitted code before it is + written to the 'main' file. This can be used to set up a + debugger or perform other hackery to make the language work + nicely with the Riju environment. + type: string + minLength: 1 + createEmpty: + title: "Overwrite the 'main' file when executing 'repl' command" + description: | + Normally, the 'template' code is immediately written into the + 'main' file at session start. This is to satisfy various + language servers which expect files to actually exist on disk + before they can be analyzed. The 'createEmpty' option overrides + this, so that the value of the option (typically an empty + string) will be written to the 'main' file instead. + + This is to account for languages such as Zsh, where 'main' has + to be set to '.zshrc', which would result in the 'repl' command + executing the 'template' code just like the 'run' command if it + were not for the 'createEmpty' option. + type: string + examples: + - "" + + compile: + title: "Compilation command" + description: | + Shell command to compile the 'main' file into an object file or + executable, if the language has a compilation step. + type: string + minLength: 1 + run: + title: "Run command" + description: | + Command to execute the 'main' file (or whatever the 'main' file + was compiled into, if 'compile' was provided) and then start an + interactive session, preferably with all local variables from + the 'main' file still in scope. + type: string + minLength: 1 + helloInput: + title: "Program input for 'run' test" + description: | + By default the 'run' test operates by simply running the + 'template' code and expecting to see "Hello, world!" as output. + If some input needs to be provided before the output can be + printed (e.g. for stream processing languages like jq and sed), + it can be given as part of this option. + + This value can be multiline if multiple lines of input need to + be entered to get the desired output. A line can be of the form + 'DELAY: n' where n is an integer, to insert a delay of n seconds + before sending the next line of input. + + An empty string means just an input of a single newline + character. + type: string + hello: + title: "Expected output for 'run' test" + description: | + If the language cannot reasonably print "Hello, world!" exactly, + provide this option to specify what it actually prints. Note + that the 'run' test does not actually check for the trailing + newline, although it's still desired. + + Newlines are allowed, and are not interpreted specially. + + This is interpreted as a JavaScript regular expression instead + of a literal string, if 'helloMaxLength' is provided. That + feature can be useful if the output of a programming language is + always nondeterministic. + type: string + minLength: 1 + default: "Hello, world!" + helloMaxLength: + title: "Maximum length for 'hello' regular expression matches" + description: | + If this is provided, then the value of the 'hello' option is + interpreted as a regular expression to match against the program + output for the 'run' test. Regex matching is difficult to do + efficiently against a stream, so to help the implementation, in + this case it is required to provide an upper bound on how long + matches can be. (In most reasonable cases, all matches will be + the same length, so this just means the length of any match for + the regular expression.) + type: integer + minimum: 1 + runReplInput: + title: "REPL input for 'runrepl' test specifically" + description: | + This is the same as 'input', but it is used only for the + 'runrepl' test and hence can be used as an override in the case + that the needed input for 'runrepl' is different than that for + 'repl'. + type: string + minLength: 1 + runReplOutput: + title: "Expected REPL output for 'runrepl' test specifically" + description: | + This is the same as 'output', but it is used only for the + 'runrepl' test and hence can be used as an override in the case + that the expected output for 'runrepl' is different than that + for 'repl'. + type: string + minLength: 1 + + # TODO: fill in documentation + scope: + type: object + additionalProperties: false + required: [code] + properties: + code: + type: string + minLength: 1 + after: + type: string + minLength: 1 + input: + type: string + minLength: 1 + output: + type: string + minLength: 1 + + ensure: + type: string + minLength: 1 + + format: + type: object + additionalProperties: false + required: [run] + properties: + run: + type: string + minLength: 1 + input: + type: string + minLength: 1 + output: + type: string + minLength: 1 + + pkg: + type: object + additionalProperties: false + required: [install] + properties: + install: + type: string + pattern: "NAME" + uninstall: + type: string + pattern: "NAME" + all: + type: string + minLength: 1 + search: + type: string + pattern: "NAME" + + lsp: + type: object + additionalProperties: false + required: [start, code, item] + properties: + setup: + type: string + minLength: 1 + start: + type: string + minLength: 1 + disableDynamicRegistration: + type: boolean + default: false + init: {} + config: {} + lang: + type: string + minLength: 1 + code: + type: string + minLength: 1 + after: + type: string + minLength: 1 + item: + type: string + minLength: 1 + + skip: + type: array + items: + enum: + - ensure + - run + - repl + - runrepl + - scope + - format + - lsp diff --git a/yarn.lock b/yarn.lock index 4efa403..21eb2e5 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2720,6 +2720,11 @@ jsonfile@^2.1.0: optionalDependencies: graceful-fs "^4.1.6" +jsonschema@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/jsonschema/-/jsonschema-1.4.0.tgz#1afa34c4bc22190d8e42271ec17ac8b3404f87b2" + integrity sha512-/YgW6pRMr6M7C+4o8kS+B/2myEpHCrxO4PEWnqJNBFMjn7EWXqlQ4tGwL6xTHeRplwuZmcAncdvfOad1nT2yMw== + kind-of@^3.0.2, kind-of@^3.0.3, kind-of@^3.2.0: version "3.2.2" resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64"