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 e330efb78a8..b38ad5a7d48 100644 --- a/libs/remix-ui/editor/src/lib/remix-ui-editor.tsx +++ b/libs/remix-ui/editor/src/lib/remix-ui-editor.tsx @@ -9,6 +9,7 @@ import { solidityTokensProvider, solidityLanguageConfig } from './syntaxes/solid import { cairoTokensProvider, cairoLanguageConfig } from './syntaxes/cairo' import { zokratesTokensProvider, zokratesLanguageConfig } from './syntaxes/zokrates' import { moveTokenProvider, moveLanguageConfig } from './syntaxes/move' +import { vyperTokenProvider, vyperLanguageConfig } from './syntaxes/vyper' import { tomlLanguageConfig, tomlTokenProvider } from './syntaxes/toml' import { monacoTypes } from '@remix-ui/editor' import { loadTypes } from './web-types' @@ -369,6 +370,8 @@ export const EditorUI = (props: EditorUIProps) => { monacoRef.current.editor.setModelLanguage(file.model, 'remix-toml') } else if (file.language === 'noir') { monacoRef.current.editor.setModelLanguage(file.model, 'remix-noir') + } else if (file.language === 'python') { + monacoRef.current.editor.setModelLanguage(file.model, 'remix-vyper') } }, [props.currentFile, props.isDiff]) @@ -1011,6 +1014,7 @@ export const EditorUI = (props: EditorUIProps) => { monacoRef.current.languages.register({ id: 'remix-zokrates' }) monacoRef.current.languages.register({ id: 'remix-move' }) monacoRef.current.languages.register({ id: 'remix-circom' }) + monacoRef.current.languages.register({ id: 'remix-vyper' }) monacoRef.current.languages.register({ id: 'remix-toml' }) monacoRef.current.languages.register({ id: 'remix-noir' }) @@ -1035,6 +1039,7 @@ export const EditorUI = (props: EditorUIProps) => { monacoRef.current.languages.setMonarchTokensProvider('remix-circom', circomTokensProvider as any) monacoRef.current.languages.setLanguageConfiguration('remix-circom', circomLanguageConfig(monacoRef.current) as any) + monacoRef.current.languages.registerInlineCompletionsProvider('remix-circom', inlineCompletionProvider) monacoRef.current.languages.setMonarchTokensProvider('remix-toml', tomlTokenProvider as any) monacoRef.current.languages.setLanguageConfiguration('remix-toml', tomlLanguageConfig as any) @@ -1050,6 +1055,11 @@ export const EditorUI = (props: EditorUIProps) => { monacoRef.current.languages.registerInlineCompletionsProvider('remix-solidity', inlineCompletionProvider) monaco.languages.registerCodeActionProvider('remix-solidity', new RemixCodeActionProvider(props, monaco)) + monacoRef.current.languages.setMonarchTokensProvider('remix-vyper', vyperTokenProvider as any) + monacoRef.current.languages.setLanguageConfiguration('remix-vyper', vyperLanguageConfig as any) + monacoRef.current.languages.registerCompletionItemProvider('remix-vyper', new RemixCompletionProvider(props, monaco)) + monacoRef.current.languages.registerInlineCompletionsProvider('remix-vyper', inlineCompletionProvider) + loadTypes(monacoRef.current) } diff --git a/libs/remix-ui/editor/src/lib/syntaxes/vyper.ts b/libs/remix-ui/editor/src/lib/syntaxes/vyper.ts new file mode 100644 index 00000000000..59545ab13a8 --- /dev/null +++ b/libs/remix-ui/editor/src/lib/syntaxes/vyper.ts @@ -0,0 +1,75 @@ +export const vyperLanguageConfig = { + comments: { + lineComment: "#", + }, + brackets: [ + ["{", "}"], + ["[", "]"], + ["(", ")"], + ], + autoClosingPairs: [ + { open: "[", close: "]" }, + { open: "{", close: "}" }, + { open: "(", close: ")" }, + { open: "'", close: "'", notIn: ["string"] }, + { open: '"', close: '"', notIn: ["string"] }, + ], + surroundingPairs: [ + { open: "{", close: "}" }, + { open: "[", close: "]" }, + { open: "(", close: ")" }, + { open: "'", close: "'" }, + { open: '"', close: '"' }, + ], +}; + +export const vyperTokenProvider = { + keywords: [ + "contract", "def", "if", "elif", "else", "for", "while", "break", "continue", "return", "assert", "pass", "log", "struct", + "event", "indexed", "public", "private", "pure", "view", "payable", "nonpayable", "external", "internal", "self", "send", + "call", "delegatecall", "transfer", "mod", "range", "True", "False", "None", + ], + + typeKeywords: [ + "address", "bool", "bytes", "bytes32", "decimal", "int128", "uint256", "string", "mapping", "immutable", + ], + + operators: [ + "=", "+", "-", "*", "/", "%", "**", "//", "&", "|", "^", "~", "<<", ">>", "+=", "-=", "*=", "/=", "%=", "**=", "//=", + "&=", "|=", "^=", "<<=", ">>=", "==", "!=", "<", "<=", ">", ">=", "and", "or", "not", + ], + + symbols: /[=> { data-id="remix_ai_switch" id='remix_ai_switch' className="btn ai-switch text-ai pl-2 pr-0 py-0" - disabled={!(tabsState.currentExt === 'sol')} + disabled={!((tabsState.currentExt === 'sol') || (tabsState.currentExt === 'vy') || (tabsState.currentExt === 'circom') )} onClick={async () => { await props.plugin.call('settings', 'updateCopilotChoice', !ai_switch) setAI_switch(!ai_switch)