diff --git a/src/app.js b/src/app.js index 0fb711af02..7877862bb8 100644 --- a/src/app.js +++ b/src/app.js @@ -155,6 +155,7 @@ class App { self._components = {} self._components.compilerImport = new CompilerImport() registry.put({api: self._components.compilerImport, name: 'compilerimport'}) + self._components.gistHandler = new GistHandler() self.data = { _layout: { right: { @@ -252,6 +253,66 @@ class App { } } } + startdebugging (txHash) { + const self = this + self.event.trigger('debuggingRequested', []) + self._view.transactionDebugger.debug(txHash) + } + loadFromGist (gistId) { + const self = this + return self._components.gistHandler.handleLoad(gistId, function (gistId) { + request.get({ + url: `https://api.github.com/gists/${gistId}`, + json: true + }, (error, response, data = {}) => { + if (error || !data.files) { + modalDialogCustom.alert(`Gist load error: ${error || data.message}`) + return + } + self.loadFiles(data.files, 'gist', (errorLoadingFile) => { + if (!errorLoadingFile) self._api.filesProviders['gist'].id = gistId + }) + }) + }) + } + loadFiles (filesSet, fileProvider, callback) { + const self = this + if (!fileProvider) fileProvider = 'browser' + + async.each(Object.keys(filesSet), (file, callback) => { + helper.createNonClashingName(file, self._api.filesProviders[fileProvider], + (error, name) => { + if (error) { + modalDialogCustom.alert('Unexpected error loading the file ' + error) + } else if (helper.checkSpecialChars(name)) { + modalDialogCustom.alert('Special characters are not allowed') + } else { + self._api.filesProviders[fileProvider].set(name, filesSet[file].content) + } + callback() + }) + }, (error) => { + if (!error) self._components.fileManager.switchFile() + if (callback) callback(error) + }) + } + importExternal (url, cb) { + const self = this + self._components.compilerImport.import(url, + (loadingMsg) => { + toolTip(loadingMsg) + }, + (error, content, cleanUrl, type, url) => { + if (!error) { + if (self._api.filesProviders[type]) { + self._api.filesProviders[type].addReadOnly(cleanUrl, content, url) + } + cb(null, content) + } else { + cb(error) + } + }) + } } module.exports = App @@ -291,23 +352,6 @@ Please make a backup of your contracts and start using http://remix.ethereum.org } }) - function importExternal (url, cb) { - self._components.compilerImport.import(url, - (loadingMsg) => { - toolTip(loadingMsg) - }, - (error, content, cleanUrl, type, url) => { - if (!error) { - if (filesProviders[type]) { - filesProviders[type].addReadOnly(cleanUrl, content, url) - } - cb(null, content) - } else { - cb(error) - } - }) - } - function importFileCb (url, filecb) { if (url.indexOf('/remix_tests.sol') !== -1) { return filecb(null, remixTests.assertLibCode) @@ -319,7 +363,7 @@ Please make a backup of your contracts and start using http://remix.ethereum.org if (exist) { return provider.get(url, filecb) } else { - importExternal(url, filecb) + self.importExternal(url, filecb) } }) } else if (self._components.compilerImport.isRelativeImport(url)) { @@ -333,7 +377,7 @@ Please make a backup of your contracts and start using http://remix.ethereum.org (error, result) => { filecb(error, result) } ) } else { - importExternal(url, filecb) + self.importExternal(url, filecb) } } @@ -386,7 +430,7 @@ Please make a backup of your contracts and start using http://remix.ethereum.org udapp.reset({}) udappUI.reset() udapp.event.register('debugRequested', this, function (txResult) { - startdebugging(txResult.transactionHash) + self.startdebugging(txResult.transactionHash) }) // ----------------- Tx listener ----------------- @@ -419,7 +463,12 @@ Please make a backup of your contracts and start using http://remix.ethereum.org }) registry.put({api: eventsDecoder, name: 'eventsDecoder'}) - txlistener.startListening() + txlistener.startListening() + + // ----------------- editor ---------------------------- + this._components.editor = new Editor({}) // @TODO: put into editorpanel + var editor = self._components.editor // shortcut for the editor + registry.put({api: editor, name: 'editor'}) // ----------------- Command Interpreter ----------------- /* @@ -427,71 +476,8 @@ Please make a backup of your contracts and start using http://remix.ethereum.org and interpret them as commands */ var cmdInterpreter = new CommandInterpreter() - cmdInterpreter.event.register('debug', (hash, cb) => { - startdebugging(hash) - if (cb) cb() - }) - cmdInterpreter.event.register('loadgist', (id, cb) => { - loadFromGist({gist: id}) - if (cb) cb() - }) - cmdInterpreter.event.register('loadurl', (url, cb) => { - importExternal(url, (err, content) => { - if (err) { - toolTip(`Unable to load ${url} from swarm: ${err}`) - if (cb) cb(err) - } else { - try { - content = JSON.parse(content) - async.eachOfSeries(content.sources, (value, file, callbackSource) => { - var url = value.urls[0] // @TODO retrieve all other contents ? - importExternal(url, (error, content) => { - if (error) { - toolTip(`Cannot retrieve the content of ${url}: ${error}`) - } - callbackSource() - }) - }, (error) => { - if (cb) cb(error) - }) - } catch (e) {} - if (cb) cb() - } - }) - }) - cmdInterpreter.event.register('setproviderurl', (url, cb) => { - executionContext.setProviderFromEndpoint(url, 'web3', (error) => { - if (error) toolTip(error) - if (cb) cb() - }) - }) - cmdInterpreter.event.register('batch', (url, cb) => { - var content = editor.get(editor.current()) - if (!content) { - toolTip('no content to execute') - if (cb) cb() - return - } - var split = content.split('\n') - async.eachSeries(split, (value, cb) => { - if (!cmdInterpreter.interpret(value, (error) => { - error ? cb(`Cannot run ${value}. stopping`) : cb() - })) { - cb(`Cannot interpret ${value}. stopping`) - } - }, (error) => { - if (error) toolTip(error) - if (cb) cb() - }) - }) registry.put({api: cmdInterpreter, name: 'cmdinterpreter'}) - - // ----------------- editor ---------------------------- - this._components.editor = new Editor({}) // @TODO: put into editorpanel - var editor = self._components.editor // shortcut for the editor - registry.put({api: editor, name: 'editor'}) - var config = self._api.config var filesProviders = self._api.filesProviders @@ -517,7 +503,6 @@ Please make a backup of your contracts and start using http://remix.ethereum.org this._view.centerpanel.appendChild(this._components.editorpanel.render()) var queryParams = new QueryParams() - var gistHandler = new GistHandler() // The event listener needs to be registered as early as possible, because the // parent will send the message upon the "load" event. @@ -532,57 +517,17 @@ Please make a backup of your contracts and start using http://remix.ethereum.org this.event = new EventManager() - // Add files received from remote instance (i.e. another remix-ide) - function loadFiles (filesSet, fileProvider, callback) { - if (!fileProvider) fileProvider = 'browser' - - async.each(Object.keys(filesSet), (file, callback) => { - helper.createNonClashingName(file, filesProviders[fileProvider], - (error, name) => { - if (error) { - modalDialogCustom.alert('Unexpected error loading the file ' + error) - } else if (helper.checkSpecialChars(name)) { - modalDialogCustom.alert('Special characters are not allowed') - } else { - filesProviders[fileProvider].set(name, filesSet[file].content) - } - callback() - }) - }, (error) => { - if (!error) fileManager.switchFile() - if (callback) callback(error) - }) - } - // Replace early callback with instant response loadFilesCallback = function (files) { - loadFiles(files) + self.loadFiles(files) } // Run if we did receive an event from remote instance while starting up if (filesToLoad !== null) { - loadFiles(filesToLoad) - } - - // ------------------ gist load ---------------- - function loadFromGist (gistId) { - return gistHandler.handleLoad(gistId, function (gistId) { - request.get({ - url: `https://api.github.com/gists/${gistId}`, - json: true - }, (error, response, data = {}) => { - if (error || !data.files) { - modalDialogCustom.alert(`Gist load error: ${error || data.message}`) - return - } - loadFiles(data.files, 'gist', (errorLoadingFile) => { - if (!errorLoadingFile) filesProviders['gist'].id = gistId - }) - }) - }) + self.loadFiles(filesToLoad) } - var loadingFromGist = loadFromGist(queryParams.get()) + var loadingFromGist = self.loadFromGist(queryParams.get()) // insert ballot contract if there are no files available if (!loadingFromGist) { @@ -745,7 +690,7 @@ Please make a backup of your contracts and start using http://remix.ethereum.org }) txLogger.event.register('debugRequested', (hash) => { - startdebugging(hash) + self.startdebugging(hash) }) var previousInput = '' @@ -812,12 +757,7 @@ Please make a backup of your contracts and start using http://remix.ethereum.org } if (queryParams.get().debugtx) { - startdebugging(queryParams.get().debugtx) + self.startdebugging(queryParams.get().debugtx) } }) - - function startdebugging (txHash) { - self.event.trigger('debuggingRequested', []) - self._view.transactionDebugger.debug(txHash) - } } diff --git a/src/lib/cmdInterpreter.js b/src/lib/cmdInterpreter.js index 8aa8d285be..327cd8bcf0 100644 --- a/src/lib/cmdInterpreter.js +++ b/src/lib/cmdInterpreter.js @@ -2,9 +2,12 @@ var remixLib = require('remix-lib') var EventManager = remixLib.EventManager +var CommandInterpreterAPI = require('./cmdInterpreterAPI') + class CmdInterpreter { - constructor () { + constructor (api) { this.event = new EventManager() + this.api = new CommandInterpreterAPI(this) } interpret (cmd, cb) { if (!cmd) return false @@ -12,7 +15,7 @@ class CmdInterpreter { if (accept) { var param = accept[2] if (param) param = param.trim() - this.event.trigger(accept[1], [param, cb]) + this.api[accept[1]](param, cb) return accept[1] } return null diff --git a/src/lib/cmdInterpreterAPI.js b/src/lib/cmdInterpreterAPI.js new file mode 100644 index 0000000000..bea077d136 --- /dev/null +++ b/src/lib/cmdInterpreterAPI.js @@ -0,0 +1,85 @@ +'use strict' +var async = require('async') +var remixLib = require('remix-lib') +var EventManager = remixLib.EventManager + +var executionContext = require('../execution-context') +var toolTip = require('../app/ui/tooltip') +var globalRegistry = require('../global/registry') + +class CmdInterpreterAPI { + constructor (cmdInterpreter, localRegistry) { + const self = this + self.event = new EventManager() + self._components = {} + self._components.registry = localRegistry || globalRegistry + self._components.cmdInterpreter = cmdInterpreter + self._deps = { + app: self._components.registry.get('app').api, + editor: self._components.registry.get('editor').api + } + } + debug (hash, cb) { + const self = this + self._deps.app.startdebugging(hash) + if (cb) cb() + } + loadgist (id, cb) { + const self = this + self._deps.app.loadFromGist({gist: id}) + if (cb) cb() + } + loadurl (url, cb) { + const self = this + self._deps.app.importExternal(url, (err, content) => { + if (err) { + toolTip(`Unable to load ${url} from swarm: ${err}`) + if (cb) cb(err) + } else { + try { + content = JSON.parse(content) + async.eachOfSeries(content.sources, (value, file, callbackSource) => { + var url = value.urls[0] // @TODO retrieve all other contents ? + self._deps.app.importExternal(url, (error, content) => { + if (error) { + toolTip(`Cannot retrieve the content of ${url}: ${error}`) + } + callbackSource() + }) + }, (error) => { + if (cb) cb(error) + }) + } catch (e) {} + if (cb) cb() + } + }) + } + setproviderurl (url, cb) { + executionContext.setProviderFromEndpoint(url, 'web3', (error) => { + if (error) toolTip(error) + if (cb) cb() + }) + } + batch (url, cb) { + const self = this + var content = self._deps.editor.currentContent() + if (!content) { + toolTip('no content to execute') + if (cb) cb() + return + } + var split = content.split('\n') + async.eachSeries(split, (value, cb) => { + if (!self._components.cmdInterpreter.interpret(value, (error) => { + error ? cb(`Cannot run ${value}. stopping`) : cb() + })) { + cb(`Cannot interpret ${value}. stopping`) + } + }, (error) => { + if (error) toolTip(error) + if (cb) cb() + }) + } +} + +module.exports = CmdInterpreterAPI