Compare commits

...

25 Commits

Author SHA1 Message Date
Eugene Pankov
0d4ebe3d96 Revert "bumped electron"
This reverts commit 7237c2b05a.
2019-04-30 21:18:17 +02:00
Eugene Pankov
c856f460e6 Revert "bumped xterm for true color support (#23)"
This reverts commit c5958bc9a0.
2019-04-29 19:55:36 +02:00
Eugene Pankov
6a969d2cd2 Revert "use new style xterm events"
This reverts commit d42e070e6c.
2019-04-29 19:50:53 +02:00
Eugene Pankov
b6cbd42d8b less touchbar flicker, activity icons 2019-04-28 14:38:21 +02:00
Eugene Pankov
7237c2b05a bumped electron 2019-04-28 14:37:50 +02:00
Eugene Pankov
19a217923e build fix 2019-04-28 12:55:13 +02:00
Eugene Pankov
7f160e9421 Merge branch 'master' of github.com:Eugeny/terminus 2019-04-28 11:48:12 +02:00
Eugene Pankov
d0c245d0d5 fixed funky source maps 2019-04-28 11:42:34 +02:00
Eugene Pankov
693edab597 prevent recovered tabs from blanking out 2019-04-28 11:41:31 +02:00
Eugene Pankov
d42e070e6c use new style xterm events 2019-04-17 22:03:20 +02:00
Eugene Pankov
c5958bc9a0 bumped xterm for true color support (#23) 2019-04-17 21:57:52 +02:00
Eugene Pankov
9dc2337787 hotkey naming 2019-04-16 15:42:11 +02:00
Eugene
1a38cc30a8 Merge pull request #766 from Mezner/master
Create close pane hotkey.
2019-04-16 15:39:22 +02:00
Russell Myers
4949f14184 Create close pane hotkey. 2019-04-15 21:16:54 -04:00
Eugene
11902020a5 Merge pull request #743 from mischah/relaxed-theme
Add Relaxed color scheme
2019-03-30 08:30:05 -07:00
Michael Kühnel
3f96c21f33 Add Relaxed color scheme 2019-03-30 16:22:20 +01:00
Eugene
9e81f0aa0e Update README.md 2019-03-19 13:26:06 +01:00
Eugene
1cce23cef5 Update README.md 2019-03-19 13:02:33 +01:00
Eugene Pankov
b7a56adb60 smaller icons for the compact theme 2019-03-18 22:34:46 +01:00
Eugene Pankov
eb02752cbf use dynamic xterm atlas for faster startup 2019-03-18 22:23:44 +01:00
Eugene Pankov
3a6eb8cb2f bumped plugin versions 2019-03-18 22:02:23 +01:00
Eugene Pankov
a7d62b0234 fixed home/end keys with conpty (fixes #587) 2019-03-18 22:00:43 +01:00
Eugene
b9cbe4f12d Update snapcraft.yaml 2019-03-13 12:45:41 +01:00
Eugene
5f74b35ba9 Update snapcraft.yaml 2019-03-13 12:39:14 +01:00
Eugene
affb439ab2 Update snapcraft.yaml 2019-03-13 12:33:48 +01:00
29 changed files with 197 additions and 68 deletions

View File

@@ -1,31 +1,36 @@
![](https://github.com/Eugeny/terminus/raw/master/docs/readme.png)
<p align="center">
<a href="https://raw.githubusercontent.com/Eugeny/terminus/master/LICENSE"><img src="https://img.shields.io/badge/license-MIT-blue.svg"/></a> <a href="https://travis-ci.org/Eugeny/terminus"><img src="https://travis-ci.org/Eugeny/terminus.svg?branch=master"/></a>
<a href="https://ci.appveyor.com/project/Eugeny/terminus"><img src="https://ci.appveyor.com/api/projects/status/wnnq4hm5mbd9rgoy?svg=true"/></a>
<a href="https://raw.githubusercontent.com/Eugeny/terminus/master/LICENSE"><img alt="GitHub" src="https://img.shields.io/github/license/eugeny/terminus.svg?label=License&style=flat-square"></a> <a href="https://travis-ci.org/Eugeny/terminus"><img alt="Travis (.org)" src="https://img.shields.io/travis/Eugeny/terminus.svg?label=CI&logo=travis&logoColor=white&style=flat-square"></a>
<a href="https://ci.appveyor.com/project/Eugeny/terminus"><img alt="AppVeyor" src="https://img.shields.io/appveyor/ci/eugeny/terminus.svg?label=CI&logo=appveyor&logoColor=white&style=flat-square"></a>
</p>
<p align="center">
<a href="https://github.com/Eugeny/terminus/releases/latest">Downloads</a> | <a href="https://gitter.im/terminus-terminal/community">Community</a> | <a href="https://ci.appveyor.com/project/Eugeny/terminus/build/artifacts">Latest Windows nightly</a>
<a href="https://github.com/Eugeny/terminus/releases/latest"><img alt="GitHub All Releases" src="https://img.shields.io/github/downloads/eugeny/terminus/total.svg?label=DOWNLOAD&logo=github&style=for-the-badge"></a> <a href="https://ci.appveyor.com/project/Eugeny/terminus/build/artifacts"><img src="https://img.shields.io/badge/download-nightly%20build-magenta.svg?logo=appveyor&style=for-the-badge"/></a> <a href="https://gitter.im/terminus-terminal/community"><img alt="Gitter" src="https://img.shields.io/gitter/room/terminus/community.svg?color=blue&logo=gitter&style=for-the-badge"></a>
</p>
----
**Terminus** is a terminal heavily inspired by Hyper. It is, however, designed for people who need to get things done.
**Terminus** is a highly configurable terminal emulator for Windows, macOS and Linux
* Runs on Windows, macOS and Linux
* Theming and color schemes
* Fully configurable shortcuts
* Split panes
* Remembers your tabs
* PowerShell (and PS Core), WSL, Git-Bash, Cygwin, Cmder and CMD support
* Integrated SSH client and connection manager
* Full Unicode support including double-width characters
* Doesn't choke on fast-flowing outputs
* Proper shell-like experience on Windows including tab completion (via Clink)
* PowerShell (+Core), WSL (Bash on Windows), Git-Bash, Cygwin, Cmder and CMD support
* Remembers your tabs
* Integrated SSH client and connection manager
* Proper shell experience on Windows including tab completion (via Clink)
[![Buy me a coffee](https://github.com/Eugeny/terminus/raw/master/docs/kofi.png)](https://ko-fi.com/eugeny)
---
* **Terminus is** an alternative to Windows' standard terminal (conhost), PowerShell ISE, PuTTY or iTerm
* **Terminus is not** a new shell or a MinGW or Cygwin replacement. Neither is it lightweight - if RAM usage is of importance, consider [Conemu](https://conemu.github.io) or [Alacritty](https://github.com/jwilm/alacritty)
---

BIN
app/assets/activity.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.9 KiB

View File

@@ -14,7 +14,7 @@ module.exports = {
minimize: false,
},
context: __dirname,
devtool: 'source-map',
devtool: 'eval-source-map',
output: {
path: path.join(__dirname, 'dist'),
pathinfo: true,

View File

@@ -9,7 +9,7 @@ module.exports = {
},
mode: process.env.TERMINUS_DEV ? 'development' : 'production',
context: __dirname,
devtool: 'source-map',
devtool: 'eval-source-map',
output: {
path: path.join(__dirname, 'dist'),
pathinfo: true,

26
snap/snapcraft.yaml Normal file
View File

@@ -0,0 +1,26 @@
name: terminus
version: '1.0.0'
summary: A terminal for a modern age
description: |
Terminus is a terminal heavily inspired by Hyper. It is, however, designed for people who need to get things done.
grade: devel
confinement: devmode
apps:
terminus:
command: opt/terminus/terminus
parts:
app:
plugin: nodejs
source: .
build-packages:
- libfontconfig-dev
override-build: |
yarn
./scripts/build-native.js
yarn run build
./scripts/build-linux.js
mkdir -p $SNAPCRAFT_PART_INSTALL/opt/terminus || true
cp -ar dist/linux-unpacked/* $SNAPCRAFT_PART_INSTALL/opt/terminus/

View File

@@ -1,6 +1,6 @@
{
"name": "terminus-community-color-schemes",
"version": "1.0.68-c17-g8b64a81",
"version": "1.0.73-c4-ga7d62b0",
"description": "Community color schemes for Terminus",
"keywords": [
"terminus-builtin-plugin"

View File

@@ -0,0 +1,36 @@
! special
*.foreground: #d8d8d8
*.background: #343a43
*.cursorColor: #d8d8d8
! black
*.color0: #2c3037
*.color8: #626262
! red
*.color1: #bb5653
*.color9: #c35956
! green
*.color2: #909d62
*.color10: #9fab76
! yellow
*.color3: #eac179
*.color11: #ecc179
! blue
*.color4: #698698
*.color12: #7da9c7
! magenta
*.color5: #b06597
*.color13: #ba6ca0
! cyan
*.color6: #c9dfff
*.color14: #abbacf
! white
*.color7: #d8d8d8
*.color15: #f7f7f7

View File

@@ -4,7 +4,7 @@ const webpack = require('webpack')
module.exports = {
target: 'node',
entry: 'src/index.ts',
devtool: 'source-map',
devtool: 'eval-source-map',
context: __dirname,
output: {
path: path.resolve(__dirname, 'dist'),

View File

@@ -1,6 +1,6 @@
{
"name": "terminus-core",
"version": "1.0.68-c17-g8b64a81",
"version": "1.0.73-c4-ga7d62b0",
"description": "Terminus core",
"keywords": [
"terminus-builtin-plugin"

View File

@@ -210,18 +210,21 @@ export class SplitTabComponent extends BaseTabComponent implements OnInit, OnDes
case 'split-left':
this.splitTab(this.focusedTab, 'l')
break
case 'split-nav-left':
case 'pane-nav-left':
this.navigate('l')
break
case 'split-nav-right':
case 'pane-nav-right':
this.navigate('r')
break
case 'split-nav-up':
case 'pane-nav-up':
this.navigate('t')
break
case 'split-nav-down':
case 'pane-nav-down':
this.navigate('b')
break
case 'close-pane':
this.removeTab(this.focusedTab)
break
}
})
}
@@ -336,6 +339,8 @@ export class SplitTabComponent extends BaseTabComponent implements OnInit, OnDes
if (this.root.children.length === 0) {
this.destroy()
} else {
this.focusAnyIn(parent)
}
}

View File

@@ -42,12 +42,13 @@ hotkeys:
- 'Ctrl-Shift-D'
split-left: []
split-top: []
split-nav-right:
pane-nav-right:
- 'Ctrl-Alt-ArrowRight'
split-nav-down:
pane-nav-down:
- 'Ctrl-Alt-ArrowDown'
split-nav-up:
pane-nav-up:
- 'Ctrl-Alt-ArrowUp'
split-nav-left:
pane-nav-left:
- 'Ctrl-Alt-ArrowLeft'
close-pane: []
pluginBlacklist: ['ssh']

View File

@@ -40,12 +40,14 @@ hotkeys:
- '⌘-D'
split-left: []
split-top: []
split-nav-right:
pane-nav-right:
- '⌘-⌥-ArrowRight'
split-nav-down:
pane-nav-down:
- '⌘-⌥-ArrowDown'
split-nav-up:
pane-nav-up:
- '⌘-⌥-ArrowUp'
split-nav-left:
pane-nav-left:
- '⌘-⌥-ArrowLeft'
close-pane:
- '⌘-Shift-W'
pluginBlacklist: ['ssh']

View File

@@ -42,12 +42,13 @@ hotkeys:
- 'Ctrl-Shift-D'
split-left: []
split-top: []
split-nav-right:
pane-nav-right:
- 'Ctrl-Alt-ArrowRight'
split-nav-down:
pane-nav-down:
- 'Ctrl-Alt-ArrowDown'
split-nav-up:
pane-nav-up:
- 'Ctrl-Alt-ArrowUp'
split-nav-left:
pane-nav-left:
- 'Ctrl-Alt-ArrowLeft'
close-pane: []
pluginBlacklist: []

View File

@@ -94,21 +94,25 @@ export class AppHotkeyProvider extends HotkeyProvider {
name: 'Split to the top',
},
{
id: 'split-nav-up',
id: 'pane-nav-up',
name: 'Focus the pane above',
},
{
id: 'split-nav-down',
id: 'pane-nav-down',
name: 'Focus the pane below',
},
{
id: 'split-nav-left',
id: 'pane-nav-left',
name: 'Focus the pane on the left',
},
{
id: 'split-nav-right',
id: 'pane-nav-right',
name: 'Focus the pane on the right',
},
{
id: 'close-pane',
name: 'Close focused pane',
},
]
async provide (): Promise<IHotkeyDescription[]> {

View File

@@ -10,6 +10,7 @@ import { IToolbarButton, ToolbarButtonProvider } from '../api'
@Injectable({ providedIn: 'root' })
export class TouchbarService {
private tabsSegmentedControl: TouchBarSegmentedControl
private buttonsSegmentedControl: TouchBarSegmentedControl
private tabSegments: SegmentedControlSegment[] = []
private nsImageCache: {[id: string]: Electron.NativeImage} = {}
@@ -24,16 +25,31 @@ export class TouchbarService {
if (this.hostApp.platform !== Platform.macOS) {
return
}
app.tabsChanged$.subscribe(() => this.update())
app.activeTabChange$.subscribe(() => this.update())
app.tabsChanged$.subscribe(() => this.updateTabs())
app.activeTabChange$.subscribe(() => this.updateTabs())
let activityIconPath = `${electron.app.getAppPath()}/assets/activity.png`
let activityIcon = this.electron.nativeImage.createFromPath(activityIconPath)
app.tabOpened$.subscribe(tab => {
tab.titleChange$.subscribe(title => {
this.tabSegments[app.tabs.indexOf(tab)].label = this.shortenTitle(title)
this.tabsSegmentedControl.segments = this.tabSegments
})
tab.activity$.subscribe(hasActivity => {
let showIcon = this.app.activeTab !== tab && hasActivity
this.tabSegments[app.tabs.indexOf(tab)].icon = showIcon ? activityIcon : null
})
})
}
updateTabs () {
this.tabSegments = this.app.tabs.map(tab => ({
label: this.shortenTitle(tab.title),
}))
this.tabsSegmentedControl.segments = this.tabSegments
this.tabsSegmentedControl.selectedIndex = this.app.tabs.indexOf(this.app.activeTab)
}
update () {
if (this.hostApp.platform !== Platform.macOS) {
return
@@ -47,6 +63,7 @@ export class TouchbarService {
this.tabSegments = this.app.tabs.map(tab => ({
label: this.shortenTitle(tab.title),
}))
this.tabsSegmentedControl = new this.electron.TouchBar.TouchBarSegmentedControl({
segments: this.tabSegments,
selectedIndex: this.app.tabs.indexOf(this.app.activeTab),
@@ -54,23 +71,32 @@ export class TouchbarService {
this.app.selectTab(this.app.tabs[selectedIndex])
})
})
this.buttonsSegmentedControl = new this.electron.TouchBar.TouchBarSegmentedControl({
segments: buttons.map(button => this.getButton(button)),
mode: 'buttons',
change: (selectedIndex) => this.zone.run(() => {
buttons[selectedIndex].click()
})
})
let touchBar = new this.electron.TouchBar({
items: [
this.tabsSegmentedControl,
new this.electron.TouchBar.TouchBarSpacer({ size: 'flexible' }),
new this.electron.TouchBar.TouchBarSpacer({ size: 'small' }),
...buttons.map(button => this.getButton(button))
this.buttonsSegmentedControl,
]
})
this.hostApp.setTouchBar(touchBar)
}
private getButton (button: IToolbarButton): Electron.TouchBarButton {
return new this.electron.TouchBar.TouchBarButton({
private getButton (button: IToolbarButton): Electron.SegmentedControlSegment {
return {
label: button.touchBarNSImage ? null : this.shortenTitle(button.touchBarTitle || button.title),
icon: button.touchBarNSImage ? this.getCachedNSImage(button.touchBarNSImage) : null,
click: () => this.zone.run(() => button.click()),
})
// click: () => this.zone.run(() => button.click()),
}
}
private getCachedNSImage (name: string) {

View File

@@ -6,6 +6,10 @@ app-root {
.btn-tab-bar {
line-height: 29px !important;
svg {
height: 14px;
}
}
}

View File

@@ -4,7 +4,7 @@ const webpack = require('webpack')
module.exports = {
target: 'node',
entry: 'src/index.ts',
devtool: 'source-map',
devtool: 'eval-source-map',
context: __dirname,
mode: 'development',
output: {

View File

@@ -1,6 +1,6 @@
{
"name": "terminus-plugin-manager",
"version": "1.0.68-c17-g8b64a81",
"version": "1.0.73-c4-ga7d62b0",
"description": "Terminus' plugin manager",
"keywords": [
"terminus-builtin-plugin"

View File

@@ -4,7 +4,7 @@ const webpack = require('webpack')
module.exports = {
target: 'node',
entry: 'src/index.ts',
devtool: 'source-map',
devtool: 'eval-source-map',
context: __dirname,
output: {
path: path.resolve(__dirname, 'dist'),

View File

@@ -1,6 +1,6 @@
{
"name": "terminus-settings",
"version": "1.0.68-c17-g8b64a81",
"version": "1.0.73-c4-ga7d62b0",
"description": "Terminus terminal settings page",
"keywords": [
"terminus-builtin-plugin"

View File

@@ -4,7 +4,7 @@ const webpack = require('webpack')
module.exports = {
target: 'node',
entry: 'src/index.ts',
devtool: 'source-map',
devtool: 'eval-source-map',
context: __dirname,
mode: 'development',
output: {

View File

@@ -1,6 +1,6 @@
{
"name": "terminus-ssh",
"version": "1.0.68-c17-g8b64a81",
"version": "1.0.73-c4-ga7d62b0",
"description": "SSH connection manager for Terminus",
"keywords": [
"terminus-builtin-plugin"

View File

@@ -3,7 +3,7 @@ const path = require('path')
module.exports = {
target: 'node',
entry: 'src/index.ts',
devtool: 'source-map',
devtool: 'eval-source-map',
context: __dirname,
output: {
path: path.resolve(__dirname, 'dist'),

View File

@@ -1,6 +1,6 @@
{
"name": "terminus-terminal",
"version": "1.0.68-c17-g8b64a81",
"version": "1.0.73-c4-ga7d62b0",
"description": "Terminus' terminal emulation core",
"keywords": [
"terminus-builtin-plugin"
@@ -28,7 +28,7 @@
"slug": "^0.9.3",
"uuid": "^3.3.2",
"xterm": "3.10.1",
"xterm-addon-ligatures-tmp": "^0.1.0-beta-1"
"xterm-addon-ligatures": "^0.1.0-beta-2"
},
"peerDependencies": {
"@angular/common": "4.0.1",

View File

@@ -110,12 +110,6 @@ export class BaseTerminalTabComponent extends BaseTabComponent implements OnInit
case 'reset-zoom':
this.resetZoom()
break
case 'home':
this.sendInput('\x1bOH')
break
case 'end':
this.sendInput('\x1bOF')
break
case 'previous-word':
this.sendInput('\x1bb')
break

View File

@@ -1,9 +1,11 @@
import { Component, Input } from '@angular/core'
import { Subscription } from 'rxjs'
import { first } from 'rxjs/operators'
import { BaseTabProcess } from 'terminus-core'
import { BaseTerminalTabComponent } from './baseTerminalTab.component'
import { SessionOptions } from '../api'
import { Session } from '../services/sessions.service'
import { WIN_BUILD_CONPTY_SUPPORTED, isWindowsBuild } from '../utils'
/** @hidden */
@Component({
@@ -13,11 +15,28 @@ import { Session } from '../services/sessions.service'
})
export class TerminalTabComponent extends BaseTerminalTabComponent {
@Input() sessionOptions: SessionOptions
private homeEndSubscription: Subscription
ngOnInit () {
this.logger = this.log.create('terminalTab')
this.session = new Session(this.config)
let isConPTY = isWindowsBuild(WIN_BUILD_CONPTY_SUPPORTED) && this.config.store.terminal.useConPTY
this.homeEndSubscription = this.hotkeys.matchedHotkey.subscribe(hotkey => {
if (!this.hasFocus) {
return
}
switch (hotkey) {
case 'home':
this.sendInput(isConPTY ? '\x1b[H' : '\x1bOH')
break
case 'end':
this.sendInput(isConPTY ? '\x1b[F' : '\x1bOF')
break
}
})
this.frontendReady$.pipe(first()).subscribe(() => {
this.initializeSession(this.size.columns, this.size.rows)
})
@@ -73,4 +92,9 @@ export class TerminalTabComponent extends BaseTerminalTabComponent {
}
)).response === 1
}
ngOnDestroy () {
this.homeEndSubscription.unsubscribe()
super.ngOnDestroy()
}
}

View File

@@ -1,14 +1,11 @@
import { Frontend } from './frontend'
import { Terminal, ITheme } from 'xterm'
import * as fit from 'xterm/src/addons/fit/fit'
import * as ligatures from 'xterm-addon-ligatures-tmp'
import { fit } from 'xterm/src/addons/fit/fit'
import { enableLigatures } from 'xterm-addon-ligatures'
import 'xterm/lib/xterm.css'
import './xterm.css'
import deepEqual = require('deep-equal')
Terminal.applyAddon(fit)
Terminal.applyAddon(ligatures)
/** @hidden */
export class XTermFrontend extends Frontend {
enableResizing = true
@@ -25,6 +22,7 @@ export class XTermFrontend extends Frontend {
this.xterm = new Terminal({
allowTransparency: true,
enableBold: true,
experimentalCharAtlas: 'dynamic',
})
this.xtermCore = (this.xterm as any)._core
@@ -74,7 +72,7 @@ export class XTermFrontend extends Frontend {
this.resizeHandler = () => {
try {
(this.xterm as any).fit()
fit(this.xterm)
} catch {
// tends to throw when element wasn't shown yet
}
@@ -145,11 +143,14 @@ export class XTermFrontend extends Frontend {
configure (): void {
let config = this.configService.store
setTimeout(() => {
setImmediate(() => {
if (this.xterm.cols && this.xterm.rows) {
this.xtermCore.charMeasure.measure(this.xtermCore.options)
this.xtermCore.renderer._updateDimensions()
this.resizeHandler()
}
})
this.xterm.setOption('fontFamily', `"${config.terminal.font}", "monospace-fallback", monospace`)
this.xterm.setOption('bellStyle', config.terminal.bell)
this.xterm.setOption('cursorStyle', {
@@ -184,7 +185,7 @@ export class XTermFrontend extends Frontend {
}
if (config.terminal.ligatures && this.xterm.element) {
(this.xterm as any).enableLigatures()
enableLigatures(this.xterm)
}
}

View File

@@ -4,7 +4,7 @@ const webpack = require('webpack')
module.exports = {
target: 'node',
entry: 'src/index.ts',
devtool: 'source-map',
devtool: 'eval-source-map',
context: __dirname,
output: {
path: path.resolve(__dirname, 'dist'),

View File

@@ -253,10 +253,10 @@ windows-process-tree@^0.2.3:
dependencies:
nan "^2.10.0"
xterm-addon-ligatures-tmp@^0.1.0-beta-1:
xterm-addon-ligatures@^0.1.0-beta-2:
version "0.1.0-beta-2"
resolved "https://registry.yarnpkg.com/xterm-addon-ligatures-tmp/-/xterm-addon-ligatures-tmp-0.1.0-beta-2.tgz#1063a282b279b7586372dee7892cea59738c613e"
integrity sha512-d+UoX5dfP7ZSEE/DnQlqubs7Bpw5UxLfTAibpo4pOU2KFw+lRlsLgHg5fcmhXoEvD9rj01enYTsIjedNwnwC5Q==
resolved "https://registry.yarnpkg.com/xterm-addon-ligatures/-/xterm-addon-ligatures-0.1.0-beta-2.tgz#def635fd0ca671fe61179629f8492b76c66dec6e"
integrity sha512-MN5zCBxrF9xagzUYIpcgHS4L/Isod3m3ET5S7AUEEbymLJ+4zccio32eyq65Bcc50x/Bm57Hoh9gaSEUdojs8g==
dependencies:
font-finder "^1.0.2"
font-ligatures "^1.3.1"