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
b9cac35b
Commit
b9cac35b
authored
Aug 31, 2017
by
serapath
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Refactor terminal and add improved (auto) scrolling logic
parent
e32d58d9
Show whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
173 additions
and
57 deletions
+173
-57
terminal.js
src/app/panels/terminal.js
+173
-57
No files found.
src/app/panels/terminal.js
View file @
b9cac35b
...
@@ -15,11 +15,12 @@ var css = csjs`
...
@@ -15,11 +15,12 @@ var css = csjs`
flex-direction : column;
flex-direction : column;
font-size : 12px;
font-size : 12px;
font-family : monospace;
font-family : monospace;
color :
white
;
color :
black
;
background-color :
grey
;
background-color :
white
;
margin-top : auto;
margin-top : auto;
height : 100%;
height : 100%;
min-height : 1.7em;
min-height : 1.7em;
overflow : hidden;
}
}
.bar {
.bar {
...
@@ -52,8 +53,7 @@ var css = csjs`
...
@@ -52,8 +53,7 @@ var css = csjs`
overflow-y : auto;
overflow-y : auto;
font-family : monospace;
font-family : monospace;
}
}
.journal {
.log {
margin-top : auto;
margin-top : auto;
font-family : monospace;
font-family : monospace;
}
}
...
@@ -63,7 +63,6 @@ var css = csjs`
...
@@ -63,7 +63,6 @@ var css = csjs`
line-height : 2ch;
line-height : 2ch;
margin : 1ch;
margin : 1ch;
}
}
.cli {
.cli {
line-height : 1.7em;
line-height : 1.7em;
font-family : monospace;
font-family : monospace;
...
@@ -77,14 +76,26 @@ var css = csjs`
...
@@ -77,14 +76,26 @@ var css = csjs`
outline : none;
outline : none;
font-family : monospace;
font-family : monospace;
}
}
.error {
.error {
color : red;
color : red;
}
}
.info {
.info {
color : blue;
color : blue;
}
}
.default {
.log {
color : white;
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 {
.ghostbar {
position : absolute;
position : absolute;
...
@@ -159,11 +170,12 @@ class Terminal {
...
@@ -159,11 +170,12 @@ class Terminal {
}
}
self
.
event
=
new
EventManager
()
self
.
event
=
new
EventManager
()
self
.
_api
=
opts
.
api
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
=
{}
self
.
_templates
.
default
=
self
.
_blocksRenderer
(
'default'
)
self
.
logger
=
{}
self
.
_templates
.
error
=
self
.
_blocksRenderer
(
'error'
)
;[
'log'
,
'info'
,
'error'
].
forEach
(
typename
=>
{
self
.
_templates
.
info
=
self
.
_blocksRenderer
(
'info'
)
self
.
registerType
(
typename
,
self
.
_blocksRenderer
(
typename
))
})
self
.
_jsSandboxContext
=
{}
self
.
_jsSandboxContext
=
{}
self
.
_jsSandbox
=
vm
.
createContext
(
self
.
_jsSandboxContext
)
self
.
_jsSandbox
=
vm
.
createContext
(
self
.
_jsSandboxContext
)
if
(
opts
.
shell
)
self
.
_shell
=
opts
.
shell
if
(
opts
.
shell
)
self
.
_shell
=
opts
.
shell
...
@@ -171,57 +183,163 @@ class Terminal {
...
@@ -171,57 +183,163 @@ class Terminal {
}
}
render
()
{
render
()
{
var
self
=
this
var
self
=
this
if
(
self
.
_view
.
panel
)
return
self
.
_view
.
pan
el
if
(
self
.
_view
.
el
)
return
self
.
_view
.
el
self
.
_view
.
log
=
yo
`<div class=
${
css
.
log
}
></div>`
self
.
_view
.
journal
=
yo
`<div class=
${
css
.
journal
}
></div>`
self
.
_view
.
input
=
yo
`
self
.
_view
.
input
=
yo
`
<span class=
${
css
.
input
}
contenteditable="true" onkeydown=
${
change
}
></span>
<span class=
${
css
.
input
}
contenteditable="true" onkeydown=
${
change
}
></span>
`
`
self
.
_view
.
cli
=
yo
`
self
.
_view
.
cli
=
yo
`
<div class=
${
css
.
cli
}
onclick=
${
e
=>
self
.
_view
.
input
.
focus
()}
>
<div class=
${
css
.
cli
}
>
<span class=
${
css
.
prompt
}
>
${
'>'
}
</span>
<span class=
${
css
.
prompt
}
>
${
'>'
}
</span>
${
self
.
_view
.
input
}
${
self
.
_view
.
input
}
</div>
</div>
`
`
self
.
_view
.
icon
=
yo
`<i onmouseenter=
${
hover
}
onmouseleave=
${
hover
}
onmousedown=
${
minimize
}
class="
${
css
.
minimize
}
fa fa-angle-double-down"></i>`
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
`
self
.
_view
.
bar
=
yo
`
<div class=
${
css
.
bar
}
onmousedown=
${
mousedown
}
>
<div class=
${
css
.
bar
}
>
${
self
.
_view
.
dragbar
}
${
self
.
_view
.
icon
}
${
self
.
_view
.
icon
}
</div>
</div>
`
`
self
.
_view
.
term
=
yo
`
self
.
_view
.
term
=
yo
`
<div class=
${
css
.
terminal
}
onscroll=
${
reattach
}
>
<div class=
${
css
.
terminal
}
onscroll=
${
throttle
(
reattach
,
50
)}
onclick=
${
focusinput
}
>
${
self
.
_view
.
log
}
${
self
.
_view
.
journal
}
${
self
.
_view
.
cli
}
${
self
.
_view
.
cli
}
</div>
</div>
`
`
self
.
_view
.
pan
el
=
yo
`
self
.
_view
.
el
=
yo
`
<div class=
${
css
.
panel
}
>
<div class=
${
css
.
panel
}
>
${
self
.
_view
.
bar
}
${
self
.
_view
.
bar
}
${
self
.
_view
.
term
}
${
self
.
_view
.
term
}
</div>
</div>
`
`
self
.
log
(
self
.
data
.
banner
)
self
.
_output
(
self
.
data
.
banner
)
function
focusinput
(
event
)
{
if
(
self
.
_view
.
journal
.
offsetHeight
-
self
.
_view
.
term
.
scrollTop
<
330
)
{
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
)
{
function
reattach
(
event
)
{
var
el
=
event
.
currentTarget
var
el
=
event
.
currentTarget
var
isBottomed
=
el
.
scrollHeight
-
el
.
scrollTop
===
el
.
clientHeight
var
isBottomed
=
el
.
scrollHeight
-
el
.
scrollTop
<
el
.
clientHeight
+
30
if
(
isBottomed
)
{
if
(
isBottomed
)
{
if
(
inserted
)
{
text
.
innerText
=
''
background
.
onclick
=
undefined
self
.
_view
.
journal
.
removeChild
(
placeholder
)
}
inserted
=
false
delete
self
.
scroll2bottom
delete
self
.
scroll2bottom
// @TODO: delete new message indicator
}
else
{
}
else
{
self
.
scroll2bottom
=
function
()
{
}
if
(
!
inserted
)
self
.
_view
.
journal
.
appendChild
(
placeholder
)
// @TODO: while in stopped mode: show indicator about new lines getting logged
inserted
=
true
check
()
if
(
!
placeholder
.
nextElementSibling
)
{
placeholder
.
style
.
display
=
'none'
}
else
{
placeholder
.
style
=
''
}
self
.
scroll2bottom
=
function
()
{
var
next
=
placeholder
.
nextElementSibling
if
(
next
)
{
console
.
error
(
'new messages'
)
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
hover
(
event
)
{
event
.
currentTarget
.
classList
.
toggle
(
css
.
hover
)
}
function
minimize
(
event
)
{
function
minimize
(
event
)
{
event
.
preventDefault
()
event
.
preventDefault
()
event
.
stopPropagation
()
event
.
stopPropagation
()
if
(
event
.
button
===
0
)
{
var
classList
=
self
.
_view
.
icon
.
classList
var
classList
=
self
.
_view
.
icon
.
classList
classList
.
toggle
(
'fa-angle-double-down'
)
classList
.
toggle
(
'fa-angle-double-down'
)
classList
.
toggle
(
'fa-angle-double-up'
)
classList
.
toggle
(
'fa-angle-double-up'
)
self
.
event
.
trigger
(
'resize'
,
[])
self
.
event
.
trigger
(
'resize'
,
[])
}
}
}
// ----------------- resizeable ui ---------------
// ----------------- resizeable ui ---------------
function
mousedown
(
event
)
{
function
mousedown
(
event
)
{
event
.
preventDefault
()
event
.
preventDefault
()
...
@@ -256,7 +374,7 @@ class Terminal {
...
@@ -256,7 +374,7 @@ class Terminal {
self
.
event
.
trigger
(
'resize'
,
[
self
.
_api
.
getPosition
(
event
)])
self
.
event
.
trigger
(
'resize'
,
[
self
.
_api
.
getPosition
(
event
)])
}
}
return
self
.
_view
.
pan
el
return
self
.
_view
.
el
function
change
(
event
)
{
function
change
(
event
)
{
if
(
event
.
which
===
13
)
{
if
(
event
.
which
===
13
)
{
...
@@ -301,7 +419,7 @@ class Terminal {
...
@@ -301,7 +419,7 @@ class Terminal {
}
}
_blocksRenderer
(
mode
)
{
_blocksRenderer
(
mode
)
{
var
self
=
this
var
self
=
this
var
modes
=
{
log
:
true
,
info
:
true
,
error
:
true
,
default
:
true
}
var
modes
=
{
log
:
true
,
info
:
true
,
error
:
true
}
if
(
modes
[
mode
])
{
if
(
modes
[
mode
])
{
return
function
render
()
{
return
function
render
()
{
var
args
=
[].
slice
.
call
(
arguments
)
var
args
=
[].
slice
.
call
(
arguments
)
...
@@ -319,23 +437,44 @@ class Terminal {
...
@@ -319,23 +437,44 @@ class Terminal {
throw
new
Error
(
'mode is not supported'
)
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
)
{
registerType
(
typename
,
template
)
{
var
self
=
this
var
self
=
this
if
(
typeof
template
!==
'function'
)
throw
new
Error
(
'invalid template'
)
if
(
typeof
template
!==
'function'
)
throw
new
Error
(
'invalid template'
)
self
.
_templates
[
typename
]
=
template
self
.
_templates
[
typename
]
=
template
self
.
logger
[
typename
]
=
function
()
{
var
args
=
[...
arguments
].
map
(
x
=>
({
type
:
typename
,
value
:
x
}))
self
.
_output
.
apply
(
self
,
args
)
}
}
}
log
()
{
log
()
{
// @TODO: temporary to not break stuff that uses the old API
this
.
_output
.
apply
(
this
,
arguments
)
}
_output
()
{
var
self
=
this
var
self
=
this
var
args
=
[...
arguments
]
var
args
=
[...
arguments
]
self
.
data
.
session
.
push
(
args
)
self
.
data
.
session
.
push
(
args
)
args
.
forEach
(
function
(
data
)
{
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
]
var
render
=
self
.
_templates
[
data
.
type
]
if
(
!
render
)
render
=
self
.
_templates
.
default
var
blocks
=
render
(
data
.
value
)
var
blocks
=
render
(
data
.
value
)
blocks
=
blocks
instanceof
Array
?
blocks
:
[
blocks
]
blocks
=
[].
concat
(
blocks
)
blocks
.
forEach
(
function
(
block
)
{
blocks
.
forEach
(
function
(
block
)
{
self
.
_view
.
log
.
appendChild
(
yo
`
self
.
_view
.
journal
.
appendChild
(
yo
`
<div class="
${
css
.
block
}
${
css
[
data
.
type
]
||
data
.
type
}
">
<div class="
${
css
.
block
}
${
css
[
data
.
type
]
||
data
.
type
}
">
${
block
}
${
block
}
</div>
</div>
...
@@ -344,41 +483,18 @@ class Terminal {
...
@@ -344,41 +483,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
()
{
scroll2bottom
()
{
var
self
=
this
var
self
=
this
setTimeout
(
function
()
{
setTimeout
(
function
()
{
self
.
_view
.
term
.
scrollTop
=
self
.
_view
.
term
.
scrollHeight
self
.
_view
.
term
.
scrollTop
=
self
.
_view
.
term
.
scrollHeight
},
0
)
},
0
)
}
}
execute
(
input
)
{
_shell
(
script
,
done
)
{
// default shell
var
self
=
this
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
{
try
{
var
context
=
vm
.
createContext
(
Object
.
assign
(
this
.
_jsSandboxContext
,
domTerminalFeatures
(
this
)))
var
context
=
vm
.
createContext
(
Object
.
assign
(
self
.
_jsSandboxContext
,
domTerminalFeatures
(
self
)))
var
result
=
vm
.
runInContext
(
inpu
t
,
context
)
var
result
=
vm
.
runInContext
(
scrip
t
,
context
)
this
.
_jsSandboxContext
=
Object
.
assign
({},
context
)
self
.
_jsSandboxContext
=
Object
.
assign
({},
context
)
done
(
null
,
result
)
done
(
null
,
result
)
}
catch
(
error
)
{
}
catch
(
error
)
{
done
(
error
.
message
)
done
(
error
.
message
)
...
@@ -391,7 +507,7 @@ function domTerminalFeatures (self) {
...
@@ -391,7 +507,7 @@ function domTerminalFeatures (self) {
return
{
return
{
web3
:
self
.
_api
.
context
()
!==
'vm'
?
new
Web3
(
self
.
_api
.
web3
().
currentProvider
)
:
null
,
web3
:
self
.
_api
.
context
()
!==
'vm'
?
new
Web3
(
self
.
_api
.
web3
().
currentProvider
)
:
null
,
console
:
{
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