use profiles for everything

This commit is contained in:
Eugene Pankov 2019-05-11 21:28:04 +02:00
parent bc71547d92
commit 48ff7d7d5a
26 changed files with 159 additions and 101 deletions

View File

@ -23,7 +23,12 @@ export interface IToolbarButton {
weight?: number weight?: number
click: () => void click?: () => void
submenu?: () => Promise<IToolbarButton[]>
/** @hidden */
submenuItems?: IToolbarButton[]
} }
/** /**

View File

@ -32,22 +32,44 @@ title-bar(
) )
.btn-group.background .btn-group.background
button.btn.btn-secondary.btn-tab-bar( .d-flex(
*ngFor='let button of leftToolbarButtons', *ngFor='let button of leftToolbarButtons',
[title]='button.title', ngbDropdown,
(click)='button.click()', (openChange)='generateButtonSubmenu(button)',
[innerHTML]='button.icon',
) )
button.btn.btn-secondary.btn-tab-bar(
[title]='button.title',
(click)='button.click && button.click()',
[innerHTML]='button.icon',
ngbDropdownToggle,
)
div(*ngIf='button.submenu', ngbDropdownMenu)
button.dropdown-item(
*ngFor='let item of button.submenuItems',
(click)='item.click()',
ngbDropdownItem,
) {{item.title}}
.drag-space.background([class.persistent]='config.store.appearance.frame == "thin" && hostApp.platform != Platform.macOS') .drag-space.background([class.persistent]='config.store.appearance.frame == "thin" && hostApp.platform != Platform.macOS')
.btn-group.background .btn-group.background
button.btn.btn-secondary.btn-tab-bar( .d-flex(
*ngFor='let button of rightToolbarButtons', *ngFor='let button of rightToolbarButtons',
[title]='button.title', ngbDropdown,
(click)='button.click()', (openChange)='generateButtonSubmenu(button)',
[innerHTML]='button.icon',
) )
button.btn.btn-secondary.btn-tab-bar(
[title]='button.title',
(click)='button.click && button.click()',
[innerHTML]='button.icon',
ngbDropdownToggle,
)
div(*ngIf='button.submenu', ngbDropdownMenu)
button.dropdown-item(
*ngFor='let item of button.submenuItems',
(click)='item.click()',
ngbDropdownItem,
) {{item.title}}
button.btn.btn-secondary.btn-tab-bar.btn-update( button.btn.btn-secondary.btn-tab-bar.btn-update(
*ngIf='updatesAvailable', *ngIf='updatesAvailable',

View File

@ -233,6 +233,12 @@ export class AppRootComponent {
}) })
} }
async generateButtonSubmenu (button: IToolbarButton) {
if (button.submenu) {
button.submenuItems = await button.submenu()
}
}
private getToolbarButtons (aboveZero: boolean): IToolbarButton[] { private getToolbarButtons (aboveZero: boolean): IToolbarButton[] {
let buttons: IToolbarButton[] = [] let buttons: IToolbarButton[] = []
this.config.enabledServices(this.toolbarButtonProviders).forEach(provider => { this.config.enabledServices(this.toolbarButtonProviders).forEach(provider => {

View File

@ -23,6 +23,7 @@ export class StartPageComponent {
return this.config.enabledServices(this.toolbarButtonProviders) return this.config.enabledServices(this.toolbarButtonProviders)
.map(provider => provider.provide()) .map(provider => provider.provide())
.reduce((a, b) => a.concat(b)) .reduce((a, b) => a.concat(b))
.filter(x => !!x.click)
.sort((a: IToolbarButton, b: IToolbarButton) => (a.weight || 0) - (b.weight || 0)) .sort((a: IToolbarButton, b: IToolbarButton) => (a.weight || 0) - (b.weight || 0))
} }
} }

View File

@ -65,6 +65,7 @@ export class TouchbarService {
this.config.enabledServices(this.toolbarButtonProviders).forEach(provider => { this.config.enabledServices(this.toolbarButtonProviders).forEach(provider => {
buttons = buttons.concat(provider.provide()) buttons = buttons.concat(provider.provide())
}) })
buttons = buttons.filter(x => !!x.touchBarNSImage)
buttons.sort((a, b) => (a.weight || 0) - (b.weight || 0)) buttons.sort((a, b) => (a.weight || 0) - (b.weight || 0))
this.tabSegments = this.app.tabs.map(tab => ({ this.tabSegments = this.app.tabs.map(tab => ({
label: this.shortenTitle(tab.title), label: this.shortenTitle(tab.title),

View File

@ -136,6 +136,10 @@ app-root {
background: transparent; background: transparent;
&:hover { background: rgba(0, 0, 0, .25) !important; } &:hover { background: rgba(0, 0, 0, .25) !important; }
&:active { background: rgba(0, 0, 0, .5) !important; } &:active { background: rgba(0, 0, 0, .5) !important; }
&::after {
display: none;
}
} }
&>.tabs { &>.tabs {

View File

@ -52,6 +52,5 @@
"macos-native-processlist": "^1.0.1", "macos-native-processlist": "^1.0.1",
"windows-native-registry": "^1.0.14", "windows-native-registry": "^1.0.14",
"@terminus-term/windows-process-tree": "^0.2.4" "@terminus-term/windows-process-tree": "^0.2.4"
}, }
"false": {}
} }

View File

@ -35,6 +35,7 @@ export interface SessionOptions {
export interface Profile { export interface Profile {
name: string, name: string,
sessionOptions: SessionOptions, sessionOptions: SessionOptions,
isBuiltin?: boolean
} }
export interface ITerminalColorScheme { export interface ITerminalColorScheme {
@ -66,7 +67,7 @@ export interface IShell {
name?: string name?: string
command: string command: string
args?: string[] args?: string[]
env?: {[id: string]: string} env: {[id: string]: string}
/** /**
* Base path to which shell's internal FS is relative * Base path to which shell's internal FS is relative

View File

@ -31,13 +31,27 @@ export class ButtonProvider extends ToolbarButtonProvider {
} }
provide (): IToolbarButton[] { provide (): IToolbarButton[] {
return [{ return [
icon: this.domSanitizer.bypassSecurityTrustHtml(require('./icons/plus.svg')), {
title: 'New terminal', icon: this.domSanitizer.bypassSecurityTrustHtml(require('./icons/plus.svg')),
touchBarNSImage: 'NSTouchBarAddDetailTemplate', title: 'New terminal',
click: async () => { touchBarNSImage: 'NSTouchBarAddDetailTemplate',
this.terminal.openTab() click: async () => {
} this.terminal.openTab()
}] }
},
{
icon: this.domSanitizer.bypassSecurityTrustHtml(require('./icons/profiles.svg')),
title: 'New terminal with profile',
submenu: async () => {
let profiles = await this.terminal.getProfiles()
return profiles.map(profile => ({
icon: null,
title: profile.name,
click: () => this.terminal.openTab(profile),
}))
}
},
]
} }
} }

View File

@ -2,17 +2,17 @@ h3.mb-3 Shell
.form-line .form-line
.header .header
.title Shell .title Profile
.description Default shell for new tabs .description Default profile for new tabs
select.form-control( select.form-control(
[(ngModel)]='config.store.terminal.shell', [(ngModel)]='config.store.terminal.profile',
(ngModelChange)='config.save()', (ngModelChange)='config.save()',
) )
option( option(
*ngFor='let shell of shells', *ngFor='let profile of profiles',
[ngValue]='shell.id' [ngValue]='slug(profile.name)'
) {{shell.name}} ) {{profile.name}}
.form-line(*ngIf='isConPTYAvailable') .form-line(*ngIf='isConPTYAvailable')
@ -28,10 +28,10 @@ h3.mb-3 Shell
.alert.alert-info.d-flex.align-items-center(*ngIf='config.store.terminal.useConPTY && isConPTYAvailable && !isConPTYStable') .alert.alert-info.d-flex.align-items-center(*ngIf='config.store.terminal.useConPTY && isConPTYAvailable && !isConPTYStable')
.mr-auto Windows 10 build 18309 or above is recommended for ConPTY .mr-auto Windows 10 build 18309 or above is recommended for ConPTY
.alert.alert-info.d-flex.align-items-center(*ngIf='config.store.terminal.shell.startsWith("wsl") && (config.store.terminal.frontend != "hterm" || !config.store.terminal.useConPTY)') .alert.alert-info.d-flex.align-items-center(*ngIf='config.store.terminal.profile.startsWith("WSL") && (config.store.terminal.frontend != "hterm" || !config.store.terminal.useConPTY)')
.mr-auto WSL terminal only supports TrueColor with ConPTY and the hterm frontend .mr-auto WSL terminal only supports TrueColor with ConPTY and the hterm frontend
.form-line(*ngIf='config.store.terminal.shell == "custom"') .form-line(*ngIf='config.store.terminal.profile == "Custom shell"')
.header .header
.title Custom shell .title Custom shell
@ -66,7 +66,7 @@ h3.mt-3 Saved Profiles
.list-group.list-group-flush.mt-3.mb-3 .list-group.list-group-flush.mt-3.mb-3
.list-group-item.list-group-item-action.d-flex.align-items-center( .list-group-item.list-group-item-action.d-flex.align-items-center(
*ngFor='let profile of profiles', *ngFor='let profile of config.store.terminal.profiles',
(click)='editProfile(profile)', (click)='editProfile(profile)',
) )
.mr-auto .mr-auto

View File

@ -1,3 +1,4 @@
import slug from 'slug'
import { Component } from '@angular/core' import { Component } from '@angular/core'
import { NgbModal } from '@ng-bootstrap/ng-bootstrap' import { NgbModal } from '@ng-bootstrap/ng-bootstrap'
import { Subscription } from 'rxjs' import { Subscription } from 'rxjs'
@ -17,6 +18,7 @@ export class ShellSettingsTabComponent {
Platform = Platform Platform = Platform
isConPTYAvailable: boolean isConPTYAvailable: boolean
isConPTYStable: boolean isConPTYStable: boolean
slug = slug
private configSubscription: Subscription private configSubscription: Subscription
constructor ( constructor (
@ -44,13 +46,12 @@ export class ShellSettingsTabComponent {
this.configSubscription.unsubscribe() this.configSubscription.unsubscribe()
} }
reload () { async reload () {
this.profiles = this.config.store.terminal.profiles this.profiles = await this.terminalService.getProfiles()
} }
pickWorkingDirectory () { pickWorkingDirectory () {
let shell = this.shells.find(x => x.id === this.config.store.terminal.shell) let shell = this.shells.find(x => x.id === this.config.store.terminal.shell)
console.log(shell)
let paths = this.electron.dialog.showOpenDialog( let paths = this.electron.dialog.showOpenDialog(
this.hostApp.getWindow(), this.hostApp.getWindow(),
{ {
@ -68,9 +69,9 @@ export class ShellSettingsTabComponent {
name: shell.name, name: shell.name,
sessionOptions: this.terminalService.optionsFromShell(shell), sessionOptions: this.terminalService.optionsFromShell(shell),
} }
this.profiles.push(profile) this.config.store.terminal.profiles = [profile, ...this.config.store.terminal.profiles]
this.config.store.terminal.profiles = this.profiles
this.config.save() this.config.save()
this.reload()
} }
editProfile (profile: Profile) { editProfile (profile: Profile) {
@ -83,8 +84,8 @@ export class ShellSettingsTabComponent {
} }
deleteProfile (profile: Profile) { deleteProfile (profile: Profile) {
this.profiles = this.profiles.filter(x => x !== profile) this.config.store.terminal.profiles = this.config.store.terminal.profiles.filter(x => x !== profile)
this.config.store.terminal.profiles = this.profiles
this.config.save() this.config.save()
this.reload()
} }
} }

View File

@ -16,9 +16,11 @@ export class TerminalSettingsTabComponent {
openWSLVolumeMixer () { openWSLVolumeMixer () {
this.electron.shell.openItem('sndvol.exe') this.electron.shell.openItem('sndvol.exe')
this.terminal.openTab({ this.terminal.openTab({
id: '', name: null,
command: 'wsl.exe', sessionOptions: {
args: ['tput', 'bel'], command: 'wsl.exe',
args: ['tput', 'bel'],
},
}, null, true) }, null, true)
} }
} }

View File

@ -65,6 +65,7 @@ export class TerminalConfigProvider extends ConfigProvider {
terminal: { terminal: {
font: 'Menlo', font: 'Menlo',
shell: 'default', shell: 'default',
profile: 'user-default',
}, },
hotkeys: { hotkeys: {
'ctrl-c': ['Ctrl-C'], 'ctrl-c': ['Ctrl-C'],
@ -103,6 +104,7 @@ export class TerminalConfigProvider extends ConfigProvider {
terminal: { terminal: {
font: 'Consolas', font: 'Consolas',
shell: 'clink', shell: 'clink',
profile: 'cmd-clink',
rightClick: 'paste', rightClick: 'paste',
copyOnSelect: true, copyOnSelect: true,
}, },
@ -143,6 +145,7 @@ export class TerminalConfigProvider extends ConfigProvider {
terminal: { terminal: {
font: 'Liberation Mono', font: 'Liberation Mono',
shell: 'default', shell: 'default',
profile: 'user-default',
}, },
hotkeys: { hotkeys: {
'ctrl-c': ['Ctrl-C'], 'ctrl-c': ['Ctrl-C'],

View File

@ -21,7 +21,7 @@ export class NewTabContextMenu extends TerminalContextMenuItemProvider {
} }
async getItems (tab: BaseTerminalTabComponent): Promise<Electron.MenuItemConstructorOptions[]> { async getItems (tab: BaseTerminalTabComponent): Promise<Electron.MenuItemConstructorOptions[]> {
let shells = await this.terminalService.shells$.toPromise() let profiles = await this.terminalService.getProfiles()
let items: Electron.MenuItemConstructorOptions[] = [ let items: Electron.MenuItemConstructorOptions[] = [
{ {
@ -31,45 +31,31 @@ export class NewTabContextMenu extends TerminalContextMenuItemProvider {
}) })
}, },
{ {
label: 'New with shell', label: 'New with profile',
submenu: shells.map(shell => ({ submenu: profiles.map(profile => ({
label: shell.name, label: profile.name,
click: () => this.zone.run(async () => { click: () => this.zone.run(async () => {
this.terminalService.openTab(shell, await tab.session.getWorkingDirectory()) this.terminalService.openTab(profile, await tab.session.getWorkingDirectory())
}), }),
})), }))
}, },
] ]
if (this.uac.isAvailable) { if (this.uac.isAvailable) {
items.push({ items.push({
label: 'New as admin', label: 'New admin tab',
submenu: shells.map(shell => ({ submenu: profiles.map(profile => ({
label: shell.name, label: profile.name,
click: () => this.zone.run(async () => { click: () => this.zone.run(async () => {
let options = this.terminalService.optionsFromShell(shell) this.terminalService.openTabWithOptions({
options.runAsAdministrator = true ...profile.sessionOptions,
this.terminalService.openTabWithOptions(options) runAsAdministrator: true
})
}), }),
})), })),
}) })
} }
items = items.concat([
{
label: 'New with profile',
submenu: this.config.store.terminal.profiles.length ? this.config.store.terminal.profiles.map(profile => ({
label: profile.name,
click: () => this.zone.run(() => {
this.terminalService.openTabWithOptions(profile.sessionOptions)
}),
})) : [{
label: 'No profiles saved',
enabled: false,
}],
},
])
return items return items
} }
} }

View File

@ -1,6 +1,6 @@
import slug from 'slug' import slug from 'slug'
import { Injectable } from '@angular/core' import { Injectable } from '@angular/core'
import { IHotkeyDescription, HotkeyProvider, ConfigService } from 'terminus-core' import { IHotkeyDescription, HotkeyProvider } from 'terminus-core'
import { TerminalService } from './services/terminal.service' import { TerminalService } from './services/terminal.service'
/** @hidden */ /** @hidden */
@ -66,19 +66,14 @@ export class TerminalHotkeyProvider extends HotkeyProvider {
] ]
constructor ( constructor (
private config: ConfigService,
private terminal: TerminalService, private terminal: TerminalService,
) { super() } ) { super() }
async provide (): Promise<IHotkeyDescription[]> { async provide (): Promise<IHotkeyDescription[]> {
let shells = await this.terminal.shells$.toPromise() let profiles = await this.terminal.getProfiles()
return [ return [
...this.hotkeys, ...this.hotkeys,
...shells.map(shell => ({ ...profiles.map(profile => ({
id: `shell.${shell.id}`,
name: `New tab: ${shell.name}`
})),
...this.config.store.terminal.profiles.map(profile => ({
id: `profile.${slug(profile.name)}`, id: `profile.${slug(profile.name)}`,
name: `New tab: ${profile.name}` name: `New tab: ${profile.name}`
})), })),

View File

@ -1 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 384 512"><path d="M368 224H224V80c0-8.84-7.16-16-16-16h-32c-8.84 0-16 7.16-16 16v144H16c-8.84 0-16 7.16-16 16v32c0 8.84 7.16 16 16 16h144v144c0 8.84 7.16 16 16 16h32c8.84 0 16-7.16 16-16V288h144c8.84 0 16-7.16 16-16v-32c0-8.84-7.16-16-16-16z"/></svg> <svg aria-hidden="true" focusable="false" data-prefix="fal" data-icon="plus" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 384 512" class="svg-inline--fa fa-plus fa-w-12 fa-3x"><path fill="#ffffff" d="M376 232H216V72c0-4.42-3.58-8-8-8h-32c-4.42 0-8 3.58-8 8v160H8c-4.42 0-8 3.58-8 8v32c0 4.42 3.58 8 8 8h160v160c0 4.42 3.58 8 8 8h32c4.42 0 8-3.58 8-8V280h160c4.42 0 8-3.58 8-8v-32c0-4.42-3.58-8-8-8z" class="" stroke="none" stroke-width="1px"></path></svg>

Before

Width:  |  Height:  |  Size: 303 B

After

Width:  |  Height:  |  Size: 469 B

View File

@ -0,0 +1 @@
<svg aria-hidden="true" focusable="false" data-prefix="fal" data-icon="window-restore" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" class="svg-inline--fa fa-window-restore fa-w-16 fa-3x"><path fill="#ffffff" d="M464 0H144c-26.5 0-48 21.5-48 48v48H48c-26.5 0-48 21.5-48 48v320c0 26.5 21.5 48 48 48h320c26.5 0 48-21.5 48-48v-48h48c26.5 0 48-21.5 48-48V48c0-26.5-21.5-48-48-48zM32 144c0-8.8 7.2-16 16-16h320c8.8 0 16 7.2 16 16v80H32v-80zm352 320c0 8.8-7.2 16-16 16H48c-8.8 0-16-7.2-16-16V256h352v208zm96-96c0 8.8-7.2 16-16 16h-48V144c0-26.5-21.5-48-48-48H128V48c0-8.8 7.2-16 16-16h320c8.8 0 16 7.2 16 16v320z" class="" stroke="none" stroke-width="1px"></path></svg>

After

Width:  |  Height:  |  Size: 685 B

View File

@ -161,15 +161,8 @@ export default class TerminalModule {
if (hotkey === 'new-window') { if (hotkey === 'new-window') {
hostApp.newWindow() hostApp.newWindow()
} }
if (hotkey.startsWith('shell.')) {
let shells = await terminal.shells$.toPromise()
let shell = shells.find(x => x.id === hotkey.split('.')[1])
if (shell) {
terminal.openTab(shell)
}
}
if (hotkey.startsWith('profile.')) { if (hotkey.startsWith('profile.')) {
let profiles = config.store.terminal.profiles let profiles = await config.store.terminal.getProfiles()
let profile = profiles.find(x => slug(x.name) === hotkey.split('.')[1]) let profile = profiles.find(x => slug(x.name) === hotkey.split('.')[1])
if (profile) { if (profile) {
terminal.openTabWithOptions(profile.sessionOptions) terminal.openTabWithOptions(profile.sessionOptions)
@ -188,9 +181,11 @@ export default class TerminalModule {
hostApp.cliRunCommand$.subscribe(async command => { hostApp.cliRunCommand$.subscribe(async command => {
terminal.openTab({ terminal.openTab({
id: '', name: '',
command: command[0], sessionOptions: {
args: command.slice(1), command: command[0],
args: command.slice(1),
},
}, null, true) }, null, true)
hostApp.bringToFront() hostApp.bringToFront()
}) })

View File

@ -1,8 +1,9 @@
import * as fs from 'mz/fs' import * as fs from 'mz/fs'
import slug from 'slug'
import { Observable, AsyncSubject } from 'rxjs' import { Observable, AsyncSubject } from 'rxjs'
import { Injectable, Inject } from '@angular/core' import { Injectable, Inject } from '@angular/core'
import { AppService, Logger, LogService, ConfigService, SplitTabComponent } from 'terminus-core' import { AppService, Logger, LogService, ConfigService, SplitTabComponent } from 'terminus-core'
import { IShell, ShellProvider, SessionOptions } from '../api' import { IShell, ShellProvider, SessionOptions, Profile } from '../api'
import { TerminalTabComponent } from '../components/terminalTab.component' import { TerminalTabComponent } from '../components/terminalTab.component'
import { UACService } from './uac.service' import { UACService } from './uac.service'
@ -37,6 +38,18 @@ export class TerminalService {
return shellLists.reduce((a, b) => a.concat(b), []) return shellLists.reduce((a, b) => a.concat(b), [])
} }
async getProfiles (): Promise<Profile[]> {
let shells = await this.shells$.toPromise()
return [
...this.config.store.terminal.profiles,
...shells.map(shell => ({
name: shell.name,
sessionOptions: this.optionsFromShell(shell),
isBuiltin: true
}))
]
}
private async reloadShells () { private async reloadShells () {
this.shells = new AsyncSubject<IShell[]>() this.shells = new AsyncSubject<IShell[]>()
let shells = await this.getShells() let shells = await this.getShells()
@ -49,11 +62,16 @@ export class TerminalService {
* Launches a new terminal with a specific shell and CWD * Launches a new terminal with a specific shell and CWD
* @param pause Wait for a keypress when the shell exits * @param pause Wait for a keypress when the shell exits
*/ */
async openTab (shell?: IShell, cwd?: string, pause?: boolean): Promise<TerminalTabComponent> { async openTab (profile?: Profile, cwd?: string, pause?: boolean): Promise<TerminalTabComponent> {
cwd = cwd || profile.sessionOptions.cwd
if (cwd && !fs.existsSync(cwd)) { if (cwd && !fs.existsSync(cwd)) {
console.warn('Ignoring non-existent CWD:', cwd) console.warn('Ignoring non-existent CWD:', cwd)
cwd = null cwd = null
} }
if (!profile) {
let profiles = await this.getProfiles()
profile = profiles.find(x => slug(x.name) === this.config.store.terminal.profile) || profiles[0]
}
if (!cwd) { if (!cwd) {
if (this.app.activeTab instanceof TerminalTabComponent && this.app.activeTab.session) { if (this.app.activeTab instanceof TerminalTabComponent && this.app.activeTab.session) {
cwd = await this.app.activeTab.session.getWorkingDirectory() cwd = await this.app.activeTab.session.getWorkingDirectory()
@ -68,14 +86,10 @@ export class TerminalService {
cwd = cwd || this.config.store.terminal.workingDirectory cwd = cwd || this.config.store.terminal.workingDirectory
cwd = cwd || null cwd = cwd || null
} }
if (!shell) {
let shells = await this.shells$.toPromise()
shell = shells.find(x => x.id === this.config.store.terminal.shell) || shells[0]
}
this.logger.log(`Starting shell ${shell.name}`, shell) this.logger.log(`Starting profile ${profile.name}`, profile)
let sessionOptions = { let sessionOptions = {
...this.optionsFromShell(shell), ...profile.sessionOptions,
pauseAfterExit: pause, pauseAfterExit: pause,
cwd, cwd,
} }

View File

@ -47,7 +47,8 @@ export class CmderShellProvider extends ShellProvider {
'-noexit', '-noexit',
'-command', '-command',
`Invoke-Expression '. ''${path.join(process.env.CMDER_ROOT, 'vendor', 'profile.ps1')}'''` `Invoke-Expression '. ''${path.join(process.env.CMDER_ROOT, 'vendor', 'profile.ps1')}'''`
] ],
env: {},
}, },
] ]
} }

View File

@ -19,6 +19,7 @@ export class CustomShellProvider extends ShellProvider {
name: 'Custom shell', name: 'Custom shell',
command: args[0], command: args[0],
args: args.slice(1), args: args.slice(1),
env: {},
}] }]
} }
} }

View File

@ -28,7 +28,8 @@ export class LinuxDefaultShellProvider extends ShellProvider {
return [{ return [{
id: 'default', id: 'default',
name: 'User default', name: 'User default',
command: '/bin/sh' command: '/bin/sh',
env: {},
}] }]
} else { } else {
return [{ return [{
@ -36,6 +37,7 @@ export class LinuxDefaultShellProvider extends ShellProvider {
name: 'User default', name: 'User default',
command: line.split(':')[6], command: line.split(':')[6],
args: ['--login'], args: ['--login'],
env: {},
}] }]
} }
} }

View File

@ -23,6 +23,7 @@ export class MacOSDefaultShellProvider extends ShellProvider {
name: 'User default', name: 'User default',
command: shellEntry.split(' ')[1].trim(), command: shellEntry.split(' ')[1].trim(),
args: ['--login'], args: ['--login'],
env: {},
}] }]
} }
} }

View File

@ -24,9 +24,10 @@ export class POSIXShellsProvider extends ShellProvider {
.filter(x => x && !x.startsWith('#')) .filter(x => x && !x.startsWith('#'))
.map(x => ({ .map(x => ({
id: slug(x), id: slug(x),
name: x, name: x.split('/')[2],
command: x, command: x,
args: ['-l'], args: ['-l'],
env: {},
})) }))
} }
} }

View File

@ -40,6 +40,7 @@ export class WindowsDefaultShellProvider extends ShellProvider {
...shell, ...shell,
id: 'default', id: 'default',
name: 'User default', name: 'User default',
env: {},
}] }]
} }
} }

View File

@ -33,9 +33,10 @@ export class WindowsStockShellsProvider extends ShellProvider {
`clink_${process.arch}.exe`, `clink_${process.arch}.exe`,
), ),
'inject', 'inject',
] ],
env: {},
}, },
{ id: 'cmd', name: 'CMD (stock)', command: 'cmd.exe' }, { id: 'cmd', name: 'CMD (stock)', command: 'cmd.exe', env: {} },
{ {
id: 'powershell', id: 'powershell',
name: 'PowerShell', name: 'PowerShell',