@ -3,9 +3,15 @@ import {isArray} from 'lodash'
import Editor , { loader , Monaco } from '@monaco-editor/react'
import Editor , { loader , Monaco } from '@monaco-editor/react'
import { AlertModal } from '@remix-ui/app'
import { AlertModal } from '@remix-ui/app'
import { reducerActions , reducerListener , initialState } from './actions/editor'
import { reducerActions , reducerListener , initialState } from './actions/editor'
import { solidityTokensProvider , solidityLanguageConfig } from './syntaxes/solidity'
import {
solidityTokensProvider ,
solidityLanguageConfig
} from './syntaxes/solidity'
import { cairoTokensProvider , cairoLanguageConfig } from './syntaxes/cairo'
import { cairoTokensProvider , cairoLanguageConfig } from './syntaxes/cairo'
import { zokratesTokensProvider , zokratesLanguageConfig } from './syntaxes/zokrates'
import {
zokratesTokensProvider ,
zokratesLanguageConfig
} from './syntaxes/zokrates'
import { moveTokenProvider , moveLanguageConfig } from './syntaxes/move'
import { moveTokenProvider , moveLanguageConfig } from './syntaxes/move'
import { monacoTypes } from '@remix-ui/editor'
import { monacoTypes } from '@remix-ui/editor'
import { loadTypes } from './web-types'
import { loadTypes } from './web-types'
@ -95,7 +101,14 @@ export type DecorationsReturn = {
export type PluginType = {
export type PluginType = {
on : ( plugin : string , event : string , listener : any ) = > void
on : ( plugin : string , event : string , listener : any ) = > void
call : ( plugin : string , method : string , arg1? : any , arg2? : any , arg3? : any , arg4? : any ) = > any
call : (
plugin : string ,
method : string ,
arg1? : any ,
arg2? : any ,
arg3? : any ,
arg4? : any
) = > any
}
}
export type EditorAPIType = {
export type EditorAPIType = {
@ -104,12 +117,30 @@ export type EditorAPIType = {
getValue : ( uri : string ) = > string
getValue : ( uri : string ) = > string
getCursorPosition : ( offset? : boolean ) = > number | monacoTypes . IPosition
getCursorPosition : ( offset? : boolean ) = > number | monacoTypes . IPosition
getHoverPosition : ( position : monacoTypes.IPosition ) = > number
getHoverPosition : ( position : monacoTypes.IPosition ) = > number
addDecoration : ( marker : sourceMarker , filePath : string , typeOfDecoration : string ) = > DecorationsReturn
addDecoration : (
clearDecorationsByPlugin : ( filePath : string , plugin : string , typeOfDecoration : string , registeredDecorations : any , currentDecorations : any ) = > DecorationsReturn
marker : sourceMarker ,
keepDecorationsFor : ( filePath : string , plugin : string , typeOfDecoration : string , registeredDecorations : any , currentDecorations : any ) = > DecorationsReturn
filePath : string ,
typeOfDecoration : string
) = > DecorationsReturn
clearDecorationsByPlugin : (
filePath : string ,
plugin : string ,
typeOfDecoration : string ,
registeredDecorations : any ,
currentDecorations : any
) = > DecorationsReturn
keepDecorationsFor : (
filePath : string ,
plugin : string ,
typeOfDecoration : string ,
registeredDecorations : any ,
currentDecorations : any
) = > DecorationsReturn
addErrorMarker : ( errors : errorMarker [ ] , from : string ) = > void
addErrorMarker : ( errors : errorMarker [ ] , from : string ) = > void
clearErrorMarkers : ( sources : string [ ] | { [ fileName : string ] : any } , from : string ) = > void
clearErrorMarkers : (
getPositionAt : ( offset : number ) = > monacoTypes . IPosition
sources : string [ ] | { [ fileName : string ] : any } ,
from : string
) = > void
}
}
/* eslint-disable-next-line */
/* eslint-disable-next-line */
@ -161,7 +192,10 @@ export const EditorUI = (props: EditorUIProps) => {
const [ editorModelsState , dispatch ] = useReducer ( reducerActions , initialState )
const [ editorModelsState , dispatch ] = useReducer ( reducerActions , initialState )
const formatColor = ( name ) = > {
const formatColor = ( name ) = > {
let color = window . getComputedStyle ( document . documentElement ) . getPropertyValue ( name ) . trim ( )
let color = window
. getComputedStyle ( document . documentElement )
. getPropertyValue ( name )
. trim ( )
if ( color . length === 4 ) {
if ( color . length === 4 ) {
color = color . concat ( color . substr ( 1 ) )
color = color . concat ( color . substr ( 1 ) )
}
}
@ -287,7 +321,8 @@ export const EditorUI = (props: EditorUIProps) => {
'editorSuggestWidget.highlightForeground' : primaryColor ,
'editorSuggestWidget.highlightForeground' : primaryColor ,
'editorSuggestWidget.focusHighlightForeground' : infoColor ,
'editorSuggestWidget.focusHighlightForeground' : infoColor ,
'editor.lineHighlightBorder' : secondaryColor ,
'editor.lineHighlightBorder' : secondaryColor ,
'editor.lineHighlightBackground' : textbackground === darkColor ? lightColor : secondaryColor ,
'editor.lineHighlightBackground' :
textbackground === darkColor ? lightColor : secondaryColor ,
'editorGutter.background' : lightColor ,
'editorGutter.background' : lightColor ,
//'editor.selectionHighlightBackground': secondaryColor,
//'editor.selectionHighlightBackground': secondaryColor,
'minimap.background' : lightColor ,
'minimap.background' : lightColor ,
@ -309,7 +344,9 @@ export const EditorUI = (props: EditorUIProps) => {
useEffect ( ( ) = > {
useEffect ( ( ) = > {
if ( ! editorRef . current || ! props . currentFile ) return
if ( ! editorRef . current || ! props . currentFile ) return
currentFileRef . current = props . currentFile
currentFileRef . current = props . currentFile
props . plugin . call ( 'fileManager' , 'getUrlFromPath' , currentFileRef . current ) . then ( ( url ) = > ( currentUrlRef . current = url . file ) )
props . plugin
. call ( 'fileManager' , 'getUrlFromPath' , currentFileRef . current )
. then ( ( url ) = > ( currentUrlRef . current = url . file ) )
const file = editorModelsState [ props . currentFile ]
const file = editorModelsState [ props . currentFile ]
editorRef . current . setModel ( file . model )
editorRef . current . setModel ( file . model )
@ -329,18 +366,34 @@ export const EditorUI = (props: EditorUIProps) => {
}
}
} , [ props . currentFile ] )
} , [ props . currentFile ] )
const convertToMonacoDecoration = ( decoration : lineText | sourceAnnotation | sourceMarker , typeOfDecoration : string ) = > {
const convertToMonacoDecoration = (
decoration : lineText | sourceAnnotation | sourceMarker ,
typeOfDecoration : string
) = > {
if ( typeOfDecoration === 'sourceAnnotationsPerFile' ) {
if ( typeOfDecoration === 'sourceAnnotationsPerFile' ) {
decoration = decoration as sourceAnnotation
decoration = decoration as sourceAnnotation
return {
return {
type : typeOfDecoration ,
type : typeOfDecoration ,
range : new monacoRef . current . Range ( decoration . row + 1 , 1 , decoration . row + 1 , 1 ) ,
range : new monacoRef . current . Range (
decoration . row + 1 ,
1 ,
decoration . row + 1 ,
1
) ,
options : {
options : {
isWholeLine : false ,
isWholeLine : false ,
glyphMarginHoverMessage : {
glyphMarginHoverMessage : {
value : ( decoration . from ? ` from ${ decoration . from } : \ n ` : '' ) + decoration . text
value :
( decoration . from ? ` from ${ decoration . from } : \ n ` : '' ) +
decoration . text
} ,
} ,
glyphMarginClassName : ` fal fa-exclamation-square text- ${ decoration . type === 'error' ? 'danger' : decoration . type === 'warning' ? 'warning' : 'info' } `
glyphMarginClassName : ` fal fa-exclamation-square text- ${
decoration . type === 'error'
? 'danger'
: decoration . type === 'warning'
? 'warning'
: 'info'
} `
}
}
}
}
}
}
@ -348,7 +401,9 @@ export const EditorUI = (props: EditorUIProps) => {
decoration = decoration as sourceMarker
decoration = decoration as sourceMarker
let isWholeLine = false
let isWholeLine = false
if (
if (
( decoration . position . start . line === decoration . position . end . line && decoration . position . end . column - decoration . position . start . column < 2 ) ||
( decoration . position . start . line === decoration . position . end . line &&
decoration . position . end . column - decoration . position . start . column <
2 ) ||
decoration . position . start . line !== decoration . position . end . line
decoration . position . start . line !== decoration . position . end . line
) {
) {
// in this case we force highlighting the whole line (doesn't make sense to highlight 2 chars)
// in this case we force highlighting the whole line (doesn't make sense to highlight 2 chars)
@ -364,7 +419,9 @@ export const EditorUI = (props: EditorUIProps) => {
) ,
) ,
options : {
options : {
isWholeLine ,
isWholeLine ,
inlineClassName : ` ${ isWholeLine ? 'alert-info' : 'inline-class' } border-0 highlightLine ${ decoration . position . start . line + 1 } `
inlineClassName : ` ${
isWholeLine ? 'alert-info' : 'inline-class'
} border - 0 highlightLine $ { decoration . position . start . line + 1 } `
}
}
}
}
}
}
@ -410,7 +467,13 @@ export const EditorUI = (props: EditorUIProps) => {
}
}
}
}
props . editorAPI . clearDecorationsByPlugin = ( filePath : string , plugin : string , typeOfDecoration : string , registeredDecorations : any , currentDecorations : any ) = > {
props . editorAPI . clearDecorationsByPlugin = (
filePath : string ,
plugin : string ,
typeOfDecoration : string ,
registeredDecorations : any ,
currentDecorations : any
) = > {
const model = editorModelsState [ filePath ] ? . model
const model = editorModelsState [ filePath ] ? . model
if ( ! model )
if ( ! model )
return {
return {
@ -421,19 +484,33 @@ export const EditorUI = (props: EditorUIProps) => {
const newRegisteredDecorations = [ ]
const newRegisteredDecorations = [ ]
if ( registeredDecorations ) {
if ( registeredDecorations ) {
for ( const decoration of registeredDecorations ) {
for ( const decoration of registeredDecorations ) {
if ( decoration . type === typeOfDecoration && decoration . value . from !== plugin ) {
if (
decorations . push ( convertToMonacoDecoration ( decoration . value , typeOfDecoration ) )
decoration . type === typeOfDecoration &&
decoration . value . from !== plugin
) {
decorations . push (
convertToMonacoDecoration ( decoration . value , typeOfDecoration )
)
newRegisteredDecorations . push ( decoration )
newRegisteredDecorations . push ( decoration )
}
}
}
}
}
}
return {
return {
currentDecorations : model.deltaDecorations ( currentDecorations , decorations ) ,
currentDecorations : model.deltaDecorations (
currentDecorations ,
decorations
) ,
registeredDecorations : newRegisteredDecorations
registeredDecorations : newRegisteredDecorations
}
}
}
}
props . editorAPI . keepDecorationsFor = ( filePath : string , plugin : string , typeOfDecoration : string , registeredDecorations : any , currentDecorations : any ) = > {
props . editorAPI . keepDecorationsFor = (
filePath : string ,
plugin : string ,
typeOfDecoration : string ,
registeredDecorations : any ,
currentDecorations : any
) = > {
const model = editorModelsState [ filePath ] ? . model
const model = editorModelsState [ filePath ] ? . model
if ( ! model )
if ( ! model )
return {
return {
@ -443,37 +520,63 @@ export const EditorUI = (props: EditorUIProps) => {
if ( registeredDecorations ) {
if ( registeredDecorations ) {
for ( const decoration of registeredDecorations ) {
for ( const decoration of registeredDecorations ) {
if ( decoration . value . from === plugin ) {
if ( decoration . value . from === plugin ) {
decorations . push ( convertToMonacoDecoration ( decoration . value , typeOfDecoration ) )
decorations . push (
convertToMonacoDecoration ( decoration . value , typeOfDecoration )
)
}
}
}
}
}
}
return {
return {
currentDecorations : model.deltaDecorations ( currentDecorations , decorations )
currentDecorations : model.deltaDecorations (
currentDecorations ,
decorations
)
}
}
}
}
const addDecoration = ( decoration : sourceAnnotation | sourceMarker , filePath : string , typeOfDecoration : string ) = > {
const addDecoration = (
decoration : sourceAnnotation | sourceMarker ,
filePath : string ,
typeOfDecoration : string
) = > {
const model = editorModelsState [ filePath ] ? . model
const model = editorModelsState [ filePath ] ? . model
if ( ! model ) return { currentDecorations : [ ] }
if ( ! model ) return { currentDecorations : [ ] }
const monacoDecoration = convertToMonacoDecoration ( decoration , typeOfDecoration )
const monacoDecoration = convertToMonacoDecoration (
decoration ,
typeOfDecoration
)
return {
return {
currentDecorations : model.deltaDecorations ( [ ] , [ monacoDecoration ] ) ,
currentDecorations : model.deltaDecorations ( [ ] , [ monacoDecoration ] ) ,
registeredDecorations : [ { value : decoration , type : typeOfDecoration } ]
registeredDecorations : [ { value : decoration , type : typeOfDecoration } ]
}
}
}
}
props . editorAPI . addDecoration = ( marker : sourceMarker , filePath : string , typeOfDecoration : string ) = > {
props . editorAPI . addDecoration = (
marker : sourceMarker ,
filePath : string ,
typeOfDecoration : string
) = > {
return addDecoration ( marker , filePath , typeOfDecoration )
return addDecoration ( marker , filePath , typeOfDecoration )
}
}
props . editorAPI . addErrorMarker = async ( errors : errorMarker [ ] , from : string ) = > {
props . editorAPI . addErrorMarker = async (
const allMarkersPerfile : Record < string , Array < monacoTypes.editor.IMarkerData > > = { }
errors : errorMarker [ ] ,
from : string
) = > {
const allMarkersPerfile : Record <
string ,
Array < monacoTypes.editor.IMarkerData >
> = { }
for ( const error of errors ) {
for ( const error of errors ) {
let filePath = error . file
let filePath = error . file
if ( ! filePath ) return
if ( ! filePath ) return
const fileFromUrl = await props . plugin . call ( 'fileManager' , 'getPathFromUrl' , filePath )
const fileFromUrl = await props . plugin . call (
'fileManager' ,
'getPathFromUrl' ,
filePath
)
filePath = fileFromUrl . file
filePath = fileFromUrl . file
const model = editorModelsState [ filePath ] ? . model
const model = editorModelsState [ filePath ] ? . model
const errorServerityMap = {
const errorServerityMap = {
@ -483,9 +586,14 @@ export const EditorUI = (props: EditorUIProps) => {
}
}
if ( model ) {
if ( model ) {
const markerData : monacoTypes.editor.IMarkerData = {
const markerData : monacoTypes.editor.IMarkerData = {
severity : typeof error . severity === 'string' ? errorServerityMap [ error . severity ] : error . severity ,
severity :
startLineNumber : ( error . position . start && error . position . start . line ) || 0 ,
typeof error . severity === 'string'
startColumn : ( error . position . start && error . position . start . column ) || 0 ,
? errorServerityMap [ error . severity ]
: error . severity ,
startLineNumber :
( error . position . start && error . position . start . line ) || 0 ,
startColumn :
( error . position . start && error . position . start . column ) || 0 ,
endLineNumber : ( error . position . end && error . position . end . line ) || 0 ,
endLineNumber : ( error . position . end && error . position . end . line ) || 0 ,
endColumn : ( error . position . end && error . position . end . column ) || 0 ,
endColumn : ( error . position . end && error . position . end . column ) || 0 ,
message : error.message
message : error.message
@ -499,14 +607,23 @@ export const EditorUI = (props: EditorUIProps) => {
for ( const filePath in allMarkersPerfile ) {
for ( const filePath in allMarkersPerfile ) {
const model = editorModelsState [ filePath ] ? . model
const model = editorModelsState [ filePath ] ? . model
if ( model ) {
if ( model ) {
monacoRef . current . editor . setModelMarkers ( model , from , allMarkersPerfile [ filePath ] )
monacoRef . current . editor . setModelMarkers (
model ,
from ,
allMarkersPerfile [ filePath ]
)
}
}
}
}
}
}
props . editorAPI . clearErrorMarkers = async ( sources : string [ ] | { [ fileName : string ] : any } , from : string ) = > {
props . editorAPI . clearErrorMarkers = async (
sources : string [ ] | { [ fileName : string ] : any } ,
from : string
) = > {
if ( sources ) {
if ( sources ) {
for ( const source of Array . isArray ( sources ) ? sources : Object.keys ( sources ) ) {
for ( const source of Array . isArray ( sources )
? sources
: Object . keys ( sources ) ) {
const filePath = source
const filePath = source
const model = editorModelsState [ filePath ] ? . model
const model = editorModelsState [ filePath ] ? . model
if ( model ) {
if ( model ) {
@ -534,7 +651,9 @@ export const EditorUI = (props: EditorUIProps) => {
if ( ! monacoRef . current ) return
if ( ! monacoRef . current ) return
const model = editorModelsState [ currentFileRef . current ] ? . model
const model = editorModelsState [ currentFileRef . current ] ? . model
if ( model ) {
if ( model ) {
return offset ? model . getOffsetAt ( editorRef . current . getPosition ( ) ) : editorRef . current . getPosition ( )
return offset
? model . getOffsetAt ( editorRef . current . getPosition ( ) )
: editorRef . current . getPosition ( )
}
}
}
}
@ -550,8 +669,9 @@ export const EditorUI = (props: EditorUIProps) => {
props . editorAPI . getFontSize = ( ) = > {
props . editorAPI . getFontSize = ( ) = > {
if ( ! editorRef . current ) return
if ( ! editorRef . current ) return
return editorRef . current . getOption ( 43 ) . fontSize
return editorRef . current . getOption ( 51 )
}
}
props . editorAPI . getPositionAt = ( offset : number ) : IPosition = > {
props . editorAPI . getPositionAt = ( offset : number ) : IPosition = > {
return editorRef . current . getModel ( ) . getPositionAt ( offset )
return editorRef . current . getModel ( ) . getPositionAt ( offset )
}
}
@ -562,10 +682,15 @@ export const EditorUI = (props: EditorUIProps) => {
setCurrentBreakpoints ( ( prevState ) = > {
setCurrentBreakpoints ( ( prevState ) = > {
const currentFile = currentUrlRef . current
const currentFile = currentUrlRef . current
if ( ! prevState [ currentFile ] ) prevState [ currentFile ] = { }
if ( ! prevState [ currentFile ] ) prevState [ currentFile ] = { }
const decoration = Object . keys ( prevState [ currentFile ] ) . filter ( ( line ) = > parseInt ( line ) === position . lineNumber )
const decoration = Object . keys ( prevState [ currentFile ] ) . filter (
( line ) = > parseInt ( line ) === position . lineNumber
)
if ( decoration . length ) {
if ( decoration . length ) {
props . events . onBreakPointCleared ( currentFile , position . lineNumber )
props . events . onBreakPointCleared ( currentFile , position . lineNumber )
model . deltaDecorations ( [ prevState [ currentFile ] [ position . lineNumber ] ] , [ ] )
model . deltaDecorations (
[ prevState [ currentFile ] [ position . lineNumber ] ] ,
[ ]
)
delete prevState [ currentFile ] [ position . lineNumber ]
delete prevState [ currentFile ] [ position . lineNumber ]
} else {
} else {
props . events . onBreakPointAdded ( currentFile , position . lineNumber )
props . events . onBreakPointAdded ( currentFile , position . lineNumber )
@ -573,7 +698,12 @@ export const EditorUI = (props: EditorUIProps) => {
[ ] ,
[ ] ,
[
[
{
{
range : new monacoRef . current . Range ( position . lineNumber , 1 , position . lineNumber , 1 ) ,
range : new monacoRef . current . Range (
position . lineNumber ,
1 ,
position . lineNumber ,
1
) ,
options : {
options : {
isWholeLine : false ,
isWholeLine : false ,
glyphMarginClassName : 'fas fa-circle text-info'
glyphMarginClassName : 'fas fa-circle text-info'
@ -591,7 +721,13 @@ export const EditorUI = (props: EditorUIProps) => {
function handleEditorDidMount ( editor ) {
function handleEditorDidMount ( editor ) {
editorRef . current = editor
editorRef . current = editor
defineAndSetTheme ( monacoRef . current )
defineAndSetTheme ( monacoRef . current )
reducerListener ( props . plugin , dispatch , monacoRef . current , editorRef . current , props . events )
reducerListener (
props . plugin ,
dispatch ,
monacoRef . current ,
editorRef . current ,
props . events
)
props . events . onEditorMounted ( )
props . events . onEditorMounted ( )
editor . onMouseUp ( ( e ) = > {
editor . onMouseUp ( ( e ) = > {
// see https://microsoft.github.io/monaco-editor/typedoc/enums/editor.MouseTargetType.html
// see https://microsoft.github.io/monaco-editor/typedoc/enums/editor.MouseTargetType.html
@ -603,7 +739,14 @@ export const EditorUI = (props: EditorUIProps) => {
} )
} )
editor . onDidPaste ( ( e ) = > {
editor . onDidPaste ( ( e ) = > {
if ( ! pasteCodeRef . current && e && e . range && e . range . startLineNumber >= 0 && e . range . endLineNumber >= 0 && e . range . endLineNumber - e . range . startLineNumber > 10 ) {
if (
! pasteCodeRef . current &&
e &&
e . range &&
e . range . startLineNumber >= 0 &&
e . range . endLineNumber >= 0 &&
e . range . endLineNumber - e . range . startLineNumber > 10
) {
const modalContent : AlertModal = {
const modalContent : AlertModal = {
id : 'newCodePasted' ,
id : 'newCodePasted' ,
title : 'Pasted Code Alert' ,
title : 'Pasted Code Alert' ,
@ -613,16 +756,28 @@ export const EditorUI = (props: EditorUIProps) => {
< i className = "fas fa-exclamation-triangle text-danger mr-1" > < / i >
< i className = "fas fa-exclamation-triangle text-danger mr-1" > < / i >
You have just pasted a code snippet or contract in the editor .
You have just pasted a code snippet or contract in the editor .
< div >
< div >
Make sure you fully understand this code before deploying or interacting with it . Don ' t get scammed !
Make sure you fully understand this code before deploying or
interacting with it . Don ' t get scammed !
< div className = "mt-2" >
< div className = "mt-2" >
Running untrusted code can put your wallet < span className = "text-warning" > at risk < / span > . In a worst - case scenario , you could { ' ' }
Running untrusted code can put your wallet { ' ' }
< span className = "text-warning" > at risk < / span > . In a
worst - case scenario , you could { ' ' }
< span className = "text-warning" > lose all your money < / span > .
< span className = "text-warning" > lose all your money < / span > .
< / div >
< / div >
< div className = "text-warning mt-2" > If you don 't fully understand it, please don' t run this code . < / div >
< div className = "text-warning mt-2" >
< div className = "mt-2" > If you are not a smart contract developer , ask someone you trust who has the skills to determine if this code is safe to use . < / div >
If you don 't fully understand it, please don' t run this code .
< / div >
< div className = "mt-2" >
If you are not a smart contract developer , ask someone you
trust who has the skills to determine if this code is safe to
use .
< / div >
< div className = "mt-2" >
< div className = "mt-2" >
See { ' ' }
See { ' ' }
< a target = "_blank" href = "https://remix-ide.readthedocs.io/en/latest/security.html" >
< a
target = "_blank"
href = "https://remix-ide.readthedocs.io/en/latest/security.html"
>
{ ' ' }
{ ' ' }
these recommendations { ' ' }
these recommendations { ' ' }
< / a > { ' ' }
< / a > { ' ' }
@ -638,12 +793,20 @@ export const EditorUI = (props: EditorUIProps) => {
} )
} )
// zoomin zoomout
// zoomin zoomout
editor . addCommand ( monacoRef . current . KeyMod . CtrlCmd | ( monacoRef . current . KeyCode as any ) . US_EQUAL , ( ) = > {
editor . addCommand (
editor . updateOptions ( { fontSize : editor.getOption ( 43 ) . fontSize + 1 } )
monacoRef . current . KeyMod . CtrlCmd |
} )
( monacoRef . current . KeyCode as any ) . US_EQUAL ,
editor . addCommand ( monacoRef . current . KeyMod . CtrlCmd | ( monacoRef . current . KeyCode as any ) . US_MINUS , ( ) = > {
( ) = > {
editor . updateOptions ( { fontSize : editor.getOption ( 43 ) . fontSize - 1 } )
editor . updateOptions ( { fontSize : editor.getOption ( 51 ) + 1 } )
} )
}
)
editor . addCommand (
monacoRef . current . KeyMod . CtrlCmd |
( monacoRef . current . KeyCode as any ) . US_MINUS ,
( ) = > {
editor . updateOptions ( { fontSize : editor.getOption ( 51 ) - 1 } )
}
)
// add context menu items
// add context menu items
const zoominAction = {
const zoominAction = {
@ -656,7 +819,7 @@ export const EditorUI = (props: EditorUIProps) => {
monacoRef . current . KeyMod . CtrlCmd | monacoRef . current . KeyCode . Equal
monacoRef . current . KeyMod . CtrlCmd | monacoRef . current . KeyCode . Equal
] ,
] ,
run : ( ) = > {
run : ( ) = > {
editor . updateOptions ( { fontSize : editor.getOption ( 43 ) . fontSize + 1 } )
editor . updateOptions ( { fontSize : editor.getOption ( 51 ) + 1 } )
}
}
}
}
const zoomOutAction = {
const zoomOutAction = {
@ -669,7 +832,7 @@ export const EditorUI = (props: EditorUIProps) => {
monacoRef . current . KeyMod . CtrlCmd | monacoRef . current . KeyCode . Minus
monacoRef . current . KeyMod . CtrlCmd | monacoRef . current . KeyCode . Minus
] ,
] ,
run : ( ) = > {
run : ( ) = > {
editor . updateOptions ( { fontSize : editor.getOption ( 43 ) . fontSize - 1 } )
editor . updateOptions ( { fontSize : editor.getOption ( 51 ) - 1 } )
}
}
}
}
const formatAction = {
const formatAction = {
@ -679,7 +842,9 @@ export const EditorUI = (props: EditorUIProps) => {
contextMenuGroupId : 'formatting' , // create a new grouping
contextMenuGroupId : 'formatting' , // create a new grouping
keybindings : [
keybindings : [
// eslint-disable-next-line no-bitwise
// eslint-disable-next-line no-bitwise
monacoRef . current . KeyMod . Shift | monacoRef . current . KeyMod . Alt | monacoRef . current . KeyCode . KeyF
monacoRef . current . KeyMod . Shift |
monacoRef . current . KeyMod . Alt |
monacoRef . current . KeyCode . KeyF
] ,
] ,
run : async ( ) = > {
run : async ( ) = > {
const file = await props . plugin . call ( 'fileManager' , 'getCurrentFile' )
const file = await props . plugin . call ( 'fileManager' , 'getCurrentFile' )
@ -687,7 +852,10 @@ export const EditorUI = (props: EditorUIProps) => {
}
}
}
}
const freeFunctionCondition = editor . createContextKey ( 'freeFunctionCondition' , false )
const freeFunctionCondition = editor . createContextKey (
'freeFunctionCondition' ,
false
)
let freeFunctionAction
let freeFunctionAction
const executeFreeFunctionAction = {
const executeFreeFunctionAction = {
id : 'executeFreeFunction' ,
id : 'executeFreeFunction' ,
@ -697,21 +865,48 @@ export const EditorUI = (props: EditorUIProps) => {
precondition : 'freeFunctionCondition' ,
precondition : 'freeFunctionCondition' ,
keybindings : [
keybindings : [
// eslint-disable-next-line no-bitwise
// eslint-disable-next-line no-bitwise
monacoRef . current . KeyMod . Shift | monacoRef . current . KeyMod . Alt | monacoRef . current . KeyCode . KeyR
monacoRef . current . KeyMod . Shift |
monacoRef . current . KeyMod . Alt |
monacoRef . current . KeyCode . KeyR
] ,
] ,
run : async ( ) = > {
run : async ( ) = > {
const { nodesAtPosition } = await retrieveNodesAtPosition ( props . editorAPI , props . plugin )
const { nodesAtPosition } = await retrieveNodesAtPosition (
props . editorAPI ,
props . plugin
)
// find the contract and get the nodes of the contract and the base contracts and imports
// find the contract and get the nodes of the contract and the base contracts and imports
if ( nodesAtPosition && isArray ( nodesAtPosition ) && nodesAtPosition . length ) {
if (
const freeFunctionNode = nodesAtPosition . find ( ( node ) = > node . kind === 'freeFunction' )
nodesAtPosition &&
isArray ( nodesAtPosition ) &&
nodesAtPosition . length
) {
const freeFunctionNode = nodesAtPosition . find (
( node ) = > node . kind === 'freeFunction'
)
if ( freeFunctionNode ) {
if ( freeFunctionNode ) {
const file = await props . plugin . call ( 'fileManager' , 'getCurrentFile' )
const file = await props . plugin . call (
props . plugin . call ( 'solidity-script' , 'execute' , file , freeFunctionNode . name )
'fileManager' ,
'getCurrentFile'
)
props . plugin . call (
'solidity-script' ,
'execute' ,
file ,
freeFunctionNode . name
)
} else {
} else {
props . plugin . call ( 'notification' , 'toast' , 'This can only execute free function' )
props . plugin . call (
'notification' ,
'toast' ,
'This can only execute free function'
)
}
}
} else {
} else {
props . plugin . call ( 'notification' , 'toast' , 'Please go to Remix settings and activate the code editor features or wait that the current editor context is loaded.' )
props . plugin . call (
'notification' ,
'toast' ,
'Please go to Remix settings and activate the code editor features or wait that the current editor context is loaded.'
)
}
}
}
}
}
}
@ -721,7 +916,12 @@ export const EditorUI = (props: EditorUIProps) => {
freeFunctionAction = editor . addAction ( executeFreeFunctionAction )
freeFunctionAction = editor . addAction ( executeFreeFunctionAction )
// we have to add the command because the menu action isn't always available (see onContextMenuHandlerForFreeFunction)
// we have to add the command because the menu action isn't always available (see onContextMenuHandlerForFreeFunction)
editor . addCommand ( monacoRef . current . KeyMod . Shift | monacoRef . current . KeyMod . Alt | monacoRef . current . KeyCode . KeyR , ( ) = > executeFreeFunctionAction . run ( ) )
editor . addCommand (
monacoRef . current . KeyMod . Shift |
monacoRef . current . KeyMod . Alt |
monacoRef . current . KeyCode . KeyR ,
( ) = > executeFreeFunctionAction . run ( )
)
const contextmenu = editor . getContribution ( 'editor.contrib.contextmenu' )
const contextmenu = editor . getContribution ( 'editor.contrib.contextmenu' )
const orgContextMenuMethod = contextmenu . _onContextMenu
const orgContextMenuMethod = contextmenu . _onContextMenu
@ -735,8 +935,13 @@ export const EditorUI = (props: EditorUIProps) => {
freeFunctionCondition . set ( false )
freeFunctionCondition . set ( false )
return
return
}
}
const { nodesAtPosition } = await retrieveNodesAtPosition ( props . editorAPI , props . plugin )
const { nodesAtPosition } = await retrieveNodesAtPosition (
const freeFunctionNode = nodesAtPosition . find ( ( node ) = > node . kind === 'freeFunction' )
props . editorAPI ,
props . plugin
)
const freeFunctionNode = nodesAtPosition . find (
( node ) = > node . kind === 'freeFunction'
)
if ( freeFunctionNode ) {
if ( freeFunctionNode ) {
executeFreeFunctionAction . label = ` Run the free function " ${ freeFunctionNode . name } " in the Remix VM `
executeFreeFunctionAction . label = ` Run the free function " ${ freeFunctionNode . name } " in the Remix VM `
freeFunctionAction = editor . addAction ( executeFreeFunctionAction )
freeFunctionAction = editor . addAction ( executeFreeFunctionAction )
@ -786,27 +991,75 @@ export const EditorUI = (props: EditorUIProps) => {
monacoRef . current . languages . register ( { id : 'remix-circom' } )
monacoRef . current . languages . register ( { id : 'remix-circom' } )
// Register a tokens provider for the language
// Register a tokens provider for the language
monacoRef . current . languages . setMonarchTokensProvider ( 'remix-solidity' , solidityTokensProvider as any )
monacoRef . current . languages . setMonarchTokensProvider (
monacoRef . current . languages . setLanguageConfiguration ( 'remix-solidity' , solidityLanguageConfig as any )
'remix-solidity' ,
solidityTokensProvider as any
)
monacoRef . current . languages . setLanguageConfiguration (
'remix-solidity' ,
solidityLanguageConfig as any
)
monacoRef . current . languages . setMonarchTokensProvider ( 'remix-cairo' , cairoTokensProvider as any )
monacoRef . current . languages . setMonarchTokensProvider (
monacoRef . current . languages . setLanguageConfiguration ( 'remix-cairo' , cairoLanguageConfig as any )
'remix-cairo' ,
cairoTokensProvider as any
)
monacoRef . current . languages . setLanguageConfiguration (
'remix-cairo' ,
cairoLanguageConfig as any
)
monacoRef . current . languages . setMonarchTokensProvider ( 'remix-zokrates' , zokratesTokensProvider as any )
monacoRef . current . languages . setMonarchTokensProvider (
monacoRef . current . languages . setLanguageConfiguration ( 'remix-zokrates' , zokratesLanguageConfig as any )
'remix-zokrates' ,
zokratesTokensProvider as any
)
monacoRef . current . languages . setLanguageConfiguration (
'remix-zokrates' ,
zokratesLanguageConfig as any
)
monacoRef . current . languages . setMonarchTokensProvider ( 'remix-move' , moveTokenProvider as any )
monacoRef . current . languages . setMonarchTokensProvider (
monacoRef . current . languages . setLanguageConfiguration ( 'remix-move' , moveLanguageConfig as any )
'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 . setMonarchTokensProvider (
monacoRef . current . languages . setLanguageConfiguration ( 'remix-circom' , circomLanguageConfig ( monacoRef . current ) as any )
'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 . registerDefinitionProvider (
monacoRef . current . languages . registerDocumentHighlightProvider ( 'remix-solidity' , new RemixHighLightProvider ( props , monaco ) )
'remix-solidity' ,
monacoRef . current . languages . registerReferenceProvider ( 'remix-solidity' , new RemixReferenceProvider ( props , monaco ) )
new RemixDefinitionProvider ( props , monaco )
monacoRef . current . languages . registerHoverProvider ( 'remix-solidity' , new RemixHoverProvider ( props , monaco ) )
)
monacoRef . current . languages . registerCompletionItemProvider ( 'remix-solidity' , new RemixCompletionProvider ( props , monaco ) )
monacoRef . current . languages . registerDocumentHighlightProvider (
monaco . languages . registerCodeActionProvider ( 'remix-solidity' , new RemixCodeActionProvider ( props , monaco ) )
'remix-solidity' ,
new RemixHighLightProvider ( props , monaco )
)
monacoRef . current . languages . registerReferenceProvider (
'remix-solidity' ,
new RemixReferenceProvider ( props , monaco )
)
monacoRef . current . languages . registerHoverProvider (
'remix-solidity' ,
new RemixHoverProvider ( props , monaco )
)
monacoRef . current . languages . registerCompletionItemProvider (
'remix-solidity' ,
new RemixCompletionProvider ( props , monaco )
)
monaco . languages . registerCodeActionProvider (
'remix-solidity' ,
new RemixCodeActionProvider ( props , monaco )
)
loadTypes ( monacoRef . current )
loadTypes ( monacoRef . current )
}
}
@ -816,12 +1069,18 @@ export const EditorUI = (props: EditorUIProps) => {
< Editor
< Editor
width = "100%"
width = "100%"
path = { props . currentFile }
path = { props . currentFile }
language = { editorModelsState [ props . currentFile ] ? editorModelsState [ props . currentFile ] . language : 'text' }
language = {
editorModelsState [ props . currentFile ]
? editorModelsState [ props . currentFile ] . language
: 'text'
}
onMount = { handleEditorDidMount }
onMount = { handleEditorDidMount }
beforeMount = { handleEditorWillMount }
beforeMount = { handleEditorWillMount }
options = { {
options = { {
glyphMargin : true ,
glyphMargin : true ,
readOnly : ( ! editorRef . current || ! props . currentFile ) && editorModelsState [ props . currentFile ] ? . readOnly
readOnly :
( ! editorRef . current || ! props . currentFile ) &&
editorModelsState [ props . currentFile ] ? . readOnly
} }
} }
defaultValue = { defaultEditorValue }
defaultValue = { defaultEditorValue }
/ >
/ >