1
1
mirror of https://github.com/Eugeny/tabby.git synced 2024-10-26 12:43:50 +03:00
This commit is contained in:
Eugene Pankov 2017-04-05 10:50:02 +02:00
parent c894410fdb
commit 7a4806bcc9
6 changed files with 87 additions and 71 deletions

View File

@ -7,8 +7,6 @@ import { Inject, Injectable } from '@angular/core'
import { LinkHandler } from './api'
import { TerminalDecorator, TerminalTabComponent } from '../terminal/api'
const debounceDelay = 500
@Injectable()
export class LinkHighlighterDecorator extends TerminalDecorator {
@ -17,40 +15,11 @@ export class LinkHighlighterDecorator extends TerminalDecorator {
}
attach (terminal: TerminalTabComponent): void {
const Screen = terminal.hterm.screen_.constructor
if (Screen._linkHighlighterInstalled) {
return
}
Screen._linkHighlighterInstalled = true
const oldInsertString = Screen.prototype.insertString
const oldDeleteChars = Screen.prototype.deleteChars
let self = this
Screen.prototype.insertString = function (content) {
let ret = oldInsertString.bind(this)(content)
self.debounceInsertLinks(this)
return ret
}
Screen.prototype.deleteChars = function (count) {
let ret = oldDeleteChars.bind(this)(count)
self.debounceInsertLinks(this)
return ret
}
}
debounceInsertLinks (screen) {
if (screen.__insertLinksTimeout) {
screen.__insertLinksRebounce = true
} else {
screen.__insertLinksTimeout = window.setTimeout(() => {
this.insertLinks(screen)
screen.__insertLinksTimeout = null
if (screen.__insertLinksRebounce) {
screen.__insertLinksRebounce = false
this.debounceInsertLinks(screen)
}
}, debounceDelay)
}
terminal.contentUpdated$
.debounceTime(1000)
.subscribe(() => {
this.insertLinks(terminal.hterm.screen_)
})
}
insertLinks (screen) {

View File

@ -19,12 +19,14 @@ export class TerminalTabComponent extends BaseTabComponent<TerminalTab> {
hterm: any
configSubscription: Subscription
focusedSubscription: Subscription
startupTime: number
title$ = new BehaviorSubject('')
size$ = new ReplaySubject<ResizeEvent>(1)
input$ = new Subject<string>()
output$ = new Subject<string>()
contentUpdated$ = new Subject<void>()
alternateScreenActive$ = new BehaviorSubject(false)
mouseEvent$ = new Subject<Event>()
private io: any
constructor(
private zone: NgZone,
@ -33,7 +35,6 @@ export class TerminalTabComponent extends BaseTabComponent<TerminalTab> {
@Inject(TerminalDecorator) private decorators: TerminalDecorator[],
) {
super()
this.startupTime = performance.now()
this.configSubscription = config.change.subscribe(() => {
this.configure()
})
@ -53,18 +54,13 @@ export class TerminalTabComponent extends BaseTabComponent<TerminalTab> {
this.hterm.onTerminalReady = () => {
this.hterm.installKeyboard()
let io = this.hterm.io.push()
this.attachIOHandlers(io)
this.io = this.hterm.io.push()
this.attachIOHandlers(this.io)
const dataSubscription = this.model.session.dataAvailable.subscribe((data) => {
if (performance.now() - this.startupTime > 500) {
this.zone.run(() => {
this.model.displayActivity()
})
}
this.zone.run(() => {
this.output$.next(data)
})
io.writeUTF8(data)
this.write(data)
})
const closedSubscription = this.model.session.closed.subscribe(() => {
dataSubscription.unsubscribe()
@ -75,6 +71,12 @@ export class TerminalTabComponent extends BaseTabComponent<TerminalTab> {
}
this.hterm.decorate(this.elementRef.nativeElement)
this.configure()
setTimeout(() => {
this.output$.subscribe(() => {
this.model.displayActivity()
})
}, 1000)
}
attachHTermHandlers (hterm: any) {
@ -85,23 +87,54 @@ export class TerminalTabComponent extends BaseTabComponent<TerminalTab> {
})
}
const oldInsertString = hterm.screen_.insertString.bind(hterm.screen_)
hterm.screen_.insertString = (data) => {
oldInsertString(data)
this.contentUpdated$.next()
const _decorate = hterm.scrollPort_.decorate.bind(hterm.scrollPort_)
hterm.scrollPort_.decorate = (...args) => {
_decorate(...args)
hterm.scrollPort_.screen_.style.cssText += `; padding-right: ${hterm.scrollPort_.screen_.offsetWidth - hterm.scrollPort_.screen_.clientWidth}px;`
}
const oldDeleteChars = hterm.screen_.deleteChars.bind(hterm.screen_)
hterm.screen_.deleteChars = (count) => {
let ret = oldDeleteChars(count)
this.contentUpdated$.next()
return ret
const _setAlternateMode = hterm.setAlternateMode.bind(hterm)
hterm.setAlternateMode = (state) => {
_setAlternateMode(state)
this.alternateScreenActive$.next(state)
}
const _onPaste_ = hterm.onPaste_.bind(hterm)
hterm.onPaste_ = (event) => {
event.text = event.text.trim()
_onPaste_(event)
}
const _onMouse_ = hterm.onMouse_.bind(hterm)
hterm.onMouse_ = (event) => {
this.mouseEvent$.next(event)
if ((event.ctrlKey || event.metaKey) && event.type === 'mousewheel') {
event.preventDefault()
let delta = Math.round(event.wheelDeltaY / 50)
this.sendInput(((delta > 0) ? '\u001bOA' : '\u001bOB').repeat(Math.abs(delta)))
}
_onMouse_(event)
}
for (let screen of [hterm.primaryScreen_, hterm.alternateScreen_]) {
const _insertString = screen.insertString.bind(screen)
screen.insertString = (data) => {
_insertString(data)
this.contentUpdated$.next()
}
const _deleteChars = screen.deleteChars.bind(screen)
screen.deleteChars = (count) => {
let ret = _deleteChars(count)
this.contentUpdated$.next()
return ret
}
}
}
attachIOHandlers (io: any) {
io.onVTKeystroke = io.sendString = (data) => {
this.model.session.write(data)
this.sendInput(data)
this.zone.run(() => {
this.input$.next(data)
})
@ -115,6 +148,14 @@ export class TerminalTabComponent extends BaseTabComponent<TerminalTab> {
}
}
sendInput (data: string) {
this.model.session.write(data)
}
write (data: string) {
this.io.writeUTF8(data)
}
configure () {
let config = this.config.full()
preferenceManager.set('font-family', config.terminal.font)
@ -133,5 +174,12 @@ export class TerminalTabComponent extends BaseTabComponent<TerminalTab> {
})
this.focusedSubscription.unsubscribe()
this.configSubscription.unsubscribe()
this.title$.complete()
this.size$.complete()
this.input$.complete()
this.output$.complete()
this.contentUpdated$.complete()
this.alternateScreenActive$.complete()
this.mouseEvent$.complete()
}
}

View File

@ -27,16 +27,4 @@ preferenceManager.set('color-palette-overrides', {
0: '#1D272D',
})
const oldDecorate = hterm.hterm.ScrollPort.prototype.decorate
hterm.hterm.ScrollPort.prototype.decorate = function (...args) {
oldDecorate.bind(this)(...args)
this.screen_.style.cssText += `; padding-right: ${this.screen_.offsetWidth - this.screen_.clientWidth}px;`
}
const oldPaste = hterm.hterm.Terminal.prototype.onPaste_
hterm.hterm.Terminal.prototype.onPaste_ = function (e) {
e.text = e.text.trim()
oldPaste.bind(this)(e)
}
hterm.hterm.Terminal.prototype.showOverlay = () => null

View File

@ -30,6 +30,7 @@ import { hterm } from './hterm'
{ provide: TabRecoveryProvider, useClass: RecoveryProvider, multi: true },
SessionsService,
{ provide: SessionPersistenceProvider, useClass: ScreenPersistenceProvider },
// { provide: SessionPersistenceProvider, useValue: null },
{ provide: SettingsTabProvider, useClass: TerminalSettingsProvider, multi: true },
{ provide: ConfigProvider, useClass: TerminalConfigProvider, multi: true },
],

View File

@ -47,9 +47,12 @@ export class ScreenPersistenceProvider extends SessionPersistenceProvider {
term xterm-color
bindkey "^[OH" beginning-of-line
bindkey "^[OF" end-of-line
bindkey "\\027[?1049h" stuff ----alternate enter-----
bindkey "\\027[?1049l" stuff ----alternate leave-----
termcapinfo xterm* 'hs:ts=\\E]0;:fs=\\007:ds=\\E]0;\\007'
defhstatus "^Et"
hardstatus off
altscreen on
`, 'utf-8')
let recoveryId = `term-tab-${Date.now()}`
let args = ['-d', '-m', '-c', configPath, '-U', '-S', recoveryId, '--', options.command].concat(options.args || [])

View File

@ -130,8 +130,10 @@ export class SessionsService {
}
async createNewSession (options: SessionOptions) : Promise<Session> {
let recoveryId = await this.persistence.startSession(options)
options = await this.persistence.attachSession(recoveryId)
if (this.persistence) {
let recoveryId = await this.persistence.startSession(options)
options = await this.persistence.attachSession(recoveryId)
}
let session = this.addSession(options)
return session
}
@ -142,7 +144,9 @@ export class SessionsService {
let session = new Session(options)
const destroySubscription = session.destroyed.subscribe(() => {
delete this.sessions[session.name]
this.persistence.terminateSession(session.recoveryId)
if (this.persistence) {
this.persistence.terminateSession(session.recoveryId)
}
destroySubscription.unsubscribe()
})
this.sessions[session.name] = session
@ -150,6 +154,9 @@ export class SessionsService {
}
async recover (recoveryId: string) : Promise<Session> {
if (!this.persistence) {
return null
}
const options = await this.persistence.attachSession(recoveryId)
if (!options) {
return null