Merge pull request #3935 from ethereum/circom-syntax

Support syntax highlighting for `.circom` files
pull/5370/head
David Disu 2 years ago committed by GitHub
commit 1ef8b9993c
  1. 3
      apps/remix-ide/src/app/editor/editor.js
  2. 7
      libs/remix-ui/editor/src/lib/remix-ui-editor.tsx
  3. 186
      libs/remix-ui/editor/src/lib/syntaxes/circom.ts
  4. 3
      libs/remix-ui/helper/src/lib/remix-ui-helper.ts

@ -51,7 +51,8 @@ class Editor extends Plugin {
rs: 'rust',
cairo: 'cairo',
ts: 'typescript',
move: 'move'
move: 'move',
circom: 'circom'
}
this.activated = false

@ -17,6 +17,7 @@ import { RemixHighLightProvider } from './providers/highlightProvider'
import { RemixDefinitionProvider } from './providers/definitionProvider'
import { RemixCodeActionProvider } from './providers/codeActionProvider'
import './remix-ui-editor.css'
import { circomLanguageConfig, circomTokensProvider } from './syntaxes/circom'
enum MarkerSeverity {
@ -322,6 +323,8 @@ export const EditorUI = (props: EditorUIProps) => {
monacoRef.current.editor.setModelLanguage(file.model, 'remix-zokrates')
} else if (file.language === 'move') {
monacoRef.current.editor.setModelLanguage(file.model, 'remix-move')
} else if (file.language === 'circom') {
monacoRef.current.editor.setModelLanguage(file.model, 'remix-circom')
}
}, [props.currentFile])
@ -731,6 +734,7 @@ export const EditorUI = (props: EditorUIProps) => {
monacoRef.current.languages.register({ id: 'remix-cairo' })
monacoRef.current.languages.register({ id: 'remix-zokrates' })
monacoRef.current.languages.register({ id: 'remix-move' })
monacoRef.current.languages.register({ id: 'remix-circom' })
// Register a tokens provider for the language
monacoRef.current.languages.setMonarchTokensProvider('remix-solidity', solidityTokensProvider as any)
@ -745,6 +749,9 @@ export const EditorUI = (props: EditorUIProps) => {
monacoRef.current.languages.setMonarchTokensProvider('remix-move', moveTokenProvider as any)
monacoRef.current.languages.setLanguageConfiguration('remix-move', moveLanguageConfig as any)
monacoRef.current.languages.setMonarchTokensProvider('remix-circom', circomTokensProvider as any)
monacoRef.current.languages.setLanguageConfiguration('remix-circom', circomLanguageConfig(monacoRef.current) as any)
monacoRef.current.languages.registerDefinitionProvider('remix-solidity', new RemixDefinitionProvider(props, monaco))
monacoRef.current.languages.registerDocumentHighlightProvider('remix-solidity', new RemixHighLightProvider(props, monaco))
monacoRef.current.languages.registerReferenceProvider('remix-solidity', new RemixReferenceProvider(props, monaco))

@ -0,0 +1,186 @@
/* eslint-disable */
export const circomLanguageConfig = (monaco) => ({
wordPattern:
/(-?\d*\.\d\w*)|([^\`\~\!\@\#\%\^\&\*\(\)\-\=\+\[\{\]\}\\\|\;\:\'\"\,\.\<\>\/\?\s]+)/g,
comments: {
lineComment: "//",
blockComment: ["/*", "*/"],
},
brackets: [
["{", "}"],
["[", "]"],
["(", ")"],
],
onEnterRules: [
{
beforeText: /^\s*\/\*\*(?!\/)([^\*]|\*(?!\/))*$/,
afterText: /^\s*\*\/$/,
action: {
indentAction: monaco.languages.IndentAction.IndentOutdent,
appendText: " * ",
},
},
{
beforeText: /^\s*\/\*\*(?!\/)([^\*]|\*(?!\/))*$/,
action: {
indentAction: monaco.languages.IndentAction.None,
appendText: " * ",
},
},
{
beforeText: /^(\t|(\ \ ))*\ \*(\ ([^\*]|\*(?!\/))*)?$/,
action: {
indentAction: monaco.languages.IndentAction.None,
appendText: "* ",
},
},
{
beforeText: /^(\t|(\ \ ))*\ \*\/\s*$/,
action: {
indentAction: monaco.languages.IndentAction.None,
removeText: 1,
},
},
],
autoClosingPairs: [
{ open: "{", close: "}" },
{ open: "[", close: "]" },
{ open: "(", close: ")" },
{ open: '"', close: '"', notIn: ["string"] },
{ open: "'", close: "'", notIn: ["string", "comment"] },
{ open: "`", close: "`", notIn: ["string", "comment"] },
{ open: "/**", close: " */", notIn: ["string"] },
],
folding: {
markers: {
start: new RegExp("^\\s*//\\s*#?region\\b"),
end: new RegExp("^\\s*//\\s*#?endregion\\b"),
},
},
})
export const circomTokensProvider = {
defaultToken: "",
tokenPostfix: ".circom",
keywords: [
"signal",
"input",
"output",
"public",
"template",
"component",
"parallel",
"custom",
"var",
"function",
"return",
"if",
"else",
"for",
"while",
"do",
"log",
"assert",
"include",
"pragma",
],
typeKeywords: ["input", "output", "public"],
operators: [
"!",
"~",
"-",
"||",
"&&",
"==",
"!=",
"<",
">",
"<=",
">=",
"|",
"&",
"<<",
">>",
"+",
"-",
"*",
"/",
"\\",
"%",
"**",
"^",
"=",
"<--",
"<==",
],
escapes:
/\\(?:[abfnrtv\\"']|x[0-9A-Fa-f]{1,4}|u[0-9A-Fa-f]{4}|U[0-9A-Fa-f]{8})/,
tokenizer: {
root: [
[
/[a-z_$][\w$]*/,
{
cases: {
"@typeKeywords": "keyword",
"@keywords": "keyword",
"@default": "identifier",
},
},
],
[/[A-Z][\w\$]*/, "type.identifier"],
{ include: "@whitespace" },
[/[{}()\[\]]/, "@brackets"],
[
/@\s*[a-zA-Z_\$][\w\$]*/,
{ token: "annotation", log: "annotation token: $0" },
],
[/\d*\.\d+([eE][\-+]?\d+)?/, "number.float"],
[/0[xX][0-9a-fA-F]+/, "number.hex"],
[/\d+/, "number"],
[/[;,.]/, "delimiter"],
[/"([^"\\]|\\.)*$/, "string.invalid"],
[/"/, { token: "string.quote", bracket: "@open", next: "@string" }],
[/'[^\\']'/, "string"],
[/(')(@escapes)(')/, ["string", "string.escape", "string"]],
[/'/, "string.invalid"],
],
comment: [
[/[^\/*]+/, "comment"],
[/\/\*/, "comment", "@push"],
["\\*/", "comment", "@pop"],
[/[\/*]/, "comment"],
],
string: [
[/[^\\"]+/, "string"],
[/@escapes/, "string.escape"],
[/\\./, "string.escape.invalid"],
[/"/, { token: "string.quote", bracket: "@close", next: "@pop" }],
],
whitespace: [
[/[ \t\r\n]+/, "white"],
[/\/\*/, "comment", "@comment"],
[/\/\/.*$/, "comment"],
],
},
}

@ -80,7 +80,8 @@ export const getPathIcon = (path: string) => {
? 'fak fa-lexon' : path.endsWith('ts')
? 'small fak fa-ts-logo' : path.endsWith('.tsc')
? 'fad fa-brackets-curly' : path.endsWith('.cairo')
? 'small fak fa-cairo' : 'far fa-file'
? 'small fak fa-cairo' : path.endsWith('.circom')
? 'fak fa-circom-plug1' : 'far fa-file'
}
export const isNumeric = (value) => {

Loading…
Cancel
Save