mirror of
https://github.com/Eugeny/tabby.git
synced 2025-08-09 19:01:53 +00:00
Compare commits
22 Commits
v1.0.0-alp
...
v1.0.0-alp
Author | SHA1 | Date | |
---|---|---|---|
![]() |
11f188f1e8 | ||
![]() |
9a9db28054 | ||
![]() |
47d57d08ee | ||
![]() |
39e2c386f0 | ||
![]() |
c73d39026b | ||
![]() |
89dff969b1 | ||
![]() |
e1eb1beb87 | ||
![]() |
8d12d6a547 | ||
![]() |
33f67503bd | ||
![]() |
21e1656780 | ||
![]() |
ceacf5c760 | ||
![]() |
e0c0cd17bd | ||
![]() |
e81e5034b9 | ||
![]() |
11e0c36ebc | ||
![]() |
e52fd0a3dd | ||
![]() |
48ccc538e5 | ||
![]() |
53ac39232c | ||
![]() |
f68e06c9ed | ||
![]() |
6c884e090c | ||
![]() |
38cda117e2 | ||
![]() |
fb64ca08d3 | ||
![]() |
0fe7edc5b5 |
@@ -115,7 +115,7 @@ export async function findPlugins (): Promise<IPluginInfo[]> {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
let info = JSON.parse(await fs.readFile(infoPath, {encoding: 'utf-8'}))
|
let info = JSON.parse(await fs.readFile(infoPath, {encoding: 'utf-8'}))
|
||||||
if (!info.keywords || info.keywords.indexOf('terminus-plugin') === -1) {
|
if (!info.keywords || !(info.keywords.includes('terminus-plugin') || info.keywords.includes('terminus-builtin-plugin'))) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
let author = info.author
|
let author = info.author
|
||||||
|
@@ -58,3 +58,7 @@
|
|||||||
color: #842fe0;
|
color: #842fe0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.modal-dialog {
|
||||||
|
-webkit-app-region: no-drag;
|
||||||
|
}
|
||||||
|
@@ -1,9 +1,9 @@
|
|||||||
{
|
{
|
||||||
"name": "terminus-community-color-schemes",
|
"name": "terminus-community-color-schemes",
|
||||||
"version": "1.0.0-alpha.24",
|
"version": "1.0.0-alpha.35",
|
||||||
"description": "Community color schemes for Terminus",
|
"description": "Community color schemes for Terminus",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"terminus-plugin"
|
"terminus-builtin-plugin"
|
||||||
],
|
],
|
||||||
"main": "dist/index.js",
|
"main": "dist/index.js",
|
||||||
"typings": "dist/index.d.ts",
|
"typings": "dist/index.d.ts",
|
||||||
|
@@ -1,9 +1,9 @@
|
|||||||
{
|
{
|
||||||
"name": "terminus-core",
|
"name": "terminus-core",
|
||||||
"version": "1.0.0-alpha.24",
|
"version": "1.0.0-alpha.35.1",
|
||||||
"description": "Terminus core",
|
"description": "Terminus core",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"terminus-plugin"
|
"terminus-builtin-plugin"
|
||||||
],
|
],
|
||||||
"main": "dist/index.js",
|
"main": "dist/index.js",
|
||||||
"typings": "dist/index.d.ts",
|
"typings": "dist/index.d.ts",
|
||||||
@@ -20,6 +20,7 @@
|
|||||||
"@types/js-yaml": "^3.9.0",
|
"@types/js-yaml": "^3.9.0",
|
||||||
"@types/node": "^7.0.37",
|
"@types/node": "^7.0.37",
|
||||||
"@types/webpack-env": "^1.13.0",
|
"@types/webpack-env": "^1.13.0",
|
||||||
|
"@types/winston": "^2.3.6",
|
||||||
"axios": "0.16.2",
|
"axios": "0.16.2",
|
||||||
"bootstrap": "4.0.0-alpha.6",
|
"bootstrap": "4.0.0-alpha.6",
|
||||||
"core-js": "^2.4.1",
|
"core-js": "^2.4.1",
|
||||||
@@ -39,7 +40,8 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"deepmerge": "^1.5.0",
|
"deepmerge": "^1.5.0",
|
||||||
"js-yaml": "^3.9.0"
|
"js-yaml": "^3.9.0",
|
||||||
|
"winston": "^2.4.0"
|
||||||
},
|
},
|
||||||
"false": {}
|
"false": {}
|
||||||
}
|
}
|
||||||
|
@@ -19,7 +19,6 @@ title-bar(
|
|||||||
[class.drag-region]='hostApp.platform == Platform.macOS',
|
[class.drag-region]='hostApp.platform == Platform.macOS',
|
||||||
@animateTab,
|
@animateTab,
|
||||||
(click)='app.selectTab(tab)',
|
(click)='app.selectTab(tab)',
|
||||||
(closeClicked)='app.closeTab(tab, true)',
|
|
||||||
)
|
)
|
||||||
|
|
||||||
.btn-group
|
.btn-group
|
||||||
@@ -30,7 +29,7 @@ title-bar(
|
|||||||
)
|
)
|
||||||
i.fa([class]='"fa fa-" + button.icon')
|
i.fa([class]='"fa fa-" + button.icon')
|
||||||
|
|
||||||
.drag-space
|
.drag-space(*ngIf='config.store.appearance.frame == "thin" && hostApp.platform != Platform.macOS')
|
||||||
|
|
||||||
.btn-group
|
.btn-group
|
||||||
button.btn.btn-secondary.btn-tab-bar(
|
button.btn.btn-secondary.btn-tab-bar(
|
||||||
|
@@ -150,6 +150,8 @@ export class AppRootComponent {
|
|||||||
if (this.app.tabs.length === 0) {
|
if (this.app.tabs.length === 0) {
|
||||||
this.app.openDefaultTab()
|
this.app.openDefaultTab()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.app.emitReady()
|
||||||
}
|
}
|
||||||
|
|
||||||
@HostListener('dragover')
|
@HostListener('dragover')
|
||||||
|
@@ -1,3 +1,3 @@
|
|||||||
.index {{index + 1}}
|
.index {{index + 1}}
|
||||||
.name([title]='tab.customTitle || tab.title') {{tab.customTitle || tab.title}}
|
.name([title]='tab.customTitle || tab.title') {{tab.customTitle || tab.title}}
|
||||||
button((click)='closeClicked.emit()') ×
|
button((click)='app.closeTab(tab, true)') ×
|
||||||
|
@@ -1,7 +1,6 @@
|
|||||||
$tabs-height: 36px;
|
$tabs-height: 36px;
|
||||||
|
|
||||||
:host {
|
:host {
|
||||||
line-height: $tabs-height - 2px;
|
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
|
||||||
flex: 1000 1 200px;
|
flex: 1000 1 200px;
|
||||||
@@ -24,9 +23,9 @@ $tabs-height: 36px;
|
|||||||
margin-left: 10px;
|
margin-left: 10px;
|
||||||
width: 20px;
|
width: 20px;
|
||||||
border-radius: 10px;
|
border-radius: 10px;
|
||||||
line-height: 35px;
|
|
||||||
text-align: center;
|
text-align: center;
|
||||||
transition: 0.25s all;
|
transition: 0.25s all;
|
||||||
|
align-self: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.name {
|
.name {
|
||||||
@@ -36,6 +35,7 @@ $tabs-height: 36px;
|
|||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
min-width: 0;
|
min-width: 0;
|
||||||
|
align-self: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
button {
|
button {
|
||||||
@@ -49,7 +49,7 @@ $tabs-height: 36px;
|
|||||||
height: $button-size;
|
height: $button-size;
|
||||||
border-radius: $button-size / 2;
|
border-radius: $button-size / 2;
|
||||||
line-height: $button-size * 0.87;
|
line-height: $button-size * 0.87;
|
||||||
margin-top: ($tabs-height - $button-size) * 0.5;
|
align-self: center;
|
||||||
margin-right: 10px;
|
margin-right: 10px;
|
||||||
|
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
@@ -1,7 +1,9 @@
|
|||||||
import { Component, Input, Output, EventEmitter, HostBinding, HostListener } from '@angular/core'
|
import { Component, Input, HostBinding, HostListener, NgZone } from '@angular/core'
|
||||||
import { NgbModal } from '@ng-bootstrap/ng-bootstrap'
|
import { NgbModal } from '@ng-bootstrap/ng-bootstrap'
|
||||||
import { BaseTabComponent } from './baseTab.component'
|
import { BaseTabComponent } from './baseTab.component'
|
||||||
import { RenameTabModalComponent } from './renameTabModal.component'
|
import { RenameTabModalComponent } from './renameTabModal.component'
|
||||||
|
import { ElectronService } from '../services/electron.service'
|
||||||
|
import { AppService } from '../services/app.service'
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'tab-header',
|
selector: 'tab-header',
|
||||||
@@ -13,11 +15,55 @@ export class TabHeaderComponent {
|
|||||||
@Input() @HostBinding('class.active') active: boolean
|
@Input() @HostBinding('class.active') active: boolean
|
||||||
@Input() @HostBinding('class.has-activity') hasActivity: boolean
|
@Input() @HostBinding('class.has-activity') hasActivity: boolean
|
||||||
@Input() tab: BaseTabComponent
|
@Input() tab: BaseTabComponent
|
||||||
@Output() closeClicked = new EventEmitter()
|
private contextMenu: any
|
||||||
|
|
||||||
constructor (
|
constructor (
|
||||||
|
zone: NgZone,
|
||||||
|
electron: ElectronService,
|
||||||
|
public app: AppService,
|
||||||
private ngbModal: NgbModal,
|
private ngbModal: NgbModal,
|
||||||
) { }
|
) {
|
||||||
|
this.contextMenu = electron.remote.Menu.buildFromTemplate([
|
||||||
|
{
|
||||||
|
label: 'Close',
|
||||||
|
click: () => {
|
||||||
|
zone.run(() => {
|
||||||
|
app.closeTab(this.tab, true)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Close other tabs',
|
||||||
|
click: () => {
|
||||||
|
zone.run(() => {
|
||||||
|
for (let tab of app.tabs.filter(x => x !== this.tab)) {
|
||||||
|
app.closeTab(tab, true)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Close tabs to the right',
|
||||||
|
click: () => {
|
||||||
|
zone.run(() => {
|
||||||
|
for (let tab of app.tabs.slice(app.tabs.indexOf(this.tab) + 1)) {
|
||||||
|
app.closeTab(tab, true)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Close tabs to the left',
|
||||||
|
click: () => {
|
||||||
|
zone.run(() => {
|
||||||
|
for (let tab of app.tabs.slice(0, app.tabs.indexOf(this.tab))) {
|
||||||
|
app.closeTab(tab, true)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
])
|
||||||
|
}
|
||||||
|
|
||||||
@HostListener('dblclick') onDoubleClick (): void {
|
@HostListener('dblclick') onDoubleClick (): void {
|
||||||
let modal = this.ngbModal.open(RenameTabModalComponent)
|
let modal = this.ngbModal.open(RenameTabModalComponent)
|
||||||
@@ -29,7 +75,15 @@ export class TabHeaderComponent {
|
|||||||
|
|
||||||
@HostListener('auxclick', ['$event']) onAuxClick ($event: MouseEvent): void {
|
@HostListener('auxclick', ['$event']) onAuxClick ($event: MouseEvent): void {
|
||||||
if ($event.which === 2) {
|
if ($event.which === 2) {
|
||||||
this.closeClicked.emit()
|
this.app.closeTab(this.tab, true)
|
||||||
|
}
|
||||||
|
if ($event.which === 3) {
|
||||||
|
this.contextMenu.popup({
|
||||||
|
x: $event.pageX,
|
||||||
|
y: $event.pageY,
|
||||||
|
async: true,
|
||||||
|
})
|
||||||
|
event.preventDefault()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -29,7 +29,7 @@ import { HotkeyProvider } from './api/hotkeyProvider'
|
|||||||
import { ConfigProvider } from './api/configProvider'
|
import { ConfigProvider } from './api/configProvider'
|
||||||
import { Theme } from './api/theme'
|
import { Theme } from './api/theme'
|
||||||
|
|
||||||
import { StandardTheme } from './theme'
|
import { StandardTheme, StandardCompactTheme } from './theme'
|
||||||
import { CoreConfigProvider } from './config'
|
import { CoreConfigProvider } from './config'
|
||||||
|
|
||||||
import 'perfect-scrollbar/dist/css/perfect-scrollbar.css'
|
import 'perfect-scrollbar/dist/css/perfect-scrollbar.css'
|
||||||
@@ -47,6 +47,7 @@ const PROVIDERS = [
|
|||||||
UpdaterService,
|
UpdaterService,
|
||||||
{ provide: HotkeyProvider, useClass: AppHotkeyProvider, multi: true },
|
{ provide: HotkeyProvider, useClass: AppHotkeyProvider, multi: true },
|
||||||
{ provide: Theme, useClass: StandardTheme, multi: true },
|
{ provide: Theme, useClass: StandardTheme, multi: true },
|
||||||
|
{ provide: Theme, useClass: StandardCompactTheme, multi: true },
|
||||||
{ provide: ConfigProvider, useClass: CoreConfigProvider, multi: true },
|
{ provide: ConfigProvider, useClass: CoreConfigProvider, multi: true },
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
import { Subject } from 'rxjs'
|
import { Subject, AsyncSubject } from 'rxjs'
|
||||||
import { Injectable, ComponentFactoryResolver, Injector, Optional } from '@angular/core'
|
import { Injectable, ComponentFactoryResolver, Injector, Optional } from '@angular/core'
|
||||||
import { DefaultTabProvider } from '../api/defaultTabProvider'
|
import { DefaultTabProvider } from '../api/defaultTabProvider'
|
||||||
import { BaseTabComponent } from '../components/baseTab.component'
|
import { BaseTabComponent } from '../components/baseTab.component'
|
||||||
@@ -12,7 +12,8 @@ export class AppService {
|
|||||||
activeTab: BaseTabComponent
|
activeTab: BaseTabComponent
|
||||||
lastTabIndex = 0
|
lastTabIndex = 0
|
||||||
logger: Logger
|
logger: Logger
|
||||||
tabsChanged$ = new Subject()
|
tabsChanged$ = new Subject<void>()
|
||||||
|
ready$ = new AsyncSubject<void>()
|
||||||
|
|
||||||
constructor (
|
constructor (
|
||||||
private componentFactoryResolver: ComponentFactoryResolver,
|
private componentFactoryResolver: ComponentFactoryResolver,
|
||||||
@@ -97,4 +98,9 @@ export class AppService {
|
|||||||
}
|
}
|
||||||
this.tabsChanged$.next()
|
this.tabsChanged$.next()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
emitReady () {
|
||||||
|
this.ready$.next(null)
|
||||||
|
this.ready$.complete()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -14,7 +14,10 @@ export class DockingService {
|
|||||||
private electron: ElectronService,
|
private electron: ElectronService,
|
||||||
private config: ConfigService,
|
private config: ConfigService,
|
||||||
private hostApp: HostAppService,
|
private hostApp: HostAppService,
|
||||||
) {}
|
) {
|
||||||
|
electron.screen.on('display-removed', () => this.repositionWindow())
|
||||||
|
electron.screen.on('display-metrics-changed', () => this.repositionWindow())
|
||||||
|
}
|
||||||
|
|
||||||
dock () {
|
dock () {
|
||||||
let display = this.electron.screen.getAllDisplays()
|
let display = this.electron.screen.getAllDisplays()
|
||||||
@@ -71,4 +74,20 @@ export class DockingService {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getWindow () {
|
||||||
|
return this.electron.app.window
|
||||||
|
}
|
||||||
|
|
||||||
|
repositionWindow () {
|
||||||
|
let [x, y] = this.getWindow().getPosition()
|
||||||
|
for (let screen of this.electron.screen.getAllDisplays()) {
|
||||||
|
let bounds = screen.bounds
|
||||||
|
if (x >= bounds.x && x <= bounds.x + bounds.width && y >= bounds.y && y <= bounds.y + bounds.height) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let screen = this.electron.screen.getPrimaryDisplay()
|
||||||
|
this.getWindow().setPosition(screen.bounds.x, screen.bounds.y)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,12 +1,47 @@
|
|||||||
import { Injectable } from '@angular/core'
|
import { Injectable } from '@angular/core'
|
||||||
|
import { ElectronService } from './electron.service'
|
||||||
|
import * as winston from 'winston'
|
||||||
|
import * as fs from 'fs'
|
||||||
|
import * as path from 'path'
|
||||||
|
|
||||||
|
const initializeWinston = (electron: ElectronService) => {
|
||||||
|
const logDirectory = electron.app.getPath('userData')
|
||||||
|
|
||||||
|
if (!fs.existsSync(logDirectory)) {
|
||||||
|
fs.mkdirSync(logDirectory)
|
||||||
|
}
|
||||||
|
|
||||||
|
return new winston.Logger({
|
||||||
|
transports: [
|
||||||
|
new winston.transports.File({
|
||||||
|
level: 'info',
|
||||||
|
filename: path.join(logDirectory, 'log.txt'),
|
||||||
|
handleExceptions: false,
|
||||||
|
json: false,
|
||||||
|
maxsize: 5242880,
|
||||||
|
maxFiles: 5,
|
||||||
|
colorize: false
|
||||||
|
}),
|
||||||
|
new winston.transports.Console({
|
||||||
|
level: 'info',
|
||||||
|
handleExceptions: false,
|
||||||
|
json: false,
|
||||||
|
colorize: true
|
||||||
|
})
|
||||||
|
],
|
||||||
|
exitOnError: false
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
export class Logger {
|
export class Logger {
|
||||||
constructor (
|
constructor (
|
||||||
|
private winstonLogger: any,
|
||||||
private name: string,
|
private name: string,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
doLog (level: string, ...args: any[]) {
|
doLog (level: string, ...args: any[]) {
|
||||||
console[level](`%c[${this.name}]`, 'color: #aaa', ...args)
|
console[level](`%c[${this.name}]`, 'color: #aaa', ...args)
|
||||||
|
this.winstonLogger[level](...args)
|
||||||
}
|
}
|
||||||
|
|
||||||
debug (...args: any[]) { this.doLog('debug', ...args) }
|
debug (...args: any[]) { this.doLog('debug', ...args) }
|
||||||
@@ -18,7 +53,13 @@ export class Logger {
|
|||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class LogService {
|
export class LogService {
|
||||||
|
private log: any
|
||||||
|
|
||||||
|
constructor (electron: ElectronService) {
|
||||||
|
this.log = initializeWinston(electron)
|
||||||
|
}
|
||||||
|
|
||||||
create (name: string): Logger {
|
create (name: string): Logger {
|
||||||
return new Logger(name)
|
return new Logger(this.log, name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
15
terminus-core/src/theme.compact.scss
Normal file
15
terminus-core/src/theme.compact.scss
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
@import './theme.scss';
|
||||||
|
|
||||||
|
app-root {
|
||||||
|
.tab-bar {
|
||||||
|
height: 27px !important;
|
||||||
|
|
||||||
|
.btn-tab-bar {
|
||||||
|
line-height: 29px !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
terminaltab .content {
|
||||||
|
margin: 5px !important;
|
||||||
|
}
|
||||||
|
}
|
@@ -131,6 +131,7 @@ app-root {
|
|||||||
background: $body-bg2;
|
background: $body-bg2;
|
||||||
border-left: 1px solid transparent;
|
border-left: 1px solid transparent;
|
||||||
border-right: 1px solid transparent;
|
border-right: 1px solid transparent;
|
||||||
|
border-top: 1px solid transparent;
|
||||||
|
|
||||||
.index {
|
.index {
|
||||||
color: #555;
|
color: #555;
|
||||||
@@ -159,10 +160,12 @@ app-root {
|
|||||||
|
|
||||||
tab-header {
|
tab-header {
|
||||||
border-top: 1px solid transparent;
|
border-top: 1px solid transparent;
|
||||||
|
border-bottom: 1px solid $border-color;
|
||||||
|
margin-bottom: -1px;
|
||||||
|
|
||||||
&.active {
|
&.active {
|
||||||
border-top: 1px solid $teal;
|
border-top: 1px solid $teal;
|
||||||
margin-bottom: -1px;
|
border-bottom-color: transparent;
|
||||||
}
|
}
|
||||||
|
|
||||||
&.has-activity:not(.active) {
|
&.has-activity:not(.active) {
|
||||||
@@ -176,6 +179,8 @@ app-root {
|
|||||||
|
|
||||||
tab-header {
|
tab-header {
|
||||||
border-bottom: 1px solid transparent;
|
border-bottom: 1px solid transparent;
|
||||||
|
border-top: 1px solid $border-color;
|
||||||
|
margin-top: -1px;
|
||||||
|
|
||||||
&.active {
|
&.active {
|
||||||
border-bottom: 1px solid $teal;
|
border-bottom: 1px solid $teal;
|
||||||
|
@@ -7,3 +7,10 @@ export class StandardTheme extends Theme {
|
|||||||
css = require('./theme.scss')
|
css = require('./theme.scss')
|
||||||
terminalBackground = '#1D272D'
|
terminalBackground = '#1D272D'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class StandardCompactTheme extends Theme {
|
||||||
|
name = 'Compact'
|
||||||
|
css = require('./theme.compact.scss')
|
||||||
|
terminalBackground = '#1D272D'
|
||||||
|
}
|
||||||
|
@@ -45,6 +45,7 @@ module.exports = {
|
|||||||
'path',
|
'path',
|
||||||
'deepmerge',
|
'deepmerge',
|
||||||
'untildify',
|
'untildify',
|
||||||
|
'winston',
|
||||||
'js-yaml',
|
'js-yaml',
|
||||||
/^rxjs/,
|
/^rxjs/,
|
||||||
/^@angular/,
|
/^@angular/,
|
||||||
|
@@ -6,7 +6,7 @@
|
|||||||
version "3.9.1"
|
version "3.9.1"
|
||||||
resolved "https://registry.yarnpkg.com/@types/js-yaml/-/js-yaml-3.9.1.tgz#2f3c142771bb345829ce690c5838760b6b9ba553"
|
resolved "https://registry.yarnpkg.com/@types/js-yaml/-/js-yaml-3.9.1.tgz#2f3c142771bb345829ce690c5838760b6b9ba553"
|
||||||
|
|
||||||
"@types/node@^7.0.37":
|
"@types/node@*", "@types/node@^7.0.37":
|
||||||
version "7.0.43"
|
version "7.0.43"
|
||||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-7.0.43.tgz#a187e08495a075f200ca946079c914e1a5fe962c"
|
resolved "https://registry.yarnpkg.com/@types/node/-/node-7.0.43.tgz#a187e08495a075f200ca946079c914e1a5fe962c"
|
||||||
|
|
||||||
@@ -14,12 +14,22 @@
|
|||||||
version "1.13.1"
|
version "1.13.1"
|
||||||
resolved "https://registry.yarnpkg.com/@types/webpack-env/-/webpack-env-1.13.1.tgz#b45c222e24301bd006e3edfc762cc6b51bda236a"
|
resolved "https://registry.yarnpkg.com/@types/webpack-env/-/webpack-env-1.13.1.tgz#b45c222e24301bd006e3edfc762cc6b51bda236a"
|
||||||
|
|
||||||
|
"@types/winston@^2.3.6":
|
||||||
|
version "2.3.6"
|
||||||
|
resolved "https://registry.yarnpkg.com/@types/winston/-/winston-2.3.6.tgz#0f0954b9e16abd40598dc6e9cc2ea43044237997"
|
||||||
|
dependencies:
|
||||||
|
"@types/node" "*"
|
||||||
|
|
||||||
argparse@^1.0.7:
|
argparse@^1.0.7:
|
||||||
version "1.0.9"
|
version "1.0.9"
|
||||||
resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.9.tgz#73d83bc263f86e97f8cc4f6bae1b0e90a7d22c86"
|
resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.9.tgz#73d83bc263f86e97f8cc4f6bae1b0e90a7d22c86"
|
||||||
dependencies:
|
dependencies:
|
||||||
sprintf-js "~1.0.2"
|
sprintf-js "~1.0.2"
|
||||||
|
|
||||||
|
async@~1.0.0:
|
||||||
|
version "1.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/async/-/async-1.0.0.tgz#f8fc04ca3a13784ade9e1641af98578cfbd647a9"
|
||||||
|
|
||||||
axios@0.16.2:
|
axios@0.16.2:
|
||||||
version "0.16.2"
|
version "0.16.2"
|
||||||
resolved "https://registry.yarnpkg.com/axios/-/axios-0.16.2.tgz#ba4f92f17167dfbab40983785454b9ac149c3c6d"
|
resolved "https://registry.yarnpkg.com/axios/-/axios-0.16.2.tgz#ba4f92f17167dfbab40983785454b9ac149c3c6d"
|
||||||
@@ -44,10 +54,18 @@ bootstrap@4.0.0-alpha.6:
|
|||||||
jquery ">=1.9.1"
|
jquery ">=1.9.1"
|
||||||
tether "^1.4.0"
|
tether "^1.4.0"
|
||||||
|
|
||||||
|
colors@1.0.x:
|
||||||
|
version "1.0.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/colors/-/colors-1.0.3.tgz#0433f44d809680fdeb60ed260f1b0c262e82a40b"
|
||||||
|
|
||||||
core-js@^2.4.1:
|
core-js@^2.4.1:
|
||||||
version "2.5.1"
|
version "2.5.1"
|
||||||
resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.5.1.tgz#ae6874dc66937789b80754ff5428df66819ca50b"
|
resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.5.1.tgz#ae6874dc66937789b80754ff5428df66819ca50b"
|
||||||
|
|
||||||
|
cycle@1.0.x:
|
||||||
|
version "1.0.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/cycle/-/cycle-1.0.3.tgz#21e80b2be8580f98b468f379430662b046c34ad2"
|
||||||
|
|
||||||
debug@^2.4.5:
|
debug@^2.4.5:
|
||||||
version "2.6.8"
|
version "2.6.8"
|
||||||
resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.8.tgz#e731531ca2ede27d188222427da17821d68ff4fc"
|
resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.8.tgz#e731531ca2ede27d188222427da17821d68ff4fc"
|
||||||
@@ -97,6 +115,10 @@ esprima@^4.0.0:
|
|||||||
version "4.0.0"
|
version "4.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.0.tgz#4499eddcd1110e0b218bacf2fa7f7f59f55ca804"
|
resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.0.tgz#4499eddcd1110e0b218bacf2fa7f7f59f55ca804"
|
||||||
|
|
||||||
|
eyes@0.1.x:
|
||||||
|
version "0.1.8"
|
||||||
|
resolved "https://registry.yarnpkg.com/eyes/-/eyes-0.1.8.tgz#62cf120234c683785d902348a800ef3e0cc20bc0"
|
||||||
|
|
||||||
follow-redirects@^1.2.3:
|
follow-redirects@^1.2.3:
|
||||||
version "1.2.4"
|
version "1.2.4"
|
||||||
resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.2.4.tgz#355e8f4d16876b43f577b0d5ce2668b9723214ea"
|
resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.2.4.tgz#355e8f4d16876b43f577b0d5ce2668b9723214ea"
|
||||||
@@ -126,6 +148,10 @@ is-buffer@^1.1.5:
|
|||||||
version "1.1.5"
|
version "1.1.5"
|
||||||
resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.5.tgz#1f3b26ef613b214b88cbca23cc6c01d87961eecc"
|
resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.5.tgz#1f3b26ef613b214b88cbca23cc6c01d87961eecc"
|
||||||
|
|
||||||
|
isstream@0.1.x:
|
||||||
|
version "0.1.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a"
|
||||||
|
|
||||||
jquery@>=1.9.1:
|
jquery@>=1.9.1:
|
||||||
version "3.2.1"
|
version "3.2.1"
|
||||||
resolved "https://registry.yarnpkg.com/jquery/-/jquery-3.2.1.tgz#5c4d9de652af6cd0a770154a631bba12b015c787"
|
resolved "https://registry.yarnpkg.com/jquery/-/jquery-3.2.1.tgz#5c4d9de652af6cd0a770154a631bba12b015c787"
|
||||||
@@ -191,6 +217,10 @@ sprintf-js@~1.0.2:
|
|||||||
version "1.0.3"
|
version "1.0.3"
|
||||||
resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c"
|
resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c"
|
||||||
|
|
||||||
|
stack-trace@0.0.x:
|
||||||
|
version "0.0.10"
|
||||||
|
resolved "https://registry.yarnpkg.com/stack-trace/-/stack-trace-0.0.10.tgz#547c70b347e8d32b4e108ea1a2a159e5fdde19c0"
|
||||||
|
|
||||||
tether@^1.4.0:
|
tether@^1.4.0:
|
||||||
version "1.4.0"
|
version "1.4.0"
|
||||||
resolved "https://registry.yarnpkg.com/tether/-/tether-1.4.0.tgz#0f9fa171f75bf58485d8149e94799d7ae74d1c1a"
|
resolved "https://registry.yarnpkg.com/tether/-/tether-1.4.0.tgz#0f9fa171f75bf58485d8149e94799d7ae74d1c1a"
|
||||||
@@ -209,6 +239,17 @@ uuid-1345@^0.99.6:
|
|||||||
dependencies:
|
dependencies:
|
||||||
macaddress "^0.2.7"
|
macaddress "^0.2.7"
|
||||||
|
|
||||||
|
winston@^2.4.0:
|
||||||
|
version "2.4.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/winston/-/winston-2.4.0.tgz#808050b93d52661ed9fb6c26b3f0c826708b0aee"
|
||||||
|
dependencies:
|
||||||
|
async "~1.0.0"
|
||||||
|
colors "1.0.x"
|
||||||
|
cycle "1.0.x"
|
||||||
|
eyes "0.1.x"
|
||||||
|
isstream "0.1.x"
|
||||||
|
stack-trace "0.0.x"
|
||||||
|
|
||||||
xelement@^1.0.16:
|
xelement@^1.0.16:
|
||||||
version "1.0.16"
|
version "1.0.16"
|
||||||
resolved "https://registry.yarnpkg.com/xelement/-/xelement-1.0.16.tgz#900bb46c20fc2dffadff778a9d2dc36699d0ff7e"
|
resolved "https://registry.yarnpkg.com/xelement/-/xelement-1.0.16.tgz#900bb46c20fc2dffadff778a9d2dc36699d0ff7e"
|
||||||
|
@@ -1,9 +1,9 @@
|
|||||||
{
|
{
|
||||||
"name": "terminus-plugin-manager",
|
"name": "terminus-plugin-manager",
|
||||||
"version": "1.0.0-alpha.24",
|
"version": "1.0.0-alpha.35.1",
|
||||||
"description": "Terminus' plugin manager",
|
"description": "Terminus' plugin manager",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"terminus-plugin"
|
"terminus-builtin-plugin"
|
||||||
],
|
],
|
||||||
"main": "dist/index.js",
|
"main": "dist/index.js",
|
||||||
"typings": "dist/index.d.ts",
|
"typings": "dist/index.d.ts",
|
||||||
|
@@ -78,7 +78,8 @@ div(*ngIf='npmInstalled')
|
|||||||
.d-flex.w-100
|
.d-flex.w-100
|
||||||
.mr-auto.d-flex.flex-column
|
.mr-auto.d-flex.flex-column
|
||||||
strong {{plugin.name}}
|
strong {{plugin.name}}
|
||||||
small.text-muted.mb-0 {{plugin.description}}
|
a.text-muted.mb-0((click)='showPluginInfo(plugin)')
|
||||||
|
small {{plugin.description}}
|
||||||
.d-flex.flex-column.align-items-end.mr-3
|
.d-flex.flex-column.align-items-end.mr-3
|
||||||
div {{plugin.version}}
|
div {{plugin.version}}
|
||||||
small.text-muted {{plugin.author}}
|
small.text-muted {{plugin.author}}
|
||||||
|
@@ -5,6 +5,7 @@ import { PluginsSettingsTabComponent } from './components/pluginsSettingsTab.com
|
|||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class PluginsSettingsTabProvider extends SettingsTabProvider {
|
export class PluginsSettingsTabProvider extends SettingsTabProvider {
|
||||||
|
id = 'plugins'
|
||||||
title = 'Plugins'
|
title = 'Plugins'
|
||||||
|
|
||||||
getComponentType (): ComponentType {
|
getComponentType (): ComponentType {
|
||||||
|
@@ -1,9 +1,9 @@
|
|||||||
{
|
{
|
||||||
"name": "terminus-settings",
|
"name": "terminus-settings",
|
||||||
"version": "1.0.0-alpha.24",
|
"version": "1.0.0-alpha.35.3",
|
||||||
"description": "Terminus terminal settings page",
|
"description": "Terminus terminal settings page",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"terminus-plugin"
|
"terminus-builtin-plugin"
|
||||||
],
|
],
|
||||||
"main": "dist/index.js",
|
"main": "dist/index.js",
|
||||||
"typings": "dist/index.d.ts",
|
"typings": "dist/index.d.ts",
|
||||||
|
@@ -3,6 +3,7 @@ import { Component } from '@angular/core'
|
|||||||
export declare type ComponentType = new (...args: any[]) => Component
|
export declare type ComponentType = new (...args: any[]) => Component
|
||||||
|
|
||||||
export abstract class SettingsTabProvider {
|
export abstract class SettingsTabProvider {
|
||||||
|
id: string
|
||||||
title: string
|
title: string
|
||||||
|
|
||||||
getComponentType (): ComponentType {
|
getComponentType (): ComponentType {
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
button.btn.btn-outline-warning.btn-block(*ngIf='config.restartRequested', '(click)'='restartApp()') Restart the app to apply changes
|
button.btn.btn-outline-warning.btn-block(*ngIf='config.restartRequested', '(click)'='restartApp()') Restart the app to apply changes
|
||||||
|
|
||||||
ngb-tabset.vertical(type='tabs')
|
ngb-tabset.vertical(type='tabs', [activeId]='activeTab')
|
||||||
ngb-tab
|
ngb-tab(id='application')
|
||||||
ng-template(ngbTabTitle)
|
ng-template(ngbTabTitle)
|
||||||
| Application
|
| Application
|
||||||
ng-template(ngbTabContent)
|
ng-template(ngbTabContent)
|
||||||
@@ -18,7 +18,7 @@ ngb-tabset.vertical(type='tabs')
|
|||||||
.form-group
|
.form-group
|
||||||
label Show tabs
|
label Show tabs
|
||||||
br
|
br
|
||||||
div(
|
.btn-group(
|
||||||
'[(ngModel)]'='config.store.appearance.tabsLocation',
|
'[(ngModel)]'='config.store.appearance.tabsLocation',
|
||||||
(ngModelChange)='config.save()',
|
(ngModelChange)='config.save()',
|
||||||
ngbRadioGroup
|
ngbRadioGroup
|
||||||
@@ -41,7 +41,7 @@ ngb-tabset.vertical(type='tabs')
|
|||||||
.form-group
|
.form-group
|
||||||
label Window frame
|
label Window frame
|
||||||
br
|
br
|
||||||
div(
|
.btn-group(
|
||||||
'[(ngModel)]'='config.store.appearance.frame'
|
'[(ngModel)]'='config.store.appearance.frame'
|
||||||
'(ngModelChange)'='config.save(); config.requestRestart()'
|
'(ngModelChange)'='config.save(); config.requestRestart()'
|
||||||
ngbRadioGroup
|
ngbRadioGroup
|
||||||
@@ -74,7 +74,7 @@ ngb-tabset.vertical(type='tabs')
|
|||||||
.form-group
|
.form-group
|
||||||
label Dock the terminal
|
label Dock the terminal
|
||||||
br
|
br
|
||||||
div(
|
.btn-group(
|
||||||
'[(ngModel)]'='config.store.appearance.dock'
|
'[(ngModel)]'='config.store.appearance.dock'
|
||||||
'(ngModelChange)'='config.save(); docking.dock()'
|
'(ngModelChange)'='config.save(); docking.dock()'
|
||||||
ngbRadioGroup
|
ngbRadioGroup
|
||||||
@@ -164,7 +164,7 @@ ngb-tabset.vertical(type='tabs')
|
|||||||
'(ngModelChange)'='config.save()',
|
'(ngModelChange)'='config.save()',
|
||||||
)
|
)
|
||||||
|
|
||||||
ngb-tab
|
ngb-tab(id='hotkeys')
|
||||||
ng-template(ngbTabTitle)
|
ng-template(ngbTabTitle)
|
||||||
| Hotkeys
|
| Hotkeys
|
||||||
ng-template(ngbTabContent)
|
ng-template(ngbTabContent)
|
||||||
@@ -184,7 +184,7 @@ ngb-tabset.vertical(type='tabs')
|
|||||||
'(modelChange)'='config.save(); docking.dock()'
|
'(modelChange)'='config.save(); docking.dock()'
|
||||||
)
|
)
|
||||||
|
|
||||||
ngb-tab(*ngFor='let provider of settingsProviders')
|
ngb-tab(*ngFor='let provider of settingsProviders', [id]='provider.id')
|
||||||
ng-template(ngbTabTitle)
|
ng-template(ngbTabTitle)
|
||||||
| {{provider.title}}
|
| {{provider.title}}
|
||||||
ng-template(ngbTabContent)
|
ng-template(ngbTabContent)
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
import { Component, Inject } from '@angular/core'
|
import { Component, Inject, Input } from '@angular/core'
|
||||||
import { ElectronService, DockingService, ConfigService, IHotkeyDescription, HotkeyProvider, BaseTabComponent, Theme, HostAppService } from 'terminus-core'
|
import { ElectronService, DockingService, ConfigService, IHotkeyDescription, HotkeyProvider, BaseTabComponent, Theme, HostAppService } from 'terminus-core'
|
||||||
|
|
||||||
import { SettingsTabProvider } from '../api'
|
import { SettingsTabProvider } from '../api'
|
||||||
@@ -12,6 +12,7 @@ import { SettingsTabProvider } from '../api'
|
|||||||
],
|
],
|
||||||
})
|
})
|
||||||
export class SettingsTabComponent extends BaseTabComponent {
|
export class SettingsTabComponent extends BaseTabComponent {
|
||||||
|
@Input() activeTab: string
|
||||||
hotkeyFilter = ''
|
hotkeyFilter = ''
|
||||||
private hotkeyDescriptions: IHotkeyDescription[]
|
private hotkeyDescriptions: IHotkeyDescription[]
|
||||||
private screens
|
private screens
|
||||||
|
@@ -40,3 +40,4 @@ export default class SettingsModule {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export * from './api'
|
export * from './api'
|
||||||
|
export { SettingsTabComponent }
|
||||||
|
@@ -1,9 +1,9 @@
|
|||||||
{
|
{
|
||||||
"name": "terminus-terminal",
|
"name": "terminus-terminal",
|
||||||
"version": "1.0.0-alpha.24",
|
"version": "1.0.0-alpha.35.1",
|
||||||
"description": "Terminus' terminal emulation core",
|
"description": "Terminus' terminal emulation core",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"terminus-plugin"
|
"terminus-builtin-plugin"
|
||||||
],
|
],
|
||||||
"main": "dist/index.js",
|
"main": "dist/index.js",
|
||||||
"typings": "dist/index.d.ts",
|
"typings": "dist/index.d.ts",
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
|
h3.mb-2 Appearance
|
||||||
.row
|
.row
|
||||||
.col-md-6
|
.col-md-6
|
||||||
.form-group
|
.form-group
|
||||||
label Preview
|
|
||||||
.appearance-preview(
|
.appearance-preview(
|
||||||
[style.font-family]='config.store.terminal.font',
|
[style.font-family]='config.store.terminal.font',
|
||||||
[style.font-size]='config.store.terminal.fontSize + "px"',
|
[style.font-size]='config.store.terminal.fontSize + "px"',
|
||||||
@@ -60,23 +60,6 @@
|
|||||||
span([style.color]='config.store.terminal.colorScheme.colors[15]') W
|
span([style.color]='config.store.terminal.colorScheme.colors[15]') W
|
||||||
div
|
div
|
||||||
span
|
span
|
||||||
div
|
|
||||||
span john@doe-pc
|
|
||||||
span([style.color]='config.store.terminal.colorScheme.colors[1]') $
|
|
||||||
span webpack
|
|
||||||
div
|
|
||||||
span Asset Size
|
|
||||||
div
|
|
||||||
span([style.color]='config.store.terminal.colorScheme.colors[2]') main.js
|
|
||||||
span 234 kB
|
|
||||||
span([style.color]='config.store.terminal.colorScheme.colors[2]') [emitted]
|
|
||||||
div
|
|
||||||
span([style.color]='config.store.terminal.colorScheme.colors[3]') big.js
|
|
||||||
span([style.color]='config.store.terminal.colorScheme.colors[3]') 1.2 MB
|
|
||||||
span([style.color]='config.store.terminal.colorScheme.colors[2]') [emitted]
|
|
||||||
span([style.color]='config.store.terminal.colorScheme.colors[3]') [big]
|
|
||||||
div
|
|
||||||
span
|
|
||||||
div
|
div
|
||||||
span john@doe-pc
|
span john@doe-pc
|
||||||
span([style.color]='config.store.terminal.colorScheme.colors[1]') $
|
span([style.color]='config.store.terminal.colorScheme.colors[1]') $
|
||||||
@@ -178,7 +161,7 @@
|
|||||||
.form-group.mr-3
|
.form-group.mr-3
|
||||||
label Terminal background
|
label Terminal background
|
||||||
br
|
br
|
||||||
div(
|
.btn-group(
|
||||||
'[(ngModel)]'='config.store.terminal.background',
|
'[(ngModel)]'='config.store.terminal.background',
|
||||||
(ngModelChange)='config.save()',
|
(ngModelChange)='config.save()',
|
||||||
ngbRadioGroup
|
ngbRadioGroup
|
||||||
@@ -197,10 +180,11 @@
|
|||||||
[value]='"colorScheme"'
|
[value]='"colorScheme"'
|
||||||
)
|
)
|
||||||
| From colors
|
| From colors
|
||||||
|
|
||||||
.form-group
|
.form-group
|
||||||
label Cursor shape
|
label Cursor shape
|
||||||
br
|
br
|
||||||
div(
|
.btn-group(
|
||||||
[(ngModel)]='config.store.terminal.cursor',
|
[(ngModel)]='config.store.terminal.cursor',
|
||||||
(ngModelChange)='config.save()',
|
(ngModelChange)='config.save()',
|
||||||
ngbRadioGroup
|
ngbRadioGroup
|
||||||
@@ -227,22 +211,56 @@
|
|||||||
)
|
)
|
||||||
| ▁
|
| ▁
|
||||||
|
|
||||||
.form-group
|
h3.mt-2.mb-2 Behaviour
|
||||||
label Shell
|
|
||||||
select.form-control(
|
.row
|
||||||
'[(ngModel)]'='config.store.terminal.shell',
|
.col-md-6
|
||||||
|
.d-flex
|
||||||
|
.form-group.mr-3
|
||||||
|
label Shell
|
||||||
|
select.form-control(
|
||||||
|
'[(ngModel)]'='config.store.terminal.shell',
|
||||||
|
(ngModelChange)='config.save()',
|
||||||
|
)
|
||||||
|
option(
|
||||||
|
*ngFor='let shell of shells',
|
||||||
|
[ngValue]='shell.id'
|
||||||
|
) {{shell.name}}
|
||||||
|
|
||||||
|
.form-group
|
||||||
|
label Session persistence
|
||||||
|
select.form-control(
|
||||||
|
'[(ngModel)]'='config.store.terminal.persistence',
|
||||||
|
(ngModelChange)='config.save()',
|
||||||
|
)
|
||||||
|
option([ngValue]='null') Off
|
||||||
|
option(
|
||||||
|
*ngFor='let provider of persistenceProviders',
|
||||||
|
[ngValue]='provider.id'
|
||||||
|
) {{provider.displayName}}
|
||||||
|
|
||||||
|
.form-group(*ngIf='config.store.terminal.shell == "custom"')
|
||||||
|
label Custom shell
|
||||||
|
input.form-control(
|
||||||
|
type='text',
|
||||||
|
'[(ngModel)]'='config.store.terminal.customShell',
|
||||||
(ngModelChange)='config.save()',
|
(ngModelChange)='config.save()',
|
||||||
)
|
)
|
||||||
option(
|
|
||||||
*ngFor='let shell of shells',
|
|
||||||
[ngValue]='shell.id'
|
|
||||||
) {{shell.name}}
|
|
||||||
|
|
||||||
.form-group
|
.form-group
|
||||||
label Terminal bell
|
label Working directory
|
||||||
|
input.form-control(
|
||||||
|
type='text',
|
||||||
|
placeholder='Home directory',
|
||||||
|
'[(ngModel)]'='config.store.terminal.workingDirectory',
|
||||||
|
(ngModelChange)='config.save()',
|
||||||
|
)
|
||||||
|
|
||||||
|
.form-group
|
||||||
|
label Auto-open a terminal on app start
|
||||||
br
|
br
|
||||||
div(
|
.btn-group(
|
||||||
'[(ngModel)]'='config.store.terminal.bell',
|
'[(ngModel)]'='config.store.terminal.autoOpen',
|
||||||
(ngModelChange)='config.save()',
|
(ngModelChange)='config.save()',
|
||||||
ngbRadioGroup
|
ngbRadioGroup
|
||||||
)
|
)
|
||||||
@@ -250,32 +268,115 @@
|
|||||||
input(
|
input(
|
||||||
type='radio',
|
type='radio',
|
||||||
ngbButton,
|
ngbButton,
|
||||||
[value]='"off"'
|
[value]='false'
|
||||||
)
|
)
|
||||||
| Off
|
| Off
|
||||||
label.btn.btn-secondary(ngbButtonLabel)
|
label.btn.btn-secondary(ngbButtonLabel)
|
||||||
input(
|
input(
|
||||||
type='radio',
|
type='radio',
|
||||||
ngbButton,
|
ngbButton,
|
||||||
[value]='"visual"'
|
[value]='true'
|
||||||
)
|
)
|
||||||
| Visual
|
| On
|
||||||
label.btn.btn-secondary(ngbButtonLabel)
|
|
||||||
input(
|
.col-md-6
|
||||||
type='radio',
|
.d-flex
|
||||||
ngbButton,
|
.form-group.mr-3
|
||||||
[value]='"audible"'
|
label Terminal bell
|
||||||
)
|
br
|
||||||
| Audible
|
.btn-group(
|
||||||
|
'[(ngModel)]'='config.store.terminal.bell',
|
||||||
|
(ngModelChange)='config.save()',
|
||||||
|
ngbRadioGroup
|
||||||
|
)
|
||||||
|
label.btn.btn-secondary(ngbButtonLabel)
|
||||||
|
input(
|
||||||
|
type='radio',
|
||||||
|
ngbButton,
|
||||||
|
[value]='"off"'
|
||||||
|
)
|
||||||
|
| Off
|
||||||
|
label.btn.btn-secondary(ngbButtonLabel)
|
||||||
|
input(
|
||||||
|
type='radio',
|
||||||
|
ngbButton,
|
||||||
|
[value]='"visual"'
|
||||||
|
)
|
||||||
|
| Visual
|
||||||
|
label.btn.btn-secondary(ngbButtonLabel)
|
||||||
|
input(
|
||||||
|
type='radio',
|
||||||
|
ngbButton,
|
||||||
|
[value]='"audible"'
|
||||||
|
)
|
||||||
|
| Audible
|
||||||
|
|
||||||
.form-group
|
.form-group
|
||||||
label Session persistence
|
label Blink cursor
|
||||||
select.form-control(
|
br
|
||||||
'[(ngModel)]'='config.store.terminal.persistence',
|
.btn-group(
|
||||||
(ngModelChange)='config.save()',
|
'[(ngModel)]'='config.store.terminal.cursorBlink',
|
||||||
)
|
(ngModelChange)='config.save()',
|
||||||
option([ngValue]='null') Off
|
ngbRadioGroup
|
||||||
option(
|
)
|
||||||
*ngFor='let provider of persistenceProviders',
|
label.btn.btn-secondary(ngbButtonLabel)
|
||||||
[ngValue]='provider.id'
|
input(
|
||||||
) {{provider.displayName}}
|
type='radio',
|
||||||
|
ngbButton,
|
||||||
|
[value]='false'
|
||||||
|
)
|
||||||
|
| Off
|
||||||
|
label.btn.btn-secondary(ngbButtonLabel)
|
||||||
|
input(
|
||||||
|
type='radio',
|
||||||
|
ngbButton,
|
||||||
|
[value]='true'
|
||||||
|
)
|
||||||
|
| On
|
||||||
|
|
||||||
|
.d-flex
|
||||||
|
.form-group.mr-3
|
||||||
|
label Copy on select
|
||||||
|
br
|
||||||
|
.btn-group(
|
||||||
|
'[(ngModel)]'='config.store.terminal.copyOnSelect',
|
||||||
|
(ngModelChange)='config.save()',
|
||||||
|
ngbRadioGroup
|
||||||
|
)
|
||||||
|
label.btn.btn-secondary(ngbButtonLabel)
|
||||||
|
input(
|
||||||
|
type='radio',
|
||||||
|
ngbButton,
|
||||||
|
[value]='false'
|
||||||
|
)
|
||||||
|
| Off
|
||||||
|
label.btn.btn-secondary(ngbButtonLabel)
|
||||||
|
input(
|
||||||
|
type='radio',
|
||||||
|
ngbButton,
|
||||||
|
[value]='true'
|
||||||
|
)
|
||||||
|
| On
|
||||||
|
|
||||||
|
.form-group
|
||||||
|
label Right click behaviour
|
||||||
|
br
|
||||||
|
.btn-group(
|
||||||
|
'[(ngModel)]'='config.store.terminal.rightClick',
|
||||||
|
(ngModelChange)='config.save()',
|
||||||
|
ngbRadioGroup
|
||||||
|
)
|
||||||
|
label.btn.btn-secondary(ngbButtonLabel)
|
||||||
|
input(
|
||||||
|
type='radio',
|
||||||
|
ngbButton,
|
||||||
|
value='menu'
|
||||||
|
)
|
||||||
|
| Menu
|
||||||
|
label.btn.btn-secondary(ngbButtonLabel)
|
||||||
|
input(
|
||||||
|
type='radio',
|
||||||
|
ngbButton,
|
||||||
|
value='paste'
|
||||||
|
)
|
||||||
|
| Paste
|
||||||
|
@@ -60,23 +60,28 @@ export class TerminalTabComponent extends BaseTabComponent {
|
|||||||
this.decorators = this.decorators || []
|
this.decorators = this.decorators || []
|
||||||
this.title = 'Terminal'
|
this.title = 'Terminal'
|
||||||
this.resize$.first().subscribe(async (resizeEvent) => {
|
this.resize$.first().subscribe(async (resizeEvent) => {
|
||||||
this.session = this.sessions.addSession(
|
if (!this.session) {
|
||||||
Object.assign({}, this.sessionOptions, resizeEvent)
|
this.session = this.sessions.addSession(
|
||||||
)
|
Object.assign({}, this.sessionOptions, resizeEvent)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
this.session.resize(resizeEvent.width, resizeEvent.height)
|
this.session.resize(resizeEvent.width, resizeEvent.height)
|
||||||
}, 1000)
|
}, 1000)
|
||||||
|
|
||||||
// this.session.output$.bufferTime(10).subscribe((datas) => {
|
// this.session.output$.bufferTime(10).subscribe((datas) => {
|
||||||
this.session.output$.subscribe(data => {
|
this.session.output$.subscribe(data => {
|
||||||
// let data = datas.join('')
|
|
||||||
this.zone.run(() => {
|
this.zone.run(() => {
|
||||||
this.output$.next(data)
|
this.output$.next(data)
|
||||||
|
this.write(data)
|
||||||
})
|
})
|
||||||
this.write(data)
|
|
||||||
})
|
})
|
||||||
|
|
||||||
this.sessionCloseSubscription = this.session.closed$.subscribe(() => {
|
this.sessionCloseSubscription = this.session.closed$.subscribe(() => {
|
||||||
this.app.closeTab(this)
|
this.app.closeTab(this)
|
||||||
})
|
})
|
||||||
|
|
||||||
this.session.releaseInitialDataBuffer()
|
this.session.releaseInitialDataBuffer()
|
||||||
})
|
})
|
||||||
this.hotkeysSubscription = this.hotkeys.matchedHotkey.subscribe(hotkey => {
|
this.hotkeysSubscription = this.hotkeys.matchedHotkey.subscribe(hotkey => {
|
||||||
@@ -178,7 +183,7 @@ export class TerminalTabComponent extends BaseTabComponent {
|
|||||||
label: 'Paste',
|
label: 'Paste',
|
||||||
click: () => {
|
click: () => {
|
||||||
this.zone.run(() => {
|
this.zone.run(() => {
|
||||||
this.sendInput(this.electron.clipboard.readText())
|
this.paste()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -223,12 +228,17 @@ export class TerminalTabComponent extends BaseTabComponent {
|
|||||||
this.mouseEvent$.next(event)
|
this.mouseEvent$.next(event)
|
||||||
if (event.type === 'mousedown') {
|
if (event.type === 'mousedown') {
|
||||||
if (event.which === 3) {
|
if (event.which === 3) {
|
||||||
this.contextMenu.popup({
|
if (this.config.store.terminal.rightClick === 'menu') {
|
||||||
x: event.pageX,
|
this.contextMenu.popup({
|
||||||
y: event.pageY,
|
x: event.pageX + this.content.nativeElement.getBoundingClientRect().left,
|
||||||
async: true,
|
y: event.pageY + this.content.nativeElement.getBoundingClientRect().top,
|
||||||
})
|
async: true,
|
||||||
|
})
|
||||||
|
} else if (this.config.store.terminal.rightClick === 'paste') {
|
||||||
|
this.paste()
|
||||||
|
}
|
||||||
event.preventDefault()
|
event.preventDefault()
|
||||||
|
event.stopPropagation()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -302,6 +312,10 @@ export class TerminalTabComponent extends BaseTabComponent {
|
|||||||
this.io.writeUTF8(data)
|
this.io.writeUTF8(data)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
paste () {
|
||||||
|
this.sendInput(this.electron.clipboard.readText())
|
||||||
|
}
|
||||||
|
|
||||||
clear () {
|
clear () {
|
||||||
this.hterm.wipeContents()
|
this.hterm.wipeContents()
|
||||||
this.hterm.onVTKeystroke('\f')
|
this.hterm.onVTKeystroke('\f')
|
||||||
@@ -319,9 +333,11 @@ export class TerminalTabComponent extends BaseTabComponent {
|
|||||||
preferenceManager.set('send-encoding', 'raw')
|
preferenceManager.set('send-encoding', 'raw')
|
||||||
preferenceManager.set('ctrl-plus-minus-zero-zoom', false)
|
preferenceManager.set('ctrl-plus-minus-zero-zoom', false)
|
||||||
preferenceManager.set('scrollbar-visible', this.hostApp.platform === Platform.macOS)
|
preferenceManager.set('scrollbar-visible', this.hostApp.platform === Platform.macOS)
|
||||||
preferenceManager.set('copy-on-select', false)
|
preferenceManager.set('copy-on-select', config.terminal.copyOnSelect)
|
||||||
preferenceManager.set('alt-sends-what', 'browser-key')
|
preferenceManager.set('alt-sends-what', 'browser-key')
|
||||||
preferenceManager.set('alt-gr-mode', 'ctrl-alt')
|
preferenceManager.set('alt-gr-mode', 'ctrl-alt')
|
||||||
|
preferenceManager.set('pass-alt-number', true)
|
||||||
|
preferenceManager.set('cursor-blink', config.terminal.cursorBlink)
|
||||||
|
|
||||||
if (config.terminal.colorScheme.foreground) {
|
if (config.terminal.colorScheme.foreground) {
|
||||||
preferenceManager.set('foreground-color', config.terminal.colorScheme.foreground)
|
preferenceManager.set('foreground-color', config.terminal.colorScheme.foreground)
|
||||||
@@ -368,6 +384,10 @@ export class TerminalTabComponent extends BaseTabComponent {
|
|||||||
beam: hterm.hterm.Terminal.cursorShape.BEAM,
|
beam: hterm.hterm.Terminal.cursorShape.BEAM,
|
||||||
}[config.terminal.cursor]
|
}[config.terminal.cursor]
|
||||||
this.hterm.applyCursorShape()
|
this.hterm.applyCursorShape()
|
||||||
|
this.hterm.setCursorBlink(config.terminal.cursorBlink)
|
||||||
|
if (config.terminal.cursorBlink) {
|
||||||
|
this.hterm.onCursorBlink_()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
zoomIn () {
|
zoomIn () {
|
||||||
|
@@ -3,6 +3,7 @@ import { ConfigProvider, Platform } from 'terminus-core'
|
|||||||
export class TerminalConfigProvider extends ConfigProvider {
|
export class TerminalConfigProvider extends ConfigProvider {
|
||||||
defaults = {
|
defaults = {
|
||||||
terminal: {
|
terminal: {
|
||||||
|
autoOpen: false,
|
||||||
fontSize: 14,
|
fontSize: 14,
|
||||||
linePadding: 0,
|
linePadding: 0,
|
||||||
bell: 'off',
|
bell: 'off',
|
||||||
@@ -10,6 +11,11 @@ export class TerminalConfigProvider extends ConfigProvider {
|
|||||||
background: 'theme',
|
background: 'theme',
|
||||||
ligatures: false,
|
ligatures: false,
|
||||||
cursor: 'block',
|
cursor: 'block',
|
||||||
|
cursorBlink: true,
|
||||||
|
customShell: '',
|
||||||
|
rightClick: 'menu',
|
||||||
|
copyOnSelect: false,
|
||||||
|
workingDirectory: '',
|
||||||
colorScheme: {
|
colorScheme: {
|
||||||
__nonStructural: true,
|
__nonStructural: true,
|
||||||
name: 'Material',
|
name: 'Material',
|
||||||
@@ -77,6 +83,8 @@ export class TerminalConfigProvider extends ConfigProvider {
|
|||||||
font: 'Consolas',
|
font: 'Consolas',
|
||||||
shell: 'clink',
|
shell: 'clink',
|
||||||
persistence: null,
|
persistence: null,
|
||||||
|
rightClick: 'paste',
|
||||||
|
copyOnSelect: true,
|
||||||
},
|
},
|
||||||
hotkeys: {
|
hotkeys: {
|
||||||
'copy': [
|
'copy': [
|
||||||
|
@@ -3,14 +3,14 @@ import { BrowserModule } from '@angular/platform-browser'
|
|||||||
import { FormsModule } from '@angular/forms'
|
import { FormsModule } from '@angular/forms'
|
||||||
import { NgbModule } from '@ng-bootstrap/ng-bootstrap'
|
import { NgbModule } from '@ng-bootstrap/ng-bootstrap'
|
||||||
|
|
||||||
import { ToolbarButtonProvider, TabRecoveryProvider, ConfigProvider, HotkeysService, HotkeyProvider } from 'terminus-core'
|
import { ToolbarButtonProvider, TabRecoveryProvider, ConfigProvider, HotkeysService, HotkeyProvider, AppService, ConfigService } from 'terminus-core'
|
||||||
import { SettingsTabProvider } from 'terminus-settings'
|
import { SettingsTabProvider } from 'terminus-settings'
|
||||||
|
|
||||||
import { TerminalTabComponent } from './components/terminalTab.component'
|
import { TerminalTabComponent } from './components/terminalTab.component'
|
||||||
import { TerminalSettingsTabComponent } from './components/terminalSettingsTab.component'
|
import { TerminalSettingsTabComponent } from './components/terminalSettingsTab.component'
|
||||||
import { ColorPickerComponent } from './components/colorPicker.component'
|
import { ColorPickerComponent } from './components/colorPicker.component'
|
||||||
|
|
||||||
import { SessionsService } from './services/sessions.service'
|
import { SessionsService, BaseSession } from './services/sessions.service'
|
||||||
import { TerminalService } from './services/terminal.service'
|
import { TerminalService } from './services/terminal.service'
|
||||||
|
|
||||||
import { ScreenPersistenceProvider } from './persistence/screen'
|
import { ScreenPersistenceProvider } from './persistence/screen'
|
||||||
@@ -24,6 +24,7 @@ import { TerminalConfigProvider } from './config'
|
|||||||
import { TerminalHotkeyProvider } from './hotkeys'
|
import { TerminalHotkeyProvider } from './hotkeys'
|
||||||
import { HyperColorSchemes } from './colorSchemes'
|
import { HyperColorSchemes } from './colorSchemes'
|
||||||
|
|
||||||
|
import { CustomShellProvider } from './shells/custom'
|
||||||
import { Cygwin32ShellProvider } from './shells/cygwin32'
|
import { Cygwin32ShellProvider } from './shells/cygwin32'
|
||||||
import { Cygwin64ShellProvider } from './shells/cygwin64'
|
import { Cygwin64ShellProvider } from './shells/cygwin64'
|
||||||
import { GitBashShellProvider } from './shells/gitBash'
|
import { GitBashShellProvider } from './shells/gitBash'
|
||||||
@@ -59,6 +60,7 @@ import { hterm } from './hterm'
|
|||||||
{ provide: ShellProvider, useClass: WindowsStockShellsProvider, multi: true },
|
{ provide: ShellProvider, useClass: WindowsStockShellsProvider, multi: true },
|
||||||
{ provide: ShellProvider, useClass: MacOSDefaultShellProvider, multi: true },
|
{ provide: ShellProvider, useClass: MacOSDefaultShellProvider, multi: true },
|
||||||
{ provide: ShellProvider, useClass: LinuxDefaultShellProvider, multi: true },
|
{ provide: ShellProvider, useClass: LinuxDefaultShellProvider, multi: true },
|
||||||
|
{ provide: ShellProvider, useClass: CustomShellProvider, multi: true },
|
||||||
{ provide: ShellProvider, useClass: Cygwin32ShellProvider, multi: true },
|
{ provide: ShellProvider, useClass: Cygwin32ShellProvider, multi: true },
|
||||||
{ provide: ShellProvider, useClass: Cygwin64ShellProvider, multi: true },
|
{ provide: ShellProvider, useClass: Cygwin64ShellProvider, multi: true },
|
||||||
{ provide: ShellProvider, useClass: GitBashShellProvider, multi: true },
|
{ provide: ShellProvider, useClass: GitBashShellProvider, multi: true },
|
||||||
@@ -76,7 +78,12 @@ import { hterm } from './hterm'
|
|||||||
],
|
],
|
||||||
})
|
})
|
||||||
export default class TerminalModule {
|
export default class TerminalModule {
|
||||||
constructor (hotkeys: HotkeysService) {
|
constructor (
|
||||||
|
app: AppService,
|
||||||
|
config: ConfigService,
|
||||||
|
hotkeys: HotkeysService,
|
||||||
|
terminal: TerminalService,
|
||||||
|
) {
|
||||||
let events = [
|
let events = [
|
||||||
{
|
{
|
||||||
name: 'keydown',
|
name: 'keydown',
|
||||||
@@ -101,8 +108,13 @@ export default class TerminalModule {
|
|||||||
hotkeys.emitKeyEvent(nativeEvent)
|
hotkeys.emitKeyEvent(nativeEvent)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
if (config.store.terminal.autoOpen) {
|
||||||
|
app.ready$.subscribe(() => {
|
||||||
|
terminal.openTab()
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export * from './api'
|
export * from './api'
|
||||||
export { TerminalService }
|
export { TerminalService, BaseSession, TerminalTabComponent }
|
||||||
|
@@ -14,7 +14,7 @@ export interface IChildProcess {
|
|||||||
command: string
|
command: string
|
||||||
}
|
}
|
||||||
|
|
||||||
export class Session {
|
export abstract class BaseSession {
|
||||||
open: boolean
|
open: boolean
|
||||||
name: string
|
name: string
|
||||||
output$ = new Subject<string>()
|
output$ = new Subject<string>()
|
||||||
@@ -22,11 +22,46 @@ export class Session {
|
|||||||
destroyed$ = new Subject<void>()
|
destroyed$ = new Subject<void>()
|
||||||
recoveryId: string
|
recoveryId: string
|
||||||
truePID: number
|
truePID: number
|
||||||
private pty: any
|
|
||||||
private initialDataBuffer = ''
|
private initialDataBuffer = ''
|
||||||
private initialDataBufferReleased = false
|
private initialDataBufferReleased = false
|
||||||
|
|
||||||
|
emitOutput (data: string) {
|
||||||
|
if (!this.initialDataBufferReleased) {
|
||||||
|
this.initialDataBuffer += data
|
||||||
|
} else {
|
||||||
|
this.output$.next(data)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
releaseInitialDataBuffer () {
|
||||||
|
this.initialDataBufferReleased = true
|
||||||
|
this.output$.next(this.initialDataBuffer)
|
||||||
|
this.initialDataBuffer = null
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract resize (columns, rows)
|
||||||
|
abstract write (data)
|
||||||
|
abstract kill (signal?: string)
|
||||||
|
abstract async getChildProcesses (): Promise<IChildProcess[]>
|
||||||
|
abstract async gracefullyKillProcess (): Promise<void>
|
||||||
|
abstract async getWorkingDirectory (): Promise<string>
|
||||||
|
|
||||||
|
async destroy (): Promise<void> {
|
||||||
|
if (this.open) {
|
||||||
|
this.open = false
|
||||||
|
this.closed$.next()
|
||||||
|
this.destroyed$.next()
|
||||||
|
this.output$.complete()
|
||||||
|
await this.gracefullyKillProcess()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class Session extends BaseSession {
|
||||||
|
private pty: any
|
||||||
|
|
||||||
constructor (options: SessionOptions) {
|
constructor (options: SessionOptions) {
|
||||||
|
super()
|
||||||
this.name = options.name
|
this.name = options.name
|
||||||
this.recoveryId = options.recoveryId
|
this.recoveryId = options.recoveryId
|
||||||
|
|
||||||
@@ -65,12 +100,8 @@ export class Session {
|
|||||||
|
|
||||||
this.open = true
|
this.open = true
|
||||||
|
|
||||||
this.pty.on('data', (data) => {
|
this.pty.on('data', data => {
|
||||||
if (!this.initialDataBufferReleased) {
|
this.emitOutput(data)
|
||||||
this.initialDataBuffer += data
|
|
||||||
} else {
|
|
||||||
this.output$.next(data)
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
|
|
||||||
this.pty.on('exit', () => {
|
this.pty.on('exit', () => {
|
||||||
@@ -86,12 +117,6 @@ export class Session {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
releaseInitialDataBuffer () {
|
|
||||||
this.initialDataBufferReleased = true
|
|
||||||
this.output$.next(this.initialDataBuffer)
|
|
||||||
this.initialDataBuffer = null
|
|
||||||
}
|
|
||||||
|
|
||||||
resize (columns, rows) {
|
resize (columns, rows) {
|
||||||
if (this.pty._writable) {
|
if (this.pty._writable) {
|
||||||
this.pty.resize(columns, rows)
|
this.pty.resize(columns, rows)
|
||||||
@@ -144,16 +169,6 @@ export class Session {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async destroy (): Promise<void> {
|
|
||||||
if (this.open) {
|
|
||||||
this.open = false
|
|
||||||
this.closed$.next()
|
|
||||||
this.destroyed$.next()
|
|
||||||
this.output$.complete()
|
|
||||||
await this.gracefullyKillProcess()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async getWorkingDirectory (): Promise<string> {
|
async getWorkingDirectory (): Promise<string> {
|
||||||
if (!this.truePID) {
|
if (!this.truePID) {
|
||||||
return null
|
return null
|
||||||
|
@@ -14,19 +14,31 @@ export class TerminalService {
|
|||||||
private app: AppService,
|
private app: AppService,
|
||||||
private sessions: SessionsService,
|
private sessions: SessionsService,
|
||||||
private config: ConfigService,
|
private config: ConfigService,
|
||||||
@Inject(ShellProvider) shellProviders: ShellProvider[],
|
@Inject(ShellProvider) private shellProviders: ShellProvider[],
|
||||||
log: LogService,
|
log: LogService,
|
||||||
) {
|
) {
|
||||||
this.logger = log.create('terminal')
|
this.logger = log.create('terminal')
|
||||||
Promise.all(shellProviders.map(x => x.provide())).then(shellLists => {
|
this.reloadShells()
|
||||||
this.shells$.next(shellLists.reduce((a, b) => a.concat(b)))
|
|
||||||
this.shells$.complete()
|
config.changed$.subscribe(() => {
|
||||||
|
this.reloadShells()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async reloadShells () {
|
||||||
|
this.shells$ = new AsyncSubject<IShell[]>()
|
||||||
|
let shellLists = await Promise.all(this.shellProviders.map(x => x.provide()))
|
||||||
|
this.shells$.next(shellLists.reduce((a, b) => a.concat(b)))
|
||||||
|
this.shells$.complete()
|
||||||
|
}
|
||||||
|
|
||||||
async openTab (shell?: IShell, cwd?: string): Promise<TerminalTabComponent> {
|
async openTab (shell?: IShell, cwd?: string): Promise<TerminalTabComponent> {
|
||||||
if (!cwd && this.app.activeTab instanceof TerminalTabComponent) {
|
if (!cwd) {
|
||||||
cwd = await this.app.activeTab.session.getWorkingDirectory()
|
if (this.app.activeTab instanceof TerminalTabComponent) {
|
||||||
|
cwd = await this.app.activeTab.session.getWorkingDirectory()
|
||||||
|
} else {
|
||||||
|
cwd = this.config.store.terminal.workingDirectory || null
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (!shell) {
|
if (!shell) {
|
||||||
let shells = await this.shells$.toPromise()
|
let shells = await this.shells$.toPromise()
|
||||||
|
@@ -5,6 +5,7 @@ import { TerminalSettingsTabComponent } from './components/terminalSettingsTab.c
|
|||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class TerminalSettingsTabProvider extends SettingsTabProvider {
|
export class TerminalSettingsTabProvider extends SettingsTabProvider {
|
||||||
|
id = 'terminal'
|
||||||
title = 'Terminal'
|
title = 'Terminal'
|
||||||
|
|
||||||
getComponentType (): ComponentType {
|
getComponentType (): ComponentType {
|
||||||
|
23
terminus-terminal/src/shells/custom.ts
Normal file
23
terminus-terminal/src/shells/custom.ts
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
import { Injectable } from '@angular/core'
|
||||||
|
import { ConfigService } from 'terminus-core'
|
||||||
|
|
||||||
|
import { ShellProvider, IShell } from '../api'
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class CustomShellProvider extends ShellProvider {
|
||||||
|
constructor (
|
||||||
|
private config: ConfigService,
|
||||||
|
) {
|
||||||
|
super()
|
||||||
|
}
|
||||||
|
|
||||||
|
async provide (): Promise<IShell[]> {
|
||||||
|
let args = this.config.store.terminal.customShell.split(' ')
|
||||||
|
return [{
|
||||||
|
id: 'custom',
|
||||||
|
name: 'Custom',
|
||||||
|
command: args[0],
|
||||||
|
args: args.slice(1),
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
}
|
@@ -33,7 +33,8 @@ export class LinuxDefaultShellProvider extends ShellProvider {
|
|||||||
return [{
|
return [{
|
||||||
id: 'default',
|
id: 'default',
|
||||||
name: 'User default',
|
name: 'User default',
|
||||||
command: line.split(':')[6]
|
command: line.split(':')[6],
|
||||||
|
args: ['--login'],
|
||||||
}]
|
}]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -20,7 +20,8 @@ export class MacOSDefaultShellProvider extends ShellProvider {
|
|||||||
return [{
|
return [{
|
||||||
id: 'default',
|
id: 'default',
|
||||||
name: 'User default',
|
name: 'User default',
|
||||||
command: shellEntry.split(' ')[1].trim()
|
command: shellEntry.split(' ')[1].trim(),
|
||||||
|
args: ['--login'],
|
||||||
}]
|
}]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -24,6 +24,7 @@ export class POSIXShellsProvider extends ShellProvider {
|
|||||||
id: x,
|
id: x,
|
||||||
name: x,
|
name: x,
|
||||||
command: x,
|
command: x,
|
||||||
|
args: ['--login'],
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -25,7 +25,10 @@ export class WSLShellProvider extends ShellProvider {
|
|||||||
return [{
|
return [{
|
||||||
id: 'wsl',
|
id: 'wsl',
|
||||||
name: 'Bash on Windows',
|
name: 'Bash on Windows',
|
||||||
command: wslPath
|
command: wslPath,
|
||||||
|
env: {
|
||||||
|
TERM: 'xterm-color',
|
||||||
|
}
|
||||||
}]
|
}]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -15,8 +15,10 @@
|
|||||||
"skipLibCheck": true,
|
"skipLibCheck": true,
|
||||||
"lib": [
|
"lib": [
|
||||||
"dom",
|
"dom",
|
||||||
"es2015",
|
"es5",
|
||||||
"es7"
|
"es6",
|
||||||
|
"es7",
|
||||||
|
"es2015"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user