mirror of
https://github.com/Eugeny/tabby.git
synced 2025-07-23 11:58:01 +00:00
This commit is contained in:
@@ -23,6 +23,7 @@ export class ProfilesService {
|
|||||||
weight: 0,
|
weight: 0,
|
||||||
isBuiltin: false,
|
isBuiltin: false,
|
||||||
isTemplate: false,
|
isTemplate: false,
|
||||||
|
terminalColorScheme: null,
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor (
|
constructor (
|
||||||
|
@@ -4,13 +4,13 @@ export abstract class LinkHandler {
|
|||||||
regex: RegExp
|
regex: RegExp
|
||||||
priority = 1
|
priority = 1
|
||||||
|
|
||||||
convert (uri: string, _tab?: BaseTerminalTabComponent): Promise<string>|string {
|
convert (uri: string, _tab?: BaseTerminalTabComponent<any>): Promise<string>|string {
|
||||||
return uri
|
return uri
|
||||||
}
|
}
|
||||||
|
|
||||||
verify (_uri: string, _tab?: BaseTerminalTabComponent): Promise<boolean>|boolean {
|
verify (_uri: string, _tab?: BaseTerminalTabComponent<any>): Promise<boolean>|boolean {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract handle (uri: string, tab?: BaseTerminalTabComponent): void
|
abstract handle (uri: string, tab?: BaseTerminalTabComponent<any>): void
|
||||||
}
|
}
|
||||||
|
@@ -14,7 +14,7 @@ export class LinkHighlighterDecorator extends TerminalDecorator {
|
|||||||
super()
|
super()
|
||||||
}
|
}
|
||||||
|
|
||||||
attach (tab: BaseTerminalTabComponent): void {
|
attach (tab: BaseTerminalTabComponent<any>): void {
|
||||||
if (!(tab.frontend instanceof XTermFrontend)) {
|
if (!(tab.frontend instanceof XTermFrontend)) {
|
||||||
// not xterm
|
// not xterm
|
||||||
return
|
return
|
||||||
|
@@ -65,7 +65,7 @@ export class BaseFileHandler extends LinkHandler {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async convert (uri: string, tab?: BaseTerminalTabComponent): Promise<string> {
|
async convert (uri: string, tab?: BaseTerminalTabComponent<any>): Promise<string> {
|
||||||
let p = untildify(uri)
|
let p = untildify(uri)
|
||||||
if (!path.isAbsolute(p) && tab) {
|
if (!path.isAbsolute(p) && tab) {
|
||||||
const cwd = await tab.session?.getWorkingDirectory()
|
const cwd = await tab.session?.getWorkingDirectory()
|
||||||
@@ -102,7 +102,7 @@ export class WindowsFileHandler extends BaseFileHandler {
|
|||||||
super(toastr, platform)
|
super(toastr, platform)
|
||||||
}
|
}
|
||||||
|
|
||||||
convert (uri: string, tab?: BaseTerminalTabComponent): Promise<string> {
|
convert (uri: string, tab?: BaseTerminalTabComponent<any>): Promise<string> {
|
||||||
const sanitizedUri = uri.replace(/"/g, '')
|
const sanitizedUri = uri.replace(/"/g, '')
|
||||||
return super.convert(sanitizedUri, tab)
|
return super.convert(sanitizedUri, tab)
|
||||||
}
|
}
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
import { Profile } from 'tabby-core'
|
import { BaseTerminalProfile } from 'tabby-terminal'
|
||||||
|
|
||||||
export interface Shell {
|
export interface Shell {
|
||||||
id: string
|
id: string
|
||||||
@@ -44,7 +44,7 @@ export interface SessionOptions {
|
|||||||
runAsAdministrator?: boolean
|
runAsAdministrator?: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface LocalProfile extends Profile {
|
export interface LocalProfile extends BaseTerminalProfile {
|
||||||
options: SessionOptions
|
options: SessionOptions
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -13,9 +13,8 @@ import { UACService } from '../services/uac.service'
|
|||||||
styles: BaseTerminalTabComponent.styles,
|
styles: BaseTerminalTabComponent.styles,
|
||||||
animations: BaseTerminalTabComponent.animations,
|
animations: BaseTerminalTabComponent.animations,
|
||||||
})
|
})
|
||||||
export class TerminalTabComponent extends BaseTerminalTabComponent {
|
export class TerminalTabComponent extends BaseTerminalTabComponent<LocalProfile> {
|
||||||
@Input() sessionOptions: SessionOptions // Deprecated
|
@Input() sessionOptions: SessionOptions // Deprecated
|
||||||
@Input() profile: LocalProfile
|
|
||||||
session: Session|null = null
|
session: Session|null = null
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-useless-constructor
|
// eslint-disable-next-line @typescript-eslint/no-useless-constructor
|
||||||
|
@@ -30,7 +30,7 @@ export class TerminalService {
|
|||||||
* Launches a new terminal with a specific shell and CWD
|
* Launches a new terminal with a specific shell and CWD
|
||||||
* @param pause Wait for a keypress when the shell exits
|
* @param pause Wait for a keypress when the shell exits
|
||||||
*/
|
*/
|
||||||
async openTab (profile?: PartialProfile<LocalProfile>|null, cwd?: string|null, pause?: boolean): Promise<TerminalTabComponent> {
|
async openTab (profile?: PartialProfile<LocalProfile>|null, cwd?: string|null, pause?: boolean): Promise<TerminalTabComponent|null> {
|
||||||
if (!profile) {
|
if (!profile) {
|
||||||
profile = await this.getDefaultProfile()
|
profile = await this.getDefaultProfile()
|
||||||
}
|
}
|
||||||
@@ -55,6 +55,6 @@ export class TerminalService {
|
|||||||
return (await this.profilesService.openNewTabForProfile({
|
return (await this.profilesService.openNewTabForProfile({
|
||||||
...fullProfile,
|
...fullProfile,
|
||||||
options,
|
options,
|
||||||
})) as TerminalTabComponent
|
})) as TerminalTabComponent|null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -22,6 +22,7 @@ export class SaveAsProfileContextMenu extends TabContextMenuItemProvider {
|
|||||||
if (!(tab instanceof TerminalTabComponent)) {
|
if (!(tab instanceof TerminalTabComponent)) {
|
||||||
return []
|
return []
|
||||||
}
|
}
|
||||||
|
const terminalTab = tab
|
||||||
const items: MenuItemOptions[] = [
|
const items: MenuItemOptions[] = [
|
||||||
{
|
{
|
||||||
label: this.translate.instant('Save as profile'),
|
label: this.translate.instant('Save as profile'),
|
||||||
@@ -34,8 +35,8 @@ export class SaveAsProfileContextMenu extends TabContextMenuItemProvider {
|
|||||||
}
|
}
|
||||||
const profile = {
|
const profile = {
|
||||||
options: {
|
options: {
|
||||||
...tab.profile.options,
|
...terminalTab.profile.options,
|
||||||
cwd: await tab.session?.getWorkingDirectory() ?? tab.profile.options.cwd,
|
cwd: await terminalTab.session?.getWorkingDirectory() ?? terminalTab.profile.options.cwd,
|
||||||
},
|
},
|
||||||
name,
|
name,
|
||||||
type: 'local',
|
type: 'local',
|
||||||
@@ -117,13 +118,14 @@ export class NewTabContextMenu extends TabContextMenuItemProvider {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (tab instanceof TerminalTabComponent && tabHeader && this.uac.isAvailable) {
|
if (tab instanceof TerminalTabComponent && tabHeader && this.uac.isAvailable) {
|
||||||
|
const terminalTab = tab
|
||||||
items.push({
|
items.push({
|
||||||
label: this.translate.instant('Duplicate as administrator'),
|
label: this.translate.instant('Duplicate as administrator'),
|
||||||
click: () => {
|
click: () => {
|
||||||
this.profilesService.openNewTabForProfile({
|
this.profilesService.openNewTabForProfile({
|
||||||
...tab.profile,
|
...terminalTab.profile,
|
||||||
options: {
|
options: {
|
||||||
...tab.profile.options,
|
...terminalTab.profile.options,
|
||||||
runAsAdministrator: true,
|
runAsAdministrator: true,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
@@ -1,12 +1,12 @@
|
|||||||
import stripAnsi from 'strip-ansi'
|
import stripAnsi from 'strip-ansi'
|
||||||
import { SerialPortStream } from '@serialport/stream'
|
import { SerialPortStream } from '@serialport/stream'
|
||||||
import { LogService, NotificationsService, Profile } from 'tabby-core'
|
import { LogService, NotificationsService } from 'tabby-core'
|
||||||
import { Subject, Observable } from 'rxjs'
|
import { Subject, Observable } from 'rxjs'
|
||||||
import { Injector, NgZone } from '@angular/core'
|
import { Injector, NgZone } from '@angular/core'
|
||||||
import { BaseSession, LoginScriptsOptions, SessionMiddleware, StreamProcessingOptions, TerminalStreamProcessor } from 'tabby-terminal'
|
import { BaseSession, BaseTerminalProfile, LoginScriptsOptions, SessionMiddleware, StreamProcessingOptions, TerminalStreamProcessor } from 'tabby-terminal'
|
||||||
import { SerialService } from './services/serial.service'
|
import { SerialService } from './services/serial.service'
|
||||||
|
|
||||||
export interface SerialProfile extends Profile {
|
export interface SerialProfile extends BaseTerminalProfile {
|
||||||
options: SerialProfileOptions
|
options: SerialProfileOptions
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -14,8 +14,7 @@ import { SerialSession, BAUD_RATES, SerialProfile } from '../api'
|
|||||||
styles: [require('./serialTab.component.scss'), ...BaseTerminalTabComponent.styles],
|
styles: [require('./serialTab.component.scss'), ...BaseTerminalTabComponent.styles],
|
||||||
animations: BaseTerminalTabComponent.animations,
|
animations: BaseTerminalTabComponent.animations,
|
||||||
})
|
})
|
||||||
export class SerialTabComponent extends BaseTerminalTabComponent {
|
export class SerialTabComponent extends BaseTerminalTabComponent<SerialProfile> {
|
||||||
profile?: SerialProfile
|
|
||||||
session: SerialSession|null = null
|
session: SerialSession|null = null
|
||||||
serialPort: any
|
serialPort: any
|
||||||
Platform = Platform
|
Platform = Platform
|
||||||
@@ -56,16 +55,11 @@ export class SerialTabComponent extends BaseTerminalTabComponent {
|
|||||||
super.ngOnInit()
|
super.ngOnInit()
|
||||||
|
|
||||||
setImmediate(() => {
|
setImmediate(() => {
|
||||||
this.setTitle(this.profile!.name)
|
this.setTitle(this.profile.name)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
async initializeSession () {
|
async initializeSession () {
|
||||||
if (!this.profile) {
|
|
||||||
this.logger.error('No serial profile info supplied')
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
const session = new SerialSession(this.injector, this.profile)
|
const session = new SerialSession(this.injector, this.profile)
|
||||||
this.setSession(session)
|
this.setSession(session)
|
||||||
|
|
||||||
@@ -121,6 +115,6 @@ export class SerialTabComponent extends BaseTerminalTabComponent {
|
|||||||
})),
|
})),
|
||||||
)
|
)
|
||||||
this.serialPort.update({ baudRate: rate })
|
this.serialPort.update({ baudRate: rate })
|
||||||
this.profile!.options.baudrate = rate
|
this.profile.options.baudrate = rate
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,5 +1,4 @@
|
|||||||
import { Profile } from 'tabby-core'
|
import { BaseTerminalProfile, LoginScriptsOptions } from 'tabby-terminal'
|
||||||
import { LoginScriptsOptions } from 'tabby-terminal'
|
|
||||||
|
|
||||||
export enum SSHAlgorithmType {
|
export enum SSHAlgorithmType {
|
||||||
HMAC = 'hmac',
|
HMAC = 'hmac',
|
||||||
@@ -8,7 +7,7 @@ export enum SSHAlgorithmType {
|
|||||||
HOSTKEY = 'serverHostKey',
|
HOSTKEY = 'serverHostKey',
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface SSHProfile extends Profile {
|
export interface SSHProfile extends BaseTerminalProfile {
|
||||||
options: SSHProfileOptions
|
options: SSHProfileOptions
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -248,6 +248,11 @@ ul.nav-tabs(ngbNav, #nav='ngbNav')
|
|||||||
div(*ngFor='let alg of supportedAlgorithms.serverHostKey')
|
div(*ngFor='let alg of supportedAlgorithms.serverHostKey')
|
||||||
checkbox([text]='alg', [(ngModel)]='algorithms.serverHostKey[alg]')
|
checkbox([text]='alg', [(ngModel)]='algorithms.serverHostKey[alg]')
|
||||||
|
|
||||||
|
li(ngbNavItem)
|
||||||
|
a(ngbNavLink, translate) Color scheme
|
||||||
|
ng-template(ngbNavContent)
|
||||||
|
color-scheme-selector([(model)]='profile.terminalColorScheme')
|
||||||
|
|
||||||
li(ngbNavItem)
|
li(ngbNavItem)
|
||||||
a(ngbNavLink, translate) Login scripts
|
a(ngbNavLink, translate) Login scripts
|
||||||
ng-template(ngbNavContent)
|
ng-template(ngbNavContent)
|
||||||
|
@@ -19,9 +19,8 @@ import { SSHMultiplexerService } from '../services/sshMultiplexer.service'
|
|||||||
styles: [require('./sshTab.component.scss'), ...BaseTerminalTabComponent.styles],
|
styles: [require('./sshTab.component.scss'), ...BaseTerminalTabComponent.styles],
|
||||||
animations: BaseTerminalTabComponent.animations,
|
animations: BaseTerminalTabComponent.animations,
|
||||||
})
|
})
|
||||||
export class SSHTabComponent extends BaseTerminalTabComponent {
|
export class SSHTabComponent extends BaseTerminalTabComponent<SSHProfile> {
|
||||||
Platform = Platform
|
Platform = Platform
|
||||||
profile?: SSHProfile
|
|
||||||
sshSession: SSHSession|null = null
|
sshSession: SSHSession|null = null
|
||||||
session: SSHShellSession|null = null
|
session: SSHShellSession|null = null
|
||||||
sftpPanelVisible = false
|
sftpPanelVisible = false
|
||||||
@@ -45,10 +44,6 @@ export class SSHTabComponent extends BaseTerminalTabComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ngOnInit (): void {
|
ngOnInit (): void {
|
||||||
if (!this.profile) {
|
|
||||||
throw new Error('Profile not set')
|
|
||||||
}
|
|
||||||
|
|
||||||
this.logger = this.log.create('terminalTab')
|
this.logger = this.log.create('terminalTab')
|
||||||
|
|
||||||
this.subscribeUntilDestroyed(this.hotkeys.hotkey$, hotkey => {
|
this.subscribeUntilDestroyed(this.hotkeys.hotkey$, hotkey => {
|
||||||
@@ -184,10 +179,6 @@ export class SSHTabComponent extends BaseTerminalTabComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private async initializeSessionMaybeMultiplex (multiplex = true): Promise<void> {
|
private async initializeSessionMaybeMultiplex (multiplex = true): Promise<void> {
|
||||||
if (!this.profile) {
|
|
||||||
throw new Error('No SSH connection info supplied')
|
|
||||||
}
|
|
||||||
|
|
||||||
this.sshSession = await this.setupOneSession(this.injector, this.profile, multiplex)
|
this.sshSession = await this.setupOneSession(this.injector, this.profile, multiplex)
|
||||||
const session = new SSHShellSession(this.injector, this.sshSession, this.profile)
|
const session = new SSHShellSession(this.injector, this.sshSession, this.profile)
|
||||||
|
|
||||||
@@ -244,13 +235,13 @@ export class SSHTabComponent extends BaseTerminalTabComponent {
|
|||||||
if (!this.session?.open) {
|
if (!this.session?.open) {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
if (!(this.profile?.options.warnOnClose ?? this.config.store.ssh.warnOnClose)) {
|
if (!(this.profile.options.warnOnClose ?? this.config.store.ssh.warnOnClose)) {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
return (await this.platform.showMessageBox(
|
return (await this.platform.showMessageBox(
|
||||||
{
|
{
|
||||||
type: 'warning',
|
type: 'warning',
|
||||||
message: this.translate.instant(_('Disconnect from {host}?'), this.profile?.options),
|
message: this.translate.instant(_('Disconnect from {host}?'), this.profile.options),
|
||||||
buttons: [
|
buttons: [
|
||||||
this.translate.instant(_('Disconnect')),
|
this.translate.instant(_('Disconnect')),
|
||||||
this.translate.instant(_('Do not close')),
|
this.translate.instant(_('Do not close')),
|
||||||
|
@@ -18,7 +18,7 @@ export class SFTPContextMenu extends TabContextMenuItemProvider {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async getItems (tab: BaseTabComponent): Promise<MenuItemOptions[]> {
|
async getItems (tab: BaseTabComponent): Promise<MenuItemOptions[]> {
|
||||||
if (!(tab instanceof SSHTabComponent) || !tab.profile) {
|
if (!(tab instanceof SSHTabComponent)) {
|
||||||
return []
|
return []
|
||||||
}
|
}
|
||||||
const items = [{
|
const items = [{
|
||||||
|
@@ -14,9 +14,8 @@ import { TelnetProfile, TelnetSession } from '../session'
|
|||||||
styles: [require('./telnetTab.component.scss'), ...BaseTerminalTabComponent.styles],
|
styles: [require('./telnetTab.component.scss'), ...BaseTerminalTabComponent.styles],
|
||||||
animations: BaseTerminalTabComponent.animations,
|
animations: BaseTerminalTabComponent.animations,
|
||||||
})
|
})
|
||||||
export class TelnetTabComponent extends BaseTerminalTabComponent {
|
export class TelnetTabComponent extends BaseTerminalTabComponent<TelnetProfile> {
|
||||||
Platform = Platform
|
Platform = Platform
|
||||||
profile?: TelnetProfile
|
|
||||||
session: TelnetSession|null = null
|
session: TelnetSession|null = null
|
||||||
private reconnectOffered = false
|
private reconnectOffered = false
|
||||||
|
|
||||||
@@ -29,10 +28,6 @@ export class TelnetTabComponent extends BaseTerminalTabComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ngOnInit (): void {
|
ngOnInit (): void {
|
||||||
if (!this.profile) {
|
|
||||||
throw new Error('Profile not set')
|
|
||||||
}
|
|
||||||
|
|
||||||
this.logger = this.log.create('telnetTab')
|
this.logger = this.log.create('telnetTab')
|
||||||
|
|
||||||
this.subscribeUntilDestroyed(this.hotkeys.hotkey$, hotkey => {
|
this.subscribeUntilDestroyed(this.hotkeys.hotkey$, hotkey => {
|
||||||
@@ -69,10 +64,6 @@ export class TelnetTabComponent extends BaseTerminalTabComponent {
|
|||||||
|
|
||||||
async initializeSession (): Promise<void> {
|
async initializeSession (): Promise<void> {
|
||||||
this.reconnectOffered = false
|
this.reconnectOffered = false
|
||||||
if (!this.profile) {
|
|
||||||
this.logger.error('No Telnet connection info supplied')
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
const session = new TelnetSession(this.injector, this.profile)
|
const session = new TelnetSession(this.injector, this.profile)
|
||||||
this.setSession(session)
|
this.setSession(session)
|
||||||
@@ -119,7 +110,7 @@ export class TelnetTabComponent extends BaseTerminalTabComponent {
|
|||||||
return (await this.platform.showMessageBox(
|
return (await this.platform.showMessageBox(
|
||||||
{
|
{
|
||||||
type: 'warning',
|
type: 'warning',
|
||||||
message: this.translate.instant(_('Disconnect from {host}?'), this.profile?.options),
|
message: this.translate.instant(_('Disconnect from {host}?'), this.profile.options),
|
||||||
buttons: [
|
buttons: [
|
||||||
this.translate.instant(_('Disconnect')),
|
this.translate.instant(_('Disconnect')),
|
||||||
this.translate.instant(_('Do not close')),
|
this.translate.instant(_('Do not close')),
|
||||||
|
@@ -2,12 +2,12 @@ import { Socket } from 'net'
|
|||||||
import colors from 'ansi-colors'
|
import colors from 'ansi-colors'
|
||||||
import stripAnsi from 'strip-ansi'
|
import stripAnsi from 'strip-ansi'
|
||||||
import { Injector } from '@angular/core'
|
import { Injector } from '@angular/core'
|
||||||
import { Profile, LogService } from 'tabby-core'
|
import { LogService } from 'tabby-core'
|
||||||
import { BaseSession, LoginScriptsOptions, SessionMiddleware, StreamProcessingOptions, TerminalStreamProcessor } from 'tabby-terminal'
|
import { BaseSession, BaseTerminalProfile, LoginScriptsOptions, SessionMiddleware, StreamProcessingOptions, TerminalStreamProcessor } from 'tabby-terminal'
|
||||||
import { Subject, Observable } from 'rxjs'
|
import { Subject, Observable } from 'rxjs'
|
||||||
|
|
||||||
|
|
||||||
export interface TelnetProfile extends Profile {
|
export interface TelnetProfile extends BaseTerminalProfile {
|
||||||
options: TelnetProfileOptions
|
options: TelnetProfileOptions
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "tabby-terminal",
|
"name": "tabby-terminal",
|
||||||
"version": "1.0.189-nightly.0",
|
"version": "1.0.189-nightly.2",
|
||||||
"description": "Tabby's terminal emulation core",
|
"description": "Tabby's terminal emulation core",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"tabby-builtin-plugin"
|
"tabby-builtin-plugin"
|
||||||
|
@@ -9,7 +9,7 @@ import { BaseSession } from '../session'
|
|||||||
|
|
||||||
import { Frontend } from '../frontends/frontend'
|
import { Frontend } from '../frontends/frontend'
|
||||||
import { XTermFrontend, XTermWebGLFrontend } from '../frontends/xtermFrontend'
|
import { XTermFrontend, XTermWebGLFrontend } from '../frontends/xtermFrontend'
|
||||||
import { ResizeEvent } from './interfaces'
|
import { ResizeEvent, BaseTerminalProfile } from './interfaces'
|
||||||
import { TerminalDecorator } from './decorator'
|
import { TerminalDecorator } from './decorator'
|
||||||
import { SearchPanelComponent } from '../components/searchPanel.component'
|
import { SearchPanelComponent } from '../components/searchPanel.component'
|
||||||
import { MultifocusService } from '../services/multifocus.service'
|
import { MultifocusService } from '../services/multifocus.service'
|
||||||
@@ -17,7 +17,7 @@ import { MultifocusService } from '../services/multifocus.service'
|
|||||||
/**
|
/**
|
||||||
* A class to base your custom terminal tabs on
|
* A class to base your custom terminal tabs on
|
||||||
*/
|
*/
|
||||||
export class BaseTerminalTabComponent extends BaseTabComponent implements OnInit, OnDestroy {
|
export class BaseTerminalTabComponent<P extends BaseTerminalProfile> extends BaseTabComponent implements OnInit, OnDestroy {
|
||||||
static template: string = require<string>('../components/baseTerminalTab.component.pug')
|
static template: string = require<string>('../components/baseTerminalTab.component.pug')
|
||||||
static styles: string[] = [require<string>('../components/baseTerminalTab.component.scss')]
|
static styles: string[] = [require<string>('../components/baseTerminalTab.component.scss')]
|
||||||
static animations: AnimationTriggerMetadata[] = [
|
static animations: AnimationTriggerMetadata[] = [
|
||||||
@@ -90,6 +90,8 @@ export class BaseTerminalTabComponent extends BaseTabComponent implements OnInit
|
|||||||
frontendReady = new Subject<void>()
|
frontendReady = new Subject<void>()
|
||||||
size: ResizeEvent
|
size: ResizeEvent
|
||||||
|
|
||||||
|
profile: P
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Enables normall passthrough from session output to terminal input
|
* Enables normall passthrough from session output to terminal input
|
||||||
*/
|
*/
|
||||||
@@ -356,12 +358,12 @@ export class BaseTerminalTabComponent extends BaseTabComponent implements OnInit
|
|||||||
|
|
||||||
setImmediate(async () => {
|
setImmediate(async () => {
|
||||||
if (this.hasFocus) {
|
if (this.hasFocus) {
|
||||||
await this.frontend?.attach(this.content.nativeElement)
|
await this.frontend?.attach(this.content.nativeElement, this.profile)
|
||||||
this.frontend?.configure()
|
this.frontend?.configure(this.profile)
|
||||||
} else {
|
} else {
|
||||||
this.focused$.pipe(first()).subscribe(async () => {
|
this.focused$.pipe(first()).subscribe(async () => {
|
||||||
await this.frontend?.attach(this.content.nativeElement)
|
await this.frontend?.attach(this.content.nativeElement, this.profile)
|
||||||
this.frontend?.configure()
|
this.frontend?.configure(this.profile)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@@ -508,11 +510,12 @@ export class BaseTerminalTabComponent extends BaseTabComponent implements OnInit
|
|||||||
* Applies the user settings to the terminal
|
* Applies the user settings to the terminal
|
||||||
*/
|
*/
|
||||||
configure (): void {
|
configure (): void {
|
||||||
this.frontend?.configure()
|
this.frontend?.configure(this.profile)
|
||||||
|
|
||||||
if (this.config.store.terminal.background === 'colorScheme') {
|
if (this.config.store.terminal.background === 'colorScheme') {
|
||||||
if (this.config.store.terminal.colorScheme.background) {
|
const scheme = this.profile.terminalColorScheme ?? this.config.store.terminal.colorScheme
|
||||||
this.backgroundColor = this.config.store.terminal.colorScheme.background
|
if (scheme.background) {
|
||||||
|
this.backgroundColor = scheme.background
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
this.backgroundColor = null
|
this.backgroundColor = null
|
||||||
@@ -809,7 +812,7 @@ export class BaseTerminalTabComponent extends BaseTabComponent implements OnInit
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected forEachFocusedTerminalPane (cb: (tab: BaseTerminalTabComponent) => void): void {
|
protected forEachFocusedTerminalPane (cb: (tab: BaseTerminalTabComponent<any>) => void): void {
|
||||||
if (this.parent && this.parent instanceof SplitTabComponent && this.parent._allFocusMode) {
|
if (this.parent && this.parent instanceof SplitTabComponent && this.parent._allFocusMode) {
|
||||||
for (const tab of this.parent.getAllTabs()) {
|
for (const tab of this.parent.getAllTabs()) {
|
||||||
if (tab instanceof BaseTerminalTabComponent) {
|
if (tab instanceof BaseTerminalTabComponent) {
|
||||||
|
@@ -8,5 +8,5 @@ import { BaseTerminalTabComponent } from './baseTerminalTab.component'
|
|||||||
export abstract class TerminalContextMenuItemProvider {
|
export abstract class TerminalContextMenuItemProvider {
|
||||||
weight: number
|
weight: number
|
||||||
|
|
||||||
abstract getItems (tab: BaseTerminalTabComponent): Promise<MenuItemOptions[]>
|
abstract getItems (tab: BaseTerminalTabComponent<any>): Promise<MenuItemOptions[]>
|
||||||
}
|
}
|
||||||
|
@@ -5,18 +5,18 @@ import { BaseTerminalTabComponent } from './baseTerminalTab.component'
|
|||||||
* Extend to automatically run actions on new terminals
|
* Extend to automatically run actions on new terminals
|
||||||
*/
|
*/
|
||||||
export abstract class TerminalDecorator {
|
export abstract class TerminalDecorator {
|
||||||
private smartSubscriptions = new Map<BaseTerminalTabComponent, Subscription[]>()
|
private smartSubscriptions = new Map<BaseTerminalTabComponent<any>, Subscription[]>()
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called when a new terminal tab starts
|
* Called when a new terminal tab starts
|
||||||
*/
|
*/
|
||||||
attach (terminal: BaseTerminalTabComponent): void { } // eslint-disable-line
|
attach (terminal: BaseTerminalTabComponent<any>): void { } // eslint-disable-line
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called before a terminal tab is destroyed.
|
* Called before a terminal tab is destroyed.
|
||||||
* Make sure to call super()
|
* Make sure to call super()
|
||||||
*/
|
*/
|
||||||
detach (terminal: BaseTerminalTabComponent): void {
|
detach (terminal: BaseTerminalTabComponent<any>): void {
|
||||||
for (const s of this.smartSubscriptions.get(terminal) ?? []) {
|
for (const s of this.smartSubscriptions.get(terminal) ?? []) {
|
||||||
s.unsubscribe()
|
s.unsubscribe()
|
||||||
}
|
}
|
||||||
@@ -26,7 +26,7 @@ export abstract class TerminalDecorator {
|
|||||||
/**
|
/**
|
||||||
* Automatically cancel @subscription once detached from @terminal
|
* Automatically cancel @subscription once detached from @terminal
|
||||||
*/
|
*/
|
||||||
protected subscribeUntilDetached (terminal: BaseTerminalTabComponent, subscription?: Subscription): void {
|
protected subscribeUntilDetached (terminal: BaseTerminalTabComponent<any>, subscription?: Subscription): void {
|
||||||
if (!subscription) {
|
if (!subscription) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@@ -1,3 +1,5 @@
|
|||||||
|
import { Profile } from 'tabby-core'
|
||||||
|
|
||||||
export interface ResizeEvent {
|
export interface ResizeEvent {
|
||||||
columns: number
|
columns: number
|
||||||
rows: number
|
rows: number
|
||||||
@@ -11,4 +13,9 @@ export interface TerminalColorScheme {
|
|||||||
colors: string[]
|
colors: string[]
|
||||||
selection?: string
|
selection?: string
|
||||||
selectionForeground?: string
|
selectionForeground?: string
|
||||||
|
cursorAccent?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface BaseTerminalProfile extends Profile {
|
||||||
|
terminalColorScheme?: TerminalColorScheme
|
||||||
}
|
}
|
||||||
|
@@ -0,0 +1,31 @@
|
|||||||
|
.head
|
||||||
|
.bg-dark.p-3.mb-4(*ngIf='model')
|
||||||
|
.d-flex.align-items-center
|
||||||
|
span {{model.name}}
|
||||||
|
.mr-auto
|
||||||
|
a.btn-link((click)='selectScheme(null); $event.preventDefault()', href='#', translate) Clear
|
||||||
|
|
||||||
|
color-scheme-preview([scheme]='model')
|
||||||
|
|
||||||
|
.input-group.mb-3
|
||||||
|
.input-group-prepend
|
||||||
|
.input-group-text
|
||||||
|
i.fas.fa-fw.fa-search
|
||||||
|
input.form-control(type='search', [placeholder]='"Search color schemes"|translate', [(ngModel)]='filter')
|
||||||
|
|
||||||
|
.body
|
||||||
|
.list-group-light.mb-3
|
||||||
|
ng-container(*ngFor='let scheme of allColorSchemes')
|
||||||
|
.list-group-item.list-group-item-action(
|
||||||
|
[hidden]='filter && !scheme.name.toLowerCase().includes(filter.toLowerCase())',
|
||||||
|
(click)='selectScheme(scheme)',
|
||||||
|
[class.active]='(currentCustomScheme || currentStockScheme) === scheme'
|
||||||
|
)
|
||||||
|
.d-flex.w-100.align-items-center
|
||||||
|
i.fas.fa-fw([class.fa-check]='model?.name === scheme.name')
|
||||||
|
|
||||||
|
.ml-2
|
||||||
|
|
||||||
|
.mr-auto {{scheme.name}}
|
||||||
|
|
||||||
|
color-scheme-preview([scheme]='scheme')
|
@@ -0,0 +1,53 @@
|
|||||||
|
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
|
||||||
|
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker'
|
||||||
|
|
||||||
|
import { Component, Inject, Input, ChangeDetectionStrategy, ChangeDetectorRef, HostBinding, Output, EventEmitter } from '@angular/core'
|
||||||
|
import { ConfigService } from 'tabby-core'
|
||||||
|
import { TerminalColorSchemeProvider } from '../api/colorSchemeProvider'
|
||||||
|
import { TerminalColorScheme } from '../api/interfaces'
|
||||||
|
|
||||||
|
_('Search color schemes')
|
||||||
|
|
||||||
|
/** @hidden */
|
||||||
|
@Component({
|
||||||
|
selector: 'color-scheme-selector',
|
||||||
|
template: require('./colorSchemeSelector.component.pug'),
|
||||||
|
styles: [`
|
||||||
|
:host {
|
||||||
|
display: block;
|
||||||
|
max-height: 100vh;
|
||||||
|
overflow-y: auto;
|
||||||
|
}
|
||||||
|
`],
|
||||||
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||||
|
})
|
||||||
|
export class ColorSchemeSelectorComponent {
|
||||||
|
allColorSchemes: TerminalColorScheme[] = []
|
||||||
|
filter = ''
|
||||||
|
|
||||||
|
@Input() model: TerminalColorScheme|null = null
|
||||||
|
@Output() modelChange = new EventEmitter<TerminalColorScheme|null>()
|
||||||
|
|
||||||
|
@HostBinding('class.content-box') true
|
||||||
|
|
||||||
|
constructor (
|
||||||
|
@Inject(TerminalColorSchemeProvider) private colorSchemeProviders: TerminalColorSchemeProvider[],
|
||||||
|
private changeDetector: ChangeDetectorRef,
|
||||||
|
public config: ConfigService,
|
||||||
|
) { }
|
||||||
|
|
||||||
|
async ngOnInit () {
|
||||||
|
const stockColorSchemes = (await Promise.all(this.config.enabledServices(this.colorSchemeProviders).map(x => x.getSchemes()))).reduce((a, b) => a.concat(b))
|
||||||
|
stockColorSchemes.sort((a, b) => a.name.localeCompare(b.name))
|
||||||
|
const customColorSchemes = this.config.store.terminal.customColorSchemes
|
||||||
|
|
||||||
|
this.allColorSchemes = customColorSchemes.concat(stockColorSchemes)
|
||||||
|
this.changeDetector.markForCheck()
|
||||||
|
}
|
||||||
|
|
||||||
|
selectScheme (scheme: TerminalColorScheme) {
|
||||||
|
this.model = scheme
|
||||||
|
this.modelChange.emit(scheme)
|
||||||
|
this.changeDetector.markForCheck()
|
||||||
|
}
|
||||||
|
}
|
@@ -10,7 +10,7 @@ import { BaseTerminalTabComponent } from '../api/baseTerminalTab.component'
|
|||||||
styles: [require('./terminalToolbar.component.scss')],
|
styles: [require('./terminalToolbar.component.scss')],
|
||||||
})
|
})
|
||||||
export class TerminalToolbarComponent {
|
export class TerminalToolbarComponent {
|
||||||
@Input() tab: BaseTerminalTabComponent
|
@Input() tab: BaseTerminalTabComponent<any>
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-useless-constructor
|
// eslint-disable-next-line @typescript-eslint/no-useless-constructor
|
||||||
constructor (
|
constructor (
|
||||||
|
@@ -12,7 +12,7 @@ export class DebugDecorator extends TerminalDecorator {
|
|||||||
super()
|
super()
|
||||||
}
|
}
|
||||||
|
|
||||||
attach (terminal: BaseTerminalTabComponent): void {
|
attach (terminal: BaseTerminalTabComponent<any>): void {
|
||||||
let sessionOutputBuffer = ''
|
let sessionOutputBuffer = ''
|
||||||
const bufferLength = 8192
|
const bufferLength = 8192
|
||||||
|
|
||||||
@@ -83,23 +83,23 @@ export class DebugDecorator extends TerminalDecorator {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private doSaveState (terminal: BaseTerminalTabComponent) {
|
private doSaveState (terminal: BaseTerminalTabComponent<any>) {
|
||||||
this.saveFile(terminal.frontend!.saveState(), 'state.txt')
|
this.saveFile(terminal.frontend!.saveState(), 'state.txt')
|
||||||
}
|
}
|
||||||
|
|
||||||
private async doCopyState (terminal: BaseTerminalTabComponent) {
|
private async doCopyState (terminal: BaseTerminalTabComponent<any>) {
|
||||||
const data = '```' + JSON.stringify(terminal.frontend!.saveState()) + '```'
|
const data = '```' + JSON.stringify(terminal.frontend!.saveState()) + '```'
|
||||||
this.platform.setClipboard({ text: data })
|
this.platform.setClipboard({ text: data })
|
||||||
}
|
}
|
||||||
|
|
||||||
private async doLoadState (terminal: BaseTerminalTabComponent) {
|
private async doLoadState (terminal: BaseTerminalTabComponent<any>) {
|
||||||
const data = await this.loadFile()
|
const data = await this.loadFile()
|
||||||
if (data) {
|
if (data) {
|
||||||
terminal.frontend!.restoreState(data)
|
terminal.frontend!.restoreState(data)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async doPasteState (terminal: BaseTerminalTabComponent) {
|
private async doPasteState (terminal: BaseTerminalTabComponent<any>) {
|
||||||
let data = this.platform.readClipboard()
|
let data = this.platform.readClipboard()
|
||||||
if (data) {
|
if (data) {
|
||||||
if (data.startsWith('`')) {
|
if (data.startsWith('`')) {
|
||||||
@@ -118,14 +118,14 @@ export class DebugDecorator extends TerminalDecorator {
|
|||||||
this.platform.setClipboard({ text: data })
|
this.platform.setClipboard({ text: data })
|
||||||
}
|
}
|
||||||
|
|
||||||
private async doLoadOutput (terminal: BaseTerminalTabComponent) {
|
private async doLoadOutput (terminal: BaseTerminalTabComponent<any>) {
|
||||||
const data = await this.loadFile()
|
const data = await this.loadFile()
|
||||||
if (data) {
|
if (data) {
|
||||||
await terminal.frontend?.write(data)
|
await terminal.frontend?.write(data)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async doPasteOutput (terminal: BaseTerminalTabComponent) {
|
private async doPasteOutput (terminal: BaseTerminalTabComponent<any>) {
|
||||||
let data = this.platform.readClipboard()
|
let data = this.platform.readClipboard()
|
||||||
if (data) {
|
if (data) {
|
||||||
if (data.startsWith('`')) {
|
if (data.startsWith('`')) {
|
||||||
|
@@ -5,7 +5,7 @@ import { BaseTerminalTabComponent } from '../api/baseTerminalTab.component'
|
|||||||
/** @hidden */
|
/** @hidden */
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class PathDropDecorator extends TerminalDecorator {
|
export class PathDropDecorator extends TerminalDecorator {
|
||||||
attach (terminal: BaseTerminalTabComponent): void {
|
attach (terminal: BaseTerminalTabComponent<any>): void {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
this.subscribeUntilDetached(terminal, terminal.frontend?.dragOver$.subscribe(event => {
|
this.subscribeUntilDetached(terminal, terminal.frontend?.dragOver$.subscribe(event => {
|
||||||
event.preventDefault()
|
event.preventDefault()
|
||||||
@@ -19,7 +19,7 @@ export class PathDropDecorator extends TerminalDecorator {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
private injectPath (terminal: BaseTerminalTabComponent, path: string) {
|
private injectPath (terminal: BaseTerminalTabComponent<any>, path: string) {
|
||||||
if (path.includes(' ')) {
|
if (path.includes(' ')) {
|
||||||
path = `"${path}"`
|
path = `"${path}"`
|
||||||
}
|
}
|
||||||
|
@@ -220,7 +220,7 @@ export class ZModemDecorator extends TerminalDecorator {
|
|||||||
super()
|
super()
|
||||||
}
|
}
|
||||||
|
|
||||||
attach (terminal: BaseTerminalTabComponent): void {
|
attach (terminal: BaseTerminalTabComponent<any>): void {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
this.attachToSession(terminal)
|
this.attachToSession(terminal)
|
||||||
this.subscribeUntilDetached(terminal, terminal.sessionChanged$.subscribe(() => {
|
this.subscribeUntilDetached(terminal, terminal.sessionChanged$.subscribe(() => {
|
||||||
@@ -229,7 +229,7 @@ export class ZModemDecorator extends TerminalDecorator {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
private attachToSession (terminal: BaseTerminalTabComponent) {
|
private attachToSession (terminal: BaseTerminalTabComponent<any>) {
|
||||||
if (!terminal.session) {
|
if (!terminal.session) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
import { Injector } from '@angular/core'
|
import { Injector } from '@angular/core'
|
||||||
import { Observable, Subject, AsyncSubject, ReplaySubject, BehaviorSubject } from 'rxjs'
|
import { Observable, Subject, AsyncSubject, ReplaySubject, BehaviorSubject } from 'rxjs'
|
||||||
import { ResizeEvent } from '../api/interfaces'
|
import { BaseTerminalProfile, ResizeEvent } from '../api/interfaces'
|
||||||
|
|
||||||
export interface SearchOptions {
|
export interface SearchOptions {
|
||||||
regex?: boolean
|
regex?: boolean
|
||||||
@@ -64,7 +64,7 @@ export abstract class Frontend {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract attach (host: HTMLElement): Promise<void>
|
abstract attach (host: HTMLElement, profile: BaseTerminalProfile): Promise<void>
|
||||||
detach (host: HTMLElement): void { } // eslint-disable-line
|
detach (host: HTMLElement): void { } // eslint-disable-line
|
||||||
|
|
||||||
abstract getSelection (): string
|
abstract getSelection (): string
|
||||||
@@ -80,7 +80,7 @@ export abstract class Frontend {
|
|||||||
abstract scrollPages (pages: number): void
|
abstract scrollPages (pages: number): void
|
||||||
abstract scrollToBottom (): void
|
abstract scrollToBottom (): void
|
||||||
|
|
||||||
abstract configure (): void
|
abstract configure (profile: BaseTerminalProfile): void
|
||||||
abstract setZoom (zoom: number): void
|
abstract setZoom (zoom: number): void
|
||||||
|
|
||||||
abstract findNext (term: string, searchOptions?: SearchOptions): SearchState
|
abstract findNext (term: string, searchOptions?: SearchOptions): SearchState
|
||||||
|
@@ -16,6 +16,7 @@ import deepEqual from 'deep-equal'
|
|||||||
import { Attributes } from 'xterm/src/common/buffer/Constants'
|
import { Attributes } from 'xterm/src/common/buffer/Constants'
|
||||||
import { AttributeData } from 'xterm/src/common/buffer/AttributeData'
|
import { AttributeData } from 'xterm/src/common/buffer/AttributeData'
|
||||||
import { CellData } from 'xterm/src/common/buffer/CellData'
|
import { CellData } from 'xterm/src/common/buffer/CellData'
|
||||||
|
import { BaseTerminalProfile, TerminalColorScheme } from '../api/interfaces'
|
||||||
|
|
||||||
const COLOR_NAMES = [
|
const COLOR_NAMES = [
|
||||||
'black', 'red', 'green', 'yellow', 'blue', 'magenta', 'cyan', 'white',
|
'black', 'red', 'green', 'yellow', 'blue', 'magenta', 'cyan', 'white',
|
||||||
@@ -214,7 +215,7 @@ export class XTermFrontend extends Frontend {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
async attach (host: HTMLElement): Promise<void> {
|
async attach (host: HTMLElement, profile: BaseTerminalProfile): Promise<void> {
|
||||||
this.element = host
|
this.element = host
|
||||||
|
|
||||||
this.xterm.open(host)
|
this.xterm.open(host)
|
||||||
@@ -224,7 +225,7 @@ export class XTermFrontend extends Frontend {
|
|||||||
await new Promise(resolve => setTimeout(resolve, this.hostApp.platform === Platform.Web ? 1000 : 0))
|
await new Promise(resolve => setTimeout(resolve, this.hostApp.platform === Platform.Web ? 1000 : 0))
|
||||||
|
|
||||||
// Just configure the colors to avoid a flash
|
// Just configure the colors to avoid a flash
|
||||||
this.configureColors()
|
this.configureColors(profile.terminalColorScheme)
|
||||||
|
|
||||||
if (this.enableWebGL) {
|
if (this.enableWebGL) {
|
||||||
this.webGLAddon = new WebglAddon()
|
this.webGLAddon = new WebglAddon()
|
||||||
@@ -353,20 +354,22 @@ export class XTermFrontend extends Frontend {
|
|||||||
this.xtermCore._scrollToBottom()
|
this.xtermCore._scrollToBottom()
|
||||||
}
|
}
|
||||||
|
|
||||||
private configureColors () {
|
private configureColors (scheme: TerminalColorScheme|undefined): void {
|
||||||
const config = this.configService.store
|
const config = this.configService.store
|
||||||
|
|
||||||
|
scheme = scheme ?? config.terminal.colorScheme
|
||||||
|
|
||||||
const theme: ITheme = {
|
const theme: ITheme = {
|
||||||
foreground: config.terminal.colorScheme.foreground,
|
foreground: scheme!.foreground,
|
||||||
selectionBackground: config.terminal.colorScheme.selection || '#88888888',
|
selectionBackground: scheme!.selection ?? '#88888888',
|
||||||
selectionForeground: config.terminal.colorScheme.selectionForeground || undefined,
|
selectionForeground: scheme!.selectionForeground ?? undefined,
|
||||||
background: config.terminal.background === 'colorScheme' ? config.terminal.colorScheme.background : '#00000000',
|
background: config.terminal.background === 'colorScheme' ? scheme!.background : '#00000000',
|
||||||
cursor: config.terminal.colorScheme.cursor,
|
cursor: scheme!.cursor,
|
||||||
cursorAccent: config.terminal.colorScheme.cursorAccent,
|
cursorAccent: scheme!.cursorAccent,
|
||||||
}
|
}
|
||||||
|
|
||||||
for (let i = 0; i < COLOR_NAMES.length; i++) {
|
for (let i = 0; i < COLOR_NAMES.length; i++) {
|
||||||
theme[COLOR_NAMES[i]] = config.terminal.colorScheme.colors[i]
|
theme[COLOR_NAMES[i]] = scheme!.colors[i]
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!deepEqual(this.configuredTheme, theme)) {
|
if (!deepEqual(this.configuredTheme, theme)) {
|
||||||
@@ -375,7 +378,7 @@ export class XTermFrontend extends Frontend {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
configure (): void {
|
configure (profile: BaseTerminalProfile): void {
|
||||||
const config = this.configService.store
|
const config = this.configService.store
|
||||||
|
|
||||||
setImmediate(() => {
|
setImmediate(() => {
|
||||||
@@ -408,7 +411,7 @@ export class XTermFrontend extends Frontend {
|
|||||||
|
|
||||||
this.copyOnSelect = config.terminal.copyOnSelect
|
this.copyOnSelect = config.terminal.copyOnSelect
|
||||||
|
|
||||||
this.configureColors()
|
this.configureColors(profile.terminalColorScheme)
|
||||||
|
|
||||||
if (this.opened && config.terminal.ligatures && !this.ligaturesAddon && this.hostApp.platform !== Platform.Web) {
|
if (this.opened && config.terminal.ligatures && !this.ligaturesAddon && this.hostApp.platform !== Platform.Web) {
|
||||||
this.ligaturesAddon = new LigaturesAddon()
|
this.ligaturesAddon = new LigaturesAddon()
|
||||||
|
@@ -17,6 +17,7 @@ import { SearchPanelComponent } from './components/searchPanel.component'
|
|||||||
import { StreamProcessingSettingsComponent } from './components/streamProcessingSettings.component'
|
import { StreamProcessingSettingsComponent } from './components/streamProcessingSettings.component'
|
||||||
import { LoginScriptsSettingsComponent } from './components/loginScriptsSettings.component'
|
import { LoginScriptsSettingsComponent } from './components/loginScriptsSettings.component'
|
||||||
import { TerminalToolbarComponent } from './components/terminalToolbar.component'
|
import { TerminalToolbarComponent } from './components/terminalToolbar.component'
|
||||||
|
import { ColorSchemeSelectorComponent } from './components/colorSchemeSelector.component'
|
||||||
|
|
||||||
import { TerminalDecorator } from './api/decorator'
|
import { TerminalDecorator } from './api/decorator'
|
||||||
import { TerminalContextMenuItemProvider } from './api/contextMenuProvider'
|
import { TerminalContextMenuItemProvider } from './api/contextMenuProvider'
|
||||||
@@ -64,10 +65,12 @@ import { TerminalCLIHandler } from './cli'
|
|||||||
AppearanceSettingsTabComponent,
|
AppearanceSettingsTabComponent,
|
||||||
ColorSchemeSettingsTabComponent,
|
ColorSchemeSettingsTabComponent,
|
||||||
TerminalSettingsTabComponent,
|
TerminalSettingsTabComponent,
|
||||||
|
ColorSchemeSelectorComponent,
|
||||||
],
|
],
|
||||||
declarations: [
|
declarations: [
|
||||||
ColorPickerComponent,
|
ColorPickerComponent,
|
||||||
ColorSchemePreviewComponent,
|
ColorSchemePreviewComponent,
|
||||||
|
ColorSchemeSelectorComponent,
|
||||||
AppearanceSettingsTabComponent,
|
AppearanceSettingsTabComponent,
|
||||||
ColorSchemeSettingsTabComponent,
|
ColorSchemeSettingsTabComponent,
|
||||||
TerminalSettingsTabComponent,
|
TerminalSettingsTabComponent,
|
||||||
@@ -78,6 +81,7 @@ import { TerminalCLIHandler } from './cli'
|
|||||||
],
|
],
|
||||||
exports: [
|
exports: [
|
||||||
ColorPickerComponent,
|
ColorPickerComponent,
|
||||||
|
ColorSchemeSelectorComponent,
|
||||||
SearchPanelComponent,
|
SearchPanelComponent,
|
||||||
StreamProcessingSettingsComponent,
|
StreamProcessingSettingsComponent,
|
||||||
LoginScriptsSettingsComponent,
|
LoginScriptsSettingsComponent,
|
||||||
|
@@ -6,7 +6,7 @@ import { SplitTabComponent, TranslateService, AppService, HotkeysService } from
|
|||||||
@Injectable({ providedIn: 'root' })
|
@Injectable({ providedIn: 'root' })
|
||||||
export class MultifocusService {
|
export class MultifocusService {
|
||||||
private inputSubscription: Subscription|null = null
|
private inputSubscription: Subscription|null = null
|
||||||
private currentTab: BaseTerminalTabComponent|null = null
|
private currentTab: BaseTerminalTabComponent<any>|null = null
|
||||||
private warningElement: HTMLElement
|
private warningElement: HTMLElement
|
||||||
|
|
||||||
constructor (
|
constructor (
|
||||||
@@ -32,7 +32,7 @@ export class MultifocusService {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
start (currentTab: BaseTerminalTabComponent, tabs: BaseTerminalTabComponent[]): void {
|
start (currentTab: BaseTerminalTabComponent<any>, tabs: BaseTerminalTabComponent<any>[]): void {
|
||||||
if (this.inputSubscription) {
|
if (this.inputSubscription) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -87,7 +87,7 @@ export class MultifocusService {
|
|||||||
} else {
|
} else {
|
||||||
return []
|
return []
|
||||||
}
|
}
|
||||||
}) as (_) => BaseTerminalTabComponent[])
|
}) as (_) => BaseTerminalTabComponent<any>[])
|
||||||
.flat()
|
.flat()
|
||||||
this.start(currentTab, tabs)
|
this.start(currentTab, tabs)
|
||||||
|
|
||||||
|
@@ -1,7 +1,10 @@
|
|||||||
import { Component, Injector } from '@angular/core'
|
import { Component, Injector } from '@angular/core'
|
||||||
import { BaseTerminalTabComponent } from 'tabby-terminal'
|
import { BaseTerminalProfile, BaseTerminalTabComponent } from 'tabby-terminal'
|
||||||
import { Session } from '../session'
|
import { Session } from '../session'
|
||||||
|
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-type-alias
|
||||||
|
type DemoProfile = BaseTerminalProfile
|
||||||
|
|
||||||
/** @hidden */
|
/** @hidden */
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'demoTerminalTab',
|
selector: 'demoTerminalTab',
|
||||||
@@ -9,7 +12,7 @@ import { Session } from '../session'
|
|||||||
styles: BaseTerminalTabComponent.styles,
|
styles: BaseTerminalTabComponent.styles,
|
||||||
animations: BaseTerminalTabComponent.animations,
|
animations: BaseTerminalTabComponent.animations,
|
||||||
})
|
})
|
||||||
export class DemoTerminalTabComponent extends BaseTerminalTabComponent {
|
export class DemoTerminalTabComponent extends BaseTerminalTabComponent<DemoProfile> {
|
||||||
session: Session|null = null
|
session: Session|null = null
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-useless-constructor
|
// eslint-disable-next-line @typescript-eslint/no-useless-constructor
|
||||||
|
Reference in New Issue
Block a user