Compare commits
18 Commits
v1.0.0-alp
...
v1.0.0-alp
Author | SHA1 | Date | |
---|---|---|---|
![]() |
63158ac6cd | ||
![]() |
4f44087989 | ||
![]() |
ab3c49b9b2 | ||
![]() |
28d01a1b56 | ||
![]() |
a979f0108e | ||
![]() |
3c74b8ec38 | ||
![]() |
9d7bf2ae44 | ||
![]() |
3b43b3914b | ||
![]() |
e9f22dd8b5 | ||
![]() |
e68cafdb70 | ||
![]() |
fde16b8699 | ||
![]() |
245c65d750 | ||
![]() |
c7d9f944d5 | ||
![]() |
4ca806e142 | ||
![]() |
0255985bc6 | ||
![]() |
104f1ee7aa | ||
![]() |
132d0553ae | ||
![]() |
b007ff6ff6 |
@@ -14,11 +14,11 @@
|
||||
viewBox="0 0 150 150"
|
||||
version="1.1"
|
||||
id="svg8"
|
||||
inkscape:version="0.92.1 r15371"
|
||||
inkscape:version="0.92.2 (5c3e80d, 2017-08-06)"
|
||||
sodipodi:docname="logo.svg"
|
||||
inkscape:export-filename="/home/eugene/Work/term/build/icons/16x16.png"
|
||||
inkscape:export-xdpi="2.7093334"
|
||||
inkscape:export-ydpi="2.7093334">
|
||||
inkscape:export-filename="/home/eugene/Work/term/build/icons/512x512.png"
|
||||
inkscape:export-xdpi="86.699997"
|
||||
inkscape:export-ydpi="86.699997">
|
||||
<defs
|
||||
id="defs2" />
|
||||
<sodipodi:namedview
|
||||
@@ -29,8 +29,8 @@
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="0.49497475"
|
||||
inkscape:cx="134.39743"
|
||||
inkscape:cy="340.43068"
|
||||
inkscape:cx="85.897128"
|
||||
inkscape:cy="375.72042"
|
||||
inkscape:document-units="mm"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="false"
|
||||
@@ -43,7 +43,9 @@
|
||||
fit-margin-top="0"
|
||||
fit-margin-left="0"
|
||||
fit-margin-right="0"
|
||||
fit-margin-bottom="0" />
|
||||
fit-margin-bottom="0"
|
||||
inkscape:snap-intersection-paths="true"
|
||||
inkscape:object-paths="true" />
|
||||
<metadata
|
||||
id="metadata5">
|
||||
<rdf:RDF>
|
||||
@@ -64,24 +66,24 @@
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path138"
|
||||
style="opacity:0.9;fill:#ccccff;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:round;stroke-opacity:1"
|
||||
d="m 39.305965,108.47713 60.922105,35.13225 0.0945,21.68327 -61.016595,-37.11662 z"
|
||||
style="opacity:0.9;fill:#bfd9f1;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.12037313px;stroke-linecap:butt;stroke-linejoin:round;stroke-opacity:1"
|
||||
d="M 33.048081,103.66303 101.30357,143.02426 80.80219,154.86063 33.048089,125.73315 Z"
|
||||
sodipodi:nodetypes="ccccc" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path116"
|
||||
style="opacity:0.9;fill:#6666cc;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:round;stroke-opacity:1"
|
||||
d="m 136.19445,144.4429 0.0455,20.67266 -78.028381,44.11611 -0.0031,-19.78119 z"
|
||||
style="opacity:0.9;fill:#6666af;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.12037313px;stroke-linecap:butt;stroke-linejoin:round;stroke-opacity:1"
|
||||
d="m 141.59934,143.95811 0.051,23.16109 -87.420905,49.42651 -0.0034,-22.16232 z"
|
||||
sodipodi:nodetypes="ccccc" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path118"
|
||||
style="opacity:0.9;fill:#ccccff;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:round;stroke-opacity:1"
|
||||
d="m 39.471179,178.6501 18.737341,10.818 0.0031,19.78099 -18.740409,-10.88245 z"
|
||||
style="opacity:0.9;fill:#bfd9f1;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.12037313px;stroke-linecap:butt;stroke-linejoin:round;stroke-opacity:1"
|
||||
d="m 33.233182,182.28294 20.992812,12.1202 0.0034,22.16208 -20.996251,-12.19239 z"
|
||||
sodipodi:nodetypes="ccccc" />
|
||||
<path
|
||||
style="opacity:0.9;fill:#b4e2ff;fill-rule:evenodd;stroke:none;stroke-width:1.00546169px;stroke-linecap:butt;stroke-linejoin:round;stroke-opacity:1"
|
||||
d="m 56.43263,98.242186 -17.391087,10.041014 61.186527,35.32618 -61.020778,35.23005 18.839694,10.87703 61.020784,-35.23005 17.39108,-10.04102 z"
|
||||
style="opacity:0.9;fill:#9dbef0;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.12649226px;stroke-linecap:butt;stroke-linejoin:round;stroke-opacity:1"
|
||||
d="m 52.236336,92.196079 -19.484508,11.249681 68.551742,39.5785 -68.366041,39.4708 21.107487,12.18633 68.366044,-39.4708 19.48451,-11.24968 z"
|
||||
id="path134"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cccccccc" />
|
Before Width: | Height: | Size: 3.3 KiB After Width: | Height: | Size: 3.5 KiB |
BIN
app/assets/tray-darwinHighlightTemplate.png
Normal file
After Width: | Height: | Size: 415 B |
BIN
app/assets/tray-darwinHighlightTemplate@2x.png
Normal file
After Width: | Height: | Size: 955 B |
BIN
app/assets/tray-darwinTemplate.png
Normal file
After Width: | Height: | Size: 365 B |
BIN
app/assets/tray-darwinTemplate@2x.png
Normal file
After Width: | Height: | Size: 894 B |
BIN
app/assets/tray.png
Normal file
After Width: | Height: | Size: 1.4 KiB |
54
app/main.js
@@ -32,6 +32,16 @@ if (!process.env.TERMINUS_PLUGINS) {
|
||||
setupWindowManagement = () => {
|
||||
app.window.on('show', () => {
|
||||
app.window.webContents.send('host:window-shown')
|
||||
if (app.tray) {
|
||||
app.tray.destroy()
|
||||
app.tray = null
|
||||
}
|
||||
})
|
||||
|
||||
app.window.on('hide', (e) => {
|
||||
if (!app.tray) {
|
||||
setupTray()
|
||||
}
|
||||
})
|
||||
|
||||
app.window.on('close', (e) => {
|
||||
@@ -75,20 +85,7 @@ setupWindowManagement = () => {
|
||||
})
|
||||
|
||||
electron.ipcMain.on('window-set-bounds', (event, bounds) => {
|
||||
let actualBounds = app.window.getBounds()
|
||||
actualBounds.width -= bounds.x - actualBounds.x
|
||||
actualBounds.height -= bounds.y - actualBounds.y
|
||||
actualBounds.x = bounds.x
|
||||
actualBounds.y = bounds.y
|
||||
app.window.setBounds(actualBounds)
|
||||
setTimeout(() => {
|
||||
actualBounds = app.window.getBounds()
|
||||
bounds.width += bounds.x - actualBounds.x
|
||||
bounds.height += bounds.y - actualBounds.y
|
||||
bounds.x = actualBounds.x
|
||||
bounds.y = actualBounds.y
|
||||
app.window.setBounds(bounds)
|
||||
}, 100)
|
||||
app.window.setBounds(bounds)
|
||||
})
|
||||
|
||||
electron.ipcMain.on('window-set-always-on-top', (event, flag) => {
|
||||
@@ -97,6 +94,35 @@ setupWindowManagement = () => {
|
||||
}
|
||||
|
||||
|
||||
setupTray = () => {
|
||||
if (process.platform == 'darwin') {
|
||||
app.tray = new electron.Tray(`${app.getAppPath()}/assets/tray-darwinTemplate.png`)
|
||||
app.tray.setPressedImage(`${app.getAppPath()}/assets/tray-darwinHighlightTemplate.png`)
|
||||
} else {
|
||||
app.tray = new electron.Tray(`${app.getAppPath()}/assets/tray.png`)
|
||||
}
|
||||
|
||||
app.tray.on('click', () => {
|
||||
app.window.show()
|
||||
app.window.focus()
|
||||
})
|
||||
|
||||
const contextMenu = electron.Menu.buildFromTemplate([{
|
||||
label: 'Show',
|
||||
click () {
|
||||
app.window.show()
|
||||
app.window.focus()
|
||||
}
|
||||
}])
|
||||
|
||||
if (process.platform != 'darwin') {
|
||||
app.tray.setContextMenu(contextMenu)
|
||||
}
|
||||
|
||||
app.tray.setToolTip(`Terminus ${app.getVersion()}`)
|
||||
}
|
||||
|
||||
|
||||
setupMenu = () => {
|
||||
let template = [{
|
||||
label: "Application",
|
||||
|
@@ -39,7 +39,7 @@
|
||||
.terminus-logo {
|
||||
width: 160px;
|
||||
height: 160px;
|
||||
background: url('./logo.svg');
|
||||
background: url('../assets/logo.svg');
|
||||
background-repeat: none;
|
||||
background-size: contain;
|
||||
margin: auto;
|
||||
|
Before Width: | Height: | Size: 4.9 KiB After Width: | Height: | Size: 4.3 KiB |
Before Width: | Height: | Size: 655 B After Width: | Height: | Size: 644 B |
Before Width: | Height: | Size: 9.8 KiB After Width: | Height: | Size: 8.3 KiB |
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.2 KiB |
Before Width: | Height: | Size: 20 KiB After Width: | Height: | Size: 18 KiB |
Before Width: | Height: | Size: 2.4 KiB After Width: | Height: | Size: 2.3 KiB |
@@ -15,19 +15,22 @@
|
||||
viewBox="0 0 150 150"
|
||||
version="1.1"
|
||||
id="svg8"
|
||||
inkscape:version="0.92.1 r15371"
|
||||
sodipodi:docname="icon.svg">
|
||||
inkscape:version="0.92.2 (5c3e80d, 2017-08-06)"
|
||||
sodipodi:docname="icon.svg"
|
||||
inkscape:export-filename="/home/eugene/Work/term/build/icons/512x512.png"
|
||||
inkscape:export-xdpi="86.699997"
|
||||
inkscape:export-ydpi="86.699997">
|
||||
<defs
|
||||
id="defs2">
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
id="linearGradient4649">
|
||||
<stop
|
||||
style="stop-color:#000916;stop-opacity:1"
|
||||
style="stop-color:#000316;stop-opacity:1"
|
||||
offset="0"
|
||||
id="stop4645" />
|
||||
<stop
|
||||
style="stop-color:#004565;stop-opacity:1"
|
||||
style="stop-color:#190065;stop-opacity:1"
|
||||
offset="1"
|
||||
id="stop4647" />
|
||||
</linearGradient>
|
||||
@@ -39,7 +42,8 @@
|
||||
y1="85.146751"
|
||||
x2="89.26284"
|
||||
y2="229.47229"
|
||||
gradientUnits="userSpaceOnUse" />
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(0.82182032,0,0,0.82182032,15.208802,28.029361)" />
|
||||
</defs>
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
@@ -49,8 +53,8 @@
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="0.49497475"
|
||||
inkscape:cx="134.39743"
|
||||
inkscape:cy="340.43068"
|
||||
inkscape:cx="85.897128"
|
||||
inkscape:cy="375.72042"
|
||||
inkscape:document-units="mm"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="false"
|
||||
@@ -63,7 +67,9 @@
|
||||
fit-margin-top="0"
|
||||
fit-margin-left="0"
|
||||
fit-margin-right="0"
|
||||
fit-margin-bottom="0" />
|
||||
fit-margin-bottom="0"
|
||||
inkscape:snap-intersection-paths="true"
|
||||
inkscape:object-paths="true" />
|
||||
<metadata
|
||||
id="metadata5">
|
||||
<rdf:RDF>
|
||||
@@ -83,34 +89,34 @@
|
||||
transform="translate(-10.356544,-82.309525)">
|
||||
<rect
|
||||
id="rect168"
|
||||
width="150"
|
||||
height="150"
|
||||
x="10.356544"
|
||||
y="82.309525"
|
||||
style="fill:url(#linearGradient4651);fill-opacity:1;stroke-width:0.26458332"
|
||||
rx="10"
|
||||
ry="10" />
|
||||
width="123.27305"
|
||||
height="123.27305"
|
||||
x="23.72002"
|
||||
y="95.673004"
|
||||
style="fill:url(#linearGradient4651);fill-opacity:1;stroke-width:0.21743995"
|
||||
rx="8.2182035"
|
||||
ry="8.2182035" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path138"
|
||||
style="opacity:0.9;fill:#ccccff;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:round;stroke-opacity:1"
|
||||
d="m 39.305965,108.47713 60.922105,35.13225 0.0945,21.68327 -61.016595,-37.11662 z"
|
||||
style="opacity:0.9;fill:#bfd9f1;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.82182032px;stroke-linecap:butt;stroke-linejoin:round;stroke-opacity:1"
|
||||
d="m 47.511243,117.17807 50.067023,28.8724 -15.038249,8.68226 -35.028768,-21.3657 z"
|
||||
sodipodi:nodetypes="ccccc" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path116"
|
||||
style="opacity:0.9;fill:#6666cc;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:round;stroke-opacity:1"
|
||||
d="m 136.19445,144.4429 0.0455,20.67266 -78.028381,44.11611 -0.0031,-19.78119 z"
|
||||
style="opacity:0.9;fill:#6666af;fill-rule:evenodd;stroke:none;stroke-width:0.82182032px;stroke-linecap:butt;stroke-linejoin:round;stroke-opacity:1;fill-opacity:1"
|
||||
d="m 127.13617,146.73547 0.0374,16.98921 -64.125308,36.25552 -0.0025,-16.25659 z"
|
||||
sodipodi:nodetypes="ccccc" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path118"
|
||||
style="opacity:0.9;fill:#ccccff;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:round;stroke-opacity:1"
|
||||
d="m 39.471179,178.6501 18.737341,10.818 0.0031,19.78099 -18.740409,-10.88245 z"
|
||||
style="opacity:0.9;fill:#bfd9f1;fill-rule:evenodd;stroke:none;stroke-width:0.82182032px;stroke-linecap:butt;stroke-linejoin:round;stroke-opacity:1;fill-opacity:1"
|
||||
d="m 47.647019,174.84764 15.398727,8.89046 0.0025,16.25641 -15.401249,-8.94341 z"
|
||||
sodipodi:nodetypes="ccccc" />
|
||||
<path
|
||||
style="opacity:0.9;fill:#b4e2ff;fill-rule:evenodd;stroke:none;stroke-width:1.00546169px;stroke-linecap:butt;stroke-linejoin:round;stroke-opacity:1"
|
||||
d="m 56.43263,98.242186 -17.391087,10.041014 61.186527,35.32618 -61.020778,35.23005 18.839694,10.87703 61.020784,-35.23005 17.39108,-10.04102 z"
|
||||
style="opacity:0.9;fill:#9dbef0;fill-rule:evenodd;stroke:none;stroke-width:0.82630885px;stroke-linecap:butt;stroke-linejoin:round;stroke-opacity:1;fill-opacity:1"
|
||||
d="m 61.586284,108.76679 -14.292349,8.25191 50.284331,29.03177 -50.148115,28.95277 15.482843,8.93896 50.148116,-28.95277 14.29235,-8.25191 z"
|
||||
id="path134"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cccccccc" />
|
||||
|
Before Width: | Height: | Size: 4.0 KiB After Width: | Height: | Size: 4.4 KiB |
Before Width: | Height: | Size: 361 KiB After Width: | Height: | Size: 361 KiB |
@@ -9,7 +9,7 @@
|
||||
"core-js": "2.4.1",
|
||||
"cross-env": "4.0.0",
|
||||
"css-loader": "0.28.0",
|
||||
"electron": "1.6.11",
|
||||
"electron": "1.8.4",
|
||||
"electron-builder": "17.1.1",
|
||||
"electron-builder-squirrel-windows": "17.0.1",
|
||||
"electron-rebuild": "1.5.11",
|
||||
@@ -98,7 +98,8 @@
|
||||
},
|
||||
"rpm": {
|
||||
"depends": [
|
||||
"screen"
|
||||
"screen",
|
||||
"gnome-python2-gnomekeyring"
|
||||
],
|
||||
"artifactName": "terminus-${version}-${os}-${arch}.rpm"
|
||||
}
|
||||
|
@@ -1,12 +1,13 @@
|
||||
title-bar(
|
||||
*ngIf='config.store.appearance.frame == "full" && config.store.appearance.dock == "off"',
|
||||
*ngIf='!hostApp.getWindow().isFullScreen() && config.store.appearance.frame == "full" && config.store.appearance.dock == "off"',
|
||||
[class.inset]='hostApp.platform == Platform.macOS'
|
||||
)
|
||||
|
||||
.content(
|
||||
[class.tabs-on-top]='config.store.appearance.tabsLocation == "top"'
|
||||
[class.tabs-on-top]='config.store.appearance.tabsLocation == "top"'
|
||||
)
|
||||
.tab-bar(
|
||||
*ngIf='!hostApp.getWindow().isFullScreen()',
|
||||
[class.inset]='hostApp.platform == Platform.macOS && config.store.appearance.frame == "thin" && config.store.appearance.tabsLocation == "top"'
|
||||
)
|
||||
.tabs
|
||||
@@ -20,7 +21,7 @@ title-bar(
|
||||
@animateTab,
|
||||
(click)='app.selectTab(tab)',
|
||||
)
|
||||
|
||||
|
||||
.btn-group
|
||||
button.btn.btn-secondary.btn-tab-bar(
|
||||
*ngFor='let button of leftToolbarButtons',
|
||||
@@ -28,9 +29,9 @@ title-bar(
|
||||
(click)='button.click()',
|
||||
)
|
||||
i.fa([class]='"fa fa-" + button.icon')
|
||||
|
||||
|
||||
.drag-space([class.persistent]='config.store.appearance.frame == "thin" && hostApp.platform != Platform.macOS')
|
||||
|
||||
|
||||
.btn-group
|
||||
button.btn.btn-secondary.btn-tab-bar(
|
||||
*ngFor='let button of rightToolbarButtons',
|
||||
@@ -53,7 +54,7 @@ title-bar(
|
||||
start-page(*ngIf='ready && app.tabs.length == 0')
|
||||
|
||||
tab-body(
|
||||
*ngFor='let tab of app.tabs; trackBy: tab?.id',
|
||||
*ngFor='let tab of app.tabs; trackBy: tab?.id',
|
||||
[active]='tab == app.activeTab',
|
||||
[tab]='tab',
|
||||
[scrollable]='tab.scrollable',
|
||||
|
@@ -97,6 +97,9 @@ export class AppRootComponent {
|
||||
this.app.previousTab()
|
||||
}
|
||||
}
|
||||
if (hotkey === 'toggle-fullscreen') {
|
||||
this.hostApp.toggleFullscreen()
|
||||
}
|
||||
})
|
||||
|
||||
this.docking.dock()
|
||||
|
@@ -1,6 +1,8 @@
|
||||
hotkeys:
|
||||
toggle-window:
|
||||
- 'Ctrl+Space'
|
||||
toggle-fullscreen:
|
||||
- 'F11'
|
||||
close-tab:
|
||||
- 'Ctrl-Shift-W'
|
||||
- ['Ctrl-A', 'K']
|
||||
|
@@ -1,6 +1,8 @@
|
||||
hotkeys:
|
||||
toggle-window:
|
||||
- 'Ctrl+Space'
|
||||
toggle-fullscreen:
|
||||
- 'Ctrl+⌘+F'
|
||||
close-tab:
|
||||
- '⌘-W'
|
||||
toggle-last-tab: []
|
||||
|
@@ -1,6 +1,8 @@
|
||||
hotkeys:
|
||||
toggle-window:
|
||||
- 'Ctrl+Space'
|
||||
toggle-fullscreen:
|
||||
- 'F11'
|
||||
close-tab:
|
||||
- 'Ctrl-Shift-W'
|
||||
- ['Ctrl-A', 'K']
|
||||
|
@@ -73,6 +73,11 @@ export class HostAppService {
|
||||
return this.electron.app.getPath(type)
|
||||
}
|
||||
|
||||
toggleFullscreen () {
|
||||
let window = this.getWindow()
|
||||
window.setFullScreen(!window.isFullScreen())
|
||||
}
|
||||
|
||||
openDevTools () {
|
||||
this.getWindow().webContents.openDevTools({ mode: 'undocked' })
|
||||
}
|
||||
|
@@ -178,6 +178,10 @@ export class AppHotkeyProvider extends HotkeyProvider {
|
||||
id: 'toggle-window',
|
||||
name: 'Toggle terminal window',
|
||||
},
|
||||
{
|
||||
id: 'toggle-fullscreen',
|
||||
name: 'Toggle fullscreen mode',
|
||||
},
|
||||
{
|
||||
id: 'close-tab',
|
||||
name: 'Close tab',
|
||||
|
@@ -5,7 +5,7 @@ export const metaKeyName = {
|
||||
}[process.platform]
|
||||
|
||||
export const altKeyName = {
|
||||
darwin: 'Option',
|
||||
darwin: '⌥',
|
||||
win32: 'Alt',
|
||||
linux: 'Alt',
|
||||
}[process.platform]
|
||||
|
@@ -41,7 +41,9 @@ export class Logger {
|
||||
|
||||
doLog (level: string, ...args: any[]) {
|
||||
console[level](`%c[${this.name}]`, 'color: #aaa', ...args)
|
||||
this.winstonLogger[level](...args)
|
||||
if (this.winstonLogger) {
|
||||
this.winstonLogger[level](...args)
|
||||
}
|
||||
}
|
||||
|
||||
debug (...args: any[]) { this.doLog('debug', ...args) }
|
||||
|
@@ -45,7 +45,7 @@ export class PluginManagerService {
|
||||
return
|
||||
}
|
||||
if (this.hostApp.platform !== Platform.Windows) {
|
||||
let searchPaths = (await exec('bash -c -l "echo $PATH"'))[0].toString().trim().split(':')
|
||||
let searchPaths = (await exec('$SHELL -c -i \'echo $PATH\''))[0].toString().trim().split(':')
|
||||
for (let searchPath of searchPaths) {
|
||||
if (await fs.exists(path.join(searchPath, 'npm'))) {
|
||||
this.logger.debug('Found npm in', searchPath)
|
||||
|
@@ -18,7 +18,7 @@
|
||||
input.form-control(
|
||||
type='number',
|
||||
placeholder='22',
|
||||
[(ngModel)]='connection.post',
|
||||
[(ngModel)]='connection.port',
|
||||
)
|
||||
|
||||
.form-group
|
||||
|
@@ -88,20 +88,40 @@ export class TerminalTabComponent extends BaseTabComponent {
|
||||
if (!this.hasFocus) {
|
||||
return
|
||||
}
|
||||
if (hotkey === 'copy') {
|
||||
this.hterm.copySelectionToClipboard()
|
||||
}
|
||||
if (hotkey === 'clear') {
|
||||
this.clear()
|
||||
}
|
||||
if (hotkey === 'zoom-in') {
|
||||
this.zoomIn()
|
||||
}
|
||||
if (hotkey === 'zoom-out') {
|
||||
this.zoomOut()
|
||||
}
|
||||
if (hotkey === 'reset-zoom') {
|
||||
this.resetZoom()
|
||||
switch (hotkey) {
|
||||
case 'copy':
|
||||
this.hterm.copySelectionToClipboard()
|
||||
break
|
||||
case 'clear':
|
||||
this.clear()
|
||||
break
|
||||
case 'zoom-in':
|
||||
this.zoomIn()
|
||||
break
|
||||
case 'zoom-out':
|
||||
this.zoomOut()
|
||||
break
|
||||
case 'reset-zoom':
|
||||
this.resetZoom()
|
||||
break
|
||||
case 'home':
|
||||
this.sendInput('\x1bOH')
|
||||
break
|
||||
case 'end':
|
||||
this.sendInput('\x1bOF')
|
||||
break
|
||||
case 'previous-word':
|
||||
this.sendInput('\x1bb')
|
||||
break
|
||||
case 'next-word':
|
||||
this.sendInput('\x1bf')
|
||||
break
|
||||
case 'delete-previous-word':
|
||||
this.sendInput('\x1b\x7f')
|
||||
break
|
||||
case 'delete-next-word':
|
||||
this.sendInput('\x1bd')
|
||||
break
|
||||
}
|
||||
})
|
||||
this.bellPlayer = document.createElement('audio')
|
||||
|
@@ -75,7 +75,13 @@ export class TerminalConfigProvider extends ConfigProvider {
|
||||
['Ctrl-A', 'Ctrl-C'],
|
||||
'⌘-T',
|
||||
'⌘-N',
|
||||
]
|
||||
],
|
||||
'home': ['⌘-ArrowLeft', 'Home'],
|
||||
'end': ['⌘-ArrowRight', 'End'],
|
||||
'previous-word': ['⌥-ArrowLeft'],
|
||||
'next-word': ['⌥-ArrowRight'],
|
||||
'delete-previous-word': ['⌥-Backspace'],
|
||||
'delete-next-word': ['⌥-Delete'],
|
||||
},
|
||||
},
|
||||
[Platform.Windows]: {
|
||||
@@ -108,7 +114,13 @@ export class TerminalConfigProvider extends ConfigProvider {
|
||||
['Ctrl-A', 'C'],
|
||||
['Ctrl-A', 'Ctrl-C'],
|
||||
'Ctrl-Shift-T',
|
||||
]
|
||||
],
|
||||
'home': ['Home'],
|
||||
'end': ['End'],
|
||||
'previous-word': ['Ctrl-ArrowLeft'],
|
||||
'next-word': ['Ctrl-ArrowRight'],
|
||||
'delete-previous-word': ['Ctrl-Backspace'],
|
||||
'delete-next-word': ['Ctrl-Delete'],
|
||||
},
|
||||
},
|
||||
[Platform.Linux]: {
|
||||
@@ -139,7 +151,13 @@ export class TerminalConfigProvider extends ConfigProvider {
|
||||
['Ctrl-A', 'C'],
|
||||
['Ctrl-A', 'Ctrl-C'],
|
||||
'Ctrl-Shift-T',
|
||||
]
|
||||
],
|
||||
'home': ['Home'],
|
||||
'end': ['End'],
|
||||
'previous-word': ['Ctrl-ArrowLeft'],
|
||||
'next-word': ['Ctrl-ArrowRight'],
|
||||
'delete-previous-word': ['Ctrl-Backspace'],
|
||||
'delete-next-word': ['Ctrl-Delete'],
|
||||
},
|
||||
},
|
||||
}
|
||||
|
@@ -8,6 +8,30 @@ export class TerminalHotkeyProvider extends HotkeyProvider {
|
||||
id: 'copy',
|
||||
name: 'Copy to clipboard',
|
||||
},
|
||||
{
|
||||
id: 'home',
|
||||
name: 'Beginning of the line',
|
||||
},
|
||||
{
|
||||
id: 'end',
|
||||
name: 'End of the line',
|
||||
},
|
||||
{
|
||||
id: 'previous-word',
|
||||
name: 'Jump to previous word',
|
||||
},
|
||||
{
|
||||
id: 'next-word',
|
||||
name: 'Jump to next word',
|
||||
},
|
||||
{
|
||||
id: 'delete-previous-word',
|
||||
name: 'Delete previous word',
|
||||
},
|
||||
{
|
||||
id: 'delete-next-word',
|
||||
name: 'Delete next word',
|
||||
},
|
||||
{
|
||||
id: 'clear',
|
||||
name: 'Clear terminal',
|
||||
|
@@ -8,6 +8,15 @@ a:hover {
|
||||
|
||||
x-screen {
|
||||
transition: 0.125s ease background;
|
||||
|
||||
&::-webkit-scrollbar {
|
||||
width: 3px;
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-thumb {
|
||||
background: rgba(255, 255, 255, 0.2);
|
||||
}
|
||||
}
|
||||
|
||||
x-row > span {
|
||||
|
@@ -3,6 +3,8 @@ import { execFileSync } from 'child_process'
|
||||
import * as AsyncLock from 'async-lock'
|
||||
import { ConnectableObservable, AsyncSubject, Subject } from 'rxjs'
|
||||
import * as childProcess from 'child_process'
|
||||
|
||||
import { Logger } from 'terminus-core'
|
||||
import { SessionOptions, SessionPersistenceProvider } from '../api'
|
||||
|
||||
declare function delay (ms: number): Promise<void>
|
||||
@@ -52,10 +54,11 @@ export class TMuxCommandProcess {
|
||||
private block$ = new Subject<TMuxBlock>()
|
||||
private response$: ConnectableObservable<TMuxBlock>
|
||||
private lock = new AsyncLock({ timeout: 1000 })
|
||||
private logger = new Logger(null, 'tmuxProcess')
|
||||
|
||||
constructor () {
|
||||
this.process = childProcess.spawn('tmux', ['-C', '-f', '/dev/null', '-L', 'terminus', 'new-session', '-A', '-D', '-s', 'control'])
|
||||
console.log('[tmux] started')
|
||||
this.logger.log('started')
|
||||
this.process.stdout.on('data', data => {
|
||||
// console.debug('tmux says:', data.toString())
|
||||
this.rawOutput$.next(data.toString())
|
||||
@@ -103,18 +106,18 @@ export class TMuxCommandProcess {
|
||||
this.response$.connect()
|
||||
|
||||
this.block$.subscribe(block => {
|
||||
console.debug('[tmux] block:', block)
|
||||
this.logger.debug('block:', block)
|
||||
})
|
||||
|
||||
this.message$.subscribe(message => {
|
||||
console.debug('[tmux] message:', message)
|
||||
this.logger.debug('message:', message)
|
||||
})
|
||||
}
|
||||
|
||||
command (command: string): Promise<TMuxBlock> {
|
||||
return this.lock.acquire('key', () => {
|
||||
let p = this.response$.take(1).toPromise()
|
||||
console.debug('[tmux] command:', command)
|
||||
this.logger.debug('command:', command)
|
||||
this.process.stdin.write(command + '\n')
|
||||
return p
|
||||
}).then(response => {
|
||||
@@ -137,13 +140,18 @@ export class TMuxCommandProcess {
|
||||
export class TMux {
|
||||
private process: TMuxCommandProcess
|
||||
private ready: Promise<void>
|
||||
private logger = new Logger(null, 'tmux')
|
||||
|
||||
constructor () {
|
||||
this.process = new TMuxCommandProcess()
|
||||
this.ready = (async () => {
|
||||
for (let line of TMUX_CONFIG.split('\n')) {
|
||||
if (line) {
|
||||
await this.process.command(line)
|
||||
try {
|
||||
await this.process.command(line)
|
||||
} catch (e) {
|
||||
this.logger.warn('Skipping failing config line:', line)
|
||||
}
|
||||
}
|
||||
}
|
||||
// Tmux sometimes sends a stray response block at start
|
||||
|
@@ -34,7 +34,7 @@ export class TerminalService {
|
||||
|
||||
async openTab (shell?: IShell, cwd?: string): Promise<TerminalTabComponent> {
|
||||
if (!cwd) {
|
||||
if (this.app.activeTab instanceof TerminalTabComponent) {
|
||||
if (this.app.activeTab instanceof TerminalTabComponent && this.app.activeTab.session) {
|
||||
cwd = await this.app.activeTab.session.getWorkingDirectory()
|
||||
} else {
|
||||
cwd = this.config.store.terminal.workingDirectory || null
|
||||
|
@@ -36,12 +36,20 @@ export class WindowsStockShellsProvider extends ShellProvider {
|
||||
{ id: 'cmd', name: 'CMD (stock)', command: 'cmd.exe' },
|
||||
{
|
||||
id: 'powershell',
|
||||
name: 'PowerShell',
|
||||
name: 'Windows PowerShell',
|
||||
command: 'powershell.exe',
|
||||
env: {
|
||||
TERM: 'cygwin',
|
||||
}
|
||||
},
|
||||
{
|
||||
id: 'powershell-core',
|
||||
name: 'PowerShell Core',
|
||||
command: 'pwsh.exe',
|
||||
env: {
|
||||
TERM: 'cygwin',
|
||||
}
|
||||
},
|
||||
]
|
||||
}
|
||||
}
|
||||
|
48
yarn.lock
@@ -43,9 +43,9 @@
|
||||
version "7.0.5"
|
||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-7.0.5.tgz#96a0f0a618b7b606f1ec547403c00650210bfbb7"
|
||||
|
||||
"@types/node@^7.0.18":
|
||||
version "7.0.52"
|
||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-7.0.52.tgz#8990d3350375542b0c21a83cd0331e6a8fc86716"
|
||||
"@types/node@^8.0.24":
|
||||
version "8.9.5"
|
||||
resolved "http://registry.npmjs.org/@types/node/-/node-8.9.5.tgz#162b864bc70be077e6db212b322754917929e976"
|
||||
|
||||
"@types/webpack-env@1.13.0":
|
||||
version "1.13.0"
|
||||
@@ -1179,7 +1179,7 @@ debug@^3.1.0:
|
||||
dependencies:
|
||||
ms "2.0.0"
|
||||
|
||||
debuglog@*, debuglog@^1.0.1:
|
||||
debuglog@^1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/debuglog/-/debuglog-1.0.1.tgz#aa24ffb9ac3df9a2351837cfb2d279360cd78492"
|
||||
|
||||
@@ -1459,11 +1459,11 @@ electron-to-chromium@^1.2.7:
|
||||
version "1.3.31"
|
||||
resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.31.tgz#00d832cba9fe2358652b0c48a8816c8e3a037e9f"
|
||||
|
||||
electron@1.6.11:
|
||||
version "1.6.11"
|
||||
resolved "https://registry.yarnpkg.com/electron/-/electron-1.6.11.tgz#be79c0ebdcefedb5bf28117409800fa53baceffa"
|
||||
electron@^1.8.4:
|
||||
version "1.8.4"
|
||||
resolved "https://registry.yarnpkg.com/electron/-/electron-1.8.4.tgz#cca8d0e6889f238f55b414ad224f03e03b226a38"
|
||||
dependencies:
|
||||
"@types/node" "^7.0.18"
|
||||
"@types/node" "^8.0.24"
|
||||
electron-download "^3.0.1"
|
||||
extract-zip "^1.0.3"
|
||||
|
||||
@@ -2272,7 +2272,7 @@ import-lazy@^2.1.0:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.yarnpkg.com/import-lazy/-/import-lazy-2.1.0.tgz#05698e3d45c88e8d7e9d92cb0584e77f096f3e43"
|
||||
|
||||
imurmurhash@*, imurmurhash@^0.1.4:
|
||||
imurmurhash@^0.1.4:
|
||||
version "0.1.4"
|
||||
resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea"
|
||||
|
||||
@@ -2813,10 +2813,6 @@ lockfile@~1.0.3:
|
||||
version "1.0.3"
|
||||
resolved "https://registry.yarnpkg.com/lockfile/-/lockfile-1.0.3.tgz#2638fc39a0331e9cac1a04b71799931c9c50df79"
|
||||
|
||||
lodash._baseindexof@*:
|
||||
version "3.1.0"
|
||||
resolved "https://registry.yarnpkg.com/lodash._baseindexof/-/lodash._baseindexof-3.1.0.tgz#fe52b53a1c6761e42618d654e4a25789ed61822c"
|
||||
|
||||
lodash._baseuniq@~4.6.0:
|
||||
version "4.6.0"
|
||||
resolved "https://registry.yarnpkg.com/lodash._baseuniq/-/lodash._baseuniq-4.6.0.tgz#0ebb44e456814af7905c6212fa2c9b2d51b841e8"
|
||||
@@ -2824,28 +2820,10 @@ lodash._baseuniq@~4.6.0:
|
||||
lodash._createset "~4.0.0"
|
||||
lodash._root "~3.0.0"
|
||||
|
||||
lodash._bindcallback@*:
|
||||
version "3.0.1"
|
||||
resolved "https://registry.yarnpkg.com/lodash._bindcallback/-/lodash._bindcallback-3.0.1.tgz#e531c27644cf8b57a99e17ed95b35c748789392e"
|
||||
|
||||
lodash._cacheindexof@*:
|
||||
version "3.0.2"
|
||||
resolved "https://registry.yarnpkg.com/lodash._cacheindexof/-/lodash._cacheindexof-3.0.2.tgz#3dc69ac82498d2ee5e3ce56091bafd2adc7bde92"
|
||||
|
||||
lodash._createcache@*:
|
||||
version "3.1.2"
|
||||
resolved "https://registry.yarnpkg.com/lodash._createcache/-/lodash._createcache-3.1.2.tgz#56d6a064017625e79ebca6b8018e17440bdcf093"
|
||||
dependencies:
|
||||
lodash._getnative "^3.0.0"
|
||||
|
||||
lodash._createset@~4.0.0:
|
||||
version "4.0.3"
|
||||
resolved "https://registry.yarnpkg.com/lodash._createset/-/lodash._createset-4.0.3.tgz#0f4659fbb09d75194fa9e2b88a6644d363c9fe26"
|
||||
|
||||
lodash._getnative@*, lodash._getnative@^3.0.0:
|
||||
version "3.9.1"
|
||||
resolved "https://registry.yarnpkg.com/lodash._getnative/-/lodash._getnative-3.9.1.tgz#570bc7dede46d61cdcde687d65d3eecbaa3aaff5"
|
||||
|
||||
lodash._root@~3.0.0:
|
||||
version "3.0.1"
|
||||
resolved "https://registry.yarnpkg.com/lodash._root/-/lodash._root-3.0.1.tgz#fba1c4524c19ee9a5f8136b4609f017cf4ded692"
|
||||
@@ -2870,10 +2848,6 @@ lodash.mergewith@^4.6.0:
|
||||
version "4.6.0"
|
||||
resolved "https://registry.yarnpkg.com/lodash.mergewith/-/lodash.mergewith-4.6.0.tgz#150cf0a16791f5903b8891eab154609274bdea55"
|
||||
|
||||
lodash.restparam@*:
|
||||
version "3.6.1"
|
||||
resolved "https://registry.yarnpkg.com/lodash.restparam/-/lodash.restparam-3.6.1.tgz#936a4e309ef330a7645ed4145986c85ae5b20805"
|
||||
|
||||
lodash.tail@^4.1.1:
|
||||
version "4.1.1"
|
||||
resolved "https://registry.yarnpkg.com/lodash.tail/-/lodash.tail-4.1.1.tgz#d2333a36d9e7717c8ad2f7cacafec7c32b444664"
|
||||
@@ -4470,7 +4444,7 @@ readable-stream@~1.1.10, readable-stream@~1.1.9:
|
||||
isarray "0.0.1"
|
||||
string_decoder "~0.10.x"
|
||||
|
||||
readdir-scoped-modules@*, readdir-scoped-modules@^1.0.0:
|
||||
readdir-scoped-modules@^1.0.0:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/readdir-scoped-modules/-/readdir-scoped-modules-1.0.2.tgz#9fafa37d286be5d92cbaebdee030dc9b5f406747"
|
||||
dependencies:
|
||||
@@ -5542,7 +5516,7 @@ val-loader@0.5.0:
|
||||
dependencies:
|
||||
loader-utils "0.2.x"
|
||||
|
||||
validate-npm-package-license@*, validate-npm-package-license@^3.0.1:
|
||||
validate-npm-package-license@^3.0.1:
|
||||
version "3.0.1"
|
||||
resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.1.tgz#2804babe712ad3379459acfbe24746ab2c303fbc"
|
||||
dependencies:
|
||||
|