mirror of
https://github.com/Eugeny/tabby.git
synced 2025-08-18 15:21:51 +00:00
lint
This commit is contained in:
@@ -4,7 +4,7 @@ import { NgbModule } from '@ng-bootstrap/ng-bootstrap'
|
|||||||
import { ToastrModule } from 'ngx-toastr'
|
import { ToastrModule } from 'ngx-toastr'
|
||||||
|
|
||||||
export function getRootModule (plugins: any[]) {
|
export function getRootModule (plugins: any[]) {
|
||||||
let imports = [
|
const imports = [
|
||||||
BrowserModule,
|
BrowserModule,
|
||||||
...plugins,
|
...plugins,
|
||||||
NgbModule.forRoot(),
|
NgbModule.forRoot(),
|
||||||
@@ -15,7 +15,7 @@ export function getRootModule (plugins: any[]) {
|
|||||||
extendedTimeOut: 5000,
|
extendedTimeOut: 5000,
|
||||||
}),
|
}),
|
||||||
]
|
]
|
||||||
let bootstrap = [
|
const bootstrap = [
|
||||||
...(plugins.filter(x => x.bootstrap).map(x => x.bootstrap)),
|
...(plugins.filter(x => x.bootstrap).map(x => x.bootstrap)),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@@ -16,8 +16,8 @@ Raven.config(
|
|||||||
{
|
{
|
||||||
release: require('electron').remote.app.getVersion(),
|
release: require('electron').remote.app.getVersion(),
|
||||||
dataCallback: (data: any) => {
|
dataCallback: (data: any) => {
|
||||||
const normalize = (filename) => {
|
const normalize = (filename: string) => {
|
||||||
let splitArray = filename.split('/')
|
const splitArray = filename.split('/')
|
||||||
return splitArray[splitArray.length - 1]
|
return splitArray[splitArray.length - 1]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -32,10 +32,10 @@ async function bootstrap (plugins: IPluginInfo[], safeMode = false): Promise<NgM
|
|||||||
if (safeMode) {
|
if (safeMode) {
|
||||||
plugins = plugins.filter(x => x.isBuiltin)
|
plugins = plugins.filter(x => x.isBuiltin)
|
||||||
}
|
}
|
||||||
let pluginsModules = await loadPlugins(plugins, (current, total) => {
|
const pluginsModules = await loadPlugins(plugins, (current, total) => {
|
||||||
(document.querySelector('.progress .bar') as HTMLElement).style.width = 100 * current / total + '%'
|
(document.querySelector('.progress .bar') as HTMLElement).style.width = 100 * current / total + '%'
|
||||||
})
|
})
|
||||||
let module = getRootModule(pluginsModules)
|
const module = getRootModule(pluginsModules)
|
||||||
window['rootModule'] = module
|
window['rootModule'] = module
|
||||||
return platformBrowserDynamic().bootstrapModule(module)
|
return platformBrowserDynamic().bootstrapModule(module)
|
||||||
}
|
}
|
||||||
|
@@ -12,7 +12,7 @@ function normalizePath (path: string): string {
|
|||||||
return path
|
return path
|
||||||
}
|
}
|
||||||
|
|
||||||
nodeRequire.main.paths.map(x => nodeModule.globalPaths.push(normalizePath(x)))
|
nodeRequire.main.paths.map((x: string) => nodeModule.globalPaths.push(normalizePath(x)))
|
||||||
|
|
||||||
if (process.env.TERMINUS_DEV) {
|
if (process.env.TERMINUS_DEV) {
|
||||||
nodeModule.globalPaths.unshift(path.dirname(require('electron').remote.app.getAppPath()))
|
nodeModule.globalPaths.unshift(path.dirname(require('electron').remote.app.getAppPath()))
|
||||||
@@ -38,7 +38,7 @@ if (process.env.TERMINUS_PLUGINS) {
|
|||||||
process.env.TERMINUS_PLUGINS.split(':').map(x => nodeModule.globalPaths.push(normalizePath(x)))
|
process.env.TERMINUS_PLUGINS.split(':').map(x => nodeModule.globalPaths.push(normalizePath(x)))
|
||||||
}
|
}
|
||||||
|
|
||||||
export declare type ProgressCallback = (current, total) => void
|
export declare type ProgressCallback = (current: number, total: number) => void
|
||||||
|
|
||||||
export interface IPluginInfo {
|
export interface IPluginInfo {
|
||||||
name: string
|
name: string
|
||||||
@@ -80,7 +80,7 @@ builtinModules.forEach(m => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
const originalRequire = (global as any).require
|
const originalRequire = (global as any).require
|
||||||
;(global as any).require = function (query) {
|
;(global as any).require = function (query: string) {
|
||||||
if (cachedBuiltinModules[query]) {
|
if (cachedBuiltinModules[query]) {
|
||||||
return cachedBuiltinModules[query]
|
return cachedBuiltinModules[query]
|
||||||
}
|
}
|
||||||
@@ -88,9 +88,9 @@ const originalRequire = (global as any).require
|
|||||||
}
|
}
|
||||||
|
|
||||||
export async function findPlugins (): Promise<IPluginInfo[]> {
|
export async function findPlugins (): Promise<IPluginInfo[]> {
|
||||||
let paths = nodeModule.globalPaths
|
const paths = nodeModule.globalPaths
|
||||||
let foundPlugins: IPluginInfo[] = []
|
let foundPlugins: IPluginInfo[] = []
|
||||||
let candidateLocations: { pluginDir: string, packageName: string }[] = []
|
const candidateLocations: { pluginDir: string, packageName: string }[] = []
|
||||||
const PREFIX = 'terminus-'
|
const PREFIX = 'terminus-'
|
||||||
|
|
||||||
for (let pluginDir of paths) {
|
for (let pluginDir of paths) {
|
||||||
@@ -98,28 +98,28 @@ export async function findPlugins (): Promise<IPluginInfo[]> {
|
|||||||
if (!await fs.exists(pluginDir)) {
|
if (!await fs.exists(pluginDir)) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
let pluginNames = await fs.readdir(pluginDir)
|
const pluginNames = await fs.readdir(pluginDir)
|
||||||
if (await fs.exists(path.join(pluginDir, 'package.json'))) {
|
if (await fs.exists(path.join(pluginDir, 'package.json'))) {
|
||||||
candidateLocations.push({
|
candidateLocations.push({
|
||||||
pluginDir: path.dirname(pluginDir),
|
pluginDir: path.dirname(pluginDir),
|
||||||
packageName: path.basename(pluginDir)
|
packageName: path.basename(pluginDir)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
for (let packageName of pluginNames) {
|
for (const packageName of pluginNames) {
|
||||||
if (packageName.startsWith(PREFIX)) {
|
if (packageName.startsWith(PREFIX)) {
|
||||||
candidateLocations.push({ pluginDir, packageName })
|
candidateLocations.push({ pluginDir, packageName })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (let { pluginDir, packageName } of candidateLocations) {
|
for (const { pluginDir, packageName } of candidateLocations) {
|
||||||
let pluginPath = path.join(pluginDir, packageName)
|
const pluginPath = path.join(pluginDir, packageName)
|
||||||
let infoPath = path.join(pluginPath, 'package.json')
|
const infoPath = path.join(pluginPath, 'package.json')
|
||||||
if (!await fs.exists(infoPath)) {
|
if (!await fs.exists(infoPath)) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
let name = packageName.substring(PREFIX.length)
|
const name = packageName.substring(PREFIX.length)
|
||||||
|
|
||||||
if (foundPlugins.some(x => x.name === name)) {
|
if (foundPlugins.some(x => x.name === name)) {
|
||||||
console.info(`Plugin ${packageName} already exists, overriding`)
|
console.info(`Plugin ${packageName} already exists, overriding`)
|
||||||
@@ -127,7 +127,7 @@ export async function findPlugins (): Promise<IPluginInfo[]> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
let info = JSON.parse(await fs.readFile(infoPath, { encoding: 'utf-8' }))
|
const info = JSON.parse(await fs.readFile(infoPath, { encoding: 'utf-8' }))
|
||||||
if (!info.keywords || !(info.keywords.includes('terminus-plugin') || info.keywords.includes('terminus-builtin-plugin'))) {
|
if (!info.keywords || !(info.keywords.includes('terminus-plugin') || info.keywords.includes('terminus-builtin-plugin'))) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@@ -153,17 +153,17 @@ export async function findPlugins (): Promise<IPluginInfo[]> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export async function loadPlugins (foundPlugins: IPluginInfo[], progress: ProgressCallback): Promise<any[]> {
|
export async function loadPlugins (foundPlugins: IPluginInfo[], progress: ProgressCallback): Promise<any[]> {
|
||||||
let plugins: any[] = []
|
const plugins: any[] = []
|
||||||
progress(0, 1)
|
progress(0, 1)
|
||||||
let index = 0
|
let index = 0
|
||||||
for (let foundPlugin of foundPlugins) {
|
for (const foundPlugin of foundPlugins) {
|
||||||
console.info(`Loading ${foundPlugin.name}: ${nodeRequire.resolve(foundPlugin.path)}`)
|
console.info(`Loading ${foundPlugin.name}: ${nodeRequire.resolve(foundPlugin.path)}`)
|
||||||
progress(index, foundPlugins.length)
|
progress(index, foundPlugins.length)
|
||||||
try {
|
try {
|
||||||
const label = 'Loading ' + foundPlugin.name
|
const label = 'Loading ' + foundPlugin.name
|
||||||
console.time(label)
|
console.time(label)
|
||||||
let packageModule = nodeRequire(foundPlugin.path)
|
const packageModule = nodeRequire(foundPlugin.path)
|
||||||
let pluginModule = packageModule.default.forRoot ? packageModule.default.forRoot() : packageModule.default
|
const pluginModule = packageModule.default.forRoot ? packageModule.default.forRoot() : packageModule.default
|
||||||
pluginModule['pluginName'] = foundPlugin.name
|
pluginModule['pluginName'] = foundPlugin.name
|
||||||
pluginModule['bootstrap'] = packageModule.bootstrap
|
pluginModule['bootstrap'] = packageModule.bootstrap
|
||||||
plugins.push(pluginModule)
|
plugins.push(pluginModule)
|
||||||
|
@@ -6,13 +6,13 @@ const schemeContents = require.context('../schemes/', true, /.*/)
|
|||||||
@Injectable()
|
@Injectable()
|
||||||
export class ColorSchemes extends TerminalColorSchemeProvider {
|
export class ColorSchemes extends TerminalColorSchemeProvider {
|
||||||
async getSchemes (): Promise<ITerminalColorScheme[]> {
|
async getSchemes (): Promise<ITerminalColorScheme[]> {
|
||||||
let schemes: ITerminalColorScheme[] = []
|
const schemes: ITerminalColorScheme[] = []
|
||||||
|
|
||||||
schemeContents.keys().forEach(schemeFile => {
|
schemeContents.keys().forEach(schemeFile => {
|
||||||
let lines = (schemeContents(schemeFile).default as string).split('\n')
|
const lines = (schemeContents(schemeFile).default as string).split('\n')
|
||||||
|
|
||||||
// process #define variables
|
// process #define variables
|
||||||
let variables: any = {}
|
const variables: any = {}
|
||||||
lines
|
lines
|
||||||
.filter(x => x.startsWith('#define'))
|
.filter(x => x.startsWith('#define'))
|
||||||
.map(x => x.split(' ').map(v => v.trim()))
|
.map(x => x.split(' ').map(v => v.trim()))
|
||||||
@@ -20,7 +20,7 @@ export class ColorSchemes extends TerminalColorSchemeProvider {
|
|||||||
variables[variableName] = variableValue
|
variables[variableName] = variableValue
|
||||||
})
|
})
|
||||||
|
|
||||||
let values: any = {}
|
const values: any = {}
|
||||||
lines
|
lines
|
||||||
.filter(x => x.startsWith('*.'))
|
.filter(x => x.startsWith('*.'))
|
||||||
.map(x => x.substring(2))
|
.map(x => x.substring(2))
|
||||||
@@ -29,7 +29,7 @@ export class ColorSchemes extends TerminalColorSchemeProvider {
|
|||||||
values[key] = variables[value] ? variables[value] : value
|
values[key] = variables[value] ? variables[value] : value
|
||||||
})
|
})
|
||||||
|
|
||||||
let colors: string[] = []
|
const colors: string[] = []
|
||||||
let colorIndex = 0
|
let colorIndex = 0
|
||||||
while (values[`color${colorIndex}`]) {
|
while (values[`color${colorIndex}`]) {
|
||||||
colors.push(values[`color${colorIndex}`])
|
colors.push(values[`color${colorIndex}`])
|
||||||
|
@@ -91,7 +91,7 @@ export class AppRootComponent {
|
|||||||
|
|
||||||
this.hotkeys.matchedHotkey.subscribe((hotkey) => {
|
this.hotkeys.matchedHotkey.subscribe((hotkey) => {
|
||||||
if (hotkey.startsWith('tab-')) {
|
if (hotkey.startsWith('tab-')) {
|
||||||
let index = parseInt(hotkey.split('-')[1])
|
const index = parseInt(hotkey.split('-')[1])
|
||||||
if (index <= this.app.tabs.length) {
|
if (index <= this.app.tabs.length) {
|
||||||
this.app.selectTab(this.app.tabs[index - 1])
|
this.app.selectTab(this.app.tabs[index - 1])
|
||||||
}
|
}
|
||||||
|
@@ -23,7 +23,7 @@ export class CheckboxComponent implements ControlValueAccessor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.model = !this.model
|
this.model = !this.model
|
||||||
for (let fx of this.changed) {
|
for (const fx of this.changed) {
|
||||||
fx(this.model)
|
fx(this.model)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -35,7 +35,7 @@ export class SplitContainer {
|
|||||||
*/
|
*/
|
||||||
getAllTabs () {
|
getAllTabs () {
|
||||||
let r = []
|
let r = []
|
||||||
for (let child of this.children) {
|
for (const child of this.children) {
|
||||||
if (child instanceof SplitContainer) {
|
if (child instanceof SplitContainer) {
|
||||||
r = r.concat(child.getAllTabs())
|
r = r.concat(child.getAllTabs())
|
||||||
} else {
|
} else {
|
||||||
@@ -50,7 +50,7 @@ export class SplitContainer {
|
|||||||
*/
|
*/
|
||||||
normalize () {
|
normalize () {
|
||||||
for (let i = 0; i < this.children.length; i++) {
|
for (let i = 0; i < this.children.length; i++) {
|
||||||
let child = this.children[i]
|
const child = this.children[i]
|
||||||
|
|
||||||
if (child instanceof SplitContainer) {
|
if (child instanceof SplitContainer) {
|
||||||
child.normalize()
|
child.normalize()
|
||||||
@@ -63,7 +63,7 @@ export class SplitContainer {
|
|||||||
} else if (child.children.length === 1) {
|
} else if (child.children.length === 1) {
|
||||||
this.children[i] = child.children[0]
|
this.children[i] = child.children[0]
|
||||||
} else if (child.orientation === this.orientation) {
|
} else if (child.orientation === this.orientation) {
|
||||||
let ratio = this.ratios[i]
|
const ratio = this.ratios[i]
|
||||||
this.children.splice(i, 1)
|
this.children.splice(i, 1)
|
||||||
this.ratios.splice(i, 1)
|
this.ratios.splice(i, 1)
|
||||||
for (let j = 0; j < child.children.length; j++) {
|
for (let j = 0; j < child.children.length; j++) {
|
||||||
@@ -76,7 +76,7 @@ export class SplitContainer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let s = 0
|
let s = 0
|
||||||
for (let x of this.ratios) {
|
for (const x of this.ratios) {
|
||||||
s += x
|
s += x
|
||||||
}
|
}
|
||||||
this.ratios = this.ratios.map(x => x / s)
|
this.ratios = this.ratios.map(x => x / s)
|
||||||
@@ -94,8 +94,8 @@ export class SplitContainer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async serialize () {
|
async serialize () {
|
||||||
let children = []
|
const children = []
|
||||||
for (let child of this.children) {
|
for (const child of this.children) {
|
||||||
if (child instanceof SplitContainer) {
|
if (child instanceof SplitContainer) {
|
||||||
children.push(await child.serialize())
|
children.push(await child.serialize())
|
||||||
} else {
|
} else {
|
||||||
@@ -257,7 +257,7 @@ export class SplitTabComponent extends BaseTabComponent implements OnInit, OnDes
|
|||||||
|
|
||||||
focus (tab: BaseTabComponent) {
|
focus (tab: BaseTabComponent) {
|
||||||
this.focusedTab = tab
|
this.focusedTab = tab
|
||||||
for (let x of this.getAllTabs()) {
|
for (const x of this.getAllTabs()) {
|
||||||
if (x !== tab) {
|
if (x !== tab) {
|
||||||
x.emitBlurred()
|
x.emitBlurred()
|
||||||
}
|
}
|
||||||
@@ -294,7 +294,7 @@ export class SplitTabComponent extends BaseTabComponent implements OnInit, OnDes
|
|||||||
(target.orientation === 'v' && ['l', 'r'].includes(side)) ||
|
(target.orientation === 'v' && ['l', 'r'].includes(side)) ||
|
||||||
(target.orientation === 'h' && ['t', 'b'].includes(side))
|
(target.orientation === 'h' && ['t', 'b'].includes(side))
|
||||||
) {
|
) {
|
||||||
let newContainer = new SplitContainer()
|
const newContainer = new SplitContainer()
|
||||||
newContainer.orientation = (target.orientation === 'v') ? 'h' : 'v'
|
newContainer.orientation = (target.orientation === 'v') ? 'h' : 'v'
|
||||||
newContainer.children = [relative]
|
newContainer.children = [relative]
|
||||||
newContainer.ratios = [1]
|
newContainer.ratios = [1]
|
||||||
@@ -326,8 +326,8 @@ export class SplitTabComponent extends BaseTabComponent implements OnInit, OnDes
|
|||||||
}
|
}
|
||||||
|
|
||||||
removeTab (tab: BaseTabComponent) {
|
removeTab (tab: BaseTabComponent) {
|
||||||
let parent = this.getParentOf(tab)
|
const parent = this.getParentOf(tab)
|
||||||
let index = parent.children.indexOf(tab)
|
const index = parent.children.indexOf(tab)
|
||||||
parent.ratios.splice(index, 1)
|
parent.ratios.splice(index, 1)
|
||||||
parent.children.splice(index, 1)
|
parent.children.splice(index, 1)
|
||||||
|
|
||||||
@@ -350,7 +350,7 @@ export class SplitTabComponent extends BaseTabComponent implements OnInit, OnDes
|
|||||||
navigate (dir: SplitDirection) {
|
navigate (dir: SplitDirection) {
|
||||||
let rel: BaseTabComponent | SplitContainer = this.focusedTab
|
let rel: BaseTabComponent | SplitContainer = this.focusedTab
|
||||||
let parent = this.getParentOf(rel)
|
let parent = this.getParentOf(rel)
|
||||||
let orientation = ['l', 'r'].includes(dir) ? 'h' : 'v'
|
const orientation = ['l', 'r'].includes(dir) ? 'h' : 'v'
|
||||||
|
|
||||||
while (parent !== this.root && parent.orientation !== orientation) {
|
while (parent !== this.root && parent.orientation !== orientation) {
|
||||||
rel = parent
|
rel = parent
|
||||||
@@ -361,7 +361,7 @@ export class SplitTabComponent extends BaseTabComponent implements OnInit, OnDes
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
let index = parent.children.indexOf(rel)
|
const index = parent.children.indexOf(rel)
|
||||||
if (['l', 't'].includes(dir)) {
|
if (['l', 't'].includes(dir)) {
|
||||||
if (index > 0) {
|
if (index > 0) {
|
||||||
this.focusAnyIn(parent.children[index - 1])
|
this.focusAnyIn(parent.children[index - 1])
|
||||||
@@ -374,7 +374,7 @@ export class SplitTabComponent extends BaseTabComponent implements OnInit, OnDes
|
|||||||
}
|
}
|
||||||
|
|
||||||
async splitTab (tab: BaseTabComponent, dir: SplitDirection) {
|
async splitTab (tab: BaseTabComponent, dir: SplitDirection) {
|
||||||
let newTab = await this.tabsService.duplicate(tab)
|
const newTab = await this.tabsService.duplicate(tab)
|
||||||
this.addTab(newTab, tab, dir)
|
this.addTab(newTab, tab, dir)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -383,9 +383,9 @@ export class SplitTabComponent extends BaseTabComponent implements OnInit, OnDes
|
|||||||
*/
|
*/
|
||||||
getParentOf (tab: BaseTabComponent | SplitContainer, root?: SplitContainer): SplitContainer {
|
getParentOf (tab: BaseTabComponent | SplitContainer, root?: SplitContainer): SplitContainer {
|
||||||
root = root || this.root
|
root = root || this.root
|
||||||
for (let child of root.children) {
|
for (const child of root.children) {
|
||||||
if (child instanceof SplitContainer) {
|
if (child instanceof SplitContainer) {
|
||||||
let r = this.getParentOf(tab, child)
|
const r = this.getParentOf(tab, child)
|
||||||
if (r) {
|
if (r) {
|
||||||
return r
|
return r
|
||||||
}
|
}
|
||||||
@@ -419,7 +419,7 @@ export class SplitTabComponent extends BaseTabComponent implements OnInit, OnDes
|
|||||||
}
|
}
|
||||||
|
|
||||||
private attachTabView (tab: BaseTabComponent) {
|
private attachTabView (tab: BaseTabComponent) {
|
||||||
let ref = this.viewContainer.insert(tab.hostView) as EmbeddedViewRef<any>
|
const ref = this.viewContainer.insert(tab.hostView) as EmbeddedViewRef<any>
|
||||||
this.viewRefs.set(tab, ref)
|
this.viewRefs.set(tab, ref)
|
||||||
|
|
||||||
ref.rootNodes[0].addEventListener('click', () => this.focus(tab))
|
ref.rootNodes[0].addEventListener('click', () => this.focus(tab))
|
||||||
@@ -436,7 +436,7 @@ export class SplitTabComponent extends BaseTabComponent implements OnInit, OnDes
|
|||||||
}
|
}
|
||||||
|
|
||||||
private detachTabView (tab: BaseTabComponent) {
|
private detachTabView (tab: BaseTabComponent) {
|
||||||
let ref = this.viewRefs.get(tab)
|
const ref = this.viewRefs.get(tab)
|
||||||
this.viewRefs.delete(tab)
|
this.viewRefs.delete(tab)
|
||||||
this.viewContainer.remove(this.viewContainer.indexOf(ref))
|
this.viewContainer.remove(this.viewContainer.indexOf(ref))
|
||||||
}
|
}
|
||||||
@@ -448,8 +448,8 @@ export class SplitTabComponent extends BaseTabComponent implements OnInit, OnDes
|
|||||||
}
|
}
|
||||||
|
|
||||||
private layoutInternal (root: SplitContainer, x: number, y: number, w: number, h: number) {
|
private layoutInternal (root: SplitContainer, x: number, y: number, w: number, h: number) {
|
||||||
let size = (root.orientation === 'v') ? h : w
|
const size = (root.orientation === 'v') ? h : w
|
||||||
let sizes = root.ratios.map(x => x * size)
|
const sizes = root.ratios.map(x => x * size)
|
||||||
|
|
||||||
root.x = x
|
root.x = x
|
||||||
root.y = y
|
root.y = y
|
||||||
@@ -458,14 +458,14 @@ export class SplitTabComponent extends BaseTabComponent implements OnInit, OnDes
|
|||||||
|
|
||||||
let offset = 0
|
let offset = 0
|
||||||
root.children.forEach((child, i) => {
|
root.children.forEach((child, i) => {
|
||||||
let childX = (root.orientation === 'v') ? x : (x + offset)
|
const childX = (root.orientation === 'v') ? x : (x + offset)
|
||||||
let childY = (root.orientation === 'v') ? (y + offset) : y
|
const childY = (root.orientation === 'v') ? (y + offset) : y
|
||||||
let childW = (root.orientation === 'v') ? w : sizes[i]
|
const childW = (root.orientation === 'v') ? w : sizes[i]
|
||||||
let childH = (root.orientation === 'v') ? sizes[i] : h
|
const childH = (root.orientation === 'v') ? sizes[i] : h
|
||||||
if (child instanceof SplitContainer) {
|
if (child instanceof SplitContainer) {
|
||||||
this.layoutInternal(child, childX, childY, childW, childH)
|
this.layoutInternal(child, childX, childY, childW, childH)
|
||||||
} else {
|
} else {
|
||||||
let element = this.viewRefs.get(child).rootNodes[0]
|
const element = this.viewRefs.get(child).rootNodes[0]
|
||||||
element.style.position = 'absolute'
|
element.style.position = 'absolute'
|
||||||
element.style.left = `${childX}%`
|
element.style.left = `${childX}%`
|
||||||
element.style.top = `${childY}%`
|
element.style.top = `${childY}%`
|
||||||
@@ -486,19 +486,19 @@ export class SplitTabComponent extends BaseTabComponent implements OnInit, OnDes
|
|||||||
}
|
}
|
||||||
|
|
||||||
private async recoverContainer (root: SplitContainer, state: any) {
|
private async recoverContainer (root: SplitContainer, state: any) {
|
||||||
let children: (SplitContainer | BaseTabComponent)[] = []
|
const children: (SplitContainer | BaseTabComponent)[] = []
|
||||||
root.orientation = state.orientation
|
root.orientation = state.orientation
|
||||||
root.ratios = state.ratios
|
root.ratios = state.ratios
|
||||||
root.children = children
|
root.children = children
|
||||||
for (let childState of state.children) {
|
for (const childState of state.children) {
|
||||||
if (childState.type === 'app:split-tab') {
|
if (childState.type === 'app:split-tab') {
|
||||||
let child = new SplitContainer()
|
const child = new SplitContainer()
|
||||||
await this.recoverContainer(child, childState)
|
await this.recoverContainer(child, childState)
|
||||||
children.push(child)
|
children.push(child)
|
||||||
} else {
|
} else {
|
||||||
let recovered = await this.tabRecovery.recoverTab(childState)
|
const recovered = await this.tabRecovery.recoverTab(childState)
|
||||||
if (recovered) {
|
if (recovered) {
|
||||||
let tab = this.tabsService.create(recovered.type, recovered.options)
|
const tab = this.tabsService.create(recovered.type, recovered.options)
|
||||||
children.push(tab)
|
children.push(tab)
|
||||||
this.attachTabView(tab)
|
this.attachTabView(tab)
|
||||||
} else {
|
} else {
|
||||||
|
@@ -25,13 +25,13 @@ export class SplitTabSpannerComponent {
|
|||||||
ngAfterViewInit () {
|
ngAfterViewInit () {
|
||||||
this.element.nativeElement.addEventListener('mousedown', e => {
|
this.element.nativeElement.addEventListener('mousedown', e => {
|
||||||
this.isActive = true
|
this.isActive = true
|
||||||
let start = this.isVertical ? e.pageY : e.pageX
|
const start = this.isVertical ? e.pageY : e.pageX
|
||||||
let current = start
|
let current = start
|
||||||
let oldPosition = this.isVertical ? this.element.nativeElement.offsetTop : this.element.nativeElement.offsetLeft
|
const oldPosition = this.isVertical ? this.element.nativeElement.offsetTop : this.element.nativeElement.offsetLeft
|
||||||
|
|
||||||
const dragHandler = e => {
|
const dragHandler = e => {
|
||||||
current = this.isVertical ? e.pageY : e.pageX
|
current = this.isVertical ? e.pageY : e.pageX
|
||||||
let newPosition = oldPosition + (current - start)
|
const newPosition = oldPosition + (current - start)
|
||||||
if (this.isVertical) {
|
if (this.isVertical) {
|
||||||
this.element.nativeElement.style.top = `${newPosition - this.marginOffset}px`
|
this.element.nativeElement.style.top = `${newPosition - this.marginOffset}px`
|
||||||
} else {
|
} else {
|
||||||
|
@@ -52,7 +52,7 @@ export class TabHeaderComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
showRenameTabModal (): void {
|
showRenameTabModal (): void {
|
||||||
let modal = this.ngbModal.open(RenameTabModalComponent)
|
const modal = this.ngbModal.open(RenameTabModalComponent)
|
||||||
modal.componentInstance.value = this.tab.customTitle || this.tab.title
|
modal.componentInstance.value = this.tab.customTitle || this.tab.title
|
||||||
modal.result.then(result => {
|
modal.result.then(result => {
|
||||||
this.tab.setTitle(result)
|
this.tab.setTitle(result)
|
||||||
@@ -62,7 +62,7 @@ export class TabHeaderComponent {
|
|||||||
|
|
||||||
async buildContextMenu (): Promise<Electron.MenuItemConstructorOptions[]> {
|
async buildContextMenu (): Promise<Electron.MenuItemConstructorOptions[]> {
|
||||||
let items: Electron.MenuItemConstructorOptions[] = []
|
let items: Electron.MenuItemConstructorOptions[] = []
|
||||||
for (let section of await Promise.all(this.contextMenuProviders.map(x => x.getItems(this.tab, this)))) {
|
for (const section of await Promise.all(this.contextMenuProviders.map(x => x.getItems(this.tab, this)))) {
|
||||||
items.push({ type: 'separator' })
|
items.push({ type: 'separator' })
|
||||||
items = items.concat(section)
|
items = items.concat(section)
|
||||||
}
|
}
|
||||||
|
@@ -68,7 +68,7 @@ export class AppService {
|
|||||||
private tabsService: TabsService,
|
private tabsService: TabsService,
|
||||||
) {
|
) {
|
||||||
this.tabRecovery.recoverTabs().then(tabs => {
|
this.tabRecovery.recoverTabs().then(tabs => {
|
||||||
for (let tab of tabs) {
|
for (const tab of tabs) {
|
||||||
this.openNewTabRaw(tab.type, tab.options)
|
this.openNewTabRaw(tab.type, tab.options)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -98,7 +98,7 @@ export class AppService {
|
|||||||
})
|
})
|
||||||
|
|
||||||
tab.destroyed$.subscribe(() => {
|
tab.destroyed$.subscribe(() => {
|
||||||
let newIndex = Math.max(0, this.tabs.indexOf(tab) - 1)
|
const newIndex = Math.max(0, this.tabs.indexOf(tab) - 1)
|
||||||
this.tabs = this.tabs.filter((x) => x !== tab)
|
this.tabs = this.tabs.filter((x) => x !== tab)
|
||||||
if (tab === this._activeTab) {
|
if (tab === this._activeTab) {
|
||||||
this.selectTab(this.tabs[newIndex])
|
this.selectTab(this.tabs[newIndex])
|
||||||
@@ -113,7 +113,7 @@ export class AppService {
|
|||||||
* @param inputs Properties to be assigned on the new tab component instance
|
* @param inputs Properties to be assigned on the new tab component instance
|
||||||
*/
|
*/
|
||||||
openNewTabRaw (type: TabComponentType, inputs?: any): BaseTabComponent {
|
openNewTabRaw (type: TabComponentType, inputs?: any): BaseTabComponent {
|
||||||
let tab = this.tabsService.create(type, inputs)
|
const tab = this.tabsService.create(type, inputs)
|
||||||
this.addTabRaw(tab)
|
this.addTabRaw(tab)
|
||||||
return tab
|
return tab
|
||||||
}
|
}
|
||||||
@@ -123,8 +123,8 @@ export class AppService {
|
|||||||
* @param inputs Properties to be assigned on the new tab component instance
|
* @param inputs Properties to be assigned on the new tab component instance
|
||||||
*/
|
*/
|
||||||
openNewTab (type: TabComponentType, inputs?: any): BaseTabComponent {
|
openNewTab (type: TabComponentType, inputs?: any): BaseTabComponent {
|
||||||
let splitTab = this.tabsService.create(SplitTabComponent) as SplitTabComponent
|
const splitTab = this.tabsService.create(SplitTabComponent) as SplitTabComponent
|
||||||
let tab = this.tabsService.create(type, inputs)
|
const tab = this.tabsService.create(type, inputs)
|
||||||
splitTab.addTab(tab, null, 'r')
|
splitTab.addTab(tab, null, 'r')
|
||||||
this.addTabRaw(splitTab)
|
this.addTabRaw(splitTab)
|
||||||
return tab
|
return tab
|
||||||
@@ -164,7 +164,7 @@ export class AppService {
|
|||||||
|
|
||||||
nextTab () {
|
nextTab () {
|
||||||
if (this.tabs.length > 1) {
|
if (this.tabs.length > 1) {
|
||||||
let tabIndex = this.tabs.indexOf(this._activeTab)
|
const tabIndex = this.tabs.indexOf(this._activeTab)
|
||||||
if (tabIndex < this.tabs.length - 1) {
|
if (tabIndex < this.tabs.length - 1) {
|
||||||
this.selectTab(this.tabs[tabIndex + 1])
|
this.selectTab(this.tabs[tabIndex + 1])
|
||||||
} else if (this.config.store.appearance.cycleTabs) {
|
} else if (this.config.store.appearance.cycleTabs) {
|
||||||
@@ -175,7 +175,7 @@ export class AppService {
|
|||||||
|
|
||||||
previousTab () {
|
previousTab () {
|
||||||
if (this.tabs.length > 1) {
|
if (this.tabs.length > 1) {
|
||||||
let tabIndex = this.tabs.indexOf(this._activeTab)
|
const tabIndex = this.tabs.indexOf(this._activeTab)
|
||||||
if (tabIndex > 0) {
|
if (tabIndex > 0) {
|
||||||
this.selectTab(this.tabs[tabIndex - 1])
|
this.selectTab(this.tabs[tabIndex - 1])
|
||||||
} else if (this.config.store.appearance.cycleTabs) {
|
} else if (this.config.store.appearance.cycleTabs) {
|
||||||
@@ -200,19 +200,19 @@ export class AppService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async duplicateTab (tab: BaseTabComponent) {
|
async duplicateTab (tab: BaseTabComponent) {
|
||||||
let dup = await this.tabsService.duplicate(tab)
|
const dup = await this.tabsService.duplicate(tab)
|
||||||
if (dup) {
|
if (dup) {
|
||||||
this.addTabRaw(dup)
|
this.addTabRaw(dup)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async closeAllTabs () {
|
async closeAllTabs () {
|
||||||
for (let tab of this.tabs) {
|
for (const tab of this.tabs) {
|
||||||
if (!await tab.canClose()) {
|
if (!await tab.canClose()) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (let tab of this.tabs) {
|
for (const tab of this.tabs) {
|
||||||
tab.destroy()
|
tab.destroy()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -230,7 +230,7 @@ export class AppService {
|
|||||||
*/
|
*/
|
||||||
observeTabCompletion (tab: BaseTabComponent): Observable<void> {
|
observeTabCompletion (tab: BaseTabComponent): Observable<void> {
|
||||||
if (!this.completionObservers.has(tab)) {
|
if (!this.completionObservers.has(tab)) {
|
||||||
let observer = new CompletionObserver(tab)
|
const observer = new CompletionObserver(tab)
|
||||||
observer.destroyed$.subscribe(() => {
|
observer.destroyed$.subscribe(() => {
|
||||||
this.stopObservingTabCompletion(tab)
|
this.stopObservingTabCompletion(tab)
|
||||||
})
|
})
|
||||||
|
@@ -21,12 +21,12 @@ function isNonStructuralObjectMember (v) {
|
|||||||
/** @hidden */
|
/** @hidden */
|
||||||
export class ConfigProxy {
|
export class ConfigProxy {
|
||||||
constructor (real: any, defaults: any) {
|
constructor (real: any, defaults: any) {
|
||||||
for (let key in defaults) {
|
for (const key in defaults) {
|
||||||
if (isStructuralMember(defaults[key])) {
|
if (isStructuralMember(defaults[key])) {
|
||||||
if (!real[key]) {
|
if (!real[key]) {
|
||||||
real[key] = {}
|
real[key] = {}
|
||||||
}
|
}
|
||||||
let proxy = new ConfigProxy(real[key], defaults[key])
|
const proxy = new ConfigProxy(real[key], defaults[key])
|
||||||
Object.defineProperty(
|
Object.defineProperty(
|
||||||
this,
|
this,
|
||||||
key,
|
key,
|
||||||
@@ -177,9 +177,9 @@ export class ConfigService {
|
|||||||
enabledServices<T> (services: T[]): T[] {
|
enabledServices<T> (services: T[]): T[] {
|
||||||
if (!this.servicesCache) {
|
if (!this.servicesCache) {
|
||||||
this.servicesCache = {}
|
this.servicesCache = {}
|
||||||
let ngModule = window['rootModule'].ngInjectorDef
|
const ngModule = window['rootModule'].ngInjectorDef
|
||||||
for (let imp of ngModule.imports) {
|
for (const imp of ngModule.imports) {
|
||||||
let module = (imp['ngModule'] || imp)
|
const module = (imp['ngModule'] || imp)
|
||||||
if (module.ngInjectorDef && module.ngInjectorDef.providers) {
|
if (module.ngInjectorDef && module.ngInjectorDef.providers) {
|
||||||
this.servicesCache[module['pluginName']] = module.ngInjectorDef.providers.map(provider => {
|
this.servicesCache[module['pluginName']] = module.ngInjectorDef.providers.map(provider => {
|
||||||
return provider['useClass'] || provider
|
return provider['useClass'] || provider
|
||||||
@@ -188,7 +188,7 @@ export class ConfigService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
return services.filter(service => {
|
return services.filter(service => {
|
||||||
for (let pluginName in this.servicesCache) {
|
for (const pluginName in this.servicesCache) {
|
||||||
if (this.servicesCache[pluginName].includes(service.constructor)) {
|
if (this.servicesCache[pluginName].includes(service.constructor)) {
|
||||||
return !this.store.pluginBlacklist.includes(pluginName)
|
return !this.store.pluginBlacklist.includes(pluginName)
|
||||||
}
|
}
|
||||||
|
@@ -21,7 +21,7 @@ export class DockingService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dock () {
|
dock () {
|
||||||
let dockSide = this.config.store.appearance.dock
|
const dockSide = this.config.store.appearance.dock
|
||||||
|
|
||||||
if (dockSide === 'off') {
|
if (dockSide === 'off') {
|
||||||
this.hostApp.setAlwaysOnTop(false)
|
this.hostApp.setAlwaysOnTop(false)
|
||||||
@@ -34,9 +34,9 @@ export class DockingService {
|
|||||||
display = this.getCurrentScreen()
|
display = this.getCurrentScreen()
|
||||||
}
|
}
|
||||||
|
|
||||||
let newBounds: Bounds = { x: 0, y: 0, width: 0, height: 0 }
|
const newBounds: Bounds = { x: 0, y: 0, width: 0, height: 0 }
|
||||||
let fill = this.config.store.appearance.dockFill
|
const fill = this.config.store.appearance.dockFill
|
||||||
let [minWidth, minHeight] = this.hostApp.getWindow().getMinimumSize()
|
const [minWidth, minHeight] = this.hostApp.getWindow().getMinimumSize()
|
||||||
|
|
||||||
if (dockSide === 'left' || dockSide === 'right') {
|
if (dockSide === 'left' || dockSide === 'right') {
|
||||||
newBounds.width = Math.max(minWidth, Math.round(fill * display.bounds.width))
|
newBounds.width = Math.max(minWidth, Math.round(fill * display.bounds.width))
|
||||||
@@ -80,14 +80,14 @@ export class DockingService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private repositionWindow () {
|
private repositionWindow () {
|
||||||
let [x, y] = this.hostApp.getWindow().getPosition()
|
const [x, y] = this.hostApp.getWindow().getPosition()
|
||||||
for (let screen of this.electron.screen.getAllDisplays()) {
|
for (const screen of this.electron.screen.getAllDisplays()) {
|
||||||
let bounds = screen.bounds
|
const bounds = screen.bounds
|
||||||
if (x >= bounds.x && x <= bounds.x + bounds.width && y >= bounds.y && y <= bounds.y + bounds.height) {
|
if (x >= bounds.x && x <= bounds.x + bounds.width && y >= bounds.y && y <= bounds.y + bounds.height) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let screen = this.electron.screen.getPrimaryDisplay()
|
const screen = this.electron.screen.getPrimaryDisplay()
|
||||||
this.hostApp.getWindow().setPosition(screen.bounds.x, screen.bounds.y)
|
this.hostApp.getWindow().setPosition(screen.bounds.x, screen.bounds.y)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -29,12 +29,12 @@ export class HomeBaseService {
|
|||||||
reportBug () {
|
reportBug () {
|
||||||
let body = `Version: ${this.appVersion}\n`
|
let body = `Version: ${this.appVersion}\n`
|
||||||
body += `Platform: ${os.platform()} ${os.release()}\n`
|
body += `Platform: ${os.platform()} ${os.release()}\n`
|
||||||
let label = {
|
const label = {
|
||||||
darwin: 'OS: macOS',
|
darwin: 'OS: macOS',
|
||||||
windows: 'OS: Windows',
|
windows: 'OS: Windows',
|
||||||
linux: 'OS: Linux',
|
linux: 'OS: Linux',
|
||||||
}[os.platform()]
|
}[os.platform()]
|
||||||
let plugins = (window as any).installedPlugins.filter(x => !x.isBuiltin).map(x => x.name)
|
const plugins = (window as any).installedPlugins.filter(x => !x.isBuiltin).map(x => x.name)
|
||||||
body += `Plugins: ${plugins.join(', ') || 'none'}\n\n`
|
body += `Plugins: ${plugins.join(', ') || 'none'}\n\n`
|
||||||
this.electron.shell.openExternal(`https://github.com/eugeny/terminus/issues/new?body=${encodeURIComponent(body)}&labels=${label}`)
|
this.electron.shell.openExternal(`https://github.com/eugeny/terminus/issues/new?body=${encodeURIComponent(body)}&labels=${label}`)
|
||||||
}
|
}
|
||||||
|
@@ -170,7 +170,7 @@ export class HostAppService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
toggleFullscreen () {
|
toggleFullscreen () {
|
||||||
let window = this.getWindow()
|
const window = this.getWindow()
|
||||||
window.setFullScreen(!this.isFullScreen)
|
window.setFullScreen(!this.isFullScreen)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
import { Injectable, Inject, NgZone, EventEmitter } from '@angular/core'
|
import { Injectable, Inject, NgZone, EventEmitter } from '@angular/core'
|
||||||
import { IHotkeyDescription, HotkeyProvider } from '../api/hotkeyProvider'
|
import { IHotkeyDescription, HotkeyProvider } from '../api/hotkeyProvider'
|
||||||
import { NativeKeyEvent, stringifyKeySequence } from './hotkeys.util'
|
import { stringifyKeySequence } from './hotkeys.util'
|
||||||
import { ConfigService } from '../services/config.service'
|
import { ConfigService } from '../services/config.service'
|
||||||
import { ElectronService } from '../services/electron.service'
|
import { ElectronService } from '../services/electron.service'
|
||||||
|
|
||||||
@@ -13,13 +13,13 @@ export interface PartialHotkeyMatch {
|
|||||||
const KEY_TIMEOUT = 2000
|
const KEY_TIMEOUT = 2000
|
||||||
|
|
||||||
interface EventBufferEntry {
|
interface EventBufferEntry {
|
||||||
event: NativeKeyEvent
|
event: KeyboardEvent
|
||||||
time: number
|
time: number
|
||||||
}
|
}
|
||||||
|
|
||||||
@Injectable({ providedIn: 'root' })
|
@Injectable({ providedIn: 'root' })
|
||||||
export class HotkeysService {
|
export class HotkeysService {
|
||||||
key = new EventEmitter<NativeKeyEvent>()
|
key = new EventEmitter<KeyboardEvent>()
|
||||||
matchedHotkey = new EventEmitter<string>()
|
matchedHotkey = new EventEmitter<string>()
|
||||||
globalHotkey = new EventEmitter()
|
globalHotkey = new EventEmitter()
|
||||||
private currentKeystrokes: EventBufferEntry[] = []
|
private currentKeystrokes: EventBufferEntry[] = []
|
||||||
@@ -33,9 +33,9 @@ export class HotkeysService {
|
|||||||
private config: ConfigService,
|
private config: ConfigService,
|
||||||
@Inject(HotkeyProvider) private hotkeyProviders: HotkeyProvider[],
|
@Inject(HotkeyProvider) private hotkeyProviders: HotkeyProvider[],
|
||||||
) {
|
) {
|
||||||
let events = ['keydown', 'keyup']
|
const events = ['keydown', 'keyup']
|
||||||
events.forEach((event) => {
|
events.forEach(event => {
|
||||||
document.addEventListener(event, (nativeEvent) => {
|
document.addEventListener(event, (nativeEvent: KeyboardEvent) => {
|
||||||
if (document.querySelectorAll('input:focus').length === 0) {
|
if (document.querySelectorAll('input:focus').length === 0) {
|
||||||
this.pushKeystroke(event, nativeEvent)
|
this.pushKeystroke(event, nativeEvent)
|
||||||
this.processKeystrokes()
|
this.processKeystrokes()
|
||||||
@@ -58,8 +58,8 @@ export class HotkeysService {
|
|||||||
* @param name DOM event name
|
* @param name DOM event name
|
||||||
* @param nativeEvent event object
|
* @param nativeEvent event object
|
||||||
*/
|
*/
|
||||||
pushKeystroke (name, nativeEvent) {
|
pushKeystroke (name: string, nativeEvent: KeyboardEvent) {
|
||||||
nativeEvent.event = name
|
(nativeEvent as any).event = name
|
||||||
this.currentKeystrokes.push({ event: nativeEvent, time: performance.now() })
|
this.currentKeystrokes.push({ event: nativeEvent, time: performance.now() })
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -69,7 +69,7 @@ export class HotkeysService {
|
|||||||
processKeystrokes () {
|
processKeystrokes () {
|
||||||
if (this.isEnabled()) {
|
if (this.isEnabled()) {
|
||||||
this.zone.run(() => {
|
this.zone.run(() => {
|
||||||
let matched = this.getCurrentFullyMatchedHotkey()
|
const matched = this.getCurrentFullyMatchedHotkey()
|
||||||
if (matched) {
|
if (matched) {
|
||||||
console.log('Matched hotkey', matched)
|
console.log('Matched hotkey', matched)
|
||||||
this.matchedHotkey.emit(matched)
|
this.matchedHotkey.emit(matched)
|
||||||
@@ -79,7 +79,7 @@ export class HotkeysService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
emitKeyEvent (nativeEvent) {
|
emitKeyEvent (nativeEvent: KeyboardEvent) {
|
||||||
this.zone.run(() => {
|
this.zone.run(() => {
|
||||||
this.key.emit(nativeEvent)
|
this.key.emit(nativeEvent)
|
||||||
})
|
})
|
||||||
@@ -100,7 +100,7 @@ export class HotkeysService {
|
|||||||
if (typeof value === 'string') {
|
if (typeof value === 'string') {
|
||||||
value = [value]
|
value = [value]
|
||||||
}
|
}
|
||||||
value.forEach(item => {
|
value.forEach((item: string | string[]) => {
|
||||||
item = (typeof item === 'string') ? [item] : item
|
item = (typeof item === 'string') ? [item] : item
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@@ -121,13 +121,13 @@ export class HotkeysService {
|
|||||||
return this.getHotkeysConfigRecursive(this.config.store.hotkeys)
|
return this.getHotkeysConfigRecursive(this.config.store.hotkeys)
|
||||||
}
|
}
|
||||||
|
|
||||||
private getHotkeysConfigRecursive (branch) {
|
private getHotkeysConfigRecursive (branch: any) {
|
||||||
let keys = {}
|
const keys = {}
|
||||||
for (let key in branch) {
|
for (const key in branch) {
|
||||||
let value = branch[key]
|
let value = branch[key]
|
||||||
if (value instanceof Object && !(value instanceof Array)) {
|
if (value instanceof Object && !(value instanceof Array)) {
|
||||||
let subkeys = this.getHotkeysConfigRecursive(value)
|
const subkeys = this.getHotkeysConfigRecursive(value)
|
||||||
for (let subkey in subkeys) {
|
for (const subkey in subkeys) {
|
||||||
keys[key + '.' + subkey] = subkeys[subkey]
|
keys[key + '.' + subkey] = subkeys[subkey]
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -135,7 +135,7 @@ export class HotkeysService {
|
|||||||
value = [value]
|
value = [value]
|
||||||
}
|
}
|
||||||
if (value) {
|
if (value) {
|
||||||
value = value.map(item => (typeof item === 'string') ? [item] : item)
|
value = value.map((item: string | string[]) => (typeof item === 'string') ? [item] : item)
|
||||||
keys[key] = value
|
keys[key] = value
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -144,15 +144,15 @@ export class HotkeysService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private getCurrentFullyMatchedHotkey (): string {
|
private getCurrentFullyMatchedHotkey (): string {
|
||||||
let currentStrokes = this.getCurrentKeystrokes()
|
const currentStrokes = this.getCurrentKeystrokes()
|
||||||
let config = this.getHotkeysConfig()
|
const config = this.getHotkeysConfig()
|
||||||
for (let id in config) {
|
for (const id in config) {
|
||||||
for (let sequence of config[id]) {
|
for (const sequence of config[id]) {
|
||||||
if (currentStrokes.length < sequence.length) {
|
if (currentStrokes.length < sequence.length) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if (sequence.every(
|
if (sequence.every(
|
||||||
(x, index) =>
|
(x: string, index: number) =>
|
||||||
x.toLowerCase() ===
|
x.toLowerCase() ===
|
||||||
currentStrokes[currentStrokes.length - sequence.length + index].toLowerCase()
|
currentStrokes[currentStrokes.length - sequence.length + index].toLowerCase()
|
||||||
)) {
|
)) {
|
||||||
@@ -164,14 +164,14 @@ export class HotkeysService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
getCurrentPartiallyMatchedHotkeys (): PartialHotkeyMatch[] {
|
getCurrentPartiallyMatchedHotkeys (): PartialHotkeyMatch[] {
|
||||||
let currentStrokes = this.getCurrentKeystrokes()
|
const currentStrokes = this.getCurrentKeystrokes()
|
||||||
let config = this.getHotkeysConfig()
|
const config = this.getHotkeysConfig()
|
||||||
let result = []
|
const result = []
|
||||||
for (let id in config) {
|
for (const id in config) {
|
||||||
for (let sequence of config[id]) {
|
for (const sequence of config[id]) {
|
||||||
for (let matchLength = Math.min(currentStrokes.length, sequence.length); matchLength > 0; matchLength--) {
|
for (let matchLength = Math.min(currentStrokes.length, sequence.length); matchLength > 0; matchLength--) {
|
||||||
if (sequence.slice(0, matchLength).every(
|
if (sequence.slice(0, matchLength).every(
|
||||||
(x, index) =>
|
(x: string, index: number) =>
|
||||||
x.toLowerCase() ===
|
x.toLowerCase() ===
|
||||||
currentStrokes[currentStrokes.length - matchLength + index].toLowerCase()
|
currentStrokes[currentStrokes.length - matchLength + index].toLowerCase()
|
||||||
)) {
|
)) {
|
||||||
|
@@ -10,24 +10,14 @@ export const altKeyName = {
|
|||||||
linux: 'Alt',
|
linux: 'Alt',
|
||||||
}[process.platform]
|
}[process.platform]
|
||||||
|
|
||||||
export interface NativeKeyEvent {
|
export function stringifyKeySequence (events: KeyboardEvent[]): string[] {
|
||||||
event?: string
|
const items: string[] = []
|
||||||
altKey: boolean
|
|
||||||
ctrlKey: boolean
|
|
||||||
metaKey: boolean
|
|
||||||
shiftKey: boolean
|
|
||||||
key: string
|
|
||||||
keyCode: string
|
|
||||||
}
|
|
||||||
|
|
||||||
export function stringifyKeySequence (events: NativeKeyEvent[]): string[] {
|
|
||||||
let items: string[] = []
|
|
||||||
events = events.slice()
|
events = events.slice()
|
||||||
|
|
||||||
while (events.length > 0) {
|
while (events.length > 0) {
|
||||||
let event = events.shift()
|
const event = events.shift()
|
||||||
if (event.event === 'keydown') {
|
if ((event as any).event === 'keydown') {
|
||||||
let itemKeys: string[] = []
|
const itemKeys: string[] = []
|
||||||
if (event.ctrlKey) {
|
if (event.ctrlKey) {
|
||||||
itemKeys.push('Ctrl')
|
itemKeys.push('Ctrl')
|
||||||
}
|
}
|
||||||
@@ -46,7 +36,7 @@ export function stringifyKeySequence (events: NativeKeyEvent[]): string[] {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
let key = (event as any).code
|
let key = event.code
|
||||||
key = key.replace('Key', '')
|
key = key.replace('Key', '')
|
||||||
key = key.replace('Arrow', '')
|
key = key.replace('Arrow', '')
|
||||||
key = key.replace('Digit', '')
|
key = key.replace('Digit', '')
|
||||||
|
@@ -61,11 +61,11 @@ export class ShellIntegrationService {
|
|||||||
async install () {
|
async install () {
|
||||||
const exe = process.env.PORTABLE_EXECUTABLE_FILE || this.electron.app.getPath('exe')
|
const exe = process.env.PORTABLE_EXECUTABLE_FILE || this.electron.app.getPath('exe')
|
||||||
if (this.hostApp.platform === Platform.macOS) {
|
if (this.hostApp.platform === Platform.macOS) {
|
||||||
for (let wf of this.automatorWorkflows) {
|
for (const wf of this.automatorWorkflows) {
|
||||||
await exec(`cp -r "${this.automatorWorkflowsLocation}/${wf}" "${this.automatorWorkflowsDestination}"`)
|
await exec(`cp -r "${this.automatorWorkflowsLocation}/${wf}" "${this.automatorWorkflowsDestination}"`)
|
||||||
}
|
}
|
||||||
} else if (this.hostApp.platform === Platform.Windows) {
|
} else if (this.hostApp.platform === Platform.Windows) {
|
||||||
for (let registryKey of this.registryKeys) {
|
for (const registryKey of this.registryKeys) {
|
||||||
wnr.createRegistryKey(wnr.HK.CU, registryKey.path)
|
wnr.createRegistryKey(wnr.HK.CU, registryKey.path)
|
||||||
wnr.createRegistryKey(wnr.HK.CU, registryKey.path + '\\command')
|
wnr.createRegistryKey(wnr.HK.CU, registryKey.path + '\\command')
|
||||||
wnr.setRegistryValue(wnr.HK.CU, registryKey.path, 'Icon', wnr.REG.SZ, exe)
|
wnr.setRegistryValue(wnr.HK.CU, registryKey.path, 'Icon', wnr.REG.SZ, exe)
|
||||||
@@ -76,11 +76,11 @@ export class ShellIntegrationService {
|
|||||||
|
|
||||||
async remove () {
|
async remove () {
|
||||||
if (this.hostApp.platform === Platform.macOS) {
|
if (this.hostApp.platform === Platform.macOS) {
|
||||||
for (let wf of this.automatorWorkflows) {
|
for (const wf of this.automatorWorkflows) {
|
||||||
await exec(`rm -rf "${this.automatorWorkflowsDestination}/${wf}"`)
|
await exec(`rm -rf "${this.automatorWorkflowsDestination}/${wf}"`)
|
||||||
}
|
}
|
||||||
} else if (this.hostApp.platform === Platform.Windows) {
|
} else if (this.hostApp.platform === Platform.Windows) {
|
||||||
for (let registryKey of this.registryKeys) {
|
for (const registryKey of this.registryKeys) {
|
||||||
wnr.deleteRegistryKey(wnr.HK.CU, registryKey.path)
|
wnr.deleteRegistryKey(wnr.HK.CU, registryKey.path)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -28,9 +28,9 @@ export class TabRecoveryService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async recoverTab (token: any): Promise<RecoveredTab> {
|
async recoverTab (token: any): Promise<RecoveredTab> {
|
||||||
for (let provider of this.config.enabledServices(this.tabRecoveryProviders)) {
|
for (const provider of this.config.enabledServices(this.tabRecoveryProviders)) {
|
||||||
try {
|
try {
|
||||||
let tab = await provider.recover(token)
|
const tab = await provider.recover(token)
|
||||||
if (tab) {
|
if (tab) {
|
||||||
return tab
|
return tab
|
||||||
}
|
}
|
||||||
@@ -43,9 +43,9 @@ export class TabRecoveryService {
|
|||||||
|
|
||||||
async recoverTabs (): Promise<RecoveredTab[]> {
|
async recoverTabs (): Promise<RecoveredTab[]> {
|
||||||
if (window.localStorage.tabsRecovery) {
|
if (window.localStorage.tabsRecovery) {
|
||||||
let tabs: RecoveredTab[] = []
|
const tabs: RecoveredTab[] = []
|
||||||
for (let token of JSON.parse(window.localStorage.tabsRecovery)) {
|
for (const token of JSON.parse(window.localStorage.tabsRecovery)) {
|
||||||
let tab = await this.recoverTab(token)
|
const tab = await this.recoverTab(token)
|
||||||
if (tab) {
|
if (tab) {
|
||||||
tabs.push(tab)
|
tabs.push(tab)
|
||||||
}
|
}
|
||||||
|
@@ -17,9 +17,9 @@ export class TabsService {
|
|||||||
* Instantiates a tab component and assigns given inputs
|
* Instantiates a tab component and assigns given inputs
|
||||||
*/
|
*/
|
||||||
create (type: TabComponentType, inputs?: any): BaseTabComponent {
|
create (type: TabComponentType, inputs?: any): BaseTabComponent {
|
||||||
let componentFactory = this.componentFactoryResolver.resolveComponentFactory(type)
|
const componentFactory = this.componentFactoryResolver.resolveComponentFactory(type)
|
||||||
let componentRef = componentFactory.create(this.injector)
|
const componentRef = componentFactory.create(this.injector)
|
||||||
let tab = componentRef.instance
|
const tab = componentRef.instance
|
||||||
tab.hostView = componentRef.hostView
|
tab.hostView = componentRef.hostView
|
||||||
Object.assign(tab, inputs || {})
|
Object.assign(tab, inputs || {})
|
||||||
return tab
|
return tab
|
||||||
@@ -29,11 +29,11 @@ export class TabsService {
|
|||||||
* Duplicates an existing tab instance (using the tab recovery system)
|
* Duplicates an existing tab instance (using the tab recovery system)
|
||||||
*/
|
*/
|
||||||
async duplicate (tab: BaseTabComponent): Promise<BaseTabComponent> {
|
async duplicate (tab: BaseTabComponent): Promise<BaseTabComponent> {
|
||||||
let token = await tab.getRecoveryToken()
|
const token = await tab.getRecoveryToken()
|
||||||
if (!token) {
|
if (!token) {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
let dup = await this.tabRecovery.recoverTab(token)
|
const dup = await this.tabRecovery.recoverTab(token)
|
||||||
if (dup) {
|
if (dup) {
|
||||||
return this.create(dup.type, dup.options)
|
return this.create(dup.type, dup.options)
|
||||||
}
|
}
|
||||||
|
@@ -28,19 +28,19 @@ export class TouchbarService {
|
|||||||
app.tabsChanged$.subscribe(() => this.updateTabs())
|
app.tabsChanged$.subscribe(() => this.updateTabs())
|
||||||
app.activeTabChange$.subscribe(() => this.updateTabs())
|
app.activeTabChange$.subscribe(() => this.updateTabs())
|
||||||
|
|
||||||
let activityIconPath = `${electron.app.getAppPath()}/assets/activity.png`
|
const activityIconPath = `${electron.app.getAppPath()}/assets/activity.png`
|
||||||
let activityIcon = this.electron.nativeImage.createFromPath(activityIconPath)
|
const activityIcon = this.electron.nativeImage.createFromPath(activityIconPath)
|
||||||
app.tabOpened$.subscribe(tab => {
|
app.tabOpened$.subscribe(tab => {
|
||||||
tab.titleChange$.subscribe(title => {
|
tab.titleChange$.subscribe(title => {
|
||||||
let segment = this.tabSegments[app.tabs.indexOf(tab)]
|
const segment = this.tabSegments[app.tabs.indexOf(tab)]
|
||||||
if (segment) {
|
if (segment) {
|
||||||
segment.label = this.shortenTitle(title)
|
segment.label = this.shortenTitle(title)
|
||||||
this.tabsSegmentedControl.segments = this.tabSegments
|
this.tabsSegmentedControl.segments = this.tabSegments
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
tab.activity$.subscribe(hasActivity => {
|
tab.activity$.subscribe(hasActivity => {
|
||||||
let showIcon = this.app.activeTab !== tab && hasActivity
|
const showIcon = this.app.activeTab !== tab && hasActivity
|
||||||
let segment = this.tabSegments[app.tabs.indexOf(tab)]
|
const segment = this.tabSegments[app.tabs.indexOf(tab)]
|
||||||
if (segment) {
|
if (segment) {
|
||||||
segment.icon = showIcon ? activityIcon : null
|
segment.icon = showIcon ? activityIcon : null
|
||||||
}
|
}
|
||||||
@@ -87,7 +87,7 @@ export class TouchbarService {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
let touchBar = new this.electron.TouchBar({
|
const touchBar = new this.electron.TouchBar({
|
||||||
items: [
|
items: [
|
||||||
this.tabsSegmentedControl,
|
this.tabsSegmentedControl,
|
||||||
new this.electron.TouchBar.TouchBarSpacer({ size: 'flexible' }),
|
new this.electron.TouchBar.TouchBarSpacer({ size: 'flexible' }),
|
||||||
|
@@ -49,9 +49,9 @@ export class UpdaterService {
|
|||||||
async check (): Promise<boolean> {
|
async check (): Promise<boolean> {
|
||||||
if (!this.electronUpdaterAvailable) {
|
if (!this.electronUpdaterAvailable) {
|
||||||
this.logger.debug('Checking for updates')
|
this.logger.debug('Checking for updates')
|
||||||
let response = await axios.get(UPDATES_URL)
|
const response = await axios.get(UPDATES_URL)
|
||||||
let data = response.data
|
const data = response.data
|
||||||
let version = data.tag_name.substring(1)
|
const version = data.tag_name.substring(1)
|
||||||
if (this.electron.app.getVersion() !== version) {
|
if (this.electron.app.getVersion() !== version) {
|
||||||
this.logger.info('Update available')
|
this.logger.info('Update available')
|
||||||
this.updateURL = data.html_url
|
this.updateURL = data.html_url
|
||||||
|
@@ -27,7 +27,7 @@ export class CloseContextMenu extends TabContextMenuItemProvider {
|
|||||||
{
|
{
|
||||||
label: 'Close other tabs',
|
label: 'Close other tabs',
|
||||||
click: () => this.zone.run(() => {
|
click: () => this.zone.run(() => {
|
||||||
for (let t of this.app.tabs.filter(x => x !== tab)) {
|
for (const t of this.app.tabs.filter(x => x !== tab)) {
|
||||||
this.app.closeTab(t, true)
|
this.app.closeTab(t, true)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@@ -35,7 +35,7 @@ export class CloseContextMenu extends TabContextMenuItemProvider {
|
|||||||
{
|
{
|
||||||
label: 'Close tabs to the right',
|
label: 'Close tabs to the right',
|
||||||
click: () => this.zone.run(() => {
|
click: () => this.zone.run(() => {
|
||||||
for (let t of this.app.tabs.slice(this.app.tabs.indexOf(tab) + 1)) {
|
for (const t of this.app.tabs.slice(this.app.tabs.indexOf(tab) + 1)) {
|
||||||
this.app.closeTab(t, true)
|
this.app.closeTab(t, true)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@@ -43,7 +43,7 @@ export class CloseContextMenu extends TabContextMenuItemProvider {
|
|||||||
{
|
{
|
||||||
label: 'Close tabs to the left',
|
label: 'Close tabs to the left',
|
||||||
click: () => this.zone.run(() => {
|
click: () => this.zone.run(() => {
|
||||||
for (let t of this.app.tabs.slice(0, this.app.tabs.indexOf(tab))) {
|
for (const t of this.app.tabs.slice(0, this.app.tabs.indexOf(tab))) {
|
||||||
this.app.closeTab(t, true)
|
this.app.closeTab(t, true)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@@ -111,7 +111,7 @@ export class TaskCompletionContextMenu extends TabContextMenuItemProvider {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async getItems (tab: BaseTabComponent): Promise<Electron.MenuItemConstructorOptions[]> {
|
async getItems (tab: BaseTabComponent): Promise<Electron.MenuItemConstructorOptions[]> {
|
||||||
let process = await tab.getCurrentProcess()
|
const process = await tab.getCurrentProcess()
|
||||||
if (process) {
|
if (process) {
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
|
@@ -2,6 +2,6 @@
|
|||||||
"extends": "../tsconfig.json",
|
"extends": "../tsconfig.json",
|
||||||
"exclude": ["node_modules", "dist"],
|
"exclude": ["node_modules", "dist"],
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"baseUrl": "src",
|
"baseUrl": "src"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -44,7 +44,7 @@ export class PluginsSettingsTabComponent {
|
|||||||
})
|
})
|
||||||
)
|
)
|
||||||
this.availablePlugins$.pipe(first()).subscribe(available => {
|
this.availablePlugins$.pipe(first()).subscribe(available => {
|
||||||
for (let plugin of this.pluginManager.installedPlugins) {
|
for (const plugin of this.pluginManager.installedPlugins) {
|
||||||
this.knownUpgrades[plugin.name] = available.find(x => x.name === plugin.name && semver.gt(x.version, plugin.version))
|
this.knownUpgrades[plugin.name] = available.find(x => x.name === plugin.name && semver.gt(x.version, plugin.version))
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@@ -34,7 +34,7 @@ export class ButtonProvider extends ToolbarButtonProvider {
|
|||||||
}
|
}
|
||||||
|
|
||||||
open (): void {
|
open (): void {
|
||||||
let settingsTab = this.app.tabs.find(tab => tab instanceof SettingsTabComponent)
|
const settingsTab = this.app.tabs.find(tab => tab instanceof SettingsTabComponent)
|
||||||
if (settingsTab) {
|
if (settingsTab) {
|
||||||
this.app.selectTab(settingsTab)
|
this.app.selectTab(settingsTab)
|
||||||
} else {
|
} else {
|
||||||
|
@@ -124,7 +124,7 @@ export class SettingsTabComponent extends BaseTabComponent {
|
|||||||
|
|
||||||
getHotkey (id: string) {
|
getHotkey (id: string) {
|
||||||
let ptr = this.config.store.hotkeys
|
let ptr = this.config.store.hotkeys
|
||||||
for (let token of id.split(/\./g)) {
|
for (const token of id.split(/\./g)) {
|
||||||
ptr = ptr[token]
|
ptr = ptr[token]
|
||||||
}
|
}
|
||||||
return ptr
|
return ptr
|
||||||
@@ -133,7 +133,7 @@ export class SettingsTabComponent extends BaseTabComponent {
|
|||||||
setHotkey (id: string, value) {
|
setHotkey (id: string, value) {
|
||||||
let ptr = this.config.store
|
let ptr = this.config.store
|
||||||
let prop = 'hotkeys'
|
let prop = 'hotkeys'
|
||||||
for (let token of id.split(/\./g)) {
|
for (const token of id.split(/\./g)) {
|
||||||
ptr = ptr[prop]
|
ptr = ptr[prop]
|
||||||
prop = token
|
prop = token
|
||||||
}
|
}
|
||||||
|
@@ -43,16 +43,16 @@ export class SSHSession extends BaseSession {
|
|||||||
this.open = true
|
this.open = true
|
||||||
|
|
||||||
this.shell.on('data', data => {
|
this.shell.on('data', data => {
|
||||||
let dataString = data.toString()
|
const dataString = data.toString()
|
||||||
this.emitOutput(dataString)
|
this.emitOutput(dataString)
|
||||||
|
|
||||||
if (this.scripts) {
|
if (this.scripts) {
|
||||||
let found = false
|
let found = false
|
||||||
for (let script of this.scripts) {
|
for (const script of this.scripts) {
|
||||||
let match = false
|
let match = false
|
||||||
let cmd = ''
|
let cmd = ''
|
||||||
if (script.isRegex) {
|
if (script.isRegex) {
|
||||||
let re = new RegExp(script.expect, 'g')
|
const re = new RegExp(script.expect, 'g')
|
||||||
if (dataString.match(re)) {
|
if (dataString.match(re)) {
|
||||||
cmd = dataString.replace(re, script.send)
|
cmd = dataString.replace(re, script.send)
|
||||||
match = true
|
match = true
|
||||||
@@ -128,7 +128,7 @@ export class SSHSession extends BaseSession {
|
|||||||
|
|
||||||
private executeUnconditionalScripts () {
|
private executeUnconditionalScripts () {
|
||||||
if (this.scripts) {
|
if (this.scripts) {
|
||||||
for (let script of this.scripts) {
|
for (const script of this.scripts) {
|
||||||
if (!script.expect) {
|
if (!script.expect) {
|
||||||
console.log('Executing script:', script.send)
|
console.log('Executing script:', script.send)
|
||||||
this.shell.write(script.send + '\n')
|
this.shell.write(script.send + '\n')
|
||||||
|
@@ -26,7 +26,7 @@ export class EditConnectionModalComponent {
|
|||||||
) {
|
) {
|
||||||
this.newScript = { expect: '', send: '' }
|
this.newScript = { expect: '', send: '' }
|
||||||
|
|
||||||
for (let k of Object.values(SSHAlgorithmType)) {
|
for (const k of Object.values(SSHAlgorithmType)) {
|
||||||
this.supportedAlgorithms[k] = ALGORITHMS[{
|
this.supportedAlgorithms[k] = ALGORITHMS[{
|
||||||
[SSHAlgorithmType.KEX]: 'SUPPORTED_KEX',
|
[SSHAlgorithmType.KEX]: 'SUPPORTED_KEX',
|
||||||
[SSHAlgorithmType.HOSTKEY]: 'SUPPORTED_SERVER_HOST_KEY',
|
[SSHAlgorithmType.HOSTKEY]: 'SUPPORTED_SERVER_HOST_KEY',
|
||||||
@@ -45,13 +45,13 @@ export class EditConnectionModalComponent {
|
|||||||
async ngOnInit () {
|
async ngOnInit () {
|
||||||
this.hasSavedPassword = !!(await this.passwordStorage.loadPassword(this.connection))
|
this.hasSavedPassword = !!(await this.passwordStorage.loadPassword(this.connection))
|
||||||
this.connection.algorithms = this.connection.algorithms || {}
|
this.connection.algorithms = this.connection.algorithms || {}
|
||||||
for (let k of Object.values(SSHAlgorithmType)) {
|
for (const k of Object.values(SSHAlgorithmType)) {
|
||||||
if (!this.connection.algorithms[k]) {
|
if (!this.connection.algorithms[k]) {
|
||||||
this.connection.algorithms[k] = this.defaultAlgorithms[k]
|
this.connection.algorithms[k] = this.defaultAlgorithms[k]
|
||||||
}
|
}
|
||||||
|
|
||||||
this.algorithms[k] = {}
|
this.algorithms[k] = {}
|
||||||
for (let alg of this.connection.algorithms[k]) {
|
for (const alg of this.connection.algorithms[k]) {
|
||||||
this.algorithms[k][alg] = true
|
this.algorithms[k][alg] = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -63,7 +63,7 @@ export class EditConnectionModalComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
selectPrivateKey () {
|
selectPrivateKey () {
|
||||||
let path = this.electron.dialog.showOpenDialog(
|
const path = this.electron.dialog.showOpenDialog(
|
||||||
this.hostApp.getWindow(),
|
this.hostApp.getWindow(),
|
||||||
{
|
{
|
||||||
title: 'Select private key',
|
title: 'Select private key',
|
||||||
@@ -75,7 +75,7 @@ export class EditConnectionModalComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
save () {
|
save () {
|
||||||
for (let k of Object.values(SSHAlgorithmType)) {
|
for (const k of Object.values(SSHAlgorithmType)) {
|
||||||
this.connection.algorithms[k] = Object.entries(this.algorithms[k])
|
this.connection.algorithms[k] = Object.entries(this.algorithms[k])
|
||||||
.filter(([k, v]) => !!v)
|
.filter(([k, v]) => !!v)
|
||||||
.map(([k, v]) => k)
|
.map(([k, v]) => k)
|
||||||
@@ -88,7 +88,7 @@ export class EditConnectionModalComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
moveScriptUp (script: LoginScript) {
|
moveScriptUp (script: LoginScript) {
|
||||||
let index = this.connection.scripts.indexOf(script)
|
const index = this.connection.scripts.indexOf(script)
|
||||||
if (index > 0) {
|
if (index > 0) {
|
||||||
this.connection.scripts.splice(index, 1)
|
this.connection.scripts.splice(index, 1)
|
||||||
this.connection.scripts.splice(index - 1, 0, script)
|
this.connection.scripts.splice(index - 1, 0, script)
|
||||||
@@ -96,7 +96,7 @@ export class EditConnectionModalComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
moveScriptDown (script: LoginScript) {
|
moveScriptDown (script: LoginScript) {
|
||||||
let index = this.connection.scripts.indexOf(script)
|
const index = this.connection.scripts.indexOf(script)
|
||||||
if (index >= 0 && index < this.connection.scripts.length - 1) {
|
if (index >= 0 && index < this.connection.scripts.length - 1) {
|
||||||
this.connection.scripts.splice(index, 1)
|
this.connection.scripts.splice(index, 1)
|
||||||
this.connection.scripts.splice(index + 1, 0, script)
|
this.connection.scripts.splice(index + 1, 0, script)
|
||||||
|
@@ -47,7 +47,7 @@ export class SSHModalComponent {
|
|||||||
host = host.split(':')[0]
|
host = host.split(':')[0]
|
||||||
}
|
}
|
||||||
|
|
||||||
let connection: SSHConnection = {
|
const connection: SSHConnection = {
|
||||||
name: this.quickTarget,
|
name: this.quickTarget,
|
||||||
host, user, port
|
host, user, port
|
||||||
}
|
}
|
||||||
@@ -88,7 +88,7 @@ export class SSHModalComponent {
|
|||||||
connections = connections.filter(connection => (connection.name + connection.group).toLowerCase().includes(this.quickTarget))
|
connections = connections.filter(connection => (connection.name + connection.group).toLowerCase().includes(this.quickTarget))
|
||||||
}
|
}
|
||||||
|
|
||||||
for (let connection of connections) {
|
for (const connection of connections) {
|
||||||
connection.group = connection.group || null
|
connection.group = connection.group || null
|
||||||
let group = this.childGroups.find(x => x.name === connection.group)
|
let group = this.childGroups.find(x => x.name === connection.group)
|
||||||
if (!group) {
|
if (!group) {
|
||||||
|
@@ -25,14 +25,14 @@ export class SSHSettingsTabComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
createConnection () {
|
createConnection () {
|
||||||
let connection: SSHConnection = {
|
const connection: SSHConnection = {
|
||||||
name: '',
|
name: '',
|
||||||
host: '',
|
host: '',
|
||||||
port: 22,
|
port: 22,
|
||||||
user: 'root',
|
user: 'root',
|
||||||
}
|
}
|
||||||
|
|
||||||
let modal = this.ngbModal.open(EditConnectionModalComponent)
|
const modal = this.ngbModal.open(EditConnectionModalComponent)
|
||||||
modal.componentInstance.connection = connection
|
modal.componentInstance.connection = connection
|
||||||
modal.result.then(result => {
|
modal.result.then(result => {
|
||||||
this.connections.push(result)
|
this.connections.push(result)
|
||||||
@@ -43,7 +43,7 @@ export class SSHSettingsTabComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
editConnection (connection: SSHConnection) {
|
editConnection (connection: SSHConnection) {
|
||||||
let modal = this.ngbModal.open(EditConnectionModalComponent)
|
const modal = this.ngbModal.open(EditConnectionModalComponent)
|
||||||
modal.componentInstance.connection = Object.assign({}, connection)
|
modal.componentInstance.connection = Object.assign({}, connection)
|
||||||
modal.result.then(result => {
|
modal.result.then(result => {
|
||||||
Object.assign(connection, result)
|
Object.assign(connection, result)
|
||||||
@@ -71,12 +71,12 @@ export class SSHSettingsTabComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
editGroup (group: ISSHConnectionGroup) {
|
editGroup (group: ISSHConnectionGroup) {
|
||||||
let modal = this.ngbModal.open(PromptModalComponent)
|
const modal = this.ngbModal.open(PromptModalComponent)
|
||||||
modal.componentInstance.prompt = 'New group name'
|
modal.componentInstance.prompt = 'New group name'
|
||||||
modal.componentInstance.value = group.name
|
modal.componentInstance.value = group.name
|
||||||
modal.result.then(result => {
|
modal.result.then(result => {
|
||||||
if (result) {
|
if (result) {
|
||||||
for (let connection of this.connections.filter(x => x.group === group.name)) {
|
for (const connection of this.connections.filter(x => x.group === group.name)) {
|
||||||
connection.group = result
|
connection.group = result
|
||||||
}
|
}
|
||||||
this.config.store.ssh.connections = this.connections
|
this.config.store.ssh.connections = this.connections
|
||||||
@@ -96,7 +96,7 @@ export class SSHSettingsTabComponent {
|
|||||||
defaultId: 1,
|
defaultId: 1,
|
||||||
}
|
}
|
||||||
)).response === 1) {
|
)).response === 1) {
|
||||||
for (let connection of this.connections.filter(x => x.group === group.name)) {
|
for (const connection of this.connections.filter(x => x.group === group.name)) {
|
||||||
connection.group = null
|
connection.group = null
|
||||||
}
|
}
|
||||||
this.config.save()
|
this.config.save()
|
||||||
@@ -108,7 +108,7 @@ export class SSHSettingsTabComponent {
|
|||||||
this.connections = this.config.store.ssh.connections
|
this.connections = this.config.store.ssh.connections
|
||||||
this.childGroups = []
|
this.childGroups = []
|
||||||
|
|
||||||
for (let connection of this.connections) {
|
for (const connection of this.connections) {
|
||||||
connection.group = connection.group || null
|
connection.group = connection.group || null
|
||||||
let group = this.childGroups.find(x => x.name === connection.group)
|
let group = this.childGroups.find(x => x.name === connection.group)
|
||||||
if (!group) {
|
if (!group) {
|
||||||
|
@@ -44,7 +44,7 @@ export class SSHTabComponent extends BaseTerminalTabComponent {
|
|||||||
this.session = new SSHSession(this.connection)
|
this.session = new SSHSession(this.connection)
|
||||||
this.attachSessionHandlers()
|
this.attachSessionHandlers()
|
||||||
this.write(`Connecting to ${this.connection.host}`)
|
this.write(`Connecting to ${this.connection.host}`)
|
||||||
let interval = setInterval(() => this.write('.'), 500)
|
const interval = setInterval(() => this.write('.'), 500)
|
||||||
try {
|
try {
|
||||||
await this.ssh.connectSession(this.session, message => {
|
await this.ssh.connectSession(this.session, message => {
|
||||||
this.write('\r\n' + message)
|
this.write('\r\n' + message)
|
||||||
|
@@ -55,7 +55,7 @@ export class SSHService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!privateKeyPath) {
|
if (!privateKeyPath) {
|
||||||
let userKeyPath = path.join(process.env.HOME, '.ssh', 'id_rsa')
|
const userKeyPath = path.join(process.env.HOME, '.ssh', 'id_rsa')
|
||||||
if (await fs.exists(userKeyPath)) {
|
if (await fs.exists(userKeyPath)) {
|
||||||
log(`Using user's default private key: ${userKeyPath}`)
|
log(`Using user's default private key: ${userKeyPath}`)
|
||||||
privateKeyPath = userKeyPath
|
privateKeyPath = userKeyPath
|
||||||
@@ -78,7 +78,7 @@ export class SSHService {
|
|||||||
encrypted = encrypted || privateKey.includes('Encryption:') && !privateKey.includes('Encryption: none')
|
encrypted = encrypted || privateKey.includes('Encryption:') && !privateKey.includes('Encryption: none')
|
||||||
}
|
}
|
||||||
if (encrypted) {
|
if (encrypted) {
|
||||||
let modal = this.ngbModal.open(PromptModalComponent)
|
const modal = this.ngbModal.open(PromptModalComponent)
|
||||||
log('Key requires passphrase')
|
log('Key requires passphrase')
|
||||||
modal.componentInstance.prompt = 'Private key passphrase'
|
modal.componentInstance.prompt = 'Private key passphrase'
|
||||||
modal.componentInstance.password = true
|
modal.componentInstance.password = true
|
||||||
@@ -89,7 +89,7 @@ export class SSHService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let ssh = new Client()
|
const ssh = new Client()
|
||||||
let connected = false
|
let connected = false
|
||||||
let savedPassword: string = null
|
let savedPassword: string = null
|
||||||
await new Promise(async (resolve, reject) => {
|
await new Promise(async (resolve, reject) => {
|
||||||
@@ -113,9 +113,9 @@ export class SSHService {
|
|||||||
ssh.on('keyboard-interactive', (name, instructions, instructionsLang, prompts, finish) => this.zone.run(async () => {
|
ssh.on('keyboard-interactive', (name, instructions, instructionsLang, prompts, finish) => this.zone.run(async () => {
|
||||||
log(`Keyboard-interactive auth requested: ${name}`)
|
log(`Keyboard-interactive auth requested: ${name}`)
|
||||||
this.logger.info('Keyboard-interactive auth:', name, instructions, instructionsLang)
|
this.logger.info('Keyboard-interactive auth:', name, instructions, instructionsLang)
|
||||||
let results = []
|
const results = []
|
||||||
for (let prompt of prompts) {
|
for (const prompt of prompts) {
|
||||||
let modal = this.ngbModal.open(PromptModalComponent)
|
const modal = this.ngbModal.open(PromptModalComponent)
|
||||||
modal.componentInstance.prompt = prompt.prompt
|
modal.componentInstance.prompt = prompt.prompt
|
||||||
modal.componentInstance.password = !prompt.echo
|
modal.componentInstance.password = !prompt.echo
|
||||||
results.push(await modal.result)
|
results.push(await modal.result)
|
||||||
@@ -133,7 +133,7 @@ export class SSHService {
|
|||||||
|
|
||||||
let agent: string = null
|
let agent: string = null
|
||||||
if (this.hostApp.platform === Platform.Windows) {
|
if (this.hostApp.platform === Platform.Windows) {
|
||||||
let pageantRunning = new Promise<boolean>(resolve => {
|
const pageantRunning = new Promise<boolean>(resolve => {
|
||||||
windowsProcessTree.getProcessList(list => {
|
windowsProcessTree.getProcessList(list => {
|
||||||
resolve(list.some(x => x.name === 'pageant.exe'))
|
resolve(list.some(x => x.name === 'pageant.exe'))
|
||||||
}, 0)
|
}, 0)
|
||||||
@@ -180,7 +180,7 @@ export class SSHService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!keychainPasswordUsed) {
|
if (!keychainPasswordUsed) {
|
||||||
let password = await this.passwordStorage.loadPassword(session.connection)
|
const password = await this.passwordStorage.loadPassword(session.connection)
|
||||||
if (password) {
|
if (password) {
|
||||||
log('Trying saved password')
|
log('Trying saved password')
|
||||||
keychainPasswordUsed = true
|
keychainPasswordUsed = true
|
||||||
@@ -188,7 +188,7 @@ export class SSHService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let modal = this.ngbModal.open(PromptModalComponent)
|
const modal = this.ngbModal.open(PromptModalComponent)
|
||||||
modal.componentInstance.prompt = `Password for ${session.connection.user}@${session.connection.host}`
|
modal.componentInstance.prompt = `Password for ${session.connection.user}@${session.connection.host}`
|
||||||
modal.componentInstance.password = true
|
modal.componentInstance.password = true
|
||||||
try {
|
try {
|
||||||
@@ -201,7 +201,7 @@ export class SSHService {
|
|||||||
})
|
})
|
||||||
|
|
||||||
try {
|
try {
|
||||||
let shell: any = await new Promise<any>((resolve, reject) => {
|
const shell: any = await new Promise<any>((resolve, reject) => {
|
||||||
ssh.shell({ term: 'xterm-256color' }, (err, shell) => {
|
ssh.shell({ term: 'xterm-256color' }, (err, shell) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
reject(err)
|
reject(err)
|
||||||
|
@@ -211,7 +211,7 @@ export class BaseTerminalTabComponent extends BaseTabComponent implements OnInit
|
|||||||
|
|
||||||
async buildContextMenu (): Promise<Electron.MenuItemConstructorOptions[]> {
|
async buildContextMenu (): Promise<Electron.MenuItemConstructorOptions[]> {
|
||||||
let items: Electron.MenuItemConstructorOptions[] = []
|
let items: Electron.MenuItemConstructorOptions[] = []
|
||||||
for (let section of await Promise.all(this.contextMenuProviders.map(x => x.getItems(this)))) {
|
for (const section of await Promise.all(this.contextMenuProviders.map(x => x.getItems(this)))) {
|
||||||
items = items.concat(section)
|
items = items.concat(section)
|
||||||
items.push({ type: 'separator' })
|
items.push({ type: 'separator' })
|
||||||
}
|
}
|
||||||
@@ -220,7 +220,7 @@ export class BaseTerminalTabComponent extends BaseTabComponent implements OnInit
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected detachTermContainerHandlers () {
|
protected detachTermContainerHandlers () {
|
||||||
for (let subscription of this.termContainerSubscriptions) {
|
for (const subscription of this.termContainerSubscriptions) {
|
||||||
subscription.unsubscribe()
|
subscription.unsubscribe()
|
||||||
}
|
}
|
||||||
this.termContainerSubscriptions = []
|
this.termContainerSubscriptions = []
|
||||||
@@ -277,7 +277,7 @@ export class BaseTerminalTabComponent extends BaseTabComponent implements OnInit
|
|||||||
}
|
}
|
||||||
} else if (event.altKey) {
|
} else if (event.altKey) {
|
||||||
event.preventDefault()
|
event.preventDefault()
|
||||||
let delta = Math.round(wheelDeltaY / 50)
|
const delta = Math.round(wheelDeltaY / 50)
|
||||||
this.sendInput(((delta > 0) ? '\u001bOA' : '\u001bOB').repeat(Math.abs(delta)))
|
this.sendInput(((delta > 0) ? '\u001bOA' : '\u001bOB').repeat(Math.abs(delta)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -316,9 +316,9 @@ export class BaseTerminalTabComponent extends BaseTabComponent implements OnInit
|
|||||||
* Feeds input into the terminal frontend
|
* Feeds input into the terminal frontend
|
||||||
*/
|
*/
|
||||||
write (data: string) {
|
write (data: string) {
|
||||||
let percentageMatch = /(^|[^\d])(\d+(\.\d+)?)%([^\d]|$)/.exec(data)
|
const percentageMatch = /(^|[^\d])(\d+(\.\d+)?)%([^\d]|$)/.exec(data)
|
||||||
if (percentageMatch) {
|
if (percentageMatch) {
|
||||||
let percentage = percentageMatch[3] ? parseFloat(percentageMatch[2]) : parseInt(percentageMatch[2])
|
const percentage = percentageMatch[3] ? parseFloat(percentageMatch[2]) : parseInt(percentageMatch[2])
|
||||||
if (percentage > 0 && percentage <= 100) {
|
if (percentage > 0 && percentage <= 100) {
|
||||||
this.setProgress(percentage)
|
this.setProgress(percentage)
|
||||||
this.logger.debug('Detected progress:', percentage)
|
this.logger.debug('Detected progress:', percentage)
|
||||||
|
@@ -18,8 +18,8 @@ export class ButtonProvider extends ToolbarButtonProvider {
|
|||||||
super()
|
super()
|
||||||
if (!electron.remote.process.env.TERMINUS_DEV) {
|
if (!electron.remote.process.env.TERMINUS_DEV) {
|
||||||
setImmediate(async () => {
|
setImmediate(async () => {
|
||||||
let argv: string[] = electron.remote.process.argv
|
const argv: string[] = electron.remote.process.argv
|
||||||
for (let arg of argv.slice(1).concat([electron.remote.process.argv0])) {
|
for (const arg of argv.slice(1).concat([electron.remote.process.argv0])) {
|
||||||
if (await fs.exists(arg)) {
|
if (await fs.exists(arg)) {
|
||||||
if ((await fs.stat(arg)).isDirectory()) {
|
if ((await fs.stat(arg)).isDirectory()) {
|
||||||
this.terminal.openTab(null, arg)
|
this.terminal.openTab(null, arg)
|
||||||
@@ -44,7 +44,7 @@ export class ButtonProvider extends ToolbarButtonProvider {
|
|||||||
icon: this.domSanitizer.bypassSecurityTrustHtml(require('./icons/profiles.svg')),
|
icon: this.domSanitizer.bypassSecurityTrustHtml(require('./icons/profiles.svg')),
|
||||||
title: 'New terminal with profile',
|
title: 'New terminal with profile',
|
||||||
submenu: async () => {
|
submenu: async () => {
|
||||||
let profiles = await this.terminal.getProfiles()
|
const profiles = await this.terminal.getProfiles()
|
||||||
return profiles.map(profile => ({
|
return profiles.map(profile => ({
|
||||||
icon: profile.icon,
|
icon: profile.icon,
|
||||||
title: profile.name,
|
title: profile.name,
|
||||||
|
@@ -8,15 +8,15 @@ import { ITerminalColorScheme } from './api/interfaces'
|
|||||||
@Injectable()
|
@Injectable()
|
||||||
export class HyperColorSchemes extends TerminalColorSchemeProvider {
|
export class HyperColorSchemes extends TerminalColorSchemeProvider {
|
||||||
async getSchemes (): Promise<ITerminalColorScheme[]> {
|
async getSchemes (): Promise<ITerminalColorScheme[]> {
|
||||||
let pluginsPath = path.join(process.env.HOME, '.hyper_plugins', 'node_modules')
|
const pluginsPath = path.join(process.env.HOME, '.hyper_plugins', 'node_modules')
|
||||||
if (!(await fs.exists(pluginsPath))) return []
|
if (!(await fs.exists(pluginsPath))) return []
|
||||||
let plugins = await fs.readdir(pluginsPath)
|
const plugins = await fs.readdir(pluginsPath)
|
||||||
|
|
||||||
let themes: ITerminalColorScheme[] = []
|
const themes: ITerminalColorScheme[] = []
|
||||||
|
|
||||||
plugins.forEach(plugin => {
|
plugins.forEach(plugin => {
|
||||||
try {
|
try {
|
||||||
let module = (global as any).require(path.join(pluginsPath, plugin))
|
const module = (global as any).require(path.join(pluginsPath, plugin))
|
||||||
if (module.decorateConfig) {
|
if (module.decorateConfig) {
|
||||||
let config: any
|
let config: any
|
||||||
try {
|
try {
|
||||||
|
@@ -31,7 +31,7 @@ export class AppearanceSettingsTabComponent {
|
|||||||
|
|
||||||
async ngOnInit () {
|
async ngOnInit () {
|
||||||
if (this.hostApp.platform === Platform.Windows || this.hostApp.platform === Platform.macOS) {
|
if (this.hostApp.platform === Platform.Windows || this.hostApp.platform === Platform.macOS) {
|
||||||
let fonts = await new Promise<any[]>((resolve) => fontManager.findFonts({ monospace: true }, resolve))
|
const fonts = await new Promise<any[]>((resolve) => fontManager.findFonts({ monospace: true }, resolve))
|
||||||
this.fonts = fonts.map(x => (x.family + ' ' + x.style).trim())
|
this.fonts = fonts.map(x => (x.family + ' ' + x.style).trim())
|
||||||
this.fonts.sort()
|
this.fonts.sort()
|
||||||
}
|
}
|
||||||
|
@@ -29,7 +29,7 @@ export class ColorPickerComponent {
|
|||||||
if (!this.isOpen) {
|
if (!this.isOpen) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
let windowRef = (this.popover as any)._windowRef
|
const windowRef = (this.popover as any)._windowRef
|
||||||
if (!windowRef) {
|
if (!windowRef) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@@ -22,8 +22,8 @@ export class EnvironmentEditorComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
getModel () {
|
getModel () {
|
||||||
let model = {}
|
const model = {}
|
||||||
for (let pair of this.vars) {
|
for (const pair of this.vars) {
|
||||||
model[pair.key] = pair.value
|
model[pair.key] = pair.value
|
||||||
}
|
}
|
||||||
return model
|
return model
|
||||||
|
@@ -51,8 +51,8 @@ export class ShellSettingsTabComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pickWorkingDirectory () {
|
pickWorkingDirectory () {
|
||||||
let shell = this.shells.find(x => x.id === this.config.store.terminal.shell)
|
const shell = this.shells.find(x => x.id === this.config.store.terminal.shell)
|
||||||
let paths = this.electron.dialog.showOpenDialog(
|
const paths = this.electron.dialog.showOpenDialog(
|
||||||
this.hostApp.getWindow(),
|
this.hostApp.getWindow(),
|
||||||
{
|
{
|
||||||
defaultPath: shell.fsBase,
|
defaultPath: shell.fsBase,
|
||||||
@@ -65,7 +65,7 @@ export class ShellSettingsTabComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
newProfile (shell: IShell) {
|
newProfile (shell: IShell) {
|
||||||
let profile: Profile = {
|
const profile: Profile = {
|
||||||
name: shell.name,
|
name: shell.name,
|
||||||
sessionOptions: this.terminalService.optionsFromShell(shell),
|
sessionOptions: this.terminalService.optionsFromShell(shell),
|
||||||
}
|
}
|
||||||
@@ -75,7 +75,7 @@ export class ShellSettingsTabComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
editProfile (profile: Profile) {
|
editProfile (profile: Profile) {
|
||||||
let modal = this.ngbModal.open(EditProfileModalComponent)
|
const modal = this.ngbModal.open(EditProfileModalComponent)
|
||||||
modal.componentInstance.profile = Object.assign({}, profile)
|
modal.componentInstance.profile = Object.assign({}, profile)
|
||||||
modal.result.then(result => {
|
modal.result.then(result => {
|
||||||
Object.assign(profile, result)
|
Object.assign(profile, result)
|
||||||
|
@@ -22,7 +22,7 @@ export class TerminalTabComponent extends BaseTerminalTabComponent {
|
|||||||
this.logger = this.log.create('terminalTab')
|
this.logger = this.log.create('terminalTab')
|
||||||
this.session = new Session(this.config)
|
this.session = new Session(this.config)
|
||||||
|
|
||||||
let isConPTY = isWindowsBuild(WIN_BUILD_CONPTY_SUPPORTED) && this.config.store.terminal.useConPTY
|
const isConPTY = isWindowsBuild(WIN_BUILD_CONPTY_SUPPORTED) && this.config.store.terminal.useConPTY
|
||||||
|
|
||||||
this.homeEndSubscription = this.hotkeys.matchedHotkey.subscribe(hotkey => {
|
this.homeEndSubscription = this.hotkeys.matchedHotkey.subscribe(hotkey => {
|
||||||
if (!this.hasFocus) {
|
if (!this.hasFocus) {
|
||||||
@@ -58,7 +58,7 @@ export class TerminalTabComponent extends BaseTerminalTabComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async getRecoveryToken (): Promise<any> {
|
async getRecoveryToken (): Promise<any> {
|
||||||
let cwd = this.session ? await this.session.getWorkingDirectory() : null
|
const cwd = this.session ? await this.session.getWorkingDirectory() : null
|
||||||
return {
|
return {
|
||||||
type: 'app:terminal-tab',
|
type: 'app:terminal-tab',
|
||||||
sessionOptions: {
|
sessionOptions: {
|
||||||
@@ -69,7 +69,7 @@ export class TerminalTabComponent extends BaseTerminalTabComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async getCurrentProcess (): Promise<BaseTabProcess> {
|
async getCurrentProcess (): Promise<BaseTabProcess> {
|
||||||
let children = await this.session.getChildProcesses()
|
const children = await this.session.getChildProcesses()
|
||||||
if (!children.length) {
|
if (!children.length) {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
@@ -79,7 +79,7 @@ export class TerminalTabComponent extends BaseTerminalTabComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async canClose (): Promise<boolean> {
|
async canClose (): Promise<boolean> {
|
||||||
let children = await this.session.getChildProcesses()
|
const children = await this.session.getChildProcesses()
|
||||||
if (children.length === 0) {
|
if (children.length === 0) {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
@@ -21,9 +21,9 @@ export class NewTabContextMenu extends TerminalContextMenuItemProvider {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async getItems (tab: BaseTerminalTabComponent): Promise<Electron.MenuItemConstructorOptions[]> {
|
async getItems (tab: BaseTerminalTabComponent): Promise<Electron.MenuItemConstructorOptions[]> {
|
||||||
let profiles = await this.terminalService.getProfiles()
|
const profiles = await this.terminalService.getProfiles()
|
||||||
|
|
||||||
let items: Electron.MenuItemConstructorOptions[] = [
|
const items: Electron.MenuItemConstructorOptions[] = [
|
||||||
{
|
{
|
||||||
label: 'New terminal',
|
label: 'New terminal',
|
||||||
click: () => this.zone.run(() => {
|
click: () => this.zone.run(() => {
|
||||||
|
@@ -43,7 +43,7 @@ export abstract class Frontend {
|
|||||||
detach (host: HTMLElement): void { } // tslint:disable-line
|
detach (host: HTMLElement): void { } // tslint:disable-line
|
||||||
|
|
||||||
destroy (): void {
|
destroy (): void {
|
||||||
for (let o of [
|
for (const o of [
|
||||||
this.ready,
|
this.ready,
|
||||||
this.title,
|
this.title,
|
||||||
this.alternateScreenActive,
|
this.alternateScreenActive,
|
||||||
|
@@ -46,7 +46,7 @@ hterm.lib.wc.charWidthDisregardAmbiguous = codepoint => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
hterm.hterm.Terminal.prototype.applyCursorShape = function () {
|
hterm.hterm.Terminal.prototype.applyCursorShape = function () {
|
||||||
let modes = [
|
const modes = [
|
||||||
[hterm.hterm.Terminal.cursorShape.BLOCK, true],
|
[hterm.hterm.Terminal.cursorShape.BLOCK, true],
|
||||||
[this.defaultCursorShape || hterm.hterm.Terminal.cursorShape.BLOCK, false],
|
[this.defaultCursorShape || hterm.hterm.Terminal.cursorShape.BLOCK, false],
|
||||||
[hterm.hterm.Terminal.cursorShape.BLOCK, false],
|
[hterm.hterm.Terminal.cursorShape.BLOCK, false],
|
||||||
@@ -55,7 +55,7 @@ hterm.hterm.Terminal.prototype.applyCursorShape = function () {
|
|||||||
[hterm.hterm.Terminal.cursorShape.BEAM, true],
|
[hterm.hterm.Terminal.cursorShape.BEAM, true],
|
||||||
[hterm.hterm.Terminal.cursorShape.BEAM, false],
|
[hterm.hterm.Terminal.cursorShape.BEAM, false],
|
||||||
]
|
]
|
||||||
let modeNumber = this.cursorMode || 1
|
const modeNumber = this.cursorMode || 1
|
||||||
if (modeNumber >= modes.length) {
|
if (modeNumber >= modes.length) {
|
||||||
console.warn('Unknown cursor style: ' + modeNumber)
|
console.warn('Unknown cursor style: ' + modeNumber)
|
||||||
return
|
return
|
||||||
@@ -76,14 +76,14 @@ hterm.hterm.VT.CSI[' q'] = function (parseState) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
hterm.hterm.VT.OSC['4'] = function (parseState) {
|
hterm.hterm.VT.OSC['4'] = function (parseState) {
|
||||||
let args = parseState.args[0].split(';')
|
const args = parseState.args[0].split(';')
|
||||||
|
|
||||||
let pairCount = args.length / 2
|
const pairCount = args.length / 2
|
||||||
let colorPalette = this.terminal.getTextAttributes().colorPalette
|
const colorPalette = this.terminal.getTextAttributes().colorPalette
|
||||||
let responseArray = []
|
const responseArray = []
|
||||||
|
|
||||||
for (let pairNumber = 0; pairNumber < pairCount; ++pairNumber) {
|
for (let pairNumber = 0; pairNumber < pairCount; ++pairNumber) {
|
||||||
let colorIndex = parseInt(args[pairNumber * 2])
|
const colorIndex = parseInt(args[pairNumber * 2])
|
||||||
let colorValue = args[pairNumber * 2 + 1]
|
let colorValue = args[pairNumber * 2 + 1]
|
||||||
|
|
||||||
if (colorIndex >= colorPalette.length) {
|
if (colorIndex >= colorPalette.length) {
|
||||||
|
@@ -54,7 +54,7 @@ export class HTermFrontend extends Frontend {
|
|||||||
}
|
}
|
||||||
|
|
||||||
configure (): void {
|
configure (): void {
|
||||||
let config = this.configService.store
|
const config = this.configService.store
|
||||||
|
|
||||||
this.configuredFontSize = config.terminal.fontSize
|
this.configuredFontSize = config.terminal.fontSize
|
||||||
this.configuredLinePadding = config.terminal.linePadding
|
this.configuredLinePadding = config.terminal.linePadding
|
||||||
@@ -157,7 +157,7 @@ export class HTermFrontend extends Frontend {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private setFontSize () {
|
private setFontSize () {
|
||||||
let size = this.configuredFontSize * Math.pow(1.1, this.zoom)
|
const size = this.configuredFontSize * Math.pow(1.1, this.zoom)
|
||||||
preferenceManager.set('font-size', size)
|
preferenceManager.set('font-size', size)
|
||||||
if (this.term) {
|
if (this.term) {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
@@ -229,7 +229,7 @@ export class HTermFrontend extends Frontend {
|
|||||||
|
|
||||||
this.term.ringBell = () => this.bell.next()
|
this.term.ringBell = () => this.bell.next()
|
||||||
|
|
||||||
for (let screen of [this.term.primaryScreen_, this.term.alternateScreen_]) {
|
for (const screen of [this.term.primaryScreen_, this.term.alternateScreen_]) {
|
||||||
const _insertString = screen.insertString.bind(screen)
|
const _insertString = screen.insertString.bind(screen)
|
||||||
screen.insertString = (data) => {
|
screen.insertString = (data) => {
|
||||||
_insertString(data)
|
_insertString(data)
|
||||||
@@ -238,7 +238,7 @@ export class HTermFrontend extends Frontend {
|
|||||||
|
|
||||||
const _deleteChars = screen.deleteChars.bind(screen)
|
const _deleteChars = screen.deleteChars.bind(screen)
|
||||||
screen.deleteChars = (count) => {
|
screen.deleteChars = (count) => {
|
||||||
let ret = _deleteChars(count)
|
const ret = _deleteChars(count)
|
||||||
this.contentUpdated.next()
|
this.contentUpdated.next()
|
||||||
return ret
|
return ret
|
||||||
}
|
}
|
||||||
@@ -246,7 +246,7 @@ export class HTermFrontend extends Frontend {
|
|||||||
const _expandSelection = screen.expandSelection.bind(screen)
|
const _expandSelection = screen.expandSelection.bind(screen)
|
||||||
screen.expandSelection = (selection) => {
|
screen.expandSelection = (selection) => {
|
||||||
// Drop whitespace at the end of selection
|
// Drop whitespace at the end of selection
|
||||||
let range = selection.getRangeAt(0)
|
const range = selection.getRangeAt(0)
|
||||||
if (range.endOffset > 0 && range.endContainer.nodeType === 3 && range.endContainer.textContent !== '') {
|
if (range.endOffset > 0 && range.endContainer.nodeType === 3 && range.endContainer.textContent !== '') {
|
||||||
while (/[\s\S]+\s$/.test(range.endContainer.textContent.substr(0,range.endOffset))) {
|
while (/[\s\S]+\s$/.test(range.endContainer.textContent.substr(0,range.endOffset))) {
|
||||||
range.setEnd(range.endContainer, range.endOffset - 1)
|
range.setEnd(range.endContainer, range.endOffset - 1)
|
||||||
@@ -258,7 +258,7 @@ export class HTermFrontend extends Frontend {
|
|||||||
|
|
||||||
const _measureCharacterSize = this.term.scrollPort_.measureCharacterSize.bind(this.term.scrollPort_)
|
const _measureCharacterSize = this.term.scrollPort_.measureCharacterSize.bind(this.term.scrollPort_)
|
||||||
this.term.scrollPort_.measureCharacterSize = () => {
|
this.term.scrollPort_.measureCharacterSize = () => {
|
||||||
let size = _measureCharacterSize()
|
const size = _measureCharacterSize()
|
||||||
size.height += this.configuredLinePadding
|
size.height += this.configuredLinePadding
|
||||||
return size
|
return size
|
||||||
}
|
}
|
||||||
|
@@ -123,7 +123,7 @@ export class XTermFrontend extends Frontend {
|
|||||||
host.addEventListener('mouseup', event => this.mouseEvent.next(event as MouseEvent))
|
host.addEventListener('mouseup', event => this.mouseEvent.next(event as MouseEvent))
|
||||||
host.addEventListener('mousewheel', event => this.mouseEvent.next(event as MouseEvent))
|
host.addEventListener('mousewheel', event => this.mouseEvent.next(event as MouseEvent))
|
||||||
|
|
||||||
let ro = new window['ResizeObserver'](() => this.resizeHandler())
|
const ro = new window['ResizeObserver'](() => this.resizeHandler())
|
||||||
ro.observe(host)
|
ro.observe(host)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -167,7 +167,7 @@ export class XTermFrontend extends Frontend {
|
|||||||
}
|
}
|
||||||
|
|
||||||
configure (): void {
|
configure (): void {
|
||||||
let config = this.configService.store
|
const config = this.configService.store
|
||||||
|
|
||||||
setImmediate(() => {
|
setImmediate(() => {
|
||||||
if (this.xterm.cols && this.xterm.rows && this.xtermCore.charMeasure) {
|
if (this.xterm.cols && this.xterm.rows && this.xtermCore.charMeasure) {
|
||||||
@@ -194,7 +194,7 @@ export class XTermFrontend extends Frontend {
|
|||||||
|
|
||||||
this.copyOnSelect = config.terminal.copyOnSelect
|
this.copyOnSelect = config.terminal.copyOnSelect
|
||||||
|
|
||||||
let theme: ITheme = {
|
const theme: ITheme = {
|
||||||
foreground: config.terminal.colorScheme.foreground,
|
foreground: config.terminal.colorScheme.foreground,
|
||||||
background: (config.terminal.background === 'colorScheme') ? config.terminal.colorScheme.background : (config.appearance.vibrancy ? 'transparent' : this.themesService.findCurrentTheme().terminalBackground),
|
background: (config.terminal.background === 'colorScheme') ? config.terminal.colorScheme.background : (config.appearance.vibrancy ? 'transparent' : this.themesService.findCurrentTheme().terminalBackground),
|
||||||
cursor: config.terminal.colorScheme.cursor,
|
cursor: config.terminal.colorScheme.cursor,
|
||||||
@@ -252,7 +252,7 @@ export class XTermFrontend extends Frontend {
|
|||||||
|
|
||||||
private getHexColor (mode: number, color: number): string {
|
private getHexColor (mode: number, color: number): string {
|
||||||
if (mode === Attributes.CM_RGB) {
|
if (mode === Attributes.CM_RGB) {
|
||||||
let rgb = AttributeData.toColorRGB(color)
|
const rgb = AttributeData.toColorRGB(color)
|
||||||
return rgb.map(x => x.toString(16).padStart(2, '0')).join('')
|
return rgb.map(x => x.toString(16).padStart(2, '0')).join('')
|
||||||
}
|
}
|
||||||
if (mode === Attributes.CM_P16 || mode === Attributes.CM_P256) {
|
if (mode === Attributes.CM_P16 || mode === Attributes.CM_P256) {
|
||||||
@@ -265,7 +265,7 @@ export class XTermFrontend extends Frontend {
|
|||||||
let html = '<div>'
|
let html = '<div>'
|
||||||
let lastStyle = null
|
let lastStyle = null
|
||||||
const line = (this.xterm.buffer.getLine(y) as any)._line
|
const line = (this.xterm.buffer.getLine(y) as any)._line
|
||||||
let cell = new CellData()
|
const cell = new CellData()
|
||||||
for (let i = start; i < end; i++) {
|
for (let i = start; i < end; i++) {
|
||||||
line.loadCell(i, cell)
|
line.loadCell(i, cell)
|
||||||
const fg = this.getHexColor(cell.getFgColorMode(), cell.getFgColor())
|
const fg = this.getHexColor(cell.getFgColorMode(), cell.getFgColor())
|
||||||
|
@@ -74,7 +74,7 @@ export class TerminalHotkeyProvider extends HotkeyProvider {
|
|||||||
) { super() }
|
) { super() }
|
||||||
|
|
||||||
async provide (): Promise<IHotkeyDescription[]> {
|
async provide (): Promise<IHotkeyDescription[]> {
|
||||||
let profiles = await this.terminal.getProfiles()
|
const profiles = await this.terminal.getProfiles()
|
||||||
return [
|
return [
|
||||||
...this.hotkeys,
|
...this.hotkeys,
|
||||||
...profiles.map(profile => ({
|
...profiles.map(profile => ({
|
||||||
|
@@ -131,7 +131,7 @@ export default class TerminalModule {
|
|||||||
hostApp: HostAppService,
|
hostApp: HostAppService,
|
||||||
dockMenu: DockMenuService,
|
dockMenu: DockMenuService,
|
||||||
) {
|
) {
|
||||||
let events = [
|
const events = [
|
||||||
{
|
{
|
||||||
name: 'keydown',
|
name: 'keydown',
|
||||||
htermHandler: 'onKeyDown_',
|
htermHandler: 'onKeyDown_',
|
||||||
@@ -142,7 +142,7 @@ export default class TerminalModule {
|
|||||||
},
|
},
|
||||||
]
|
]
|
||||||
events.forEach((event) => {
|
events.forEach((event) => {
|
||||||
let oldHandler = hterm.hterm.Keyboard.prototype[event.htermHandler]
|
const oldHandler = hterm.hterm.Keyboard.prototype[event.htermHandler]
|
||||||
hterm.hterm.Keyboard.prototype[event.htermHandler] = function (nativeEvent) {
|
hterm.hterm.Keyboard.prototype[event.htermHandler] = function (nativeEvent) {
|
||||||
hotkeys.pushKeystroke(event.name, nativeEvent)
|
hotkeys.pushKeystroke(event.name, nativeEvent)
|
||||||
if (hotkeys.getCurrentPartiallyMatchedHotkeys().length === 0) {
|
if (hotkeys.getCurrentPartiallyMatchedHotkeys().length === 0) {
|
||||||
@@ -169,8 +169,8 @@ export default class TerminalModule {
|
|||||||
hostApp.newWindow()
|
hostApp.newWindow()
|
||||||
}
|
}
|
||||||
if (hotkey.startsWith('profile.')) {
|
if (hotkey.startsWith('profile.')) {
|
||||||
let profiles = await terminal.getProfiles()
|
const profiles = await terminal.getProfiles()
|
||||||
let profile = profiles.find(x => slug(x.name).toLowerCase() === hotkey.split('.')[1])
|
const profile = profiles.find(x => slug(x.name).toLowerCase() === hotkey.split('.')[1])
|
||||||
if (profile) {
|
if (profile) {
|
||||||
terminal.openTabWithOptions(profile.sessionOptions)
|
terminal.openTabWithOptions(profile.sessionOptions)
|
||||||
}
|
}
|
||||||
@@ -205,7 +205,7 @@ export default class TerminalModule {
|
|||||||
})
|
})
|
||||||
|
|
||||||
hostApp.cliOpenProfile$.subscribe(async profileName => {
|
hostApp.cliOpenProfile$.subscribe(async profileName => {
|
||||||
let profile = config.store.terminal.profiles.find(x => x.name === profileName)
|
const profile = config.store.terminal.profiles.find(x => x.name === profileName)
|
||||||
if (!profile) {
|
if (!profile) {
|
||||||
console.error('Requested profile', profileName, 'not found')
|
console.error('Requested profile', profileName, 'not found')
|
||||||
return
|
return
|
||||||
|
@@ -15,7 +15,7 @@ export class PathDropDecorator extends TerminalDecorator {
|
|||||||
event.preventDefault()
|
event.preventDefault()
|
||||||
}),
|
}),
|
||||||
terminal.frontend.drop$.subscribe(event => {
|
terminal.frontend.drop$.subscribe(event => {
|
||||||
for (let file of event.dataTransfer.files as any) {
|
for (const file of event.dataTransfer.files as any) {
|
||||||
this.injectPath(terminal, file.path)
|
this.injectPath(terminal, file.path)
|
||||||
}
|
}
|
||||||
event.preventDefault()
|
event.preventDefault()
|
||||||
@@ -32,8 +32,8 @@ export class PathDropDecorator extends TerminalDecorator {
|
|||||||
terminal.sendInput(path + ' ')
|
terminal.sendInput(path + ' ')
|
||||||
}
|
}
|
||||||
|
|
||||||
detach (terminal: TerminalTabComponent): void {
|
detach (_terminal: TerminalTabComponent): void {
|
||||||
for (let s of this.subscriptions) {
|
for (const s of this.subscriptions) {
|
||||||
s.unsubscribe()
|
s.unsubscribe()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -94,7 +94,7 @@ export class Session extends BaseSession {
|
|||||||
start (options: SessionOptions) {
|
start (options: SessionOptions) {
|
||||||
this.name = options.name
|
this.name = options.name
|
||||||
|
|
||||||
let env = {
|
const env = {
|
||||||
...process.env,
|
...process.env,
|
||||||
TERM: 'xterm-256color',
|
TERM: 'xterm-256color',
|
||||||
TERM_PROGRAM: 'Terminus',
|
TERM_PROGRAM: 'Terminus',
|
||||||
@@ -103,7 +103,7 @@ export class Session extends BaseSession {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (process.platform === 'darwin' && !process.env.LC_ALL) {
|
if (process.platform === 'darwin' && !process.env.LC_ALL) {
|
||||||
let locale = process.env.LC_CTYPE || 'en_US.UTF-8'
|
const locale = process.env.LC_CTYPE || 'en_US.UTF-8'
|
||||||
Object.assign(env, {
|
Object.assign(env, {
|
||||||
LANG: locale,
|
LANG: locale,
|
||||||
LC_ALL: locale,
|
LC_ALL: locale,
|
||||||
@@ -175,9 +175,9 @@ export class Session extends BaseSession {
|
|||||||
|
|
||||||
processOSC1337 (data) {
|
processOSC1337 (data) {
|
||||||
if (data.includes(OSC1337Prefix)) {
|
if (data.includes(OSC1337Prefix)) {
|
||||||
let preData = data.substring(0, data.indexOf(OSC1337Prefix))
|
const preData = data.substring(0, data.indexOf(OSC1337Prefix))
|
||||||
let params = data.substring(data.indexOf(OSC1337Prefix) + OSC1337Prefix.length)
|
let params = data.substring(data.indexOf(OSC1337Prefix) + OSC1337Prefix.length)
|
||||||
let postData = params.substring(params.indexOf(OSC1337Suffix) + OSC1337Suffix.length)
|
const postData = params.substring(params.indexOf(OSC1337Suffix) + OSC1337Suffix.length)
|
||||||
params = params.substring(0, params.indexOf(OSC1337Suffix))
|
params = params.substring(0, params.indexOf(OSC1337Suffix))
|
||||||
|
|
||||||
if (params.startsWith('CurrentDir=')) {
|
if (params.startsWith('CurrentDir=')) {
|
||||||
@@ -216,7 +216,7 @@ export class Session extends BaseSession {
|
|||||||
return []
|
return []
|
||||||
}
|
}
|
||||||
if (process.platform === 'darwin') {
|
if (process.platform === 'darwin') {
|
||||||
let processes = await macOSNativeProcessList.getProcessList()
|
const processes = await macOSNativeProcessList.getProcessList()
|
||||||
return processes.filter(x => x.ppid === this.truePID).map(p => ({
|
return processes.filter(x => x.ppid === this.truePID).map(p => ({
|
||||||
pid: p.pid,
|
pid: p.pid,
|
||||||
ppid: p.ppid,
|
ppid: p.ppid,
|
||||||
@@ -304,7 +304,7 @@ export class Session extends BaseSession {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private guessWindowsCWD (data: string) {
|
private guessWindowsCWD (data: string) {
|
||||||
let match = windowsDirectoryRegex.exec(data)
|
const match = windowsDirectoryRegex.exec(data)
|
||||||
if (match) {
|
if (match) {
|
||||||
this.guessedCWD = match[0]
|
this.guessedCWD = match[0]
|
||||||
}
|
}
|
||||||
|
@@ -35,12 +35,12 @@ export class TerminalService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private async getShells (): Promise<IShell[]> {
|
private async getShells (): Promise<IShell[]> {
|
||||||
let shellLists = await Promise.all(this.config.enabledServices(this.shellProviders).map(x => x.provide()))
|
const shellLists = await Promise.all(this.config.enabledServices(this.shellProviders).map(x => x.provide()))
|
||||||
return shellLists.reduce((a, b) => a.concat(b), [])
|
return shellLists.reduce((a, b) => a.concat(b), [])
|
||||||
}
|
}
|
||||||
|
|
||||||
async getProfiles (includeHidden?: boolean): Promise<Profile[]> {
|
async getProfiles (includeHidden?: boolean): Promise<Profile[]> {
|
||||||
let shells = await this.shells$.toPromise()
|
const shells = await this.shells$.toPromise()
|
||||||
return [
|
return [
|
||||||
...this.config.store.terminal.profiles,
|
...this.config.store.terminal.profiles,
|
||||||
...shells.filter(x => includeHidden || !x.hidden).map(shell => ({
|
...shells.filter(x => includeHidden || !x.hidden).map(shell => ({
|
||||||
@@ -54,7 +54,7 @@ export class TerminalService {
|
|||||||
|
|
||||||
private async reloadShells () {
|
private async reloadShells () {
|
||||||
this.shells = new AsyncSubject<IShell[]>()
|
this.shells = new AsyncSubject<IShell[]>()
|
||||||
let shells = await this.getShells()
|
const shells = await this.getShells()
|
||||||
this.logger.debug('Shells list:', shells)
|
this.logger.debug('Shells list:', shells)
|
||||||
this.shells.next(shells)
|
this.shells.next(shells)
|
||||||
this.shells.complete()
|
this.shells.complete()
|
||||||
@@ -66,7 +66,7 @@ export class TerminalService {
|
|||||||
*/
|
*/
|
||||||
async openTab (profile?: Profile, cwd?: string, pause?: boolean): Promise<TerminalTabComponent> {
|
async openTab (profile?: Profile, cwd?: string, pause?: boolean): Promise<TerminalTabComponent> {
|
||||||
if (!profile) {
|
if (!profile) {
|
||||||
let profiles = await this.getProfiles(true)
|
const profiles = await this.getProfiles(true)
|
||||||
profile = profiles.find(x => slug(x.name).toLowerCase() === this.config.store.terminal.profile) || profiles[0]
|
profile = profiles.find(x => slug(x.name).toLowerCase() === this.config.store.terminal.profile) || profiles[0]
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -82,7 +82,7 @@ export class TerminalService {
|
|||||||
cwd = await this.app.activeTab.session.getWorkingDirectory()
|
cwd = await this.app.activeTab.session.getWorkingDirectory()
|
||||||
}
|
}
|
||||||
if (this.app.activeTab instanceof SplitTabComponent) {
|
if (this.app.activeTab instanceof SplitTabComponent) {
|
||||||
let focusedTab = this.app.activeTab.getFocusedTab()
|
const focusedTab = this.app.activeTab.getFocusedTab()
|
||||||
|
|
||||||
if (focusedTab instanceof TerminalTabComponent && focusedTab.session) {
|
if (focusedTab instanceof TerminalTabComponent && focusedTab.session) {
|
||||||
cwd = await focusedTab.session.getWorkingDirectory()
|
cwd = await focusedTab.session.getWorkingDirectory()
|
||||||
@@ -93,7 +93,7 @@ export class TerminalService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.logger.info(`Starting profile ${profile.name}`, profile)
|
this.logger.info(`Starting profile ${profile.name}`, profile)
|
||||||
let sessionOptions = {
|
const sessionOptions = {
|
||||||
...profile.sessionOptions,
|
...profile.sessionOptions,
|
||||||
pauseAfterExit: pause,
|
pauseAfterExit: pause,
|
||||||
cwd,
|
cwd,
|
||||||
|
@@ -18,7 +18,7 @@ export class TerminalFrontendService {
|
|||||||
|
|
||||||
getFrontend (session?: BaseSession): Frontend {
|
getFrontend (session?: BaseSession): Frontend {
|
||||||
if (!session) {
|
if (!session) {
|
||||||
let frontend: Frontend = new ({
|
const frontend: Frontend = new ({
|
||||||
'xterm': XTermFrontend,
|
'xterm': XTermFrontend,
|
||||||
'xterm-webgl': XTermWebGLFrontend,
|
'xterm-webgl': XTermWebGLFrontend,
|
||||||
'hterm': HTermFrontend,
|
'hterm': HTermFrontend,
|
||||||
|
@@ -33,7 +33,7 @@ export class UACService {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
let options = { ...sessionOptions }
|
const options = { ...sessionOptions }
|
||||||
options.args = [options.command, ...options.args]
|
options.args = [options.command, ...options.args]
|
||||||
options.command = helperPath
|
options.command = helperPath
|
||||||
return options
|
return options
|
||||||
|
@@ -14,7 +14,7 @@ export class CustomShellProvider extends ShellProvider {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async provide (): Promise<IShell[]> {
|
async provide (): Promise<IShell[]> {
|
||||||
let args = this.config.store.terminal.customShell.split(' ')
|
const args = this.config.store.terminal.customShell.split(' ')
|
||||||
return [{
|
return [{
|
||||||
id: 'custom',
|
id: 'custom',
|
||||||
name: 'Custom shell',
|
name: 'Custom shell',
|
||||||
|
@@ -25,7 +25,7 @@ export class Cygwin32ShellProvider extends ShellProvider {
|
|||||||
return []
|
return []
|
||||||
}
|
}
|
||||||
|
|
||||||
let cygwinPath = wnr.getRegistryValue(wnr.HK.LM, 'Software\\WOW6432Node\\Cygwin\\setup', 'rootdir')
|
const cygwinPath = wnr.getRegistryValue(wnr.HK.LM, 'Software\\WOW6432Node\\Cygwin\\setup', 'rootdir')
|
||||||
|
|
||||||
if (!cygwinPath) {
|
if (!cygwinPath) {
|
||||||
return []
|
return []
|
||||||
|
@@ -25,7 +25,7 @@ export class Cygwin64ShellProvider extends ShellProvider {
|
|||||||
return []
|
return []
|
||||||
}
|
}
|
||||||
|
|
||||||
let cygwinPath = wnr.getRegistryValue(wnr.HK.LM, 'Software\\Cygwin\\setup', 'rootdir')
|
const cygwinPath = wnr.getRegistryValue(wnr.HK.LM, 'Software\\Cygwin\\setup', 'rootdir')
|
||||||
|
|
||||||
if (!cygwinPath) {
|
if (!cygwinPath) {
|
||||||
return []
|
return []
|
||||||
|
@@ -22,7 +22,7 @@ export class LinuxDefaultShellProvider extends ShellProvider {
|
|||||||
if (this.hostApp.platform !== Platform.Linux) {
|
if (this.hostApp.platform !== Platform.Linux) {
|
||||||
return []
|
return []
|
||||||
}
|
}
|
||||||
let line = (await fs.readFile('/etc/passwd', { encoding: 'utf-8' }))
|
const line = (await fs.readFile('/etc/passwd', { encoding: 'utf-8' }))
|
||||||
.split('\n').find(x => x.startsWith(process.env.LOGNAME + ':'))
|
.split('\n').find(x => x.startsWith(process.env.LOGNAME + ':'))
|
||||||
if (!line) {
|
if (!line) {
|
||||||
this.logger.warn('Could not detect user shell')
|
this.logger.warn('Could not detect user shell')
|
||||||
|
@@ -18,7 +18,7 @@ export class MacOSDefaultShellProvider extends ShellProvider {
|
|||||||
if (this.hostApp.platform !== Platform.macOS) {
|
if (this.hostApp.platform !== Platform.macOS) {
|
||||||
return []
|
return []
|
||||||
}
|
}
|
||||||
let shellEntry = (await exec(`/usr/bin/dscl . -read /Users/${process.env.LOGNAME} UserShell`))[0].toString()
|
const shellEntry = (await exec(`/usr/bin/dscl . -read /Users/${process.env.LOGNAME} UserShell`))[0].toString()
|
||||||
return [{
|
return [{
|
||||||
id: 'default',
|
id: 'default',
|
||||||
name: 'User default',
|
name: 'User default',
|
||||||
|
@@ -32,10 +32,10 @@ export class WindowsDefaultShellProvider extends ShellProvider {
|
|||||||
return []
|
return []
|
||||||
}
|
}
|
||||||
// Figure out a sensible default
|
// Figure out a sensible default
|
||||||
let shellLists = await Promise.all(this.providers.map(x => x.provide()))
|
const shellLists = await Promise.all(this.providers.map(x => x.provide()))
|
||||||
for (let list of shellLists) {
|
for (const list of shellLists) {
|
||||||
if (list.length) {
|
if (list.length) {
|
||||||
let shell = list[list.length - 1]
|
const shell = list[list.length - 1]
|
||||||
|
|
||||||
return [{
|
return [{
|
||||||
...shell,
|
...shell,
|
||||||
|
@@ -29,7 +29,7 @@ export class WSLShellProvider extends ShellProvider {
|
|||||||
const bashPath = `${process.env.windir}\\system32\\bash.exe`
|
const bashPath = `${process.env.windir}\\system32\\bash.exe`
|
||||||
const wslPath = `${process.env.windir}\\system32\\wsl.exe`
|
const wslPath = `${process.env.windir}\\system32\\wsl.exe`
|
||||||
|
|
||||||
let shells: IShell[] = [{
|
const shells: IShell[] = [{
|
||||||
id: 'wsl',
|
id: 'wsl',
|
||||||
name: 'WSL / Default distro',
|
name: 'WSL / Default distro',
|
||||||
command: wslPath,
|
command: wslPath,
|
||||||
@@ -40,7 +40,7 @@ export class WSLShellProvider extends ShellProvider {
|
|||||||
}]
|
}]
|
||||||
|
|
||||||
const lxssPath = 'Software\\Microsoft\\Windows\\CurrentVersion\\Lxss'
|
const lxssPath = 'Software\\Microsoft\\Windows\\CurrentVersion\\Lxss'
|
||||||
let lxss = wnr.getRegistryKey(wnr.HK.CU, lxssPath)
|
const lxss = wnr.getRegistryKey(wnr.HK.CU, lxssPath)
|
||||||
if (!lxss || !lxss.DefaultDistribution || !isWindowsBuild(WIN_BUILD_WSL_EXE_DISTRO_FLAG)) {
|
if (!lxss || !lxss.DefaultDistribution || !isWindowsBuild(WIN_BUILD_WSL_EXE_DISTRO_FLAG)) {
|
||||||
if (await fs.exists(bashPath)) {
|
if (await fs.exists(bashPath)) {
|
||||||
return [{
|
return [{
|
||||||
@@ -56,12 +56,12 @@ export class WSLShellProvider extends ShellProvider {
|
|||||||
return []
|
return []
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (let child of wnr.listRegistrySubkeys(wnr.HK.CU, lxssPath)) {
|
for (const child of wnr.listRegistrySubkeys(wnr.HK.CU, lxssPath)) {
|
||||||
let childKey = wnr.getRegistryKey(wnr.HK.CU, lxssPath + '\\' + child)
|
const childKey = wnr.getRegistryKey(wnr.HK.CU, lxssPath + '\\' + child)
|
||||||
if (!childKey.DistributionName) {
|
if (!childKey.DistributionName) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
let name = childKey.DistributionName.value
|
const name = childKey.DistributionName.value
|
||||||
shells.push({
|
shells.push({
|
||||||
id: `wsl-${slug(name)}`,
|
id: `wsl-${slug(name)}`,
|
||||||
name: `WSL / ${name}`,
|
name: `WSL / ${name}`,
|
||||||
|
@@ -22,7 +22,7 @@ export class SaveAsProfileContextMenu extends TabContextMenuItemProvider {
|
|||||||
{
|
{
|
||||||
label: 'Save as profile',
|
label: 'Save as profile',
|
||||||
click: () => this.zone.run(async () => {
|
click: () => this.zone.run(async () => {
|
||||||
let profile = {
|
const profile = {
|
||||||
sessionOptions: {
|
sessionOptions: {
|
||||||
...tab.sessionOptions,
|
...tab.sessionOptions,
|
||||||
cwd: (await tab.session.getWorkingDirectory()) || tab.sessionOptions.cwd,
|
cwd: (await tab.session.getWorkingDirectory()) || tab.sessionOptions.cwd,
|
||||||
|
@@ -10,6 +10,7 @@
|
|||||||
"spaces"
|
"spaces"
|
||||||
],
|
],
|
||||||
"ter-indent": [true, 4],
|
"ter-indent": [true, 4],
|
||||||
|
"prefer-const": true,
|
||||||
"trailing-comma": [
|
"trailing-comma": [
|
||||||
true,
|
true,
|
||||||
{
|
{
|
||||||
|
Reference in New Issue
Block a user