mirror of
https://github.com/Eugeny/tabby.git
synced 2025-06-22 12:29:53 +00:00
.
This commit is contained in:
parent
2846637815
commit
c894410fdb
@ -5,7 +5,7 @@
|
||||
|
||||
import { Inject, Injectable } from '@angular/core'
|
||||
import { LinkHandler } from './api'
|
||||
import { TerminalDecorator } from '../terminal/api'
|
||||
import { TerminalDecorator, TerminalTabComponent } from '../terminal/api'
|
||||
|
||||
const debounceDelay = 500
|
||||
|
||||
@ -16,8 +16,8 @@ export class LinkHighlighterDecorator extends TerminalDecorator {
|
||||
super()
|
||||
}
|
||||
|
||||
decorate (terminal): void {
|
||||
const Screen = terminal.screen_.constructor
|
||||
attach (terminal: TerminalTabComponent): void {
|
||||
const Screen = terminal.hterm.screen_.constructor
|
||||
if (Screen._linkHighlighterInstalled) {
|
||||
return
|
||||
}
|
||||
@ -26,13 +26,13 @@ export class LinkHighlighterDecorator extends TerminalDecorator {
|
||||
const oldInsertString = Screen.prototype.insertString
|
||||
const oldDeleteChars = Screen.prototype.deleteChars
|
||||
let self = this
|
||||
Screen.prototype.insertString = function (...args) {
|
||||
let ret = oldInsertString.bind(this)(...args)
|
||||
Screen.prototype.insertString = function (content) {
|
||||
let ret = oldInsertString.bind(this)(content)
|
||||
self.debounceInsertLinks(this)
|
||||
return ret
|
||||
}
|
||||
Screen.prototype.deleteChars = function (...args) {
|
||||
let ret = oldDeleteChars.bind(this)(...args)
|
||||
Screen.prototype.deleteChars = function (count) {
|
||||
let ret = oldDeleteChars.bind(this)(count)
|
||||
self.debounceInsertLinks(this)
|
||||
return ret
|
||||
}
|
||||
|
@ -1,4 +1,5 @@
|
||||
import * as fs from 'fs'
|
||||
const untildify = require('untildify')
|
||||
|
||||
import { Injectable } from '@angular/core'
|
||||
import { LinkHandler } from './api'
|
||||
@ -20,12 +21,16 @@ export class URLHandler extends LinkHandler {
|
||||
|
||||
@Injectable()
|
||||
export class FileHandler extends LinkHandler {
|
||||
regex = '/[^\\s.,;\'"]+'
|
||||
regex = '[~/][^\\s.,;\'"]+'
|
||||
|
||||
constructor (private electron: ElectronService) {
|
||||
super()
|
||||
}
|
||||
|
||||
convert (uri: string): string {
|
||||
return untildify(uri)
|
||||
}
|
||||
|
||||
verify (uri: string) {
|
||||
return fs.existsSync(uri)
|
||||
}
|
||||
|
@ -1,13 +1,22 @@
|
||||
import { TerminalTabComponent } from './components/terminalTab'
|
||||
export { TerminalTabComponent } from './components/terminalTab'
|
||||
|
||||
export abstract class TerminalDecorator {
|
||||
abstract decorate (terminal): void
|
||||
attach (_terminal: TerminalTabComponent): void { }
|
||||
detach (_terminal: TerminalTabComponent): void { }
|
||||
}
|
||||
|
||||
export interface ResizeEvent {
|
||||
width: number
|
||||
height: number
|
||||
}
|
||||
|
||||
export interface SessionOptions {
|
||||
name?: string,
|
||||
command?: string,
|
||||
args?: string[],
|
||||
cwd?: string,
|
||||
env?: any,
|
||||
name?: string
|
||||
command?: string
|
||||
args?: string[]
|
||||
cwd?: string
|
||||
env?: any
|
||||
recoveryId?: string
|
||||
recoveredTruePID?: number
|
||||
}
|
||||
|
@ -1,11 +1,11 @@
|
||||
import { BehaviorSubject, Subscription } from 'rxjs'
|
||||
import { BehaviorSubject, ReplaySubject, Subject, Subscription } from 'rxjs'
|
||||
import { Component, NgZone, Inject, ElementRef } from '@angular/core'
|
||||
|
||||
import { ConfigService } from 'services/config'
|
||||
|
||||
import { BaseTabComponent } from 'components/baseTab'
|
||||
import { TerminalTab } from '../tab'
|
||||
import { TerminalDecorator } from '../api'
|
||||
import { TerminalDecorator, ResizeEvent } from '../api'
|
||||
|
||||
import { hterm, preferenceManager } from '../hterm'
|
||||
|
||||
@ -16,11 +16,15 @@ import { hterm, preferenceManager } from '../hterm'
|
||||
styles: [require('./terminalTab.scss')],
|
||||
})
|
||||
export class TerminalTabComponent extends BaseTabComponent<TerminalTab> {
|
||||
terminal: any
|
||||
title$ = new BehaviorSubject('')
|
||||
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>()
|
||||
|
||||
constructor(
|
||||
private zone: NgZone,
|
||||
@ -37,27 +41,29 @@ export class TerminalTabComponent extends BaseTabComponent<TerminalTab> {
|
||||
|
||||
initTab () {
|
||||
this.focusedSubscription = this.model.focused.subscribe(() => {
|
||||
this.terminal.scrollPort_.focus()
|
||||
this.hterm.scrollPort_.focus()
|
||||
})
|
||||
|
||||
this.terminal = new hterm.hterm.Terminal()
|
||||
this.hterm = new hterm.hterm.Terminal()
|
||||
this.decorators.forEach((decorator) => {
|
||||
decorator.decorate(this.terminal)
|
||||
decorator.attach(this)
|
||||
})
|
||||
this.terminal.setWindowTitle = (title) => {
|
||||
this.zone.run(() => {
|
||||
this.model.title = title
|
||||
})
|
||||
}
|
||||
this.terminal.onTerminalReady = () => {
|
||||
this.terminal.installKeyboard()
|
||||
let io = this.terminal.io.push()
|
||||
|
||||
this.attachHTermHandlers(this.hterm)
|
||||
|
||||
this.hterm.onTerminalReady = () => {
|
||||
this.hterm.installKeyboard()
|
||||
let io = this.hterm.io.push()
|
||||
this.attachIOHandlers(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)
|
||||
})
|
||||
const closedSubscription = this.model.session.closed.subscribe(() => {
|
||||
@ -65,20 +71,50 @@ export class TerminalTabComponent extends BaseTabComponent<TerminalTab> {
|
||||
closedSubscription.unsubscribe()
|
||||
})
|
||||
|
||||
io.onVTKeystroke = io.sendString = (str) => {
|
||||
this.model.session.write(str)
|
||||
}
|
||||
io.onTerminalResize = (columns, rows) => {
|
||||
console.log(`Resizing to ${columns}x${rows}`)
|
||||
this.model.session.resize(columns, rows)
|
||||
}
|
||||
|
||||
this.model.session.releaseInitialDataBuffer()
|
||||
}
|
||||
this.terminal.decorate(this.elementRef.nativeElement)
|
||||
this.hterm.decorate(this.elementRef.nativeElement)
|
||||
this.configure()
|
||||
}
|
||||
|
||||
attachHTermHandlers (hterm: any) {
|
||||
hterm.setWindowTitle = (title) => {
|
||||
this.zone.run(() => {
|
||||
this.model.title = title
|
||||
this.title$.next(title)
|
||||
})
|
||||
}
|
||||
|
||||
const oldInsertString = hterm.screen_.insertString.bind(hterm.screen_)
|
||||
hterm.screen_.insertString = (data) => {
|
||||
oldInsertString(data)
|
||||
this.contentUpdated$.next()
|
||||
}
|
||||
|
||||
const oldDeleteChars = hterm.screen_.deleteChars.bind(hterm.screen_)
|
||||
hterm.screen_.deleteChars = (count) => {
|
||||
let ret = oldDeleteChars(count)
|
||||
this.contentUpdated$.next()
|
||||
return ret
|
||||
}
|
||||
}
|
||||
|
||||
attachIOHandlers (io: any) {
|
||||
io.onVTKeystroke = io.sendString = (data) => {
|
||||
this.model.session.write(data)
|
||||
this.zone.run(() => {
|
||||
this.input$.next(data)
|
||||
})
|
||||
}
|
||||
io.onTerminalResize = (columns, rows) => {
|
||||
// console.log(`Resizing to ${columns}x${rows}`)
|
||||
this.zone.run(() => {
|
||||
this.model.session.resize(columns, rows)
|
||||
this.size$.next({ width: columns, height: rows })
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
configure () {
|
||||
let config = this.config.full()
|
||||
preferenceManager.set('font-family', config.terminal.font)
|
||||
@ -88,9 +124,13 @@ export class TerminalTabComponent extends BaseTabComponent<TerminalTab> {
|
||||
preferenceManager.set('enable-clipboard-notice', false)
|
||||
preferenceManager.set('receive-encoding', 'raw')
|
||||
preferenceManager.set('send-encoding', 'raw')
|
||||
this.hterm.setBracketedPaste(config.terminal.bracketedPaste)
|
||||
}
|
||||
|
||||
ngOnDestroy () {
|
||||
this.decorators.forEach((decorator) => {
|
||||
decorator.detach(this)
|
||||
})
|
||||
this.focusedSubscription.unsubscribe()
|
||||
this.configSubscription.unsubscribe()
|
||||
}
|
||||
|
@ -7,6 +7,7 @@ export class TerminalConfigProvider extends ConfigProvider {
|
||||
font: 'monospace',
|
||||
fontSize: 14,
|
||||
bell: 'off',
|
||||
bracketedPaste: true,
|
||||
},
|
||||
hotkeys: {
|
||||
'new-tab': [
|
||||
|
@ -33,4 +33,10 @@ hterm.hterm.ScrollPort.prototype.decorate = function (...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
|
||||
|
@ -120,11 +120,13 @@ app-root .content {
|
||||
}
|
||||
|
||||
&.has-activity:not(.active) {
|
||||
/*
|
||||
.content-wrapper .index {
|
||||
background: $blue;
|
||||
color: white;
|
||||
text-shadow: 0 1px 1px rgba(0,0,0,.95);
|
||||
}
|
||||
*/
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -150,10 +152,14 @@ app-root .content {
|
||||
}
|
||||
|
||||
&.active .content-wrapper {
|
||||
border-top: 1px solid $blue;
|
||||
border-top: 1px solid $teal;
|
||||
border-top-left-radius: $tab-border-radius;
|
||||
border-top-right-radius: $tab-border-radius;
|
||||
}
|
||||
|
||||
&.has-activity:not(.active) .content-wrapper {
|
||||
border-top: 1px solid $green;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -178,10 +184,14 @@ app-root .content {
|
||||
}
|
||||
|
||||
&.active .content-wrapper {
|
||||
border-bottom: 1px solid $blue;
|
||||
border-bottom: 1px solid $teal;
|
||||
border-bottom-left-radius: $tab-border-radius;
|
||||
border-bottom-right-radius: $tab-border-radius;
|
||||
}
|
||||
|
||||
&.has-activity:not(.active) .content-wrapper {
|
||||
border-bottom: 1px solid $green;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -29,6 +29,7 @@
|
||||
"tslint": "4.5.0",
|
||||
"tslint-eslint-rules": "^3.5.1",
|
||||
"typescript": "2.2.1",
|
||||
"untildify": "^3.0.2",
|
||||
"url-loader": "^0.5.7",
|
||||
"val-loader": "^0.5.0",
|
||||
"vrsource-tslint-rules": "^4.0.1",
|
||||
|
Loading…
x
Reference in New Issue
Block a user