diff --git a/.gitignore b/.gitignore
index d0429e2909..d35a9539a0 100644
--- a/.gitignore
+++ b/.gitignore
@@ -30,6 +30,7 @@ soljson.js
*.launch
.settings/
*.sublime-workspace
+.vscode/
# IDE - VSCode
.vscode/*
diff --git a/apps/remix-ide/src/app/panels/terminal.js b/apps/remix-ide/src/app/panels/terminal.js
index 95bca9da9a..eb67e15e55 100644
--- a/apps/remix-ide/src/app/panels/terminal.js
+++ b/apps/remix-ide/src/app/panels/terminal.js
@@ -69,26 +69,6 @@ class Terminal extends Plugin {
this._INDEX.allMain = []
this._INDEX.commands = {}
this._INDEX.commandsMain = {}
- this.registerCommand('html', this._blocksRenderer('html'), { activate: true })
- this.registerCommand('log', this._blocksRenderer('log'), { activate: true })
- this.registerCommand('info', this._blocksRenderer('info'), { activate: true })
- this.registerCommand('warn', this._blocksRenderer('warn'), { activate: true })
- this.registerCommand('error', this._blocksRenderer('error'), { activate: true })
- this.registerCommand('script', function execute (args, scopedCommands, append) {
- var script = String(args[0])
- this._shell(script, scopedCommands, function (error, output) {
- if (error) scopedCommands.error(error)
- else if (output) scopedCommands.log(output)
- })
- }, { activate: true })
- function basicFilter (value, query) { try { return value.indexOf(query) !== -1 } catch (e) { return false } }
-
- this.registerFilter('log', basicFilter)
- this.registerFilter('info', basicFilter)
- this.registerFilter('warn', basicFilter)
- this.registerFilter('error', basicFilter)
- this.registerFilter('script', basicFilter)
-
if (opts.shell) this._shell = opts.shell // ???
register(this)
}
@@ -109,12 +89,18 @@ class Terminal extends Plugin {
this.renderComponent()
}
+ onDeactivation () {
+ this.off('scriptRunner', 'log')
+ this.off('scriptRunner', 'info')
+ this.off('scriptRunner', 'warn')
+ this.off('scriptRunner', 'error')
+ }
+
render () {
return this.element
}
renderComponent () {
-
ReactDOM.render(
,
this.element
)
@@ -213,6 +200,8 @@ class Terminal extends Plugin {
if (self._commands[name]) throw new Error(`command "${name}" exists already`)
if (typeof command !== 'function') throw new Error(`invalid command: ${command}`)
self._commands[name] = command
+ console.log({ command })
+ console.log(self._commands)
self._INDEX.commands[name] = []
self._INDEX.commandsMain[name] = []
self.commands[name] = function _command () {
diff --git a/libs/remix-ui/terminal/src/lib/actions/terminalAction.ts b/libs/remix-ui/terminal/src/lib/actions/terminalAction.ts
index e69de29bb2..4e14ac46c8 100644
--- a/libs/remix-ui/terminal/src/lib/actions/terminalAction.ts
+++ b/libs/remix-ui/terminal/src/lib/actions/terminalAction.ts
@@ -0,0 +1,103 @@
+
+export const registerCommandAction = (name, command, activate, dispatch) => {
+ const commands: any = {}
+ const _commands: any = {}
+ _commands[name] = command
+ const data: any = {
+ // lineLength: props.options.lineLength || 80,
+ session: [],
+ activeFilters: { commands: {}, input: '' },
+ filterFns: {}
+ }
+ const _INDEX = {
+ all: [],
+ allMain: [],
+ commands: {},
+ commandsMain: {}
+ }
+
+ const registerFilter = (commandName, filterFn) => {
+ data.filterFns[commandName] = filterFn
+ }
+
+ // const _appendItem = (item) => {
+ // var { el, gidx } = item
+ // _JOURNAL[gidx] = item
+ // if (!_jobs.length) {
+ // requestAnimationFrame(function updateTerminal () {
+ // _jobs.forEach(el => _view.journal.appendChild(el))
+ // .scroll2bottom()
+ // ._jobs = []
+ // })
+ // }
+ // if (data.activeFilters.commands[item.cmd]) _jobs.push(el)
+ // }
+
+ commands[name] = function () {
+ const args = [...arguments]
+ const steps = []
+ const root = { steps, cmd: name, gidx: 0, idx: 0 }
+ const ITEM = { root, cmd: name }
+ root.gidx = _INDEX.allMain.push(ITEM) - 1
+ // root.idx = _INDEX.commandsMain[name].push(ITEM) - 1
+ let item
+ function append (cmd, params, el) {
+ if (cmd) { // subcommand
+ item = { el, cmd, root }
+ } else { // command
+ item = ITEM
+ item.el = el
+ cmd = name
+ }
+ item.gidx = _INDEX.all.push(item) - 1
+ item.idx = _INDEX.commands[cmd].push(item) - 1
+ item.step = steps.push(item) - 1
+ item.args = params
+ // _appendItem(item)
+ console.log({ item }, 'append items')
+ // self._appendItem(item)
+ }
+ var scopedCommands = _scopeCommands(append)
+ command(args, scopedCommands, el => append(null, args, blockify(el)))
+ console.log({ args })
+ }
+ const help = typeof command.help === 'string' ? command.help : [
+ '// no help available for:', `terminal.command.${name}`
+ ].join('\n')
+ commands[name].toString = () => { return help }
+ commands[name].help = help
+ data.activeFilters.commands[name] = activate && activate.activate
+ if (activate.filterFn) {
+ registerFilter(name, activate.filterFn)
+ }
+ dispatch({ type: name, payload: { commands: commands, _commands: _commands, data: data } })
+
+ const blockify = (el) => {
+ return `
${el}
`
+ }
+
+ const _scopeCommands = (append) => {
+ const scopedCommands = {}
+ Object.keys(commands).forEach(function makeScopedCommand (cmd) {
+ var command = _commands[cmd]
+ scopedCommands[cmd] = function _command () {
+ var args = [...arguments]
+ console.log({ cmd }, { args }, { blockify })
+ command(args, scopedCommands, el => append(cmd, args, blockify(el)))
+ }
+ })
+ console.log({ scopedCommands })
+ return scopedCommands
+ }
+
+}
+
+export const filterFnAction = (name, filterFn, dispatch) => {
+ const data: any = {
+ // session: [],
+ // activeFilters: { commands: {}, input: '' },
+ filterFns: {}
+ }
+ data.filterFns[name] = filterFn
+ dispatch({ type: name, payload: { data: data } })
+}
diff --git a/libs/remix-ui/terminal/src/lib/reducers/terminalReducer.ts b/libs/remix-ui/terminal/src/lib/reducers/terminalReducer.ts
index e69de29bb2..43fae4b344 100644
--- a/libs/remix-ui/terminal/src/lib/reducers/terminalReducer.ts
+++ b/libs/remix-ui/terminal/src/lib/reducers/terminalReducer.ts
@@ -0,0 +1,120 @@
+export const initialState = {
+ journalBlocks: {
+ },
+ data: {
+ // lineLength: props.options.lineLength || 80,
+ session: [],
+ activeFilters: { commands: {}, input: '' },
+ filterFns: {}
+ },
+ _commandHistory: [],
+ _commands: {},
+ commands: {},
+ _JOURNAL: [],
+ _jobs: [],
+ _INDEX: {
+ },
+ _INDEXall: [],
+ _INDEXallMain: [],
+ _INDEXcommands: {},
+ _INDEXcommandsMain: {}
+}
+
+export const registerCommandReducer = (state, action) => {
+ switch (action.type) {
+ case 'html' :
+ return {
+ ...state,
+ _commands: Object.assign(initialState._commands, action.payload._commands),
+ commands: Object.assign(initialState.commands, action.payload.commands),
+ data: Object.assign(initialState.data, { ...action.payload.data })
+ }
+ case 'log':
+ return {
+ ...state,
+ _commands: Object.assign(initialState._commands, action.payload._commands),
+ commands: Object.assign(initialState.commands, action.payload.commands),
+ data: Object.assign(initialState.data, { ...action.payload.data })
+
+ }
+ case 'info':
+ return {
+ ...state,
+ _commands: Object.assign(initialState._commands, action.payload._commands),
+ commands: Object.assign(initialState.commands, action.payload.commands),
+ data: Object.assign(initialState.data, action.payload.data)
+ }
+ case 'warn':
+ return {
+ ...state,
+ _commands: Object.assign(initialState._commands, action.payload._commands),
+ commands: Object.assign(initialState.commands, action.payload.commands),
+ data: Object.assign(initialState.data, action.payload.data)
+ }
+ case 'error':
+ return {
+ ...state,
+ _commands: Object.assign(initialState._commands, action.payload._commands),
+ commands: Object.assign(initialState.commands, action.payload.commands),
+ data: Object.assign(initialState.data, action.payload.data)
+ }
+ case 'script':
+ return {
+ ...state,
+ _commands: Object.assign(initialState._commands, action.payload._commands),
+ commands: Object.assign(initialState.commands, action.payload.commands),
+ data: Object.assign(initialState.data, action.payload.data)
+ }
+ default :
+ return { state }
+ }
+}
+
+export const registerFilterReducer = (state, action) => {
+ switch (action.type) {
+ case 'log':
+ console.log({ action }, { state }, 'register Filter')
+ return {
+ ...state,
+ data: Object.assign(initialState.data.filterFns, action.payload.data.filterFns)
+
+ }
+ case 'info':
+ console.log({ action }, 'registerFilter')
+ return {
+ ...state,
+ data: Object.assign(initialState.data.filterFns, action.payload.data.filterFns)
+ }
+ case 'warn':
+ return {
+ ...state,
+ data: Object.assign(initialState.data.filterFns, action.payload.data.filterFns)
+ }
+ case 'error':
+ return {
+ ...state,
+ data: Object.assign(initialState.data.filterFns, action.payload.data.filterFns)
+ }
+ case 'script':
+ return {
+ ...state,
+ data: Object.assign(initialState.data.filterFns, action.payload.data.filterFns)
+ }
+ default :
+ return { state }
+ }
+}
+
+export const addCommandHistoryReducer = (state, action) => {
+ switch (action.type) {
+ case 'cmdHistory':
+ console.log({ action }, { state }, 'cmd history')
+ return {
+ ...state,
+ _commandHistory: initialState._commandHistory.unshift(action.payload.script)
+
+ }
+ default :
+ return { state }
+ }
+}
diff --git a/libs/remix-ui/terminal/src/lib/remix-ui-terminal.tsx b/libs/remix-ui/terminal/src/lib/remix-ui-terminal.tsx
index 185ab2843f..9f2f421b09 100644
--- a/libs/remix-ui/terminal/src/lib/remix-ui-terminal.tsx
+++ b/libs/remix-ui/terminal/src/lib/remix-ui-terminal.tsx
@@ -1,6 +1,10 @@
-import React, { useState, useEffect, useRef, SyntheticEvent, MouseEvent } from 'react' // eslint-disable-line
+import React, { useState, useEffect, useReducer, useRef, SyntheticEvent, MouseEvent } from 'react' // eslint-disable-line
import { useKeyPress } from './custom-hooks/useKeyPress' // eslint-disable-line
import { useWindowResize } from 'beautiful-react-hooks'
+import { registerCommandAction, filterFnAction } from './actions/terminalAction'
+import { initialState, registerCommandReducer, registerFilterReducer, addCommandHistoryReducer } from './reducers/terminalReducer'
+import javascriptserialize from 'javascript-serialize'
+import jsbeautify from 'js-beautify'
import './remix-ui-terminal.css'
@@ -15,10 +19,10 @@ export interface RemixUiTerminalProps {
options: any
data: any
cmdInterpreter: any
- registerCommand: any
command: any
version: any
config: any
+ thisState: any
// blockRenderHtml: any
// blockRenderLog: any
@@ -44,6 +48,10 @@ export const RemixUiTerminal = (props: RemixUiTerminalProps) => {
const [separatorYPosition, setSeparatorYPosition] = useState(undefined)
const [dragging, setDragging] = useState(false)
+ const [newstate, dispatch] = useReducer(registerCommandReducer, initialState)
+ const [filterState, filterDispatch] = useReducer(registerFilterReducer, initialState)
+ const [cmdHistory, cmdHistoryDispatch] = useReducer(addCommandHistoryReducer, initialState)
+
const [state, setState] = useState({
journalBlocks: {
intro: (
@@ -102,16 +110,27 @@ export const RemixUiTerminal = (props: RemixUiTerminalProps) => {
const inputEl = useRef(null)
// events
useEffect(() => {
- // window.addEventListener('resize', function () {
- // props.event.trigger('resize', [])
- // props.event.trigger('resize', [])
- // })
- // return () => {
- // window.removeEventListener('resize', function () {
- // props.event.trigger('resize', [])
- // props.event.trigger('resize', [])
- // })
- // }
+ registerCommandAction('html', _blocksRenderer('html'), { activate: true }, dispatch)
+ registerCommandAction('log', _blocksRenderer('log'), { activate: true }, dispatch)
+ registerCommandAction('info', _blocksRenderer('info'), { activate: true }, dispatch)
+ registerCommandAction('warn', _blocksRenderer('warn'), { activate: true }, dispatch)
+ registerCommandAction('error', _blocksRenderer('error'), { activate: true }, dispatch)
+ registerCommandAction('script', function execute (args, scopedCommands, append) {
+ var script = String(args[0])
+ props.thisState._shell(script, scopedCommands, function (error, output) {
+ if (error) scopedCommands.error(error)
+ else if (output) scopedCommands.log(output)
+ })
+ }, { activate: true }, dispatch)
+ filterFnAction('log', basicFilter, filterDispatch)
+ filterFnAction('info', basicFilter, filterDispatch)
+ filterFnAction('warn', basicFilter, filterDispatch)
+ filterFnAction('error', basicFilter, filterDispatch)
+ filterFnAction('script', basicFilter, filterDispatch)
+ // console.log({ htmlresullt }, { logresult })
+ // dispatch({ type: 'html', payload: { commands: htmlresullt.commands } })
+ // dispatch({ type: 'log', payload: { _commands: logresult._commands } })
+ // registerCommand('log', _blocksRenderer('log'), { activate: true })
}, [])
const placeCaretAtEnd = (el) => {
@@ -157,56 +176,6 @@ export const RemixUiTerminal = (props: RemixUiTerminalProps) => {
}
}
- // const reattached = (event) => {
- // let el = event.currentTarget
- // var isBottomed = el.scrollHeight - el.scrollTop - el.clientHeight < 30
- // if (isBottomed) {
-
- // } else {
- // // if (!inserted)
- // }
- // }
-
- const registerCommand = (name, command, opts) => {
- const { _commands, _INDEXcommands, _INDEXallMain, _INDEXcommandsMain, _INDEXall, commands } = state
- // TODO if no _commands[name] throw an error
-
- // TODO if typeof command !== 'function' throw error
-
- _commands[name] = command
- _INDEXcommands[name] = []
- _INDEXallMain[name] = []
-
- // TODO _command function goes here
- commands[name] = function _command () {
- const steps = []
- const args = [...arguments]
- const gidx = 0
- const idx = 0
- const step = 0
- const root = { steps, cmd: name, gidx, idx }
- const ITEM = { root, cmd: name, el: {} }
- root.gidx = _INDEXallMain.push(ITEM) - 1
- root.idx = _INDEXcommandsMain[name].push(ITEM) - 1
- function append (cmd, params, el) {
- let item = { el, cmd, root, gidx, idx, step, args: [...arguments] }
- if (cmd) {
- item = { el, cmd, root, gidx, idx, step, args }
- } else {
- // item = ITEM
- item.el = el
- cmd = name
- }
- item.gidx = _INDEXall.push(item) - 1
- item.idx = _INDEXcommands[cmd].push(item) - 1
- item.step = steps.push(item) - 1
- item.args = params
- _appendItem(item)
- }
- }
-
- return commands[name]
- }
const _appendItem = (item: any) => {
let { _JOURNAL, _jobs, data } = state
@@ -259,16 +228,17 @@ export const RemixUiTerminal = (props: RemixUiTerminalProps) => {
const isKnownScript = ['remix.', 'git'].some(prefix => script.trim().startsWith(prefix))
if (isKnownScript) return script
return `
- try {
- const ret = ${script};
- if (ret instanceof Promise) {
- ret.then((result) => { console.log(result) }).catch((error) => { console.log(error) })
- } else {
- console.log(ret)
- }
- } catch (e) {
- console.log(e.message)
- }`
+ try {
+ const ret = ${script};
+ if (ret instanceof Promise) {
+ ret.then((result) => { console.log(result) }).catch((error) => { console.log(error) })
+ } else {
+ console.log(ret)
+ }
+ } catch (e) {
+ console.log(e.message)
+ }
+ `
}
const handleKeyDown = (event) => {
@@ -289,10 +259,16 @@ export const RemixUiTerminal = (props: RemixUiTerminalProps) => {
// scroll2botton () function not implemented
props.autoCompletePopup.removeAutoComplete()
} else { //
+ console.log('hit enter')
setCmdIndex(-1)
setCmdTemp('')
const script = inputEl.current.innerText.trim()
console.log({ script }, ' script ')
+ if (script.length) {
+ cmdHistoryDispatch({ type: 'cmdHistory', payload: { script } })
+ const result = newstate.commands.script(wrapScript(script))
+ console.log({ result })
+ }
// inputEl.current.innerText += '\n'
// if (script.length) {
// // self._cmdHistory.unshift(script)
@@ -417,9 +393,58 @@ export const RemixUiTerminal = (props: RemixUiTerminalProps) => {
}
}, [leftHeight, setLeftHeight])
+ /* block contents that gets rendered from scriptRunner */
+
+ const _blocksRenderer = (mode) => {
+ if (mode === 'html') {
+ return function logger (args) {
+ console.log({ args })
+ if (args.length) {
+ return args[0]
+ }
+ }
+ }
+ mode = {
+ log: 'text-info',
+ info: 'text-info',
+ warn: 'text-warning',
+ error: 'text-danger'
+ }[mode] // defaults
+
+ if (mode) {
+ const filterUndefined = (el) => el !== undefined && el !== null
+ return function logger (args) {
+ var types = args.filter(filterUndefined).map(type => type)
+ var values = javascriptserialize.apply(null, args.filter(filterUndefined)).map(function (val, idx) {
+ if (typeof args[idx] === 'string') {
+ const el = document.createElement('div')
+ el.innerHTML = args[idx].replace(/(\r\n|\n|\r)/gm, '
')
+ val = el.children.length === 0 ? el.firstChild : el
+ }
+ if (types[idx] === 'element') val = jsbeautify.html(val)
+ return val
+ })
+ if (values.length) {
+ console.log({ values })
+ return `${values}`
+ }
+ }
+ } else {
+ throw new Error('mode is not supported')
+ }
+ }
+
+ function basicFilter (value, query) { try { return value.indexOf(query) !== -1 } catch (e) { return false } }
+
+ const registerCommand = (name, command, opts) => {
+ // setState((prevState) => ({ ...prevState, _commands[name]: command }))
+ }
+
+ /* end of block content that gets rendered from script Runner */
+
return (
- {console.log({ props })}
+ {console.log({ newstate })}
{/* ${self._view.dragbar} */}