mirror of
https://github.com/Eugeny/tabby.git
synced 2025-07-19 18:07:58 +00:00
moved login scripts processing into tabby-terminal
This commit is contained in:
@@ -1,22 +1,15 @@
|
||||
import stripAnsi from 'strip-ansi'
|
||||
import SerialPort from 'serialport'
|
||||
import { Logger, LogService, NotificationsService, Profile } from 'tabby-core'
|
||||
import { LogService, NotificationsService, Profile } from 'tabby-core'
|
||||
import { Subject, Observable } from 'rxjs'
|
||||
import { Injector, NgZone } from '@angular/core'
|
||||
import { BaseSession, StreamProcessingOptions, TerminalStreamProcessor } from 'tabby-terminal'
|
||||
|
||||
export interface LoginScript {
|
||||
expect: string
|
||||
send: string
|
||||
isRegex?: boolean
|
||||
optional?: boolean
|
||||
}
|
||||
import { BaseSession, LoginScriptsOptions, StreamProcessingOptions, TerminalStreamProcessor } from 'tabby-terminal'
|
||||
|
||||
export interface SerialProfile extends Profile {
|
||||
options: SerialProfileOptions
|
||||
}
|
||||
|
||||
export interface SerialProfileOptions extends StreamProcessingOptions {
|
||||
export interface SerialProfileOptions extends StreamProcessingOptions, LoginScriptsOptions {
|
||||
port: string
|
||||
baudrate?: number
|
||||
databits?: number
|
||||
@@ -26,7 +19,6 @@ export interface SerialProfileOptions extends StreamProcessingOptions {
|
||||
xon?: boolean
|
||||
xoff?: boolean
|
||||
xany?: boolean
|
||||
scripts?: LoginScript[]
|
||||
color?: string
|
||||
}
|
||||
|
||||
@@ -40,9 +32,7 @@ export interface SerialPortInfo {
|
||||
}
|
||||
|
||||
export class SerialSession extends BaseSession {
|
||||
scripts?: LoginScript[]
|
||||
serial: SerialPort
|
||||
logger: Logger
|
||||
|
||||
get serviceMessage$ (): Observable<string> { return this.serviceMessage }
|
||||
private serviceMessage = new Subject<string>()
|
||||
@@ -51,62 +41,20 @@ export class SerialSession extends BaseSession {
|
||||
private notifications: NotificationsService
|
||||
|
||||
constructor (injector: Injector, public profile: SerialProfile) {
|
||||
super()
|
||||
|
||||
this.logger = injector.get(LogService).create(`serial-${profile.options.port}`)
|
||||
super(injector.get(LogService).create(`serial-${profile.options.port}`))
|
||||
this.zone = injector.get(NgZone)
|
||||
this.notifications = injector.get(NotificationsService)
|
||||
|
||||
this.scripts = profile.options.scripts ?? []
|
||||
this.streamProcessor = new TerminalStreamProcessor(profile.options)
|
||||
this.streamProcessor.outputToSession$.subscribe(data => {
|
||||
this.serial?.write(data.toString())
|
||||
})
|
||||
this.streamProcessor.outputToTerminal$.subscribe(data => {
|
||||
this.emitOutput(data)
|
||||
|
||||
const dataString = data.toString()
|
||||
|
||||
if (this.scripts) {
|
||||
let found = false
|
||||
for (const script of this.scripts) {
|
||||
let match = false
|
||||
let cmd = ''
|
||||
if (script.isRegex) {
|
||||
const re = new RegExp(script.expect, 'g')
|
||||
if (re.test(dataString)) {
|
||||
cmd = dataString.replace(re, script.send)
|
||||
match = true
|
||||
found = true
|
||||
}
|
||||
} else {
|
||||
if (dataString.includes(script.expect)) {
|
||||
cmd = script.send
|
||||
match = true
|
||||
found = true
|
||||
}
|
||||
}
|
||||
|
||||
if (match) {
|
||||
this.logger.info('Executing script: "' + cmd + '"')
|
||||
this.serial.write(cmd + '\n')
|
||||
this.scripts = this.scripts.filter(x => x !== script)
|
||||
} else {
|
||||
if (script.optional) {
|
||||
this.logger.debug('Skip optional script: ' + script.expect)
|
||||
found = true
|
||||
this.scripts = this.scripts.filter(x => x !== script)
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (found) {
|
||||
this.executeUnconditionalScripts()
|
||||
}
|
||||
}
|
||||
this.loginScriptProcessor?.feedFromSession(data)
|
||||
})
|
||||
|
||||
this.setLoginScriptsOptions(profile.options)
|
||||
}
|
||||
|
||||
async start (): Promise<void> {
|
||||
@@ -151,6 +99,7 @@ export class SerialSession extends BaseSession {
|
||||
})
|
||||
|
||||
this.open = true
|
||||
setTimeout(() => this.streamProcessor.start())
|
||||
|
||||
this.serial.on('readable', () => {
|
||||
this.streamProcessor.feedFromSession(this.serial.read())
|
||||
@@ -163,7 +112,7 @@ export class SerialSession extends BaseSession {
|
||||
}
|
||||
})
|
||||
|
||||
this.executeUnconditionalScripts()
|
||||
this.loginScriptProcessor?.executeUnconditionalScripts()
|
||||
}
|
||||
|
||||
write (data: Buffer): void {
|
||||
@@ -205,18 +154,4 @@ export class SerialSession extends BaseSession {
|
||||
async getWorkingDirectory (): Promise<string|null> {
|
||||
return null
|
||||
}
|
||||
|
||||
private executeUnconditionalScripts () {
|
||||
if (this.scripts) {
|
||||
for (const script of this.scripts) {
|
||||
if (!script.expect) {
|
||||
console.log('Executing script:', script.send)
|
||||
this.serial.write(script.send + '\n')
|
||||
this.scripts = this.scripts.filter(x => x !== script)
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -80,43 +80,6 @@ ul.nav-tabs(ngbNav, #nav='ngbNav')
|
||||
li(ngbNavItem)
|
||||
a(ngbNavLink) Login scripts
|
||||
ng-template(ngbNavContent)
|
||||
table(*ngIf='profile.options.scripts.length > 0')
|
||||
tr
|
||||
th String to expect
|
||||
th String to be sent
|
||||
th.pl-2 Regex
|
||||
th.pl-2 Optional
|
||||
th.pl-2 Actions
|
||||
tr(*ngFor='let script of profile.options.scripts')
|
||||
td.pr-2
|
||||
input.form-control(
|
||||
type='text',
|
||||
[(ngModel)]='script.expect'
|
||||
)
|
||||
td
|
||||
input.form-control(
|
||||
type='text',
|
||||
[(ngModel)]='script.send'
|
||||
)
|
||||
td.pl-2
|
||||
checkbox(
|
||||
[(ngModel)]='script.isRegex',
|
||||
)
|
||||
td.pl-2
|
||||
checkbox(
|
||||
[(ngModel)]='script.optional',
|
||||
)
|
||||
td.pl-2
|
||||
.input-group.flex-nowrap
|
||||
button.btn.btn-outline-info.ml-0((click)='moveScriptUp(script)')
|
||||
i.fas.fa-arrow-up
|
||||
button.btn.btn-outline-info.ml-0((click)='moveScriptDown(script)')
|
||||
i.fas.fa-arrow-down
|
||||
button.btn.btn-outline-danger.ml-0((click)='deleteScript(script)')
|
||||
i.fas.fa-trash
|
||||
|
||||
button.btn.btn-outline-info.mt-2((click)='addScript()')
|
||||
i.fas.fa-plus
|
||||
span New item
|
||||
login-scripts-settings([options]='profile.options')
|
||||
|
||||
div([ngbNavOutlet]='nav')
|
||||
|
@@ -1,8 +1,8 @@
|
||||
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
|
||||
import { Component } from '@angular/core'
|
||||
import { debounceTime, distinctUntilChanged, map } from 'rxjs/operators'
|
||||
import { PlatformService, ProfileSettingsComponent } from 'tabby-core'
|
||||
import { LoginScript, SerialPortInfo, BAUD_RATES, SerialProfile } from '../api'
|
||||
import { ProfileSettingsComponent } from 'tabby-core'
|
||||
import { SerialPortInfo, BAUD_RATES, SerialProfile } from '../api'
|
||||
import { SerialService } from '../services/serial.service'
|
||||
|
||||
/** @hidden */
|
||||
@@ -14,7 +14,6 @@ export class SerialProfileSettingsComponent implements ProfileSettingsComponent
|
||||
foundPorts: SerialPortInfo[]
|
||||
|
||||
constructor (
|
||||
private platform: PlatformService,
|
||||
private serial: SerialService,
|
||||
) { }
|
||||
|
||||
@@ -40,50 +39,6 @@ export class SerialProfileSettingsComponent implements ProfileSettingsComponent
|
||||
}
|
||||
|
||||
async ngOnInit () {
|
||||
this.profile.options.scripts = this.profile.options.scripts ?? []
|
||||
this.foundPorts = await this.serial.listPorts()
|
||||
}
|
||||
|
||||
moveScriptUp (script: LoginScript) {
|
||||
if (!this.profile.options.scripts) {
|
||||
this.profile.options.scripts = []
|
||||
}
|
||||
const index = this.profile.options.scripts.indexOf(script)
|
||||
if (index > 0) {
|
||||
this.profile.options.scripts.splice(index, 1)
|
||||
this.profile.options.scripts.splice(index - 1, 0, script)
|
||||
}
|
||||
}
|
||||
|
||||
moveScriptDown (script: LoginScript) {
|
||||
if (!this.profile.options.scripts) {
|
||||
this.profile.options.scripts = []
|
||||
}
|
||||
const index = this.profile.options.scripts.indexOf(script)
|
||||
if (index >= 0 && index < this.profile.options.scripts.length - 1) {
|
||||
this.profile.options.scripts.splice(index, 1)
|
||||
this.profile.options.scripts.splice(index + 1, 0, script)
|
||||
}
|
||||
}
|
||||
|
||||
async deleteScript (script: LoginScript) {
|
||||
if (this.profile.options.scripts && (await this.platform.showMessageBox(
|
||||
{
|
||||
type: 'warning',
|
||||
message: 'Delete this script?',
|
||||
detail: script.expect,
|
||||
buttons: ['Keep', 'Delete'],
|
||||
defaultId: 1,
|
||||
}
|
||||
)).response === 1) {
|
||||
this.profile.options.scripts = this.profile.options.scripts.filter(x => x !== script)
|
||||
}
|
||||
}
|
||||
|
||||
addScript () {
|
||||
if (!this.profile.options.scripts) {
|
||||
this.profile.options.scripts = []
|
||||
}
|
||||
this.profile.options.scripts.push({ expect: '', send: '' })
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user