From d1b961c57c8780e63bf1484be0ba491c93b12303 Mon Sep 17 00:00:00 2001 From: ioedeveloper Date: Wed, 19 Jul 2023 15:03:49 +0100 Subject: [PATCH 1/3] Add language config and tokens provider for circom support in the editor --- apps/remix-ide/src/app/editor/editor.js | 3 +- .../editor/src/lib/remix-ui-editor.tsx | 7 + .../editor/src/lib/syntaxes/circom.ts | 211 ++++++++++++++++++ 3 files changed, 220 insertions(+), 1 deletion(-) create mode 100644 libs/remix-ui/editor/src/lib/syntaxes/circom.ts diff --git a/apps/remix-ide/src/app/editor/editor.js b/apps/remix-ide/src/app/editor/editor.js index 2de1353d15..2b0a4dd912 100644 --- a/apps/remix-ide/src/app/editor/editor.js +++ b/apps/remix-ide/src/app/editor/editor.js @@ -51,7 +51,8 @@ class Editor extends Plugin { rs: 'rust', cairo: 'cairo', ts: 'typescript', - move: 'move' + move: 'move', + circom: 'circom' } this.activated = false diff --git a/libs/remix-ui/editor/src/lib/remix-ui-editor.tsx b/libs/remix-ui/editor/src/lib/remix-ui-editor.tsx index fe39eed3e8..373d28be1b 100644 --- a/libs/remix-ui/editor/src/lib/remix-ui-editor.tsx +++ b/libs/remix-ui/editor/src/lib/remix-ui-editor.tsx @@ -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)) diff --git a/libs/remix-ui/editor/src/lib/syntaxes/circom.ts b/libs/remix-ui/editor/src/lib/syntaxes/circom.ts new file mode 100644 index 0000000000..b610dd4f8e --- /dev/null +++ b/libs/remix-ui/editor/src/lib/syntaxes/circom.ts @@ -0,0 +1,211 @@ +/* eslint-disable */ +export const circomLanguageConfig = (monaco) => ({ + wordPattern: + /(-?\d*\.\d\w*)|([^\`\~\!\@\#\%\^\&\*\(\)\-\=\+\[\{\]\}\\\|\;\:\'\"\,\.\<\>\/\?\s]+)/g, + + comments: { + lineComment: "//", + blockComment: ["/*", "*/"], + }, + + brackets: [ + ["{", "}"], + ["[", "]"], + ["(", ")"], + ], + + onEnterRules: [ + { + // e.g. /** | */ + beforeText: /^\s*\/\*\*(?!\/)([^\*]|\*(?!\/))*$/, + afterText: /^\s*\*\/$/, + action: { + indentAction: monaco.languages.IndentAction.IndentOutdent, + appendText: " * ", + }, + }, + { + // e.g. /** ...| + beforeText: /^\s*\/\*\*(?!\/)([^\*]|\*(?!\/))*$/, + action: { + indentAction: monaco.languages.IndentAction.None, + appendText: " * ", + }, + }, + { + // e.g. * ...| + beforeText: /^(\t|(\ \ ))*\ \*(\ ([^\*]|\*(?!\/))*)?$/, + action: { + indentAction: monaco.languages.IndentAction.None, + appendText: "* ", + }, + }, + { + // e.g. */| + 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: [ + "!", + "~", + "-", + "||", + "&&", + "==", + "!=", + "<", + ">", + "<=", + ">=", + "|", + "&", + "<<", + ">>", + "+", + "-", + "*", + "/", + "\\", + "%", + "**", + "^", + "=", + "<--", + "<==", + ], + + // we include these common regular expressions + // symbols: /[=>](?!@symbols)/, "@brackets"], + // [ + // /@symbols/, + // { cases: { "@operators": "operator", "@default": "" } }, + // ], + + // @ annotations. + // As an example, we emit a debugging log message on these tokens. + // Note: message are supressed during the first load -- change some lines to see them. + [ + /@\s*[a-zA-Z_\$][\w\$]*/, + { token: "annotation", log: "annotation token: $0" }, + ], + + // numbers + [/\d*\.\d+([eE][\-+]?\d+)?/, "number.float"], + [/0[xX][0-9a-fA-F]+/, "number.hex"], + [/\d+/, "number"], + + // delimiter: after number because of .\d floats + [/[;,.]/, "delimiter"], + + // strings + [/"([^"\\]|\\.)*$/, "string.invalid"], // non-teminated string + [/"/, { token: "string.quote", bracket: "@open", next: "@string" }], + + // characters + [/'[^\\']'/, "string"], + [/(')(@escapes)(')/, ["string", "string.escape", "string"]], + [/'/, "string.invalid"], + ], + + comment: [ + [/[^\/*]+/, "comment"], + [/\/\*/, "comment", "@push"], // nested comment + ["\\*/", "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"], + ], + }, +} From 633dfc2de9a72a42d11ebdf32cf59aecf7675875 Mon Sep 17 00:00:00 2001 From: ioedeveloper Date: Tue, 25 Jul 2023 11:11:57 +0100 Subject: [PATCH 2/3] Remove used comments --- .../editor/src/lib/syntaxes/circom.ts | 31 ++----------------- 1 file changed, 3 insertions(+), 28 deletions(-) diff --git a/libs/remix-ui/editor/src/lib/syntaxes/circom.ts b/libs/remix-ui/editor/src/lib/syntaxes/circom.ts index b610dd4f8e..6b09887c3a 100644 --- a/libs/remix-ui/editor/src/lib/syntaxes/circom.ts +++ b/libs/remix-ui/editor/src/lib/syntaxes/circom.ts @@ -16,7 +16,6 @@ export const circomLanguageConfig = (monaco) => ({ onEnterRules: [ { - // e.g. /** | */ beforeText: /^\s*\/\*\*(?!\/)([^\*]|\*(?!\/))*$/, afterText: /^\s*\*\/$/, action: { @@ -25,7 +24,6 @@ export const circomLanguageConfig = (monaco) => ({ }, }, { - // e.g. /** ...| beforeText: /^\s*\/\*\*(?!\/)([^\*]|\*(?!\/))*$/, action: { indentAction: monaco.languages.IndentAction.None, @@ -33,7 +31,6 @@ export const circomLanguageConfig = (monaco) => ({ }, }, { - // e.g. * ...| beforeText: /^(\t|(\ \ ))*\ \*(\ ([^\*]|\*(?!\/))*)?$/, action: { indentAction: monaco.languages.IndentAction.None, @@ -41,7 +38,6 @@ export const circomLanguageConfig = (monaco) => ({ }, }, { - // e.g. */| beforeText: /^(\t|(\ \ ))*\ \*\/\s*$/, action: { indentAction: monaco.languages.IndentAction.None, @@ -126,18 +122,12 @@ export const circomTokensProvider = { "<==", ], - // we include these common regular expressions - // symbols: /[=>](?!@symbols)/, "@brackets"], - // [ - // /@symbols/, - // { cases: { "@operators": "operator", "@default": "" } }, - // ], - - // @ annotations. - // As an example, we emit a debugging log message on these tokens. - // Note: message are supressed during the first load -- change some lines to see them. [ /@\s*[a-zA-Z_\$][\w\$]*/, { token: "annotation", log: "annotation token: $0" }, ], - // numbers [/\d*\.\d+([eE][\-+]?\d+)?/, "number.float"], [/0[xX][0-9a-fA-F]+/, "number.hex"], [/\d+/, "number"], - // delimiter: after number because of .\d floats [/[;,.]/, "delimiter"], - // strings - [/"([^"\\]|\\.)*$/, "string.invalid"], // non-teminated string + [/"([^"\\]|\\.)*$/, "string.invalid"], [/"/, { token: "string.quote", bracket: "@open", next: "@string" }], - // characters [/'[^\\']'/, "string"], [/(')(@escapes)(')/, ["string", "string.escape", "string"]], [/'/, "string.invalid"], @@ -190,7 +165,7 @@ export const circomTokensProvider = { comment: [ [/[^\/*]+/, "comment"], - [/\/\*/, "comment", "@push"], // nested comment + [/\/\*/, "comment", "@push"], ["\\*/", "comment", "@pop"], [/[\/*]/, "comment"], ], From 9825a540080a77e4f010288dfb89869a17d83acc Mon Sep 17 00:00:00 2001 From: ioedeveloper Date: Tue, 25 Jul 2023 12:04:26 +0100 Subject: [PATCH 3/3] Added .circom icons --- libs/remix-ui/helper/src/lib/remix-ui-helper.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libs/remix-ui/helper/src/lib/remix-ui-helper.ts b/libs/remix-ui/helper/src/lib/remix-ui-helper.ts index e06253c325..21925ed8f8 100644 --- a/libs/remix-ui/helper/src/lib/remix-ui-helper.ts +++ b/libs/remix-ui/helper/src/lib/remix-ui-helper.ts @@ -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) => {