diff --git a/vscode-flux/language-configuration.json b/vscode-flux/language-configuration.json new file mode 100644 index 0000000..6d693ca --- /dev/null +++ b/vscode-flux/language-configuration.json @@ -0,0 +1,45 @@ +{ + "comments": { + "lineComment": "//", + "blockComment": ["/*", "*/"] + }, + "brackets": [ + ["{", "}"], + ["[", "]"], + ["(", ")"] + ], + "autoClosingPairs": [ + { "open": "{", "close": "}" }, + { "open": "[", "close": "]" }, + { "open": "(", "close": ")" }, + { "open": "\"", "close": "\"", "notIn": ["string", "comment"] }, + { "open": "'", "close": "'", "notIn": ["string", "comment"] }, + { "open": "/*", "close": " */" } + ], + "surroundingPairs": [ + ["{", "}"], + ["[", "]"], + ["(", ")"], + ["\"", "\""], + ["'", "'"] + ], + "onEnterRules": [ + { + "beforeText": { "pattern": "^\\s*/\\*\\*(?!/)([^*]|\\*(?!/))*$" }, + "action": { "indent": "indentOutdent", "appendText": " * " } + }, + { + "beforeText": { "pattern": "^\\s* \\* (?!/).*$" }, + "action": { "indent": "none", "appendText": "* " } + }, + { + "beforeText": { "pattern": "^\\s* \\*/$" }, + "action": { "indent": "none", "removeText": 1 } + } + ], + "indentationRules": { + "increaseIndentPattern": { "pattern": "^.*\\{[^}\"']*$" }, + "decreaseIndentPattern": { "pattern": "^\\s*\\}" } + }, + "wordPattern": { "pattern": "[a-zA-Z_][a-zA-Z0-9_]*" } +} diff --git a/vscode-flux/package.json b/vscode-flux/package.json new file mode 100644 index 0000000..3c0d3e1 --- /dev/null +++ b/vscode-flux/package.json @@ -0,0 +1,34 @@ +{ + "name": "flux-lang", + "displayName": "Flux", + "description": "Syntax highlighting for the Flux programming language — a simple, fast systems language in the spirit of C and Rust.", + "version": "0.1.0", + "publisher": "flux-lang", + "engines": { + "vscode": "^1.74.0" + }, + "categories": [ + "Programming Languages" + ], + "contributes": { + "languages": [ + { + "id": "flux", + "aliases": ["Flux", "flux"], + "extensions": [".flux", ".flx"], + "configuration": "./language-configuration.json", + "icon": { + "light": "./icons/flux-light.png", + "dark": "./icons/flux-dark.png" + } + } + ], + "grammars": [ + { + "language": "flux", + "scopeName": "source.flux", + "path": "./syntaxes/flux.tmLanguage.json" + } + ] + } +} diff --git a/vscode-flux/syntaxes/flux.tmLanguage.json b/vscode-flux/syntaxes/flux.tmLanguage.json new file mode 100644 index 0000000..ebadedd --- /dev/null +++ b/vscode-flux/syntaxes/flux.tmLanguage.json @@ -0,0 +1,199 @@ +{ + "$schema": "https://raw.githubusercontent.com/martinring/tmlanguage/master/tmlanguage.json", + "name": "Flux", + "scopeName": "source.flux", + "fileTypes": ["flux"], + "patterns": [ + { "include": "#line-comment" }, + { "include": "#block-comment" }, + { "include": "#string" }, + { "include": "#char" }, + { "include": "#number" }, + { "include": "#fn-def" }, + { "include": "#struct-def" }, + { "include": "#control-keywords" }, + { "include": "#decl-keywords" }, + { "include": "#type-keywords" }, + { "include": "#boolean-literals" }, + { "include": "#operator-keywords" }, + { "include": "#operators" }, + { "include": "#punctuation" } + ], + "repository": { + + "line-comment": { + "name": "comment.line.double-slash.flux", + "match": "//.*$" + }, + + "block-comment": { + "name": "comment.block.flux", + "begin": "/\\*", + "end": "\\*/", + "beginCaptures": { "0": { "name": "punctuation.definition.comment.begin.flux" } }, + "endCaptures": { "0": { "name": "punctuation.definition.comment.end.flux" } } + }, + + "string": { + "name": "string.quoted.double.flux", + "begin": "\"", + "end": "\"", + "beginCaptures": { "0": { "name": "punctuation.definition.string.begin.flux" } }, + "endCaptures": { "0": { "name": "punctuation.definition.string.end.flux" } }, + "patterns": [ { "include": "#escape-sequence" } ] + }, + + "char": { + "name": "string.quoted.single.flux", + "begin": "'", + "end": "'", + "beginCaptures": { "0": { "name": "punctuation.definition.string.begin.flux" } }, + "endCaptures": { "0": { "name": "punctuation.definition.string.end.flux" } }, + "patterns": [ { "include": "#escape-sequence" } ] + }, + + "escape-sequence": { + "name": "constant.character.escape.flux", + "match": "\\\\([nrt\\\\\"'0]|u\\{[0-9a-fA-F]{1,6}\\})" + }, + + "number": { + "patterns": [ + { + "comment": "Floating-point: 3.14, 1.0e-9, 2e4", + "name": "constant.numeric.float.flux", + "match": "\\b\\d[\\d_]*\\.\\d[\\d_]*(?:[eE][+-]?\\d[\\d_]*)?\\b|\\b\\d[\\d_]*[eE][+-]?\\d[\\d_]*\\b" + }, + { + "comment": "Hexadecimal integer: 0xFF, 0xDEAD_BEEF", + "name": "constant.numeric.integer.hex.flux", + "match": "\\b0x[0-9a-fA-F][0-9a-fA-F_]*\\b" + }, + { + "comment": "Octal integer: 0o77", + "name": "constant.numeric.integer.octal.flux", + "match": "\\b0o[0-7][0-7_]*\\b" + }, + { + "comment": "Binary integer: 0b1010", + "name": "constant.numeric.integer.binary.flux", + "match": "\\b0b[01][01_]*\\b" + }, + { + "comment": "Decimal integer: 42, 1_000_000", + "name": "constant.numeric.integer.decimal.flux", + "match": "\\b\\d[\\d_]*\\b" + } + ] + }, + + "fn-def": { + "comment": "Highlight function name after `fn`", + "match": "\\b(fn)\\s+([a-zA-Z_][a-zA-Z0-9_]*)", + "captures": { + "1": { "name": "keyword.declaration.function.flux" }, + "2": { "name": "entity.name.function.flux" } + } + }, + + "struct-def": { + "comment": "Highlight struct name after `struct`", + "match": "\\b(struct)\\s+([a-zA-Z_][a-zA-Z0-9_]*)", + "captures": { + "1": { "name": "keyword.declaration.type.flux" }, + "2": { "name": "entity.name.type.struct.flux" } + } + }, + + "control-keywords": { + "name": "keyword.control.flux", + "match": "\\b(if|else|while|loop|break|continue|return)\\b" + }, + + "decl-keywords": { + "patterns": [ + { + "name": "keyword.other.let.flux", + "match": "\\blet\\b" + }, + { + "name": "storage.modifier.mut.flux", + "match": "\\bmut\\b" + } + ] + }, + + "type-keywords": { + "patterns": [ + { + "comment": "Primitive numeric types", + "name": "support.type.primitive.flux", + "match": "\\b(u8|u16|u32|u64|i8|i16|i32|i64|f32|f64)\\b" + }, + { + "comment": "Other primitive types", + "name": "support.type.primitive.flux", + "match": "\\b(bool|char)\\b" + }, + { + "comment": "Opaque pointer keyword", + "name": "support.type.opaque.flux", + "match": "\\bopaque\\b" + } + ] + }, + + "boolean-literals": { + "name": "constant.language.boolean.flux", + "match": "\\b(true|false)\\b" + }, + + "operator-keywords": { + "name": "keyword.operator.logical.flux", + "match": "\\b(and|or)\\b" + }, + + "operators": { + "patterns": [ + { + "comment": "Arrow (return type separator)", + "name": "keyword.operator.arrow.flux", + "match": "->" + }, + { + "comment": "Comparison operators", + "name": "keyword.operator.comparison.flux", + "match": "==|!=|<=|>=|<|>" + }, + { + "comment": "Assignment", + "name": "keyword.operator.assignment.flux", + "match": "(?])=(?!=)" + }, + { + "comment": "Arithmetic: + - * / %", + "name": "keyword.operator.arithmetic.flux", + "match": "[+\\-*/%]" + }, + { + "comment": "Bitwise: & | ^ ~ and unary ! ~", + "name": "keyword.operator.bitwise.flux", + "match": "[&|^~!]" + } + ] + }, + + "punctuation": { + "patterns": [ + { "name": "punctuation.terminator.statement.flux", "match": ";" }, + { "name": "punctuation.separator.comma.flux", "match": "," }, + { "name": "punctuation.accessor.dot.flux", "match": "\\." }, + { "name": "punctuation.separator.colon.flux", "match": ":" }, + { "name": "punctuation.brackets.round.flux", "match": "[()]" }, + { "name": "punctuation.brackets.square.flux", "match": "[\\[\\]]" }, + { "name": "punctuation.brackets.curly.flux", "match": "[{}]" } + ] + } + + } +}