Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
B
baas-ide
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
JIRA
JIRA
Merge Requests
1
Merge Requests
1
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
guxukai
baas-ide
Commits
558d25ed
Commit
558d25ed
authored
Aug 31, 2017
by
yann300
Committed by
GitHub
Aug 31, 2017
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #750 from serapath-contribution/master5
Refactor terminal and add improved (auto) scrolling logic
parents
5c55288f
b75836b9
Show whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
176 additions
and
59 deletions
+176
-59
terminal.js
src/app/panels/terminal.js
+176
-59
No files found.
src/app/panels/terminal.js
View file @
558d25ed
...
...
@@ -8,6 +8,8 @@ var vm = require('vm')
var
EventManager
=
require
(
'ethereum-remix'
).
lib
.
EventManager
var
Web3
=
require
(
'web3'
)
var
executionContext
=
require
(
'../../execution-context'
)
var
css
=
csjs
`
.panel {
position : relative;
...
...
@@ -15,11 +17,12 @@ var css = csjs`
flex-direction : column;
font-size : 12px;
font-family : monospace;
color :
white
;
background-color : grey;
color :
black
;
background-color :
light
grey;
margin-top : auto;
height : 100%;
min-height : 1.7em;
overflow : hidden;
}
.bar {
...
...
@@ -52,8 +55,7 @@ var css = csjs`
overflow-y : auto;
font-family : monospace;
}
.log {
.journal {
margin-top : auto;
font-family : monospace;
}
...
...
@@ -63,7 +65,6 @@ var css = csjs`
line-height : 2ch;
margin : 1ch;
}
.cli {
line-height : 1.7em;
font-family : monospace;
...
...
@@ -77,14 +78,26 @@ var css = csjs`
outline : none;
font-family : monospace;
}
.error {
color : red;
}
.info {
color : blue;
}
.default {
color : white;
.log {
color : black;
}
.dragbarHorizontal {
position : absolute;
top : 0;
height : 0.5em;
right : 0;
left : 0;
cursor : ns-resize;
z-index : 999;
border-top : 2px solid hsla(215, 81%, 79%, .3);
}
.ghostbar {
position : absolute;
...
...
@@ -159,11 +172,12 @@ class Terminal {
}
self
.
event
=
new
EventManager
()
self
.
_api
=
opts
.
api
self
.
_view
=
{
panel
:
null
,
bar
:
null
,
input
:
null
,
term
:
null
,
log
:
null
,
cli
:
null
}
self
.
_view
=
{
el
:
null
,
bar
:
null
,
input
:
null
,
term
:
null
,
journal
:
null
,
cli
:
null
}
self
.
_templates
=
{}
self
.
_templates
.
default
=
self
.
_blocksRenderer
(
'default'
)
self
.
_templates
.
error
=
self
.
_blocksRenderer
(
'error'
)
self
.
_templates
.
info
=
self
.
_blocksRenderer
(
'info'
)
self
.
logger
=
{}
;[
'log'
,
'info'
,
'error'
].
forEach
(
typename
=>
{
self
.
registerType
(
typename
,
self
.
_blocksRenderer
(
typename
))
})
self
.
_jsSandboxContext
=
{}
self
.
_jsSandbox
=
vm
.
createContext
(
self
.
_jsSandboxContext
)
if
(
opts
.
shell
)
self
.
_shell
=
opts
.
shell
...
...
@@ -171,57 +185,162 @@ class Terminal {
}
render
()
{
var
self
=
this
if
(
self
.
_view
.
panel
)
return
self
.
_view
.
pan
el
self
.
_view
.
log
=
yo
`<div class=
${
css
.
log
}
></div>`
if
(
self
.
_view
.
el
)
return
self
.
_view
.
el
self
.
_view
.
journal
=
yo
`<div class=
${
css
.
journal
}
></div>`
self
.
_view
.
input
=
yo
`
<span class=
${
css
.
input
}
contenteditable="true" onkeydown=
${
change
}
></span>
`
self
.
_view
.
cli
=
yo
`
<div class=
${
css
.
cli
}
onclick=
${
e
=>
self
.
_view
.
input
.
focus
()}
>
<div class=
${
css
.
cli
}
>
<span class=
${
css
.
prompt
}
>
${
'>'
}
</span>
${
self
.
_view
.
input
}
</div>
`
self
.
_view
.
icon
=
yo
`<i onmouseenter=
${
hover
}
onmouseleave=
${
hover
}
onmousedown=
${
minimize
}
class="
${
css
.
minimize
}
fa fa-angle-double-down"></i>`
self
.
_view
.
dragbar
=
yo
`<div onmousedown=
${
mousedown
}
class=
${
css
.
dragbarHorizontal
}
></div>`
self
.
_view
.
bar
=
yo
`
<div class=
${
css
.
bar
}
onmousedown=
${
mousedown
}
>
<div class=
${
css
.
bar
}
>
${
self
.
_view
.
dragbar
}
${
self
.
_view
.
icon
}
</div>
`
self
.
_view
.
term
=
yo
`
<div class=
${
css
.
terminal
}
onscroll=
${
reattach
}
>
${
self
.
_view
.
log
}
<div class=
${
css
.
terminal
}
onscroll=
${
throttle
(
reattach
,
50
)}
onclick=
${
focusinput
}
>
${
self
.
_view
.
journal
}
${
self
.
_view
.
cli
}
</div>
`
self
.
_view
.
pan
el
=
yo
`
self
.
_view
.
el
=
yo
`
<div class=
${
css
.
panel
}
>
${
self
.
_view
.
bar
}
${
self
.
_view
.
term
}
</div>
`
self
.
log
(
self
.
data
.
banner
)
self
.
_output
(
self
.
data
.
banner
)
function
focusinput
(
event
)
{
if
(
self
.
_view
.
journal
.
offsetHeight
-
(
self
.
_view
.
term
.
scrollTop
+
self
.
_view
.
term
.
offsetHeight
)
<
50
)
{
refocus
()
}
}
function
refocus
()
{
self
.
_view
.
input
.
focus
()
reattach
({
currentTarget
:
self
.
_view
.
term
})
self
.
scroll2bottom
()
}
var
css2
=
csjs
`
.anchor {
position : static;
border-top : 2px dotted blue;
height : 10px;
}
.overlay {
position : absolute;
width : 100%;
display : flex;
align-items : center;
justify-content : center;
bottom : 0;
right : 15px;
height : 20%;
min-height : 50px;
}
.text {
z-index : 2;
color : black;
font-size : 25px;
font-weight : bold;
pointer-events : none;
}
.background {
z-index : 1;
opacity : 0.8;
background-color : #a6aeba;
cursor : pointer;
}
`
var
text
=
yo
`<div class="
${
css2
.
overlay
}
${
css2
.
text
}
"></div>`
var
background
=
yo
`<div class="
${
css2
.
overlay
}
${
css2
.
background
}
"></div>`
var
placeholder
=
yo
`<div class=
${
css2
.
anchor
}
>
${
background
}${
text
}
</div>`
var
inserted
=
false
function
throttle
(
fn
,
wait
)
{
var
time
=
Date
.
now
()
return
function
()
{
if
((
time
+
wait
-
Date
.
now
())
<
0
)
{
fn
.
apply
(
this
,
arguments
)
time
=
Date
.
now
()
}
}
}
function
reattach
(
event
)
{
var
el
=
event
.
currentTarget
var
isBottomed
=
el
.
scrollHeight
-
el
.
scrollTop
===
el
.
clientHeight
var
isBottomed
=
el
.
scrollHeight
-
el
.
scrollTop
<
el
.
clientHeight
+
30
if
(
isBottomed
)
{
if
(
inserted
)
{
text
.
innerText
=
''
background
.
onclick
=
undefined
self
.
_view
.
journal
.
removeChild
(
placeholder
)
}
inserted
=
false
delete
self
.
scroll2bottom
// @TODO: delete new message indicator
}
else
{
self
.
scroll2bottom
=
function
()
{
}
// @TODO: while in stopped mode: show indicator about new lines getting logged
if
(
!
inserted
)
self
.
_view
.
journal
.
appendChild
(
placeholder
)
inserted
=
true
check
()
if
(
!
placeholder
.
nextElementSibling
)
{
placeholder
.
style
.
display
=
'none'
}
else
{
placeholder
.
style
=
''
}
self
.
scroll2bottom
=
function
()
{
var
next
=
placeholder
.
nextElementSibling
if
(
next
)
{
placeholder
.
style
=
''
check
()
var
messages
=
1
while
((
next
=
next
.
nextElementSibling
))
messages
+=
1
text
.
innerText
=
`
${
messages
}
new unread log entries`
}
else
{
placeholder
.
style
.
display
=
'none'
}
}
}
}
function
check
()
{
var
pos1
=
self
.
_view
.
term
.
offsetHeight
+
self
.
_view
.
term
.
scrollTop
-
(
self
.
_view
.
el
.
offsetHeight
*
0.15
)
var
pos2
=
placeholder
.
offsetTop
if
((
pos1
-
pos2
)
>
0
)
{
text
.
style
.
display
=
'none'
background
.
style
.
position
=
'relative'
background
.
style
.
opacity
=
0.3
background
.
style
.
right
=
0
background
.
style
.
borderBox
=
'content-box'
background
.
style
.
padding
=
'2px'
background
.
style
.
height
=
(
self
.
_view
.
journal
.
offsetHeight
-
(
placeholder
.
offsetTop
+
placeholder
.
offsetHeight
))
+
'px'
background
.
onclick
=
undefined
background
.
style
.
cursor
=
'default'
}
else
{
background
.
style
=
''
text
.
style
=
''
background
.
onclick
=
function
(
event
)
{
console
.
error
(
'background click'
)
placeholder
.
scrollIntoView
()
check
()
}
}
}
function
hover
(
event
)
{
event
.
currentTarget
.
classList
.
toggle
(
css
.
hover
)
}
function
minimize
(
event
)
{
event
.
preventDefault
()
event
.
stopPropagation
()
if
(
event
.
button
===
0
)
{
var
classList
=
self
.
_view
.
icon
.
classList
classList
.
toggle
(
'fa-angle-double-down'
)
classList
.
toggle
(
'fa-angle-double-up'
)
self
.
event
.
trigger
(
'resize'
,
[])
}
}
// ----------------- resizeable ui ---------------
function
mousedown
(
event
)
{
event
.
preventDefault
()
...
...
@@ -256,7 +375,7 @@ class Terminal {
self
.
event
.
trigger
(
'resize'
,
[
self
.
_api
.
getPosition
(
event
)])
}
return
self
.
_view
.
pan
el
return
self
.
_view
.
el
function
change
(
event
)
{
if
(
event
.
which
===
13
)
{
...
...
@@ -301,7 +420,7 @@ class Terminal {
}
_blocksRenderer
(
mode
)
{
var
self
=
this
var
modes
=
{
log
:
true
,
info
:
true
,
error
:
true
,
default
:
true
}
var
modes
=
{
log
:
true
,
info
:
true
,
error
:
true
}
if
(
modes
[
mode
])
{
return
function
render
()
{
var
args
=
[].
slice
.
call
(
arguments
)
...
...
@@ -319,23 +438,44 @@ class Terminal {
throw
new
Error
(
'mode is not supported'
)
}
}
execute
(
script
)
{
var
self
=
this
script
=
String
(
script
)
self
.
_output
({
type
:
'log'
,
value
:
`>
${
script
}
`
})
self
.
_shell
(
script
,
function
(
error
,
output
)
{
if
(
error
)
{
self
.
_output
({
type
:
'error'
,
value
:
error
})
return
error
}
else
{
self
.
_output
({
type
:
'log'
,
value
:
output
})
return
output
}
})
}
registerType
(
typename
,
template
)
{
var
self
=
this
if
(
typeof
template
!==
'function'
)
throw
new
Error
(
'invalid template'
)
self
.
_templates
[
typename
]
=
template
self
.
logger
[
typename
]
=
function
()
{
var
args
=
[...
arguments
].
map
(
x
=>
({
type
:
typename
,
value
:
x
}))
self
.
_output
.
apply
(
self
,
args
)
}
}
log
()
{
// @TODO: temporary to not break stuff that uses the old API
this
.
_output
.
apply
(
this
,
arguments
)
}
_output
()
{
var
self
=
this
var
args
=
[...
arguments
]
self
.
data
.
session
.
push
(
args
)
args
.
forEach
(
function
(
data
)
{
if
(
!
data
||
!
data
.
type
)
data
=
{
type
:
'
default
'
,
value
:
data
}
if
(
!
data
||
!
data
.
type
)
data
=
{
type
:
'
log
'
,
value
:
data
}
var
render
=
self
.
_templates
[
data
.
type
]
if
(
!
render
)
render
=
self
.
_templates
.
default
var
blocks
=
render
(
data
.
value
)
blocks
=
blocks
instanceof
Array
?
blocks
:
[
blocks
]
blocks
=
[].
concat
(
blocks
)
blocks
.
forEach
(
function
(
block
)
{
self
.
_view
.
log
.
appendChild
(
yo
`
self
.
_view
.
journal
.
appendChild
(
yo
`
<div class="
${
css
.
block
}
${
css
[
data
.
type
]
||
data
.
type
}
">
${
block
}
</div>
...
...
@@ -344,41 +484,18 @@ class Terminal {
})
})
}
info
()
{
var
self
=
this
var
args
=
[...
arguments
].
map
(
x
=>
({
type
:
'info'
,
value
:
x
}))
self
.
log
.
apply
(
self
,
args
)
}
error
()
{
var
self
=
this
var
args
=
[...
arguments
].
map
(
x
=>
({
type
:
'error'
,
value
:
x
}))
self
.
log
.
apply
(
self
,
args
)
}
scroll2bottom
()
{
var
self
=
this
setTimeout
(
function
()
{
self
.
_view
.
term
.
scrollTop
=
self
.
_view
.
term
.
scrollHeight
},
0
)
}
execute
(
input
)
{
_shell
(
script
,
done
)
{
// default shell
var
self
=
this
input
=
String
(
input
)
self
.
log
(
`>
${
input
}
`
)
self
.
_shell
(
input
,
function
(
error
,
output
)
{
if
(
error
)
{
self
.
error
(
error
)
return
error
}
else
{
self
.
log
(
output
)
return
output
}
})
}
_shell
(
input
,
done
)
{
// default shell
try
{
var
context
=
vm
.
createContext
(
Object
.
assign
(
this
.
_jsSandboxContext
,
domTerminalFeatures
(
this
)))
var
result
=
vm
.
runInContext
(
inpu
t
,
context
)
this
.
_jsSandboxContext
=
Object
.
assign
({},
context
)
var
context
=
vm
.
createContext
(
Object
.
assign
(
self
.
_jsSandboxContext
,
domTerminalFeatures
(
self
)))
var
result
=
vm
.
runInContext
(
scrip
t
,
context
)
self
.
_jsSandboxContext
=
Object
.
assign
({},
context
)
done
(
null
,
result
)
}
catch
(
error
)
{
done
(
error
.
message
)
...
...
@@ -386,12 +503,12 @@ class Terminal {
}
}
// @TODO add all the `console` functions
function
domTerminalFeatures
(
self
)
{
// @TODO add all the `console` functions
return
{
web3
:
self
.
_api
.
context
()
!==
'vm'
?
new
Web3
(
self
.
_api
.
web3
().
currentProvider
)
:
null
,
web3
:
executionContext
.
getProvider
()
!==
'vm'
?
new
Web3
(
executionContext
.
web3
().
currentProvider
)
:
null
,
console
:
{
log
:
function
()
{
self
.
log
.
apply
(
self
,
arguments
)
}
log
:
function
()
{
self
.
_output
.
apply
(
self
,
arguments
)
}
}
}
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment