mirror of
https://github.com/Eugeny/tabby.git
synced 2025-03-01 15:06:27 +08:00
WSL2 support - fixes #271
This commit is contained in:
parent
f58cab0820
commit
b29ab2690f
@ -155,6 +155,8 @@ export class ConfigService {
|
||||
}
|
||||
|
||||
save (): void {
|
||||
// Scrub undefined values
|
||||
this._store = JSON.parse(JSON.stringify(this._store))
|
||||
fs.writeFileSync(this.path, yaml.safeDump(this._store), 'utf8')
|
||||
this.emitChange()
|
||||
this.hostApp.broadcastConfigChange(this.store)
|
||||
|
@ -19,6 +19,7 @@ export interface Profile {
|
||||
name: string
|
||||
color?: string
|
||||
sessionOptions: SessionOptions
|
||||
shell?: string
|
||||
isBuiltin?: boolean
|
||||
icon?: string
|
||||
}
|
||||
|
@ -11,7 +11,7 @@ h3.mb-3 Shell
|
||||
)
|
||||
option(
|
||||
*ngFor='let profile of profiles',
|
||||
[ngValue]='slugify(profile.name).toLowerCase()'
|
||||
[ngValue]='terminal.getProfileID(profile)'
|
||||
) {{profile.name}}
|
||||
|
||||
|
||||
|
@ -1,4 +1,3 @@
|
||||
import slugify from 'slugify'
|
||||
import { Component } from '@angular/core'
|
||||
import { NgbModal } from '@ng-bootstrap/ng-bootstrap'
|
||||
import { Subscription } from 'rxjs'
|
||||
@ -17,14 +16,13 @@ export class ShellSettingsTabComponent {
|
||||
Platform = Platform
|
||||
isConPTYAvailable: boolean
|
||||
isConPTYStable: boolean
|
||||
slugify = slugify
|
||||
private configSubscription: Subscription
|
||||
|
||||
constructor (
|
||||
public config: ConfigService,
|
||||
public hostApp: HostAppService,
|
||||
public terminal: TerminalService,
|
||||
private electron: ElectronService,
|
||||
private terminalService: TerminalService,
|
||||
private ngbModal: NgbModal,
|
||||
) {
|
||||
config.store.terminal.environment = config.store.terminal.environment || {}
|
||||
@ -38,7 +36,7 @@ export class ShellSettingsTabComponent {
|
||||
}
|
||||
|
||||
async ngOnInit (): Promise<void> {
|
||||
this.shells = await this.terminalService.shells$.toPromise()
|
||||
this.shells = await this.terminal.shells$.toPromise()
|
||||
}
|
||||
|
||||
ngOnDestroy (): void {
|
||||
@ -46,21 +44,22 @@ export class ShellSettingsTabComponent {
|
||||
}
|
||||
|
||||
async reload (): Promise<void> {
|
||||
this.profiles = await this.terminalService.getProfiles({ includeHidden: true })
|
||||
this.profiles = await this.terminal.getProfiles({ includeHidden: true })
|
||||
}
|
||||
|
||||
pickWorkingDirectory (): void {
|
||||
const shell = this.shells.find(x => x.id === this.config.store.terminal.shell)
|
||||
async pickWorkingDirectory (): Promise<void> {
|
||||
const profile = await this.terminal.getProfileByID(this.config.store.terminal.profile)
|
||||
const shell = this.shells.find(x => x.id === profile?.shell)
|
||||
if (!shell) {
|
||||
return
|
||||
}
|
||||
const paths = this.electron.dialog.showOpenDialog(
|
||||
const paths = (await this.electron.dialog.showOpenDialog(
|
||||
this.hostApp.getWindow(),
|
||||
{
|
||||
defaultPath: shell.fsBase,
|
||||
properties: ['openDirectory', 'showHiddenFiles'],
|
||||
}
|
||||
)
|
||||
)).filePaths
|
||||
if (paths) {
|
||||
this.config.store.terminal.workingDirectory = paths[0]
|
||||
}
|
||||
@ -69,7 +68,8 @@ export class ShellSettingsTabComponent {
|
||||
newProfile (shell: Shell): void {
|
||||
const profile: Profile = {
|
||||
name: shell.name || '',
|
||||
sessionOptions: this.terminalService.optionsFromShell(shell),
|
||||
shell: shell.id,
|
||||
sessionOptions: this.terminal.optionsFromShell(shell),
|
||||
}
|
||||
this.config.store.terminal.profiles = [profile, ...this.config.store.terminal.profiles]
|
||||
this.config.save()
|
||||
|
@ -30,7 +30,7 @@ h3.mb-3 Terminal
|
||||
)
|
||||
| Audible
|
||||
|
||||
.alert.alert-info.d-flex.align-items-center(*ngIf='config.store.terminal.bell != "audible" && config.store.terminal.shell.startsWith("wsl")')
|
||||
.alert.alert-info.d-flex.align-items-center(*ngIf='config.store.terminal.bell != "audible" && config.store.terminal.profile.startsWith("wsl")')
|
||||
.mr-auto WSL terminal bell can only be muted via Volume Mixer
|
||||
button.btn.btn-secondary((click)='openWSLVolumeMixer()') Show Mixer
|
||||
|
||||
|
@ -1,4 +1,3 @@
|
||||
import slugify from 'slugify'
|
||||
import { Injectable } from '@angular/core'
|
||||
import { HotkeyDescription, HotkeyProvider } from 'terminus-core'
|
||||
import { TerminalService } from './services/terminal.service'
|
||||
@ -78,7 +77,7 @@ export class TerminalHotkeyProvider extends HotkeyProvider {
|
||||
return [
|
||||
...this.hotkeys,
|
||||
...profiles.map(profile => ({
|
||||
id: `profile.${slugify(profile.name).toLowerCase()}`,
|
||||
id: `profile.${this.terminal.getProfileID(profile)}`,
|
||||
name: `New tab: ${profile.name}`,
|
||||
})),
|
||||
]
|
||||
|
@ -1,5 +1,4 @@
|
||||
import * as fs from 'mz/fs'
|
||||
import slugify from 'slugify'
|
||||
|
||||
import { NgModule } from '@angular/core'
|
||||
import { BrowserModule } from '@angular/platform-browser'
|
||||
@ -187,8 +186,7 @@ export default class TerminalModule { // eslint-disable-line @typescript-eslint/
|
||||
hostApp.newWindow()
|
||||
}
|
||||
if (hotkey.startsWith('profile.')) {
|
||||
const profiles = await terminal.getProfiles()
|
||||
const profile = profiles.find(x => slugify(x.name).toLowerCase() === hotkey.split('.')[1])
|
||||
const profile = await terminal.getProfileByID(hotkey.split('.')[1])
|
||||
if (profile) {
|
||||
terminal.openTabWithOptions(profile.sessionOptions)
|
||||
}
|
||||
|
@ -40,6 +40,7 @@ export class TerminalService {
|
||||
...this.config.store.terminal.profiles,
|
||||
...skipDefault ? [] : shells.filter(x => includeHidden || !x.hidden).map(shell => ({
|
||||
name: shell.name,
|
||||
shell: shell.id,
|
||||
icon: shell.icon,
|
||||
sessionOptions: this.optionsFromShell(shell),
|
||||
isBuiltin: true,
|
||||
@ -47,14 +48,25 @@ export class TerminalService {
|
||||
]
|
||||
}
|
||||
|
||||
getProfileID (profile: Profile): string {
|
||||
return slugify(profile.name).toLowerCase()
|
||||
}
|
||||
|
||||
async getProfileByID (id: string): Promise<Profile> {
|
||||
const profiles = await this.getProfiles({ includeHidden: true })
|
||||
return profiles.find(x => this.getProfileID(x) === id) || profiles[0]
|
||||
}
|
||||
|
||||
/**
|
||||
* Launches a new terminal with a specific shell and CWD
|
||||
* @param pause Wait for a keypress when the shell exits
|
||||
*/
|
||||
async openTab (profile?: Profile, cwd?: string|null, pause?: boolean): Promise<TerminalTabComponent> {
|
||||
if (!profile) {
|
||||
const profiles = await this.getProfiles({ includeHidden: true })
|
||||
profile = profiles.find(x => slugify(x.name).toLowerCase() === this.config.store.terminal.profile) || profiles[0]
|
||||
profile = await this.getProfileByID(this.config.store.terminal.profile)
|
||||
if (!profile) {
|
||||
profile = (await this.getProfiles({ includeHidden: true }))[0]
|
||||
}
|
||||
}
|
||||
|
||||
cwd = cwd || profile.sessionOptions.cwd
|
||||
|
@ -88,13 +88,15 @@ export class WSLShellProvider extends ShellProvider {
|
||||
if (!childKey.DistributionName) {
|
||||
continue
|
||||
}
|
||||
const wslVersion = (childKey.Flags.value & 8) ? 2 : 1
|
||||
const name = childKey.DistributionName.value
|
||||
const fsBase = (wslVersion === 2) ? `\\\\wsl$\\${name}` : (childKey.BasePath.value as string + '\\rootfs')
|
||||
const shell: Shell = {
|
||||
id: `wsl-${slugify(name)}`,
|
||||
name: `WSL / ${name}`,
|
||||
command: wslPath,
|
||||
args: ['-d', name],
|
||||
fsBase: childKey.BasePath.value as string + '\\rootfs',
|
||||
fsBase,
|
||||
env: {
|
||||
TERM: 'xterm-color',
|
||||
COLORTERM: 'truecolor',
|
||||
|
Loading…
Reference in New Issue
Block a user