split terminus-local out of terminus-terminal
6
.github/dependabot.yml
vendored
@ -30,6 +30,12 @@ updates:
|
||||
interval: daily
|
||||
time: "04:00"
|
||||
open-pull-requests-limit: 20
|
||||
- package-ecosystem: npm
|
||||
directory: "/terminus-local"
|
||||
schedule:
|
||||
interval: daily
|
||||
time: "04:00"
|
||||
open-pull-requests-limit: 20
|
||||
- package-ecosystem: npm
|
||||
directory: "/terminus-community-color-schemes"
|
||||
schedule:
|
||||
|
@ -42,6 +42,7 @@ terminus
|
||||
├─ scripts # Maintenance scripts
|
||||
├─ terminus-community-color-schemes # Plugin that provides color schemes
|
||||
├─ terminus-core # Plugin that provides base UI and tab management
|
||||
└─ terminus-local # Plugin that provides local shells and profiles
|
||||
├─ terminus-plugin-manager # Plugin that installs other plugins
|
||||
├─ terminus-settings # Plugin that provides the settings tab
|
||||
└─ terminus-terminal # Plugin that provides terminal tabs
|
||||
@ -61,7 +62,7 @@ terminus-pluginname
|
||||
| └─ index.ts # Module entry point
|
||||
├─ package.json
|
||||
├─ tsconfig.json
|
||||
└─ webpack.config.js
|
||||
└─ webpack.config.js
|
||||
```
|
||||
|
||||
# Plugins
|
||||
@ -115,6 +116,6 @@ export default class MyModule { }
|
||||
```
|
||||
|
||||
|
||||
See `terminus-core/src/api.ts`, `terminus-settings/src/api.ts` and `terminus-terminal/src/api.ts` for the available extension points.
|
||||
See `terminus-core/src/api.ts`, `terminus-settings/src/api.ts`, `terminus-local/src/api.ts` and `terminus-terminal/src/api.ts` for the available extension points.
|
||||
|
||||
Publish your plugin on NPM with a `terminus-plugin` keyword to make it appear in the Plugin Manager.
|
||||
|
@ -57,6 +57,7 @@
|
||||
"peerDependencies": {
|
||||
"terminus-community-color-schemes": "*",
|
||||
"terminus-core": "*",
|
||||
"terminus-local": "*",
|
||||
"terminus-plugin-manager": "*",
|
||||
"terminus-serial": "*",
|
||||
"terminus-settings": "*",
|
||||
|
@ -65,6 +65,7 @@ const builtinModules = [
|
||||
'rxjs',
|
||||
'rxjs/operators',
|
||||
'terminus-core',
|
||||
'terminus-local',
|
||||
'terminus-settings',
|
||||
'terminus-terminal',
|
||||
'zone.js/dist/zone.js',
|
||||
@ -128,6 +129,10 @@ export async function findPlugins (): Promise<PluginInfo[]> {
|
||||
|
||||
const name = packageName.substring(PREFIX.length)
|
||||
|
||||
if (builtinModules.includes(packageName) && pluginDir !== builtinPluginsPath) {
|
||||
continue
|
||||
}
|
||||
|
||||
if (foundPlugins.some(x => x.name === name)) {
|
||||
console.info(`Plugin ${packageName} already exists, overriding`)
|
||||
foundPlugins = foundPlugins.filter(x => x.name !== name)
|
||||
|
@ -66,13 +66,13 @@
|
||||
"**/graceful-fs": "^4.2.4"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "npm run build:typings && webpack --color --config app/webpack.main.config.js && webpack --color --config app/webpack.config.js && webpack --color --config terminus-core/webpack.config.js && webpack --color --config terminus-settings/webpack.config.js && webpack --color --config terminus-terminal/webpack.config.js && webpack --color --config terminus-plugin-manager/webpack.config.js && webpack --color --config terminus-community-color-schemes/webpack.config.js && webpack --color --config terminus-ssh/webpack.config.js && webpack --color --config terminus-serial/webpack.config.js",
|
||||
"build": "npm run build:typings && webpack --color --config app/webpack.main.config.js && webpack --color --config app/webpack.config.js && webpack --color --config terminus-core/webpack.config.js && webpack --color --config terminus-settings/webpack.config.js && webpack --color --config terminus-terminal/webpack.config.js && webpack --color --config terminus-local/webpack.config.js && webpack --color --config terminus-plugin-manager/webpack.config.js && webpack --color --config terminus-community-color-schemes/webpack.config.js && webpack --color --config terminus-ssh/webpack.config.js && webpack --color --config terminus-serial/webpack.config.js",
|
||||
"build:typings": "node scripts/build-typings.js",
|
||||
"watch": "cross-env TERMINUS_DEV=1 webpack --progress --color --watch",
|
||||
"start": "cross-env TERMINUS_DEV=1 electron app --debug --inspect",
|
||||
"start:prod": "electron app --debug",
|
||||
"prod": "cross-env TERMINUS_DEV=1 electron app",
|
||||
"docs": "typedoc --out docs/api --tsconfig terminus-core/src/tsconfig.typings.json terminus-core/src/index.ts && typedoc --out docs/api/terminal --tsconfig terminus-terminal/tsconfig.typings.json terminus-terminal/src/index.ts && typedoc --out docs/api/settings --tsconfig terminus-settings/tsconfig.typings.json terminus-settings/src/index.ts",
|
||||
"docs": "typedoc --out docs/api --tsconfig terminus-core/src/tsconfig.typings.json terminus-core/src/index.ts && typedoc --out docs/api/terminal --tsconfig terminus-terminal/tsconfig.typings.json terminus-terminal/src/index.ts && typedoc --out docs/api/local --tsconfig terminus-local/tsconfig.typings.json terminus-local/src/index.ts && typedoc --out docs/api/settings --tsconfig terminus-settings/tsconfig.typings.json terminus-settings/src/index.ts",
|
||||
"lint": "eslint --ext ts */src */lib",
|
||||
"postinstall": "node ./scripts/install-deps.js"
|
||||
},
|
||||
|
@ -4,7 +4,7 @@ const path = require('path')
|
||||
const vars = require('./vars')
|
||||
|
||||
let lifecycles = []
|
||||
for (let dir of ['app', 'terminus-core', 'terminus-ssh', 'terminus-terminal']) {
|
||||
for (let dir of ['app', 'terminus-core', 'terminus-local', 'terminus-ssh', 'terminus-terminal']) {
|
||||
const build = rebuild({
|
||||
buildPath: path.resolve(__dirname, '../' + dir),
|
||||
electronVersion: vars.electronVersion,
|
||||
|
@ -17,6 +17,7 @@ if (exports.version.includes('-c')) {
|
||||
exports.builtinPlugins = [
|
||||
'terminus-core',
|
||||
'terminus-settings',
|
||||
'terminus-local',
|
||||
'terminus-terminal',
|
||||
'terminus-community-color-schemes',
|
||||
'terminus-plugin-manager',
|
||||
|
@ -1,7 +1,7 @@
|
||||
Terminus Core Plugin
|
||||
--------------------
|
||||
|
||||
See also: [Settings plugin API](./settings/), [Terminal plugin API](./terminal/)
|
||||
See also: [Settings plugin API](./settings/), [Terminal plugin API](./terminal/), [Local terminal API](./local/)
|
||||
|
||||
* tabbed interface services
|
||||
* toolbar UI
|
||||
|
@ -105,16 +105,10 @@ export class ConfigService {
|
||||
private constructor (
|
||||
electron: ElectronService,
|
||||
private hostApp: HostAppService,
|
||||
@Inject(ConfigProvider) configProviders: ConfigProvider[],
|
||||
@Inject(ConfigProvider) private configProviders: ConfigProvider[],
|
||||
) {
|
||||
this.path = path.join(electron.app.getPath('userData'), 'config.yaml')
|
||||
this.defaults = configProviders.map(provider => {
|
||||
let defaults = provider.platformDefaults[hostApp.platform] || {}
|
||||
if (provider.defaults) {
|
||||
defaults = configMerge(defaults, provider.defaults)
|
||||
}
|
||||
return defaults
|
||||
}).reduce(configMerge)
|
||||
this.defaults = this.mergeDefaults()
|
||||
this.load()
|
||||
|
||||
hostApp.configChangeBroadcast$.subscribe(() => {
|
||||
@ -123,6 +117,17 @@ export class ConfigService {
|
||||
})
|
||||
}
|
||||
|
||||
mergeDefaults (): unknown {
|
||||
const providers = this.configProviders
|
||||
return providers.map(provider => {
|
||||
let defaults = provider.platformDefaults[this.hostApp.platform] || {}
|
||||
if (provider.defaults) {
|
||||
defaults = configMerge(defaults, provider.defaults)
|
||||
}
|
||||
return defaults
|
||||
}).reduce(configMerge)
|
||||
}
|
||||
|
||||
getDefaults (): Record<string, any> {
|
||||
const cleanup = o => {
|
||||
if (o instanceof Array) {
|
||||
|
1
terminus-local/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
dist
|
23
terminus-local/README.md
Normal file
@ -0,0 +1,23 @@
|
||||
Terminus Local Plugin
|
||||
---------------------
|
||||
|
||||
* local shells
|
||||
|
||||
Using the API:
|
||||
|
||||
```ts
|
||||
import { ShellProvider } from 'terminus-local'
|
||||
```
|
||||
|
||||
Exporting your subclasses:
|
||||
|
||||
```ts
|
||||
@NgModule({
|
||||
...
|
||||
providers: [
|
||||
...
|
||||
{ provide: ShellProvider, useClass: MyShellPlugin, multi: true },
|
||||
...
|
||||
]
|
||||
})
|
||||
```
|
48
terminus-local/package.json
Normal file
@ -0,0 +1,48 @@
|
||||
{
|
||||
"name": "terminus-local",
|
||||
"version": "1.0.135-nightly.0",
|
||||
"description": "Terminus' local shell plugin",
|
||||
"keywords": [
|
||||
"terminus-builtin-plugin"
|
||||
],
|
||||
"main": "dist/index.js",
|
||||
"typings": "typings/index.d.ts",
|
||||
"scripts": {
|
||||
"build": "webpack --progress --color --display-modules",
|
||||
"watch": "webpack --progress --color --watch"
|
||||
},
|
||||
"files": [
|
||||
"typings"
|
||||
],
|
||||
"author": "Eugene Pankov",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"hterm-umdjs": "1.4.1",
|
||||
"opentype.js": "^1.3.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/deep-equal": "^1.0.0",
|
||||
"@types/shell-escape": "^0.2.0",
|
||||
"ansi-colors": "^4.1.1",
|
||||
"dataurl": "0.1.0",
|
||||
"deep-equal": "2.0.5",
|
||||
"mz": "^2.6.0",
|
||||
"ps-node": "^0.1.6",
|
||||
"runes": "^0.4.2",
|
||||
"shell-escape": "^0.2.0",
|
||||
"slugify": "^1.4.0",
|
||||
"utils-decorators": "^1.8.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@angular/animations": "^9.1.9",
|
||||
"@angular/common": "^9.1.11",
|
||||
"@angular/core": "^9.1.9",
|
||||
"@angular/forms": "^9.1.11",
|
||||
"@angular/platform-browser": "^9.1.11",
|
||||
"@ng-bootstrap/ng-bootstrap": "^6.1.0",
|
||||
"rxjs": "^6.5.5",
|
||||
"terminus-core": "*",
|
||||
"terminus-settings": "*",
|
||||
"terminus-terminal": "*"
|
||||
}
|
||||
}
|
57
terminus-local/src/api.ts
Normal file
@ -0,0 +1,57 @@
|
||||
export interface Shell {
|
||||
id: string
|
||||
name?: string
|
||||
command: string
|
||||
args?: string[]
|
||||
env: Record<string, string>
|
||||
|
||||
/**
|
||||
* Base path to which shell's internal FS is relative
|
||||
* Currently used for WSL only
|
||||
*/
|
||||
fsBase?: string
|
||||
|
||||
/**
|
||||
* SVG icon
|
||||
*/
|
||||
icon?: string
|
||||
|
||||
hidden?: boolean
|
||||
}
|
||||
|
||||
/**
|
||||
* Extend to add support for more shells
|
||||
*/
|
||||
export abstract class ShellProvider {
|
||||
abstract provide (): Promise<Shell[]>
|
||||
}
|
||||
|
||||
|
||||
export interface SessionOptions {
|
||||
restoreFromPTYID?: string
|
||||
name?: string
|
||||
command: string
|
||||
args?: string[]
|
||||
cwd?: string
|
||||
env?: Record<string, string>
|
||||
width?: number
|
||||
height?: number
|
||||
pauseAfterExit?: boolean
|
||||
runAsAdministrator?: boolean
|
||||
}
|
||||
|
||||
export interface Profile {
|
||||
name: string
|
||||
color?: string
|
||||
sessionOptions: SessionOptions
|
||||
shell?: string
|
||||
isBuiltin?: boolean
|
||||
icon?: string
|
||||
disableDynamicTitle?: boolean
|
||||
}
|
||||
|
||||
export interface ChildProcess {
|
||||
pid: number
|
||||
ppid: number
|
||||
command: string
|
||||
}
|
119
terminus-local/src/cli.ts
Normal file
@ -0,0 +1,119 @@
|
||||
import * as path from 'path'
|
||||
import * as fs from 'mz/fs'
|
||||
import { Injectable } from '@angular/core'
|
||||
import { CLIHandler, CLIEvent, HostAppService, AppService, ConfigService } from 'terminus-core'
|
||||
import { TerminalService } from './services/terminal.service'
|
||||
|
||||
@Injectable()
|
||||
export class TerminalCLIHandler extends CLIHandler {
|
||||
firstMatchOnly = true
|
||||
priority = 0
|
||||
|
||||
constructor (
|
||||
private config: ConfigService,
|
||||
private hostApp: HostAppService,
|
||||
private terminal: TerminalService,
|
||||
) {
|
||||
super()
|
||||
}
|
||||
|
||||
async handle (event: CLIEvent): Promise<boolean> {
|
||||
const op = event.argv._[0]
|
||||
|
||||
if (op === 'open') {
|
||||
this.handleOpenDirectory(path.resolve(event.cwd, event.argv.directory))
|
||||
} else if (op === 'run') {
|
||||
this.handleRunCommand(event.argv.command)
|
||||
} else if (op === 'profile') {
|
||||
this.handleOpenProfile(event.argv.profileName)
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
private async handleOpenDirectory (directory: string) {
|
||||
if (directory.length > 1 && (directory.endsWith('/') || directory.endsWith('\\'))) {
|
||||
directory = directory.substring(0, directory.length - 1)
|
||||
}
|
||||
if (await fs.exists(directory)) {
|
||||
if ((await fs.stat(directory)).isDirectory()) {
|
||||
this.terminal.openTab(undefined, directory)
|
||||
this.hostApp.bringToFront()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private handleRunCommand (command: string[]) {
|
||||
this.terminal.openTab({
|
||||
name: '',
|
||||
sessionOptions: {
|
||||
command: command[0],
|
||||
args: command.slice(1),
|
||||
},
|
||||
}, null, true)
|
||||
this.hostApp.bringToFront()
|
||||
}
|
||||
|
||||
private handleOpenProfile (profileName: string) {
|
||||
const profile = this.config.store.terminal.profiles.find(x => x.name === profileName)
|
||||
if (!profile) {
|
||||
console.error('Requested profile', profileName, 'not found')
|
||||
return
|
||||
}
|
||||
this.terminal.openTabWithOptions(profile.sessionOptions)
|
||||
this.hostApp.bringToFront()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Injectable()
|
||||
export class OpenPathCLIHandler extends CLIHandler {
|
||||
firstMatchOnly = true
|
||||
priority = -100
|
||||
|
||||
constructor (
|
||||
private terminal: TerminalService,
|
||||
private hostApp: HostAppService,
|
||||
) {
|
||||
super()
|
||||
}
|
||||
|
||||
async handle (event: CLIEvent): Promise<boolean> {
|
||||
const op = event.argv._[0]
|
||||
const opAsPath = op ? path.resolve(event.cwd, op) : null
|
||||
|
||||
if (opAsPath && (await fs.lstat(opAsPath)).isDirectory()) {
|
||||
this.terminal.openTab(undefined, opAsPath)
|
||||
this.hostApp.bringToFront()
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
@Injectable()
|
||||
export class AutoOpenTabCLIHandler extends CLIHandler {
|
||||
firstMatchOnly = true
|
||||
priority = -1000
|
||||
|
||||
constructor (
|
||||
private app: AppService,
|
||||
private config: ConfigService,
|
||||
private terminal: TerminalService,
|
||||
) {
|
||||
super()
|
||||
}
|
||||
|
||||
async handle (event: CLIEvent): Promise<boolean> {
|
||||
if (!event.secondInstance && this.config.store.terminal.autoOpen) {
|
||||
this.app.ready$.subscribe(() => {
|
||||
this.terminal.openTab()
|
||||
})
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
}
|
@ -2,7 +2,7 @@
|
||||
import { Component } from '@angular/core'
|
||||
import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'
|
||||
import { UACService } from '../services/uac.service'
|
||||
import { Profile } from '../api/interfaces'
|
||||
import { Profile } from '../api'
|
||||
|
||||
/** @hidden */
|
||||
@Component({
|
@ -3,7 +3,7 @@ import { NgbModal } from '@ng-bootstrap/ng-bootstrap'
|
||||
import { Subscription } from 'rxjs'
|
||||
import { ConfigService, ElectronService, HostAppService, Platform, WIN_BUILD_CONPTY_SUPPORTED, WIN_BUILD_CONPTY_STABLE, isWindowsBuild } from 'terminus-core'
|
||||
import { EditProfileModalComponent } from './editProfileModal.component'
|
||||
import { Shell, Profile } from '../api/interfaces'
|
||||
import { Shell, Profile } from '../api'
|
||||
import { TerminalService } from '../services/terminal.service'
|
||||
|
||||
/** @hidden */
|
@ -1,8 +1,8 @@
|
||||
import { Component, Input, Injector } from '@angular/core'
|
||||
import { BaseTabProcess, WIN_BUILD_CONPTY_SUPPORTED, isWindowsBuild } from 'terminus-core'
|
||||
import { BaseTerminalTabComponent } from '../api/baseTerminalTab.component'
|
||||
import { SessionOptions } from '../api/interfaces'
|
||||
import { Session } from '../services/sessions.service'
|
||||
import { BaseTerminalTabComponent } from 'terminus-terminal'
|
||||
import { SessionOptions } from '../api'
|
||||
import { Session } from '../session'
|
||||
|
||||
/** @hidden */
|
||||
@Component({
|
||||
@ -52,13 +52,11 @@ export class TerminalTabComponent extends BaseTerminalTabComponent {
|
||||
}
|
||||
|
||||
initializeSession (columns: number, rows: number): void {
|
||||
this.sessions.addSession(
|
||||
this.session!,
|
||||
Object.assign({}, this.sessionOptions, {
|
||||
width: columns,
|
||||
height: rows,
|
||||
})
|
||||
)
|
||||
this.session!.start({
|
||||
...this.sessionOptions,
|
||||
width: columns,
|
||||
height: rows,
|
||||
})
|
||||
|
||||
this.attachSessionHandlers(true)
|
||||
this.recoveryStateChangedHint.next()
|
62
terminus-local/src/config.ts
Normal file
@ -0,0 +1,62 @@
|
||||
import { ConfigProvider, Platform } from 'terminus-core'
|
||||
|
||||
/** @hidden */
|
||||
export class TerminalConfigProvider extends ConfigProvider {
|
||||
defaults = {
|
||||
hotkeys: {
|
||||
'copy-current-path': [],
|
||||
shell: {
|
||||
__nonStructural: true,
|
||||
},
|
||||
profile: {
|
||||
__nonStructural: true,
|
||||
},
|
||||
},
|
||||
terminal: {
|
||||
autoOpen: false,
|
||||
customShell: '',
|
||||
workingDirectory: '',
|
||||
alwaysUseWorkingDirectory: false,
|
||||
useConPTY: true,
|
||||
showDefaultProfiles: true,
|
||||
environment: {},
|
||||
profiles: [],
|
||||
},
|
||||
}
|
||||
|
||||
platformDefaults = {
|
||||
[Platform.macOS]: {
|
||||
terminal: {
|
||||
shell: 'default',
|
||||
profile: 'user-default',
|
||||
},
|
||||
hotkeys: {
|
||||
'new-tab': [
|
||||
'⌘-T',
|
||||
],
|
||||
},
|
||||
},
|
||||
[Platform.Windows]: {
|
||||
terminal: {
|
||||
shell: 'clink',
|
||||
profile: 'cmd-clink',
|
||||
},
|
||||
hotkeys: {
|
||||
'new-tab': [
|
||||
'Ctrl-Shift-T',
|
||||
],
|
||||
},
|
||||
},
|
||||
[Platform.Linux]: {
|
||||
terminal: {
|
||||
shell: 'default',
|
||||
profile: 'user-default',
|
||||
},
|
||||
hotkeys: {
|
||||
'new-tab': [
|
||||
'Ctrl-Shift-T',
|
||||
],
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
29
terminus-local/src/hotkeys.ts
Normal file
@ -0,0 +1,29 @@
|
||||
import { Injectable } from '@angular/core'
|
||||
import { HotkeyDescription, HotkeyProvider } from 'terminus-core'
|
||||
import { TerminalService } from './services/terminal.service'
|
||||
|
||||
/** @hidden */
|
||||
@Injectable()
|
||||
export class TerminalHotkeyProvider extends HotkeyProvider {
|
||||
hotkeys: HotkeyDescription[] = [
|
||||
{
|
||||
id: 'new-tab',
|
||||
name: 'New tab',
|
||||
},
|
||||
]
|
||||
|
||||
constructor (
|
||||
private terminal: TerminalService,
|
||||
) { super() }
|
||||
|
||||
async provide (): Promise<HotkeyDescription[]> {
|
||||
const profiles = await this.terminal.getProfiles()
|
||||
return [
|
||||
...this.hotkeys,
|
||||
...profiles.map(profile => ({
|
||||
id: `profile.${this.terminal.getProfileID(profile)}`,
|
||||
name: `New tab: ${profile.name}`,
|
||||
})),
|
||||
]
|
||||
}
|
||||
}
|
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.4 KiB |
Before Width: | Height: | Size: 392 B After Width: | Height: | Size: 392 B |
Before Width: | Height: | Size: 392 B After Width: | Height: | Size: 392 B |
Before Width: | Height: | Size: 567 B After Width: | Height: | Size: 567 B |
Before Width: | Height: | Size: 570 B After Width: | Height: | Size: 570 B |
Before Width: | Height: | Size: 315 B After Width: | Height: | Size: 315 B |
Before Width: | Height: | Size: 5.0 KiB After Width: | Height: | Size: 5.0 KiB |
Before Width: | Height: | Size: 718 B After Width: | Height: | Size: 718 B |
Before Width: | Height: | Size: 17 KiB After Width: | Height: | Size: 17 KiB |
Before Width: | Height: | Size: 449 B After Width: | Height: | Size: 449 B |
Before Width: | Height: | Size: 662 B After Width: | Height: | Size: 662 B |
Before Width: | Height: | Size: 660 B After Width: | Height: | Size: 660 B |
Before Width: | Height: | Size: 665 B After Width: | Height: | Size: 665 B |
Before Width: | Height: | Size: 2.8 KiB After Width: | Height: | Size: 2.8 KiB |
Before Width: | Height: | Size: 3.0 KiB After Width: | Height: | Size: 3.0 KiB |
129
terminus-local/src/index.ts
Normal file
@ -0,0 +1,129 @@
|
||||
import { NgModule } from '@angular/core'
|
||||
import { BrowserModule } from '@angular/platform-browser'
|
||||
import { FormsModule } from '@angular/forms'
|
||||
import { NgbModule } from '@ng-bootstrap/ng-bootstrap'
|
||||
import { ToastrModule } from 'ngx-toastr'
|
||||
|
||||
import TerminusCorePlugin, { HostAppService, ToolbarButtonProvider, TabRecoveryProvider, ConfigProvider, HotkeysService, HotkeyProvider, TabContextMenuItemProvider, CLIHandler } from 'terminus-core'
|
||||
import TerminusTerminalModule from 'terminus-terminal'
|
||||
import { SettingsTabProvider } from 'terminus-settings'
|
||||
|
||||
import { TerminalTabComponent } from './components/terminalTab.component'
|
||||
import { ShellSettingsTabComponent } from './components/shellSettingsTab.component'
|
||||
import { EditProfileModalComponent } from './components/editProfileModal.component'
|
||||
import { EnvironmentEditorComponent } from './components/environmentEditor.component'
|
||||
|
||||
import { TerminalService } from './services/terminal.service'
|
||||
import { DockMenuService } from './services/dockMenu.service'
|
||||
|
||||
import { ButtonProvider } from './buttonProvider'
|
||||
import { RecoveryProvider } from './recoveryProvider'
|
||||
import { ShellProvider } from './api'
|
||||
import { ShellSettingsTabProvider } from './settings'
|
||||
import { TerminalConfigProvider } from './config'
|
||||
import { TerminalHotkeyProvider } from './hotkeys'
|
||||
import { NewTabContextMenu, SaveAsProfileContextMenu } from './tabContextMenu'
|
||||
|
||||
import { CmderShellProvider } from './shells/cmder'
|
||||
import { CustomShellProvider } from './shells/custom'
|
||||
import { Cygwin32ShellProvider } from './shells/cygwin32'
|
||||
import { Cygwin64ShellProvider } from './shells/cygwin64'
|
||||
import { GitBashShellProvider } from './shells/gitBash'
|
||||
import { LinuxDefaultShellProvider } from './shells/linuxDefault'
|
||||
import { MacOSDefaultShellProvider } from './shells/macDefault'
|
||||
import { POSIXShellsProvider } from './shells/posix'
|
||||
import { PowerShellCoreShellProvider } from './shells/powershellCore'
|
||||
import { WindowsDefaultShellProvider } from './shells/winDefault'
|
||||
import { WindowsStockShellsProvider } from './shells/windowsStock'
|
||||
import { WSLShellProvider } from './shells/wsl'
|
||||
|
||||
import { AutoOpenTabCLIHandler, OpenPathCLIHandler, TerminalCLIHandler } from './cli'
|
||||
|
||||
/** @hidden */
|
||||
@NgModule({
|
||||
imports: [
|
||||
BrowserModule,
|
||||
FormsModule,
|
||||
NgbModule,
|
||||
ToastrModule,
|
||||
TerminusCorePlugin,
|
||||
TerminusTerminalModule,
|
||||
],
|
||||
providers: [
|
||||
{ provide: SettingsTabProvider, useClass: ShellSettingsTabProvider, multi: true },
|
||||
|
||||
{ provide: ToolbarButtonProvider, useClass: ButtonProvider, multi: true },
|
||||
{ provide: TabRecoveryProvider, useClass: RecoveryProvider, multi: true },
|
||||
{ provide: ConfigProvider, useClass: TerminalConfigProvider, multi: true },
|
||||
{ provide: HotkeyProvider, useClass: TerminalHotkeyProvider, multi: true },
|
||||
|
||||
{ provide: ShellProvider, useClass: WindowsDefaultShellProvider, multi: true },
|
||||
{ provide: ShellProvider, useClass: MacOSDefaultShellProvider, multi: true },
|
||||
{ provide: ShellProvider, useClass: LinuxDefaultShellProvider, multi: true },
|
||||
{ provide: ShellProvider, useClass: WindowsStockShellsProvider, multi: true },
|
||||
{ provide: ShellProvider, useClass: PowerShellCoreShellProvider, multi: true },
|
||||
{ provide: ShellProvider, useClass: CmderShellProvider, multi: true },
|
||||
{ provide: ShellProvider, useClass: CustomShellProvider, multi: true },
|
||||
{ provide: ShellProvider, useClass: Cygwin32ShellProvider, multi: true },
|
||||
{ provide: ShellProvider, useClass: Cygwin64ShellProvider, multi: true },
|
||||
{ provide: ShellProvider, useClass: GitBashShellProvider, multi: true },
|
||||
{ provide: ShellProvider, useClass: POSIXShellsProvider, multi: true },
|
||||
{ provide: ShellProvider, useClass: WSLShellProvider, multi: true },
|
||||
|
||||
{ provide: TabContextMenuItemProvider, useClass: NewTabContextMenu, multi: true },
|
||||
{ provide: TabContextMenuItemProvider, useClass: SaveAsProfileContextMenu, multi: true },
|
||||
|
||||
{ provide: CLIHandler, useClass: TerminalCLIHandler, multi: true },
|
||||
{ provide: CLIHandler, useClass: OpenPathCLIHandler, multi: true },
|
||||
{ provide: CLIHandler, useClass: AutoOpenTabCLIHandler, multi: true },
|
||||
|
||||
// For WindowsDefaultShellProvider
|
||||
PowerShellCoreShellProvider,
|
||||
WSLShellProvider,
|
||||
WindowsStockShellsProvider,
|
||||
],
|
||||
entryComponents: [
|
||||
TerminalTabComponent,
|
||||
ShellSettingsTabComponent,
|
||||
EditProfileModalComponent,
|
||||
] as any[],
|
||||
declarations: [
|
||||
TerminalTabComponent,
|
||||
ShellSettingsTabComponent,
|
||||
EditProfileModalComponent,
|
||||
EnvironmentEditorComponent,
|
||||
] as any[],
|
||||
exports: [
|
||||
TerminalTabComponent,
|
||||
EnvironmentEditorComponent,
|
||||
],
|
||||
})
|
||||
export default class LocalTerminalModule { // eslint-disable-line @typescript-eslint/no-extraneous-class
|
||||
private constructor (
|
||||
hotkeys: HotkeysService,
|
||||
terminal: TerminalService,
|
||||
hostApp: HostAppService,
|
||||
dockMenu: DockMenuService,
|
||||
) {
|
||||
hotkeys.matchedHotkey.subscribe(async (hotkey) => {
|
||||
if (hotkey === 'new-tab') {
|
||||
terminal.openTab()
|
||||
}
|
||||
if (hotkey === 'new-window') {
|
||||
hostApp.newWindow()
|
||||
}
|
||||
if (hotkey.startsWith('profile.')) {
|
||||
const profile = await terminal.getProfileByID(hotkey.split('.')[1])
|
||||
if (profile) {
|
||||
terminal.openTabWithOptions(profile.sessionOptions)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
dockMenu.update()
|
||||
}
|
||||
}
|
||||
|
||||
export { TerminalTabComponent }
|
||||
export { TerminalService, ShellProvider }
|
||||
export * from './api'
|
@ -3,10 +3,9 @@ import slugify from 'slugify'
|
||||
import { Observable, AsyncSubject } from 'rxjs'
|
||||
import { Injectable, Inject } from '@angular/core'
|
||||
import { AppService, Logger, LogService, ConfigService, SplitTabComponent } from 'terminus-core'
|
||||
import { ShellProvider } from '../api/shellProvider'
|
||||
import { Shell, SessionOptions, Profile } from '../api/interfaces'
|
||||
import { TerminalTabComponent } from '../components/terminalTab.component'
|
||||
import { UACService } from './uac.service'
|
||||
import { ShellProvider, Shell, SessionOptions, Profile } from '../api'
|
||||
import { UACService } from '../services/uac.service'
|
||||
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class TerminalService {
|
@ -1,7 +1,7 @@
|
||||
import * as path from 'path'
|
||||
import { Injectable } from '@angular/core'
|
||||
import { ElectronService, WIN_BUILD_CONPTY_SUPPORTED, isWindowsBuild } from 'terminus-core'
|
||||
import { SessionOptions } from '../api/interfaces'
|
||||
import { SessionOptions } from '../api'
|
||||
|
||||
/** @hidden */
|
||||
@Injectable({ providedIn: 'root' })
|
@ -1,13 +1,11 @@
|
||||
import * as psNode from 'ps-node'
|
||||
import * as fs from 'mz/fs'
|
||||
import * as os from 'os'
|
||||
import { BaseSession } from 'terminus-terminal'
|
||||
import { ipcRenderer } from 'electron'
|
||||
import { getWorkingDirectoryFromPID } from 'native-process-working-directory'
|
||||
import { Observable, Subject } from 'rxjs'
|
||||
import { first } from 'rxjs/operators'
|
||||
import { Injectable } from '@angular/core'
|
||||
import { Logger, LogService, ConfigService, WIN_BUILD_CONPTY_SUPPORTED, isWindowsBuild } from 'terminus-core'
|
||||
import { SessionOptions, ChildProcess } from '../api/interfaces'
|
||||
import { ConfigService, WIN_BUILD_CONPTY_SUPPORTED, isWindowsBuild } from 'terminus-core'
|
||||
import { SessionOptions, ChildProcess } from './api'
|
||||
|
||||
/* eslint-disable block-scoped-var */
|
||||
|
||||
@ -85,65 +83,6 @@ export class PTYProxy {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A session object for a [[BaseTerminalTabComponent]]
|
||||
* Extend this to implement custom I/O and process management for your terminal tab
|
||||
*/
|
||||
export abstract class BaseSession {
|
||||
open: boolean
|
||||
name: string
|
||||
truePID: number
|
||||
protected output = new Subject<string>()
|
||||
protected binaryOutput = new Subject<Buffer>()
|
||||
protected closed = new Subject<void>()
|
||||
protected destroyed = new Subject<void>()
|
||||
private initialDataBuffer = Buffer.from('')
|
||||
private initialDataBufferReleased = false
|
||||
|
||||
get output$ (): Observable<string> { return this.output }
|
||||
get binaryOutput$ (): Observable<Buffer> { return this.binaryOutput }
|
||||
get closed$ (): Observable<void> { return this.closed }
|
||||
get destroyed$ (): Observable<void> { return this.destroyed }
|
||||
|
||||
emitOutput (data: Buffer): void {
|
||||
if (!this.initialDataBufferReleased) {
|
||||
this.initialDataBuffer = Buffer.concat([this.initialDataBuffer, data])
|
||||
} else {
|
||||
this.output.next(data.toString())
|
||||
this.binaryOutput.next(data)
|
||||
}
|
||||
}
|
||||
|
||||
releaseInitialDataBuffer (): void {
|
||||
this.initialDataBufferReleased = true
|
||||
this.output.next(this.initialDataBuffer.toString())
|
||||
this.binaryOutput.next(this.initialDataBuffer)
|
||||
this.initialDataBuffer = Buffer.from('')
|
||||
}
|
||||
|
||||
async destroy (): Promise<void> {
|
||||
if (this.open) {
|
||||
this.open = false
|
||||
this.closed.next()
|
||||
this.destroyed.next()
|
||||
this.closed.complete()
|
||||
this.destroyed.complete()
|
||||
this.output.complete()
|
||||
this.binaryOutput.complete()
|
||||
await this.gracefullyKillProcess()
|
||||
}
|
||||
}
|
||||
|
||||
abstract start (options: SessionOptions): void
|
||||
abstract resize (columns: number, rows: number): void
|
||||
abstract write (data: Buffer): void
|
||||
abstract kill (signal?: string): void
|
||||
abstract getChildProcesses (): Promise<ChildProcess[]>
|
||||
abstract gracefullyKillProcess (): Promise<void>
|
||||
abstract supportsWorkingDirectory (): boolean
|
||||
abstract getWorkingDirectory (): Promise<string|null>
|
||||
}
|
||||
|
||||
/** @hidden */
|
||||
export class Session extends BaseSession {
|
||||
private pty: PTYProxy|null = null
|
||||
@ -400,28 +339,3 @@ export class Session extends BaseSession {
|
||||
return data
|
||||
}
|
||||
}
|
||||
|
||||
/** @hidden */
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class SessionsService {
|
||||
sessions = new Map<string, BaseSession>()
|
||||
logger: Logger
|
||||
private lastID = 0
|
||||
|
||||
private constructor (
|
||||
log: LogService,
|
||||
) {
|
||||
this.logger = log.create('sessions')
|
||||
}
|
||||
|
||||
addSession (session: BaseSession, options: SessionOptions): BaseSession {
|
||||
this.lastID++
|
||||
options.name = `session-${this.lastID}`
|
||||
session.start(options)
|
||||
session.destroyed$.pipe(first()).subscribe(() => {
|
||||
this.sessions.delete(session.name)
|
||||
})
|
||||
this.sessions.set(session.name, session)
|
||||
return session
|
||||
}
|
||||
}
|
16
terminus-local/src/settings.ts
Normal file
@ -0,0 +1,16 @@
|
||||
import { Injectable } from '@angular/core'
|
||||
import { SettingsTabProvider } from 'terminus-settings'
|
||||
|
||||
import { ShellSettingsTabComponent } from './components/shellSettingsTab.component'
|
||||
|
||||
/** @hidden */
|
||||
@Injectable()
|
||||
export class ShellSettingsTabProvider extends SettingsTabProvider {
|
||||
id = 'terminal-shell'
|
||||
icon = 'list-ul'
|
||||
title = 'Shell'
|
||||
|
||||
getComponentType (): any {
|
||||
return ShellSettingsTabComponent
|
||||
}
|
||||
}
|
@ -2,8 +2,7 @@ import * as path from 'path'
|
||||
import { Injectable } from '@angular/core'
|
||||
import { HostAppService, Platform } from 'terminus-core'
|
||||
|
||||
import { ShellProvider } from '../api/shellProvider'
|
||||
import { Shell } from '../api/interfaces'
|
||||
import { ShellProvider, Shell } from '../api'
|
||||
|
||||
/** @hidden */
|
||||
@Injectable()
|
@ -1,8 +1,7 @@
|
||||
import { Injectable } from '@angular/core'
|
||||
import { ConfigService } from 'terminus-core'
|
||||
|
||||
import { ShellProvider } from '../api/shellProvider'
|
||||
import { Shell } from '../api/interfaces'
|
||||
import { ShellProvider, Shell } from '../api'
|
||||
|
||||
/** @hidden */
|
||||
@Injectable()
|
@ -2,8 +2,7 @@ import * as path from 'path'
|
||||
import { Injectable } from '@angular/core'
|
||||
import { HostAppService, Platform } from 'terminus-core'
|
||||
|
||||
import { ShellProvider } from '../api/shellProvider'
|
||||
import { Shell } from '../api/interfaces'
|
||||
import { ShellProvider, Shell } from '../api'
|
||||
|
||||
/* eslint-disable block-scoped-var */
|
||||
|
@ -2,8 +2,7 @@ import * as path from 'path'
|
||||
import { Injectable } from '@angular/core'
|
||||
import { HostAppService, Platform } from 'terminus-core'
|
||||
|
||||
import { ShellProvider } from '../api/shellProvider'
|
||||
import { Shell } from '../api/interfaces'
|
||||
import { ShellProvider, Shell } from '../api'
|
||||
|
||||
/* eslint-disable block-scoped-var */
|
||||
|
@ -2,8 +2,7 @@ import * as path from 'path'
|
||||
import { Injectable } from '@angular/core'
|
||||
import { HostAppService, Platform } from 'terminus-core'
|
||||
|
||||
import { ShellProvider } from '../api/shellProvider'
|
||||
import { Shell } from '../api/interfaces'
|
||||
import { ShellProvider, Shell } from '../api'
|
||||
|
||||
/* eslint-disable block-scoped-var */
|
||||
|
@ -2,8 +2,7 @@ import * as fs from 'mz/fs'
|
||||
import { Injectable } from '@angular/core'
|
||||
import { HostAppService, Platform, LogService, Logger } from 'terminus-core'
|
||||
|
||||
import { ShellProvider } from '../api/shellProvider'
|
||||
import { Shell } from '../api/interfaces'
|
||||
import { ShellProvider, Shell } from '../api'
|
||||
|
||||
/** @hidden */
|
||||
@Injectable()
|
@ -2,8 +2,7 @@ import { exec } from 'mz/child_process'
|
||||
import { Injectable } from '@angular/core'
|
||||
import { HostAppService, Platform } from 'terminus-core'
|
||||
|
||||
import { ShellProvider } from '../api/shellProvider'
|
||||
import { Shell } from '../api/interfaces'
|
||||
import { ShellProvider, Shell } from '../api'
|
||||
|
||||
/** @hidden */
|
||||
@Injectable()
|
@ -3,8 +3,7 @@ import slugify from 'slugify'
|
||||
import { Injectable } from '@angular/core'
|
||||
import { HostAppService, Platform } from 'terminus-core'
|
||||
|
||||
import { ShellProvider } from '../api/shellProvider'
|
||||
import { Shell } from '../api/interfaces'
|
||||
import { ShellProvider, Shell } from '../api'
|
||||
|
||||
/** @hidden */
|
||||
@Injectable()
|
@ -1,7 +1,7 @@
|
||||
import { Injectable } from '@angular/core'
|
||||
import { HostAppService, Platform } from 'terminus-core'
|
||||
import { ShellProvider } from '../api/shellProvider'
|
||||
import { Shell } from '../api/interfaces'
|
||||
|
||||
import { ShellProvider, Shell } from '../api'
|
||||
|
||||
/* eslint-disable block-scoped-var */
|
||||
|
@ -1,8 +1,7 @@
|
||||
import { Injectable } from '@angular/core'
|
||||
import { HostAppService, Platform } from 'terminus-core'
|
||||
|
||||
import { ShellProvider } from '../api/shellProvider'
|
||||
import { Shell } from '../api/interfaces'
|
||||
import { ShellProvider, Shell } from '../api'
|
||||
|
||||
import { WSLShellProvider } from './wsl'
|
||||
import { PowerShellCoreShellProvider } from './powershellCore'
|
@ -2,8 +2,7 @@ import * as path from 'path'
|
||||
import { Injectable } from '@angular/core'
|
||||
import { HostAppService, Platform, ElectronService } from 'terminus-core'
|
||||
|
||||
import { ShellProvider } from '../api/shellProvider'
|
||||
import { Shell } from '../api/interfaces'
|
||||
import { ShellProvider, Shell } from '../api'
|
||||
|
||||
/** @hidden */
|
||||
@Injectable()
|
@ -4,8 +4,7 @@ import slugify from 'slugify'
|
||||
import { Injectable } from '@angular/core'
|
||||
import { HostAppService, Platform, isWindowsBuild, WIN_BUILD_WSL_EXE_DISTRO_FLAG } from 'terminus-core'
|
||||
|
||||
import { ShellProvider } from '../api/shellProvider'
|
||||
import { Shell } from '../api/interfaces'
|
||||
import { ShellProvider, Shell } from '../api'
|
||||
|
||||
/* eslint-disable block-scoped-var */
|
||||
|
132
terminus-local/src/tabContextMenu.ts
Normal file
@ -0,0 +1,132 @@
|
||||
import { MenuItemConstructorOptions } from 'electron'
|
||||
import { Injectable, NgZone } from '@angular/core'
|
||||
import { ConfigService, BaseTabComponent, TabContextMenuItemProvider, TabHeaderComponent, SplitTabComponent, NotificationsService } from 'terminus-core'
|
||||
import { TerminalTabComponent } from './components/terminalTab.component'
|
||||
import { UACService } from './services/uac.service'
|
||||
import { TerminalService } from './services/terminal.service'
|
||||
|
||||
/** @hidden */
|
||||
@Injectable()
|
||||
export class SaveAsProfileContextMenu extends TabContextMenuItemProvider {
|
||||
constructor (
|
||||
private config: ConfigService,
|
||||
private zone: NgZone,
|
||||
private notifications: NotificationsService,
|
||||
) {
|
||||
super()
|
||||
}
|
||||
|
||||
async getItems (tab: BaseTabComponent, _tabHeader?: TabHeaderComponent): Promise<MenuItemConstructorOptions[]> {
|
||||
if (!(tab instanceof TerminalTabComponent)) {
|
||||
return []
|
||||
}
|
||||
const items: MenuItemConstructorOptions[] = [
|
||||
{
|
||||
label: 'Save as profile',
|
||||
click: () => this.zone.run(async () => {
|
||||
const profile = {
|
||||
sessionOptions: {
|
||||
...tab.sessionOptions,
|
||||
cwd: await tab.session?.getWorkingDirectory() ?? tab.sessionOptions.cwd,
|
||||
},
|
||||
name: tab.sessionOptions.command,
|
||||
}
|
||||
this.config.store.terminal.profiles = [
|
||||
...this.config.store.terminal.profiles,
|
||||
profile,
|
||||
]
|
||||
this.config.save()
|
||||
this.notifications.info('Saved')
|
||||
}),
|
||||
},
|
||||
]
|
||||
|
||||
return items
|
||||
}
|
||||
}
|
||||
|
||||
/** @hidden */
|
||||
@Injectable()
|
||||
export class NewTabContextMenu extends TabContextMenuItemProvider {
|
||||
weight = 10
|
||||
|
||||
constructor (
|
||||
public config: ConfigService,
|
||||
private zone: NgZone,
|
||||
private terminalService: TerminalService,
|
||||
private uac: UACService,
|
||||
) {
|
||||
super()
|
||||
}
|
||||
|
||||
async getItems (tab: BaseTabComponent, tabHeader?: TabHeaderComponent): Promise<MenuItemConstructorOptions[]> {
|
||||
const profiles = await this.terminalService.getProfiles()
|
||||
|
||||
const items: MenuItemConstructorOptions[] = [
|
||||
{
|
||||
label: 'New terminal',
|
||||
click: () => this.zone.run(() => {
|
||||
this.terminalService.openTabWithOptions((tab as any).sessionOptions)
|
||||
}),
|
||||
},
|
||||
{
|
||||
label: 'New with profile',
|
||||
submenu: profiles.map(profile => ({
|
||||
label: profile.name,
|
||||
click: () => this.zone.run(async () => {
|
||||
let workingDirectory = this.config.store.terminal.workingDirectory
|
||||
if (this.config.store.terminal.alwaysUseWorkingDirectory !== true && tab instanceof TerminalTabComponent) {
|
||||
workingDirectory = await tab.session?.getWorkingDirectory()
|
||||
}
|
||||
await this.terminalService.openTab(profile, workingDirectory)
|
||||
}),
|
||||
})),
|
||||
},
|
||||
]
|
||||
|
||||
if (this.uac.isAvailable) {
|
||||
items.push({
|
||||
label: 'New admin tab',
|
||||
submenu: profiles.map(profile => ({
|
||||
label: profile.name,
|
||||
click: () => this.zone.run(async () => {
|
||||
this.terminalService.openTabWithOptions({
|
||||
...profile.sessionOptions,
|
||||
runAsAdministrator: true,
|
||||
})
|
||||
}),
|
||||
})),
|
||||
})
|
||||
}
|
||||
|
||||
if (tab instanceof TerminalTabComponent && tabHeader && this.uac.isAvailable) {
|
||||
items.push({
|
||||
label: 'Duplicate as administrator',
|
||||
click: () => this.zone.run(async () => {
|
||||
this.terminalService.openTabWithOptions({
|
||||
...tab.sessionOptions,
|
||||
runAsAdministrator: true,
|
||||
})
|
||||
}),
|
||||
})
|
||||
}
|
||||
|
||||
if (tab instanceof TerminalTabComponent && tab.parent instanceof SplitTabComponent && tab.parent.getAllTabs().length > 1) {
|
||||
items.push({
|
||||
label: 'Focus all panes',
|
||||
click: () => this.zone.run(() => {
|
||||
tab.focusAllPanes()
|
||||
}),
|
||||
})
|
||||
}
|
||||
|
||||
if (tab instanceof TerminalTabComponent && tab.session?.supportsWorkingDirectory()) {
|
||||
items.push({
|
||||
label: 'Copy current path',
|
||||
click: () => this.zone.run(() => tab.copyCurrentPath()),
|
||||
})
|
||||
}
|
||||
|
||||
return items
|
||||
}
|
||||
}
|
7
terminus-local/tsconfig.json
Normal file
@ -0,0 +1,7 @@
|
||||
{
|
||||
"extends": "../tsconfig.json",
|
||||
"exclude": ["node_modules", "dist", "typings"],
|
||||
"compilerOptions": {
|
||||
"baseUrl": "src"
|
||||
}
|
||||
}
|
16
terminus-local/tsconfig.typings.json
Normal file
@ -0,0 +1,16 @@
|
||||
{
|
||||
"extends": "../tsconfig.json",
|
||||
"exclude": ["node_modules", "dist", "typings"],
|
||||
"compilerOptions": {
|
||||
"baseUrl": "src",
|
||||
"emitDeclarationOnly": true,
|
||||
"declaration": true,
|
||||
"declarationDir": "./typings",
|
||||
"paths": {
|
||||
"terminus-*": ["../../terminus-*"],
|
||||
"*": [
|
||||
"../../app/node_modules/*"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
5
terminus-local/webpack.config.js
Normal file
@ -0,0 +1,5 @@
|
||||
const config = require('../webpack.plugin.config')
|
||||
module.exports = config({
|
||||
name: 'local',
|
||||
dirname: __dirname,
|
||||
})
|
515
terminus-local/yarn.lock
Normal file
@ -0,0 +1,515 @@
|
||||
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
|
||||
# yarn lockfile v1
|
||||
|
||||
|
||||
"@types/deep-equal@^1.0.0":
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/@types/deep-equal/-/deep-equal-1.0.1.tgz#71cfabb247c22bcc16d536111f50c0ed12476b03"
|
||||
integrity sha512-mMUu4nWHLBlHtxXY17Fg6+ucS/MnndyOWyOe7MmwkoMYxvfQU2ajtRaEvqSUv+aVkMqH/C0NCI8UoVfRNQ10yg==
|
||||
|
||||
"@types/shell-escape@^0.2.0":
|
||||
version "0.2.0"
|
||||
resolved "https://registry.yarnpkg.com/@types/shell-escape/-/shell-escape-0.2.0.tgz#cd2f0df814388599dd07196dcc510de2669d1ed2"
|
||||
integrity sha512-7kUdtJtUylvyISJbe9FMcvMTjRdP0EvNDO1WbT0lT22k/IPBiPRTpmWaKu5HTWLCGLQRWVHrzVHZktTDvvR23g==
|
||||
|
||||
ansi-colors@^4.1.1:
|
||||
version "4.1.1"
|
||||
resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.1.tgz#cbb9ae256bf750af1eab344f229aa27fe94ba348"
|
||||
integrity sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==
|
||||
|
||||
any-promise@^1.0.0:
|
||||
version "1.3.0"
|
||||
resolved "https://registry.yarnpkg.com/any-promise/-/any-promise-1.3.0.tgz#abc6afeedcea52e809cdc0376aed3ce39635d17f"
|
||||
integrity sha1-q8av7tzqUugJzcA3au0845Y10X8=
|
||||
|
||||
array-filter@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/array-filter/-/array-filter-1.0.0.tgz#baf79e62e6ef4c2a4c0b831232daffec251f9d83"
|
||||
integrity sha1-uveeYubvTCpMC4MSMtr/7CUfnYM=
|
||||
|
||||
available-typed-arrays@^1.0.2:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/available-typed-arrays/-/available-typed-arrays-1.0.2.tgz#6b098ca9d8039079ee3f77f7b783c4480ba513f5"
|
||||
integrity sha512-XWX3OX8Onv97LMk/ftVyBibpGwY5a8SmuxZPzeOxqmuEqUCOM9ZE+uIaD1VNJ5QnvU2UQusvmKbuM1FR8QWGfQ==
|
||||
dependencies:
|
||||
array-filter "^1.0.0"
|
||||
|
||||
call-bind@^1.0.0, call-bind@^1.0.2:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.2.tgz#b1d4e89e688119c3c9a903ad30abb2f6a919be3c"
|
||||
integrity sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==
|
||||
dependencies:
|
||||
function-bind "^1.1.1"
|
||||
get-intrinsic "^1.0.2"
|
||||
|
||||
connected-domain@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/connected-domain/-/connected-domain-1.0.0.tgz#bfe77238c74be453a79f0cb6058deeb4f2358e93"
|
||||
integrity sha1-v+dyOMdL5FOnnwy2BY3utPI1jpM=
|
||||
|
||||
dataurl@0.1.0:
|
||||
version "0.1.0"
|
||||
resolved "https://registry.yarnpkg.com/dataurl/-/dataurl-0.1.0.tgz#1f4734feddec05ffe445747978d86759c4b33199"
|
||||
integrity sha1-H0c0/t3sBf/kRXR5eNhnWcSzMZk=
|
||||
|
||||
deep-equal@2.0.5:
|
||||
version "2.0.5"
|
||||
resolved "https://registry.yarnpkg.com/deep-equal/-/deep-equal-2.0.5.tgz#55cd2fe326d83f9cbf7261ef0e060b3f724c5cb9"
|
||||
integrity sha512-nPiRgmbAtm1a3JsnLCf6/SLfXcjyN5v8L1TXzdCmHrXJ4hx+gW/w1YCcn7z8gJtSiDArZCgYtbao3QqLm/N1Sw==
|
||||
dependencies:
|
||||
call-bind "^1.0.0"
|
||||
es-get-iterator "^1.1.1"
|
||||
get-intrinsic "^1.0.1"
|
||||
is-arguments "^1.0.4"
|
||||
is-date-object "^1.0.2"
|
||||
is-regex "^1.1.1"
|
||||
isarray "^2.0.5"
|
||||
object-is "^1.1.4"
|
||||
object-keys "^1.1.1"
|
||||
object.assign "^4.1.2"
|
||||
regexp.prototype.flags "^1.3.0"
|
||||
side-channel "^1.0.3"
|
||||
which-boxed-primitive "^1.0.1"
|
||||
which-collection "^1.0.1"
|
||||
which-typed-array "^1.1.2"
|
||||
|
||||
define-properties@^1.1.3:
|
||||
version "1.1.3"
|
||||
resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.3.tgz#cf88da6cbee26fe6db7094f61d870cbd84cee9f1"
|
||||
integrity sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==
|
||||
dependencies:
|
||||
object-keys "^1.0.12"
|
||||
|
||||
es-abstract@^1.18.0-next.1:
|
||||
version "1.18.0-next.1"
|
||||
resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.18.0-next.1.tgz#6e3a0a4bda717e5023ab3b8e90bec36108d22c68"
|
||||
integrity sha512-I4UGspA0wpZXWENrdA0uHbnhte683t3qT/1VFH9aX2dA5PPSf6QW5HHXf5HImaqPmjXaVeVk4RGWnaylmV7uAA==
|
||||
dependencies:
|
||||
es-to-primitive "^1.2.1"
|
||||
function-bind "^1.1.1"
|
||||
has "^1.0.3"
|
||||
has-symbols "^1.0.1"
|
||||
is-callable "^1.2.2"
|
||||
is-negative-zero "^2.0.0"
|
||||
is-regex "^1.1.1"
|
||||
object-inspect "^1.8.0"
|
||||
object-keys "^1.1.1"
|
||||
object.assign "^4.1.1"
|
||||
string.prototype.trimend "^1.0.1"
|
||||
string.prototype.trimstart "^1.0.1"
|
||||
|
||||
es-abstract@^1.18.0-next.2:
|
||||
version "1.18.0"
|
||||
resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.18.0.tgz#ab80b359eecb7ede4c298000390bc5ac3ec7b5a4"
|
||||
integrity sha512-LJzK7MrQa8TS0ja2w3YNLzUgJCGPdPOV1yVvezjNnS89D+VR08+Szt2mz3YB2Dck/+w5tfIq/RoUAFqJJGM2yw==
|
||||
dependencies:
|
||||
call-bind "^1.0.2"
|
||||
es-to-primitive "^1.2.1"
|
||||
function-bind "^1.1.1"
|
||||
get-intrinsic "^1.1.1"
|
||||
has "^1.0.3"
|
||||
has-symbols "^1.0.2"
|
||||
is-callable "^1.2.3"
|
||||
is-negative-zero "^2.0.1"
|
||||
is-regex "^1.1.2"
|
||||
is-string "^1.0.5"
|
||||
object-inspect "^1.9.0"
|
||||
object-keys "^1.1.1"
|
||||
object.assign "^4.1.2"
|
||||
string.prototype.trimend "^1.0.4"
|
||||
string.prototype.trimstart "^1.0.4"
|
||||
unbox-primitive "^1.0.0"
|
||||
|
||||
es-get-iterator@^1.1.1:
|
||||
version "1.1.2"
|
||||
resolved "https://registry.yarnpkg.com/es-get-iterator/-/es-get-iterator-1.1.2.tgz#9234c54aba713486d7ebde0220864af5e2b283f7"
|
||||
integrity sha512-+DTO8GYwbMCwbywjimwZMHp8AuYXOS2JZFWoi2AlPOS3ebnII9w/NLpNZtA7A0YLaVDw+O7KFCeoIV7OPvM7hQ==
|
||||
dependencies:
|
||||
call-bind "^1.0.2"
|
||||
get-intrinsic "^1.1.0"
|
||||
has-symbols "^1.0.1"
|
||||
is-arguments "^1.1.0"
|
||||
is-map "^2.0.2"
|
||||
is-set "^2.0.2"
|
||||
is-string "^1.0.5"
|
||||
isarray "^2.0.5"
|
||||
|
||||
es-to-primitive@^1.2.1:
|
||||
version "1.2.1"
|
||||
resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.2.1.tgz#e55cd4c9cdc188bcefb03b366c736323fc5c898a"
|
||||
integrity sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==
|
||||
dependencies:
|
||||
is-callable "^1.1.4"
|
||||
is-date-object "^1.0.1"
|
||||
is-symbol "^1.0.2"
|
||||
|
||||
foreach@^2.0.5:
|
||||
version "2.0.5"
|
||||
resolved "https://registry.yarnpkg.com/foreach/-/foreach-2.0.5.tgz#0bee005018aeb260d0a3af3ae658dd0136ec1b99"
|
||||
integrity sha1-C+4AUBiusmDQo6865ljdATbsG5k=
|
||||
|
||||
function-bind@^1.1.1:
|
||||
version "1.1.1"
|
||||
resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d"
|
||||
integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==
|
||||
|
||||
get-intrinsic@^1.0.1, get-intrinsic@^1.0.2, get-intrinsic@^1.1.0, get-intrinsic@^1.1.1:
|
||||
version "1.1.1"
|
||||
resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.1.1.tgz#15f59f376f855c446963948f0d24cd3637b4abc6"
|
||||
integrity sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==
|
||||
dependencies:
|
||||
function-bind "^1.1.1"
|
||||
has "^1.0.3"
|
||||
has-symbols "^1.0.1"
|
||||
|
||||
has-bigints@^1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/has-bigints/-/has-bigints-1.0.1.tgz#64fe6acb020673e3b78db035a5af69aa9d07b113"
|
||||
integrity sha512-LSBS2LjbNBTf6287JEbEzvJgftkF5qFkmCo9hDRpAzKhUOlJ+hx8dd4USs00SgsUNwc4617J9ki5YtEClM2ffA==
|
||||
|
||||
has-symbols@^1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.1.tgz#9f5214758a44196c406d9bd76cebf81ec2dd31e8"
|
||||
integrity sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==
|
||||
|
||||
has-symbols@^1.0.2:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.2.tgz#165d3070c00309752a1236a479331e3ac56f1423"
|
||||
integrity sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==
|
||||
|
||||
has@^1.0.3:
|
||||
version "1.0.3"
|
||||
resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796"
|
||||
integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==
|
||||
dependencies:
|
||||
function-bind "^1.1.1"
|
||||
|
||||
hterm-umdjs@1.4.1:
|
||||
version "1.4.1"
|
||||
resolved "https://registry.yarnpkg.com/hterm-umdjs/-/hterm-umdjs-1.4.1.tgz#0cd5352eaf927c70b83c36146cf2c2a281dba957"
|
||||
integrity sha512-r5JOmdDK1bZCmp3cKcuGRLVeum33H+pzD119ZxmQou+QUVe6SAVSz03HvKWVhM2Ao1Biv+fkhFDmnsaRPq0tFg==
|
||||
|
||||
is-arguments@^1.0.4, is-arguments@^1.1.0:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/is-arguments/-/is-arguments-1.1.0.tgz#62353031dfbee07ceb34656a6bde59efecae8dd9"
|
||||
integrity sha512-1Ij4lOMPl/xB5kBDn7I+b2ttPMKa8szhEIrXDuXQD/oe3HJLTLhqhgGspwgyGd6MOywBUqVvYicF72lkgDnIHg==
|
||||
dependencies:
|
||||
call-bind "^1.0.0"
|
||||
|
||||
is-bigint@^1.0.1:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/is-bigint/-/is-bigint-1.0.2.tgz#ffb381442503235ad245ea89e45b3dbff040ee5a"
|
||||
integrity sha512-0JV5+SOCQkIdzjBK9buARcV804Ddu7A0Qet6sHi3FimE9ne6m4BGQZfRn+NZiXbBk4F4XmHfDZIipLj9pX8dSA==
|
||||
|
||||
is-boolean-object@^1.1.0:
|
||||
version "1.1.1"
|
||||
resolved "https://registry.yarnpkg.com/is-boolean-object/-/is-boolean-object-1.1.1.tgz#3c0878f035cb821228d350d2e1e36719716a3de8"
|
||||
integrity sha512-bXdQWkECBUIAcCkeH1unwJLIpZYaa5VvuygSyS/c2lf719mTKZDU5UdDRlpd01UjADgmW8RfqaP+mRaVPdr/Ng==
|
||||
dependencies:
|
||||
call-bind "^1.0.2"
|
||||
|
||||
is-callable@^1.1.4, is-callable@^1.2.2:
|
||||
version "1.2.2"
|
||||
resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.2.tgz#c7c6715cd22d4ddb48d3e19970223aceabb080d9"
|
||||
integrity sha512-dnMqspv5nU3LoewK2N/y7KLtxtakvTuaCsU9FU50/QDmdbHNy/4/JuRtMHqRU22o3q+W89YQndQEeCVwK+3qrA==
|
||||
|
||||
is-callable@^1.2.3:
|
||||
version "1.2.3"
|
||||
resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.3.tgz#8b1e0500b73a1d76c70487636f368e519de8db8e"
|
||||
integrity sha512-J1DcMe8UYTBSrKezuIUTUwjXsho29693unXM2YhJUTR2txK/eG47bvNa/wipPFmZFgr/N6f1GA66dv0mEyTIyQ==
|
||||
|
||||
is-date-object@^1.0.1, is-date-object@^1.0.2:
|
||||
version "1.0.4"
|
||||
resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.4.tgz#550cfcc03afada05eea3dd30981c7b09551f73e5"
|
||||
integrity sha512-/b4ZVsG7Z5XVtIxs/h9W8nvfLgSAyKYdtGWQLbqy6jA1icmgjf8WCoTKgeS4wy5tYaPePouzFMANbnj94c2Z+A==
|
||||
|
||||
is-map@^2.0.1, is-map@^2.0.2:
|
||||
version "2.0.2"
|
||||
resolved "https://registry.yarnpkg.com/is-map/-/is-map-2.0.2.tgz#00922db8c9bf73e81b7a335827bc2a43f2b91127"
|
||||
integrity sha512-cOZFQQozTha1f4MxLFzlgKYPTyj26picdZTx82hbc/Xf4K/tZOOXSCkMvU4pKioRXGDLJRn0GM7Upe7kR721yg==
|
||||
|
||||
is-negative-zero@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/is-negative-zero/-/is-negative-zero-2.0.0.tgz#9553b121b0fac28869da9ed459e20c7543788461"
|
||||
integrity sha1-lVOxIbD6wohp2p7UWeIMdUN4hGE=
|
||||
|
||||
is-negative-zero@^2.0.1:
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/is-negative-zero/-/is-negative-zero-2.0.1.tgz#3de746c18dda2319241a53675908d8f766f11c24"
|
||||
integrity sha512-2z6JzQvZRa9A2Y7xC6dQQm4FSTSTNWjKIYYTt4246eMTJmIo0Q+ZyOsU66X8lxK1AbB92dFeglPLrhwpeRKO6w==
|
||||
|
||||
is-number-object@^1.0.4:
|
||||
version "1.0.5"
|
||||
resolved "https://registry.yarnpkg.com/is-number-object/-/is-number-object-1.0.5.tgz#6edfaeed7950cff19afedce9fbfca9ee6dd289eb"
|
||||
integrity sha512-RU0lI/n95pMoUKu9v1BZP5MBcZuNSVJkMkAG2dJqC4z2GlkGUNeH68SuHuBKBD/XFe+LHZ+f9BKkLET60Niedw==
|
||||
|
||||
is-regex@^1.1.1, is-regex@^1.1.2:
|
||||
version "1.1.3"
|
||||
resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.1.3.tgz#d029f9aff6448b93ebbe3f33dac71511fdcbef9f"
|
||||
integrity sha512-qSVXFz28HM7y+IWX6vLCsexdlvzT1PJNFSBuaQLQ5o0IEw8UDYW6/2+eCMVyIsbM8CNLX2a/QWmSpyxYEHY7CQ==
|
||||
dependencies:
|
||||
call-bind "^1.0.2"
|
||||
has-symbols "^1.0.2"
|
||||
|
||||
is-set@^2.0.1, is-set@^2.0.2:
|
||||
version "2.0.2"
|
||||
resolved "https://registry.yarnpkg.com/is-set/-/is-set-2.0.2.tgz#90755fa4c2562dc1c5d4024760d6119b94ca18ec"
|
||||
integrity sha512-+2cnTEZeY5z/iXGbLhPrOAaK/Mau5k5eXq9j14CpRTftq0pAJu2MwVRSZhyZWBzx3o6X795Lz6Bpb6R0GKf37g==
|
||||
|
||||
is-string@^1.0.5:
|
||||
version "1.0.6"
|
||||
resolved "https://registry.yarnpkg.com/is-string/-/is-string-1.0.6.tgz#3fe5d5992fb0d93404f32584d4b0179a71b54a5f"
|
||||
integrity sha512-2gdzbKUuqtQ3lYNrUTQYoClPhm7oQu4UdpSZMp1/DGgkHBT8E2Z1l0yMdb6D4zNAxwDiMv8MdulKROJGNl0Q0w==
|
||||
|
||||
is-symbol@^1.0.2:
|
||||
version "1.0.3"
|
||||
resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.3.tgz#38e1014b9e6329be0de9d24a414fd7441ec61937"
|
||||
integrity sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ==
|
||||
dependencies:
|
||||
has-symbols "^1.0.1"
|
||||
|
||||
is-symbol@^1.0.3:
|
||||
version "1.0.4"
|
||||
resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.4.tgz#a6dac93b635b063ca6872236de88910a57af139c"
|
||||
integrity sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==
|
||||
dependencies:
|
||||
has-symbols "^1.0.2"
|
||||
|
||||
is-typed-array@^1.1.3:
|
||||
version "1.1.5"
|
||||
resolved "https://registry.yarnpkg.com/is-typed-array/-/is-typed-array-1.1.5.tgz#f32e6e096455e329eb7b423862456aa213f0eb4e"
|
||||
integrity sha512-S+GRDgJlR3PyEbsX/Fobd9cqpZBuvUS+8asRqYDMLCb2qMzt1oz5m5oxQCxOgUDxiWsOVNi4yaF+/uvdlHlYug==
|
||||
dependencies:
|
||||
available-typed-arrays "^1.0.2"
|
||||
call-bind "^1.0.2"
|
||||
es-abstract "^1.18.0-next.2"
|
||||
foreach "^2.0.5"
|
||||
has-symbols "^1.0.1"
|
||||
|
||||
is-weakmap@^2.0.1:
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/is-weakmap/-/is-weakmap-2.0.1.tgz#5008b59bdc43b698201d18f62b37b2ca243e8cf2"
|
||||
integrity sha512-NSBR4kH5oVj1Uwvv970ruUkCV7O1mzgVFO4/rev2cLRda9Tm9HrL70ZPut4rOHgY0FNrUu9BCbXA2sdQ+x0chA==
|
||||
|
||||
is-weakset@^2.0.1:
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/is-weakset/-/is-weakset-2.0.1.tgz#e9a0af88dbd751589f5e50d80f4c98b780884f83"
|
||||
integrity sha512-pi4vhbhVHGLxohUw7PhGsueT4vRGFoXhP7+RGN0jKIv9+8PWYCQTqtADngrxOm2g46hoH0+g8uZZBzMrvVGDmw==
|
||||
|
||||
isarray@^2.0.5:
|
||||
version "2.0.5"
|
||||
resolved "https://registry.yarnpkg.com/isarray/-/isarray-2.0.5.tgz#8af1e4c1221244cc62459faf38940d4e644a5723"
|
||||
integrity sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==
|
||||
|
||||
mz@^2.6.0:
|
||||
version "2.7.0"
|
||||
resolved "https://registry.yarnpkg.com/mz/-/mz-2.7.0.tgz#95008057a56cafadc2bc63dde7f9ff6955948e32"
|
||||
integrity sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==
|
||||
dependencies:
|
||||
any-promise "^1.0.0"
|
||||
object-assign "^4.0.1"
|
||||
thenify-all "^1.0.0"
|
||||
|
||||
object-assign@^4.0.1:
|
||||
version "4.1.1"
|
||||
resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863"
|
||||
integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=
|
||||
|
||||
object-inspect@^1.8.0:
|
||||
version "1.8.0"
|
||||
resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.8.0.tgz#df807e5ecf53a609cc6bfe93eac3cc7be5b3a9d0"
|
||||
integrity sha512-jLdtEOB112fORuypAyl/50VRVIBIdVQOSUUGQHzJ4xBSbit81zRarz7GThkEFZy1RceYrWYcPcBFPQwHyAc1gA==
|
||||
|
||||
object-inspect@^1.9.0:
|
||||
version "1.10.3"
|
||||
resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.10.3.tgz#c2aa7d2d09f50c99375704f7a0adf24c5782d369"
|
||||
integrity sha512-e5mCJlSH7poANfC8z8S9s9S2IN5/4Zb3aZ33f5s8YqoazCFzNLloLU8r5VCG+G7WoqLvAAZoVMcy3tp/3X0Plw==
|
||||
|
||||
object-is@^1.1.4:
|
||||
version "1.1.5"
|
||||
resolved "https://registry.yarnpkg.com/object-is/-/object-is-1.1.5.tgz#b9deeaa5fc7f1846a0faecdceec138e5778f53ac"
|
||||
integrity sha512-3cyDsyHgtmi7I7DfSSI2LDp6SK2lwvtbg0p0R1e0RvTqF5ceGx+K2dfSjm1bKDMVCFEDAQvy+o8c6a7VujOddw==
|
||||
dependencies:
|
||||
call-bind "^1.0.2"
|
||||
define-properties "^1.1.3"
|
||||
|
||||
object-keys@^1.0.12, object-keys@^1.1.1:
|
||||
version "1.1.1"
|
||||
resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e"
|
||||
integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==
|
||||
|
||||
object.assign@^4.1.1, object.assign@^4.1.2:
|
||||
version "4.1.2"
|
||||
resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.2.tgz#0ed54a342eceb37b38ff76eb831a0e788cb63940"
|
||||
integrity sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ==
|
||||
dependencies:
|
||||
call-bind "^1.0.0"
|
||||
define-properties "^1.1.3"
|
||||
has-symbols "^1.0.1"
|
||||
object-keys "^1.1.1"
|
||||
|
||||
opentype.js@^1.3.3:
|
||||
version "1.3.3"
|
||||
resolved "https://registry.yarnpkg.com/opentype.js/-/opentype.js-1.3.3.tgz#65b8645b090a1ad444065b784d442fa19d1061f6"
|
||||
integrity sha512-/qIY/+WnKGlPIIPhbeNjynfD2PO15G9lA/xqlX2bDH+4lc3Xz5GCQ68mqxj3DdUv6AJqCeaPvuAoH8mVL0zcuA==
|
||||
dependencies:
|
||||
string.prototype.codepointat "^0.2.1"
|
||||
tiny-inflate "^1.0.3"
|
||||
|
||||
ps-node@^0.1.6:
|
||||
version "0.1.6"
|
||||
resolved "https://registry.yarnpkg.com/ps-node/-/ps-node-0.1.6.tgz#9af67a99d7b1d0132e51a503099d38a8d2ace2c3"
|
||||
integrity sha1-mvZ6mdex0BMuUaUDCZ04qNKs4sM=
|
||||
dependencies:
|
||||
table-parser "^0.1.3"
|
||||
|
||||
regexp.prototype.flags@^1.3.0:
|
||||
version "1.3.1"
|
||||
resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.3.1.tgz#7ef352ae8d159e758c0eadca6f8fcb4eef07be26"
|
||||
integrity sha512-JiBdRBq91WlY7uRJ0ds7R+dU02i6LKi8r3BuQhNXn+kmeLN+EfHhfjqMRis1zJxnlu88hq/4dx0P2OP3APRTOA==
|
||||
dependencies:
|
||||
call-bind "^1.0.2"
|
||||
define-properties "^1.1.3"
|
||||
|
||||
runes@^0.4.2:
|
||||
version "0.4.3"
|
||||
resolved "https://registry.yarnpkg.com/runes/-/runes-0.4.3.tgz#32f7738844bc767b65cc68171528e3373c7bb355"
|
||||
integrity sha512-K6p9y4ZyL9wPzA+PMDloNQPfoDGTiFYDvdlXznyGKgD10BJpcAosvATKrExRKOrNLgD8E7Um7WGW0lxsnOuNLg==
|
||||
|
||||
shell-escape@^0.2.0:
|
||||
version "0.2.0"
|
||||
resolved "https://registry.yarnpkg.com/shell-escape/-/shell-escape-0.2.0.tgz#68fd025eb0490b4f567a027f0bf22480b5f84133"
|
||||
integrity sha1-aP0CXrBJC09WegJ/C/IkgLX4QTM=
|
||||
|
||||
side-channel@^1.0.3:
|
||||
version "1.0.4"
|
||||
resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.4.tgz#efce5c8fdc104ee751b25c58d4290011fa5ea2cf"
|
||||
integrity sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==
|
||||
dependencies:
|
||||
call-bind "^1.0.0"
|
||||
get-intrinsic "^1.0.2"
|
||||
object-inspect "^1.9.0"
|
||||
|
||||
slugify@^1.4.0:
|
||||
version "1.4.7"
|
||||
resolved "https://registry.yarnpkg.com/slugify/-/slugify-1.4.7.tgz#e42359d505afd84a44513280868e31202a79a628"
|
||||
integrity sha512-tf+h5W1IrjNm/9rKKj0JU2MDMruiopx0jjVA5zCdBtcGjfp0+c5rHw/zADLC3IeKlGHtVbHtpfzvYA0OYT+HKg==
|
||||
|
||||
string.prototype.codepointat@^0.2.1:
|
||||
version "0.2.1"
|
||||
resolved "https://registry.yarnpkg.com/string.prototype.codepointat/-/string.prototype.codepointat-0.2.1.tgz#004ad44c8afc727527b108cd462b4d971cd469bc"
|
||||
integrity sha512-2cBVCj6I4IOvEnjgO/hWqXjqBGsY+zwPmHl12Srk9IXSZ56Jwwmy+66XO5Iut/oQVR7t5ihYdLB0GMa4alEUcg==
|
||||
|
||||
string.prototype.trimend@^1.0.1:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.2.tgz#6ddd9a8796bc714b489a3ae22246a208f37bfa46"
|
||||
integrity sha512-8oAG/hi14Z4nOVP0z6mdiVZ/wqjDtWSLygMigTzAb+7aPEDTleeFf+WrF+alzecxIRkckkJVn+dTlwzJXORATw==
|
||||
dependencies:
|
||||
define-properties "^1.1.3"
|
||||
es-abstract "^1.18.0-next.1"
|
||||
|
||||
string.prototype.trimend@^1.0.4:
|
||||
version "1.0.4"
|
||||
resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.4.tgz#e75ae90c2942c63504686c18b287b4a0b1a45f80"
|
||||
integrity sha512-y9xCjw1P23Awk8EvTpcyL2NIr1j7wJ39f+k6lvRnSMz+mz9CGz9NYPelDk42kOz6+ql8xjfK8oYzy3jAP5QU5A==
|
||||
dependencies:
|
||||
call-bind "^1.0.2"
|
||||
define-properties "^1.1.3"
|
||||
|
||||
string.prototype.trimstart@^1.0.1:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/string.prototype.trimstart/-/string.prototype.trimstart-1.0.2.tgz#22d45da81015309cd0cdd79787e8919fc5c613e7"
|
||||
integrity sha512-7F6CdBTl5zyu30BJFdzSTlSlLPwODC23Od+iLoVH8X6+3fvDPPuBVVj9iaB1GOsSTSIgVfsfm27R2FGrAPznWg==
|
||||
dependencies:
|
||||
define-properties "^1.1.3"
|
||||
es-abstract "^1.18.0-next.1"
|
||||
|
||||
string.prototype.trimstart@^1.0.4:
|
||||
version "1.0.4"
|
||||
resolved "https://registry.yarnpkg.com/string.prototype.trimstart/-/string.prototype.trimstart-1.0.4.tgz#b36399af4ab2999b4c9c648bd7a3fb2bb26feeed"
|
||||
integrity sha512-jh6e984OBfvxS50tdY2nRZnoC5/mLFKOREQfw8t5yytkoUsJRNxvI/E39qu1sD0OtWI3OC0XgKSmcWwziwYuZw==
|
||||
dependencies:
|
||||
call-bind "^1.0.2"
|
||||
define-properties "^1.1.3"
|
||||
|
||||
table-parser@^0.1.3:
|
||||
version "0.1.3"
|
||||
resolved "https://registry.yarnpkg.com/table-parser/-/table-parser-0.1.3.tgz#0441cfce16a59481684c27d1b5a67ff15a43c7b0"
|
||||
integrity sha1-BEHPzhallIFoTCfRtaZ/8VpDx7A=
|
||||
dependencies:
|
||||
connected-domain "^1.0.0"
|
||||
|
||||
thenify-all@^1.0.0:
|
||||
version "1.6.0"
|
||||
resolved "https://registry.yarnpkg.com/thenify-all/-/thenify-all-1.6.0.tgz#1a1918d402d8fc3f98fbf234db0bcc8cc10e9726"
|
||||
integrity sha1-GhkY1ALY/D+Y+/I02wvMjMEOlyY=
|
||||
dependencies:
|
||||
thenify ">= 3.1.0 < 4"
|
||||
|
||||
"thenify@>= 3.1.0 < 4":
|
||||
version "3.3.1"
|
||||
resolved "https://registry.yarnpkg.com/thenify/-/thenify-3.3.1.tgz#8932e686a4066038a016dd9e2ca46add9838a95f"
|
||||
integrity sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==
|
||||
dependencies:
|
||||
any-promise "^1.0.0"
|
||||
|
||||
tiny-inflate@^1.0.3:
|
||||
version "1.0.3"
|
||||
resolved "https://registry.yarnpkg.com/tiny-inflate/-/tiny-inflate-1.0.3.tgz#122715494913a1805166aaf7c93467933eea26c4"
|
||||
integrity sha512-pkY1fj1cKHb2seWDy0B16HeWyczlJA9/WW3u3c4z/NiWDsO3DOU5D7nhTLE9CF0yXv/QZFY7sEJmj24dK+Rrqw==
|
||||
|
||||
tinyqueue@^2.0.3:
|
||||
version "2.0.3"
|
||||
resolved "https://registry.yarnpkg.com/tinyqueue/-/tinyqueue-2.0.3.tgz#64d8492ebf39e7801d7bd34062e29b45b2035f08"
|
||||
integrity sha512-ppJZNDuKGgxzkHihX8v9v9G5f+18gzaTfrukGrq6ueg0lmH4nqVnA2IPG0AEH3jKEk2GRJCUhDoqpoiw3PHLBA==
|
||||
|
||||
unbox-primitive@^1.0.0:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/unbox-primitive/-/unbox-primitive-1.0.1.tgz#085e215625ec3162574dc8859abee78a59b14471"
|
||||
integrity sha512-tZU/3NqK3dA5gpE1KtyiJUrEB0lxnGkMFHptJ7q6ewdZ8s12QrODwNbhIJStmJkd1QDXa1NRA8aF2A1zk/Ypyw==
|
||||
dependencies:
|
||||
function-bind "^1.1.1"
|
||||
has-bigints "^1.0.1"
|
||||
has-symbols "^1.0.2"
|
||||
which-boxed-primitive "^1.0.2"
|
||||
|
||||
utils-decorators@^1.8.1:
|
||||
version "1.8.1"
|
||||
resolved "https://registry.yarnpkg.com/utils-decorators/-/utils-decorators-1.8.1.tgz#6e7e2cf46c05a9554c05f004e5235696142bd5f7"
|
||||
integrity sha512-UpqzJj40jdTknZpxdeYL7p+8Ynl3bpHP6yoxoY+RmuDCOaelTiOz4GcDpScPvfZhv/ivHTV1bPJZeQd8tlxczA==
|
||||
dependencies:
|
||||
tinyqueue "^2.0.3"
|
||||
|
||||
which-boxed-primitive@^1.0.1, which-boxed-primitive@^1.0.2:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz#13757bc89b209b049fe5d86430e21cf40a89a8e6"
|
||||
integrity sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==
|
||||
dependencies:
|
||||
is-bigint "^1.0.1"
|
||||
is-boolean-object "^1.1.0"
|
||||
is-number-object "^1.0.4"
|
||||
is-string "^1.0.5"
|
||||
is-symbol "^1.0.3"
|
||||
|
||||
which-collection@^1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/which-collection/-/which-collection-1.0.1.tgz#70eab71ebbbd2aefaf32f917082fc62cdcb70906"
|
||||
integrity sha512-W8xeTUwaln8i3K/cY1nGXzdnVZlidBcagyNFtBdD5kxnb4TvGKR7FfSIS3mYpwWS1QUCutfKz8IY8RjftB0+1A==
|
||||
dependencies:
|
||||
is-map "^2.0.1"
|
||||
is-set "^2.0.1"
|
||||
is-weakmap "^2.0.1"
|
||||
is-weakset "^2.0.1"
|
||||
|
||||
which-typed-array@^1.1.2:
|
||||
version "1.1.4"
|
||||
resolved "https://registry.yarnpkg.com/which-typed-array/-/which-typed-array-1.1.4.tgz#8fcb7d3ee5adf2d771066fba7cf37e32fe8711ff"
|
||||
integrity sha512-49E0SpUe90cjpoc7BOJwyPHRqSAd12c10Qm2amdEZrJPCY2NDxaW01zHITrem+rnETY3dwrbH3UUrUwagfCYDA==
|
||||
dependencies:
|
||||
available-typed-arrays "^1.0.2"
|
||||
call-bind "^1.0.0"
|
||||
es-abstract "^1.18.0-next.1"
|
||||
foreach "^2.0.5"
|
||||
function-bind "^1.1.1"
|
||||
has-symbols "^1.0.1"
|
||||
is-typed-array "^1.1.3"
|
@ -20,6 +20,7 @@
|
||||
div
|
||||
strong {{plugin.name}}
|
||||
small.text-muted.ml-1(*ngIf='!plugin.isBuiltin') {{plugin.version}} / {{plugin.author}}
|
||||
small.text-muted.ml-1(*ngIf='plugin.isBuiltin') Built-in
|
||||
small.text-warning.ml-1(*ngIf='!isPluginEnabled(plugin)') Disabled
|
||||
a.text-muted.mb-0((click)='showPluginInfo(plugin)')
|
||||
small {{plugin.description}}
|
||||
|
@ -4,23 +4,3 @@ Terminus Terminal Plugin
|
||||
* terminal tabs
|
||||
* terminal frontends
|
||||
* session management
|
||||
* shell detection
|
||||
|
||||
Using the API:
|
||||
|
||||
```ts
|
||||
import { ShellProvider } from 'terminus-terminal'
|
||||
```
|
||||
|
||||
Exporting your subclasses:
|
||||
|
||||
```ts
|
||||
@NgModule({
|
||||
...
|
||||
providers: [
|
||||
...
|
||||
{ provide: ShellProvider, useClass: MyShellPlugin, multi: true },
|
||||
...
|
||||
]
|
||||
})
|
||||
```
|
||||
|
@ -6,7 +6,7 @@ import { NgZone, OnInit, OnDestroy, Injector, ViewChild, HostBinding, Input, Ele
|
||||
import { trigger, transition, style, animate, AnimationTriggerMetadata } from '@angular/animations'
|
||||
import { AppService, ConfigService, BaseTabComponent, ElectronService, HostAppService, HotkeysService, NotificationsService, Platform, LogService, Logger, TabContextMenuItemProvider, SplitTabComponent, SubscriptionContainer } from 'terminus-core'
|
||||
|
||||
import { BaseSession, SessionsService } from '../services/sessions.service'
|
||||
import { BaseSession } from '../session'
|
||||
import { TerminalFrontendService } from '../services/terminalFrontend.service'
|
||||
|
||||
import { Frontend } from '../frontends/frontend'
|
||||
@ -19,7 +19,7 @@ import { TerminalDecorator } from './decorator'
|
||||
*/
|
||||
export class BaseTerminalTabComponent extends BaseTabComponent implements OnInit, OnDestroy {
|
||||
static template: string = require<string>('../components/baseTerminalTab.component.pug')
|
||||
static styles: string[] = [require<string>('../components/terminalTab.component.scss')]
|
||||
static styles: string[] = [require<string>('../components/baseTerminalTab.component.scss')]
|
||||
static animations: AnimationTriggerMetadata[] = [trigger('slideInOut', [
|
||||
transition(':enter', [
|
||||
style({
|
||||
@ -83,7 +83,6 @@ export class BaseTerminalTabComponent extends BaseTabComponent implements OnInit
|
||||
protected app: AppService
|
||||
protected hostApp: HostAppService
|
||||
protected hotkeys: HotkeysService
|
||||
protected sessions: SessionsService
|
||||
protected electron: ElectronService
|
||||
protected terminalContainersService: TerminalFrontendService
|
||||
protected notifications: NotificationsService
|
||||
@ -136,7 +135,6 @@ export class BaseTerminalTabComponent extends BaseTabComponent implements OnInit
|
||||
this.app = injector.get(AppService)
|
||||
this.hostApp = injector.get(HostAppService)
|
||||
this.hotkeys = injector.get(HotkeysService)
|
||||
this.sessions = injector.get(SessionsService)
|
||||
this.electron = injector.get(ElectronService)
|
||||
this.terminalContainersService = injector.get(TerminalFrontendService)
|
||||
this.notifications = injector.get(NotificationsService)
|
||||
|
@ -3,29 +3,6 @@ export interface ResizeEvent {
|
||||
rows: number
|
||||
}
|
||||
|
||||
export interface SessionOptions {
|
||||
restoreFromPTYID?: string
|
||||
name?: string
|
||||
command: string
|
||||
args?: string[]
|
||||
cwd?: string
|
||||
env?: Record<string, string>
|
||||
width?: number
|
||||
height?: number
|
||||
pauseAfterExit?: boolean
|
||||
runAsAdministrator?: boolean
|
||||
}
|
||||
|
||||
export interface Profile {
|
||||
name: string
|
||||
color?: string
|
||||
sessionOptions: SessionOptions
|
||||
shell?: string
|
||||
isBuiltin?: boolean
|
||||
icon?: string
|
||||
disableDynamicTitle?: boolean
|
||||
}
|
||||
|
||||
export interface TerminalColorScheme {
|
||||
name: string
|
||||
foreground: string
|
||||
@ -33,30 +10,3 @@ export interface TerminalColorScheme {
|
||||
cursor: string
|
||||
colors: string[]
|
||||
}
|
||||
|
||||
export interface Shell {
|
||||
id: string
|
||||
name?: string
|
||||
command: string
|
||||
args?: string[]
|
||||
env: Record<string, string>
|
||||
|
||||
/**
|
||||
* Base path to which shell's internal FS is relative
|
||||
* Currently used for WSL only
|
||||
*/
|
||||
fsBase?: string
|
||||
|
||||
/**
|
||||
* SVG icon
|
||||
*/
|
||||
icon?: string
|
||||
|
||||
hidden?: boolean
|
||||
}
|
||||
|
||||
export interface ChildProcess {
|
||||
pid: number
|
||||
ppid: number
|
||||
command: string
|
||||
}
|
||||
|
@ -1,8 +0,0 @@
|
||||
import { Shell } from './interfaces'
|
||||
|
||||
/**
|
||||
* Extend to add support for more shells
|
||||
*/
|
||||
export abstract class ShellProvider {
|
||||
abstract provide (): Promise<Shell[]>
|
||||
}
|
@ -1,10 +1,7 @@
|
||||
import * as path from 'path'
|
||||
import * as fs from 'mz/fs'
|
||||
import shellEscape from 'shell-escape'
|
||||
import { Injectable } from '@angular/core'
|
||||
import { CLIHandler, CLIEvent, HostAppService, AppService, ConfigService } from 'terminus-core'
|
||||
import { TerminalTabComponent } from './components/terminalTab.component'
|
||||
import { TerminalService } from './services/terminal.service'
|
||||
import { CLIHandler, CLIEvent, HostAppService, AppService } from 'terminus-core'
|
||||
import { BaseTerminalTabComponent } from './api/baseTerminalTab.component'
|
||||
|
||||
@Injectable()
|
||||
export class TerminalCLIHandler extends CLIHandler {
|
||||
@ -13,9 +10,7 @@ export class TerminalCLIHandler extends CLIHandler {
|
||||
|
||||
constructor (
|
||||
private app: AppService,
|
||||
private config: ConfigService,
|
||||
private hostApp: HostAppService,
|
||||
private terminal: TerminalService,
|
||||
) {
|
||||
super()
|
||||
}
|
||||
@ -23,113 +18,23 @@ export class TerminalCLIHandler extends CLIHandler {
|
||||
async handle (event: CLIEvent): Promise<boolean> {
|
||||
const op = event.argv._[0]
|
||||
|
||||
if (op === 'open') {
|
||||
this.handleOpenDirectory(path.resolve(event.cwd, event.argv.directory))
|
||||
} else if (op === 'run') {
|
||||
this.handleRunCommand(event.argv.command)
|
||||
} else if (op === 'paste') {
|
||||
if (op === 'paste') {
|
||||
let text = event.argv.text
|
||||
if (event.argv.escape) {
|
||||
text = shellEscape([text])
|
||||
}
|
||||
this.handlePaste(text)
|
||||
} else if (op === 'profile') {
|
||||
this.handleOpenProfile(event.argv.profileName)
|
||||
} else {
|
||||
return false
|
||||
return true
|
||||
}
|
||||
|
||||
return true
|
||||
return false
|
||||
}
|
||||
|
||||
private async handleOpenDirectory (directory: string) {
|
||||
if (directory.length > 1 && (directory.endsWith('/') || directory.endsWith('\\'))) {
|
||||
directory = directory.substring(0, directory.length - 1)
|
||||
}
|
||||
if (await fs.exists(directory)) {
|
||||
if ((await fs.stat(directory)).isDirectory()) {
|
||||
this.terminal.openTab(undefined, directory)
|
||||
this.hostApp.bringToFront()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private handleRunCommand (command: string[]) {
|
||||
this.terminal.openTab({
|
||||
name: '',
|
||||
sessionOptions: {
|
||||
command: command[0],
|
||||
args: command.slice(1),
|
||||
},
|
||||
}, null, true)
|
||||
this.hostApp.bringToFront()
|
||||
}
|
||||
|
||||
private handleOpenProfile (profileName: string) {
|
||||
const profile = this.config.store.terminal.profiles.find(x => x.name === profileName)
|
||||
if (!profile) {
|
||||
console.error('Requested profile', profileName, 'not found')
|
||||
return
|
||||
}
|
||||
this.terminal.openTabWithOptions(profile.sessionOptions)
|
||||
this.hostApp.bringToFront()
|
||||
}
|
||||
|
||||
private handlePaste (text: string) {
|
||||
if (this.app.activeTab instanceof TerminalTabComponent && this.app.activeTab.session) {
|
||||
if (this.app.activeTab instanceof BaseTerminalTabComponent && this.app.activeTab.session) {
|
||||
this.app.activeTab.sendInput(text)
|
||||
this.hostApp.bringToFront()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Injectable()
|
||||
export class OpenPathCLIHandler extends CLIHandler {
|
||||
firstMatchOnly = true
|
||||
priority = -100
|
||||
|
||||
constructor (
|
||||
private terminal: TerminalService,
|
||||
private hostApp: HostAppService,
|
||||
) {
|
||||
super()
|
||||
}
|
||||
|
||||
async handle (event: CLIEvent): Promise<boolean> {
|
||||
const op = event.argv._[0]
|
||||
const opAsPath = op ? path.resolve(event.cwd, op) : null
|
||||
|
||||
if (opAsPath && (await fs.lstat(opAsPath)).isDirectory()) {
|
||||
this.terminal.openTab(undefined, opAsPath)
|
||||
this.hostApp.bringToFront()
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
@Injectable()
|
||||
export class AutoOpenTabCLIHandler extends CLIHandler {
|
||||
firstMatchOnly = true
|
||||
priority = -1000
|
||||
|
||||
constructor (
|
||||
private app: AppService,
|
||||
private config: ConfigService,
|
||||
private terminal: TerminalService,
|
||||
) {
|
||||
super()
|
||||
}
|
||||
|
||||
async handle (event: CLIEvent): Promise<boolean> {
|
||||
if (!event.secondInstance && this.config.store.terminal.autoOpen) {
|
||||
this.app.ready$.subscribe(() => {
|
||||
this.terminal.openTab()
|
||||
})
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { execFile } from 'mz/child_process'
|
||||
import { Component } from '@angular/core'
|
||||
import { ConfigService, ElectronService } from 'terminus-core'
|
||||
import { TerminalService } from '../services/terminal.service'
|
||||
|
||||
/** @hidden */
|
||||
@Component({
|
||||
@ -10,17 +10,10 @@ export class TerminalSettingsTabComponent {
|
||||
constructor (
|
||||
public config: ConfigService,
|
||||
private electron: ElectronService,
|
||||
private terminal: TerminalService,
|
||||
) { }
|
||||
|
||||
openWSLVolumeMixer (): void {
|
||||
this.electron.shell.openPath('sndvol.exe')
|
||||
this.terminal.openTab({
|
||||
name: '',
|
||||
sessionOptions: {
|
||||
command: 'wsl.exe',
|
||||
args: ['tput', 'bel'],
|
||||
},
|
||||
}, null, true)
|
||||
execFile('wsl.exe', ['tput', 'bel'])
|
||||
}
|
||||
}
|
||||
|
@ -3,18 +3,8 @@ import { ConfigProvider, Platform } from 'terminus-core'
|
||||
/** @hidden */
|
||||
export class TerminalConfigProvider extends ConfigProvider {
|
||||
defaults = {
|
||||
hotkeys: {
|
||||
'copy-current-path': [],
|
||||
shell: {
|
||||
__nonStructural: true,
|
||||
},
|
||||
profile: {
|
||||
__nonStructural: true,
|
||||
},
|
||||
},
|
||||
terminal: {
|
||||
frontend: 'xterm',
|
||||
autoOpen: false,
|
||||
fontSize: 14,
|
||||
fallbackFont: null,
|
||||
linePadding: 0,
|
||||
@ -26,13 +16,10 @@ export class TerminalConfigProvider extends ConfigProvider {
|
||||
cursorBlink: true,
|
||||
hideTabIndex: false,
|
||||
hideCloseButton: false,
|
||||
customShell: '',
|
||||
rightClick: 'menu',
|
||||
pasteOnMiddleClick: true,
|
||||
copyOnSelect: false,
|
||||
scrollOnInput: true,
|
||||
workingDirectory: '',
|
||||
alwaysUseWorkingDirectory: false,
|
||||
altIsMeta: false,
|
||||
wordSeparator: ' ()[]{}\'"',
|
||||
colorScheme: {
|
||||
@ -62,12 +49,8 @@ export class TerminalConfigProvider extends ConfigProvider {
|
||||
],
|
||||
},
|
||||
customColorSchemes: [],
|
||||
environment: {},
|
||||
profiles: [],
|
||||
useConPTY: true,
|
||||
recoverTabs: true,
|
||||
warnOnMultilinePaste: true,
|
||||
showDefaultProfiles: true,
|
||||
searchRegexAlwaysEnabled: false,
|
||||
searchOptions: {
|
||||
regex: false,
|
||||
@ -83,8 +66,6 @@ export class TerminalConfigProvider extends ConfigProvider {
|
||||
[Platform.macOS]: {
|
||||
terminal: {
|
||||
font: 'Menlo',
|
||||
shell: 'default',
|
||||
profile: 'user-default',
|
||||
},
|
||||
hotkeys: {
|
||||
'ctrl-c': ['Ctrl-C'],
|
||||
@ -109,9 +90,6 @@ export class TerminalConfigProvider extends ConfigProvider {
|
||||
'reset-zoom': [
|
||||
'⌘-0',
|
||||
],
|
||||
'new-tab': [
|
||||
'⌘-T',
|
||||
],
|
||||
home: ['⌘-Left', 'Home'],
|
||||
end: ['⌘-Right', 'End'],
|
||||
'previous-word': ['⌥-Left'],
|
||||
@ -129,8 +107,6 @@ export class TerminalConfigProvider extends ConfigProvider {
|
||||
[Platform.Windows]: {
|
||||
terminal: {
|
||||
font: 'Consolas',
|
||||
shell: 'clink',
|
||||
profile: 'cmd-clink',
|
||||
rightClick: 'paste',
|
||||
pasteOnMiddleClick: false,
|
||||
copyOnSelect: true,
|
||||
@ -156,9 +132,6 @@ export class TerminalConfigProvider extends ConfigProvider {
|
||||
'reset-zoom': [
|
||||
'Ctrl-0',
|
||||
],
|
||||
'new-tab': [
|
||||
'Ctrl-Shift-T',
|
||||
],
|
||||
home: ['Home'],
|
||||
end: ['End'],
|
||||
'previous-word': ['Ctrl-Left'],
|
||||
@ -176,8 +149,6 @@ export class TerminalConfigProvider extends ConfigProvider {
|
||||
[Platform.Linux]: {
|
||||
terminal: {
|
||||
font: 'Liberation Mono',
|
||||
shell: 'default',
|
||||
profile: 'user-default',
|
||||
},
|
||||
hotkeys: {
|
||||
'ctrl-c': ['Ctrl-C'],
|
||||
@ -200,9 +171,6 @@ export class TerminalConfigProvider extends ConfigProvider {
|
||||
'reset-zoom': [
|
||||
'Ctrl-0',
|
||||
],
|
||||
'new-tab': [
|
||||
'Ctrl-Shift-T',
|
||||
],
|
||||
home: ['Home'],
|
||||
end: ['End'],
|
||||
'previous-word': ['Ctrl-Left'],
|
||||
|
@ -1,7 +1,7 @@
|
||||
import * as fs from 'fs'
|
||||
import { Injectable } from '@angular/core'
|
||||
import { TerminalDecorator } from '../api/decorator'
|
||||
import { TerminalTabComponent } from '../components/terminalTab.component'
|
||||
import { BaseTerminalTabComponent } from '../api/baseTerminalTab.component'
|
||||
import { ElectronService, HostAppService } from 'terminus-core'
|
||||
|
||||
/** @hidden */
|
||||
@ -14,7 +14,7 @@ export class DebugDecorator extends TerminalDecorator {
|
||||
super()
|
||||
}
|
||||
|
||||
attach (terminal: TerminalTabComponent): void {
|
||||
attach (terminal: BaseTerminalTabComponent): void {
|
||||
let sessionOutputBuffer = ''
|
||||
const bufferLength = 8192
|
||||
|
||||
@ -87,23 +87,23 @@ export class DebugDecorator extends TerminalDecorator {
|
||||
}
|
||||
}
|
||||
|
||||
private doSaveState (terminal: TerminalTabComponent) {
|
||||
private doSaveState (terminal: BaseTerminalTabComponent) {
|
||||
this.saveFile(terminal.frontend!.saveState(), 'state.txt')
|
||||
}
|
||||
|
||||
private async doCopyState (terminal: TerminalTabComponent) {
|
||||
private async doCopyState (terminal: BaseTerminalTabComponent) {
|
||||
const data = '```' + JSON.stringify(terminal.frontend!.saveState()) + '```'
|
||||
this.electron.clipboard.writeText(data)
|
||||
}
|
||||
|
||||
private async doLoadState (terminal: TerminalTabComponent) {
|
||||
private async doLoadState (terminal: BaseTerminalTabComponent) {
|
||||
const data = await this.loadFile()
|
||||
if (data) {
|
||||
terminal.frontend!.restoreState(data)
|
||||
}
|
||||
}
|
||||
|
||||
private async doPasteState (terminal: TerminalTabComponent) {
|
||||
private async doPasteState (terminal: BaseTerminalTabComponent) {
|
||||
let data = this.electron.clipboard.readText()
|
||||
if (data) {
|
||||
if (data.startsWith('`')) {
|
||||
@ -122,14 +122,14 @@ export class DebugDecorator extends TerminalDecorator {
|
||||
this.electron.clipboard.writeText(data)
|
||||
}
|
||||
|
||||
private async doLoadOutput (terminal: TerminalTabComponent) {
|
||||
private async doLoadOutput (terminal: BaseTerminalTabComponent) {
|
||||
const data = await this.loadFile()
|
||||
if (data) {
|
||||
terminal.frontend?.write(data)
|
||||
}
|
||||
}
|
||||
|
||||
private async doPasteOutput (terminal: TerminalTabComponent) {
|
||||
private async doPasteOutput (terminal: BaseTerminalTabComponent) {
|
||||
let data = this.electron.clipboard.readText()
|
||||
if (data) {
|
||||
if (data.startsWith('`')) {
|
||||
|
@ -1,11 +1,11 @@
|
||||
import { Injectable } from '@angular/core'
|
||||
import { TerminalDecorator } from '../api/decorator'
|
||||
import { TerminalTabComponent } from '../components/terminalTab.component'
|
||||
import { BaseTerminalTabComponent } from '../api/baseTerminalTab.component'
|
||||
|
||||
/** @hidden */
|
||||
@Injectable()
|
||||
export class PathDropDecorator extends TerminalDecorator {
|
||||
attach (terminal: TerminalTabComponent): void {
|
||||
attach (terminal: BaseTerminalTabComponent): void {
|
||||
setTimeout(() => {
|
||||
this.subscribeUntilDetached(terminal, terminal.frontend?.dragOver$.subscribe(event => {
|
||||
event.preventDefault()
|
||||
@ -19,7 +19,7 @@ export class PathDropDecorator extends TerminalDecorator {
|
||||
})
|
||||
}
|
||||
|
||||
private injectPath (terminal: TerminalTabComponent, path: string) {
|
||||
private injectPath (terminal: BaseTerminalTabComponent, path: string) {
|
||||
if (path.includes(' ')) {
|
||||
path = `"${path}"`
|
||||
}
|
||||
|
@ -6,7 +6,7 @@ import { Observable } from 'rxjs'
|
||||
import { filter } from 'rxjs/operators'
|
||||
import { Injectable } from '@angular/core'
|
||||
import { TerminalDecorator } from '../api/decorator'
|
||||
import { TerminalTabComponent } from '../components/terminalTab.component'
|
||||
import { BaseTerminalTabComponent } from '../api/baseTerminalTab.component'
|
||||
import { LogService, Logger, ElectronService, HostAppService, HotkeysService } from 'terminus-core'
|
||||
|
||||
const SPACER = ' '
|
||||
@ -29,7 +29,7 @@ export class ZModemDecorator extends TerminalDecorator {
|
||||
this.cancelEvent = hotkeys.hotkey$.pipe(filter(x => x === 'ctrl-c'))
|
||||
}
|
||||
|
||||
attach (terminal: TerminalTabComponent): void {
|
||||
attach (terminal: BaseTerminalTabComponent): void {
|
||||
const sentry = new ZModem.Sentry({
|
||||
to_terminal: data => {
|
||||
if (!terminal.enablePassthrough) {
|
||||
|
@ -1,6 +1,5 @@
|
||||
import { Injectable } from '@angular/core'
|
||||
import { HotkeyDescription, HotkeyProvider } from 'terminus-core'
|
||||
import { TerminalService } from './services/terminal.service'
|
||||
|
||||
/** @hidden */
|
||||
@Injectable()
|
||||
@ -54,10 +53,6 @@ export class TerminalHotkeyProvider extends HotkeyProvider {
|
||||
id: 'reset-zoom',
|
||||
name: 'Reset zoom',
|
||||
},
|
||||
{
|
||||
id: 'new-tab',
|
||||
name: 'New tab',
|
||||
},
|
||||
{
|
||||
id: 'ctrl-c',
|
||||
name: 'Intelligent Ctrl-C (copy/abort)',
|
||||
@ -76,18 +71,7 @@ export class TerminalHotkeyProvider extends HotkeyProvider {
|
||||
},
|
||||
]
|
||||
|
||||
constructor (
|
||||
private terminal: TerminalService,
|
||||
) { super() }
|
||||
|
||||
async provide (): Promise<HotkeyDescription[]> {
|
||||
const profiles = await this.terminal.getProfiles()
|
||||
return [
|
||||
...this.hotkeys,
|
||||
...profiles.map(profile => ({
|
||||
id: `profile.${this.terminal.getProfileID(profile)}`,
|
||||
name: `New tab: ${profile.name}`,
|
||||
})),
|
||||
]
|
||||
return this.hotkeys
|
||||
}
|
||||
}
|
||||
|
@ -4,58 +4,35 @@ import { FormsModule } from '@angular/forms'
|
||||
import { NgbModule } from '@ng-bootstrap/ng-bootstrap'
|
||||
import { ToastrModule } from 'ngx-toastr'
|
||||
|
||||
import TerminusCorePlugin, { HostAppService, ToolbarButtonProvider, TabRecoveryProvider, ConfigProvider, HotkeysService, HotkeyProvider, TabContextMenuItemProvider, CLIHandler } from 'terminus-core'
|
||||
import TerminusCorePlugin, { ConfigProvider, HotkeysService, HotkeyProvider, TabContextMenuItemProvider, CLIHandler } from 'terminus-core'
|
||||
import { SettingsTabProvider } from 'terminus-settings'
|
||||
|
||||
import { AppearanceSettingsTabComponent } from './components/appearanceSettingsTab.component'
|
||||
import { ColorSchemeSettingsTabComponent } from './components/colorSchemeSettingsTab.component'
|
||||
import { TerminalTabComponent } from './components/terminalTab.component'
|
||||
import { ShellSettingsTabComponent } from './components/shellSettingsTab.component'
|
||||
import { TerminalSettingsTabComponent } from './components/terminalSettingsTab.component'
|
||||
import { ColorPickerComponent } from './components/colorPicker.component'
|
||||
import { ColorSchemePreviewComponent } from './components/colorSchemePreview.component'
|
||||
import { EditProfileModalComponent } from './components/editProfileModal.component'
|
||||
import { EnvironmentEditorComponent } from './components/environmentEditor.component'
|
||||
import { SearchPanelComponent } from './components/searchPanel.component'
|
||||
|
||||
import { BaseSession } from './services/sessions.service'
|
||||
import { TerminalFrontendService } from './services/terminalFrontend.service'
|
||||
import { TerminalService } from './services/terminal.service'
|
||||
import { DockMenuService } from './services/dockMenu.service'
|
||||
|
||||
import { ButtonProvider } from './buttonProvider'
|
||||
import { RecoveryProvider } from './recoveryProvider'
|
||||
import { TerminalDecorator } from './api/decorator'
|
||||
import { TerminalContextMenuItemProvider } from './api/contextMenuProvider'
|
||||
import { TerminalColorSchemeProvider } from './api/colorSchemeProvider'
|
||||
import { ShellProvider } from './api/shellProvider'
|
||||
import { TerminalSettingsTabProvider, AppearanceSettingsTabProvider, ColorSchemeSettingsTabProvider, ShellSettingsTabProvider } from './settings'
|
||||
import { TerminalSettingsTabProvider, AppearanceSettingsTabProvider, ColorSchemeSettingsTabProvider } from './settings'
|
||||
import { DebugDecorator } from './features/debug'
|
||||
import { PathDropDecorator } from './features/pathDrop'
|
||||
import { ZModemDecorator } from './features/zmodem'
|
||||
import { TerminalConfigProvider } from './config'
|
||||
import { TerminalHotkeyProvider } from './hotkeys'
|
||||
import { HyperColorSchemes } from './colorSchemes'
|
||||
import { NewTabContextMenu, CopyPasteContextMenu, SaveAsProfileContextMenu, LegacyContextMenu } from './tabContextMenu'
|
||||
|
||||
import { CmderShellProvider } from './shells/cmder'
|
||||
import { CustomShellProvider } from './shells/custom'
|
||||
import { Cygwin32ShellProvider } from './shells/cygwin32'
|
||||
import { Cygwin64ShellProvider } from './shells/cygwin64'
|
||||
import { GitBashShellProvider } from './shells/gitBash'
|
||||
import { LinuxDefaultShellProvider } from './shells/linuxDefault'
|
||||
import { MacOSDefaultShellProvider } from './shells/macDefault'
|
||||
import { POSIXShellsProvider } from './shells/posix'
|
||||
import { PowerShellCoreShellProvider } from './shells/powershellCore'
|
||||
import { WindowsDefaultShellProvider } from './shells/winDefault'
|
||||
import { WindowsStockShellsProvider } from './shells/windowsStock'
|
||||
import { WSLShellProvider } from './shells/wsl'
|
||||
import { CopyPasteContextMenu, LegacyContextMenu } from './tabContextMenu'
|
||||
|
||||
import { hterm } from './frontends/hterm'
|
||||
import { Frontend } from './frontends/frontend'
|
||||
import { HTermFrontend } from './frontends/htermFrontend'
|
||||
import { XTermFrontend, XTermWebGLFrontend } from './frontends/xtermFrontend'
|
||||
import { AutoOpenTabCLIHandler, OpenPathCLIHandler, TerminalCLIHandler } from './cli'
|
||||
import { TerminalCLIHandler } from './cli'
|
||||
|
||||
/** @hidden */
|
||||
@NgModule({
|
||||
@ -69,11 +46,8 @@ import { AutoOpenTabCLIHandler, OpenPathCLIHandler, TerminalCLIHandler } from '.
|
||||
providers: [
|
||||
{ provide: SettingsTabProvider, useClass: AppearanceSettingsTabProvider, multi: true },
|
||||
{ provide: SettingsTabProvider, useClass: ColorSchemeSettingsTabProvider, multi: true },
|
||||
{ provide: SettingsTabProvider, useClass: ShellSettingsTabProvider, multi: true },
|
||||
{ provide: SettingsTabProvider, useClass: TerminalSettingsTabProvider, multi: true },
|
||||
|
||||
{ provide: ToolbarButtonProvider, useClass: ButtonProvider, multi: true },
|
||||
{ provide: TabRecoveryProvider, useClass: RecoveryProvider, multi: true },
|
||||
{ provide: ConfigProvider, useClass: TerminalConfigProvider, multi: true },
|
||||
{ provide: HotkeyProvider, useClass: TerminalHotkeyProvider, multi: true },
|
||||
{ provide: TerminalColorSchemeProvider, useClass: HyperColorSchemes, multi: true },
|
||||
@ -81,65 +55,32 @@ import { AutoOpenTabCLIHandler, OpenPathCLIHandler, TerminalCLIHandler } from '.
|
||||
{ provide: TerminalDecorator, useClass: ZModemDecorator, multi: true },
|
||||
{ provide: TerminalDecorator, useClass: DebugDecorator, multi: true },
|
||||
|
||||
{ provide: ShellProvider, useClass: WindowsDefaultShellProvider, multi: true },
|
||||
{ provide: ShellProvider, useClass: MacOSDefaultShellProvider, multi: true },
|
||||
{ provide: ShellProvider, useClass: LinuxDefaultShellProvider, multi: true },
|
||||
{ provide: ShellProvider, useClass: WindowsStockShellsProvider, multi: true },
|
||||
{ provide: ShellProvider, useClass: PowerShellCoreShellProvider, multi: true },
|
||||
{ provide: ShellProvider, useClass: CmderShellProvider, multi: true },
|
||||
{ provide: ShellProvider, useClass: CustomShellProvider, multi: true },
|
||||
{ provide: ShellProvider, useClass: Cygwin32ShellProvider, multi: true },
|
||||
{ provide: ShellProvider, useClass: Cygwin64ShellProvider, multi: true },
|
||||
{ provide: ShellProvider, useClass: GitBashShellProvider, multi: true },
|
||||
{ provide: ShellProvider, useClass: POSIXShellsProvider, multi: true },
|
||||
{ provide: ShellProvider, useClass: WSLShellProvider, multi: true },
|
||||
|
||||
{ provide: TabContextMenuItemProvider, useClass: NewTabContextMenu, multi: true },
|
||||
{ provide: TabContextMenuItemProvider, useClass: CopyPasteContextMenu, multi: true },
|
||||
{ provide: TabContextMenuItemProvider, useClass: SaveAsProfileContextMenu, multi: true },
|
||||
{ provide: TabContextMenuItemProvider, useClass: LegacyContextMenu, multi: true },
|
||||
|
||||
{ provide: CLIHandler, useClass: TerminalCLIHandler, multi: true },
|
||||
{ provide: CLIHandler, useClass: OpenPathCLIHandler, multi: true },
|
||||
{ provide: CLIHandler, useClass: AutoOpenTabCLIHandler, multi: true },
|
||||
|
||||
// For WindowsDefaultShellProvider
|
||||
PowerShellCoreShellProvider,
|
||||
WSLShellProvider,
|
||||
WindowsStockShellsProvider,
|
||||
],
|
||||
entryComponents: [
|
||||
TerminalTabComponent,
|
||||
AppearanceSettingsTabComponent,
|
||||
ColorSchemeSettingsTabComponent,
|
||||
ShellSettingsTabComponent,
|
||||
TerminalSettingsTabComponent,
|
||||
EditProfileModalComponent,
|
||||
] as any[],
|
||||
declarations: [
|
||||
ColorPickerComponent,
|
||||
ColorSchemePreviewComponent,
|
||||
TerminalTabComponent,
|
||||
AppearanceSettingsTabComponent,
|
||||
ColorSchemeSettingsTabComponent,
|
||||
ShellSettingsTabComponent,
|
||||
TerminalSettingsTabComponent,
|
||||
EditProfileModalComponent,
|
||||
EnvironmentEditorComponent,
|
||||
SearchPanelComponent,
|
||||
] as any[],
|
||||
exports: [
|
||||
ColorPickerComponent,
|
||||
EnvironmentEditorComponent,
|
||||
SearchPanelComponent,
|
||||
],
|
||||
})
|
||||
export default class TerminalModule { // eslint-disable-line @typescript-eslint/no-extraneous-class
|
||||
private constructor (
|
||||
hotkeys: HotkeysService,
|
||||
terminal: TerminalService,
|
||||
hostApp: HostAppService,
|
||||
dockMenu: DockMenuService,
|
||||
) {
|
||||
const events = [
|
||||
{
|
||||
@ -165,30 +106,11 @@ export default class TerminalModule { // eslint-disable-line @typescript-eslint/
|
||||
hotkeys.emitKeyEvent(nativeEvent)
|
||||
}
|
||||
})
|
||||
|
||||
hotkeys.matchedHotkey.subscribe(async (hotkey) => {
|
||||
if (hotkey === 'new-tab') {
|
||||
terminal.openTab()
|
||||
}
|
||||
if (hotkey === 'new-window') {
|
||||
hostApp.newWindow()
|
||||
}
|
||||
if (hotkey.startsWith('profile.')) {
|
||||
const profile = await terminal.getProfileByID(hotkey.split('.')[1])
|
||||
if (profile) {
|
||||
terminal.openTabWithOptions(profile.sessionOptions)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
dockMenu.update()
|
||||
}
|
||||
}
|
||||
|
||||
export { TerminalService, BaseSession, TerminalTabComponent, TerminalFrontendService, TerminalDecorator, TerminalContextMenuItemProvider, TerminalColorSchemeProvider, ShellProvider }
|
||||
export { TerminalFrontendService, TerminalDecorator, TerminalContextMenuItemProvider, TerminalColorSchemeProvider }
|
||||
export { Frontend, XTermFrontend, XTermWebGLFrontend, HTermFrontend }
|
||||
export { BaseTerminalTabComponent } from './api/baseTerminalTab.component'
|
||||
export * from './api/interfaces'
|
||||
|
||||
// Deprecations
|
||||
export { TerminalColorScheme as ITerminalColorScheme, Shell as IShell } from './api/interfaces'
|
||||
export * from './session'
|
||||
|
@ -3,7 +3,7 @@ import { ConfigService, ThemesService, HotkeysService } from 'terminus-core'
|
||||
import { Frontend } from '../frontends/frontend'
|
||||
import { HTermFrontend } from '../frontends/htermFrontend'
|
||||
import { XTermFrontend, XTermWebGLFrontend } from '../frontends/xtermFrontend'
|
||||
import { BaseSession } from '../services/sessions.service'
|
||||
import { BaseSession } from '../session'
|
||||
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class TerminalFrontendService {
|
||||
|
60
terminus-terminal/src/session.ts
Normal file
@ -0,0 +1,60 @@
|
||||
import { Observable, Subject } from 'rxjs'
|
||||
|
||||
|
||||
/**
|
||||
* A session object for a [[BaseTerminalTabComponent]]
|
||||
* Extend this to implement custom I/O and process management for your terminal tab
|
||||
*/
|
||||
export abstract class BaseSession {
|
||||
open: boolean
|
||||
name: string
|
||||
truePID: number
|
||||
protected output = new Subject<string>()
|
||||
protected binaryOutput = new Subject<Buffer>()
|
||||
protected closed = new Subject<void>()
|
||||
protected destroyed = new Subject<void>()
|
||||
private initialDataBuffer = Buffer.from('')
|
||||
private initialDataBufferReleased = false
|
||||
|
||||
get output$ (): Observable<string> { return this.output }
|
||||
get binaryOutput$ (): Observable<Buffer> { return this.binaryOutput }
|
||||
get closed$ (): Observable<void> { return this.closed }
|
||||
get destroyed$ (): Observable<void> { return this.destroyed }
|
||||
|
||||
emitOutput (data: Buffer): void {
|
||||
if (!this.initialDataBufferReleased) {
|
||||
this.initialDataBuffer = Buffer.concat([this.initialDataBuffer, data])
|
||||
} else {
|
||||
this.output.next(data.toString())
|
||||
this.binaryOutput.next(data)
|
||||
}
|
||||
}
|
||||
|
||||
releaseInitialDataBuffer (): void {
|
||||
this.initialDataBufferReleased = true
|
||||
this.output.next(this.initialDataBuffer.toString())
|
||||
this.binaryOutput.next(this.initialDataBuffer)
|
||||
this.initialDataBuffer = Buffer.from('')
|
||||
}
|
||||
|
||||
async destroy (): Promise<void> {
|
||||
if (this.open) {
|
||||
this.open = false
|
||||
this.closed.next()
|
||||
this.destroyed.next()
|
||||
this.closed.complete()
|
||||
this.destroyed.complete()
|
||||
this.output.complete()
|
||||
this.binaryOutput.complete()
|
||||
await this.gracefullyKillProcess()
|
||||
}
|
||||
}
|
||||
|
||||
abstract start (options: unknown): void
|
||||
abstract resize (columns: number, rows: number): void
|
||||
abstract write (data: Buffer): void
|
||||
abstract kill (signal?: string): void
|
||||
abstract gracefullyKillProcess (): Promise<void>
|
||||
abstract supportsWorkingDirectory (): boolean
|
||||
abstract getWorkingDirectory (): Promise<string|null>
|
||||
}
|
@ -2,7 +2,6 @@ import { Injectable } from '@angular/core'
|
||||
import { SettingsTabProvider } from 'terminus-settings'
|
||||
|
||||
import { AppearanceSettingsTabComponent } from './components/appearanceSettingsTab.component'
|
||||
import { ShellSettingsTabComponent } from './components/shellSettingsTab.component'
|
||||
import { TerminalSettingsTabComponent } from './components/terminalSettingsTab.component'
|
||||
import { ColorSchemeSettingsTabComponent } from './components/colorSchemeSettingsTab.component'
|
||||
|
||||
@ -30,18 +29,6 @@ export class ColorSchemeSettingsTabProvider extends SettingsTabProvider {
|
||||
}
|
||||
}
|
||||
|
||||
/** @hidden */
|
||||
@Injectable()
|
||||
export class ShellSettingsTabProvider extends SettingsTabProvider {
|
||||
id = 'terminal-shell'
|
||||
icon = 'list-ul'
|
||||
title = 'Shell'
|
||||
|
||||
getComponentType (): any {
|
||||
return ShellSettingsTabComponent
|
||||
}
|
||||
}
|
||||
|
||||
/** @hidden */
|
||||
@Injectable()
|
||||
export class TerminalSettingsTabProvider extends SettingsTabProvider {
|
||||
|
@ -1,138 +1,9 @@
|
||||
import { MenuItemConstructorOptions } from 'electron'
|
||||
import { Injectable, NgZone, Optional, Inject } from '@angular/core'
|
||||
import { ConfigService, BaseTabComponent, TabContextMenuItemProvider, TabHeaderComponent, SplitTabComponent, NotificationsService } from 'terminus-core'
|
||||
import { TerminalTabComponent } from './components/terminalTab.component'
|
||||
import { UACService } from './services/uac.service'
|
||||
import { TerminalService } from './services/terminal.service'
|
||||
import { BaseTabComponent, TabContextMenuItemProvider, TabHeaderComponent, NotificationsService } from 'terminus-core'
|
||||
import { BaseTerminalTabComponent } from './api/baseTerminalTab.component'
|
||||
import { TerminalContextMenuItemProvider } from './api/contextMenuProvider'
|
||||
|
||||
/** @hidden */
|
||||
@Injectable()
|
||||
export class SaveAsProfileContextMenu extends TabContextMenuItemProvider {
|
||||
constructor (
|
||||
private config: ConfigService,
|
||||
private zone: NgZone,
|
||||
private notifications: NotificationsService,
|
||||
) {
|
||||
super()
|
||||
}
|
||||
|
||||
async getItems (tab: BaseTabComponent, _tabHeader?: TabHeaderComponent): Promise<MenuItemConstructorOptions[]> {
|
||||
if (!(tab instanceof TerminalTabComponent)) {
|
||||
return []
|
||||
}
|
||||
const items: MenuItemConstructorOptions[] = [
|
||||
{
|
||||
label: 'Save as profile',
|
||||
click: () => this.zone.run(async () => {
|
||||
const profile = {
|
||||
sessionOptions: {
|
||||
...tab.sessionOptions,
|
||||
cwd: await tab.session?.getWorkingDirectory() ?? tab.sessionOptions.cwd,
|
||||
},
|
||||
name: tab.sessionOptions.command,
|
||||
}
|
||||
this.config.store.terminal.profiles = [
|
||||
...this.config.store.terminal.profiles,
|
||||
profile,
|
||||
]
|
||||
this.config.save()
|
||||
this.notifications.info('Saved')
|
||||
}),
|
||||
},
|
||||
]
|
||||
|
||||
return items
|
||||
}
|
||||
}
|
||||
|
||||
/** @hidden */
|
||||
@Injectable()
|
||||
export class NewTabContextMenu extends TabContextMenuItemProvider {
|
||||
weight = 10
|
||||
|
||||
constructor (
|
||||
public config: ConfigService,
|
||||
private zone: NgZone,
|
||||
private terminalService: TerminalService,
|
||||
private uac: UACService,
|
||||
) {
|
||||
super()
|
||||
}
|
||||
|
||||
async getItems (tab: BaseTabComponent, tabHeader?: TabHeaderComponent): Promise<MenuItemConstructorOptions[]> {
|
||||
const profiles = await this.terminalService.getProfiles()
|
||||
|
||||
const items: MenuItemConstructorOptions[] = [
|
||||
{
|
||||
label: 'New terminal',
|
||||
click: () => this.zone.run(() => {
|
||||
this.terminalService.openTabWithOptions((tab as any).sessionOptions)
|
||||
}),
|
||||
},
|
||||
{
|
||||
label: 'New with profile',
|
||||
submenu: profiles.map(profile => ({
|
||||
label: profile.name,
|
||||
click: () => this.zone.run(async () => {
|
||||
let workingDirectory = this.config.store.terminal.workingDirectory
|
||||
if (this.config.store.terminal.alwaysUseWorkingDirectory !== true && tab instanceof TerminalTabComponent) {
|
||||
workingDirectory = await tab.session?.getWorkingDirectory()
|
||||
}
|
||||
await this.terminalService.openTab(profile, workingDirectory)
|
||||
}),
|
||||
})),
|
||||
},
|
||||
]
|
||||
|
||||
if (this.uac.isAvailable) {
|
||||
items.push({
|
||||
label: 'New admin tab',
|
||||
submenu: profiles.map(profile => ({
|
||||
label: profile.name,
|
||||
click: () => this.zone.run(async () => {
|
||||
this.terminalService.openTabWithOptions({
|
||||
...profile.sessionOptions,
|
||||
runAsAdministrator: true,
|
||||
})
|
||||
}),
|
||||
})),
|
||||
})
|
||||
}
|
||||
|
||||
if (tab instanceof TerminalTabComponent && tabHeader && this.uac.isAvailable) {
|
||||
items.push({
|
||||
label: 'Duplicate as administrator',
|
||||
click: () => this.zone.run(async () => {
|
||||
this.terminalService.openTabWithOptions({
|
||||
...tab.sessionOptions,
|
||||
runAsAdministrator: true,
|
||||
})
|
||||
}),
|
||||
})
|
||||
}
|
||||
|
||||
if (tab instanceof BaseTerminalTabComponent && tab.parent instanceof SplitTabComponent && tab.parent.getAllTabs().length > 1) {
|
||||
items.push({
|
||||
label: 'Focus all panes',
|
||||
click: () => this.zone.run(() => {
|
||||
tab.focusAllPanes()
|
||||
}),
|
||||
})
|
||||
}
|
||||
|
||||
if (tab instanceof TerminalTabComponent && tab.session?.supportsWorkingDirectory()) {
|
||||
items.push({
|
||||
label: 'Copy current path',
|
||||
click: () => this.zone.run(() => tab.copyCurrentPath()),
|
||||
})
|
||||
}
|
||||
|
||||
return items
|
||||
}
|
||||
}
|
||||
|
||||
/** @hidden */
|
||||
@Injectable()
|
||||
export class CopyPasteContextMenu extends TabContextMenuItemProvider {
|
||||
|
@ -4,6 +4,7 @@ module.exports = [
|
||||
require('./terminus-core/webpack.config.js'),
|
||||
require('./terminus-settings/webpack.config.js'),
|
||||
require('./terminus-terminal/webpack.config.js'),
|
||||
require('./terminus-local/webpack.config.js'),
|
||||
require('./terminus-community-color-schemes/webpack.config.js'),
|
||||
require('./terminus-plugin-manager/webpack.config.js'),
|
||||
require('./terminus-ssh/webpack.config.js'),
|
||||
|