diff --git a/terminus-core/package.json b/terminus-core/package.json
index 85bcaa3a..ccbca969 100644
--- a/terminus-core/package.json
+++ b/terminus-core/package.json
@@ -19,6 +19,7 @@
"webpack": "^2.3.3",
"bootstrap": "4.0.0-alpha.6",
"core-js": "^2.4.1",
+ "ngx-perfect-scrollbar": "^4.0.0",
"style-loader": "^0.13.1",
"to-string-loader": "^1.1.5",
"json-loader": "^0.5.4",
diff --git a/terminus-core/src/components/appRoot.pug b/terminus-core/src/components/appRoot.pug
index 7dccd977..05771624 100644
--- a/terminus-core/src/components/appRoot.pug
+++ b/terminus-core/src/components/appRoot.pug
@@ -38,7 +38,7 @@ title-bar(*ngIf='!config.store.appearance.useNativeFrame && config.store.appeara
*ngFor='let tab of app.tabs; trackBy: tab?.id',
[active]='tab == app.activeTab',
[tab]='tab',
- [class.scrollable]='tab.scrollable',
+ [scrollable]='tab.scrollable',
)
toaster-container([toasterconfig]="toasterconfig")
diff --git a/terminus-core/src/components/appRoot.ts b/terminus-core/src/components/appRoot.ts
index d2c94519..467c39c2 100644
--- a/terminus-core/src/components/appRoot.ts
+++ b/terminus-core/src/components/appRoot.ts
@@ -92,7 +92,6 @@ export class AppRootComponent {
this.docking.dock()
})
- this.hotkeys.registerHotkeys()
this.hostApp.secondInstance.subscribe(() => {
this.onGlobalHotkey()
})
diff --git a/terminus-core/src/components/tabBody.scss b/terminus-core/src/components/tabBody.component.scss
similarity index 100%
rename from terminus-core/src/components/tabBody.scss
rename to terminus-core/src/components/tabBody.component.scss
diff --git a/terminus-core/src/components/tabBody.ts b/terminus-core/src/components/tabBody.component.ts
similarity index 57%
rename from terminus-core/src/components/tabBody.ts
rename to terminus-core/src/components/tabBody.component.ts
index 6ca4b833..9073a444 100644
--- a/terminus-core/src/components/tabBody.ts
+++ b/terminus-core/src/components/tabBody.component.ts
@@ -2,13 +2,21 @@ import { Component, Input, ViewChild, HostBinding, ViewContainerRef } from '@ang
import { BaseTabComponent } from '../components/baseTab'
@Component({
- selector: 'tab-body',
- template: '',
- styles: [require('./tabBody.scss')],
+ selector: 'tab-body',
+ template: `
+
+
+
+ `,
+ styles: [
+ require('./tabBody.component.scss'),
+ require('./tabBody.deep.component.css'),
+ ],
})
export class TabBodyComponent {
@Input() @HostBinding('class.active') active: boolean
@Input() tab: BaseTabComponent
+ @Input() scrollable: boolean
@ViewChild('placeholder', {read: ViewContainerRef}) placeholder: ViewContainerRef
ngAfterViewInit () {
diff --git a/terminus-core/src/components/tabBody.deep.component.css b/terminus-core/src/components/tabBody.deep.component.css
new file mode 100644
index 00000000..09a65f10
--- /dev/null
+++ b/terminus-core/src/components/tabBody.deep.component.css
@@ -0,0 +1,4 @@
+:host /deep/ .ps-content {
+ flex: auto;
+ display: flex;
+}
diff --git a/terminus-core/src/defaultConfigValues.yaml b/terminus-core/src/defaultConfigValues.yaml
index 2b958e89..2259ad40 100644
--- a/terminus-core/src/defaultConfigValues.yaml
+++ b/terminus-core/src/defaultConfigValues.yaml
@@ -6,6 +6,8 @@ appearance:
theme: 'Standard'
useNativeFrame: false
hotkeys:
+ toggle-window:
+ - 'Ctrl+Space'
close-tab:
- 'Ctrl-Shift-W'
- ['Ctrl-A', 'K']
diff --git a/terminus-core/src/index.ts b/terminus-core/src/index.ts
index 17a70326..1c550587 100644
--- a/terminus-core/src/index.ts
+++ b/terminus-core/src/index.ts
@@ -4,6 +4,7 @@ import { BrowserAnimationsModule } from '@angular/platform-browser/animations'
import { FormsModule } from '@angular/forms'
import { ToasterModule } from 'angular2-toaster'
import { NgbModule } from '@ng-bootstrap/ng-bootstrap'
+import { PerfectScrollbarModule } from 'ngx-perfect-scrollbar'
import { AppService } from './services/app'
import { ConfigService } from './services/config'
@@ -19,7 +20,7 @@ import { TabRecoveryService } from './services/tabRecovery'
import { ThemesService } from './services/themes'
import { AppRootComponent } from './components/appRoot'
-import { TabBodyComponent } from './components/tabBody'
+import { TabBodyComponent } from './components/tabBody.component'
import { StartPageComponent } from './components/startPage'
import { TabHeaderComponent } from './components/tabHeader'
import { TitleBarComponent } from './components/titleBar'
@@ -29,6 +30,7 @@ import { Theme } from './api/theme'
import { StandardTheme } from './theme'
+import 'perfect-scrollbar/dist/css/perfect-scrollbar.css'
const PROVIDERS = [
AppService,
@@ -55,6 +57,9 @@ const PROVIDERS = [
FormsModule,
ToasterModule,
NgbModule,
+ PerfectScrollbarModule.forRoot({
+ suppressScrollX: true,
+ }),
],
declarations: [
AppRootComponent,
diff --git a/terminus-core/src/services/config.ts b/terminus-core/src/services/config.ts
index b0fdd750..52c46833 100644
--- a/terminus-core/src/services/config.ts
+++ b/terminus-core/src/services/config.ts
@@ -12,7 +12,8 @@ export class ConfigProxy {
if (
defaults[key] instanceof Object &&
!(defaults[key] instanceof Array) &&
- Object.keys(defaults[key]).length > 0
+ Object.keys(defaults[key]).length > 0 &&
+ !defaults[key].__nonStructural
) {
if (!real[key]) {
real[key] = {}
diff --git a/terminus-core/src/services/hotkeys.ts b/terminus-core/src/services/hotkeys.ts
index 87ec28a2..76f60dcd 100644
--- a/terminus-core/src/services/hotkeys.ts
+++ b/terminus-core/src/services/hotkeys.ts
@@ -44,6 +44,10 @@ export class HotkeysService {
})
})
this.hotkeyDescriptions = hotkeyProviders.map(x => x.hotkeys).reduce((a, b) => a.concat(b))
+ this.config.change.subscribe(() => {
+ this.registerGlobalHotkey()
+ })
+ this.registerGlobalHotkey()
}
pushKeystroke (name, nativeEvent) {
@@ -79,11 +83,18 @@ export class HotkeysService {
return stringifyKeySequence(this.currentKeystrokes.map((x) => x.event))
}
- registerHotkeys () {
+ registerGlobalHotkey () {
this.electron.globalShortcut.unregisterAll()
- // TODO
- this.electron.globalShortcut.register('Ctrl+Space', () => {
- this.globalHotkey.emit()
+ let value = this.config.store.hotkeys['toggle-window']
+ if (typeof value == 'string') {
+ value = [value]
+ }
+ value.forEach(item => {
+ item = (typeof item == 'string') ? [item] : item
+
+ this.electron.globalShortcut.register(item[0].replace(/-/g, '+'), () => {
+ this.globalHotkey.emit()
+ })
})
}
@@ -163,6 +174,10 @@ export class HotkeysService {
@Injectable()
export class AppHotkeyProvider extends HotkeyProvider {
hotkeys: IHotkeyDescription[] = [
+ {
+ id: 'toggle-window',
+ name: 'Toggle terminal window',
+ },
{
id: 'new-tab',
name: 'New tab',
diff --git a/terminus-core/src/theme.scss b/terminus-core/src/theme.scss
index c688d46e..574b6488 100644
--- a/terminus-core/src/theme.scss
+++ b/terminus-core/src/theme.scss
@@ -42,23 +42,34 @@ $input-bg: #111;
$input-bg-disabled: #333;
$input-color: $body-color;
-//$input-border-color: rgba($black,.15);
+$input-color-placeholder: #333;
+$input-border-color: #344;
//$input-box-shadow: inset 0 1px 1px rgba($black,.075);
-
$input-border-radius: 0;
-
$input-bg-focus: $input-bg;
//$input-border-focus: lighten($brand-primary, 25%);
//$input-box-shadow-focus: $input-box-shadow, rgba($input-border-focus, .6);
$input-color-focus: $input-color;
+$input-group-addon-bg: $input-bg;
+$input-group-addon-border-color: $input-border-color;
$modal-content-bg: $body-bg;
$modal-content-border-color: $body-bg2;
-$modal-header-border-color: $body-bg2;
-$modal-footer-border-color: $body-bg2;
+$modal-header-border-color: transparent;
+$modal-footer-border-color: transparent;
$popover-bg: $body-bg2;
+$dropdown-bg: $body-bg2;
+$dropdown-link-color: $body-color;
+$dropdown-link-hover-color: #333;
+$dropdown-link-hover-bg: $body-bg3;
+//$dropdown-link-active-color: $component-active-color;
+//$dropdown-link-active-bg: $component-active-bg;
+$dropdown-link-disabled-color: #333;
+$dropdown-header-color: #333;
+
+
@import '~bootstrap/scss/bootstrap.scss';
@@ -300,3 +311,7 @@ ngb-tabset .tab-content {
margin-left: 5px;
}
}
+
+.input-group-addon + .form-control {
+ border-left: none;
+}
diff --git a/terminus-core/webpack.config.js b/terminus-core/webpack.config.js
index 55ff01d0..06e6adeb 100644
--- a/terminus-core/webpack.config.js
+++ b/terminus-core/webpack.config.js
@@ -31,6 +31,8 @@ module.exports = {
},
{ test: /\.pug$/, use: ['apply-loader', 'pug-loader'] },
{ test: /\.scss$/, use: ['to-string-loader', 'css-loader', 'sass-loader'] },
+ { test: /\.css$/, use: ['to-string-loader', 'css-loader'], include: /component\.css/ },
+ { test: /\.css$/, use: ['style-loader', 'css-loader'], exclude: /component\.css/ },
{ test: /\.yaml$/, use: ['json-loader', 'yaml-loader'] },
]
},
diff --git a/terminus-settings/package.json b/terminus-settings/package.json
index 1f545e54..361595cb 100644
--- a/terminus-settings/package.json
+++ b/terminus-settings/package.json
@@ -16,6 +16,7 @@
"@types/webpack-env": "1.13.0",
"awesome-typescript-loader": "3.1.2",
"css-loader": "^0.28.0",
+ "ng2-filter-pipe": "^0.1.7",
"node-sass": "^4.5.2",
"pug": "^2.0.0-beta3",
"pug-loader": "^2.3.0",
diff --git a/terminus-settings/src/components/settingsTab.pug b/terminus-settings/src/components/settingsTab.pug
index 03f205c0..bdb744b2 100644
--- a/terminus-settings/src/components/settingsTab.pug
+++ b/terminus-settings/src/components/settingsTab.pug
@@ -143,16 +143,21 @@ ngb-tabset.vertical(type='tabs')
template(ngbTabTitle)
| Hotkeys
template(ngbTabContent)
+ input.form-control(type='search', placeholder='Search hotkeys', [(ngModel)]='hotkeyFilter.name')
.form-group
- table
+ table.hotkeys-table
tr
- th Toggle terminal window
+ th Name
+ th ID
+ th Hotkey
+ tr(*ngFor='let hotkey of hotkeyDescriptions|filterBy:hotkeyFilter')
+ td {{hotkey.name}}
+ td {{hotkey.id}}
td
- hotkey-input('[(model)]'='globalHotkey')
- tr(*ngFor='let hotkey of hotkeyDescriptions')
- th {{hotkey.name}}
- td
- multi-hotkey-input('[(model)]'='config.store.hotkeys[hotkey.id]')
+ multi-hotkey-input(
+ '[(model)]'='config.store.hotkeys[hotkey.id]'
+ '(modelChange)'='config.save(); docking.dock()'
+ )
ngb-tab(*ngFor='let provider of settingsProviders')
template(ngbTabTitle)
diff --git a/terminus-settings/src/components/settingsTab.scss b/terminus-settings/src/components/settingsTab.scss
index 1fb34d22..9c75b481 100644
--- a/terminus-settings/src/components/settingsTab.scss
+++ b/terminus-settings/src/components/settingsTab.scss
@@ -9,7 +9,11 @@
flex: none;
}
- >.modal-body {
- padding: 0 0 20px !important;
+ .hotkeys-table {
+ margin-top: 30px;
+
+ td, th {
+ padding: 5px 10px;
+ }
}
}
diff --git a/terminus-settings/src/components/settingsTab.ts b/terminus-settings/src/components/settingsTab.ts
index c64991b0..665b6f67 100644
--- a/terminus-settings/src/components/settingsTab.ts
+++ b/terminus-settings/src/components/settingsTab.ts
@@ -13,7 +13,7 @@ import { SettingsTabProvider } from '../api'
],
})
export class SettingsTabComponent extends BaseTabComponent {
- globalHotkey = ['Ctrl+Shift+G']
+ hotkeyFilter = { name: null }
private hotkeyDescriptions: IHotkeyDescription[]
constructor(
diff --git a/terminus-settings/src/index.ts b/terminus-settings/src/index.ts
index 06e8ad01..83ba118e 100644
--- a/terminus-settings/src/index.ts
+++ b/terminus-settings/src/index.ts
@@ -2,6 +2,8 @@ import { NgModule } from '@angular/core'
import { BrowserModule } from '@angular/platform-browser'
import { FormsModule } from '@angular/forms'
import { NgbModule } from '@ng-bootstrap/ng-bootstrap'
+import { Ng2FilterPipeModule } from 'ng2-filter-pipe'
+
import { ToolbarButtonProvider, TabRecoveryProvider } from 'terminus-core'
import { HotkeyInputComponent } from './components/hotkeyInput'
@@ -20,6 +22,7 @@ import { RecoveryProvider } from './recoveryProvider'
BrowserModule,
FormsModule,
NgbModule,
+ Ng2FilterPipeModule,
],
providers: [
{ provide: ToolbarButtonProvider, useClass: ButtonProvider, multi: true },
diff --git a/terminus-terminal/src/buttonProvider.ts b/terminus-terminal/src/buttonProvider.ts
index 5f67f44e..cbb0bcf2 100644
--- a/terminus-terminal/src/buttonProvider.ts
+++ b/terminus-terminal/src/buttonProvider.ts
@@ -1,5 +1,5 @@
import { Injectable } from '@angular/core'
-import { HotkeysService, ToolbarButtonProvider, IToolbarButton, AppService, HostAppService, Platform } from 'terminus-core'
+import { HotkeysService, ToolbarButtonProvider, IToolbarButton, AppService, ConfigService } from 'terminus-core'
import { SessionsService } from './services/sessions'
import { TerminalTabComponent } from './components/terminalTab'
@@ -10,7 +10,7 @@ export class ButtonProvider extends ToolbarButtonProvider {
constructor (
private app: AppService,
private sessions: SessionsService,
- private hostApp: HostAppService,
+ private config: ConfigService,
hotkeys: HotkeysService,
) {
super()
@@ -26,11 +26,7 @@ export class ButtonProvider extends ToolbarButtonProvider {
if (this.app.activeTab instanceof TerminalTabComponent) {
cwd = await this.app.activeTab.session.getWorkingDirectory()
}
- let command = {
- [Platform.macOS]: 'zsh',
- [Platform.Linux]: 'zsh',
- [Platform.Windows]: 'cmd.exe',
- }[this.hostApp.platform]
+ let command = this.config.store.terminal.shell
this.app.openNewTab(
TerminalTabComponent,
{ session: await this.sessions.createNewSession({ command, cwd }) }
diff --git a/terminus-terminal/src/components/terminalSettingsTab.pug b/terminus-terminal/src/components/terminalSettingsTab.pug
index a8fc6abf..1ae23c40 100644
--- a/terminus-terminal/src/components/terminalSettingsTab.pug
+++ b/terminus-terminal/src/components/terminalSettingsTab.pug
@@ -194,6 +194,15 @@
[value]='"colorScheme"'
)
| From the terminal colors
+
+ .form-group
+ label Shell
+ input.form-control(
+ type='text',
+ [ngbTypeahead]='shellAutocomplete',
+ '[(ngModel)]'='config.store.terminal.shell',
+ (ngModelChange)='config.save()',
+ )
.form-group
label Terminal bell
diff --git a/terminus-terminal/src/components/terminalSettingsTab.ts b/terminus-terminal/src/components/terminalSettingsTab.ts
index a4c67211..0f67157e 100644
--- a/terminus-terminal/src/components/terminalSettingsTab.ts
+++ b/terminus-terminal/src/components/terminalSettingsTab.ts
@@ -2,13 +2,14 @@ import { Observable } from 'rxjs/Observable'
import 'rxjs/add/operator/map'
import 'rxjs/add/operator/debounceTime'
import 'rxjs/add/operator/distinctUntilChanged'
+import * as fs from 'fs-promise'
const fontManager = require('font-manager')
const equal = require('deep-equal')
+const { exec } = require('child-process-promise')
import { Component, Inject } from '@angular/core'
import { ConfigService, HostAppService, Platform } from 'terminus-core'
import { TerminalColorSchemeProvider, ITerminalColorScheme } from '../api'
-const { exec } = require('child-process-promise')
@Component({
@@ -17,6 +18,7 @@ const { exec } = require('child-process-promise')
})
export class TerminalSettingsTabComponent {
fonts: string[] = []
+ shells: string[] = []
colorSchemes: ITerminalColorScheme[] = []
equalComparator = equal
editingColorScheme: ITerminalColorScheme
@@ -43,6 +45,11 @@ export class TerminalSettingsTabComponent {
.map(x => x.split(',')[0].trim())
this.fonts.sort()
})
+
+ this.shells = (await fs.readFile('/etc/shells', 'utf-8'))
+ .split('\n')
+ .map(x => x.trim())
+ .filter(x => x && !x.startsWith('#'))
}
this.colorSchemes = (await Promise.all(this.colorSchemeProviders.map(x => x.getSchemes()))).reduce((a, b) => a.concat(b))
}
@@ -55,6 +62,10 @@ export class TerminalSettingsTabComponent {
.map(list => Array.from(new Set(list)))
}
+ shellAutocomplete = (text$: Observable) => {
+ return text$.map(_ => ['auto'].concat(this.shells))
+ }
+
editScheme (scheme: ITerminalColorScheme) {
this.editingColorScheme = scheme
this.schemeChanged = false
diff --git a/terminus-terminal/src/config.ts b/terminus-terminal/src/config.ts
index 8476d009..ccb7464e 100644
--- a/terminus-terminal/src/config.ts
+++ b/terminus-terminal/src/config.ts
@@ -9,7 +9,9 @@ export class TerminalConfigProvider extends ConfigProvider {
bell: 'off',
bracketedPaste: true,
background: 'theme',
+ shell: 'auto',
colorScheme: {
+ __nonStructural: true,
foreground: null,
background: null,
cursor: null,