提交 57227ae6 编写于 作者: E Eugene Pankov

Merge branch 'master' of github.com:Eugeny/terminus

......@@ -17,7 +17,7 @@
* Doesn't choke on fast-flowing outputs
* Tab persistence on macOS and Linux
* Proper shell-like experience on Windows including tab completion (thanks, Clink!)
* CMD, PowerShell and Bash on Windows support
* CMD, PowerShell, Cygwin, Git-Bash and Bash on Windows support
---
......
......@@ -16,5 +16,4 @@ exports.builtinPlugins = [
'terminus-plugin-manager',
]
exports.nativeModules = ['node-pty', 'font-manager']
exports.version = appInfo.version
exports.electronVersion = pkgInfo.devDependencies.electron
......@@ -40,12 +40,12 @@ export class DockingService {
newBounds.height = Math.round(fill * display.bounds.height)
}
if (dockSide === 'right') {
newBounds.x = display.bounds.x + display.bounds.width * (1.0 - fill)
newBounds.x = display.bounds.x + Math.round(display.bounds.width * (1.0 - fill))
} else {
newBounds.x = display.bounds.x
}
if (dockSide === 'bottom') {
newBounds.y = display.bounds.y + display.bounds.height * (1.0 - fill)
newBounds.y = display.bounds.y + Math.round(display.bounds.height * (1.0 - fill))
} else {
newBounds.y = display.bounds.y
}
......
......@@ -109,17 +109,17 @@ ngb-tabset.vertical(type='tabs')
label Display on
br
div(
'[(ngModel)]'='config.store.appearance.dockScreen'
'(ngModelChange)'='config.save(); docking.dock()'
[(ngModel)]='config.store.appearance.dockScreen',
(ngModelChange)='config.save(); docking.dock()',
ngbRadioGroup
)
label.btn.btn-secondary
input(
type='radio',
[value]='"current"'
value='current'
)
| Current
label.btn.btn-secondary(*ngFor='let screen of docking.getScreens()')
label.btn.btn-secondary(*ngFor='let screen of screens')
input(
type='radio',
[value]='screen.id'
......
......@@ -14,6 +14,7 @@ import { SettingsTabProvider } from '../api'
export class SettingsTabComponent extends BaseTabComponent {
hotkeyFilter = ''
private hotkeyDescriptions: IHotkeyDescription[]
private screens
constructor (
public config: ConfigService,
......@@ -28,6 +29,7 @@ export class SettingsTabComponent extends BaseTabComponent {
this.hotkeyDescriptions = hotkeyProviders.map(x => x.hotkeys).reduce((a, b) => a.concat(b))
this.title$.next('Settings')
this.scrollable = true
this.screens = this.docking.getScreens()
}
getRecoveryToken (): any {
......
import * as path from 'path'
import { exec } from 'mz/child_process'
import * as fs from 'mz/fs'
import { Injectable } from '@angular/core'
import { HotkeysService, ToolbarButtonProvider, IToolbarButton, AppService, ConfigService, ElectronService } from 'terminus-core'
import { HotkeysService, ToolbarButtonProvider, IToolbarButton, AppService, ConfigService, ElectronService, HostAppService, Platform } from 'terminus-core'
import { SessionsService } from './services/sessions.service'
import { TerminalTabComponent } from './components/terminalTab.component'
......@@ -12,6 +14,7 @@ export class ButtonProvider extends ToolbarButtonProvider {
private sessions: SessionsService,
private config: ConfigService,
private electron: ElectronService,
private hostApp: HostAppService,
hotkeys: HotkeysService,
) {
super()
......@@ -43,6 +46,22 @@ export class ButtonProvider extends ToolbarButtonProvider {
'inject',
]
}
if (command === '~default-shell~') {
if (this.hostApp.platform === Platform.Linux) {
let line = (await fs.readFile('/etc/passwd', { encoding: 'utf-8' }))
.split('\n').find(x => x.startsWith(process.env.LOGNAME + ':'))
if (!line) {
console.warn('Could not detect user shell')
command = '/bin/sh'
} else {
command = line.split(':')[5]
}
}
if (this.hostApp.platform === Platform.macOS) {
let shellEntry = (await exec(`dscl . -read /Users/${process.env.LOGNAME} UserShell`))[0].toString()
command = shellEntry.split(':')[1].trim()
}
}
let sessionOptions = await this.sessions.prepareNewSession({ command, args, cwd })
this.app.openNewTab(
TerminalTabComponent,
......
import { Observable } from 'rxjs'
import * as fs from 'fs-promise'
import * as fs from 'mz/fs'
import * as path from 'path'
import { exec } from 'mz/child_process'
const equal = require('deep-equal')
......@@ -59,16 +59,20 @@ export class TerminalSettingsTabComponent {
{ name: 'CMD (stock)', command: 'cmd.exe' },
{ name: 'PowerShell', command: 'powershell.exe' },
]
// Detect whether BoW is installed
const wslPath = `${process.env.windir}\\system32\\bash.exe`
if (await fs.exists(wslPath)) {
this.shells.push({ name: 'Bash on Windows', command: wslPath })
}
// Detect Cygwin
let cygwinPath = await new Promise<string>(resolve => {
let reg = new Registry({ hive: Registry.HKLM, key: '\\Software\\Cygwin\\setup' })
reg.get('rootdir', (err, item) => {
if (err) {
resolve(null)
return
}
resolve(item.value)
})
......@@ -76,13 +80,29 @@ export class TerminalSettingsTabComponent {
if (cygwinPath) {
this.shells.push({ name: 'Cygwin', command: path.join(cygwinPath, 'bin', 'bash.exe') })
}
// Detect Git-Bash
let gitBashPath = await new Promise<string>(resolve => {
let reg = new Registry({ hive: Registry.HKLM, key: '\\Software\\GitForWindows' })
reg.get('InstallPath', (err, item) => {
if (err) {
resolve(null)
return
}
resolve(item.value)
})
})
if (gitBashPath) {
this.shells.push({ name: 'Git-Bash', command: path.join(gitBashPath, 'bin', 'bash.exe') })
}
}
if (this.hostApp.platform === Platform.Linux || this.hostApp.platform === Platform.macOS) {
this.shells = (await fs.readFile('/etc/shells', 'utf-8'))
this.shells = [{ name: 'Default shell', command: '~default-shell~' }]
this.shells = this.shells.concat((await fs.readFile('/etc/shells', { encoding: 'utf-8' }))
.split('\n')
.map(x => x.trim())
.filter(x => x && !x.startsWith('#'))
.map(x => ({ name: x, command: x }))
.map(x => ({ name: x, command: x })))
}
this.colorSchemes = (await Promise.all(this.colorSchemeProviders.map(x => x.getSchemes()))).reduce((a, b) => a.concat(b))
}
......
......@@ -40,7 +40,7 @@ export class TerminalConfigProvider extends ConfigProvider {
[Platform.macOS]: {
terminal: {
font: 'Menlo',
shell: '/bin/zsh',
shell: '~default-shell~',
},
hotkeys: {
'new-tab': [
......@@ -67,7 +67,7 @@ export class TerminalConfigProvider extends ConfigProvider {
[Platform.Linux]: {
terminal: {
font: 'Liberation Mono',
shell: '/bin/bash',
shell: '~default-shell~',
},
hotkeys: {
'new-tab': [
......
......@@ -100,7 +100,7 @@ export class ScreenPersistenceProvider extends SessionPersistenceProvider {
altscreen on
`, 'utf-8')
let recoveryId = `term-tab-${Date.now()}`
let args = ['-d', '-m', '-c', configPath, '-U', '-S', recoveryId, '-T', 'xterm-256color', '--', options.command].concat(options.args || [])
let args = ['-d', '-m', '-c', configPath, '-U', '-S', recoveryId, '-T', 'xterm-256color', '--', '-' + options.command].concat(options.args || [])
this.logger.debug('Spawning screen with', args.join(' '))
await spawn('screen', args, {
cwd: options.cwd,
......
......@@ -28,10 +28,6 @@ export class Session {
...options.env,
TERM: 'xterm-256color',
}
if (options.command.includes(' ')) {
options.args = ['-c', options.command]
options.command = 'sh'
}
this.pty = nodePTY.spawn(options.command, options.args || [], {
name: 'xterm-256color',
cols: options.width || 80,
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册