mirror of
https://github.com/Eugeny/tabby.git
synced 2024-12-25 11:33:35 +03:00
made context menu extensible
This commit is contained in:
parent
fe31131fc1
commit
524550f6e3
@ -41,6 +41,12 @@ export abstract class TerminalColorSchemeProvider {
|
||||
abstract async getSchemes (): Promise<ITerminalColorScheme[]>
|
||||
}
|
||||
|
||||
export abstract class TerminalContextMenuItemProvider {
|
||||
weight: number
|
||||
|
||||
abstract async getItems (tab: TerminalTabComponent): Promise<Electron.MenuItemConstructorOptions[]>
|
||||
}
|
||||
|
||||
export interface IShell {
|
||||
id: string
|
||||
name?: string
|
||||
|
@ -5,11 +5,9 @@ import { Component, NgZone, Inject, Optional, ViewChild, HostBinding, Input } fr
|
||||
import { AppService, ConfigService, BaseTabComponent, BaseTabProcess, ElectronService, HostAppService, HotkeysService, Platform } from 'terminus-core'
|
||||
|
||||
import { Session, SessionsService } from '../services/sessions.service'
|
||||
import { TerminalService } from '../services/terminal.service'
|
||||
import { TerminalFrontendService } from '../services/terminalFrontend.service'
|
||||
import { UACService } from '../services/uac.service'
|
||||
|
||||
import { TerminalDecorator, ResizeEvent, SessionOptions } from '../api'
|
||||
import { TerminalDecorator, ResizeEvent, SessionOptions, TerminalContextMenuItemProvider } from '../api'
|
||||
import { Frontend } from '../frontends/frontend'
|
||||
|
||||
@Component({
|
||||
@ -49,12 +47,11 @@ export class TerminalTabComponent extends BaseTabComponent {
|
||||
private hotkeys: HotkeysService,
|
||||
private sessions: SessionsService,
|
||||
private electron: ElectronService,
|
||||
private terminalService: TerminalService,
|
||||
private terminalContainersService: TerminalFrontendService,
|
||||
public config: ConfigService,
|
||||
private toastr: ToastrService,
|
||||
private uac: UACService,
|
||||
@Optional() @Inject(TerminalDecorator) private decorators: TerminalDecorator[],
|
||||
@Optional() @Inject(TerminalContextMenuItemProvider) private contextMenuProviders: TerminalContextMenuItemProvider[],
|
||||
) {
|
||||
super()
|
||||
this.decorators = this.decorators || []
|
||||
@ -117,6 +114,8 @@ export class TerminalTabComponent extends BaseTabComponent {
|
||||
})
|
||||
this.bellPlayer = document.createElement('audio')
|
||||
this.bellPlayer.src = require<string>('../bell.ogg')
|
||||
|
||||
this.contextMenuProviders.sort((a, b) => a.weight - b.weight)
|
||||
}
|
||||
|
||||
initializeSession (columns: number, rows: number) {
|
||||
@ -206,76 +205,12 @@ export class TerminalTabComponent extends BaseTabComponent {
|
||||
}
|
||||
|
||||
async buildContextMenu (): Promise<Electron.MenuItemConstructorOptions[]> {
|
||||
let shells = await this.terminalService.shells$.toPromise()
|
||||
let items: Electron.MenuItemConstructorOptions[] = [
|
||||
{
|
||||
label: 'New terminal',
|
||||
click: () => this.zone.run(() => {
|
||||
this.terminalService.openTabWithOptions(this.sessionOptions)
|
||||
})
|
||||
},
|
||||
{
|
||||
label: 'New with shell',
|
||||
submenu: shells.map(shell => ({
|
||||
label: shell.name,
|
||||
click: () => this.zone.run(async () => {
|
||||
this.terminalService.openTab(shell, await this.session.getWorkingDirectory())
|
||||
}),
|
||||
})),
|
||||
},
|
||||
]
|
||||
|
||||
if (this.uac.isAvailable) {
|
||||
items.push({
|
||||
label: 'New as admin',
|
||||
submenu: shells.map(shell => ({
|
||||
label: shell.name,
|
||||
click: () => this.zone.run(async () => {
|
||||
let options = this.terminalService.optionsFromShell(shell)
|
||||
options.runAsAdministrator = true
|
||||
this.terminalService.openTabWithOptions(options)
|
||||
}),
|
||||
})),
|
||||
})
|
||||
let items: Electron.MenuItemConstructorOptions[] = []
|
||||
for (let section of await Promise.all(this.contextMenuProviders.map(x => x.getItems(this)))) {
|
||||
items = items.concat(section)
|
||||
items.push({ type: 'separator' })
|
||||
}
|
||||
|
||||
items = items.concat([
|
||||
{
|
||||
label: 'New with profile',
|
||||
submenu: this.config.store.terminal.profiles.length ? this.config.store.terminal.profiles.map(profile => ({
|
||||
label: profile.name,
|
||||
click: () => this.zone.run(() => {
|
||||
this.terminalService.openTabWithOptions(profile.sessionOptions)
|
||||
}),
|
||||
})) : [{
|
||||
label: 'No profiles saved',
|
||||
enabled: false,
|
||||
}],
|
||||
},
|
||||
{
|
||||
type: 'separator',
|
||||
},
|
||||
{
|
||||
label: 'Copy',
|
||||
click: () => {
|
||||
this.zone.run(() => {
|
||||
setTimeout(() => {
|
||||
this.frontend.copySelection()
|
||||
this.toastr.info('Copied')
|
||||
})
|
||||
})
|
||||
}
|
||||
},
|
||||
{
|
||||
label: 'Paste',
|
||||
click: () => {
|
||||
this.zone.run(() => {
|
||||
this.paste()
|
||||
})
|
||||
}
|
||||
},
|
||||
])
|
||||
|
||||
items.splice(items.length - 1, 1)
|
||||
return items
|
||||
}
|
||||
|
||||
|
108
terminus-terminal/src/contextMenu.ts
Normal file
108
terminus-terminal/src/contextMenu.ts
Normal file
@ -0,0 +1,108 @@
|
||||
import { NgZone, Injectable } from '@angular/core'
|
||||
import { ToastrService } from 'ngx-toastr'
|
||||
import { ConfigService } from 'terminus-core'
|
||||
import { UACService } from './services/uac.service'
|
||||
import { TerminalService } from './services/terminal.service'
|
||||
import { TerminalTabComponent } from './components/terminalTab.component'
|
||||
import { TerminalContextMenuItemProvider } from './api'
|
||||
|
||||
@Injectable()
|
||||
export class NewTabContextMenu extends TerminalContextMenuItemProvider {
|
||||
weight = 0
|
||||
|
||||
constructor (
|
||||
public config: ConfigService,
|
||||
private zone: NgZone,
|
||||
private terminalService: TerminalService,
|
||||
private uac: UACService,
|
||||
) {
|
||||
super()
|
||||
}
|
||||
|
||||
async getItems (tab: TerminalTabComponent): Promise<Electron.MenuItemConstructorOptions[]> {
|
||||
let shells = await this.terminalService.shells$.toPromise()
|
||||
|
||||
let items: Electron.MenuItemConstructorOptions[] = [
|
||||
{
|
||||
label: 'New terminal',
|
||||
click: () => this.zone.run(() => {
|
||||
this.terminalService.openTabWithOptions(tab.sessionOptions)
|
||||
})
|
||||
},
|
||||
{
|
||||
label: 'New with shell',
|
||||
submenu: shells.map(shell => ({
|
||||
label: shell.name,
|
||||
click: () => this.zone.run(async () => {
|
||||
this.terminalService.openTab(shell, await tab.session.getWorkingDirectory())
|
||||
}),
|
||||
})),
|
||||
},
|
||||
]
|
||||
|
||||
if (this.uac.isAvailable) {
|
||||
items.push({
|
||||
label: 'New as admin',
|
||||
submenu: shells.map(shell => ({
|
||||
label: shell.name,
|
||||
click: () => this.zone.run(async () => {
|
||||
let options = this.terminalService.optionsFromShell(shell)
|
||||
options.runAsAdministrator = true
|
||||
this.terminalService.openTabWithOptions(options)
|
||||
}),
|
||||
})),
|
||||
})
|
||||
}
|
||||
|
||||
items = items.concat([
|
||||
{
|
||||
label: 'New with profile',
|
||||
submenu: this.config.store.terminal.profiles.length ? this.config.store.terminal.profiles.map(profile => ({
|
||||
label: profile.name,
|
||||
click: () => this.zone.run(() => {
|
||||
this.terminalService.openTabWithOptions(profile.sessionOptions)
|
||||
}),
|
||||
})) : [{
|
||||
label: 'No profiles saved',
|
||||
enabled: false,
|
||||
}],
|
||||
},
|
||||
])
|
||||
|
||||
return items
|
||||
}
|
||||
}
|
||||
|
||||
@Injectable()
|
||||
export class CopyPasteContextMenu extends TerminalContextMenuItemProvider {
|
||||
weight = 1
|
||||
|
||||
constructor (
|
||||
private zone: NgZone,
|
||||
private toastr: ToastrService,
|
||||
) {
|
||||
super()
|
||||
}
|
||||
|
||||
async getItems (tab: TerminalTabComponent): Promise<Electron.MenuItemConstructorOptions[]> {
|
||||
return [
|
||||
{
|
||||
label: 'Copy',
|
||||
click: () => {
|
||||
this.zone.run(() => {
|
||||
setTimeout(() => {
|
||||
tab.frontend.copySelection()
|
||||
this.toastr.info('Copied')
|
||||
})
|
||||
})
|
||||
}
|
||||
},
|
||||
{
|
||||
label: 'Paste',
|
||||
click: () => {
|
||||
this.zone.run(() => tab.paste())
|
||||
}
|
||||
},
|
||||
]
|
||||
}
|
||||
}
|
@ -24,12 +24,13 @@ import { DockMenuService } from './services/dockMenu.service'
|
||||
|
||||
import { ButtonProvider } from './buttonProvider'
|
||||
import { RecoveryProvider } from './recoveryProvider'
|
||||
import { TerminalColorSchemeProvider, TerminalDecorator, ShellProvider } from './api'
|
||||
import { TerminalColorSchemeProvider, TerminalDecorator, ShellProvider, TerminalContextMenuItemProvider } from './api'
|
||||
import { TerminalSettingsTabProvider, AppearanceSettingsTabProvider, ShellSettingsTabProvider } from './settings'
|
||||
import { PathDropDecorator } from './pathDrop'
|
||||
import { TerminalConfigProvider } from './config'
|
||||
import { TerminalHotkeyProvider } from './hotkeys'
|
||||
import { HyperColorSchemes } from './colorSchemes'
|
||||
import { NewTabContextMenu, CopyPasteContextMenu } from './contextMenu'
|
||||
|
||||
import { CmderShellProvider } from './shells/cmder'
|
||||
import { CustomShellProvider } from './shells/custom'
|
||||
@ -79,6 +80,9 @@ import { hterm } from './hterm'
|
||||
{ provide: ShellProvider, useClass: PowerShellCoreShellProvider, multi: true },
|
||||
{ provide: ShellProvider, useClass: WSLShellProvider, multi: true },
|
||||
|
||||
{ provide: TerminalContextMenuItemProvider, useClass: NewTabContextMenu, multi: true },
|
||||
{ provide: TerminalContextMenuItemProvider, useClass: CopyPasteContextMenu, multi: true },
|
||||
|
||||
// For WindowsDefaultShellProvider
|
||||
PowerShellCoreShellProvider,
|
||||
WSLShellProvider,
|
||||
|
Loading…
Reference in New Issue
Block a user