Compare commits

..

71 Commits

Author SHA1 Message Date
Eugene Pankov
b1752bd0b4 updated cwd settings UI 2021-02-07 13:44:17 +01:00
Eugene Pankov
1e697a952a upgraded xterm.js 2021-02-07 13:44:08 +01:00
Eugene Pankov
6bad2a2167 cache dscl output 2021-02-07 13:43:58 +01:00
Eugene Pankov
61a46e3b4a lint 2021-02-07 13:15:24 +01:00
Eugene Pankov
cba90cec0a better error messages for X11 forwarding issues 2021-02-07 12:49:34 +01:00
Eugene Pankov
7583d92747 set terminus to use built-in graphics by default - fixes #657 2021-02-07 12:49:22 +01:00
Eugene Pankov
e2b99d71ad lint 2021-02-06 17:47:17 +01:00
Eugene Pankov
aac38fa190 CWD detection on windows where possible 2021-02-06 16:45:38 +01:00
Eugene Pankov
7098622c8f bumped electron 2021-02-06 11:20:34 +01:00
Eugene Pankov
8695003c74 lint 2021-02-01 11:40:49 +01:00
Eugene Pankov
43a27a7b7c serial newline modes 2021-01-31 20:07:26 +01:00
Eugene Pankov
dd2d2ce20d Update tsconfig.json 2021-01-31 19:33:33 +01:00
Eugene Pankov
73574374f0 readline input mode for serial terminals - #3099, #2661 2021-01-31 19:33:30 +01:00
Eugene Pankov
5bd1bfd565 better editor ts support 2021-01-31 18:20:58 +01:00
Eugene Pankov
0611afa8b5 better session handlers behaviour, added serial auto-reconnection logic - #3099 2021-01-31 18:20:39 +01:00
Eugene Pankov
91c9e8affd bumped angular 2021-01-28 22:01:42 +01:00
Eugene Pankov
322ffc5847 margin fix 2021-01-28 21:55:29 +01:00
Eugene Pankov
21084b5d24 bumped js-yaml 2021-01-28 21:52:11 +01:00
Eugene Pankov
e0efb4073a bumped eslint 2021-01-28 21:46:31 +01:00
Eugene Pankov
c42b62afe6 bumped deps 2021-01-28 21:11:53 +01:00
Eugene Pankov
e2b11c83d5 fixed cli args handling 2021-01-28 21:11:47 +01:00
Eugene Pankov
891fa5770a Update electron-builder.yml 2021-01-28 18:45:09 +01:00
Eugene Pankov
6b395cc2b3 fixed windows native module import 2021-01-28 18:20:45 +01:00
Eugene Pankov
448a1a094f fixed macOS native module builds 2021-01-27 00:26:48 +01:00
Eugene Pankov
788dd61a13 exclude native modules from app.asar and sign them 2021-01-26 15:29:18 +01:00
Eugene Pankov
467684d9ab Update api.ts 2021-01-25 21:35:00 +01:00
Eugene Pankov
5069070040 added a 'copy current path' hotkey and context menu item - fixes #2586 2021-01-25 17:30:44 +01:00
Eugene Pankov
ecf5297bc3 Merge branch 'master' of github.com:Eugeny/terminus 2021-01-24 19:27:42 +01:00
Eugene Pankov
78bd90ac55 fixed window re-focusing on linux 2021-01-24 19:27:36 +01:00
Eugene Pankov
712589eb93 fixed #1510 2021-01-24 19:06:51 +01:00
Eugene Pankov
f103e71285 better handling of CLI args - fixes #1436 2021-01-24 19:06:41 +01:00
Eugene Pankov
0cf883cc4a bumped electron 2021-01-24 13:58:47 +01:00
Eugene Pankov
2b0ad0d558 ssh: 15s default keepalive interval 2021-01-24 13:33:54 +01:00
Eugene Pankov
67bacb9dd3 ssh: better session close and reconnect behaviours - fixes #3351, fixes #3010, fixes #3276, fixes #3074, fixes #2825, fixes #3285 2021-01-24 13:28:59 +01:00
Eugene Pankov
d0a597634d ssh: fixed clearing jump host in connection settings 2021-01-24 13:08:07 +01:00
Eugene Pankov
322014c409 Merge branch 'master' of github.com:Eugeny/terminus 2021-01-24 12:43:02 +01:00
Eugene Pankov
c751a8725b rollback node-pty to pre-napi state 2021-01-24 12:42:59 +01:00
Eugene Pankov
5417efe558 ssh: blacklist broken kex algorithms 2021-01-24 11:26:43 +01:00
Eugene
bf356fcd19 Merge pull request #3362 from mi544/readme-fix
Removes unnecessary asterisks from README
2021-01-22 09:37:05 +01:00
Maksim Verkhoturov
10ee66b9dd removes unnecessary asterisks 2021-01-21 15:45:37 -07:00
Eugene
763da0d80c Merge pull request #3310 from Eugeny/dependabot/npm_and_yarn/app/npm-6.14.11
Bump npm from 6.14.10 to 6.14.11 in /app
2021-01-15 15:12:16 +01:00
Eugene
8d46bb2181 Merge pull request #3290 from Eugeny/dependabot/npm_and_yarn/terminus-core/core-js-3.8.2
Bump core-js from 3.7.0 to 3.8.2 in /terminus-core
2021-01-15 15:12:05 +01:00
Eugene Pankov
fe936c7726 fixed #3333 - duplicate color schemes 2021-01-14 09:48:58 +01:00
Eugene Pankov
2f3e32990a Update macos.yml 2021-01-13 13:52:23 +01:00
Eugene Pankov
22344f8d54 Update macos.yml 2021-01-13 10:50:34 +01:00
Eugene Pankov
f6d37a39f4 Update macos.yml 2021-01-12 18:20:17 +01:00
dependabot-preview[bot]
0e4c60ad4b Bump npm from 6.14.10 to 6.14.11 in /app
Bumps [npm](https://github.com/npm/cli) from 6.14.10 to 6.14.11.
- [Release notes](https://github.com/npm/cli/releases)
- [Changelog](https://github.com/npm/cli/blob/v6.14.11/CHANGELOG.md)
- [Commits](https://github.com/npm/cli/compare/v6.14.10...v6.14.11)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2021-01-12 17:01:34 +00:00
dependabot-preview[bot]
e8c2171d8f Bump core-js from 3.7.0 to 3.8.2 in /terminus-core
Bumps [core-js](https://github.com/zloirock/core-js) from 3.7.0 to 3.8.2.
- [Release notes](https://github.com/zloirock/core-js/releases)
- [Changelog](https://github.com/zloirock/core-js/blob/master/CHANGELOG.md)
- [Commits](https://github.com/zloirock/core-js/compare/v3.7.0...v3.8.2)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2021-01-12 17:01:01 +00:00
Eugene Pankov
f7a5be2c67 downgraded electron 2021-01-12 17:59:13 +01:00
Eugene Pankov
39fa0424a6 handle auto-updater errors 2021-01-09 18:22:58 +01:00
Eugene Pankov
bcb1b6a13b fixed tab scrolling 2021-01-09 17:48:31 +01:00
Eugene Pankov
a19f35ac44 fixed macos builds 2021-01-09 17:30:23 +01:00
Eugene Pankov
ea92f1a700 Revert "vibrancy fixes"
This reverts commit a8d78ce185.
2021-01-09 17:29:37 +01:00
Eugene Pankov
b5701cf9f9 fixed linux crashes 2021-01-09 17:29:34 +01:00
Eugene Pankov
4742530cf3 fixed invisible tab bar on the bottom in full-titlebar mode - fixes #3191 2021-01-09 17:11:05 +01:00
Eugene Pankov
a8d78ce185 vibrancy fixes 2021-01-09 17:02:01 +01:00
Eugene Pankov
bba1eaccbe fixed hotkeys page crash - fixes #3311 2021-01-09 16:15:20 +01:00
Eugene Pankov
cd6d05aa69 Merge branch 'master' of github.com:Eugeny/terminus 2021-01-09 15:38:58 +01:00
Eugene Pankov
412403c72a updated glasstron 2021-01-09 15:38:55 +01:00
Eugene
93ae907dd1 Merge pull request #3304 from Eugeny/all-contributors/add-frauhottelmann 2021-01-06 10:34:38 +01:00
allcontributors[bot]
ce24b9cc52 docs: update .all-contributorsrc [skip ci] 2021-01-06 09:32:42 +00:00
allcontributors[bot]
dc68372d76 docs: update README.md [skip ci] 2021-01-06 09:32:40 +00:00
Eugene
e0fe125cf2 Merge pull request #3303 from frauhottelmann/master
add baudrate 1500000
2021-01-06 10:32:21 +01:00
frauhottelmann
e594fcd0e7 add baudrate 1500000
1500000bps is needed for single board computers with RK3399 CPUs
2021-01-06 10:19:18 +01:00
Eugene Pankov
0219da4d85 sourcemap separation 2021-01-04 21:31:33 +01:00
Eugene Pankov
5e06b2248b better sentry upload 2021-01-04 20:44:24 +01:00
Eugene Pankov
cdc3623986 sentry wip 2021-01-04 20:02:47 +01:00
Eugene Pankov
6d016002c0 sentry symbols on linux 2021-01-04 19:39:59 +01:00
Eugene Pankov
f3569f5d2d sentry symbols on win 2021-01-04 19:21:12 +01:00
Eugene Pankov
4125582ef2 sentry symbols on mac 2021-01-04 19:11:57 +01:00
Eugene Pankov
c6331c9b1c fixed AppService.selectTab crash 2021-01-03 20:53:53 +01:00
65 changed files with 1677 additions and 942 deletions

View File

@@ -334,6 +334,15 @@
"contributions": [
"code"
]
},
{
"login": "frauhottelmann",
"name": "frauhottelmann",
"avatar_url": "https://avatars2.githubusercontent.com/u/902705?v=4",
"profile": "https://github.com/frauhottelmann",
"contributions": [
"code"
]
}
],
"contributorsPerLine": 7,

View File

@@ -1,6 +1,8 @@
parser: '@typescript-eslint/parser'
parserOptions:
project: tsconfig.json
project:
- tsconfig.json
- '*/tsconfig.typings.json'
extends:
- 'plugin:@typescript-eslint/all'
plugins:
@@ -37,6 +39,7 @@ rules:
'@typescript-eslint/no-misused-promises': off
'@typescript-eslint/typedef': off
'@typescript-eslint/consistent-type-imports': off
'@typescript-eslint/sort-type-union-intersection-members': off
'@typescript-eslint/no-use-before-define':
- error
- classes: false
@@ -81,7 +84,8 @@ rules:
argsIgnorePattern: ^_
no-undef: error
no-var: error
object-curly-spacing:
object-curly-spacing: off
'@typescript-eslint/object-curly-spacing':
- error
- always
quote-props:

View File

@@ -38,6 +38,15 @@ jobs:
GH_TOKEN: ${{ secrets.GH_TOKEN }}
USE_HARD_LINKS: false
- name: Upload symbols
run: |
sudo npm install -g @sentry/cli --unsafe-perm
./scripts/sentry-upload.js
env:
SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}
SENTRY_ORG: ${{ secrets.SENTRY_ORG }}
SENTRY_PROJECT: ${{ secrets.SENTRY_PROJECT }}
- name: Package artifacts
run: |
mkdir artifact-deb

View File

@@ -26,6 +26,10 @@ jobs:
cd ..
rm app/node_modules/.yarn-integrity
yarn
./node_modules/.bin/patch-package
cd app
../node_modules/.bin/patch-package
cd ..
- name: Build native deps
run: scripts/build-native.js
@@ -62,6 +66,15 @@ jobs:
ARCH: ${{matrix.arch}}
# DEBUG: electron-builder,electron-builder:*
- name: Upload symbols
run: |
sudo npm install -g @sentry/cli --unsafe-perm
./scripts/sentry-upload.js
env:
SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}
SENTRY_ORG: ${{ secrets.SENTRY_ORG }}
SENTRY_PROJECT: ${{ secrets.SENTRY_PROJECT }}
- name: Package artifacts
run: |
mkdir artifact-pkg

View File

@@ -34,6 +34,15 @@ jobs:
run: node scripts/build-windows.js
if: github.repository != 'Eugeny/terminus' || github.event_name != 'push'
- name: Upload symbols
run: |
npm install @sentry/cli
node scripts/sentry-upload.js
env:
SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}
SENTRY_ORG: ${{ secrets.SENTRY_ORG }}
SENTRY_PROJECT: ${{ secrets.SENTRY_PROJECT }}
- name: Package artifacts
run: |
mkdir artifact-setup

View File

@@ -1,4 +1,4 @@
****![](https://github.com/Eugeny/terminus/raw/master/docs/readme.png)
![](https://github.com/Eugeny/terminus/raw/master/docs/readme.png)
<p align="center">
@@ -74,57 +74,59 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d
<!-- markdownlint-disable -->
<table>
<tr>
<td align="center"><a href="http://www.russellmyers.com"><img src="https://avatars2.githubusercontent.com/u/184085?v=4" width="100px;" alt=""/><br /><sub><b>Russell Myers</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=mezner" title="Code">💻</a></td>
<td align="center"><a href="http://www.morwire.com"><img src="https://avatars1.githubusercontent.com/u/3991658?v=4" width="100px;" alt=""/><br /><sub><b>Austin Warren</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=ehwarren" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/Drachenkaetzchen"><img src="https://avatars1.githubusercontent.com/u/162974?v=4" width="100px;" alt=""/><br /><sub><b>Felicia Hummel</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=Drachenkaetzchen" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/mikemaccana"><img src="https://avatars2.githubusercontent.com/u/172594?v=4" width="100px;" alt=""/><br /><sub><b>Mike MacCana</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=mikemaccana" title="Tests">⚠️</a> <a href="#design-mikemaccana" title="Design">🎨</a></td>
<td align="center"><a href="https://github.com/yxuko"><img src="https://avatars1.githubusercontent.com/u/1786317?v=4" width="100px;" alt=""/><br /><sub><b>Yacine Kanzari</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=yxuko" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/BBJip"><img src="https://avatars2.githubusercontent.com/u/32908927?v=4" width="100px;" alt=""/><br /><sub><b>BBJip</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=BBJip" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/Futagirl"><img src="https://avatars2.githubusercontent.com/u/33533958?v=4" width="100px;" alt=""/><br /><sub><b>Futagirl</b></sub></a><br /><a href="#design-Futagirl" title="Design">🎨</a></td>
<td align="center"><a href="http://www.russellmyers.com"><img src="https://avatars2.githubusercontent.com/u/184085?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Russell Myers</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=mezner" title="Code">💻</a></td>
<td align="center"><a href="http://www.morwire.com"><img src="https://avatars1.githubusercontent.com/u/3991658?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Austin Warren</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=ehwarren" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/Drachenkaetzchen"><img src="https://avatars1.githubusercontent.com/u/162974?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Felicia Hummel</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=Drachenkaetzchen" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/mikemaccana"><img src="https://avatars2.githubusercontent.com/u/172594?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Mike MacCana</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=mikemaccana" title="Tests">⚠️</a> <a href="#design-mikemaccana" title="Design">🎨</a></td>
<td align="center"><a href="https://github.com/yxuko"><img src="https://avatars1.githubusercontent.com/u/1786317?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Yacine Kanzari</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=yxuko" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/BBJip"><img src="https://avatars2.githubusercontent.com/u/32908927?v=4?s=100" width="100px;" alt=""/><br /><sub><b>BBJip</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=BBJip" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/Futagirl"><img src="https://avatars2.githubusercontent.com/u/33533958?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Futagirl</b></sub></a><br /><a href="#design-Futagirl" title="Design">🎨</a></td>
</tr>
<tr>
<td align="center"><a href="https://www.levrik.io"><img src="https://avatars3.githubusercontent.com/u/9491603?v=4" width="100px;" alt=""/><br /><sub><b>Levin Rickert</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=levrik" title="Code">💻</a></td>
<td align="center"><a href="https://kwonoj.github.io"><img src="https://avatars2.githubusercontent.com/u/1210596?v=4" width="100px;" alt=""/><br /><sub><b>OJ Kwon</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=kwonoj" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/Domain"><img src="https://avatars2.githubusercontent.com/u/903197?v=4" width="100px;" alt=""/><br /><sub><b>domain</b></sub></a><br /><a href="#plugin-Domain" title="Plugin/utility libraries">🔌</a> <a href="https://github.com/Eugeny/terminus/commits?author=Domain" title="Code">💻</a></td>
<td align="center"><a href="http://www.jbrumond.me"><img src="https://avatars1.githubusercontent.com/u/195127?v=4" width="100px;" alt=""/><br /><sub><b>James Brumond</b></sub></a><br /><a href="#plugin-kbjr" title="Plugin/utility libraries">🔌</a></td>
<td align="center"><a href="http://www.growingwiththeweb.com"><img src="https://avatars0.githubusercontent.com/u/2193314?v=4" width="100px;" alt=""/><br /><sub><b>Daniel Imms</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=Tyriar" title="Code">💻</a> <a href="#plugin-Tyriar" title="Plugin/utility libraries">🔌</a> <a href="https://github.com/Eugeny/terminus/commits?author=Tyriar" title="Tests">⚠️</a></td>
<td align="center"><a href="https://github.com/baflo"><img src="https://avatars2.githubusercontent.com/u/834350?v=4" width="100px;" alt=""/><br /><sub><b>Florian Bachmann</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=baflo" title="Code">💻</a></td>
<td align="center"><a href="http://michael-kuehnel.de"><img src="https://avatars2.githubusercontent.com/u/441011?v=4" width="100px;" alt=""/><br /><sub><b>Michael Kühnel</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=mischah" title="Code">💻</a> <a href="#design-mischah" title="Design">🎨</a></td>
<td align="center"><a href="https://www.levrik.io"><img src="https://avatars3.githubusercontent.com/u/9491603?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Levin Rickert</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=levrik" title="Code">💻</a></td>
<td align="center"><a href="https://kwonoj.github.io"><img src="https://avatars2.githubusercontent.com/u/1210596?v=4?s=100" width="100px;" alt=""/><br /><sub><b>OJ Kwon</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=kwonoj" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/Domain"><img src="https://avatars2.githubusercontent.com/u/903197?v=4?s=100" width="100px;" alt=""/><br /><sub><b>domain</b></sub></a><br /><a href="#plugin-Domain" title="Plugin/utility libraries">🔌</a> <a href="https://github.com/Eugeny/terminus/commits?author=Domain" title="Code">💻</a></td>
<td align="center"><a href="http://www.jbrumond.me"><img src="https://avatars1.githubusercontent.com/u/195127?v=4?s=100" width="100px;" alt=""/><br /><sub><b>James Brumond</b></sub></a><br /><a href="#plugin-kbjr" title="Plugin/utility libraries">🔌</a></td>
<td align="center"><a href="http://www.growingwiththeweb.com"><img src="https://avatars0.githubusercontent.com/u/2193314?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Daniel Imms</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=Tyriar" title="Code">💻</a> <a href="#plugin-Tyriar" title="Plugin/utility libraries">🔌</a> <a href="https://github.com/Eugeny/terminus/commits?author=Tyriar" title="Tests">⚠️</a></td>
<td align="center"><a href="https://github.com/baflo"><img src="https://avatars2.githubusercontent.com/u/834350?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Florian Bachmann</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=baflo" title="Code">💻</a></td>
<td align="center"><a href="http://michael-kuehnel.de"><img src="https://avatars2.githubusercontent.com/u/441011?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Michael Kühnel</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=mischah" title="Code">💻</a> <a href="#design-mischah" title="Design">🎨</a></td>
</tr>
<tr>
<td align="center"><a href="https://github.com/NieLeben"><img src="https://avatars3.githubusercontent.com/u/47182955?v=4" width="100px;" alt=""/><br /><sub><b>Tilmann Meyer</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=NieLeben" title="Code">💻</a></td>
<td align="center"><a href="http://www.jubeat.net"><img src="https://avatars3.githubusercontent.com/u/11289158?v=4" width="100px;" alt=""/><br /><sub><b>PM Extra</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/issues?q=author%3APMExtra" title="Bug reports">🐛</a></td>
<td align="center"><a href="https://jjuhas.keybase.pub//"><img src="https://avatars1.githubusercontent.com/u/6438760?v=4" width="100px;" alt=""/><br /><sub><b>Jonathan</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=IgnusG" title="Code">💻</a></td>
<td align="center"><a href="https://hans-koch.me"><img src="https://avatars0.githubusercontent.com/u/1093709?v=4" width="100px;" alt=""/><br /><sub><b>Hans Koch</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=hammster" title="Code">💻</a></td>
<td align="center"><a href="http://thepuzzlemaker.info"><img src="https://avatars3.githubusercontent.com/u/12666617?v=4" width="100px;" alt=""/><br /><sub><b>Dak Smyth</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=ThePuzzlemaker" title="Code">💻</a></td>
<td align="center"><a href="http://yfwz100.github.io"><img src="https://avatars2.githubusercontent.com/u/983211?v=4" width="100px;" alt=""/><br /><sub><b>Wang Zhi</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=yfwz100" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/jack1142"><img src="https://avatars0.githubusercontent.com/u/6032823?v=4" width="100px;" alt=""/><br /><sub><b>jack1142</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=jack1142" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/NieLeben"><img src="https://avatars3.githubusercontent.com/u/47182955?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Tilmann Meyer</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=NieLeben" title="Code">💻</a></td>
<td align="center"><a href="http://www.jubeat.net"><img src="https://avatars3.githubusercontent.com/u/11289158?v=4?s=100" width="100px;" alt=""/><br /><sub><b>PM Extra</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/issues?q=author%3APMExtra" title="Bug reports">🐛</a></td>
<td align="center"><a href="https://jjuhas.keybase.pub//"><img src="https://avatars1.githubusercontent.com/u/6438760?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Jonathan</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=IgnusG" title="Code">💻</a></td>
<td align="center"><a href="https://hans-koch.me"><img src="https://avatars0.githubusercontent.com/u/1093709?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Hans Koch</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=hammster" title="Code">💻</a></td>
<td align="center"><a href="http://thepuzzlemaker.info"><img src="https://avatars3.githubusercontent.com/u/12666617?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Dak Smyth</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=ThePuzzlemaker" title="Code">💻</a></td>
<td align="center"><a href="http://yfwz100.github.io"><img src="https://avatars2.githubusercontent.com/u/983211?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Wang Zhi</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=yfwz100" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/jack1142"><img src="https://avatars0.githubusercontent.com/u/6032823?v=4?s=100" width="100px;" alt=""/><br /><sub><b>jack1142</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=jack1142" title="Code">💻</a></td>
</tr>
<tr>
<td align="center"><a href="https://github.com/hdougie"><img src="https://avatars1.githubusercontent.com/u/450799?v=4" width="100px;" alt=""/><br /><sub><b>Howie Douglas</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=hdougie" title="Code">💻</a></td>
<td align="center"><a href="https://chriskaczor.com"><img src="https://avatars2.githubusercontent.com/u/180906?v=4" width="100px;" alt=""/><br /><sub><b>Chris Kaczor</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=ckaczor" title="Code">💻</a></td>
<td align="center"><a href="https://www.boxmein.net"><img src="https://avatars1.githubusercontent.com/u/358714?v=4" width="100px;" alt=""/><br /><sub><b>Johannes Kadak</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=boxmein" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/LeSeulArtichaut"><img src="https://avatars1.githubusercontent.com/u/38361244?v=4" width="100px;" alt=""/><br /><sub><b>LeSeulArtichaut</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=LeSeulArtichaut" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/CyrilTaylor"><img src="https://avatars0.githubusercontent.com/u/12631466?v=4" width="100px;" alt=""/><br /><sub><b>Cyril Taylor</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=CyrilTaylor" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/nstefanou"><img src="https://avatars3.githubusercontent.com/u/51129173?v=4" width="100px;" alt=""/><br /><sub><b>nstefanou</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=nstefanou" title="Code">💻</a> <a href="#plugin-nstefanou" title="Plugin/utility libraries">🔌</a></td>
<td align="center"><a href="https://github.com/orin220444"><img src="https://avatars3.githubusercontent.com/u/30747229?v=4" width="100px;" alt=""/><br /><sub><b>orin220444</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=orin220444" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/hdougie"><img src="https://avatars1.githubusercontent.com/u/450799?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Howie Douglas</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=hdougie" title="Code">💻</a></td>
<td align="center"><a href="https://chriskaczor.com"><img src="https://avatars2.githubusercontent.com/u/180906?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Chris Kaczor</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=ckaczor" title="Code">💻</a></td>
<td align="center"><a href="https://www.boxmein.net"><img src="https://avatars1.githubusercontent.com/u/358714?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Johannes Kadak</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=boxmein" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/LeSeulArtichaut"><img src="https://avatars1.githubusercontent.com/u/38361244?v=4?s=100" width="100px;" alt=""/><br /><sub><b>LeSeulArtichaut</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=LeSeulArtichaut" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/CyrilTaylor"><img src="https://avatars0.githubusercontent.com/u/12631466?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Cyril Taylor</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=CyrilTaylor" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/nstefanou"><img src="https://avatars3.githubusercontent.com/u/51129173?v=4?s=100" width="100px;" alt=""/><br /><sub><b>nstefanou</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=nstefanou" title="Code">💻</a> <a href="#plugin-nstefanou" title="Plugin/utility libraries">🔌</a></td>
<td align="center"><a href="https://github.com/orin220444"><img src="https://avatars3.githubusercontent.com/u/30747229?v=4?s=100" width="100px;" alt=""/><br /><sub><b>orin220444</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=orin220444" title="Code">💻</a></td>
</tr>
<tr>
<td align="center"><a href="https://github.com/Goobles"><img src="https://avatars3.githubusercontent.com/u/8776771?v=4" width="100px;" alt=""/><br /><sub><b>Gobius Dolhain</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=Goobles" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/3l0w"><img src="https://avatars2.githubusercontent.com/u/37798980?v=4" width="100px;" alt=""/><br /><sub><b>Gwilherm Folliot</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=3l0w" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/Dimitory"><img src="https://avatars0.githubusercontent.com/u/475955?v=4" width="100px;" alt=""/><br /><sub><b>Dmitry Pronin</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=dimitory" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/JonathanBeverley"><img src="https://avatars1.githubusercontent.com/u/20328966?v=4" width="100px;" alt=""/><br /><sub><b>Jonathan Beverley</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=JonathanBeverley" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/zend"><img src="https://avatars1.githubusercontent.com/u/25160?v=4" width="100px;" alt=""/><br /><sub><b>Zenghai Liang</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=zend" title="Code">💻</a></td>
<td align="center"><a href="https://about.me/matishadow"><img src="https://avatars0.githubusercontent.com/u/9083085?v=4" width="100px;" alt=""/><br /><sub><b>Mateusz Tracz</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=matishadow" title="Code">💻</a></td>
<td align="center"><a href="https://zergpool.com"><img src="https://avatars3.githubusercontent.com/u/36234677?v=4" width="100px;" alt=""/><br /><sub><b>pinpin</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=pinpins" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/Goobles"><img src="https://avatars3.githubusercontent.com/u/8776771?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Gobius Dolhain</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=Goobles" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/3l0w"><img src="https://avatars2.githubusercontent.com/u/37798980?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Gwilherm Folliot</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=3l0w" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/Dimitory"><img src="https://avatars0.githubusercontent.com/u/475955?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Dmitry Pronin</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=dimitory" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/JonathanBeverley"><img src="https://avatars1.githubusercontent.com/u/20328966?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Jonathan Beverley</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=JonathanBeverley" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/zend"><img src="https://avatars1.githubusercontent.com/u/25160?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Zenghai Liang</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=zend" title="Code">💻</a></td>
<td align="center"><a href="https://about.me/matishadow"><img src="https://avatars0.githubusercontent.com/u/9083085?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Mateusz Tracz</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=matishadow" title="Code">💻</a></td>
<td align="center"><a href="https://zergpool.com"><img src="https://avatars3.githubusercontent.com/u/36234677?v=4?s=100" width="100px;" alt=""/><br /><sub><b>pinpin</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=pinpins" title="Code">💻</a></td>
</tr>
<tr>
<td align="center"><a href="https://github.com/TakuroOnoda"><img src="https://avatars0.githubusercontent.com/u/1407926?v=4" width="100px;" alt=""/><br /><sub><b>Takuro Onoda</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=TakuroOnoda" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/TakuroOnoda"><img src="https://avatars0.githubusercontent.com/u/1407926?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Takuro Onoda</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=TakuroOnoda" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/frauhottelmann"><img src="https://avatars2.githubusercontent.com/u/902705?v=4?s=100" width="100px;" alt=""/><br /><sub><b>frauhottelmann</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=frauhottelmann" title="Code">💻</a></td>
</tr>
</table>
<!-- markdownlint-enable -->
<!-- markdownlint-restore -->
<!-- prettier-ignore-end -->
<!-- ALL-CONTRIBUTORS-LIST:END -->
This project follows the [all-contributors](https://github.com/all-contributors/all-contributors) specification. Contributions of any kind welcome!

View File

@@ -75,7 +75,7 @@ export class Application {
}
onGlobalHotkey (): void {
if (this.windows.some(x => x.isFocused())) {
if (this.windows.some(x => x.isFocused() && x.isVisible())) {
for (const window of this.windows) {
window.hide()
}
@@ -147,7 +147,7 @@ export class Application {
handleSecondInstance (argv: string[], cwd: string): void {
this.presentAllWindows()
this.windows[this.windows.length - 1].handleSecondInstance(argv, cwd)
this.windows[this.windows.length - 1].passCliArguments(argv, cwd, true)
}
private setupMenu () {

View File

@@ -6,7 +6,7 @@ import { app } from 'electron'
export function loadConfig (): any {
const configPath = path.join(app.getPath('userData'), 'config.yaml')
if (fs.existsSync(configPath)) {
return yaml.safeLoad(fs.readFileSync(configPath, 'utf8'))
return yaml.load(fs.readFileSync(configPath, 'utf8'))
} else {
return {}
}

View File

@@ -53,7 +53,7 @@ if (argv.d) {
})
}
app.on('ready', () => {
app.on('ready', async () => {
if (process.platform === 'darwin') {
app.dock.setMenu(Menu.buildFromTemplate([
{
@@ -65,5 +65,8 @@ app.on('ready', () => {
]))
}
application.init()
application.newWindow({ hidden: argv.hidden })
const window = await application.newWindow({ hidden: argv.hidden })
await window.ready
window.passCliArguments(process.argv, process.cwd(), false)
})

View File

@@ -1,7 +1,4 @@
import * as glasstron from 'glasstron'
if (process.platform === 'win32' || process.platform === 'linux') {
glasstron.init()
}
import { Subject, Observable } from 'rxjs'
import { debounceTime } from 'rxjs/operators'
@@ -29,7 +26,7 @@ abstract class GlasstronWindow extends BrowserWindow {
abstract setBlur (_: boolean)
}
const macOSVibrancyType = compareVersions.compare(macOSRelease().version, '10.14', '>=') ? 'fullscreen-ui' : 'dark'
const macOSVibrancyType = process.platform === 'darwin' ? compareVersions.compare(macOSRelease().version, '10.14', '>=') ? 'fullscreen-ui' : 'dark' : null
export class Window {
ready: Promise<void>
@@ -39,7 +36,7 @@ export class Window {
private windowConfig: ElectronConfig
private windowBounds?: Rectangle
private closing = false
private lastVibrancy: {enabled: boolean, type?: string} | null = null
private lastVibrancy: { enabled: boolean, type?: string } | null = null
private disableVibrancyWhileDragging = false
private configStore: any
@@ -66,7 +63,9 @@ export class Window {
preload: path.join(__dirname, 'sentry.js'),
backgroundThrottling: false,
enableRemoteModule: true,
contextIsolation: false,
},
maximizable: true,
frame: false,
show: false,
backgroundColor: '#00000000',
@@ -149,7 +148,11 @@ export class Window {
if (process.platform === 'win32') {
if (parseFloat(os.release()) >= 10) {
this.window.blurType = enabled ? type === 'fluent' ? 'acrylic' : 'blurbehind' : null
this.window.setBlur(enabled)
try {
this.window.setBlur(enabled)
} catch (error) {
console.error('Failed to set window blur', error)
}
} else {
DwmEnableBlurBehindWindow(this.window, enabled)
}
@@ -188,6 +191,10 @@ export class Window {
return this.window.isFocused()
}
isVisible (): boolean {
return this.window.isVisible()
}
hide (): void {
if (process.platform === 'darwin') {
// Lose focus
@@ -223,8 +230,8 @@ export class Window {
}
}
handleSecondInstance (argv: string[], cwd: string): void {
this.send('host:second-instance', parseArgs(argv, cwd), cwd)
passCliArguments (argv: string[], cwd: string, secondInstance: boolean): void {
this.send('cli', parseArgs(argv, cwd), cwd, secondInstance)
}
private setupWindowManagement () {

View File

@@ -1,6 +1,7 @@
{
"name": "terminus",
"description": "A terminal for a modern age",
"private": true,
"repository": "https://github.com/eugeny/terminus",
"author": {
"name": "Eugene Pankov",
@@ -13,24 +14,25 @@
"watch": "webpack --progress --color --watch"
},
"dependencies": {
"@angular/animations": "^9.1.9",
"@angular/common": "^9.1.11",
"@angular/compiler": "^9.1.9",
"@angular/core": "^9.1.9",
"@angular/forms": "^9.1.11",
"@angular/platform-browser": "^9.1.9",
"@angular/platform-browser-dynamic": "^9.1.9",
"@angular/animations": "^11.1.1",
"@angular/common": "^11.1.1",
"@angular/compiler": "^11.1.1",
"@angular/core": "^11.1.1",
"@angular/forms": "^11.1.1",
"@angular/platform-browser": "^11.1.1",
"@angular/platform-browser-dynamic": "^11.1.1",
"@ng-bootstrap/ng-bootstrap": "^6.1.0",
"@terminus-term/node-pty": "0.10.0-beta11",
"@terminus-term/node-pty": "0.10.0-terminus.2",
"electron-config": "2.0.0",
"electron-debug": "^3.0.1",
"electron-is-dev": "1.1.0",
"electron-debug": "^3.2.0",
"electron-is-dev": "1.2.0",
"electron-promise-ipc": "^2.2.4",
"fontmanager-redux": "1.0.0",
"glasstron": "0.0.5",
"js-yaml": "3.14.0",
"glasstron": "0.0.6",
"js-yaml": "4.0.0",
"keytar": "^7.2.0",
"mz": "^2.7.0",
"native-process-working-directory": "^1.0.2",
"ngx-toastr": "^12.0.1",
"npm": "6",
"path": "0.12.7",

View File

@@ -0,0 +1,12 @@
diff --git a/node_modules/node-abi/abi_registry.json b/node_modules/node-abi/abi_registry.json
index bc1436d..630c1b7 100644
--- a/node_modules/node-abi/abi_registry.json
+++ b/node_modules/node-abi/abi_registry.json
@@ -94,6 +94,6 @@
"future": true,
"lts": false,
"runtime": "electron",
- "target": "12.0.0-nightly.20201013"
+ "target": "12.0.0-beta.16"
}
]

View File

@@ -95,3 +95,7 @@ input[type=range] {
&::-moz-range-track { @include track(); }
&::-ms-track { @include track(); }
}
a[ngbdropdownitem] {
cursor: pointer;
}

View File

@@ -2,40 +2,54 @@
# yarn lockfile v1
"@angular/animations@^9.1.9":
version "9.1.13"
resolved "https://registry.npmjs.org/@angular/animations/-/animations-9.1.13.tgz"
integrity sha512-ane1eeQmsP7fcAiLgRhle7YIDgE88WDMMvzqJYhSxwLzXNF/hwqNeskmNcjo8bLt9h/yTIjrCQbycLCHJfU8UQ==
"@angular/animations@^11.1.1":
version "11.1.1"
resolved "https://registry.yarnpkg.com/@angular/animations/-/animations-11.1.1.tgz#3ae6754e70ecf858322a432f6484a1bab1013315"
integrity sha512-okideoWvlTz6VqHXDWKlMGj1beWxq/ag4n/+7y8IENQFgrKQWu4m52Igr5sJUfT1W8rXqLPaSGEpp9h+1SCDcQ==
dependencies:
tslib "^2.0.0"
"@angular/common@^9.1.11":
version "9.1.13"
resolved "https://registry.npmjs.org/@angular/common/-/common-9.1.13.tgz"
integrity sha512-QACUhJWlly/nfHUmjopVS1p6ayxxa/NqjyftdCeBJaoyM2YohqWixP/n/keu1K/srJ96aFpUNsZQgmgoRv5SOQ==
"@angular/common@^11.1.1":
version "11.1.1"
resolved "https://registry.yarnpkg.com/@angular/common/-/common-11.1.1.tgz#fcf16d3d35cdc64c40458a51f879ab61ed2ecdf2"
integrity sha512-YHAmbjmwqIv43CdzRJkXJiT7p6Xm6DpsGKLuCGPoomUk7Nf5U5LsSZm/uvyTu0O+OQp2RUFUdGqW5DzSZZnKtQ==
dependencies:
tslib "^2.0.0"
"@angular/compiler@^9.1.9":
version "9.1.13"
resolved "https://registry.npmjs.org/@angular/compiler/-/compiler-9.1.13.tgz"
integrity sha512-9MLB1Xx7odKuxDoybVwiOB1ZEUZpL8FurYm4RVuW39ntsUt0IMC9Hb8UagZLTAWhaWSHydkD/KBQVVobGqd0lA==
"@angular/compiler@^11.1.1":
version "11.1.1"
resolved "https://registry.yarnpkg.com/@angular/compiler/-/compiler-11.1.1.tgz#cafe43b52fb69f0b9493e597baec14fcffd13d7d"
integrity sha512-kybGddMBL6E2BFBOHIX39VsKVxH3yD7NA1g2mQUE9KIqLAavH0KLBr8B03R9MKb6+BElGpk/5yCyCkzkwQES7w==
dependencies:
tslib "^2.0.0"
"@angular/core@^9.1.9":
version "9.1.13"
resolved "https://registry.npmjs.org/@angular/core/-/core-9.1.13.tgz"
integrity sha512-mBm24Q9GjkAsxMAzqQ86U1078+yTEpr0+syMEruUtJ0HUH6Fzn3J+6xTLb+BVcGb9RkCkFaV9T5mcn6ZM0f++g==
"@angular/core@^11.1.1":
version "11.1.1"
resolved "https://registry.yarnpkg.com/@angular/core/-/core-11.1.1.tgz#62bf9ad93d5d88afacce3ea5b03803ec5790d20b"
integrity sha512-yBBLekXeDviZ+KW3DmGeOK0CK/yQ9gCy2uHY47KUDI4UTRRLz0NI5nS9NdKwk5bpCPId6ZPNsJtHPBFXRhAnNA==
dependencies:
tslib "^2.0.0"
"@angular/forms@^9.1.11":
version "9.1.13"
resolved "https://registry.npmjs.org/@angular/forms/-/forms-9.1.13.tgz"
integrity sha512-soGVZmPq2bzkxvtTyeJB8p3ejzm4xxt+43hJw6Ag8NxpwUFPVa30oJge3JV+u8Y4yBtl5SbOZ4bBX3EkMxLcGQ==
"@angular/forms@^11.1.1":
version "11.1.1"
resolved "https://registry.yarnpkg.com/@angular/forms/-/forms-11.1.1.tgz#c8c468aba528f1f2764cf0bc7d9ab36636795473"
integrity sha512-MVysENcKonjMowdd2SxXQGcvNVpMTWVhwr5IZ2FBZKW/FNnSBq0R3nsr25zU0h8QWQHkROPtFF0+AEaENh/yAg==
dependencies:
tslib "^2.0.0"
"@angular/platform-browser-dynamic@^9.1.9":
version "9.1.13"
resolved "https://registry.npmjs.org/@angular/platform-browser-dynamic/-/platform-browser-dynamic-9.1.13.tgz"
integrity sha512-jCeHyAZ4Nap1/FOqAlKEg9UxQaSkHrxnQr6hYtWwC4ZDVUn3zLWQf6J+mbeYNOXN5yQxEiIqqhORYeOCLLqf1w==
"@angular/platform-browser-dynamic@^11.1.1":
version "11.1.1"
resolved "https://registry.yarnpkg.com/@angular/platform-browser-dynamic/-/platform-browser-dynamic-11.1.1.tgz#2e05d719a1d134a9a22fb4e4a40234ac49ba122a"
integrity sha512-fI44VfQvwzNeZdSMGZEYqYZ6Q4Y1fSbyqh2hzbhVW4/Tq6s4qKdKn3TfAD6iK6te5ewZwbccfr4Y0zMbcwTSRA==
dependencies:
tslib "^2.0.0"
"@angular/platform-browser@^9.1.9":
version "9.1.13"
resolved "https://registry.npmjs.org/@angular/platform-browser/-/platform-browser-9.1.13.tgz"
integrity sha512-F3iTz1zNbtrs7KFKUxbj8qmTsd/fiuTNcpBExjE5TtatRiE6J8vNvN1+Z/1FgPe0UXBSdTzSwZ8/RxWKw20RMw==
"@angular/platform-browser@^11.1.1":
version "11.1.1"
resolved "https://registry.yarnpkg.com/@angular/platform-browser/-/platform-browser-11.1.1.tgz#d9940e92664b06a3c6a10221f1b9438ba94b9b5f"
integrity sha512-z3OmXK9viTxNp2KpGdCiFkFCI69WVYyuMQerCwjuD2oymRpltc64uujIq3+j32UJ+sTGrjMSmgMo7ReAYMp7sg==
dependencies:
tslib "^2.0.0"
"@iarna/cli@^1.2.0":
version "1.2.0"
@@ -117,12 +131,12 @@
dependencies:
debug "^4.1.1"
"@terminus-term/node-pty@0.10.0-beta11":
version "0.10.0-beta11"
resolved "https://registry.yarnpkg.com/@terminus-term/node-pty/-/node-pty-0.10.0-beta11.tgz#9e83041bc0644f17a4329c41a13d09575653c544"
integrity sha512-ZrplD84UNV8qpCNpsG8DAo8fmoRP1Ynb9QsApIleCJjbeNvUP2ZAeR6wo0aV9B7Zqjvq5O4hoUSayIDGtORH+A==
"@terminus-term/node-pty@0.10.0-terminus.2":
version "0.10.0-terminus.2"
resolved "https://registry.yarnpkg.com/@terminus-term/node-pty/-/node-pty-0.10.0-terminus.2.tgz#028c7762d13150984bc800b8cd954ceb7dbcac68"
integrity sha512-vcscP3jldTMZeHv0XVxQjwEtnh0usUQgUWvsXtPRMy2rMjijwC1+8xFp/FKPpLpWYNTN8WWmRjSdiw+qGGU4CQ==
dependencies:
node-addon-api "^3.0.2"
nan "^2.14.0"
"@types/mz@0.0.32":
version "0.0.32"
@@ -259,12 +273,10 @@ are-we-there-yet@~1.1.2:
delegates "^1.0.0"
readable-stream "^2.0.6"
argparse@^1.0.7:
version "1.0.10"
resolved "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz"
integrity sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==
dependencies:
sprintf-js "~1.0.2"
argparse@^2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38"
integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==
asap@^2.0.0:
version "2.0.6"
@@ -837,10 +849,10 @@ electron-config@2.0.0:
dependencies:
conf "^1.0.0"
electron-debug@^3.0.1:
version "3.1.0"
resolved "https://registry.npmjs.org/electron-debug/-/electron-debug-3.1.0.tgz"
integrity sha512-SWEqLj4MgfV3tGuO5eBLQ5/Nr6M+KPxsnE0bUJZvQebGJus6RAcdmvd7L+l0Ji31h2mmrN23l2tHFtCa2FvurA==
electron-debug@^3.2.0:
version "3.2.0"
resolved "https://registry.yarnpkg.com/electron-debug/-/electron-debug-3.2.0.tgz#46a15b555c3b11872218c65ea01d058aa0814920"
integrity sha512-7xZh+LfUvJ52M9rn6N+tPuDw6oRAjxUj9SoxAZfJ0hVCXhZCsdkrSt7TgXOiWiEOBgEV8qwUIO/ScxllsPS7ow==
dependencies:
electron-is-dev "^1.1.0"
electron-localshortcut "^3.1.0"
@@ -850,7 +862,12 @@ electron-is-accelerator@^0.1.0:
resolved "https://registry.npmjs.org/electron-is-accelerator/-/electron-is-accelerator-0.1.2.tgz"
integrity sha1-UJ5RDCala1Xhf4Y6SwThEYRqsns=
electron-is-dev@1.1.0, electron-is-dev@^1.1.0:
electron-is-dev@1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/electron-is-dev/-/electron-is-dev-1.2.0.tgz#2e5cea0a1b3ccf1c86f577cee77363ef55deb05e"
integrity sha512-R1oD5gMBPS7PVU8gJwH6CtT0e6VSoD0+SzSnYpNm+dBkcijgA+K7VAMHDfnRq/lkKPZArpzplTW6jfiMYosdzw==
electron-is-dev@^1.1.0:
version "1.1.0"
resolved "https://registry.npmjs.org/electron-is-dev/-/electron-is-dev-1.1.0.tgz"
integrity sha512-Z1qA/1oHNowGtSBIcWk0pcLEqYT/j+13xUw/MYOrBUOL4X7VN0i0KCTf5SqyvMPmW5pSPKbo28wkxMxzZ20YnQ==
@@ -972,11 +989,6 @@ escape-string-regexp@^1.0.5:
resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4"
integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=
esprima@^4.0.0:
version "4.0.1"
resolved "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz"
integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==
execa@^0.7.0:
version "0.7.0"
resolved "https://registry.yarnpkg.com/execa/-/execa-0.7.0.tgz#944becd34cc41ee32a63a9faf27ad5a65fc59777"
@@ -1217,10 +1229,10 @@ github-from-package@0.0.0:
resolved "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz"
integrity sha1-l/tdlr/eiXMxPyDoKI75oWf6ZM4=
glasstron@0.0.5:
version "0.0.5"
resolved "https://registry.yarnpkg.com/glasstron/-/glasstron-0.0.5.tgz#41ed8109d1d9980a7112ccc3bd195b1aa17088bd"
integrity sha512-1eX2wcW6AxO//gE2eE55M2JkwreHLZgYSmDb0zh//Iw8OgZbf+DTAPfGVUmMQQvGqVjNdao+epu9NISTZAa23A==
glasstron@0.0.6:
version "0.0.6"
resolved "https://registry.yarnpkg.com/glasstron/-/glasstron-0.0.6.tgz#1438899cd49a1cda1999290be2165310b759fd62"
integrity sha512-WBE1zH3ZcYhLlfKATfKzuN05Anno2WYlVfImWteU5RM+gqdFLHGIxxM3VR16JvFF5oIYah01MBGQ2+3xTq44iQ==
dependencies:
node-addon-api "^3.0.0"
x11 "^2.3.0"
@@ -1405,7 +1417,7 @@ inherits@2.0.3:
resolved "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz"
integrity sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=
ini@^1.3.4, ini@^1.3.5, ini@~1.3.0:
ini@^1.3.4, ini@^1.3.5, ini@^1.3.8, ini@~1.3.0:
version "1.3.8"
resolved "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz"
integrity sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==
@@ -1581,13 +1593,12 @@ isstream@~0.1.2:
resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz"
integrity sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=
js-yaml@3.14.0:
version "3.14.0"
resolved "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.0.tgz"
integrity sha512-/4IbIeHcD9VMHFqDR/gQ7EdZdLimOvW2DdcxFjdyyZ9NsbS+ccrXqVWDtab/lRl5AlUqmpBx8EhPaWR+OtY17A==
js-yaml@4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.0.0.tgz#f426bc0ff4b4051926cd588c71113183409a121f"
integrity sha512-pqon0s+4ScYUvX30wxQi3PogGFAlUyH0awepWvwkj4jD4v+ova3RiYw8bmA6x2rDrEaj8i/oWKoRxpVNW+Re8Q==
dependencies:
argparse "^1.0.7"
esprima "^4.0.0"
argparse "^2.0.1"
jsbn@~0.1.0:
version "0.1.1"
@@ -2073,7 +2084,7 @@ mz@^2.7.0:
object-assign "^4.0.1"
thenify-all "^1.0.0"
nan@^2.13.2, nan@^2.14.2:
nan@^2.13.2, nan@^2.14.0, nan@^2.14.2:
version "2.14.2"
resolved "https://registry.yarnpkg.com/nan/-/nan-2.14.2.tgz#f5376400695168f4cc694ac9393d0c9585eeea19"
integrity sha512-M2ufzIiINKCuDfBSAUr1vWQ+vuVcA9kqx8JJUsbQi6yf1uGRyb7HfpdfUr5qLXf3B/t8dPvcjhKMmlfnP47EzQ==
@@ -2083,6 +2094,13 @@ napi-build-utils@^1.0.1:
resolved "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-1.0.2.tgz"
integrity sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==
native-process-working-directory@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/native-process-working-directory/-/native-process-working-directory-1.0.2.tgz#7843e2fa1490f53cf8d2c7d1913de8b275e8b89a"
integrity sha512-3a67QQV8r3YMUTSOgvtMOCjPDgCpb/8xjv93L8Cqb8bv3hOKsWis4/+8HCu3bgj8ADQV75SCYFSsAGM5G0cXmQ==
dependencies:
node-addon-api "^3.1.0"
ngx-toastr@^12.0.1:
version "12.1.0"
resolved "https://registry.npmjs.org/ngx-toastr/-/ngx-toastr-12.1.0.tgz"
@@ -2102,7 +2120,7 @@ node-addon-api@3.0.0:
resolved "https://registry.npmjs.org/node-addon-api/-/node-addon-api-3.0.0.tgz"
integrity sha512-sSHCgWfJ+Lui/u+0msF3oyCgvdkhxDbkCS6Q8uiJquzOimkJBvX6hl5aSSA7DR1XbMpdM8r7phjcF63sF4rkKg==
node-addon-api@^3.0.0, node-addon-api@^3.0.2:
node-addon-api@^3.0.0, node-addon-api@^3.0.2, node-addon-api@^3.1.0:
version "3.1.0"
resolved "https://registry.npmjs.org/node-addon-api/-/node-addon-api-3.1.0.tgz"
integrity sha512-flmrDNB06LIl5lywUz7YlNGZH/5p0M7W28k8hzd9Lshtdh1wshD2Y+U4h9LD6KObOy1f+fEVdgprPrEymjM5uw==
@@ -2270,9 +2288,9 @@ npm-user-validate@^1.0.1:
integrity sha512-uQwcd/tY+h1jnEaze6cdX/LrhWhoBxfSknxentoqmIuStxUExxjWd3ULMLFPiFUrZKbOVMowH6Jq2FRWfmhcEw==
npm@6:
version "6.14.10"
resolved "https://registry.yarnpkg.com/npm/-/npm-6.14.10.tgz#f45c8e4244294ba793770f2ab0e9ce2d0b93fd29"
integrity sha512-FT23Qy/JMA+qxEYReMOr1MY7642fKn8Onn+72LASPi872Owvmw0svm+/DXTHOC3yO9CheEO+EslyXEpdBdRtIA==
version "6.14.11"
resolved "https://registry.yarnpkg.com/npm/-/npm-6.14.11.tgz#e0b5598d7b9a42d275e61d8bd28cd7eee0074a3b"
integrity sha512-1Zh7LjuIoEhIyjkBflSSGzfjuPQwDlghNloppjruOH5bmj9midT9qcNT0tRUZRR04shU9ekrxNy9+UTBrqeBpQ==
dependencies:
JSONStream "^1.3.5"
abbrev "~1.1.1"
@@ -2309,7 +2327,7 @@ npm@6:
infer-owner "^1.0.4"
inflight "~1.0.6"
inherits "^2.0.4"
ini "^1.3.5"
ini "^1.3.8"
init-package-json "^1.10.3"
is-cidr "^3.0.0"
json-parse-better-errors "^1.0.2"
@@ -3025,16 +3043,16 @@ rxjs@^6.5.5:
dependencies:
tslib "^1.9.0"
safe-buffer@^5.0.1, safe-buffer@^5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1:
version "5.1.2"
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz"
integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==
safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.2.0:
safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@^5.2.0:
version "5.2.1"
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6"
integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==
safe-buffer@~5.1.0, safe-buffer@~5.1.1:
version "5.1.2"
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz"
integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==
"safer-buffer@>= 2.1.2 < 3.0.0", safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@~2.1.0:
version "2.1.2"
resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz"
@@ -3201,11 +3219,6 @@ split-on-first@^1.0.0:
resolved "https://registry.yarnpkg.com/split-on-first/-/split-on-first-1.1.0.tgz#f610afeee3b12bce1d0c30425e76398b78249a5f"
integrity sha512-43ZssAJaMusuKWL8sKUBQXHWOpq8d6CfN/u1p4gUzfJkM05C8rxTmYrkIPTXapZpORA6LkkzcUulJ8FqA7Uudw==
sprintf-js@~1.0.2:
version "1.0.3"
resolved "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz"
integrity sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=
sshpk@^1.7.0:
version "1.16.1"
resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.16.1.tgz"

View File

@@ -8,8 +8,9 @@ afterAllArtifactBuild: "./build/mac/afterBuildHook.js"
files:
- '**/*'
- dist
- '!lib'
- '!src'
- '!**/node_modules/*/{CHANGELOG.md,README.md,README,readme.md,readme}'
- '!**/node_modules/*/{CHANGELOG.md,README.md,README,readme.md,readme,node.lib}'
- '!**/node_modules/*/{test,__tests__,tests,powered-test,example,examples,docs}'
- '!**/node_modules/@angular/common/locales'
- '!**/node_modules/@angular/compiler/src'

View File

@@ -2,32 +2,33 @@
"devDependencies": {
"@fortawesome/fontawesome-free": "^5.13.0",
"@sentry/cli": "^1.61.0",
"@sentry/electron": "^2.0.4",
"@sentry/electron": "^2.2.0",
"@terminus-term/to-string-loader": "1.1.7-beta.1",
"@types/electron-config": "^3.2.2",
"@types/electron-debug": "^2.1.0",
"@types/fs-extra": "^8.1.1",
"@types/js-yaml": "^3.12.5",
"@types/node": "14.14.14",
"@types/webpack-env": "^1.16.0",
"@typescript-eslint/eslint-plugin": "^4.11.0",
"@typescript-eslint/parser": "^4.11.0",
"@typescript-eslint/eslint-plugin": "^4.14.1",
"@typescript-eslint/parser": "^4.14.1",
"apply-loader": "2.0.0",
"awesome-typescript-loader": "^5.2.1",
"compare-versions": "^3.6.0",
"core-js": "^3.8.1",
"cross-env": "7.0.2",
"css-loader": "3.4.2",
"electron": "^11.1.1",
"core-js": "^3.8.3",
"cross-env": "7.0.3",
"css-loader": "5.0.1",
"electron": "12.0.0-beta.22",
"electron-builder": "22.10.4",
"electron-download": "^4.1.1",
"electron-installer-snap": "^5.1.0",
"electron-notarize": "^1.0.0",
"electron-rebuild": "^2.3.4",
"eslint": "^7.6.0",
"eslint": "^7.18.0",
"eslint-plugin-import": "^2.21.1",
"file-loader": "^5.1.0",
"file-loader": "^6.2.0",
"graceful-fs": "^4.2.4",
"html-loader": "0.5.5",
"html-loader": "1.3.2",
"json-loader": "0.5.7",
"lru-cache": "^6.0.0",
"macos-release": "^2.4.1",
@@ -36,27 +37,27 @@
"node-sass": "^5.0.0",
"npmlog": "4.1.2",
"npx": "^10.2.2",
"pug": "^2.0.4",
"patch-package": "^6.2.2",
"pug": "^3.0.0",
"pug-html-loader": "1.1.5",
"pug-lint": "^2.6.0",
"pug-loader": "^2.4.0",
"pug-static-loader": "2.0.0",
"raw-loader": "4.0.1",
"sass-loader": "^10.1.0",
"raw-loader": "4.0.2",
"sass-loader": "^10.1.1",
"shelljs": "0.8.4",
"source-code-pro": "^2.30.2",
"source-sans-pro": "3.6.0",
"ssh2-streams": "^0.4.10",
"style-loader": "^2.0.0",
"svg-inline-loader": "^0.8.2",
"to-string-loader": "1.1.6",
"tslib": "^2.0.3",
"typedoc": "^0.18.0",
"typescript": "^3.9.7",
"url-loader": "^3.0.0",
"val-loader": "2.1.1",
"webpack": "^5.11.0",
"webpack-cli": "^4.2.0",
"url-loader": "^4.1.1",
"val-loader": "3.0.0",
"webpack": "^5.18.0",
"webpack-cli": "^4.4.0",
"yaml-loader": "0.6.0"
},
"resolutions": {
@@ -74,7 +75,5 @@
"lint": "eslint --ext ts */src */lib",
"postinstall": "node ./scripts/install-deps.js"
},
"repository": "eugeny/terminus",
"author": "Eugene Pankov",
"license": "MIT"
"private": true
}

View File

@@ -0,0 +1,12 @@
diff --git a/node_modules/node-abi/abi_registry.json b/node_modules/node-abi/abi_registry.json
index bc1436d..630c1b7 100644
--- a/node_modules/node-abi/abi_registry.json
+++ b/node_modules/node-abi/abi_registry.json
@@ -94,6 +94,6 @@
"future": true,
"lts": false,
"runtime": "electron",
- "target": "12.0.0-nightly.20201013"
+ "target": "12.0.0-beta.16"
}
]

View File

@@ -1,8 +1,6 @@
#!/usr/bin/env node
const builder = require('electron-builder').build
const vars = require('./vars')
const fs = require('fs')
const signHook = require('../build/mac/afterSignHook')
const isTag = (process.env.GITHUB_REF || '').startsWith('refs/tags/')
@@ -16,6 +14,7 @@ builder({
extraMetadata: {
version: vars.version,
},
npmRebuild: process.env.ARCH !== 'arm64',
},
publish: isTag ? 'always' : 'onTag',
}).catch(e => {

24
scripts/sentry-upload.js Executable file
View File

@@ -0,0 +1,24 @@
#!/usr/bin/env node
const sh = require('shelljs')
const vars = require('./vars')
const sentryCli = process.platform === 'win32' ? 'node_modules\\.bin\\sentry-cli.cmd' : 'sentry-cli'
sh.exec(`${sentryCli} releases new ${vars.version}`)
if (process.platform === 'darwin') {
for (const path of [
'app/node_modules/@serialport/bindings/build/Release/bindings.node',
'app/node_modules/@terminus-term/node-pty/build/Release/pty.node',
'app/node_modules/fontmanager-redux/build/Release/fontmanager.node',
'app/node_modules/macos-native-processlist/build/Release/native.node',
]) {
sh.exec('dsymutil ' + path)
}
}
sh.exec(`${sentryCli} upload-dif app/node_modules`)
sh.exec(`${sentryCli} releases set-commits --auto ${vars.version}`)
for (const p of vars.builtinPlugins) {
sh.exec(`${sentryCli} releases files ${vars.version} upload-sourcemaps ${p}/dist -u ${p}/dist/ -d ${process.platform}-${p}`)
}

View File

@@ -1,14 +1,14 @@
import { Injectable } from '@angular/core'
import { TerminalColorSchemeProvider, TerminalColorScheme } from 'terminus-terminal'
const schemeContents = require.context('../schemes/', true, /.*/)
const schemeContents = require.context('../schemes/', false, /.*/)
@Injectable()
export class ColorSchemes extends TerminalColorSchemeProvider {
async getSchemes (): Promise<TerminalColorScheme[]> {
const schemes: TerminalColorScheme[] = []
schemeContents.keys().forEach(schemeFile => {
schemeContents.keys().filter(x => !x.startsWith('./')).forEach(schemeFile => {
const lines = (schemeContents(schemeFile).default as string).split('\n')
// process #define variables

View File

@@ -26,8 +26,8 @@ $side-tab-width: 200px;
.content {
width: 100vw;
height: 100vh;
flex: auto;
flex: 1 1 0;
min-height: 0;
display: flex;
flex-direction: column-reverse;

View File

@@ -142,6 +142,8 @@ export class AppRootComponent {
this.touchbar.update()
this.hostApp.useBuiltinGraphics()
config.changed$.subscribe(() => this.updateVibrancy())
this.updateVibrancy()

View File

@@ -1,4 +1,4 @@
import { Component, Input, HostListener, ViewChildren, QueryList, ElementRef } from '@angular/core'
import { Component, Input, HostListener, ViewChildren, QueryList, ElementRef } from '@angular/core' // eslint-disable-line @typescript-eslint/no-unused-vars
import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'
import { SelectorOption } from '../api/selector'

View File

@@ -110,7 +110,7 @@ export default class AppModule { // eslint-disable-line @typescript-eslint/no-ex
})
}
static forRoot (): ModuleWithProviders {
static forRoot (): ModuleWithProviders<AppModule> {
return {
ngModule: AppModule,
providers: PROVIDERS,

View File

@@ -49,10 +49,10 @@ export class AppService {
get activeTab (): BaseTabComponent|null { return this._activeTab ?? null }
private lastTabIndex = 0
private _activeTab?: BaseTabComponent
private _activeTab: BaseTabComponent | null = null
private closedTabsStack: RecoveryToken[] = []
private activeTabChange = new Subject<BaseTabComponent>()
private activeTabChange = new Subject<BaseTabComponent|null>()
private tabsChanged = new Subject<void>()
private tabOpened = new Subject<BaseTabComponent>()
private tabClosed = new Subject<BaseTabComponent>()
@@ -60,7 +60,7 @@ export class AppService {
private completionObservers = new Map<BaseTabComponent, CompletionObserver>()
get activeTabChange$ (): Observable<BaseTabComponent> { return this.activeTabChange }
get activeTabChange$ (): Observable<BaseTabComponent|null> { return this.activeTabChange }
get tabOpened$ (): Observable<BaseTabComponent> { return this.tabOpened }
get tabsChanged$ (): Observable<void> { return this.tabsChanged }
get tabClosed$ (): Observable<BaseTabComponent> { return this.tabClosed }
@@ -185,8 +185,8 @@ export class AppService {
return null
}
selectTab (tab: BaseTabComponent): void {
if (this._activeTab === tab) {
selectTab (tab: BaseTabComponent|null): void {
if (tab && this._activeTab === tab) {
this._activeTab.emitFocused()
return
}
@@ -204,7 +204,7 @@ export class AppService {
setImmediate(() => {
this._activeTab?.emitFocused()
})
this.hostApp.setTitle(this._activeTab.title)
this.hostApp.setTitle(this._activeTab?.title)
}
getParentTab (tab: BaseTabComponent): SplitTabComponent|null {

View File

@@ -144,7 +144,7 @@ export class ConfigService {
load (): void {
if (fs.existsSync(this.path)) {
this._store = yaml.safeLoad(fs.readFileSync(this.path, 'utf8'))
this._store = yaml.load(fs.readFileSync(this.path, 'utf8'))
} else {
this._store = {}
}
@@ -154,7 +154,7 @@ 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')
fs.writeFileSync(this.path, yaml.dump(this._store), 'utf8')
this.emitChange()
this.hostApp.broadcastConfigChange(JSON.parse(JSON.stringify(this.store)))
}
@@ -163,14 +163,14 @@ export class ConfigService {
* Reads config YAML as string
*/
readRaw (): string {
return yaml.safeDump(this._store)
return yaml.dump(this._store)
}
/**
* Writes config YAML as string
*/
writeRaw (data: string): void {
this._store = yaml.safeLoad(data)
this._store = yaml.load(data)
this.save()
this.load()
this.emitChange()

View File

@@ -1,5 +1,6 @@
import type { BrowserWindow, TouchBar, MenuItemConstructorOptions } from 'electron'
import * as path from 'path'
import * as fs from 'mz/fs'
import shellEscape from 'shell-escape'
import { Observable, Subject } from 'rxjs'
import { Injectable, NgZone, EventEmitter } from '@angular/core'
@@ -7,6 +8,12 @@ import { ElectronService } from './electron.service'
import { Logger, LogService } from './log.service'
import { isWindowsBuild, WIN_BUILD_FLUENT_BG_SUPPORTED } from '../utils'
/* eslint-disable block-scoped-var */
try {
var wnr = require('windows-native-registry') // eslint-disable-line @typescript-eslint/no-var-requires, no-var
} catch (_) { }
export enum Platform {
Linux = 'Linux',
macOS = 'macOS',
@@ -150,9 +157,10 @@ export class HostAppService {
this.zone.run(() => this.displaysChanged.next())
})
electron.ipcRenderer.on('host:second-instance', (_$event, argv: any, cwd: string) => this.zone.run(() => {
electron.ipcRenderer.on('cli', (_$event, argv: any, cwd: string, secondInstance: boolean) => this.zone.run(async () => {
this.logger.info('Second instance', argv)
const op = argv._[0]
const opAsPath = op ? path.resolve(cwd, op) : null
if (op === 'open') {
this.cliOpenDirectory.next(path.resolve(cwd, argv.directory))
} else if (op === 'run') {
@@ -165,9 +173,13 @@ export class HostAppService {
this.cliPaste.next(text)
} else if (op === 'profile') {
this.cliOpenProfile.next(argv.profileName)
} else if (op === undefined) {
} else if (secondInstance && op === undefined) {
this.newWindow()
} else {
} else if (opAsPath && (await fs.lstat(opAsPath)).isDirectory()) {
this.cliOpenDirectory.next(opAsPath)
}
if (secondInstance) {
this.secondInstance.next()
}
}))
@@ -242,8 +254,8 @@ export class HostAppService {
this.electron.ipcRenderer.send('window-set-vibrancy', enable, type)
}
setTitle (title: string): void {
this.electron.ipcRenderer.send('window-set-title', title)
setTitle (title?: string): void {
this.electron.ipcRenderer.send('window-set-title', title ?? 'Terminus')
}
setTouchBar (touchBar: TouchBar): void {
@@ -277,6 +289,16 @@ export class HostAppService {
this.electron.ipcRenderer.send('app:register-global-hotkey', specs)
}
useBuiltinGraphics (): void {
const keyPath = 'SOFTWARE\\Microsoft\\DirectX\\UserGpuPreferences'
const valueName = this.electron.app.getPath('exe')
if (this.platform === Platform.Windows) {
if (!wnr.getRegistryValue(wnr.HK.CU, keyPath, valueName)) {
wnr.setRegistryValue(wnr.HK.CU, keyPath, valueName, wnr.REG.SZ, 'GpuPreference=1;')
}
}
}
relaunch (): void {
if (this.isPortable) {
this.electron.app.relaunch({ execPath: process.env.PORTABLE_EXECUTABLE_FILE })

View File

@@ -35,6 +35,10 @@ export class UpdaterService {
this.logger.info('No updates')
})
electron.autoUpdater.once('error', err => {
this.logger.error(err)
})
this.downloaded = new Promise<boolean>(resolve => {
electron.autoUpdater.once('update-downloaded', () => resolve(true))
})

View File

@@ -40,8 +40,8 @@ module.exports = {
},
},
{ test: /\.pug$/, use: ['apply-loader', 'pug-loader'] },
{ test: /\.scss$/, use: ['to-string-loader', 'css-loader', 'sass-loader'] },
{ test: /\.css$/, use: ['to-string-loader', 'css-loader'], include: /component\.css/ },
{ test: /\.scss$/, use: ['@terminus-term/to-string-loader', 'css-loader', 'sass-loader'] },
{ test: /\.css$/, use: ['@terminus-term/to-string-loader', 'css-loader'], include: /component\.css/ },
{ test: /\.css$/, use: ['style-loader', 'css-loader'], exclude: /component\.css/ },
{ test: /\.yaml$/, use: ['json-loader', 'yaml-loader'] },
{ test: /\.svg/, use: ['svg-inline-loader'] },

View File

@@ -124,9 +124,9 @@ colorspace@1.1.x:
text-hex "1.0.x"
core-js@^3.1.2:
version "3.7.0"
resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.7.0.tgz#b0a761a02488577afbf97179e4681bf49568520f"
integrity sha512-NwS7fI5M5B85EwpWuIwJN4i/fbisQUwLwiSNUWeXlkAZ0sbBjLEvLvFLf1uzAUV66PcEPt4xCGCmOZSxVf3xzA==
version "3.8.2"
resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.8.2.tgz#0a1fd6709246da9ca8eff5bb0cbd15fba9ac7044"
integrity sha512-FfApuSRgrR6G5s58casCBd9M2k+4ikuu4wbW6pJyYU7bd9zvFc9qf7vr5xmrZOhT9nn+8uwlH1oRR9jTnFoA3A==
core-util-is@~1.0.0:
version "1.0.2"

View File

@@ -40,7 +40,7 @@ module.exports = {
},
},
{ test: /\.pug$/, use: ['apply-loader', 'pug-loader'] },
{ test: /\.scss$/, use: ['to-string-loader', 'css-loader', 'sass-loader'] },
{ test: /\.scss$/, use: ['@terminus-term/to-string-loader', 'css-loader', 'sass-loader'] },
],
},
externals: [

View File

@@ -20,6 +20,7 @@
"@types/node": "14.14.14",
"@types/ssh2": "^0.5.35",
"ansi-colors": "^4.1.1",
"buffer-replace": "^1.0.0",
"cli-spinner": "^0.2.10"
},
"peerDependencies": {

View File

@@ -1,7 +1,12 @@
import stripAnsi from 'strip-ansi'
import bufferReplace from 'buffer-replace'
import { BaseSession } from 'terminus-terminal'
import { SerialPort } from 'serialport'
import { Logger } from 'terminus-core'
import { Subject, Observable } from 'rxjs'
import { Subject, Observable, interval } from 'rxjs'
import { debounce } from 'rxjs/operators'
import { ReadLine, createInterface as createReadline, clearLine } from 'readline'
import { PassThrough, Readable, Writable } from 'stream'
export interface LoginScript {
expect: string
@@ -23,10 +28,13 @@ export interface SerialConnection {
xany: boolean
scripts?: LoginScript[]
color?: string
inputMode?: InputMode
inputNewlines?: NewlineMode
outputNewlines?: NewlineMode
}
export const BAUD_RATES = [
110, 150, 300, 1200, 2400, 4800, 9600, 19200, 38400, 57600, 115200, 230400, 460800, 921600,
110, 150, 300, 1200, 2400, 4800, 9600, 19200, 38400, 57600, 115200, 230400, 460800, 921600, 1500000,
]
export interface SerialPortInfo {
@@ -34,6 +42,9 @@ export interface SerialPortInfo {
description?: string
}
export type InputMode = null | 'readline' // eslint-disable-line @typescript-eslint/no-type-alias
export type NewlineMode = null | 'cr' | 'lf' | 'crlf' // eslint-disable-line @typescript-eslint/no-type-alias
export class SerialSession extends BaseSession {
scripts?: LoginScript[]
serial: SerialPort
@@ -41,58 +52,38 @@ export class SerialSession extends BaseSession {
get serviceMessage$ (): Observable<string> { return this.serviceMessage }
private serviceMessage = new Subject<string>()
private inputReadline: ReadLine
private inputPromptVisible = true
private inputReadlineInStream: Readable & Writable
private inputReadlineOutStream: Readable & Writable
constructor (public connection: SerialConnection) {
super()
this.scripts = connection.scripts ?? []
this.inputReadlineInStream = new PassThrough()
this.inputReadlineOutStream = new PassThrough()
this.inputReadline = createReadline({
input: this.inputReadlineInStream,
output: this.inputReadlineOutStream,
terminal: true,
} as any)
this.inputReadlineOutStream.on('data', data => {
if (this.connection.inputMode === 'readline') {
this.emitOutput(data)
}
})
this.inputReadline.on('line', line => {
this.onInput(new Buffer(line + '\n'))
})
this.output$.pipe(debounce(() => interval(500))).subscribe(() => this.onOutputSettled())
}
async start (): Promise<void> {
this.open = true
this.serial.on('data', data => {
const dataString = data.toString()
this.emitOutput(data)
if (this.scripts) {
let found = false
for (const script of this.scripts) {
let match = false
let cmd = ''
if (script.isRegex) {
const re = new RegExp(script.expect, 'g')
if (dataString.match(re)) {
cmd = dataString.replace(re, script.send)
match = true
found = true
}
} else {
if (dataString.includes(script.expect)) {
cmd = script.send
match = true
found = true
}
}
if (match) {
this.logger.info('Executing script: "' + cmd + '"')
this.serial.write(cmd + '\n')
this.scripts = this.scripts.filter(x => x !== script)
} else {
if (script.optional) {
this.logger.debug('Skip optional script: ' + script.expect)
found = true
this.scripts = this.scripts.filter(x => x !== script)
} else {
break
}
}
}
if (found) {
this.executeUnconditionalScripts()
}
}
this.serial.on('readable', () => {
this.onOutput(this.serial.read())
})
this.serial.on('end', () => {
@@ -106,23 +97,33 @@ export class SerialSession extends BaseSession {
}
write (data: Buffer): void {
if (this.serial) {
this.serial.write(data.toString())
if (this.connection.inputMode === 'readline') {
this.inputReadlineInStream.write(data)
} else {
this.onInput(data)
}
}
async destroy (): Promise<void> {
this.serviceMessage.complete()
this.inputReadline.close()
await super.destroy()
}
// eslint-disable-next-line @typescript-eslint/no-empty-function, @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-empty-function
resize (_, __) { }
resize (_, __) {
this.inputReadlineOutStream.emit('resize')
}
kill (_?: string): void {
this.serial.close()
}
emitServiceMessage (msg: string): void {
this.serviceMessage.next(msg)
this.logger.info(stripAnsi(msg))
}
async getChildProcesses (): Promise<any[]> {
return []
}
@@ -131,10 +132,102 @@ export class SerialSession extends BaseSession {
this.kill('TERM')
}
supportsWorkingDirectory (): boolean {
return false
}
async getWorkingDirectory (): Promise<string|null> {
return null
}
private replaceNewlines (data: Buffer, mode?: NewlineMode): Buffer {
if (!mode) {
return data
}
data = bufferReplace(data, '\r\n', '\n')
data = bufferReplace(data, '\r', '\n')
const replacement = {
strip: '',
cr: '\r',
lf: '\n',
crlf: '\r\n',
}[mode]
return bufferReplace(data, '\n', replacement)
}
private onInput (data: Buffer) {
data = this.replaceNewlines(data, this.connection.inputNewlines)
if (this.serial) {
this.serial.write(data.toString())
}
}
private onOutputSettled () {
if (this.connection.inputMode === 'readline' && !this.inputPromptVisible) {
this.resetInputPrompt()
}
}
private resetInputPrompt () {
this.emitOutput(new Buffer('\r\n'))
this.inputReadline.prompt(true)
this.inputPromptVisible = true
}
private onOutput (data: Buffer) {
const dataString = data.toString()
if (this.connection.inputMode === 'readline') {
if (this.inputPromptVisible) {
clearLine(this.inputReadlineOutStream, 0)
this.inputPromptVisible = false
}
}
data = this.replaceNewlines(data, this.connection.outputNewlines)
this.emitOutput(data)
if (this.scripts) {
let found = false
for (const script of this.scripts) {
let match = false
let cmd = ''
if (script.isRegex) {
const re = new RegExp(script.expect, 'g')
if (re.test(dataString)) {
cmd = dataString.replace(re, script.send)
match = true
found = true
}
} else {
if (dataString.includes(script.expect)) {
cmd = script.send
match = true
found = true
}
}
if (match) {
this.logger.info('Executing script: "' + cmd + '"')
this.serial.write(cmd + '\n')
this.scripts = this.scripts.filter(x => x !== script)
} else {
if (script.optional) {
this.logger.debug('Skip optional script: ' + script.expect)
found = true
this.scripts = this.scripts.filter(x => x !== script)
} else {
break
}
}
}
if (found) {
this.executeUnconditionalScripts()
}
}
}
private executeUnconditionalScripts () {
if (this.scripts) {
for (const script of this.scripts) {

View File

@@ -11,23 +11,86 @@
[(ngModel)]='connection.name',
)
.form-group
label Path
input.form-control(
type='text',
[(ngModel)]='connection.port',
[ngbTypeahead]='portsAutocomplete',
[resultFormatter]='portsFormatter',
)
.row
.col-6
.form-group
label Path
input.form-control(
type='text',
[(ngModel)]='connection.port',
[ngbTypeahead]='portsAutocomplete',
[resultFormatter]='portsFormatter',
)
.form-group
label Baud Rate
select.form-control(
[(ngModel)]='connection.baudrate',
)
option([value]='x', *ngFor='let x of baudRates') {{x}}
.col-6
.form-group
label Baud Rate
select.form-control(
[(ngModel)]='connection.baudrate',
)
option([value]='x', *ngFor='let x of baudRates') {{x}}
ngb-tab(id='advanced')
.row
.col-6
.form-line
.header
.title Input mode
.d-flex(ngbDropdown)
button.btn.btn-secondary.btn-tab-bar(
ngbDropdownToggle,
) {{getInputModeName(connection.inputMode)}}
div(ngbDropdownMenu)
a.d-flex.flex-column(
*ngFor='let mode of inputModes',
(click)='connection.inputMode = mode.key',
ngbDropdownItem
)
div {{mode.name}}
.text-muted {{mode.description}}
.col-6
.form-line
.header
.title Input newlines
select.form-control(
[(ngModel)]='connection.inputNewlines',
)
option([ngValue]='mode.key', *ngFor='let mode of newlineModes') {{mode.name}}
.row
.col-6
//- .form-line
.header
.title Output mode
.d-flex(ngbDropdown)
button.btn.btn-secondary.btn-tab-bar(
ngbDropdownToggle,
) {{getInputModeName(connection.inputMode)}}
div(ngbDropdownMenu)
a.d-flex.flex-column(
*ngFor='let mode of inputModes',
(click)='connection.inputMode = mode.key',
ngbDropdownItem
)
div {{mode.name}}
.text-muted {{mode.description}}
.col-6
.form-line
.header
.title Output newlines
select.form-control(
[(ngModel)]='connection.outputNewlines',
)
option([ngValue]='mode.key', *ngFor='let mode of newlineModes') {{mode.name}}
ngb-tab(id='advanced')
ng-template(ngbTabTitle) Advanced
ng-template(ngbTabContent)
.form-line

View File

@@ -15,6 +15,17 @@ export class EditConnectionModalComponent {
connection: SerialConnection
foundPorts: SerialPortInfo[]
baudRates = BAUD_RATES
inputModes = [
{ key: null, name: 'Normal', description: 'Input is sent as you type' },
{ key: 'readline', name: 'Line by line', description: 'Line editor, input is sent after you press Enter' },
]
newlineModes = [
{ key: null, name: 'Keep' },
{ key: 'strip', name: 'Strip' },
{ key: 'cr', name: 'Force CR' },
{ key: 'lf', name: 'Force LF' },
{ key: 'crlf', name: 'Force CRLF' },
]
constructor (
private modalInstance: NgbActiveModal,
@@ -24,6 +35,10 @@ export class EditConnectionModalComponent {
) {
}
getInputModeName (key) {
return this.inputModes.find(x => x.key === key)?.name
}
portsAutocomplete = text$ => text$.pipe(map(() => {
return this.foundPorts.map(x => x.name)
}))

View File

@@ -34,6 +34,9 @@ export class SerialSettingsTabComponent {
xany: false,
xoff: false,
xon: false,
inputMode: null,
inputNewlines: null,
outputNewlines: null,
}
const modal = this.ngbModal.open(EditConnectionModalComponent)

View File

@@ -1,16 +1,16 @@
.tab-toolbar
.btn.btn-outline-secondary.reveal-button
i.fas.fa-ellipsis-h
.toolbar(*ngIf='session', [class.show]='!session.open')
i.fas.fa-circle.text-success.mr-2(*ngIf='session.open')
i.fas.fa-circle.text-danger.mr-2(*ngIf='!session.open')
.toolbar([class.show]='!session || !session.open')
i.fas.fa-circle.text-success.mr-2(*ngIf='session && session.open')
i.fas.fa-circle.text-danger.mr-2(*ngIf='!session || !session.open')
strong(*ngIf='session') {{session.connection.port}} ({{session.connection.baudrate}})
.mr-auto
button.btn.btn-secondary.mr-3((click)='changeBaudRate()', *ngIf='session.open')
button.btn.btn-secondary.mr-3((click)='changeBaudRate()', *ngIf='session && session.open')
span Change baud rate
button.btn.btn-info((click)='reconnect()', *ngIf='!session.open')
button.btn.btn-info((click)='reconnect()', *ngIf='!session || !session.open')
i.fas.fa-reload
span Reconnect

View File

@@ -11,14 +11,15 @@ import { Subscription } from 'rxjs'
/** @hidden */
@Component({
selector: 'serial-tab',
template: BaseTerminalTabComponent.template + (require('./serialTab.component.pug') as string),
template: `${BaseTerminalTabComponent.template} ${require('./serialTab.component.pug')}`,
styles: [require('./serialTab.component.scss'), ...BaseTerminalTabComponent.styles],
animations: BaseTerminalTabComponent.animations,
})
export class SerialTabComponent extends BaseTerminalTabComponent {
connection?: SerialConnection
session?: SerialSession
session: SerialSession|null = null
serialPort: any
private serialService: SerialService
private homeEndSubscription: Subscription
// eslint-disable-next-line @typescript-eslint/no-useless-constructor
@@ -26,6 +27,7 @@ export class SerialTabComponent extends BaseTerminalTabComponent {
injector: Injector,
) {
super(injector)
this.serialService = injector.get(SerialService)
}
ngOnInit () {
@@ -62,12 +64,8 @@ export class SerialTabComponent extends BaseTerminalTabComponent {
return
}
this.session = this.injector.get(SerialService).createSession(this.connection)
this.session.serviceMessage$.subscribe(msg => {
this.write(`\r\n${colors.black.bgWhite(' serial ')} ${msg}\r\n`)
this.session?.resize(this.size.columns, this.size.rows)
})
this.attachSessionHandlers()
const session = this.serialService.createSession(this.connection)
this.setSession(session)
this.write(`Connecting to `)
const spinner = new Spinner({
@@ -80,15 +78,32 @@ export class SerialTabComponent extends BaseTerminalTabComponent {
spinner.start()
try {
this.serialPort = await this.injector.get(SerialService).connectSession(this.session)
this.serialPort = await this.serialService.connectSession(this.session!)
spinner.stop(true)
session.emitServiceMessage('Port opened')
} catch (e) {
spinner.stop(true)
this.write(colors.black.bgRed(' X ') + ' ' + colors.red(e.message) + '\r\n')
return
}
await this.session.start()
this.session.resize(this.size.columns, this.size.rows)
await this.session!.start()
this.session!.resize(this.size.columns, this.size.rows)
}
protected attachSessionHandlers () {
this.attachSessionHandler(this.session!.serviceMessage$.subscribe(msg => {
this.write(`\r\n${colors.black.bgWhite(' Serial ')} ${msg}\r\n`)
this.session?.resize(this.size.columns, this.size.rows)
}))
this.attachSessionHandler(this.session!.destroyed$.subscribe(() => {
this.write('Press any key to reconnect\r\n')
this.input$.pipe(first()).subscribe(() => {
if (!this.session?.open) {
this.reconnect()
}
})
}))
super.attachSessionHandlers()
}
async getRecoveryToken (): Promise<any> {
@@ -99,8 +114,10 @@ export class SerialTabComponent extends BaseTerminalTabComponent {
}
}
reconnect () {
this.initializeSession()
async reconnect (): Promise<void> {
this.session?.destroy()
await this.initializeSession()
this.session?.releaseInitialDataBuffer()
}
async changeBaudRate () {

View File

@@ -30,10 +30,17 @@ export class SerialService {
}
async connectSession (session: SerialSession): Promise<SerialPort> {
const serial = new SerialPort(session.connection.port, { autoOpen: false, baudRate: session.connection.baudrate,
dataBits: session.connection.databits, stopBits: session.connection.stopbits, parity: session.connection.parity,
rtscts: session.connection.rtscts, xon: session.connection.xon, xoff: session.connection.xoff,
xany: session.connection.xany })
const serial = new SerialPort(session.connection.port, {
autoOpen: false,
baudRate: session.connection.baudrate,
dataBits: session.connection.databits,
stopBits: session.connection.stopbits,
parity: session.connection.parity,
rtscts: session.connection.rtscts,
xon: session.connection.xon,
xoff: session.connection.xoff,
xany: session.connection.xany,
})
session.serial = serial
let connected = false
await new Promise(async (resolve, reject) => {
@@ -50,6 +57,10 @@ export class SerialService {
}
})
})
serial.on('close', () => {
session.emitServiceMessage('Port closed')
session.destroy()
})
try {
serial.open()
@@ -103,7 +114,7 @@ export class SerialService {
options.push({
name: 'Manage connections',
icon: 'cog',
callback: () => this.app.openNewTab(SettingsTabComponent, { activeTab: 'serial' }),
callback: () => this.app.openNewTabRaw(SettingsTabComponent, { activeTab: 'serial' }),
})
options.push({

View File

@@ -40,7 +40,7 @@ module.exports = {
},
},
{ test: /\.pug$/, use: ['apply-loader', 'pug-loader'] },
{ test: /\.scss$/, use: ['to-string-loader', 'css-loader', 'sass-loader'] },
{ test: /\.scss$/, use: ['@terminus-term/to-string-loader', 'css-loader', 'sass-loader'] },
{ test: /\.svg/, use: ['svg-inline-loader'] },
],
},
@@ -50,6 +50,8 @@ module.exports = {
'path',
'ngx-toastr',
'serialport',
'readline',
'stream',
'windows-process-tree/build/Release/windows_process_tree.node',
/^rxjs/,
/^@angular/,

View File

@@ -32,6 +32,11 @@ ansi-colors@^4.1.1:
resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.1.tgz#cbb9ae256bf750af1eab344f229aa27fe94ba348"
integrity sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==
buffer-replace@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/buffer-replace/-/buffer-replace-1.0.0.tgz#bc427c40af4c1f06d6933dede57110acba8ade54"
integrity sha1-vEJ8QK9MHwbWkz3t5XEQrLqK3lQ=
cli-spinner@^0.2.10:
version "0.2.10"
resolved "https://registry.yarnpkg.com/cli-spinner/-/cli-spinner-0.2.10.tgz#f7d617a36f5c47a7bc6353c697fc9338ff782a47"

View File

@@ -307,7 +307,7 @@ ngb-tabset.vertical(type='pills', [activeId]='activeTab')
td {{hotkey.id}}
td.pr-5
multi-hotkey-input(
[model]='getHotkey(hotkey.id)',
[model]='getHotkey(hotkey.id) || []',
(modelChange)='setHotkey(hotkey.id, $event); config.save(); docking.dock()'
)

View File

@@ -60,7 +60,7 @@ export class SettingsTabComponent extends BaseTabComponent {
this.settingsProviders = config.enabledServices(this.settingsProviders)
this.themes = config.enabledServices(this.themes)
this.configDefaults = yaml.safeDump(config.getDefaults())
this.configDefaults = yaml.dump(config.getDefaults())
const onConfigChange = () => {
this.configFile = config.readRaw()
@@ -116,7 +116,7 @@ export class SettingsTabComponent extends BaseTabComponent {
isConfigFileValid () {
try {
yaml.safeLoad(this.configFile)
yaml.load(this.configFile)
return true
} catch (_) {
return false

View File

@@ -40,8 +40,8 @@ module.exports = {
},
},
{ test: /\.pug$/, use: ['apply-loader', 'pug-loader'] },
{ test: /\.scss$/, use: ['to-string-loader', 'css-loader', 'sass-loader'] },
{ test: /\.css$/, use: ['to-string-loader', 'css-loader', 'sass-loader'] },
{ test: /\.scss$/, use: ['@terminus-term/to-string-loader', 'css-loader', 'sass-loader'] },
{ test: /\.css$/, use: ['@terminus-term/to-string-loader', 'css-loader', 'sass-loader'] },
{ test: /\.svg/, use: ['svg-inline-loader'] },
],
},

View File

@@ -140,6 +140,9 @@ export class SSHSession extends BaseSession {
this.shell = await this.openShellChannel({ x11: this.connection.x11 })
} catch (err) {
this.emitServiceMessage(colors.bgRed.black(' X ') + ` Remote rejected opening a shell channel: ${err}`)
if (err.toString().includes('Unable to request X11')) {
this.emitServiceMessage(' Make sure `xauth` is installed on the remote side')
}
return
}
@@ -245,7 +248,13 @@ export class SSHSession extends BaseSession {
}
socket.on('error', e => {
// eslint-disable-next-line @typescript-eslint/no-base-to-string
this.emitServiceMessage(colors.bgRed.black(' X ') + ` Could not connect to the X server ${xHost}:${xPort}: ${e}`)
this.emitServiceMessage(colors.bgRed.black(' X ') + ` Could not connect to the X server: ${e}`)
this.emitServiceMessage(` Terminus tried to connect to ${xHost}:${xPort} based on the DISPLAY environment var (${displaySpec})`)
if (process.platform === 'win32') {
this.emitServiceMessage(' To use X forwarding, you need a local X server, e.g.:')
this.emitServiceMessage(' * VcXsrv: https://sourceforge.net/projects/vcxsrv/')
this.emitServiceMessage(' * Xming: https://sourceforge.net/projects/xming/')
}
reject()
})
socket.on('connect', () => {
@@ -363,6 +372,10 @@ export class SSHSession extends BaseSession {
this.kill('TERM')
}
supportsWorkingDirectory (): boolean {
return true
}
async getWorkingDirectory (): Promise<string|null> {
return null
}
@@ -398,3 +411,9 @@ export interface SSHConnectionGroup {
name: string
connections: SSHConnection[]
}
export const ALGORITHM_BLACKLIST = [
// cause native crashes in node crypto, use EC instead
'diffie-hellman-group-exchange-sha256',
'diffie-hellman-group-exchange-sha1',
]

View File

@@ -103,7 +103,7 @@
.header
.title Jump host
select.form-control([(ngModel)]='connection.jumpHost')
option([ngValue]='null') None
option(value='') None
option([ngValue]='x.name', *ngFor='let x of config.store.ssh.connections') {{x.name}}
.form-line

View File

@@ -3,7 +3,7 @@ import { Component } from '@angular/core'
import { NgbModal, NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'
import { ElectronService, HostAppService, ConfigService } from 'terminus-core'
import { PasswordStorageService } from '../services/passwordStorage.service'
import { SSHConnection, LoginScript, SSHAlgorithmType } from '../api'
import { SSHConnection, LoginScript, SSHAlgorithmType, ALGORITHM_BLACKLIST } from '../api'
import { PromptModalComponent } from './promptModal.component'
import { ALGORITHMS } from 'ssh2-streams/lib/constants'
@@ -40,8 +40,8 @@ export class EditConnectionModalComponent {
[SSHAlgorithmType.CIPHER]: 'CIPHER',
[SSHAlgorithmType.HMAC]: 'HMAC',
}[k]
this.supportedAlgorithms[k] = ALGORITHMS[supportedAlg]
this.defaultAlgorithms[k] = ALGORITHMS[defaultAlg]
this.supportedAlgorithms[k] = ALGORITHMS[supportedAlg].filter(x => !ALGORITHM_BLACKLIST.includes(x))
this.defaultAlgorithms[k] = ALGORITHMS[defaultAlg].filter(x => !ALGORITHM_BLACKLIST.includes(x))
}
}

View File

@@ -14,15 +14,17 @@ import { Subscription } from 'rxjs'
/** @hidden */
@Component({
selector: 'ssh-tab',
template: BaseTerminalTabComponent.template + (require('./sshTab.component.pug') as string),
template: `${BaseTerminalTabComponent.template} ${require('./sshTab.component.pug')}`,
styles: [require('./sshTab.component.scss'), ...BaseTerminalTabComponent.styles],
animations: BaseTerminalTabComponent.animations,
})
export class SSHTabComponent extends BaseTerminalTabComponent {
connection?: SSHConnection
session?: SSHSession
session: SSHSession|null = null
private sessionStack: SSHSession[] = []
private homeEndSubscription: Subscription
private recentInputs = ''
private reconnectOffered = false
constructor (
injector: Injector,
@@ -57,6 +59,10 @@ export class SSHTabComponent extends BaseTerminalTabComponent {
this.frontendReady$.pipe(first()).subscribe(() => {
this.initializeSession()
this.input$.subscribe(data => {
this.recentInputs += data
this.recentInputs = this.recentInputs.substring(this.recentInputs.length - 32)
})
})
super.ngOnInit()
@@ -68,12 +74,23 @@ export class SSHTabComponent extends BaseTerminalTabComponent {
async setupOneSession (session: SSHSession): Promise<void> {
if (session.connection.jumpHost) {
const jumpConnection = this.config.store.ssh.connections.find(x => x.name === session.connection.jumpHost)
const jumpConnection: SSHConnection|null = this.config.store.ssh.connections.find(x => x.name === session.connection.jumpHost)
if (!jumpConnection) {
throw new Error(`${session.connection.host}: jump host "${session.connection.jumpHost}" not found in your config`)
}
const jumpSession = this.ssh.createSession(jumpConnection)
await this.setupOneSession(jumpSession)
jumpSession.destroyed$.subscribe(() => session.destroy())
this.attachSessionHandler(
jumpSession.destroyed$.subscribe(() => {
if (session.open) {
session.destroy()
}
})
)
session.jumpStream = await new Promise((resolve, reject) => jumpSession.ssh.forwardOut(
'127.0.0.1', 0, session.connection.host, session.connection.port ?? 22,
@@ -93,15 +110,11 @@ export class SSHTabComponent extends BaseTerminalTabComponent {
this.sessionStack.push(session)
}
session.serviceMessage$.subscribe(msg => {
this.attachSessionHandler(session.serviceMessage$.subscribe(msg => {
this.write(`\r\n${colors.black.bgWhite(' SSH ')} ${msg}\r\n`)
session.resize(this.size.columns, this.size.rows)
})
}))
session.destroyed$.subscribe(() => {
this.write('\r\n' + colors.black.bgCyan(' SSH ') + ` ${session.connection.host}: session closed\r\n`)
})
this.write('\r\n' + colors.black.bgCyan(' SSH ') + ` Connecting to ${session.connection.host}\r\n`)
@@ -128,20 +141,49 @@ export class SSHTabComponent extends BaseTerminalTabComponent {
}
}
protected attachSessionHandlers (): void {
const session = this.session!
super.attachSessionHandlers()
this.attachSessionHandler(session.destroyed$.subscribe(() => {
if (
// Ctrl-D
this.recentInputs.charCodeAt(this.recentInputs.length - 1) === 4 ||
this.recentInputs.endsWith('exit\r')
) {
// User closed the session
this.destroy()
} else {
// Session was closed abruptly
this.write('\r\n' + colors.black.bgCyan(' SSH ') + ` ${session.connection.host}: session closed\r\n`)
if (!this.reconnectOffered) {
this.reconnectOffered = true
this.write('Press any key to reconnect\r\n')
this.attachSessionHandler(this.input$.pipe(first()).subscribe(() => {
this.reconnect()
}))
}
}
}))
}
async initializeSession (): Promise<void> {
this.reconnectOffered = false
if (!this.connection) {
this.logger.error('No SSH connection info supplied')
return
}
this.session = this.ssh.createSession(this.connection)
const session = this.ssh.createSession(this.connection)
this.setSession(session)
await this.setupOneSession(this.session)
try {
await this.setupOneSession(session)
} catch (e) {
this.write(colors.black.bgRed(' X ') + ' ' + colors.red(e.message) + '\r\n')
}
this.attachSessionHandlers()
await this.session.start()
this.session.resize(this.size.columns, this.size.rows)
await this.session!.start()
this.session!.resize(this.size.columns, this.size.rows)
}
async getRecoveryToken (): Promise<RecoveryToken> {

View File

@@ -12,7 +12,7 @@ import * as sshpk from 'sshpk'
import { ToastrService } from 'ngx-toastr'
import { HostAppService, Platform, Logger, LogService, ElectronService, AppService, SelectorOption, ConfigService } from 'terminus-core'
import { SettingsTabComponent } from 'terminus-settings'
import { SSHConnection, SSHSession } from '../api'
import { ALGORITHM_BLACKLIST, SSHConnection, SSHSession } from '../api'
import { PromptModalComponent } from '../components/promptModal.component'
import { PasswordStorageService } from './passwordStorage.service'
import { SSHTabComponent } from '../components/sshTab.component'
@@ -147,6 +147,10 @@ export class SSHService {
session.ssh = ssh
let connected = false
let savedPassword: string|null = null
const algorithms = {}
for (const key of Object.keys(session.connection.algorithms ?? {})) {
algorithms[key] = session.connection.algorithms![key].filter(x => !ALGORITHM_BLACKLIST.includes(x))
}
await new Promise(async (resolve, reject) => {
ssh.on('ready', () => {
connected = true
@@ -258,7 +262,7 @@ export class SSHService {
tryKeyboard: true,
agent: agent ?? undefined,
agentForward: session.connection.agentForward && !!agent,
keepaliveInterval: session.connection.keepaliveInterval,
keepaliveInterval: session.connection.keepaliveInterval ?? 15000,
keepaliveCountMax: session.connection.keepaliveCountMax,
readyTimeout: session.connection.readyTimeout,
hostVerifier: (digest: string) => {
@@ -267,7 +271,7 @@ export class SSHService {
return true
},
hostHash: 'sha256' as any,
algorithms: session.connection.algorithms,
algorithms,
sock: session.jumpStream,
authHandler: methodsLeft => {
while (true) {
@@ -379,7 +383,7 @@ export class SSHService {
options.push({
name: 'Manage connections',
icon: 'cog',
callback: () => this.app.openNewTab(SettingsTabComponent, { activeTab: 'ssh' }),
callback: () => this.app.openNewTabRaw(SettingsTabComponent, { activeTab: 'ssh' }),
})
options.push({

View File

@@ -40,7 +40,7 @@ module.exports = {
},
},
{ test: /\.pug$/, use: ['apply-loader', 'pug-loader'] },
{ test: /\.scss$/, use: ['to-string-loader', 'css-loader', 'sass-loader'] },
{ test: /\.scss$/, use: ['@terminus-term/to-string-loader', 'css-loader', 'sass-loader'] },
{ test: /\.svg/, use: ['svg-inline-loader'] },
],
},

View File

@@ -27,12 +27,12 @@
"runes": "^0.4.2",
"slugify": "^1.4.0",
"xterm": "^4.9.0-beta.7",
"xterm-addon-fit": "^0.4.0-beta.8",
"xterm-addon-ligatures": "^0.4.0-beta.5",
"xterm-addon-search": "^0.7.0-beta.2",
"xterm-addon-serialize": "^0.3.0",
"xterm-addon-fit": "^0.5.0",
"xterm-addon-ligatures": "^0.4.0",
"xterm-addon-search": "^0.8.0",
"xterm-addon-serialize": "^0.4.0",
"xterm-addon-unicode11": "^0.2.0",
"xterm-addon-webgl": "^0.8.0",
"xterm-addon-webgl": "^0.9.0",
"zmodem.js": "^0.1.9"
},
"peerDependencies": {

View File

@@ -18,6 +18,7 @@ import { TerminalDecorator } from './decorator'
/** @hidden */
export interface ToastrServiceProxy {
info: (_: string) => void
error: (_: string) => void
}
/**
* A class to base your custom terminal tabs on
@@ -35,7 +36,7 @@ export class BaseTerminalTabComponent extends BaseTabComponent implements OnInit
]),
])]
session?: BaseSession
session: BaseSession|null = null
savedState?: any
@Input() zoom = 0
@@ -94,6 +95,7 @@ export class BaseTerminalTabComponent extends BaseTabComponent implements OnInit
private bellPlayer: HTMLAudioElement
private termContainerSubscriptions: Subscription[] = []
private allFocusModeSubscription: Subscription|null = null
private sessionHandlers: Subscription[] = []
get input$ (): Observable<Buffer> {
if (!this.frontend) {
@@ -140,7 +142,7 @@ export class BaseTerminalTabComponent extends BaseTabComponent implements OnInit
this.logger = this.log.create('baseTerminalTab')
this.setTitle('Terminal')
this.hotkeysSubscription = this.hotkeys.matchedHotkey.subscribe(hotkey => {
this.hotkeysSubscription = this.hotkeys.matchedHotkey.subscribe(async hotkey => {
if (!this.hasFocus) {
return
}
@@ -207,6 +209,9 @@ export class BaseTerminalTabComponent extends BaseTabComponent implements OnInit
case 'pane-focus-all':
this.focusAllPanes()
break
case 'copy-current-path':
this.copyCurrentPath()
break
}
})
this.bellPlayer = document.createElement('audio')
@@ -343,7 +348,7 @@ export class BaseTerminalTabComponent extends BaseTabComponent implements OnInit
async paste (): Promise<void> {
let data = this.electron.clipboard.readText()
if (this.config.store.terminal.bracketedPaste) {
data = '\x1b[200~' + data + '\x1b[201~'
data = `\x1b[200~${data}\x1b[201~`
}
if (this.hostApp.platform === Platform.Windows) {
data = data.replace(/\r\n/g, '\r')
@@ -414,10 +419,11 @@ export class BaseTerminalTabComponent extends BaseTabComponent implements OnInit
return
}
if (this.parent instanceof SplitTabComponent) {
this.parent._allFocusMode = true
this.parent.layout()
const parent = this.parent
parent._allFocusMode = true
parent.layout()
this.allFocusModeSubscription = this.frontend?.input$.subscribe(data => {
for (const tab of (this.parent as SplitTabComponent).getAllTabs()) {
for (const tab of parent.getAllTabs()) {
if (tab !== this && tab instanceof BaseTerminalTabComponent) {
tab.sendInput(data)
}
@@ -438,6 +444,19 @@ export class BaseTerminalTabComponent extends BaseTabComponent implements OnInit
}
}
async copyCurrentPath (): Promise<void> {
let cwd: string|null = null
if (this.session?.supportsWorkingDirectory()) {
cwd = await this.session.getWorkingDirectory()
}
if (cwd) {
this.electron.clipboard.writeText(cwd)
this.toastr.info('Copied')
} else {
this.toastr.error('Shell does not support current path detection')
}
}
/** @hidden */
ngOnDestroy (): void {
this.frontend?.detach(this.content.nativeElement)
@@ -550,26 +569,55 @@ export class BaseTerminalTabComponent extends BaseTabComponent implements OnInit
]
}
setSession (session: BaseSession|null, destroyOnSessionClose = false): void {
if (session) {
if (this.session) {
this.setSession(null)
}
this.detachSessionHandlers()
this.session = session
this.attachSessionHandlers(destroyOnSessionClose)
} else {
this.detachSessionHandlers()
this.session = null
}
}
protected attachSessionHandler (subscription: Subscription): void {
this.sessionHandlers.push(subscription)
}
protected attachSessionHandlers (destroyOnSessionClose = false): void {
if (!this.session) {
throw new Error('Session not set')
}
// this.session.output$.bufferTime(10).subscribe((datas) => {
this.session.output$.subscribe(data => {
this.attachSessionHandler(this.session.output$.subscribe(data => {
if (this.enablePassthrough) {
this.zone.run(() => {
this.output.next(data)
this.write(data)
})
}
})
}))
if (destroyOnSessionClose) {
this.sessionCloseSubscription = this.session.closed$.subscribe(() => {
this.attachSessionHandler(this.sessionCloseSubscription = this.session.closed$.subscribe(() => {
this.frontend?.destroy()
this.destroy()
})
}))
}
this.attachSessionHandler(this.session.destroyed$.subscribe(() => {
this.setSession(null)
}))
}
protected detachSessionHandlers (): void {
for (const s of this.sessionHandlers) {
s.unsubscribe()
}
this.sessionHandlers = []
}
}

View File

@@ -10,7 +10,7 @@ import { Subject } from 'rxjs'
})
export class EnvironmentEditorComponent {
@Output() modelChange = new Subject<any>()
vars: {key: string, value: string}[] = []
vars: { key: string, value: string }[] = []
private cachedModel: any
@Input() get model (): any {

View File

@@ -57,15 +57,14 @@ h3.mb-3 Shell
.form-line
.header
.title Always Use Working Directory
.description
div By default, new terminals will open where the previous terminal was working.
div Enabling this option will always launch new terminals in the working directory specified above.
.title Directory for new tabs
toggle(
select.form-control(
[(ngModel)]='config.store.terminal.alwaysUseWorkingDirectory',
(ngModelChange)='config.save()'
(ngModelChange)='config.save()',
)
option([ngValue]='false') Same as active tab's directory
option([ngValue]='true') The working directory from above
.form-line.align-items-start
.header
@@ -97,7 +96,7 @@ h3.mt-3 Saved Profiles
button.btn.btn-outline-danger.ml-1((click)='$event.stopPropagation(); deleteProfile(profile)')
i.fas.fa-trash
div(ngbDropdown, placement='top-left')
.pb-4(ngbDropdown, placement='top-left')
button.btn.btn-primary(ngbDropdownToggle)
i.fas.fa-fw.fa-plus
| New profile

View File

@@ -4,6 +4,7 @@ import { ConfigProvider, Platform } from 'terminus-core'
export class TerminalConfigProvider extends ConfigProvider {
defaults = {
hotkeys: {
'copy-current-path': [],
shell: {
__nonStructural: true,
},

View File

@@ -62,6 +62,10 @@ export class TerminalHotkeyProvider extends HotkeyProvider {
id: 'ctrl-c',
name: 'Intelligent Ctrl-C (copy/abort)',
},
{
id: 'copy-current-path',
name: 'Copy current path',
},
{
id: 'search',
name: 'Search',

View File

@@ -194,6 +194,9 @@ export default class TerminalModule { // eslint-disable-line @typescript-eslint/
})
hostApp.cliOpenDirectory$.subscribe(async directory => {
if (directory.length > 1 && (directory.endsWith('/') || directory.endsWith('\\'))) {
directory = directory.substring(0, directory.length - 1)
}
if (await fs.exists(directory)) {
if ((await fs.stat(directory)).isDirectory()) {
terminal.openTab(undefined, directory)

View File

@@ -2,12 +2,11 @@ import * as psNode from 'ps-node'
import * as fs from 'mz/fs'
import * as os from 'os'
import * as nodePTY from '@terminus-term/node-pty'
import { getWorkingDirectoryFromPID } from 'native-process-working-directory'
import { Observable, Subject } from 'rxjs'
import { first } from 'rxjs/operators'
import { Injectable } from '@angular/core'
import { Logger, LogService, ConfigService, WIN_BUILD_CONPTY_SUPPORTED, isWindowsBuild } from 'terminus-core'
import { exec } from 'mz/child_process'
import { SessionOptions } from '../api/interfaces'
/* eslint-disable block-scoped-var */
@@ -20,7 +19,6 @@ try {
var windowsProcessTree = require('windows-process-tree') // eslint-disable-line @typescript-eslint/no-var-requires, no-var
} catch { }
export interface ChildProcess {
pid: number
ppid: number
@@ -28,7 +26,6 @@ export interface ChildProcess {
}
const windowsDirectoryRegex = /([a-zA-Z]:[^\:\[\]\?\"\<\>\|]+)/mi
const catalinaDataVolumePrefix = '/System/Volumes/Data'
const OSC1337Prefix = Buffer.from('\x1b]1337;')
const OSC1337Suffix = Buffer.from('\x07')
@@ -87,6 +84,7 @@ export abstract class BaseSession {
abstract kill (signal?: string): void
abstract async getChildProcesses (): Promise<ChildProcess[]>
abstract async gracefullyKillProcess (): Promise<void>
abstract supportsWorkingDirectory (): boolean
abstract async getWorkingDirectory (): Promise<string|null>
}
@@ -96,6 +94,7 @@ export class Session extends BaseSession {
private pauseAfterExit = false
private guessedCWD: string|null = null
private reportedCWD: string
private initialCWD: string|null = null
constructor (private config: ConfigService) {
super()
@@ -153,6 +152,7 @@ export class Session extends BaseSession {
this.truePID = processes[0].pid
processes = await this.getChildProcesses()
}
this.initialCWD = await this.getWorkingDirectory()
}, 2000)
this.open = true
@@ -259,6 +259,10 @@ export class Session extends BaseSession {
}
}
supportsWorkingDirectory (): boolean {
return !!(this.truePID || this.reportedCWD || this.guessedCWD)
}
async getWorkingDirectory (): Promise<string|null> {
if (this.reportedCWD) {
return this.reportedCWD
@@ -266,40 +270,31 @@ export class Session extends BaseSession {
if (!this.truePID) {
return null
}
if (process.platform === 'darwin') {
let lines: string[] = []
try {
lines = (await exec(`lsof -p ${this.truePID} -Fn`))[0].toString().split('\n')
} catch (e) {
return null
}
let cwd = lines[lines[1] === 'fcwd' ? 2 : 1].substring(1)
if (cwd.startsWith(catalinaDataVolumePrefix)) {
cwd = cwd.substring(catalinaDataVolumePrefix.length)
}
return cwd
let cwd: string|null = null
try {
cwd = getWorkingDirectoryFromPID(this.truePID)
} catch (exc) {
console.error(exc)
}
if (process.platform === 'linux') {
try {
const cwd = await fs.readlink(`/proc/${this.truePID}/cwd`)
return cwd
} catch (exc) {
console.error(exc)
return null
}
try {
cwd = await fs.realpath(cwd)
} catch {}
if (process.platform === 'win32' && (cwd === this.initialCWD || cwd === process.env.WINDIR)) {
// shell doesn't truly change its process' CWD
cwd = null
}
if (process.platform === 'win32') {
if (!this.guessedCWD) {
return null
}
try {
await fs.access(this.guessedCWD)
} catch (e) {
return null
}
return this.guessedCWD
// eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
cwd = cwd || this.guessedCWD
try {
await fs.access(cwd)
} catch {
return null
}
return null
return cwd
}
private guessWindowsCWD (data: string) {

View File

@@ -16,7 +16,7 @@ export class TerminalFrontendService {
private hotkeys: HotkeysService,
) { }
getFrontend (session?: BaseSession): Frontend {
getFrontend (session?: BaseSession|null): Frontend {
if (!session) {
const frontend: Frontend = new {
xterm: XTermFrontend,

View File

@@ -8,6 +8,8 @@ import { Shell } from '../api/interfaces'
/** @hidden */
@Injectable()
export class MacOSDefaultShellProvider extends ShellProvider {
private cachedShell?: string
constructor (
private hostApp: HostAppService,
) {
@@ -18,14 +20,29 @@ export class MacOSDefaultShellProvider extends ShellProvider {
if (this.hostApp.platform !== Platform.macOS) {
return []
}
const shellEntry = (await exec(`/usr/bin/dscl . -read /Users/${process.env.LOGNAME} UserShell`))[0].toString()
return [{
id: 'default',
name: 'User default',
command: shellEntry.split(' ')[1].trim(),
command: await this.getDefaultShellCached(),
args: ['--login'],
hidden: true,
env: {},
}]
}
private async getDefaultShellCached () {
if (!this.cachedShell) {
this.cachedShell = await this.getDefaultShell()
} else {
this.getDefaultShell().then(shell => {
this.cachedShell = shell
})
}
return this.cachedShell!
}
private async getDefaultShell () {
const shellEntry = (await exec(`/usr/bin/dscl . -read /Users/${process.env.LOGNAME} UserShell`))[0].toString()
return shellEntry.split(' ')[1].trim()
}
}

View File

@@ -123,6 +123,13 @@ export class NewTabContextMenu extends TabContextMenuItemProvider {
})
}
if (tab instanceof TerminalTabComponent && tab.session?.supportsWorkingDirectory()) {
items.push({
label: 'Copy current path',
click: () => this.zone.run(() => tab.copyCurrentPath()),
})
}
return items
}
}

View File

@@ -43,7 +43,7 @@ module.exports = {
},
},
{ test: /\.pug$/, use: ['apply-loader', 'pug-loader'] },
{ test: /\.scss$/, use: ['to-string-loader', 'css-loader', 'sass-loader'] },
{ test: /\.scss$/, use: ['@terminus-term/to-string-loader', 'css-loader', 'sass-loader'] },
{ test: /\.css$/, use: ['style-loader', 'css-loader'] },
{ test: /\.svg/, use: ['svg-inline-loader'] },
{
@@ -67,6 +67,7 @@ module.exports = {
'windows-native-registry',
'@terminus-term/node-pty',
'windows-process-tree',
'native-process-working-directory',
'os',
/^rxjs/,
/^@angular/,

View File

@@ -111,10 +111,10 @@ exit-on-epipe@~1.0.1:
resolved "https://registry.yarnpkg.com/exit-on-epipe/-/exit-on-epipe-1.0.1.tgz#0bdd92e87d5285d267daa8171d0eb06159689692"
integrity sha512-h2z5mrROTxce56S+pnvAV890uu7ls7f1kEvVGJbw1OlFH3/mlJ5bkXu0KRyW94v37zzHPiUd55iLn3DA7TjWpw==
font-finder@^1.0.3, font-finder@^1.0.4:
version "1.0.4"
resolved "https://registry.yarnpkg.com/font-finder/-/font-finder-1.0.4.tgz#2ca944954dd8d0e1b5bdc4c596cc08607761d89b"
integrity sha512-naF16RpjWUTFLqzhmdivYpBCrqySN6PI+a4GPtoEsCdvOpbKYTGeTjO7mxh3Wwjz4xKU+Oqx9kwOcteLDeMFQA==
font-finder@^1.0.3, font-finder@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/font-finder/-/font-finder-1.1.0.tgz#2bff2b2762acba720239c8bec898a96daae90858"
integrity sha512-wpCL2uIbi6GurJbU7ZlQ3nGd61Ho+dSU6U83/xJT5UPFfN35EeCW/rOtS+5k+IuEZu2SYmHzDIPL9eA5tSYRAw==
dependencies:
get-system-fonts "^2.0.0"
promise-stream-reader "^1.0.1"
@@ -337,43 +337,43 @@ tiny-inflate@^1.0.2:
resolved "https://registry.yarnpkg.com/tiny-inflate/-/tiny-inflate-1.0.3.tgz#122715494913a1805166aaf7c93467933eea26c4"
integrity sha512-pkY1fj1cKHb2seWDy0B16HeWyczlJA9/WW3u3c4z/NiWDsO3DOU5D7nhTLE9CF0yXv/QZFY7sEJmj24dK+Rrqw==
xterm-addon-fit@^0.4.0-beta.8:
version "0.4.0"
resolved "https://registry.yarnpkg.com/xterm-addon-fit/-/xterm-addon-fit-0.4.0.tgz#06e0c5d0a6aaacfb009ef565efa1c81e93d90193"
integrity sha512-p4BESuV/g2L6pZzFHpeNLLnep9mp/DkF3qrPglMiucSFtD8iJxtMufEoEJbN8LZwB4i+8PFpFvVuFrGOSpW05w==
xterm-addon-fit@^0.5.0:
version "0.5.0"
resolved "https://registry.yarnpkg.com/xterm-addon-fit/-/xterm-addon-fit-0.5.0.tgz#2d51b983b786a97dcd6cde805e700c7f913bc596"
integrity sha512-DsS9fqhXHacEmsPxBJZvfj2la30Iz9xk+UKjhQgnYNkrUIN5CYLbw7WEfz117c7+S86S/tpHPfvNxJsF5/G8wQ==
xterm-addon-ligatures@^0.4.0-beta.5:
version "0.4.0-beta.7"
resolved "https://registry.yarnpkg.com/xterm-addon-ligatures/-/xterm-addon-ligatures-0.4.0-beta.7.tgz#06dfafe0491a2e4744b1a6429958f261820baa00"
integrity sha512-GVZKbm7GRgs0LFtdKKmpu0Cs2jfC+sdRtl2E4vWEmhi8WNeW9iINbrsYgdtFPvs1X9OaKxEWqEXJkTcy5rmLHQ==
xterm-addon-ligatures@^0.4.0:
version "0.4.0"
resolved "https://registry.yarnpkg.com/xterm-addon-ligatures/-/xterm-addon-ligatures-0.4.0.tgz#23235d831988c5780ca1e28002b750ec0b1a78ca"
integrity sha512-on+2TgzioEL5Mz60WchsTiuR2SvYzG3xVro39HIpYFM641lpMuPM83Pdm3W/ogkaGrpGm29Ysq2S2LCl/h7rhw==
dependencies:
font-finder "^1.0.4"
font-finder "^1.1.0"
font-ligatures "^1.3.3"
xterm-addon-search@^0.7.0-beta.2:
version "0.7.0"
resolved "https://registry.yarnpkg.com/xterm-addon-search/-/xterm-addon-search-0.7.0.tgz#c929d3e5cbb335e82bff72f158ea82936d9cd4ef"
integrity sha512-6060evmJJ+tZcjnx33FXaeEHLpuXEa7l9UzUsYfMlCKbu88AbE+5LJocTKCHYd71cwCwb9pjmv/G1o9Rf9Zbcg==
xterm-addon-search@^0.8.0:
version "0.8.0"
resolved "https://registry.yarnpkg.com/xterm-addon-search/-/xterm-addon-search-0.8.0.tgz#e33eab918df7eac7e7baf95dd2b3d14133754881"
integrity sha512-MPJGPVPpHRUw9cLIuqQbrVepmENMOybVUSxIALz5h1ryyQBrVqVujq2hL5aroX5/dZJoHx9lGHQTVLQ07SKgKA==
xterm-addon-serialize@^0.3.0:
version "0.3.0"
resolved "https://registry.yarnpkg.com/xterm-addon-serialize/-/xterm-addon-serialize-0.3.0.tgz#b4f24089285801bcc5f601791a4cac416d528a6a"
integrity sha512-g+eGqgvQiON4CCEku0iG53obZxi353wig2XRR75DOoHlPMLrO63kvt2V+OahnJlxCpsWQ1BFu4Q5HquQnS6uvQ==
xterm-addon-serialize@^0.4.0:
version "0.4.0"
resolved "https://registry.yarnpkg.com/xterm-addon-serialize/-/xterm-addon-serialize-0.4.0.tgz#9854fd87afba6157b9016e9c93f0cf9e0efc2de5"
integrity sha512-xEdzCNa6ZzFplDlscYTSSUogy1C6y3G3nS68Qbe5zntFAqHOBeyggExQi0E8yZg/no8ewYH0GSKZnOheo/ZoKg==
xterm-addon-unicode11@^0.2.0:
version "0.2.0"
resolved "https://registry.yarnpkg.com/xterm-addon-unicode11/-/xterm-addon-unicode11-0.2.0.tgz#9ed0c482b353908bba27778893ca80823382737c"
integrity sha512-rjFDItPc/IDoSiEnoDFwKroNwLD/7t9vYKENjrcKVZg5tgJuuUj8D4rZtP6iVCjSB1LTLYmUs4L/EmCqIyLR/Q==
xterm-addon-webgl@^0.8.0:
version "0.8.0"
resolved "https://registry.yarnpkg.com/xterm-addon-webgl/-/xterm-addon-webgl-0.8.0.tgz#4bc6bb4dbfea5b0d2d7978d6c5cef922d584fb4f"
integrity sha512-dlpYPsv0C9S6v6+T/h/d/otSbdUTizMJdxvSoS34tUpMOHev6iW7Zqt5KRFqYxl4vCqpDk9Wmhb3fKL3kwX5fQ==
xterm-addon-webgl@^0.9.0:
version "0.9.0"
resolved "https://registry.yarnpkg.com/xterm-addon-webgl/-/xterm-addon-webgl-0.9.0.tgz#947ca94f9fd72462155c300dfb82bc471402d60a"
integrity sha512-JSRoe/MgPEKCpr7LbiC+sQUq0c9l/ZhsBXYugKx5BJsJEPsY+5EFcqAexuhsJVe/qV+CP3hsbYDe/411rw3ASA==
xterm@^4.9.0-beta.7:
version "4.9.0"
resolved "https://registry.yarnpkg.com/xterm/-/xterm-4.9.0.tgz#7a4c097a433d565339b5533b468bbc60c6c87969"
integrity sha512-wGfqufmioctKr8VkbRuZbVDfjlXWGZZ1PWHy1yqqpGT3Nm6yaJx8lxDbSEBANtgaiVPTcKSp97sxOy5IlpqYfw==
version "4.10.0"
resolved "https://registry.yarnpkg.com/xterm/-/xterm-4.10.0.tgz#fc4f554e3e718aff9b83622e858e64b0953067bb"
integrity sha512-Wn66I8YpSVkgP3R95GjABC6Eb21pFfnCSnyIqKIIoUI13ohvwd0KGVzUDfyEFfSAzKbPJfrT2+vt7SfUXBZQKQ==
yallist@^2.1.2:
version "2.1.2"

View File

@@ -24,6 +24,9 @@
"es7",
"es2015",
"es2017"
]
],
"paths": {
"terminus-*": ["../../terminus-*/src"]
}
}
}

1312
yarn.lock

File diff suppressed because it is too large Load Diff