Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Initial Nim language support #6123

Merged
merged 4 commits into from
Mar 26, 2023
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions book/src/generated/lang-support.md
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@
| msbuild || || |
| nasm ||| | |
| nickel || || `nls` |
| nim |||| `nimlangserver` |
| nix || | | `nil` |
| nu || | | |
| ocaml || || `ocamllsp` |
Expand Down
23 changes: 23 additions & 0 deletions languages.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2327,3 +2327,26 @@ roots = []
[[grammar]]
name = "rst"
source = { git = "https://github.com/stsewd/tree-sitter-rst", rev = "25e6328872ac3a764ba8b926aea12719741103f1" }

[[language]]
name = "nim"
scope = "source.nim"
injection-regex = "nim"
file-types = ["nim", "nims", "nimble"]
shebangs = []
roots = []
comment-token = "#"
indent = { tab-width = 2, unit = " " }
language-server = { command = "nimlangserver" }

[language.auto-pairs]
'(' = ')'
'[' = ']'
'"' = '"'
"'" = "'"
'{' = '}'

# Nim's tree-sitter grammar is in heavy development.
[[grammar]]
name = "nim"
source = { git = "https://github.com/aMOPel/tree-sitter-nim", rev = "240239b232550e431d67de250d1b5856209e7f06" }
315 changes: 315 additions & 0 deletions runtime/queries/nim/highlights.scm
Original file line number Diff line number Diff line change
@@ -0,0 +1,315 @@
;; Constants, Comments, and Literals

(comment) @comment.line
(multilineComment) @comment.block
(docComment) @comment.block.documentation
(multilineDocComment) @comment.block.documentation
; comments

[(literal) (generalizedLit)] @constant
[(nil_lit)] @constant.builtin
[(bool_lit)] @constant.builtin.boolean
[(char_lit)] @constant.character
[(char_esc_seq) (str_esc_seq)] @constant.character.escape
[(custom_numeric_lit)] @constant.numeric
[(int_lit) (int_suffix)] @constant.numeric.integer
[(float_lit) (float_suffix)] @constant.numeric.float
; literals
; note: somewhat irritatingly for testing, lits have the same syntax highlighting as types

[
(str_lit)
(triplestr_lit)
(rstr_lit)
(generalized_str_lit)
(generalized_triplestr_lit)
(interpolated_str_lit)
(interpolated_triplestr_lit)
] @string
; [] @string.regexp
; string literals

[
"."
","
";"
":"
] @punctuation.delimiter
[
"("
")"
"["
"]"
"{"
"}"
"{."
".}"
"#["
"]#"
] @punctuation.bracket
(interpolated_str_lit "&" @punctuation.special)
(interpolated_str_lit "{" @punctuation.special)
(interpolated_str_lit "}" @punctuation.special)
; punctuation

[
"and"
"or"
"xor"
"not"
"in"
"notin"
"is"
"isnot"
"div"
"mod"
"shl"
"shr"
] @keyword.operator
; operators: we list them explicitly to deliminate them from symbolic operators

[(operator) (opr) "="] @operator
; all operators (must come after @keyword.operator)

(pragma) @attribute
; pragmas


;; Imports and Exports

(importStmt
(keyw) @keyword.control.import
(expr (primary (symbol) @namespace))?
(expr (primary (arrayConstr (exprColonExprList (exprColonExpr (expr (primary (symbol) @namespace)))))))?)
(exportStmt
(keyw) @keyword.control.import
(expr (primary (symbol) @namespace))?
(expr (primary (arrayConstr (exprColonExprList (exprColonExpr (expr (primary (symbol) @namespace)))))))?)
(fromStmt
(keyw) @keyword.control.import
(expr (primary (symbol) @namespace))?
(expr (primary (arrayConstr (exprColonExprList (exprColonExpr (expr (primary (symbol) @namespace)))))))?)
(includeStmt
(keyw) @keyword.control.import
(expr (primary (symbol) @namespace))?
(expr (primary (arrayConstr (exprColonExprList (exprColonExpr (expr (primary (symbol) @namespace)))))))?)
(importExceptStmt
(keyw) @keyword.control.import
(expr (primary (symbol) @namespace))?
(expr (primary (arrayConstr (exprColonExprList (exprColonExpr (expr (primary (symbol) @namespace)))))))?)
; import statements
; yeah, this is a bit gross.


;; Control Flow

(ifStmt (keyw) @keyword.control.conditional)
(whenStmt (keyw) @keyword.control.conditional)
(elifStmt (keyw) @keyword.control.conditional)
(elseStmt (keyw) @keyword.control.conditional)
(caseStmt (keyw) @keyword.control.conditional)
(ofBranch (keyw) @keyword.control.conditional)
(inlineIfStmt (keyw) @keyword.control.conditional)
(inlineWhenStmt (keyw) @keyword.control.conditional)
; conditional statements
; todo: do block

(forStmt
. (keyw) @keyword.control.repeat
. (symbol) @variable
. (keyw) @keyword.control.repeat)
(whileStmt (keyw) @keyword.control.repeat)
; loop statements

(returnStmt (keyw) @keyword.control.repeat)
(yieldStmt (keyw) @keyword.control.repeat)
(discardStmt (keyw) @keyword.control.repeat)
(breakStmt (keyw) @keyword.control.repeat)
(continueStmt (keyw) @keyword.control.repeat)
; control flow statements

(raiseStmt (keyw) @keyword.control.exception)
(tryStmt (keyw) @keyword.control.exception)
(tryExceptStmt (keyw) @keyword.control.exception)
(tryFinallyStmt (keyw) @keyword.control.exception)
(inlineTryStmt (keyw) @keyword.control.exception)
; (inlineTryExceptStmt (keyw) @keyword.control.exception)
; (inlineTryFinallyStmt (keyw) @keyword.control.exception)
; exception handling statements

(staticStmt (keyw) @keyword)
(deferStmt (keyw) @keyword)
(asmStmt (keyw) @keyword)
(bindStmt (keyw) @keyword)
(mixinStmt (keyw) @keyword)
; miscellaneous blocks

(blockStmt
(keyw) @keyword.control
(symbol) @label)
; block statements


;; Types and Type Declarations

(typeDef
(keyw) @keyword.storage.type
(symbol) @type)
; names of new types type declarations

(exprColonEqExpr
. (expr (primary (symbol) @variable))
. (expr (primary (symbol) @type)))
; variables in inline tuple declarations

(primarySuffix
(indexSuffix
(exprColonEqExprList
(exprColonEqExpr
(expr
(primary
(symbol) @type))))))
; nested types in brackets, i.e. seq[string]

(primaryTypeDef (symbol) @type)
; primary types of type declarations (NOT nested types)

(primaryTypeDef (primaryPrefix (keyw) @type))
; for consistency

(primaryTypeDesc (symbol) @type)
; type annotations, on declarations or in objects

(primaryTypeDesc (primaryPrefix (keyw) @type))
; var types etc

(genericParamList (genericParam (symbol) @type))
; types in generic blocks

(enumDecl (keyw) @keyword.storage.type)
(enumElement (symbol) @type.enum.variant)
; enum declarations and elements

(tupleDecl (keyw) @keyword.storage.type)
; tuple declarations

(objectDecl (keyw) @keyword.storage.type)
(objectPart (symbol) @variable.other.member)
; object declarations and fields

(objectCase
(keyw) @keyword.control.conditional
(symbol) @variable.other.member)
(objectBranch (keyw) @keyword.control.conditional)
(objectElif (keyw) @keyword.control.conditional)
(objectElse (keyw) @keyword.control.conditional)
(objectWhen (keyw) @keyword.control.conditional)
; variant objects

(conceptDecl (keyw) @keyword.storage.type)
(conceptParam (keyw) @type)
(conceptParam (symbol) @variable)
; concept declarations, parameters, and qualifiers on those parameters

((expr
(primary (symbol))
(operator) @operator
(primary (symbol) @type))
(#match? @operator "is"))
((exprStmt
(primary (symbol))
(operator) @operator
(primary (symbol) @type))
(#match? @operator "is"))
; symbols likely to be types: "x is t" means t is either a type or a type variable

; distinct?


;; Functions

(routine
. (keyw) @keyword.function
. (symbol) @function)
; function declarations

(routineExpr (keyw) @keyword.function)
; discarded function

(routineExprTypeDesc (keyw) @keyword.function)
; function declarations as types

(primary
. (symbol) @function.call
. (primarySuffix (functionCall)))
; regular function calls

(primary
. (symbol) @function.call
. (primarySuffix (cmdCall)))
; function calls without parenthesis

(primary
(primarySuffix (qualifiedSuffix (symbol) @function.call))
. (primarySuffix (functionCall)))
; uniform function call syntax calls

(primary
(primarySuffix (qualifiedSuffix (symbol) @function.call))
. (primarySuffix (cmdCall)))
; just in case

(primary
(symbol) @constructor
(primarySuffix (objectConstr)))
; object constructor

; does not appear to be a way to distinguish these without verbatium matching
; [] @function.builtin
; [] @function.method
; [] @function.macro
; [] @function.special


;; Variables

(paramList (paramColonEquals (symbol) @variable.parameter))
; parameter identifiers

(identColon (ident) @variable.other.member)
; named parts of tuples

(symbolColonExpr (symbol) @variable)
; object constructor parameters

(symbolEqExpr (symbol) @variable)
; named parameters

(variable
(keyw) @keyword.storage.type
(declColonEquals (symbol) @variable))
; let, var, const expressions

((primary (symbol) @variable.builtin)
(#match? @variable.builtin "result"))
; `result` is an implicit builtin variable inside function scopes

((primary (symbol) @type)
(#match? @type "^[A-Z]"))
; assume PascalCase identifiers to be types

((primary
(primarySuffix
(qualifiedSuffix
(symbol) @type)))
(#match? @type "^[A-Z]"))
; assume PascalCase member variables to be enum entries

(primary (symbol) @variable)
; overzealous, matches variables

(primary (primarySuffix (qualifiedSuffix (symbol) @variable.other.member)))
; overzealous, matches member variables: i.e. x in foo.x

(keyw) @keyword
; more specific matches are done above whenever possible
Loading