Pārlūkot izejas kodu

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

Eugene Pankov 8 gadi atpakaļ
vecāks
revīzija
57227ae6ce

+ 1 - 1
README.md

@@ -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
 
 ---
 

+ 0 - 1
scripts/vars.js

@@ -16,5 +16,4 @@ exports.builtinPlugins = [
   'terminus-plugin-manager',
 ]
 exports.nativeModules = ['node-pty', 'font-manager']
-exports.version = appInfo.version
 exports.electronVersion = pkgInfo.devDependencies.electron

+ 2 - 2
terminus-core/src/services/docking.service.ts

@@ -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
         }

+ 4 - 4
terminus-settings/src/components/settingsTab.component.pug

@@ -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'

+ 2 - 0
terminus-settings/src/components/settingsTab.component.ts

@@ -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 {

+ 20 - 1
terminus-terminal/src/buttonProvider.ts

@@ -1,6 +1,8 @@
 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,

+ 23 - 3
terminus-terminal/src/components/terminalSettingsTab.component.ts

@@ -1,5 +1,5 @@
 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))
     }

+ 2 - 2
terminus-terminal/src/config.ts

@@ -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': [

+ 1 - 1
terminus-terminal/src/persistenceProviders.ts

@@ -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,

+ 0 - 4
terminus-terminal/src/services/sessions.service.ts

@@ -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,