mirror of
https://github.com/Eugeny/tabby.git
synced 2025-08-01 15:06:59 +00:00
Compare commits
37 Commits
v1.0.0-alp
...
v1.0.0-alp
Author | SHA1 | Date | |
---|---|---|---|
![]() |
c84de4c39c | ||
![]() |
649eb63f9b | ||
![]() |
ffc68401a7 | ||
![]() |
ef7b1ad5d9 | ||
![]() |
5bd8fb63e5 | ||
![]() |
addf57960d | ||
![]() |
768d222d05 | ||
![]() |
07792c227e | ||
![]() |
d1e3f282a1 | ||
![]() |
a18124043c | ||
![]() |
b3abe32321 | ||
![]() |
665a8e714e | ||
![]() |
2ec3833977 | ||
![]() |
73eb8bdbe7 | ||
![]() |
5a5cd09832 | ||
![]() |
c2f4c343a7 | ||
![]() |
153cd1ec9a | ||
![]() |
0254cabdde | ||
![]() |
9eee600ccc | ||
![]() |
24288fac9a | ||
![]() |
441164363f | ||
![]() |
3d7a4a1e0e | ||
![]() |
7984313b06 | ||
![]() |
89cc6c0d20 | ||
![]() |
d104f5e771 | ||
![]() |
5b5d145bd0 | ||
![]() |
78212a9538 | ||
![]() |
1b1b2af545 | ||
![]() |
f3f969a006 | ||
![]() |
621a6d8127 | ||
![]() |
87933edb96 | ||
![]() |
a931d47c23 | ||
![]() |
1ae027f17c | ||
![]() |
5360b2f292 | ||
![]() |
d806fb6e1e | ||
![]() |
57de182013 | ||
![]() |
3fd57e81a6 |
@@ -118,3 +118,5 @@ export default class MyModule { }
|
||||
|
||||
|
||||
See `terminus-core/src/api.ts`, `terminus-settings/src/api.ts` and `terminus-terminal/src/api.ts` for the available extension points.
|
||||
|
||||
Publish your plugin on NPM with a `terminus-plugin` keyword to make it appear in the Plugin Manager.
|
||||
|
@@ -14,7 +14,7 @@
|
||||
* Full Unicode support including double-width characters
|
||||
* Doesn't choke on fast-flowing outputs
|
||||
* Proper shell-like experience on Windows including tab completion (via Clink)
|
||||
* CMD, PowerShell, PowerShell Core, Cygwin, Cmder, Git-Bash and WSL (Bash on Windows) support
|
||||
* PowerShell Core, WSL (Bash on Windows), PowerShell, Git-Bash, Cygwin, Cmder and CMD support
|
||||
* Tab persistence on macOS and Linux
|
||||
|
||||
---
|
||||
@@ -34,9 +34,9 @@ Plugins can be installed directly from the Settings view inside Terminus.
|
||||
|
||||
# Contributing
|
||||
|
||||
Pull requests and plugins are welcome! Publish your plugin on NPM with a `terminus-plugin` keyword to make it appear in the Plugin Manager.
|
||||
Pull requests and plugins are welcome!
|
||||
|
||||
See [HACKING.md](https://github.com/Eugeny/terminus/blob/master/HACKING.md) for a very brief plugin development tutorial!
|
||||
See [HACKING.md](https://github.com/Eugeny/terminus/blob/master/HACKING.md) for information of how the project is laid out, and a very brief plugin development tutorial.
|
||||
|
||||
|
||||
## License
|
||||
|
@@ -1,4 +1,5 @@
|
||||
import { app, ipcMain, Menu, Tray, shell } from 'electron'
|
||||
import { loadConfig } from './config'
|
||||
import { Window } from './window'
|
||||
|
||||
export class Application {
|
||||
@@ -9,6 +10,14 @@ export class Application {
|
||||
ipcMain.on('app:config-change', () => {
|
||||
this.broadcast('host:config-change')
|
||||
})
|
||||
|
||||
const configData = loadConfig()
|
||||
if (process.platform === 'linux' && ((configData.appearance || {}).opacity || 1) !== 1) {
|
||||
app.commandLine.appendSwitch('enable-transparent-visuals')
|
||||
app.disableHardwareAcceleration()
|
||||
}
|
||||
|
||||
app.commandLine.appendSwitch('disable-http-cache')
|
||||
}
|
||||
|
||||
async newWindow (): Promise<Window> {
|
||||
|
13
app/lib/config.ts
Normal file
13
app/lib/config.ts
Normal file
@@ -0,0 +1,13 @@
|
||||
import * as fs from 'fs'
|
||||
import * as path from 'path'
|
||||
import * as yaml from 'js-yaml'
|
||||
import { app } from 'electron'
|
||||
|
||||
export function loadConfig (): any {
|
||||
let configPath = path.join(app.getPath('userData'), 'config.yaml')
|
||||
if (fs.existsSync(configPath)) {
|
||||
return yaml.safeLoad(fs.readFileSync(configPath, 'utf8'))
|
||||
} else {
|
||||
return {}
|
||||
}
|
||||
}
|
@@ -11,8 +11,6 @@ if (!process.env.TERMINUS_PLUGINS) {
|
||||
|
||||
const application = new Application()
|
||||
|
||||
app.commandLine.appendSwitch('disable-http-cache')
|
||||
|
||||
ipcMain.on('app:new-window', () => {
|
||||
console.log('new-window')
|
||||
application.newWindow()
|
||||
|
@@ -1,33 +1,30 @@
|
||||
import { Subject, Observable } from 'rxjs'
|
||||
import { BrowserWindow, app, ipcMain, Rectangle, Menu } from 'electron'
|
||||
import { BrowserWindow, app, ipcMain, Rectangle } from 'electron'
|
||||
import ElectronConfig = require('electron-config')
|
||||
import * as yaml from 'js-yaml'
|
||||
import * as fs from 'fs'
|
||||
import * as path from 'path'
|
||||
import * as os from 'os'
|
||||
|
||||
let electronVibrancy: any
|
||||
if (process.platform !== 'linux') {
|
||||
electronVibrancy = require('electron-vibrancy')
|
||||
import { loadConfig } from './config'
|
||||
|
||||
let SetWindowCompositionAttribute: any
|
||||
let AccentState: any
|
||||
let DwmEnableBlurBehindWindow: any
|
||||
if (process.platform === 'win32') {
|
||||
SetWindowCompositionAttribute = require('windows-swca').SetWindowCompositionAttribute
|
||||
AccentState = require('windows-swca').AccentState
|
||||
DwmEnableBlurBehindWindow = require('windows-blurbehind').DwmEnableBlurBehindWindow
|
||||
}
|
||||
|
||||
export class Window {
|
||||
ready: Promise<void>
|
||||
private visible = new Subject<boolean>()
|
||||
private window: BrowserWindow
|
||||
private vibrancyViewID: number
|
||||
private windowConfig: ElectronConfig
|
||||
private windowBounds: Rectangle
|
||||
|
||||
get visible$ (): Observable<boolean> { return this.visible }
|
||||
|
||||
constructor () {
|
||||
let configPath = path.join(app.getPath('userData'), 'config.yaml')
|
||||
let configData
|
||||
if (fs.existsSync(configPath)) {
|
||||
configData = yaml.safeLoad(fs.readFileSync(configPath, 'utf8'))
|
||||
} else {
|
||||
configData = {}
|
||||
}
|
||||
let configData = loadConfig()
|
||||
|
||||
this.windowConfig = new ElectronConfig({ name: 'window' })
|
||||
this.windowBounds = this.windowConfig.get('windowBoundaries')
|
||||
@@ -42,6 +39,7 @@ export class Window {
|
||||
webPreferences: { webSecurity: false },
|
||||
frame: false,
|
||||
show: false,
|
||||
backgroundColor: '#00000000'
|
||||
}
|
||||
Object.assign(options, this.windowBounds)
|
||||
|
||||
@@ -53,10 +51,6 @@ export class Window {
|
||||
}
|
||||
}
|
||||
|
||||
if (process.platform === 'win32' && (configData.appearance || {}).vibrancy) {
|
||||
options.transparent = true
|
||||
}
|
||||
|
||||
if (process.platform === 'linux') {
|
||||
options.backgroundColor = '#131d27'
|
||||
}
|
||||
@@ -95,11 +89,22 @@ export class Window {
|
||||
}
|
||||
|
||||
setVibrancy (enabled: boolean) {
|
||||
if (enabled && !this.vibrancyViewID) {
|
||||
this.vibrancyViewID = electronVibrancy.SetVibrancy(this.window, 0)
|
||||
} else if (!enabled && this.vibrancyViewID) {
|
||||
electronVibrancy.RemoveView(this.window, this.vibrancyViewID)
|
||||
this.vibrancyViewID = null
|
||||
if (process.platform === 'win32') {
|
||||
if (parseFloat(os.release()) >= 10) {
|
||||
let attribValue = AccentState.ACCENT_DISABLED
|
||||
let color = 0x00000000
|
||||
if (enabled) {
|
||||
if (parseInt(os.release().split('.')[2]) >= 17063) {
|
||||
attribValue = AccentState.ACCENT_ENABLE_FLUENT
|
||||
color = 0x01000000 // using a small alpha because acrylic bugs out at full transparency.
|
||||
} else {
|
||||
attribValue = AccentState.ACCENT_ENABLE_BLURBEHIND
|
||||
}
|
||||
}
|
||||
SetWindowCompositionAttribute(this.window, attribValue, color)
|
||||
} else {
|
||||
DwmEnableBlurBehindWindow(this.window, enabled)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -188,10 +193,6 @@ export class Window {
|
||||
ipcMain.on('window-set-title', (_event, title) => {
|
||||
this.window.setTitle(title)
|
||||
})
|
||||
|
||||
ipcMain.on('window-popup-context-menu', (_event, menuDefinition) => {
|
||||
Menu.buildFromTemplate(menuDefinition).popup({ window: this.window })
|
||||
})
|
||||
}
|
||||
|
||||
private destroy () {
|
||||
|
@@ -25,15 +25,18 @@
|
||||
"electron-debug": "^2.0.0",
|
||||
"electron-is-dev": "0.1.2",
|
||||
"electron-squirrel-startup": "^1.0.0",
|
||||
"electron-vibrancy": "^0.1.3",
|
||||
"js-yaml": "3.8.2",
|
||||
"mz": "^2.6.0",
|
||||
"ngx-toastr": "^8.7.3",
|
||||
"path": "0.12.7",
|
||||
"rxjs": "^6.1.0",
|
||||
"rxjs": "^6.3.3",
|
||||
"yargs": "^12.0.1",
|
||||
"zone.js": "~0.8.26"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"windows-blurbehind": "^1.0.0",
|
||||
"windows-swca": "^1.1.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/mz": "0.0.31"
|
||||
}
|
||||
|
@@ -41,6 +41,8 @@ module.exports = {
|
||||
mz: 'commonjs mz',
|
||||
path: 'commonjs path',
|
||||
yargs: 'commonjs yargs',
|
||||
'windows-swca': 'commonjs windows-swca',
|
||||
'windows-blurbehind': 'commonjs windows-blurbehind',
|
||||
},
|
||||
plugins: [
|
||||
new webpack.optimize.ModuleConcatenationPlugin(),
|
||||
|
@@ -80,10 +80,6 @@ argparse@^1.0.7:
|
||||
dependencies:
|
||||
sprintf-js "~1.0.2"
|
||||
|
||||
bindings@^1.2.1:
|
||||
version "1.3.0"
|
||||
resolved "https://registry.yarnpkg.com/bindings/-/bindings-1.3.0.tgz#b346f6ecf6a95f5a815c5839fc7cdb22502f1ed7"
|
||||
|
||||
camelcase@^4.1.0:
|
||||
version "4.1.0"
|
||||
resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-4.1.0.tgz#d545635be1e33c542649c69173e5de6acfae34dd"
|
||||
@@ -183,13 +179,6 @@ electron-squirrel-startup@^1.0.0:
|
||||
dependencies:
|
||||
debug "^2.2.0"
|
||||
|
||||
electron-vibrancy@^0.1.3:
|
||||
version "0.1.3"
|
||||
resolved "https://registry.yarnpkg.com/electron-vibrancy/-/electron-vibrancy-0.1.3.tgz#04382dd6e030e5ca5e60f8e024033738cb8479e3"
|
||||
dependencies:
|
||||
bindings "^1.2.1"
|
||||
nan "^2.0.5"
|
||||
|
||||
env-paths@^0.3.0:
|
||||
version "0.3.1"
|
||||
resolved "https://registry.yarnpkg.com/env-paths/-/env-paths-0.3.1.tgz#c30ccfcbc30c890943dc08a85582517ef00da463"
|
||||
@@ -336,10 +325,6 @@ mz@^2.6.0:
|
||||
object-assign "^4.0.1"
|
||||
thenify-all "^1.0.0"
|
||||
|
||||
nan@^2.0.5:
|
||||
version "2.10.0"
|
||||
resolved "https://registry.yarnpkg.com/nan/-/nan-2.10.0.tgz#96d0cd610ebd58d4b4de9cc0c6828cda99c7548f"
|
||||
|
||||
ngx-toastr@^8.7.3:
|
||||
version "8.7.3"
|
||||
resolved "https://registry.yarnpkg.com/ngx-toastr/-/ngx-toastr-8.7.3.tgz#d3b7a8077ba1c860dd8a44779ccad38c5ea15c92"
|
||||
@@ -441,9 +426,9 @@ require-main-filename@^1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-1.0.1.tgz#97f717b69d48784f5f526a6c5aa8ffdda055a4d1"
|
||||
|
||||
rxjs@^6.1.0:
|
||||
version "6.1.0"
|
||||
resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.1.0.tgz#833447de4e4f6427b9cec3e5eb9f56415cd28315"
|
||||
rxjs@^6.3.3:
|
||||
version "6.3.3"
|
||||
resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.3.3.tgz#3c6a7fa420e844a81390fb1158a9ec614f4bad55"
|
||||
dependencies:
|
||||
tslib "^1.9.0"
|
||||
|
||||
@@ -532,6 +517,14 @@ which@^1.2.9:
|
||||
dependencies:
|
||||
isexe "^2.0.0"
|
||||
|
||||
windows-blurbehind@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/windows-blurbehind/-/windows-blurbehind-1.0.0.tgz#050efb988704c44335bdc3efefd757f6e463b8ac"
|
||||
|
||||
windows-swca@^1.1.1:
|
||||
version "1.1.1"
|
||||
resolved "https://registry.yarnpkg.com/windows-swca/-/windows-swca-1.1.1.tgz#0b3530278c67d408baac71c3a6aeb16d55318bf8"
|
||||
|
||||
wrap-ansi@^2.0.0:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-2.1.0.tgz#d8fc3d284dd05794fe84973caecdd1cf824fdd85"
|
||||
|
@@ -4,7 +4,7 @@ platform:
|
||||
- x64
|
||||
|
||||
environment:
|
||||
nodejs_version: "7"
|
||||
nodejs_version: "10"
|
||||
|
||||
cache:
|
||||
- '%USERPROFILE%\.electron'
|
||||
|
4
build/linux/after-install.tpl
Normal file
4
build/linux/after-install.tpl
Normal file
@@ -0,0 +1,4 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Link to the binary
|
||||
ln -sf '/opt/${productFilename}/${executable}' '/usr/bin/${executable}'
|
Binary file not shown.
Before Width: | Height: | Size: 106 KiB After Width: | Height: | Size: 112 KiB |
@@ -1,92 +1,16 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="1024"
|
||||
height="1024"
|
||||
viewBox="0 0 270.93332 270.93333"
|
||||
version="1.1"
|
||||
id="svg8"
|
||||
inkscape:version="0.92.3 (2405546, 2018-03-11)"
|
||||
sodipodi:docname="icon.svg"
|
||||
inkscape:export-filename="D:\Users\Ich\Downloads\64x64.png"
|
||||
inkscape:export-xdpi="6"
|
||||
inkscape:export-ydpi="6">
|
||||
<defs
|
||||
id="defs2" />
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="0.35355339"
|
||||
inkscape:cx="-57.249603"
|
||||
inkscape:cy="781.4887"
|
||||
inkscape:document-units="px"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="false"
|
||||
inkscape:snap-bbox="true"
|
||||
inkscape:window-width="1858"
|
||||
inkscape:window-height="1050"
|
||||
inkscape:window-x="54"
|
||||
inkscape:window-y="1079"
|
||||
inkscape:window-maximized="1"
|
||||
fit-margin-top="0"
|
||||
fit-margin-left="0"
|
||||
fit-margin-right="0"
|
||||
fit-margin-bottom="0"
|
||||
inkscape:snap-intersection-paths="true"
|
||||
inkscape:object-paths="true"
|
||||
units="px" />
|
||||
<metadata
|
||||
id="metadata5">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1"
|
||||
transform="translate(-47.511065,70.941737)">
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path138"
|
||||
style="opacity:0.9;fill:#bfd9f1;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.43524027px;stroke-linecap:butt;stroke-linejoin:round;stroke-opacity:1"
|
||||
d="M 64.949149,-45.402272 213.30911,40.153203 168.74736,65.880709 64.949181,2.5692907 Z"
|
||||
sodipodi:nodetypes="ccccc" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path116"
|
||||
style="opacity:0.9;fill:#6666af;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.43524027px;stroke-linecap:butt;stroke-linejoin:round;stroke-opacity:1"
|
||||
d="m 301.0092,42.179959 -0.003,50.177506 -190.42255,107.635545 -0.003,-48.17143 z"
|
||||
sodipodi:nodetypes="ccccc" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path118"
|
||||
style="opacity:0.9;fill:#bfd9f1;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.43524027px;stroke-linecap:butt;stroke-linejoin:round;stroke-opacity:1"
|
||||
d="m 64.948697,125.47711 45.629963,26.34447 0.005,48.17143 -45.637407,-26.50135 z"
|
||||
sodipodi:nodetypes="ccccc" />
|
||||
<path
|
||||
style="opacity:0.9;fill:#9dbef0;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.44854069px;stroke-linecap:butt;stroke-linejoin:round;stroke-opacity:1"
|
||||
d="M 105.39355,-70.939125 64.949149,-45.402272 213.30911,40.153203 64.948697,125.47711 110.57866,151.82158 260.4947,65.557719 301.0092,42.179959 Z"
|
||||
id="path134"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cccccccc" />
|
||||
</g>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg width="100%" height="100%" viewBox="0 0 426 426" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:1.41421;">
|
||||
<g id="Layer-1" serif:id="Layer 1" transform="matrix(1,0,0,1,-29.3571,-233.318)">
|
||||
<g>
|
||||
<path id="path138" d="M93.68,293.848L287.16,405.423L229.046,438.975L93.68,356.409L93.68,293.848Z" style="fill:url(#_Linear1);"/>
|
||||
<path id="path118" d="M94.204,516.708L153.711,551.064L153.721,613.886L94.204,579.325L94.204,516.708Z" style="fill:url(#_Linear2);"/>
|
||||
</g>
|
||||
<path id="path116" d="M401.384,408.07L401.529,473.724L153.721,613.83L153.712,551.008L401.384,408.07Z" style="fill:rgb(0,94,167);fill-opacity:0.9;"/>
|
||||
<path id="path134" d="M148.072,261.343L92.84,293.232L287.16,405.423L93.366,517.309L153.198,551.853L346.992,439.967L402.224,408.078L148.072,261.343Z" style="fill:rgb(7,147,255);fill-opacity:0.9;"/>
|
||||
</g>
|
||||
<defs>
|
||||
<linearGradient id="_Linear1" x1="0" y1="0" x2="1" y2="0" gradientUnits="userSpaceOnUse" gradientTransform="matrix(193.48,0,0,320.038,93.6796,453.867)"><stop offset="0" style="stop-color:rgb(0,121,215);stop-opacity:0.9"/><stop offset="1" style="stop-color:rgb(40,97,156);stop-opacity:0.9"/></linearGradient>
|
||||
<linearGradient id="_Linear2" x1="0" y1="0" x2="1" y2="0" gradientUnits="userSpaceOnUse" gradientTransform="matrix(193.48,0,0,320.038,93.6796,453.867)"><stop offset="0" style="stop-color:rgb(0,121,215);stop-opacity:0.9"/><stop offset="1" style="stop-color:rgb(40,97,156);stop-opacity:0.9"/></linearGradient>
|
||||
</defs>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 3.5 KiB After Width: | Height: | Size: 1.8 KiB |
11
package.json
11
package.json
@@ -5,7 +5,7 @@
|
||||
"@types/electron-debug": "^1.1.0",
|
||||
"@types/fs-promise": "1.0.1",
|
||||
"@types/js-yaml": "^3.11.2",
|
||||
"@types/node": "7.0.5",
|
||||
"@types/node": "^10.11.5",
|
||||
"@types/webpack-env": "1.13.0",
|
||||
"apply-loader": "0.1.0",
|
||||
"awesome-typescript-loader": "^5.0.0",
|
||||
@@ -18,7 +18,7 @@
|
||||
"css-loader": "0.28.0",
|
||||
"electron": "3.0.0",
|
||||
"electron-builder": "^20.27.1",
|
||||
"electron-builder-squirrel-windows": "17.0.1",
|
||||
"electron-builder-squirrel-windows": "^20.28.3",
|
||||
"electron-installer-snap": "^3.0.0",
|
||||
"electron-rebuild": "^1.8.2",
|
||||
"eslint": "^5.4.0",
|
||||
@@ -38,7 +38,7 @@
|
||||
"node-gyp": "^3.6.2",
|
||||
"node-sass": "^4.5.3",
|
||||
"npmlog": "4.1.0",
|
||||
"npx": "^9.7.1",
|
||||
"npx": "^10.2.0",
|
||||
"pug": "^2.0.3",
|
||||
"pug-html-loader": "1.0.9",
|
||||
"pug-lint": "^2.5.0",
|
||||
@@ -56,7 +56,7 @@
|
||||
"tslint-config-standard": "5.0.2",
|
||||
"tslint-eslint-rules": "4.0.0",
|
||||
"typescript": "^2.8.3",
|
||||
"url-loader": "0.5.7",
|
||||
"url-loader": "^1.1.1",
|
||||
"val-loader": "0.5.0",
|
||||
"webpack": "^4.8.3",
|
||||
"webpack-cli": "^2.1.3",
|
||||
@@ -120,7 +120,8 @@
|
||||
"libxtst6",
|
||||
"libnss3",
|
||||
"tmux"
|
||||
]
|
||||
],
|
||||
"afterInstall": "build/linux/after-install.tpl"
|
||||
},
|
||||
"rpm": {
|
||||
"depends": [
|
||||
|
@@ -27,6 +27,7 @@
|
||||
"electron-updater": "^2.8.9",
|
||||
"ng2-dnd": "^5.0.2",
|
||||
"ngx-perfect-scrollbar": "^6.0.0",
|
||||
"rage-edit": "^1.1.0",
|
||||
"shell-escape": "^0.2.0",
|
||||
"universal-analytics": "^0.4.17"
|
||||
},
|
||||
@@ -43,7 +44,6 @@
|
||||
"dependencies": {
|
||||
"deepmerge": "^1.5.0",
|
||||
"js-yaml": "^3.9.0",
|
||||
"winreg": "^1.2.4",
|
||||
"winston": "^2.4.0"
|
||||
},
|
||||
"false": {}
|
||||
|
@@ -61,8 +61,7 @@ $tab-border-radius: 4px;
|
||||
-webkit-app-region: drag;
|
||||
|
||||
&.persistent {
|
||||
min-width: 100px;
|
||||
flex: 1 0 25%;
|
||||
min-width: 72px; // 2 x 36 px height, ie 2 squares
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -1,5 +1,5 @@
|
||||
import { Injectable } from '@angular/core'
|
||||
import { TouchBar, BrowserWindow } from 'electron'
|
||||
import { TouchBar, BrowserWindow, Menu } from 'electron'
|
||||
|
||||
@Injectable()
|
||||
export class ElectronService {
|
||||
@@ -14,6 +14,7 @@ export class ElectronService {
|
||||
remote: any
|
||||
TouchBar: typeof TouchBar
|
||||
BrowserWindow: typeof BrowserWindow
|
||||
Menu: typeof Menu
|
||||
private electron: any
|
||||
|
||||
constructor () {
|
||||
@@ -29,6 +30,7 @@ export class ElectronService {
|
||||
this.nativeImage = this.remote.nativeImage
|
||||
this.TouchBar = this.remote.TouchBar
|
||||
this.BrowserWindow = this.remote.BrowserWindow
|
||||
this.Menu = this.remote.Menu
|
||||
}
|
||||
|
||||
remoteRequire (name: string): any {
|
||||
|
@@ -169,7 +169,7 @@ export class HostAppService {
|
||||
}
|
||||
|
||||
popupContextMenu (menuDefinition: Electron.MenuItemConstructorOptions[]) {
|
||||
this.electron.ipcRenderer.send('window-popup-context-menu', menuDefinition)
|
||||
this.electron.Menu.buildFromTemplate(menuDefinition).popup({})
|
||||
}
|
||||
|
||||
broadcastConfigChange () {
|
||||
|
@@ -1,15 +1,11 @@
|
||||
import * as path from 'path'
|
||||
import * as fs from 'mz/fs'
|
||||
import { Registry } from 'rage-edit'
|
||||
import { exec } from 'mz/child_process'
|
||||
import { Injectable } from '@angular/core'
|
||||
import { ElectronService } from './electron.service'
|
||||
import { HostAppService, Platform } from './hostApp.service'
|
||||
|
||||
let Registry = null
|
||||
try {
|
||||
Registry = require('winreg')
|
||||
} catch (_) { } // tslint:disable-line no-empty
|
||||
|
||||
@Injectable()
|
||||
export class ShellIntegrationService {
|
||||
private automatorWorkflows = ['Open Terminus here.workflow', 'Paste path into Terminus.workflow']
|
||||
@@ -17,11 +13,11 @@ export class ShellIntegrationService {
|
||||
private automatorWorkflowsDestination: string
|
||||
private registryKeys = [
|
||||
{
|
||||
path: '\\Software\\Classes\\Directory\\Background\\shell\\Open Terminus here',
|
||||
path: 'HKCU\\Software\\Classes\\Directory\\Background\\shell\\Open Terminus here',
|
||||
command: 'open "%V"'
|
||||
},
|
||||
{
|
||||
path: '\\Software\\Classes\\*\\shell\\Paste path into Terminus',
|
||||
path: 'HKCU\\Software\\Classes\\*\\shell\\Paste path into Terminus',
|
||||
command: 'paste "%V"'
|
||||
},
|
||||
]
|
||||
@@ -38,16 +34,23 @@ export class ShellIntegrationService {
|
||||
)
|
||||
this.automatorWorkflowsDestination = path.join(process.env.HOME, 'Library', 'Services')
|
||||
}
|
||||
this.updatePaths()
|
||||
}
|
||||
|
||||
async updatePaths (): Promise<void> {
|
||||
// Update paths in case of an update
|
||||
if (this.hostApp.platform === Platform.Windows) {
|
||||
if (await this.isInstalled()) {
|
||||
await this.install()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async isInstalled (): Promise<boolean> {
|
||||
if (this.hostApp.platform === Platform.macOS) {
|
||||
return await fs.exists(path.join(this.automatorWorkflowsDestination, this.automatorWorkflows[0]))
|
||||
} else if (this.hostApp.platform === Platform.Windows) {
|
||||
return await new Promise<boolean>(resolve => {
|
||||
let reg = new Registry({ hive: Registry.HKCU, key: this.registryKeys[0].path, arch: 'x64' })
|
||||
reg.keyExists((err, exists) => resolve(!err && exists))
|
||||
})
|
||||
return await Registry.has(this.registryKeys[0].path)
|
||||
}
|
||||
return true
|
||||
}
|
||||
@@ -59,26 +62,8 @@ export class ShellIntegrationService {
|
||||
}
|
||||
} else if (this.hostApp.platform === Platform.Windows) {
|
||||
for (let registryKey of this.registryKeys) {
|
||||
let reg = new Registry({ hive: Registry.HKCU, key: registryKey.path, arch: 'x64' })
|
||||
await new Promise(resolve => {
|
||||
reg.set('Icon', Registry.REG_SZ, this.electron.app.getPath('exe'), () => {
|
||||
reg.create(() => {
|
||||
let cmd = new Registry({
|
||||
hive: Registry.HKCU,
|
||||
key: registryKey.path + '\\command',
|
||||
arch: 'x64'
|
||||
})
|
||||
cmd.create(() => {
|
||||
cmd.set(
|
||||
'',
|
||||
Registry.REG_SZ,
|
||||
this.electron.app.getPath('exe') + ' ' + registryKey.command,
|
||||
() => resolve()
|
||||
)
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
await Registry.set(registryKey.path, 'Icon', this.electron.app.getPath('exe'))
|
||||
await Registry.set(registryKey.path + '\\command', '', this.electron.app.getPath('exe') + ' ' + registryKey.command)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -414,6 +414,10 @@ qs@~6.5.1:
|
||||
version "6.5.2"
|
||||
resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.2.tgz#cb3ae806e8740444584ef154ce8ee98d403f3e36"
|
||||
|
||||
rage-edit@^1.1.0:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/rage-edit/-/rage-edit-1.1.0.tgz#8a5f0bf5c5ff4ab31ad086fa27a55be20fcd0357"
|
||||
|
||||
request@2.86.0:
|
||||
version "2.86.0"
|
||||
resolved "https://registry.yarnpkg.com/request/-/request-2.86.0.tgz#2b9497f449b0a32654c081a5cf426bbfb5bf5b69"
|
||||
@@ -549,10 +553,6 @@ verror@1.10.0:
|
||||
core-util-is "1.0.2"
|
||||
extsprintf "^1.2.0"
|
||||
|
||||
winreg@^1.2.4:
|
||||
version "1.2.4"
|
||||
resolved "https://registry.yarnpkg.com/winreg/-/winreg-1.2.4.tgz#ba065629b7a925130e15779108cf540990e98d1b"
|
||||
|
||||
winston@^2.4.0:
|
||||
version "2.4.0"
|
||||
resolved "https://registry.yarnpkg.com/winston/-/winston-2.4.0.tgz#808050b93d52661ed9fb6c26b3f0c826708b0aee"
|
||||
|
@@ -66,7 +66,7 @@ div(*ngIf='npmInstalled')
|
||||
i.fa.fa-fw.fa-search(*ngIf='availablePluginsReady')
|
||||
input.form-control(
|
||||
type='text',
|
||||
'[(ngModel)]'='_1',
|
||||
[(ngModel)]='_1',
|
||||
(ngModelChange)='searchAvailable(_1)',
|
||||
placeholder='Search plugins'
|
||||
)
|
||||
|
@@ -72,9 +72,13 @@ export class PluginManagerService {
|
||||
|
||||
listAvailable (query?: string): Observable<IPluginInfo[]> {
|
||||
return from(
|
||||
axios.get(`https://api.npms.io/v2/search?q=keywords%3A${KEYWORD}+${encodeURIComponent(query || '')}&from=0&size=250`, {})
|
||||
axios.get(`https://www.npmjs.com/search?q=keywords%3A${KEYWORD}+${encodeURIComponent(query || '')}&from=0&size=1000`, {
|
||||
headers: {
|
||||
'x-spiferack': '1',
|
||||
}
|
||||
})
|
||||
).pipe(
|
||||
map(response => response.data.results.map(item => ({
|
||||
map(response => response.data.objects.map(item => ({
|
||||
name: item.package.name.substring(NAME_PREFIX.length),
|
||||
packageName: item.package.name,
|
||||
description: item.package.description,
|
||||
|
@@ -44,7 +44,6 @@ module.exports = {
|
||||
'path',
|
||||
'mz/fs',
|
||||
'mz/child_process',
|
||||
'winreg',
|
||||
/^rxjs/,
|
||||
/^@angular/,
|
||||
/^@ng-bootstrap/,
|
||||
|
@@ -63,34 +63,19 @@ ngb-tabset.vertical(type='pills', [activeId]='activeTab')
|
||||
.header
|
||||
.title Vibrancy
|
||||
.description Gives the window a blurred transparent background
|
||||
|
||||
.btn-group(
|
||||
|
||||
toggle(
|
||||
[(ngModel)]='config.store.appearance.vibrancy',
|
||||
(ngModelChange)='config.save(); (hostApp.platform === Platform.Windows && config.requestRestart())',
|
||||
ngbRadioGroup
|
||||
(ngModelChange)='config.save()'
|
||||
)
|
||||
label.btn.btn-secondary(ngbButtonLabel)
|
||||
input(
|
||||
type='radio',
|
||||
ngbButton,
|
||||
[value]='true'
|
||||
)
|
||||
| Enable
|
||||
label.btn.btn-secondary(ngbButtonLabel)
|
||||
input(
|
||||
type='radio',
|
||||
ngbButton,
|
||||
[value]='false'
|
||||
)
|
||||
| Disable
|
||||
|
||||
.form-line(*ngIf='hostApp.platform !== Platform.Linux')
|
||||
.form-line
|
||||
.header
|
||||
.title Window opacity
|
||||
input(
|
||||
type='range',
|
||||
[(ngModel)]='config.store.appearance.opacity',
|
||||
(ngModelChange)='config.save()',
|
||||
(ngModelChange)='config.save(); (hostApp.platform === Platform.Linux && config.requestRestart())',
|
||||
min='0.05',
|
||||
max='1',
|
||||
step='0.01'
|
||||
@@ -259,8 +244,8 @@ ngb-tabset.vertical(type='pills', [activeId]='activeTab')
|
||||
td {{hotkey.id}}
|
||||
td
|
||||
multi-hotkey-input(
|
||||
'[(model)]'='config.store.hotkeys[hotkey.id]'
|
||||
'(modelChange)'='config.save(); docking.dock()'
|
||||
[(model)]='config.store.hotkeys[hotkey.id]',
|
||||
(modelChange)='config.save(); docking.dock()'
|
||||
)
|
||||
|
||||
ngb-tab(*ngFor='let provider of settingsProviders', [id]='provider.id')
|
||||
|
@@ -3,6 +3,8 @@ import { BaseSession } from 'terminus-terminal'
|
||||
export interface LoginScript {
|
||||
expect?: string
|
||||
send: string
|
||||
isRegex?: boolean
|
||||
optional?: boolean
|
||||
}
|
||||
|
||||
export interface SSHConnection {
|
||||
@@ -37,13 +39,35 @@ export class SSHSession extends BaseSession {
|
||||
if (this.scripts) {
|
||||
let found = false
|
||||
for (let script of this.scripts) {
|
||||
if (dataString.includes(script.expect)) {
|
||||
console.log('Executing script:', script.send)
|
||||
this.shell.write(script.send + '\n')
|
||||
this.scripts = this.scripts.filter(x => x !== script)
|
||||
found = true
|
||||
let match = false
|
||||
let cmd = ''
|
||||
if (script.isRegex) {
|
||||
let re = new RegExp(script.expect, 'g')
|
||||
if (dataString.match(re)) {
|
||||
cmd = dataString.replace(re, script.send)
|
||||
match = true
|
||||
found = true
|
||||
}
|
||||
} else {
|
||||
break
|
||||
if (dataString.includes(script.expect)) {
|
||||
cmd = script.send
|
||||
match = true
|
||||
found = true
|
||||
}
|
||||
}
|
||||
|
||||
if (match) {
|
||||
console.log('Executing script: "' + cmd + '"')
|
||||
this.shell.write(cmd + '\n')
|
||||
this.scripts = this.scripts.filter(x => x !== script)
|
||||
} else {
|
||||
if (script.optional) {
|
||||
console.log('Skip optional script: ' + script.expect)
|
||||
found = true
|
||||
this.scripts = this.scripts.filter(x => x !== script)
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -94,18 +94,28 @@
|
||||
tr
|
||||
th String to expect
|
||||
th String to be sent
|
||||
th Regex
|
||||
th Optional
|
||||
th Actions
|
||||
tr(*ngFor='let script of connection.scripts')
|
||||
td
|
||||
input.form-control(
|
||||
type='text',
|
||||
[(ngModel)]='script.expect'
|
||||
)
|
||||
type='text',
|
||||
[(ngModel)]='script.expect'
|
||||
)
|
||||
td
|
||||
input.form-control(
|
||||
type='text',
|
||||
[(ngModel)]='script.send'
|
||||
)
|
||||
type='text',
|
||||
[(ngModel)]='script.send'
|
||||
)
|
||||
td
|
||||
toggle(
|
||||
[(ngModel)]='script.isRegex',
|
||||
)
|
||||
td
|
||||
toggle(
|
||||
[(ngModel)]='script.optional',
|
||||
)
|
||||
td
|
||||
.input-group.flex-nowrap
|
||||
button.btn.btn-outline-info.ml-0((click)='moveScriptUp(script)')
|
||||
@@ -127,6 +137,14 @@
|
||||
placeholder='Enter a string to be sent',
|
||||
[(ngModel)]='newScript.send'
|
||||
)
|
||||
td
|
||||
toggle(
|
||||
[(ngModel)]='newScript.isRegex',
|
||||
)
|
||||
td
|
||||
toggle(
|
||||
[(ngModel)]='newScript.optional',
|
||||
)
|
||||
td
|
||||
.input-group.flex-nowrap
|
||||
button.btn.btn-outline-info.ml-0((click)='addScript()')
|
||||
|
@@ -83,5 +83,7 @@ export class EditConnectionModalComponent {
|
||||
clearScript () {
|
||||
this.newScript.expect = ''
|
||||
this.newScript.send = ''
|
||||
this.newScript.isRegex = false
|
||||
this.newScript.optional = false
|
||||
}
|
||||
}
|
||||
|
@@ -58,6 +58,10 @@ export class SSHModalComponent {
|
||||
this.close()
|
||||
this.ssh.connect(connection).catch(error => {
|
||||
this.toastr.error(`Could not connect: ${error}`)
|
||||
}).then(() => {
|
||||
setTimeout(() => {
|
||||
this.app.activeTab.emitFocused()
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
|
@@ -21,10 +21,10 @@
|
||||
"@types/mz": "0.0.31",
|
||||
"@types/node": "7.0.12",
|
||||
"@types/webpack-env": "1.13.0",
|
||||
"@types/winreg": "^1.2.30",
|
||||
"dataurl": "0.1.0",
|
||||
"deep-equal": "1.0.1",
|
||||
"file-loader": "^0.11.2",
|
||||
"rage-edit": "^1.1.0",
|
||||
"xterm": "^3.6.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
@@ -45,8 +45,7 @@
|
||||
"mz": "^2.6.0",
|
||||
"node-pty-tmp": "0.7.2",
|
||||
"ps-node": "^0.1.6",
|
||||
"runes": "^0.4.2",
|
||||
"winreg": "^1.2.3"
|
||||
"runes": "^0.4.2"
|
||||
},
|
||||
"false": {}
|
||||
}
|
||||
|
@@ -56,6 +56,7 @@ export interface IShell {
|
||||
command: string
|
||||
args?: string[]
|
||||
env?: any
|
||||
fsBase?: string
|
||||
}
|
||||
|
||||
export abstract class ShellProvider {
|
||||
|
@@ -3,7 +3,7 @@ ng-template(#content)
|
||||
[style.width]='"100%"',
|
||||
[style.background]='model',
|
||||
)
|
||||
input.form-control(type='text', '[(ngModel)]'='model', (ngModelChange)='onChange()', #input)
|
||||
input.form-control(type='text', [(ngModel)]='model', (ngModelChange)='onChange()', #input)
|
||||
|
||||
div(
|
||||
[ngbPopover]='content',
|
||||
|
@@ -70,23 +70,23 @@ h3.mb-3 Appearance
|
||||
|
||||
.form-group(*ngIf='editingColorScheme')
|
||||
color-picker(
|
||||
'[(model)]'='editingColorScheme.foreground',
|
||||
[(model)]='editingColorScheme.foreground',
|
||||
(modelChange)='config.save(); schemeChanged = true',
|
||||
title='FG',
|
||||
)
|
||||
color-picker(
|
||||
'[(model)]'='editingColorScheme.background',
|
||||
[(model)]='editingColorScheme.background',
|
||||
(modelChange)='config.save(); schemeChanged = true',
|
||||
title='BG',
|
||||
)
|
||||
color-picker(
|
||||
'[(model)]'='editingColorScheme.cursor',
|
||||
[(model)]='editingColorScheme.cursor',
|
||||
(modelChange)='config.save(); schemeChanged = true',
|
||||
title='CU',
|
||||
)
|
||||
color-picker(
|
||||
*ngFor='let _ of editingColorScheme.colors; let idx = index; trackBy: colorsTrackBy',
|
||||
'[(model)]'='editingColorScheme.colors[idx]',
|
||||
[(model)]='editingColorScheme.colors[idx]',
|
||||
(modelChange)='config.save(); schemeChanged = true',
|
||||
[title]='idx',
|
||||
)
|
||||
|
@@ -43,6 +43,10 @@ export class XTermFrontend extends Frontend {
|
||||
|
||||
host.addEventListener('dragOver', (event: any) => this.dragOver.next(event))
|
||||
host.addEventListener('drop', event => this.drop.next(event))
|
||||
|
||||
host.addEventListener('mousedown', event => this.mouseEvent.next(event))
|
||||
host.addEventListener('mouseup', event => this.mouseEvent.next(event))
|
||||
host.addEventListener('mousewheel', event => this.mouseEvent.next(event))
|
||||
}
|
||||
|
||||
detach (host: HTMLElement): void {
|
||||
|
@@ -57,8 +57,13 @@ hterm.hterm.Terminal.prototype.applyCursorShape = function () {
|
||||
console.warn('Unknown cursor style: ' + modeNumber)
|
||||
return
|
||||
}
|
||||
this.setCursorShape(modes[modeNumber][0])
|
||||
this.setCursorBlink(modes[modeNumber][1])
|
||||
setTimeout(() => {
|
||||
this.setCursorShape(modes[modeNumber][0])
|
||||
this.setCursorBlink(modes[modeNumber][1])
|
||||
})
|
||||
setTimeout(() => {
|
||||
this.setCursorVisible(true)
|
||||
})
|
||||
}
|
||||
|
||||
hterm.hterm.VT.CSI[' q'] = function (parseState) {
|
||||
|
@@ -1,14 +1,10 @@
|
||||
import * as path from 'path'
|
||||
import { Injectable } from '@angular/core'
|
||||
import { Registry } from 'rage-edit'
|
||||
import { HostAppService, Platform } from 'terminus-core'
|
||||
|
||||
import { ShellProvider, IShell } from '../api'
|
||||
|
||||
let Registry = null
|
||||
try {
|
||||
Registry = require('winreg')
|
||||
} catch (_) { } // tslint:disable-line no-empty
|
||||
|
||||
@Injectable()
|
||||
export class Cygwin32ShellProvider extends ShellProvider {
|
||||
constructor (
|
||||
@@ -22,15 +18,7 @@ export class Cygwin32ShellProvider extends ShellProvider {
|
||||
return []
|
||||
}
|
||||
|
||||
let cygwinPath = await new Promise<string>(resolve => {
|
||||
let reg = new Registry({ hive: Registry.HKLM, key: '\\Software\\Cygwin\\setup', arch: 'x86' })
|
||||
reg.get('rootdir', (err, item) => {
|
||||
if (err || !item) {
|
||||
return resolve(null)
|
||||
}
|
||||
resolve(item.value)
|
||||
})
|
||||
})
|
||||
let cygwinPath = await Registry.get('HKLM\\Software\\WOW6432Node\\Cygwin\\setup', 'rootdir')
|
||||
|
||||
if (!cygwinPath) {
|
||||
return []
|
||||
|
@@ -1,14 +1,10 @@
|
||||
import * as path from 'path'
|
||||
import { Injectable } from '@angular/core'
|
||||
import { Registry } from 'rage-edit'
|
||||
import { HostAppService, Platform } from 'terminus-core'
|
||||
|
||||
import { ShellProvider, IShell } from '../api'
|
||||
|
||||
let Registry = null
|
||||
try {
|
||||
Registry = require('winreg')
|
||||
} catch (_) { } // tslint:disable-line no-empty
|
||||
|
||||
@Injectable()
|
||||
export class Cygwin64ShellProvider extends ShellProvider {
|
||||
constructor (
|
||||
@@ -22,15 +18,7 @@ export class Cygwin64ShellProvider extends ShellProvider {
|
||||
return []
|
||||
}
|
||||
|
||||
let cygwinPath = await new Promise<string>(resolve => {
|
||||
let reg = new Registry({ hive: Registry.HKLM, key: '\\Software\\Cygwin\\setup', arch: 'x64' })
|
||||
reg.get('rootdir', (err, item) => {
|
||||
if (err || !item) {
|
||||
return resolve(null)
|
||||
}
|
||||
resolve(item.value)
|
||||
})
|
||||
})
|
||||
let cygwinPath = await Registry.get('HKLM\\Software\\Cygwin\\setup', 'rootdir')
|
||||
|
||||
if (!cygwinPath) {
|
||||
return []
|
||||
|
@@ -1,14 +1,10 @@
|
||||
import * as path from 'path'
|
||||
import { Injectable } from '@angular/core'
|
||||
import { Registry } from 'rage-edit'
|
||||
import { HostAppService, Platform } from 'terminus-core'
|
||||
|
||||
import { ShellProvider, IShell } from '../api'
|
||||
|
||||
let Registry = null
|
||||
try {
|
||||
Registry = require('winreg')
|
||||
} catch (_) { } // tslint:disable-line no-empty
|
||||
|
||||
@Injectable()
|
||||
export class GitBashShellProvider extends ShellProvider {
|
||||
constructor (
|
||||
@@ -22,16 +18,7 @@ export class GitBashShellProvider extends ShellProvider {
|
||||
return []
|
||||
}
|
||||
|
||||
let gitBashPath = await new Promise<string>(resolve => {
|
||||
let reg = new Registry({ hive: Registry.HKLM, key: '\\Software\\GitForWindows' })
|
||||
reg.get('InstallPath', (err, item) => {
|
||||
if (err || !item) {
|
||||
resolve(null)
|
||||
return
|
||||
}
|
||||
resolve(item.value)
|
||||
})
|
||||
})
|
||||
let gitBashPath = await Registry.get('HKLM\\Software\\GitForWindows', 'InstallPath')
|
||||
|
||||
if (!gitBashPath) {
|
||||
gitBashPath = await new Promise<string>(resolve => {
|
||||
|
@@ -1,13 +1,8 @@
|
||||
import { Injectable } from '@angular/core'
|
||||
import { Registry } from 'rage-edit'
|
||||
import { HostAppService, Platform } from 'terminus-core'
|
||||
|
||||
import { ShellProvider, IShell } from '../api'
|
||||
|
||||
let Registry = null
|
||||
try {
|
||||
Registry = require('winreg')
|
||||
} catch (_) { } // tslint:disable-line no-empty
|
||||
|
||||
@Injectable()
|
||||
export class PowerShellCoreShellProvider extends ShellProvider {
|
||||
constructor (
|
||||
@@ -21,15 +16,7 @@ export class PowerShellCoreShellProvider extends ShellProvider {
|
||||
return []
|
||||
}
|
||||
|
||||
let pwshPath = await new Promise<string>(resolve => {
|
||||
let reg = new Registry({ hive: Registry.HKLM, key: '\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\App Paths\\pwsh.exe', arch: 'x64' })
|
||||
reg.get('', (err, item) => {
|
||||
if (err || !item) {
|
||||
return resolve(null)
|
||||
}
|
||||
resolve(item.value)
|
||||
})
|
||||
})
|
||||
let pwshPath = await Registry.get('HKLM\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\App Paths\\pwsh.exe', '')
|
||||
|
||||
if (!pwshPath) {
|
||||
return []
|
||||
@@ -39,6 +26,7 @@ export class PowerShellCoreShellProvider extends ShellProvider {
|
||||
id: 'powershell-core',
|
||||
name: 'PowerShell Core',
|
||||
command: pwshPath,
|
||||
args: ['-nologo'],
|
||||
env: {
|
||||
TERM: 'cygwin',
|
||||
}
|
||||
|
@@ -7,7 +7,6 @@ import { WSLShellProvider } from './wsl'
|
||||
import { PowerShellCoreShellProvider } from './powershellCore'
|
||||
import { WindowsStockShellsProvider } from './windowsStock'
|
||||
|
||||
|
||||
@Injectable()
|
||||
export class WindowsDefaultShellProvider extends ShellProvider {
|
||||
private providers: ShellProvider[]
|
||||
|
@@ -39,6 +39,7 @@ export class WindowsStockShellsProvider extends ShellProvider {
|
||||
id: 'powershell',
|
||||
name: 'PowerShell',
|
||||
command: 'powershell.exe',
|
||||
args: ['-nologo'],
|
||||
env: {
|
||||
TERM: 'cygwin',
|
||||
}
|
||||
|
@@ -1,5 +1,5 @@
|
||||
import * as fs from 'mz/fs'
|
||||
import { exec } from 'mz/child_process'
|
||||
import { Registry } from 'rage-edit'
|
||||
import { Injectable } from '@angular/core'
|
||||
import { HostAppService, Platform } from 'terminus-core'
|
||||
|
||||
@@ -18,13 +18,9 @@ export class WSLShellProvider extends ShellProvider {
|
||||
return []
|
||||
}
|
||||
|
||||
const bashPath = `${process.env.windir}\\system32\\bash.exe`
|
||||
const wslPath = `${process.env.windir}\\system32\\wsl.exe`
|
||||
const wslConfigPath = `${process.env.windir}\\system32\\wslconfig.exe`
|
||||
if (!await fs.exists(wslPath)) {
|
||||
return []
|
||||
}
|
||||
|
||||
let lines = (await exec(`${wslConfigPath} /l`, { encoding: 'ucs2' }))[0].toString().split('\n').splice(1)
|
||||
let shells: IShell[] = [{
|
||||
id: 'wsl',
|
||||
name: 'WSL / Default distro',
|
||||
@@ -35,19 +31,33 @@ export class WSLShellProvider extends ShellProvider {
|
||||
}
|
||||
}]
|
||||
|
||||
for (let line of lines) {
|
||||
line = line.trim()
|
||||
if (!line) {
|
||||
let lxss = await Registry.get('HKCU\\Software\\Microsoft\\Windows\\CurrentVersion\\Lxss', true)
|
||||
if (!lxss || !lxss.$values.defaultdistribution) {
|
||||
if (await fs.exists(bashPath)) {
|
||||
return [{
|
||||
id: 'wsl',
|
||||
name: 'WSL / Bash on Windows',
|
||||
command: bashPath,
|
||||
env: {
|
||||
TERM: 'xterm-color',
|
||||
COLORTERM: 'truecolor',
|
||||
}
|
||||
}]
|
||||
} else {
|
||||
return []
|
||||
}
|
||||
}
|
||||
for (let child of Object.values(lxss)) {
|
||||
if (!(child as any).$values) {
|
||||
continue
|
||||
}
|
||||
if (line.endsWith('(Default)')) {
|
||||
line = line.substring(0, line.length - ' (Default)'.length)
|
||||
}
|
||||
let name = (child as any).$values.distributionname
|
||||
shells.push({
|
||||
id: `wsl-${line}`,
|
||||
name: `WSL / ${line}`,
|
||||
id: `wsl-${name}`,
|
||||
name: `WSL / ${name}`,
|
||||
command: wslPath,
|
||||
args: ['-d', line],
|
||||
args: ['-d', name],
|
||||
fsBase: (child as any).$values.basepath,
|
||||
env: {
|
||||
TERM: 'xterm-color',
|
||||
COLORTERM: 'truecolor',
|
||||
|
@@ -57,7 +57,6 @@ module.exports = {
|
||||
'node-pty-tmp',
|
||||
'mz/fs',
|
||||
'mz/child_process',
|
||||
'winreg',
|
||||
/^rxjs/,
|
||||
/^@angular/,
|
||||
/^@ng-bootstrap/,
|
||||
|
@@ -24,10 +24,6 @@
|
||||
version "1.13.0"
|
||||
resolved "https://registry.yarnpkg.com/@types/webpack-env/-/webpack-env-1.13.0.tgz#3044381647e11ee973c5af2e925323930f691d80"
|
||||
|
||||
"@types/winreg@^1.2.30":
|
||||
version "1.2.30"
|
||||
resolved "https://registry.yarnpkg.com/@types/winreg/-/winreg-1.2.30.tgz#91d6710e536d345b9c9b017c574cf6a8da64c518"
|
||||
|
||||
any-promise@^1.0.0:
|
||||
version "1.3.0"
|
||||
resolved "https://registry.yarnpkg.com/any-promise/-/any-promise-1.3.0.tgz#abc6afeedcea52e809cdc0376aed3ce39635d17f"
|
||||
@@ -112,6 +108,10 @@ ps-node@^0.1.6:
|
||||
dependencies:
|
||||
table-parser "^0.1.3"
|
||||
|
||||
rage-edit@^1.1.0:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/rage-edit/-/rage-edit-1.1.0.tgz#8a5f0bf5c5ff4ab31ad086fa27a55be20fcd0357"
|
||||
|
||||
runes@^0.4.2:
|
||||
version "0.4.2"
|
||||
resolved "https://registry.yarnpkg.com/runes/-/runes-0.4.2.tgz#1ddc1ea41de769cb32fc068a64fbbc45cd21052e"
|
||||
@@ -134,10 +134,6 @@ thenify-all@^1.0.0:
|
||||
dependencies:
|
||||
any-promise "^1.0.0"
|
||||
|
||||
winreg@^1.2.3:
|
||||
version "1.2.4"
|
||||
resolved "https://registry.yarnpkg.com/winreg/-/winreg-1.2.4.tgz#ba065629b7a925130e15779108cf540990e98d1b"
|
||||
|
||||
xterm@^3.6.0:
|
||||
version "3.6.0"
|
||||
resolved "https://registry.yarnpkg.com/xterm/-/xterm-3.6.0.tgz#9b95cd23a338e5842343aec1a104f094c5153e7c"
|
||||
|
@@ -20,7 +20,8 @@
|
||||
"es5",
|
||||
"es6",
|
||||
"es7",
|
||||
"es2015"
|
||||
"es2015",
|
||||
"es2017"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
@@ -176,9 +176,9 @@
|
||||
version "10.7.1"
|
||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-10.7.1.tgz#b704d7c259aa40ee052eec678758a68d07132a2e"
|
||||
|
||||
"@types/node@7.0.5":
|
||||
version "7.0.5"
|
||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-7.0.5.tgz#96a0f0a618b7b606f1ec547403c00650210bfbb7"
|
||||
"@types/node@^10.11.5":
|
||||
version "10.11.5"
|
||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-10.11.5.tgz#6489ebda4452592d3fd37aefa57eedc01ed13378"
|
||||
|
||||
"@types/node@^8.0.24":
|
||||
version "8.10.26"
|
||||
|
Reference in New Issue
Block a user