Compare commits
388 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
596d75adc1 | ||
![]() |
45f6e59583 | ||
![]() |
ff3f606aea | ||
![]() |
e7311a21e9 | ||
![]() |
c4a4255a7a | ||
![]() |
247053665c | ||
![]() |
141c890b9c | ||
![]() |
ccb5d90634 | ||
![]() |
8c61b8a778 | ||
![]() |
093aa66797 | ||
![]() |
669c339f87 | ||
![]() |
e6ab403e3e | ||
![]() |
fcbcdfe660 | ||
![]() |
450073d418 | ||
![]() |
8b0ba30b9f | ||
![]() |
34abc9813b | ||
![]() |
3df0c71a5a | ||
![]() |
1d9206886a | ||
![]() |
4b346b5428 | ||
![]() |
5f51049c1a | ||
![]() |
5e1f652225 | ||
![]() |
1622977991 | ||
![]() |
9a5021110d | ||
![]() |
05d842b69b | ||
![]() |
4a24bd5d90 | ||
![]() |
0fdc780eca | ||
![]() |
6f8bf46c01 | ||
![]() |
7de78365b0 | ||
![]() |
5f87123fb2 | ||
![]() |
fa1cb5fb4b | ||
![]() |
d973d6c60f | ||
![]() |
b002c59578 | ||
![]() |
ec981dc24d | ||
![]() |
12d625f561 | ||
![]() |
37a7d32bc8 | ||
![]() |
044a39abc9 | ||
![]() |
7bedfc5122 | ||
![]() |
1031b2912c | ||
![]() |
732e494400 | ||
![]() |
0a700fc6c3 | ||
![]() |
af069f25e2 | ||
![]() |
c50257fec4 | ||
![]() |
025927577e | ||
![]() |
39bbe54992 | ||
![]() |
e3a0a4bc5e | ||
![]() |
44ab6cf9b7 | ||
![]() |
1c23db3b55 | ||
![]() |
ac727885c4 | ||
![]() |
0e8482e28d | ||
![]() |
46720e3236 | ||
![]() |
c3693f5d44 | ||
![]() |
d4f3c6ebf4 | ||
![]() |
3cc4c5d1b4 | ||
![]() |
5cea920270 | ||
![]() |
0dcba9861a | ||
![]() |
03e299ecc6 | ||
![]() |
5e1e63c37b | ||
![]() |
59e73616cd | ||
![]() |
e03e96f61b | ||
![]() |
01cd2cc4b1 | ||
![]() |
f00a4cf38f | ||
![]() |
9d5860a452 | ||
![]() |
24bbbd3e96 | ||
![]() |
673cc2f9f9 | ||
![]() |
db12702baa | ||
![]() |
807cb0aac4 | ||
![]() |
4033885eb7 | ||
![]() |
4deee0d6c1 | ||
![]() |
58ef772764 | ||
![]() |
f9707f796e | ||
![]() |
37f4be68aa | ||
![]() |
84a4491104 | ||
![]() |
2b2453a397 | ||
![]() |
cc6443bb6c | ||
![]() |
58482ecc63 | ||
![]() |
00b9a3e773 | ||
![]() |
249d487813 | ||
![]() |
f6176eca6f | ||
![]() |
f4cf07b565 | ||
![]() |
581b31964e | ||
![]() |
01bc47a6b7 | ||
![]() |
7fc5228297 | ||
![]() |
6153a8ba9f | ||
![]() |
adf029cf72 | ||
![]() |
aa2989d485 | ||
![]() |
df9abb0241 | ||
![]() |
d54e6125f4 | ||
![]() |
fe6516ac44 | ||
![]() |
7a59edbe71 | ||
![]() |
f7f3ef181d | ||
![]() |
b303291ec4 | ||
![]() |
89b67e534e | ||
![]() |
928d60985b | ||
![]() |
403f988248 | ||
![]() |
2099b1b3c2 | ||
![]() |
8ab5e2f976 | ||
![]() |
92227484ac | ||
![]() |
2ede6f6a83 | ||
![]() |
dce39a6075 | ||
![]() |
15e6c42692 | ||
![]() |
f061ff53f2 | ||
![]() |
b8a0207078 | ||
![]() |
4ec09ad650 | ||
![]() |
59f1f5e986 | ||
![]() |
91bdefd9ba | ||
![]() |
382c47aae0 | ||
![]() |
b6bcb852e5 | ||
![]() |
a91a2604dc | ||
![]() |
43e9768819 | ||
![]() |
b45da4edc8 | ||
![]() |
f42abb3c52 | ||
![]() |
ac171b1d61 | ||
![]() |
62a1ce526a | ||
![]() |
ce4abc28a7 | ||
![]() |
c9bafa74d1 | ||
![]() |
37f324a458 | ||
![]() |
bb2a4c69ad | ||
![]() |
c1b70332fc | ||
![]() |
0270b56185 | ||
![]() |
e09351760d | ||
![]() |
bba98b46f5 | ||
![]() |
874cf0ed7d | ||
![]() |
9ba0cbb3c7 | ||
![]() |
3587f179a4 | ||
![]() |
5a9b4e56b7 | ||
![]() |
71780a707a | ||
![]() |
8e390eef05 | ||
![]() |
96f1342c84 | ||
![]() |
2f93202d1d | ||
![]() |
29ba16a68f | ||
![]() |
5da0ef1f0d | ||
![]() |
878e846150 | ||
![]() |
aebbe3dbfd | ||
![]() |
b9132ac5cb | ||
![]() |
bbbaaaa61c | ||
![]() |
9795efd965 | ||
![]() |
c350b99465 | ||
![]() |
6a64ea5254 | ||
![]() |
ad469c08fe | ||
![]() |
661ada154e | ||
![]() |
a8bbdea224 | ||
![]() |
4c0bf62b7b | ||
![]() |
f5b096e6d4 | ||
![]() |
463edc2822 | ||
![]() |
02ef0fcd5e | ||
![]() |
556f622527 | ||
![]() |
8bb194ddda | ||
![]() |
4a040be01e | ||
![]() |
8d90dcca0e | ||
![]() |
9f7643b0d3 | ||
![]() |
528852ba83 | ||
![]() |
7d92f24a02 | ||
![]() |
d66afd0e13 | ||
![]() |
e1c3329d75 | ||
![]() |
a8635d0882 | ||
![]() |
0c75e46a3b | ||
![]() |
450349b006 | ||
![]() |
b416570ebf | ||
![]() |
bb6b4921b4 | ||
![]() |
857fb7feeb | ||
![]() |
84dbe1f2df | ||
![]() |
96d86ca93f | ||
![]() |
47a5362863 | ||
![]() |
f7740e3030 | ||
![]() |
1187dfe4a9 | ||
![]() |
e652800a65 | ||
![]() |
12bc1025c7 | ||
![]() |
800720e578 | ||
![]() |
aba9c73974 | ||
![]() |
8faafb1014 | ||
![]() |
88f1816c62 | ||
![]() |
35e8e5f525 | ||
![]() |
2d845069c1 | ||
![]() |
64c65d35c9 | ||
![]() |
8925b20447 | ||
![]() |
ca0680519c | ||
![]() |
e9036ebeac | ||
![]() |
f35d47ee4f | ||
![]() |
d6e6e7e511 | ||
![]() |
903fa12ac4 | ||
![]() |
9071c8ca23 | ||
![]() |
6bff52c951 | ||
![]() |
7c450ec6b2 | ||
![]() |
e791190558 | ||
![]() |
a6e6c425a5 | ||
![]() |
14dcb22afe | ||
![]() |
1e25a45b4a | ||
![]() |
3e5a722b66 | ||
![]() |
524e5511c9 | ||
![]() |
946306c28b | ||
![]() |
c2d9416fec | ||
![]() |
d55f54d90b | ||
![]() |
cbb6a7ab9a | ||
![]() |
2e7caf7118 | ||
![]() |
bf56659907 | ||
![]() |
dfa95dbd78 | ||
![]() |
d41021b3cc | ||
![]() |
0ddc1bed76 | ||
![]() |
8f7f10dc8f | ||
![]() |
dea7ee8ee1 | ||
![]() |
b79d618aaa | ||
![]() |
b2c0af2307 | ||
![]() |
44cf23ec08 | ||
![]() |
7b9cc47875 | ||
![]() |
6e59ea007c | ||
![]() |
f580c72f1d | ||
![]() |
1ae91b3ea7 | ||
![]() |
60d7f546c1 | ||
![]() |
a3c834696d | ||
![]() |
00e33d6d1e | ||
![]() |
c9de6ef26b | ||
![]() |
8660d0ced4 | ||
![]() |
23fa0c100c | ||
![]() |
8376a049ad | ||
![]() |
7bd26b542a | ||
![]() |
949ec282c1 | ||
![]() |
00652f59c3 | ||
![]() |
0502410b22 | ||
![]() |
34eac02101 | ||
![]() |
480db40f10 | ||
![]() |
4ad047aed7 | ||
![]() |
d50e59eadb | ||
![]() |
067f5b3342 | ||
![]() |
c23c696adf | ||
![]() |
ea50332799 | ||
![]() |
9ce04e4945 | ||
![]() |
39d7ebb7e9 | ||
![]() |
6c97c8bd20 | ||
![]() |
c32d8f3497 | ||
![]() |
73d27a6a49 | ||
![]() |
aa3be39f89 | ||
![]() |
7c0317f38a | ||
![]() |
c2f759f52a | ||
![]() |
347f1c4840 | ||
![]() |
24bb1d70da | ||
![]() |
3187545bb7 | ||
![]() |
e6f5a3d93f | ||
![]() |
387ff7d950 | ||
![]() |
84f5d558fb | ||
![]() |
22452d9da6 | ||
![]() |
373429ce57 | ||
![]() |
a697e063a6 | ||
![]() |
25131a5e92 | ||
![]() |
8f9d6b2be8 | ||
![]() |
bc78ef49c6 | ||
![]() |
c25e7cab77 | ||
![]() |
e391524d69 | ||
![]() |
bbf3faf1e3 | ||
![]() |
902deb020b | ||
![]() |
a37d28d6db | ||
![]() |
f547122b41 | ||
![]() |
a9f9560728 | ||
![]() |
48cf9d4008 | ||
![]() |
2dd527864e | ||
![]() |
1364a69b35 | ||
![]() |
bd33689d8b | ||
![]() |
e1fad67107 | ||
![]() |
aa63b04e2a | ||
![]() |
81b0b63da4 | ||
![]() |
aaf575354d | ||
![]() |
d4428d1fc3 | ||
![]() |
debac7551b | ||
![]() |
eaf5b6166d | ||
![]() |
d931d88d69 | ||
![]() |
f64d5dfb82 | ||
![]() |
329ae39e96 | ||
![]() |
f381176333 | ||
![]() |
6ddfc8b924 | ||
![]() |
1df4e83e4a | ||
![]() |
ee8a6e7e7a | ||
![]() |
d54b17e2f3 | ||
![]() |
efc61d9e26 | ||
![]() |
6c52e0496d | ||
![]() |
01664bf104 | ||
![]() |
b19916513e | ||
![]() |
df715595de | ||
![]() |
58e5ab2e7c | ||
![]() |
3fd4318062 | ||
![]() |
ccb72b3c5d | ||
![]() |
13eb3ed832 | ||
![]() |
03c2e214e1 | ||
![]() |
589b5f698c | ||
![]() |
522eb03086 | ||
![]() |
621ac4feee | ||
![]() |
5e8489fff3 | ||
![]() |
56c4e802fe | ||
![]() |
dccf627506 | ||
![]() |
94def009c2 | ||
![]() |
82a57957b1 | ||
![]() |
04a0e91175 | ||
![]() |
77273fe052 | ||
![]() |
82ffa7a499 | ||
![]() |
6c86ea5e7a | ||
![]() |
1ba2b6a4cc | ||
![]() |
57bf1008b0 | ||
![]() |
078582e40c | ||
![]() |
c8a963ae14 | ||
![]() |
32ed3d16fd | ||
![]() |
70467e2924 | ||
![]() |
c9e12c666e | ||
![]() |
f2e082e732 | ||
![]() |
0f8a38b807 | ||
![]() |
ee936b74bf | ||
![]() |
3a24d91aa4 | ||
![]() |
42ae468780 | ||
![]() |
1fda886849 | ||
![]() |
3bf66f1346 | ||
![]() |
93084d57b0 | ||
![]() |
eb72951ec6 | ||
![]() |
ea78c46bb4 | ||
![]() |
fac1c8ec88 | ||
![]() |
a494e03f3d | ||
![]() |
8b5d50bf8b | ||
![]() |
b512353dfb | ||
![]() |
a18afbb6dc | ||
![]() |
70a333e790 | ||
![]() |
fc55327df5 | ||
![]() |
aa93bc3d74 | ||
![]() |
3ad1f4f59e | ||
![]() |
576e63584a | ||
![]() |
974879b54d | ||
![]() |
1cfe0637f4 | ||
![]() |
f58a9bcaf6 | ||
![]() |
dd6d71f023 | ||
![]() |
140eb5bd6a | ||
![]() |
16f41aad69 | ||
![]() |
323e57d2b1 | ||
![]() |
ba550b9617 | ||
![]() |
4afcfcb41a | ||
![]() |
06da6970cb | ||
![]() |
5a8e71f2f2 | ||
![]() |
38164d3136 | ||
![]() |
7ebc00a140 | ||
![]() |
49c05b9e5f | ||
![]() |
24381a9081 | ||
![]() |
1a0acad3c2 | ||
![]() |
206cf974c0 | ||
![]() |
d42fe4f107 | ||
![]() |
60e095fbc7 | ||
![]() |
b54d99ff3d | ||
![]() |
f3edf9a469 | ||
![]() |
a7ba9d88c3 | ||
![]() |
dc00aa4836 | ||
![]() |
d1a2932245 | ||
![]() |
26d7dc3031 | ||
![]() |
48ff7d7d5a | ||
![]() |
bc71547d92 | ||
![]() |
054383ed8e | ||
![]() |
005912dfe8 | ||
![]() |
32e7d2db5c | ||
![]() |
15a2662d10 | ||
![]() |
ee472bad35 | ||
![]() |
619c663438 | ||
![]() |
dd16d44b3a | ||
![]() |
01c4d029bd | ||
![]() |
4fbc2b99b0 | ||
![]() |
ea7ddc7d9a | ||
![]() |
c25c9a285e | ||
![]() |
c10e5e918f | ||
![]() |
7dc59bd5a8 | ||
![]() |
d2b9a2cb7d | ||
![]() |
6b21bbac58 | ||
![]() |
0d4ebe3d96 | ||
![]() |
c856f460e6 | ||
![]() |
6a969d2cd2 | ||
![]() |
4d84b14168 | ||
![]() |
b6cbd42d8b | ||
![]() |
7237c2b05a | ||
![]() |
19a217923e | ||
![]() |
7f160e9421 | ||
![]() |
d0c245d0d5 | ||
![]() |
693edab597 | ||
![]() |
d42e070e6c | ||
![]() |
c5958bc9a0 | ||
![]() |
9dc2337787 | ||
![]() |
1a38cc30a8 | ||
![]() |
4949f14184 | ||
![]() |
11902020a5 | ||
![]() |
3f96c21f33 | ||
![]() |
9e81f0aa0e | ||
![]() |
1cce23cef5 | ||
![]() |
b7a56adb60 | ||
![]() |
eb02752cbf | ||
![]() |
3a6eb8cb2f | ||
![]() |
a7d62b0234 | ||
![]() |
b9cbe4f12d | ||
![]() |
5f74b35ba9 | ||
![]() |
affb439ab2 |
146
.all-contributorsrc
Normal file
@@ -0,0 +1,146 @@
|
|||||||
|
{
|
||||||
|
"files": [
|
||||||
|
"README.md"
|
||||||
|
],
|
||||||
|
"imageSize": 100,
|
||||||
|
"commit": false,
|
||||||
|
"contributors": [
|
||||||
|
{
|
||||||
|
"login": "mezner",
|
||||||
|
"name": "Russell Myers",
|
||||||
|
"avatar_url": "https://avatars2.githubusercontent.com/u/184085?v=4",
|
||||||
|
"profile": "http://www.russellmyers.com",
|
||||||
|
"contributions": [
|
||||||
|
"code"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"login": "ehwarren",
|
||||||
|
"name": "Austin Warren",
|
||||||
|
"avatar_url": "https://avatars1.githubusercontent.com/u/3991658?v=4",
|
||||||
|
"profile": "http://www.morwire.com",
|
||||||
|
"contributions": [
|
||||||
|
"code"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"login": "Drachenkaetzchen",
|
||||||
|
"name": "Felicia Hummel",
|
||||||
|
"avatar_url": "https://avatars1.githubusercontent.com/u/162974?v=4",
|
||||||
|
"profile": "https://github.com/Drachenkaetzchen",
|
||||||
|
"contributions": [
|
||||||
|
"code"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"login": "mikemaccana",
|
||||||
|
"name": "Mike MacCana",
|
||||||
|
"avatar_url": "https://avatars2.githubusercontent.com/u/172594?v=4",
|
||||||
|
"profile": "https://github.com/mikemaccana",
|
||||||
|
"contributions": [
|
||||||
|
"test",
|
||||||
|
"design"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"login": "yxuko",
|
||||||
|
"name": "Yacine Kanzari",
|
||||||
|
"avatar_url": "https://avatars1.githubusercontent.com/u/1786317?v=4",
|
||||||
|
"profile": "https://github.com/yxuko",
|
||||||
|
"contributions": [
|
||||||
|
"code"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"login": "BBJip",
|
||||||
|
"name": "BBJip",
|
||||||
|
"avatar_url": "https://avatars2.githubusercontent.com/u/32908927?v=4",
|
||||||
|
"profile": "https://github.com/BBJip",
|
||||||
|
"contributions": [
|
||||||
|
"code"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"login": "Futagirl",
|
||||||
|
"name": "Futagirl",
|
||||||
|
"avatar_url": "https://avatars2.githubusercontent.com/u/33533958?v=4",
|
||||||
|
"profile": "https://github.com/Futagirl",
|
||||||
|
"contributions": [
|
||||||
|
"design"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"login": "levrik",
|
||||||
|
"name": "Levin Rickert",
|
||||||
|
"avatar_url": "https://avatars3.githubusercontent.com/u/9491603?v=4",
|
||||||
|
"profile": "https://www.levrik.io",
|
||||||
|
"contributions": [
|
||||||
|
"code"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"login": "kwonoj",
|
||||||
|
"name": "OJ Kwon",
|
||||||
|
"avatar_url": "https://avatars2.githubusercontent.com/u/1210596?v=4",
|
||||||
|
"profile": "https://kwonoj.github.io",
|
||||||
|
"contributions": [
|
||||||
|
"code"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"login": "Domain",
|
||||||
|
"name": "domain",
|
||||||
|
"avatar_url": "https://avatars2.githubusercontent.com/u/903197?v=4",
|
||||||
|
"profile": "https://github.com/Domain",
|
||||||
|
"contributions": [
|
||||||
|
"plugin",
|
||||||
|
"code"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"login": "kbjr",
|
||||||
|
"name": "James Brumond",
|
||||||
|
"avatar_url": "https://avatars1.githubusercontent.com/u/195127?v=4",
|
||||||
|
"profile": "http://www.jbrumond.me",
|
||||||
|
"contributions": [
|
||||||
|
"plugin"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"login": "Tyriar",
|
||||||
|
"name": "Daniel Imms",
|
||||||
|
"avatar_url": "https://avatars0.githubusercontent.com/u/2193314?v=4",
|
||||||
|
"profile": "http://www.growingwiththeweb.com",
|
||||||
|
"contributions": [
|
||||||
|
"code",
|
||||||
|
"plugin",
|
||||||
|
"test"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"login": "baflo",
|
||||||
|
"name": "Florian Bachmann",
|
||||||
|
"avatar_url": "https://avatars2.githubusercontent.com/u/834350?v=4",
|
||||||
|
"profile": "https://github.com/baflo",
|
||||||
|
"contributions": [
|
||||||
|
"code"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"login": "mischah",
|
||||||
|
"name": "Michael Kühnel",
|
||||||
|
"avatar_url": "https://avatars2.githubusercontent.com/u/441011?v=4",
|
||||||
|
"profile": "http://michael-kuehnel.de",
|
||||||
|
"contributions": [
|
||||||
|
"code",
|
||||||
|
"design"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"contributorsPerLine": 7,
|
||||||
|
"projectName": "terminus",
|
||||||
|
"projectOwner": "Eugeny",
|
||||||
|
"repoType": "github",
|
||||||
|
"repoHost": "https://github.com",
|
||||||
|
"commitConvention": "none"
|
||||||
|
}
|
3
.github/FUNDING.yml
vendored
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
github: eugeny
|
||||||
|
open_collective: terminus
|
||||||
|
ko_fi: eugeny
|
2
.github/stale.yml
vendored
@@ -5,7 +5,7 @@ daysUntilClose: 14
|
|||||||
# Issues with these labels will never be considered stale
|
# Issues with these labels will never be considered stale
|
||||||
exemptLabels:
|
exemptLabels:
|
||||||
- "T: Enhancement"
|
- "T: Enhancement"
|
||||||
- "S: Triaged"
|
- "S: Confirmed"
|
||||||
# Label to use when marking an issue as stale
|
# Label to use when marking an issue as stale
|
||||||
staleLabel: "S: Stale"
|
staleLabel: "S: Stale"
|
||||||
# Comment to post when marking an issue as stale. Set to `false` to disable
|
# Comment to post when marking an issue as stale. Set to `false` to disable
|
||||||
|
2
.gitignore
vendored
@@ -6,6 +6,8 @@ node_modules
|
|||||||
build/files.wxs
|
build/files.wxs
|
||||||
dist
|
dist
|
||||||
*/dist
|
*/dist
|
||||||
|
*/typings
|
||||||
|
*.tsbuildinfo
|
||||||
|
|
||||||
*.xcworkspacedata
|
*.xcworkspacedata
|
||||||
*.xcuserstate
|
*.xcuserstate
|
||||||
|
21
.travis.yml
@@ -11,29 +11,36 @@ jobs:
|
|||||||
- stage: 'Build'
|
- stage: 'Build'
|
||||||
os: linux
|
os: linux
|
||||||
before_install:
|
before_install:
|
||||||
|
- set -e
|
||||||
- yarn
|
- yarn
|
||||||
- rm app/node_modules/.yarn-integrity || true
|
- rm app/node_modules/.yarn-integrity || true
|
||||||
- scripts/install-deps.js
|
- scripts/install-deps.js
|
||||||
script:
|
script:
|
||||||
|
- set -e
|
||||||
- scripts/build-native.js
|
- scripts/build-native.js
|
||||||
|
- yarn run build:typings
|
||||||
- yarn run build
|
- yarn run build
|
||||||
- scripts/prepackage-plugins.js
|
- scripts/prepackage-plugins.js
|
||||||
- scripts/build-linux.js
|
- travis_wait scripts/build-linux.js
|
||||||
|
|
||||||
- stage: 'Build'
|
- stage: 'Build'
|
||||||
os: osx
|
os: osx
|
||||||
before_install:
|
before_install:
|
||||||
|
- set -e
|
||||||
- rm app/node_modules/.yarn-integrity || true
|
- rm app/node_modules/.yarn-integrity || true
|
||||||
- yarn
|
- yarn
|
||||||
script:
|
script:
|
||||||
|
- set -e
|
||||||
- scripts/build-native.js
|
- scripts/build-native.js
|
||||||
|
- yarn run build:typings
|
||||||
- yarn run build
|
- yarn run build
|
||||||
- scripts/prepackage-plugins.js
|
- scripts/prepackage-plugins.js
|
||||||
- scripts/build-macos.js
|
- travis_wait scripts/build-macos.js
|
||||||
|
|
||||||
- stage: 'Docs'
|
- stage: 'Docs'
|
||||||
os: linux
|
os: linux
|
||||||
script:
|
script:
|
||||||
|
- set -e
|
||||||
- openssl aes-256-cbc -K $encrypted_4e2fb4889ef8_key -iv $encrypted_4e2fb4889ef8_iv -in .travis.ssh.key.enc -out .travis.ssh.key -d
|
- openssl aes-256-cbc -K $encrypted_4e2fb4889ef8_key -iv $encrypted_4e2fb4889ef8_iv -in .travis.ssh.key.enc -out .travis.ssh.key -d
|
||||||
- eval "$(ssh-agent -s)"
|
- eval "$(ssh-agent -s)"
|
||||||
- chmod 600 .travis.ssh.key
|
- chmod 600 .travis.ssh.key
|
||||||
@@ -50,6 +57,16 @@ addons:
|
|||||||
packages:
|
packages:
|
||||||
- rpm
|
- rpm
|
||||||
- yarn
|
- yarn
|
||||||
|
- libsecret-1-dev
|
||||||
sources:
|
sources:
|
||||||
- sourceline: 'deb https://dl.yarnpkg.com/debian/ stable main'
|
- sourceline: 'deb https://dl.yarnpkg.com/debian/ stable main'
|
||||||
key_url: 'https://dl.yarnpkg.com/debian/pubkey.gpg'
|
key_url: 'https://dl.yarnpkg.com/debian/pubkey.gpg'
|
||||||
|
|
||||||
|
|
||||||
|
cache:
|
||||||
|
directories:
|
||||||
|
- node_modules
|
||||||
|
- '*/node_modules'
|
||||||
|
- $HOME/.cache/yarn
|
||||||
|
- $HOME/.cache/electron
|
||||||
|
- $HOME/.cache/electron-builder
|
||||||
|
50
README.md
@@ -1,45 +1,58 @@
|
|||||||

|

|
||||||
|
|
||||||
|
|
||||||
<p align="center">
|
<p align="center">
|
||||||
<a href="https://raw.githubusercontent.com/Eugeny/terminus/master/LICENSE"><img src="https://img.shields.io/badge/license-MIT-blue.svg"/></a> <a href="https://travis-ci.org/Eugeny/terminus"><img src="https://travis-ci.org/Eugeny/terminus.svg?branch=master"/></a>
|
<a href="https://raw.githubusercontent.com/Eugeny/terminus/master/LICENSE"><img alt="GitHub" src="https://img.shields.io/github/license/eugeny/terminus.svg?label=License&style=flat-square"></a> <a href="https://travis-ci.org/Eugeny/terminus"><img alt="Travis (.org)" src="https://img.shields.io/travis/Eugeny/terminus.svg?label=CI&logo=travis&logoColor=white&style=flat-square"></a>
|
||||||
<a href="https://ci.appveyor.com/project/Eugeny/terminus"><img src="https://ci.appveyor.com/api/projects/status/wnnq4hm5mbd9rgoy?svg=true"/></a>
|
<a href="https://ci.appveyor.com/project/Eugeny/terminus"><img alt="AppVeyor" src="https://img.shields.io/appveyor/ci/eugeny/terminus.svg?label=CI&logo=appveyor&logoColor=white&style=flat-square"></a>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p align="center">
|
<p align="center">
|
||||||
<a href="https://github.com/Eugeny/terminus/releases/latest">Downloads</a> | <a href="https://gitter.im/terminus-terminal/community">Community</a> | <a href="https://ci.appveyor.com/project/Eugeny/terminus/build/artifacts">Latest Windows nightly</a>
|
<a href="https://github.com/Eugeny/terminus/releases/latest"><img alt="GitHub All Releases" src="https://img.shields.io/github/downloads/eugeny/terminus/total.svg?label=DOWNLOAD&logo=github&style=for-the-badge"></a> <a href="https://ci.appveyor.com/project/Eugeny/terminus/build/artifacts"><img src="https://img.shields.io/badge/download-nightly%20build-magenta.svg?logo=appveyor&style=for-the-badge"/></a> <a href="https://gitter.im/terminus-terminal/community"><img alt="Gitter" src="https://img.shields.io/gitter/room/terminus/community.svg?color=blue&logo=gitter&style=for-the-badge"></a>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
----
|
----
|
||||||
|
|
||||||
**Terminus** is a terminal heavily inspired by Hyper. It is, however, designed for people who need to get things done.
|
**Terminus** is a highly configurable terminal emulator for Windows, macOS and Linux
|
||||||
|
|
||||||
* Runs on Windows, macOS and Linux
|
|
||||||
* Theming and color schemes
|
* Theming and color schemes
|
||||||
* Fully configurable shortcuts
|
* Fully configurable shortcuts
|
||||||
|
* Split panes
|
||||||
|
* Remembers your tabs
|
||||||
|
* PowerShell (and PS Core), WSL, Git-Bash, Cygwin, Cmder and CMD support
|
||||||
|
* Integrated SSH client and connection manager
|
||||||
* Full Unicode support including double-width characters
|
* Full Unicode support including double-width characters
|
||||||
* Doesn't choke on fast-flowing outputs
|
* Doesn't choke on fast-flowing outputs
|
||||||
* Proper shell-like experience on Windows including tab completion (via Clink)
|
* Proper shell experience on Windows including tab completion (via Clink)
|
||||||
* PowerShell (+Core), WSL (Bash on Windows), Git-Bash, Cygwin, Cmder and CMD support
|
|
||||||
* Remembers your tabs
|
|
||||||
* Integrated SSH client and connection manager
|
|
||||||
|
|
||||||
|
|
||||||
[](https://ko-fi.com/eugeny)
|
[](https://ko-fi.com/eugeny)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
* **Terminus is** an alternative to Windows' standard terminal (conhost), PowerShell ISE, PuTTY or iTerm
|
||||||
|
|
||||||
|
* **Terminus is not** a new shell or a MinGW or Cygwin replacement. Neither is it lightweight - if RAM usage is of importance, consider [Conemu](https://conemu.github.io) or [Alacritty](https://github.com/jwilm/alacritty)
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
# Plugins
|
# Plugins
|
||||||
|
|
||||||
Plugins can be installed directly from the Settings view inside Terminus.
|
Plugins and themes can be installed directly from the Settings view inside Terminus.
|
||||||
|
|
||||||
* [clickable-links](https://github.com/Eugeny/terminus-clickable-links) - makes paths and URLs in the terminal clickable
|
* [clickable-links](https://github.com/Eugeny/terminus-clickable-links) - makes paths and URLs in the terminal clickable
|
||||||
* [theme-hype](https://github.com/Eugeny/terminus-theme-hype) - a Hyper inspired theme
|
|
||||||
* [shell-selector](https://github.com/Eugeny/terminus-shell-selector) - a quick shell selector pane
|
* [shell-selector](https://github.com/Eugeny/terminus-shell-selector) - a quick shell selector pane
|
||||||
* [title-control](https://github.com/kbjr/terminus-title-control) - allows modifying the title of the terminal tabs by providing a prefix, suffix, and/or strings to be removed
|
* [title-control](https://github.com/kbjr/terminus-title-control) - allows modifying the title of the terminal tabs by providing a prefix, suffix, and/or strings to be removed
|
||||||
* [scrollbar](https://github.com/kbjr/terminus-scrollbar) - adds a scrollbar to terminal tabs
|
|
||||||
* [quick-cmds](https://github.com/Domain/terminus-quick-cmds) - quickly send commands to one or all terminal tabs
|
* [quick-cmds](https://github.com/Domain/terminus-quick-cmds) - quickly send commands to one or all terminal tabs
|
||||||
* [save-output](https://github.com/Eugeny/terminus-save-output) - record terminal output into a file
|
* [save-output](https://github.com/Eugeny/terminus-save-output) - record terminal output into a file
|
||||||
|
* [scrollbar](https://github.com/kbjr/terminus-scrollbar) - adds a scrollbar to hterm tabs
|
||||||
|
|
||||||
|
# Themes
|
||||||
|
|
||||||
|
* [hype](https://github.com/Eugeny/terminus-theme-hype) - a Hyper inspired theme
|
||||||
|
* [relaxed](https://github.com/Relaxed-Theme/relaxed-terminal-themes#terminus) - the Relaxed theme for Terminus
|
||||||
|
* [gruvbox](https://github.com/porkloin/terminus-theme-gruvbox)
|
||||||
|
* [windows10](https://www.npmjs.com/package/terminus-theme-windows10)
|
||||||
|
* [altair](https://github.com/yxuko/terminus-altair)
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -49,5 +62,14 @@ Pull requests and plugins are welcome!
|
|||||||
|
|
||||||
See [HACKING.md](https://github.com/Eugeny/terminus/blob/master/HACKING.md) and [API docs](http://ajenti.org/terminus-docs/) for information of how the project is laid out, and a very brief plugin development tutorial.
|
See [HACKING.md](https://github.com/Eugeny/terminus/blob/master/HACKING.md) and [API docs](http://ajenti.org/terminus-docs/) for information of how the project is laid out, and a very brief plugin development tutorial.
|
||||||
|
|
||||||
## License
|
---
|
||||||
[](https://app.fossa.io/projects/git%2Bhttps%3A%2F%2Fgithub.com%2FEugeny%2Fterminus?ref=badge_large)
|
|
||||||
|
Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/docs/en/emoji-key)):
|
||||||
|
|
||||||
|
<!-- ALL-CONTRIBUTORS-LIST:START - Do not remove or modify this section -->
|
||||||
|
<!-- prettier-ignore -->
|
||||||
|
<table><tr><td align="center"><a href="http://www.russellmyers.com"><img src="https://avatars2.githubusercontent.com/u/184085?v=4" width="100px;" alt="Russell Myers"/><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="Austin Warren"/><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="Felicia Hummel"/><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="Mike MacCana"/><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="Yacine Kanzari"/><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="BBJip"/><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="Futagirl"/><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="Levin Rickert"/><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="OJ Kwon"/><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="domain"/><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="James Brumond"/><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="Daniel Imms"/><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></tr></table>
|
||||||
|
|
||||||
|
<!-- ALL-CONTRIBUTORS-LIST:END -->
|
||||||
|
|
||||||
|
This project follows the [all-contributors](https://github.com/all-contributors/all-contributors) specification. Contributions of any kind welcome!
|
||||||
|
BIN
app/assets/activity.png
Normal file
After Width: | Height: | Size: 4.9 KiB |
4
app/dev-app-update.yml
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
owner: eugeny
|
||||||
|
repo: terminus
|
||||||
|
provider: github
|
||||||
|
updaterCacheDirName: terminus-updater
|
@@ -1,9 +1,8 @@
|
|||||||
import './lru'
|
import './lru'
|
||||||
import { app, ipcMain, Menu } from 'electron'
|
import { app, ipcMain, Menu } from 'electron'
|
||||||
import electronDebug = require('electron-debug')
|
|
||||||
import { parseArgs } from './cli'
|
import { parseArgs } from './cli'
|
||||||
import { Application } from './app'
|
import { Application } from './app'
|
||||||
if (process.platform === 'win32' && require('electron-squirrel-startup')) process.exit(0)
|
import electronDebug = require('electron-debug')
|
||||||
|
|
||||||
if (!process.env.TERMINUS_PLUGINS) {
|
if (!process.env.TERMINUS_PLUGINS) {
|
||||||
process.env.TERMINUS_PLUGINS = ''
|
process.env.TERMINUS_PLUGINS = ''
|
||||||
@@ -44,7 +43,11 @@ if (!app.requestSingleInstanceLock()) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (argv.d) {
|
if (argv.d) {
|
||||||
electronDebug({ enabled: true, showDevTools: 'undocked' })
|
electronDebug({
|
||||||
|
isEnabled: true,
|
||||||
|
showDevTools: true,
|
||||||
|
devToolsMode: 'undocked'
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
app.on('ready', () => {
|
app.on('ready', () => {
|
||||||
|
@@ -20,25 +20,27 @@
|
|||||||
"@angular/forms": "7.2.8",
|
"@angular/forms": "7.2.8",
|
||||||
"@angular/platform-browser": "7.2.8",
|
"@angular/platform-browser": "7.2.8",
|
||||||
"@angular/platform-browser-dynamic": "7.2.8",
|
"@angular/platform-browser-dynamic": "7.2.8",
|
||||||
"@ng-bootstrap/ng-bootstrap": "^3.3.1",
|
"@ng-bootstrap/ng-bootstrap": "^4.2.0",
|
||||||
"devtron": "1.4.0",
|
"devtron": "1.4.0",
|
||||||
"electron-config": "0.2.1",
|
"electron-config": "2.0.0",
|
||||||
"electron-debug": "^2.0.0",
|
"electron-debug": "^3.0.0",
|
||||||
"electron-is-dev": "0.1.2",
|
"electron-is-dev": "1.1.0",
|
||||||
"electron-squirrel-startup": "^1.0.0",
|
"electron-updater": "^4.0.6",
|
||||||
"js-yaml": "3.8.2",
|
"js-yaml": "3.13.1",
|
||||||
"mz": "^2.6.0",
|
"mz": "^2.7.0",
|
||||||
"ngx-toastr": "^9.1.1",
|
"ngx-toastr": "^9.1.1",
|
||||||
|
"npm": "~6.9.0",
|
||||||
"path": "0.12.7",
|
"path": "0.12.7",
|
||||||
"rxjs": "^6.3.3",
|
"rxjs": "^6.5.2",
|
||||||
"yargs": "^12.0.1",
|
"rxjs-compat": "^6.5.2",
|
||||||
"zone.js": "^0.8.26"
|
"yargs": "^13.2.4",
|
||||||
|
"zone.js": "^0.8.29"
|
||||||
},
|
},
|
||||||
"optionalDependencies": {
|
"optionalDependencies": {
|
||||||
"windows-blurbehind": "^1.0.0",
|
"windows-blurbehind": "^1.0.1",
|
||||||
"windows-swca": "^2.0.1"
|
"windows-swca": "^2.0.2"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/mz": "0.0.31"
|
"@types/mz": "0.0.32"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
import '../lib/lru'
|
import '../lib/lru'
|
||||||
import 'source-sans-pro'
|
import 'source-sans-pro/source-sans-pro.css'
|
||||||
import 'source-code-pro/source-code-pro.css'
|
import 'source-code-pro/source-code-pro.css'
|
||||||
import '@fortawesome/fontawesome-free/css/solid.css'
|
import '@fortawesome/fontawesome-free/css/solid.css'
|
||||||
import '@fortawesome/fontawesome-free/css/brands.css'
|
import '@fortawesome/fontawesome-free/css/brands.css'
|
||||||
|
@@ -1,8 +1,9 @@
|
|||||||
import 'zone.js'
|
import 'zone.js'
|
||||||
import 'core-js/es7/reflect'
|
import 'core-js/proposals/reflect-metadata'
|
||||||
import 'core-js/core/delay'
|
|
||||||
import 'rxjs'
|
import 'rxjs'
|
||||||
|
|
||||||
|
import isDev = require('electron-is-dev')
|
||||||
|
|
||||||
import './global.scss'
|
import './global.scss'
|
||||||
import './toastr.scss'
|
import './toastr.scss'
|
||||||
|
|
||||||
@@ -21,7 +22,7 @@ if (process.platform === 'win32') {
|
|||||||
process.env.HOME = process.env.HOMEDRIVE + process.env.HOMEPATH
|
process.env.HOME = process.env.HOMEDRIVE + process.env.HOMEPATH
|
||||||
}
|
}
|
||||||
|
|
||||||
if (require('electron-is-dev')) {
|
if (isDev) {
|
||||||
console.warn('Running in debug mode')
|
console.warn('Running in debug mode')
|
||||||
} else {
|
} else {
|
||||||
enableProdMode()
|
enableProdMode()
|
||||||
|
@@ -3,8 +3,6 @@ import * as path from 'path'
|
|||||||
const nodeModule = require('module')
|
const nodeModule = require('module')
|
||||||
const nodeRequire = (global as any).require
|
const nodeRequire = (global as any).require
|
||||||
|
|
||||||
declare function delay (ms: number): Promise<void>
|
|
||||||
|
|
||||||
function normalizePath (path: string): string {
|
function normalizePath (path: string): string {
|
||||||
const cygwinPrefix = '/cygdrive/'
|
const cygwinPrefix = '/cygdrive/'
|
||||||
if (path.startsWith(cygwinPrefix)) {
|
if (path.startsWith(cygwinPrefix)) {
|
||||||
@@ -28,6 +26,10 @@ const userPluginsPath = path.join(
|
|||||||
'plugins',
|
'plugins',
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if (!fs.existsSync(userPluginsPath)) {
|
||||||
|
fs.mkdir(userPluginsPath)
|
||||||
|
}
|
||||||
|
|
||||||
Object.assign(window, { builtinPluginsPath, userPluginsPath })
|
Object.assign(window, { builtinPluginsPath, userPluginsPath })
|
||||||
nodeModule.globalPaths.unshift(builtinPluginsPath)
|
nodeModule.globalPaths.unshift(builtinPluginsPath)
|
||||||
nodeModule.globalPaths.unshift(path.join(userPluginsPath, 'node_modules'))
|
nodeModule.globalPaths.unshift(path.join(userPluginsPath, 'node_modules'))
|
||||||
@@ -62,6 +64,7 @@ const builtinModules = [
|
|||||||
'ngx-toastr',
|
'ngx-toastr',
|
||||||
'rxjs',
|
'rxjs',
|
||||||
'rxjs/operators',
|
'rxjs/operators',
|
||||||
|
'rxjs-compat/Subject',
|
||||||
'terminus-core',
|
'terminus-core',
|
||||||
'terminus-settings',
|
'terminus-settings',
|
||||||
'terminus-terminal',
|
'terminus-terminal',
|
||||||
@@ -70,11 +73,14 @@ const builtinModules = [
|
|||||||
|
|
||||||
const cachedBuiltinModules = {}
|
const cachedBuiltinModules = {}
|
||||||
builtinModules.forEach(m => {
|
builtinModules.forEach(m => {
|
||||||
|
const label = 'Caching ' + m
|
||||||
|
console.time(label)
|
||||||
cachedBuiltinModules[m] = nodeRequire(m)
|
cachedBuiltinModules[m] = nodeRequire(m)
|
||||||
|
console.timeEnd(label)
|
||||||
})
|
})
|
||||||
|
|
||||||
const originalRequire = nodeRequire('module').prototype.require
|
const originalRequire = (global as any).require
|
||||||
nodeRequire('module').prototype.require = function (query) {
|
;(global as any).require = function (query) {
|
||||||
if (cachedBuiltinModules[query]) {
|
if (cachedBuiltinModules[query]) {
|
||||||
return cachedBuiltinModules[query]
|
return cachedBuiltinModules[query]
|
||||||
}
|
}
|
||||||
@@ -85,6 +91,7 @@ export async function findPlugins (): Promise<IPluginInfo[]> {
|
|||||||
let paths = nodeModule.globalPaths
|
let paths = nodeModule.globalPaths
|
||||||
let foundPlugins: IPluginInfo[] = []
|
let foundPlugins: IPluginInfo[] = []
|
||||||
let candidateLocations: { pluginDir: string, packageName: string }[] = []
|
let candidateLocations: { pluginDir: string, packageName: string }[] = []
|
||||||
|
const PREFIX = 'terminus-'
|
||||||
|
|
||||||
for (let pluginDir of paths) {
|
for (let pluginDir of paths) {
|
||||||
pluginDir = normalizePath(pluginDir)
|
pluginDir = normalizePath(pluginDir)
|
||||||
@@ -99,7 +106,9 @@ export async function findPlugins (): Promise<IPluginInfo[]> {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
for (let packageName of pluginNames) {
|
for (let packageName of pluginNames) {
|
||||||
candidateLocations.push({ pluginDir, packageName })
|
if (packageName.startsWith(PREFIX)) {
|
||||||
|
candidateLocations.push({ pluginDir, packageName })
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -110,7 +119,7 @@ export async function findPlugins (): Promise<IPluginInfo[]> {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
let name = packageName.substring('terminus-'.length)
|
let name = packageName.substring(PREFIX.length)
|
||||||
|
|
||||||
if (foundPlugins.some(x => x.name === name)) {
|
if (foundPlugins.some(x => x.name === name)) {
|
||||||
console.info(`Plugin ${packageName} already exists, overriding`)
|
console.info(`Plugin ${packageName} already exists, overriding`)
|
||||||
@@ -151,15 +160,17 @@ export async function loadPlugins (foundPlugins: IPluginInfo[], progress: Progre
|
|||||||
console.info(`Loading ${foundPlugin.name}: ${nodeRequire.resolve(foundPlugin.path)}`)
|
console.info(`Loading ${foundPlugin.name}: ${nodeRequire.resolve(foundPlugin.path)}`)
|
||||||
progress(index, foundPlugins.length)
|
progress(index, foundPlugins.length)
|
||||||
try {
|
try {
|
||||||
|
const label = 'Loading ' + foundPlugin.name
|
||||||
|
console.time(label)
|
||||||
let packageModule = nodeRequire(foundPlugin.path)
|
let packageModule = nodeRequire(foundPlugin.path)
|
||||||
let pluginModule = packageModule.default.forRoot ? packageModule.default.forRoot() : packageModule.default
|
let pluginModule = packageModule.default.forRoot ? packageModule.default.forRoot() : packageModule.default
|
||||||
pluginModule['pluginName'] = foundPlugin.name
|
pluginModule['pluginName'] = foundPlugin.name
|
||||||
pluginModule['bootstrap'] = packageModule.bootstrap
|
pluginModule['bootstrap'] = packageModule.bootstrap
|
||||||
plugins.push(pluginModule)
|
plugins.push(pluginModule)
|
||||||
|
console.timeEnd(label)
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(`Could not load ${foundPlugin.name}:`, error)
|
console.error(`Could not load ${foundPlugin.name}:`, error)
|
||||||
}
|
}
|
||||||
await delay(1)
|
|
||||||
index++
|
index++
|
||||||
}
|
}
|
||||||
progress(1, 1)
|
progress(1, 1)
|
||||||
|
@@ -5,7 +5,7 @@ module.exports = {
|
|||||||
name: 'terminus',
|
name: 'terminus',
|
||||||
target: 'node',
|
target: 'node',
|
||||||
entry: {
|
entry: {
|
||||||
'index.ignore': 'file-loader?name=index.html!val-loader!pug-html-loader!' + path.resolve(__dirname, './index.pug'),
|
'index.ignore': 'file-loader?name=index.html!pug-html-loader!' + path.resolve(__dirname, './index.pug'),
|
||||||
preload: path.resolve(__dirname, 'src/entry.preload.ts'),
|
preload: path.resolve(__dirname, 'src/entry.preload.ts'),
|
||||||
bundle: path.resolve(__dirname, 'src/entry.ts'),
|
bundle: path.resolve(__dirname, 'src/entry.ts'),
|
||||||
},
|
},
|
||||||
@@ -14,7 +14,7 @@ module.exports = {
|
|||||||
minimize: false,
|
minimize: false,
|
||||||
},
|
},
|
||||||
context: __dirname,
|
context: __dirname,
|
||||||
devtool: 'source-map',
|
devtool: 'eval-source-map',
|
||||||
output: {
|
output: {
|
||||||
path: path.join(__dirname, 'dist'),
|
path: path.join(__dirname, 'dist'),
|
||||||
pathinfo: true,
|
pathinfo: true,
|
||||||
|
@@ -9,7 +9,7 @@ module.exports = {
|
|||||||
},
|
},
|
||||||
mode: process.env.TERMINUS_DEV ? 'development' : 'production',
|
mode: process.env.TERMINUS_DEV ? 'development' : 'production',
|
||||||
context: __dirname,
|
context: __dirname,
|
||||||
devtool: 'source-map',
|
devtool: 'eval-source-map',
|
||||||
output: {
|
output: {
|
||||||
path: path.join(__dirname, 'dist'),
|
path: path.join(__dirname, 'dist'),
|
||||||
pathinfo: true,
|
pathinfo: true,
|
||||||
@@ -36,7 +36,6 @@ module.exports = {
|
|||||||
electron: 'commonjs electron',
|
electron: 'commonjs electron',
|
||||||
'electron-config': 'commonjs electron-config',
|
'electron-config': 'commonjs electron-config',
|
||||||
'electron-vibrancy': 'commonjs electron-vibrancy',
|
'electron-vibrancy': 'commonjs electron-vibrancy',
|
||||||
'electron-squirrel-startup': 'commonjs electron-squirrel-startup',
|
|
||||||
fs: 'commonjs fs',
|
fs: 'commonjs fs',
|
||||||
mz: 'commonjs mz',
|
mz: 'commonjs mz',
|
||||||
path: 'commonjs path',
|
path: 'commonjs path',
|
||||||
|
3054
app/yarn.lock
13
appveyor.yml
@@ -6,10 +6,6 @@ platform:
|
|||||||
environment:
|
environment:
|
||||||
nodejs_version: "10"
|
nodejs_version: "10"
|
||||||
|
|
||||||
cache:
|
|
||||||
- "%USERPROFILE%\\.electron"
|
|
||||||
- "%LOCALAPPDATA%\\Yarn"
|
|
||||||
|
|
||||||
version: "{build}"
|
version: "{build}"
|
||||||
|
|
||||||
install:
|
install:
|
||||||
@@ -18,11 +14,16 @@ install:
|
|||||||
- node scripts/build-native.js
|
- node scripts/build-native.js
|
||||||
|
|
||||||
build_script:
|
build_script:
|
||||||
|
- yarn run build:typings
|
||||||
- yarn run build
|
- yarn run build
|
||||||
- node scripts/prepackage-plugins.js
|
- node scripts/prepackage-plugins.js
|
||||||
- node scripts/build-windows.js
|
- node scripts/build-windows.js
|
||||||
|
|
||||||
artifacts:
|
artifacts:
|
||||||
- path: 'dist\win\*.exe'
|
|
||||||
- path: 'dist\squirrel-windows\*.exe'
|
|
||||||
- path: 'dist\*.exe'
|
- path: 'dist\*.exe'
|
||||||
|
|
||||||
|
cache:
|
||||||
|
- node_modules
|
||||||
|
- "*\\node_modules"
|
||||||
|
- "%USERPROFILE%\\.electron"
|
||||||
|
- "%LOCALAPPDATA%\\Yarn"
|
||||||
|
Before Width: | Height: | Size: 9.8 KiB After Width: | Height: | Size: 8.9 KiB |
Before Width: | Height: | Size: 2.2 KiB After Width: | Height: | Size: 950 B |
Before Width: | Height: | Size: 21 KiB After Width: | Height: | Size: 20 KiB |
Before Width: | Height: | Size: 3.0 KiB After Width: | Height: | Size: 1.7 KiB |
Before Width: | Height: | Size: 5.2 KiB After Width: | Height: | Size: 3.9 KiB |
3
build/installer.nsh
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
!macro customInit
|
||||||
|
nsExec::Exec '"$LOCALAPPDATA\terminus\Update.exe" --uninstall -s'
|
||||||
|
!macroend
|
BIN
extras/UAC.exe
118
package.json
@@ -1,61 +1,59 @@
|
|||||||
{
|
{
|
||||||
"name": "term",
|
"name": "term",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@fortawesome/fontawesome-free": "^5.6.3",
|
"@fortawesome/fontawesome-free": "^5.9.0",
|
||||||
"@types/electron-config": "^0.2.1",
|
"@types/electron-config": "^3.2.2",
|
||||||
"@types/electron-debug": "^1.1.0",
|
"@types/electron-debug": "^2.1.0",
|
||||||
"@types/fs-promise": "1.0.1",
|
"@types/fs-promise": "1.0.3",
|
||||||
"@types/js-yaml": "^3.11.2",
|
"@types/js-yaml": "^3.12.1",
|
||||||
"@types/node": "^10.11.5",
|
"@types/node": "^12.0.7",
|
||||||
"@types/webpack-env": "1.13.0",
|
"@types/webpack-env": "1.13.9",
|
||||||
"app-builder-lib": "^20.28.4",
|
"app-builder-lib": "^20.43.0",
|
||||||
"apply-loader": "0.1.0",
|
"apply-loader": "2.0.0",
|
||||||
"awesome-typescript-loader": "^5.0.0",
|
"awesome-typescript-loader": "^5.0.0",
|
||||||
"core-js": "2.4.1",
|
"core-js": "^3.1.3",
|
||||||
"cross-env": "4.0.0",
|
"cross-env": "5.2.0",
|
||||||
"css-loader": "0.28.0",
|
"css-loader": "2.1.1",
|
||||||
"electron": "4.0.5",
|
"electron": "^5.0.2",
|
||||||
"electron-builder": "^20.38.4",
|
"electron-builder": "^20.43.0",
|
||||||
"electron-builder-squirrel-windows": "^20.28.3",
|
"electron-installer-snap": "^3.2.0",
|
||||||
"electron-installer-snap": "^3.0.0",
|
"electron-rebuild": "^1.8.5",
|
||||||
"electron-rebuild": "^1.8.2",
|
"file-loader": "^4.0.0",
|
||||||
"file-loader": "^1.1.11",
|
"graceful-fs": "^4.1.15",
|
||||||
"graceful-fs": "^4.1.11",
|
"html-loader": "0.5.5",
|
||||||
"html-loader": "0.4.4",
|
"json-loader": "0.5.7",
|
||||||
"json-loader": "0.5.4",
|
"node-abi": "^2.8.0",
|
||||||
"node-abi": "^2.4.4",
|
"node-gyp": "^4.0.0",
|
||||||
"node-gyp": "^3.8.0",
|
"node-sass": "^4.12.0",
|
||||||
"node-sass": "^4.5.3",
|
"npmlog": "4.1.2",
|
||||||
"npmlog": "4.1.0",
|
|
||||||
"npx": "^10.2.0",
|
"npx": "^10.2.0",
|
||||||
"pug": "^2.0.3",
|
"pug": "^2.0.3",
|
||||||
"pug-html-loader": "1.0.9",
|
"pug-html-loader": "1.1.5",
|
||||||
"pug-lint": "^2.5.0",
|
"pug-lint": "^2.5.0",
|
||||||
"pug-loader": "^2.4.0",
|
"pug-loader": "^2.4.0",
|
||||||
"pug-static-loader": "0.0.1",
|
"pug-static-loader": "2.0.0",
|
||||||
"raven-js": "3.16.0",
|
"raven-js": "3.27.2",
|
||||||
"raw-loader": "0.5.1",
|
"raw-loader": "3.0.0",
|
||||||
"sass-loader": "^7.0.1",
|
"sass-loader": "^7.0.1",
|
||||||
"shelljs": "0.7.7",
|
"shelljs": "0.8.3",
|
||||||
"source-code-pro": "^2.30.1",
|
"source-code-pro": "^2.30.1",
|
||||||
"source-sans-pro": "2.0.10",
|
"source-sans-pro": "2.45.0",
|
||||||
"style-loader": "^0.23.1",
|
"style-loader": "^0.23.1",
|
||||||
"svg-inline-loader": "^0.8.0",
|
"svg-inline-loader": "^0.8.0",
|
||||||
"to-string-loader": "1.1.5",
|
"to-string-loader": "1.1.5",
|
||||||
"tslint": "^5.12.0",
|
"tslint": "^5.17.0",
|
||||||
"tslint-config-standard": "^8.0.1",
|
"tslint-config-standard": "^8.0.1",
|
||||||
"tslint-eslint-rules": "^5.4.0",
|
"tslint-eslint-rules": "^5.4.0",
|
||||||
"typedoc": "^0.14.2",
|
"typedoc": "^0.14.2",
|
||||||
"typescript": "^3.1.3",
|
"typescript": "^3.5.1",
|
||||||
"url-loader": "^1.1.1",
|
"url-loader": "^1.1.1",
|
||||||
"val-loader": "0.5.0",
|
"val-loader": "1.1.1",
|
||||||
"webpack": "^4.27.1",
|
"webpack": "^4.33.0",
|
||||||
"webpack-cli": "^3.1.2",
|
"webpack-cli": "^3.3.2",
|
||||||
"yaml-loader": "0.4.0",
|
"yaml-loader": "0.5.0"
|
||||||
"yarn": "^1.10.1"
|
|
||||||
},
|
},
|
||||||
"resolutions": {
|
"resolutions": {
|
||||||
"*/node-abi": "^2.5.0"
|
"*/node-abi": "^2.8.0"
|
||||||
},
|
},
|
||||||
"build": {
|
"build": {
|
||||||
"appId": "org.terminus",
|
"appId": "org.terminus",
|
||||||
@@ -71,16 +69,24 @@
|
|||||||
],
|
],
|
||||||
"win": {
|
"win": {
|
||||||
"icon": "./build/windows/icon.ico",
|
"icon": "./build/windows/icon.ico",
|
||||||
"publish": [
|
"artifactName": "terminus-${version}-setup.exe",
|
||||||
"github"
|
"rfc3161TimeStampServer": "http://sha256timestamp.ws.symantec.com/sha256/timestamp"
|
||||||
],
|
|
||||||
"artifactName": "terminus-${version}-setup.exe"
|
|
||||||
},
|
},
|
||||||
"squirrelWindows": {
|
"nsis": {
|
||||||
"iconUrl": "https://github.com/Eugeny/terminus/raw/master/build/windows/icon.ico",
|
"oneClick": false,
|
||||||
"loadingGif": "./build/windows/squirrel.gif",
|
"artifactName": "terminus-${version}-setup.${ext}",
|
||||||
"artifactName": "terminus-${version}-setup.exe"
|
"installerIcon": "./build/windows/icon.ico"
|
||||||
},
|
},
|
||||||
|
"publish": [
|
||||||
|
{
|
||||||
|
"provider": "bintray",
|
||||||
|
"token": "d993c4faa708a4cba84fa3a8e822457e7298d75c",
|
||||||
|
"component": "main"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"provider": "github"
|
||||||
|
}
|
||||||
|
],
|
||||||
"portable": {
|
"portable": {
|
||||||
"artifactName": "terminus-${version}-portable.exe"
|
"artifactName": "terminus-${version}-portable.exe"
|
||||||
},
|
},
|
||||||
@@ -88,9 +94,6 @@
|
|||||||
"category": "public.app-category.video",
|
"category": "public.app-category.video",
|
||||||
"icon": "./build/mac/icon.icns",
|
"icon": "./build/mac/icon.icns",
|
||||||
"artifactName": "terminus-${version}-macos.${ext}",
|
"artifactName": "terminus-${version}-macos.${ext}",
|
||||||
"publish": [
|
|
||||||
"github"
|
|
||||||
],
|
|
||||||
"extendInfo": {
|
"extendInfo": {
|
||||||
"NSRequiresAquaSystemAppearance": false
|
"NSRequiresAquaSystemAppearance": false
|
||||||
}
|
}
|
||||||
@@ -101,21 +104,17 @@
|
|||||||
"linux": {
|
"linux": {
|
||||||
"category": "Utilities",
|
"category": "Utilities",
|
||||||
"icon": "./build/icons",
|
"icon": "./build/icons",
|
||||||
"artifactName": "terminus-${version}-linux.${ext}",
|
"artifactName": "terminus-${version}-linux.${ext}"
|
||||||
"publish": [
|
|
||||||
"github"
|
|
||||||
]
|
|
||||||
},
|
},
|
||||||
"deb": {
|
"deb": {
|
||||||
"depends": [
|
"depends": [
|
||||||
"screen",
|
|
||||||
"gconf2",
|
"gconf2",
|
||||||
"gconf-service",
|
"gconf-service",
|
||||||
"libnotify4",
|
"libnotify4",
|
||||||
|
"libsecret-1-0",
|
||||||
"libappindicator1",
|
"libappindicator1",
|
||||||
"libxtst6",
|
"libxtst6",
|
||||||
"libnss3",
|
"libnss3"
|
||||||
"tmux"
|
|
||||||
],
|
],
|
||||||
"afterInstall": "build/linux/after-install.tpl"
|
"afterInstall": "build/linux/after-install.tpl"
|
||||||
},
|
},
|
||||||
@@ -127,11 +126,12 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "webpack --color --config app/webpack.main.config.js && webpack --color --config app/webpack.config.js && webpack --color --config terminus-core/webpack.config.js && webpack --color --config terminus-settings/webpack.config.js && webpack --color --config terminus-terminal/webpack.config.js && webpack --color --config terminus-settings/webpack.config.js && webpack --color --config terminus-plugin-manager/webpack.config.js && webpack --color --config terminus-community-color-schemes/webpack.config.js && webpack --color --config terminus-ssh/webpack.config.js",
|
"build": "webpack --color --config app/webpack.main.config.js && webpack --color --config app/webpack.config.js && webpack --color --config terminus-core/webpack.config.js && webpack --color --config terminus-settings/webpack.config.js && webpack --color --config terminus-terminal/webpack.config.js && webpack --color --config terminus-plugin-manager/webpack.config.js && webpack --color --config terminus-community-color-schemes/webpack.config.js && webpack --color --config terminus-ssh/webpack.config.js",
|
||||||
|
"build:typings": "tsc --project terminus-core/tsconfig.typings.json && tsc --project terminus-settings/tsconfig.typings.json && tsc --project terminus-terminal/tsconfig.typings.json && tsc --project terminus-plugin-manager/tsconfig.typings.json && tsc --project terminus-ssh/tsconfig.typings.json",
|
||||||
"watch": "cross-env TERMINUS_DEV=1 webpack --progress --color --watch",
|
"watch": "cross-env TERMINUS_DEV=1 webpack --progress --color --watch",
|
||||||
"start": "cross-env TERMINUS_DEV=1 electron app --debug",
|
"start": "cross-env TERMINUS_DEV=1 electron app --debug",
|
||||||
"prod": "cross-env TERMINUS_DEV=1 electron app",
|
"prod": "cross-env TERMINUS_DEV=1 electron app",
|
||||||
"docs": "typedoc --out docs/api terminus-core/src && typedoc --out docs/api/terminal terminus-terminal/src && typedoc --out docs/api/settings terminus-settings/src",
|
"docs": "typedoc --out docs/api terminus-core/src && typedoc --out docs/api/terminal --tsconfig terminus-terminal/tsconfig.typings.json terminus-terminal/src && typedoc --out docs/api/settings --tsconfig terminus-settings/tsconfig.typings.json terminus-settings/src",
|
||||||
"lint": "tslint -c tslint.json -t stylish terminus-*/src/**/*.ts terminus-*/src/*.ts app/src/*.ts",
|
"lint": "tslint -c tslint.json -t stylish terminus-*/src/**/*.ts terminus-*/src/*.ts app/src/*.ts",
|
||||||
"postinstall": "node ./scripts/install-deps.js"
|
"postinstall": "node ./scripts/install-deps.js"
|
||||||
},
|
},
|
||||||
|
@@ -4,7 +4,7 @@ const path = require('path')
|
|||||||
const vars = require('./vars')
|
const vars = require('./vars')
|
||||||
|
|
||||||
lifecycles = []
|
lifecycles = []
|
||||||
for (let dir of ['app', 'terminus-ssh', 'terminus-terminal']) {
|
for (let dir of ['app', 'terminus-core', 'terminus-ssh', 'terminus-terminal']) {
|
||||||
lifecycles.push([rebuild({
|
lifecycles.push([rebuild({
|
||||||
buildPath: path.resolve(__dirname, '../' + dir),
|
buildPath: path.resolve(__dirname, '../' + dir),
|
||||||
electronVersion: vars.electronVersion,
|
electronVersion: vars.electronVersion,
|
||||||
|
@@ -4,7 +4,7 @@ const vars = require('./vars')
|
|||||||
|
|
||||||
builder({
|
builder({
|
||||||
dir: true,
|
dir: true,
|
||||||
win: ['squirrel', 'portable'],
|
win: ['nsis', 'portable'],
|
||||||
config: {
|
config: {
|
||||||
extraMetadata: {
|
extraMetadata: {
|
||||||
version: vars.version,
|
version: vars.version,
|
||||||
|
26
snap/snapcraft.yaml
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
name: terminus
|
||||||
|
version: '1.0.0'
|
||||||
|
summary: A terminal for a modern age
|
||||||
|
description: |
|
||||||
|
Terminus is a terminal heavily inspired by Hyper. It is, however, designed for people who need to get things done.
|
||||||
|
|
||||||
|
grade: devel
|
||||||
|
confinement: devmode
|
||||||
|
|
||||||
|
apps:
|
||||||
|
terminus:
|
||||||
|
command: opt/terminus/terminus
|
||||||
|
|
||||||
|
parts:
|
||||||
|
app:
|
||||||
|
plugin: nodejs
|
||||||
|
source: .
|
||||||
|
build-packages:
|
||||||
|
- libfontconfig-dev
|
||||||
|
override-build: |
|
||||||
|
yarn
|
||||||
|
./scripts/build-native.js
|
||||||
|
yarn run build
|
||||||
|
./scripts/build-linux.js
|
||||||
|
mkdir -p $SNAPCRAFT_PART_INSTALL/opt/terminus || true
|
||||||
|
cp -ar dist/linux-unpacked/* $SNAPCRAFT_PART_INSTALL/opt/terminus/
|
@@ -1,12 +1,12 @@
|
|||||||
{
|
{
|
||||||
"name": "terminus-community-color-schemes",
|
"name": "terminus-community-color-schemes",
|
||||||
"version": "1.0.68-c17-g8b64a81",
|
"version": "1.0.73-c4-ga7d62b0",
|
||||||
"description": "Community color schemes for Terminus",
|
"description": "Community color schemes for Terminus",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"terminus-builtin-plugin"
|
"terminus-builtin-plugin"
|
||||||
],
|
],
|
||||||
"main": "dist/index.js",
|
"main": "dist/index.js",
|
||||||
"typings": "dist/index.d.ts",
|
"typings": "typings/index.d.ts",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "webpack --progress --color",
|
"build": "webpack --progress --color",
|
||||||
"watch": "webpack --progress --color --watch"
|
"watch": "webpack --progress --color --watch"
|
||||||
@@ -22,8 +22,7 @@
|
|||||||
"terminus-terminal": "*"
|
"terminus-terminal": "*"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/node": "7.0.12",
|
"@types/node": "12.0.7",
|
||||||
"@types/webpack-env": "^1.13.0"
|
"@types/webpack-env": "^1.13.0"
|
||||||
},
|
}
|
||||||
"false": {}
|
|
||||||
}
|
}
|
||||||
|
36
terminus-community-color-schemes/schemes/Relaxed
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
! special
|
||||||
|
*.foreground: #d8d8d8
|
||||||
|
*.background: #343a43
|
||||||
|
*.cursorColor: #d8d8d8
|
||||||
|
|
||||||
|
! black
|
||||||
|
*.color0: #2c3037
|
||||||
|
*.color8: #626262
|
||||||
|
|
||||||
|
! red
|
||||||
|
*.color1: #bb5653
|
||||||
|
*.color9: #c35956
|
||||||
|
|
||||||
|
! green
|
||||||
|
*.color2: #909d62
|
||||||
|
*.color10: #9fab76
|
||||||
|
|
||||||
|
! yellow
|
||||||
|
*.color3: #eac179
|
||||||
|
*.color11: #ecc179
|
||||||
|
|
||||||
|
! blue
|
||||||
|
*.color4: #698698
|
||||||
|
*.color12: #7da9c7
|
||||||
|
|
||||||
|
! magenta
|
||||||
|
*.color5: #b06597
|
||||||
|
*.color13: #ba6ca0
|
||||||
|
|
||||||
|
! cyan
|
||||||
|
*.color6: #c9dfff
|
||||||
|
*.color14: #abbacf
|
||||||
|
|
||||||
|
! white
|
||||||
|
*.color7: #d8d8d8
|
||||||
|
*.color15: #f7f7f7
|
@@ -9,7 +9,7 @@ export class ColorSchemes extends TerminalColorSchemeProvider {
|
|||||||
let schemes: ITerminalColorScheme[] = []
|
let schemes: ITerminalColorScheme[] = []
|
||||||
|
|
||||||
schemeContents.keys().forEach(schemeFile => {
|
schemeContents.keys().forEach(schemeFile => {
|
||||||
let lines = (schemeContents(schemeFile) as string).split('\n')
|
let lines = (schemeContents(schemeFile).default as string).split('\n')
|
||||||
|
|
||||||
// process #define variables
|
// process #define variables
|
||||||
let variables: any = {}
|
let variables: any = {}
|
||||||
|
@@ -2,7 +2,6 @@
|
|||||||
"extends": "../tsconfig.json",
|
"extends": "../tsconfig.json",
|
||||||
"exclude": ["node_modules", "dist"],
|
"exclude": ["node_modules", "dist"],
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"baseUrl": "src",
|
"baseUrl": "src"
|
||||||
"declarationDir": "dist"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -4,7 +4,7 @@ const webpack = require('webpack')
|
|||||||
module.exports = {
|
module.exports = {
|
||||||
target: 'node',
|
target: 'node',
|
||||||
entry: 'src/index.ts',
|
entry: 'src/index.ts',
|
||||||
devtool: 'source-map',
|
devtool: 'eval-source-map',
|
||||||
context: __dirname,
|
context: __dirname,
|
||||||
output: {
|
output: {
|
||||||
path: path.resolve(__dirname, 'dist'),
|
path: path.resolve(__dirname, 'dist'),
|
||||||
|
@@ -2,12 +2,12 @@
|
|||||||
# yarn lockfile v1
|
# yarn lockfile v1
|
||||||
|
|
||||||
|
|
||||||
"@types/node@7.0.12":
|
"@types/node@12.0.7":
|
||||||
version "7.0.12"
|
version "12.0.7"
|
||||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-7.0.12.tgz#ae5f67a19c15f752148004db07cbbb372e69efc9"
|
resolved "https://registry.yarnpkg.com/@types/node/-/node-12.0.7.tgz#4f2563bad652b2acb1722d7e7aae2b0ff62d192c"
|
||||||
integrity sha1-rl9noZwV91IUgATbB8u7Ny5p78k=
|
integrity sha512-1YKeT4JitGgE4SOzyB9eMwO0nGVNkNEsm9qlIt1Lqm/tG2QEiSMTD4kS3aO6L+w5SClLVxALmIBESK6Mk5wX0A==
|
||||||
|
|
||||||
"@types/webpack-env@^1.13.0":
|
"@types/webpack-env@^1.13.0":
|
||||||
version "1.13.1"
|
version "1.13.9"
|
||||||
resolved "https://registry.yarnpkg.com/@types/webpack-env/-/webpack-env-1.13.1.tgz#b45c222e24301bd006e3edfc762cc6b51bda236a"
|
resolved "https://registry.yarnpkg.com/@types/webpack-env/-/webpack-env-1.13.9.tgz#a67287861c928ebf4159a908d1fb1a2a34d4097a"
|
||||||
integrity sha512-oHyg0NssP2RCpCvE35hhbSqMJRsc5lSW+GFe+Vc65JL+kHII1VMYM+0KeV/z4utFuUqPoQRmq8KMMp7ba0dj6Q==
|
integrity sha512-p8zp5xqkly3g4cCmo2mKOHI9+Z/kObmDj0BmjbDDJQlgDTiEGTbm17MEwTAusV6XceCy+bNw9q/ZHXHyKo3zkg==
|
||||||
|
@@ -1,12 +1,12 @@
|
|||||||
{
|
{
|
||||||
"name": "terminus-core",
|
"name": "terminus-core",
|
||||||
"version": "1.0.68-c17-g8b64a81",
|
"version": "1.0.73-c4-ga7d62b0",
|
||||||
"description": "Terminus core",
|
"description": "Terminus core",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"terminus-builtin-plugin"
|
"terminus-builtin-plugin"
|
||||||
],
|
],
|
||||||
"main": "dist/index.js",
|
"main": "dist/index.js",
|
||||||
"typings": "dist/index.d.ts",
|
"typings": "typings/index.d.ts",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "webpack --progress --color --display-modules",
|
"build": "webpack --progress --color --display-modules",
|
||||||
"watch": "webpack --progress --color --watch"
|
"watch": "webpack --progress --color --watch"
|
||||||
@@ -18,18 +18,24 @@
|
|||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/js-yaml": "^3.9.0",
|
"@types/js-yaml": "^3.9.0",
|
||||||
"@types/node": "^7.0.37",
|
"@types/node": "^12.0.2",
|
||||||
"@types/webpack-env": "^1.13.0",
|
"@types/webpack-env": "^1.13.0",
|
||||||
"@types/winston": "^2.3.6",
|
"@types/winston": "^2.3.6",
|
||||||
"axios": "^0.18.0",
|
"axios": "^0.19.0",
|
||||||
"bootstrap": "^4.1.3",
|
"bootstrap": "^4.1.3",
|
||||||
"core-js": "^2.4.1",
|
"core-js": "^3.1.2",
|
||||||
"electron-updater": "^2.8.9",
|
"deepmerge": "^3.2.0",
|
||||||
|
"electron-updater": "^4.0.6",
|
||||||
|
"js-yaml": "^3.9.0",
|
||||||
|
"mixpanel": "^0.10.2",
|
||||||
"ng2-dnd": "^5.0.2",
|
"ng2-dnd": "^5.0.2",
|
||||||
"ngx-perfect-scrollbar": "^6.0.0",
|
"ngx-perfect-scrollbar": "^6.0.0",
|
||||||
"rage-edit": "^1.2.0",
|
|
||||||
"shell-escape": "^0.2.0",
|
"shell-escape": "^0.2.0",
|
||||||
"universal-analytics": "^0.4.17"
|
"uuid": "^3.3.2",
|
||||||
|
"winston": "^3.2.1"
|
||||||
|
},
|
||||||
|
"optionalDependencies": {
|
||||||
|
"windows-native-registry": "^1.0.14"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@angular/animations": "4.0.1",
|
"@angular/animations": "4.0.1",
|
||||||
@@ -40,10 +46,5 @@
|
|||||||
"@angular/platform-browser-dynamic": "4.0.1",
|
"@angular/platform-browser-dynamic": "4.0.1",
|
||||||
"rxjs": "5.3.0",
|
"rxjs": "5.3.0",
|
||||||
"zone.js": "0.8.4"
|
"zone.js": "0.8.4"
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"deepmerge": "^1.5.0",
|
|
||||||
"js-yaml": "^3.9.0",
|
|
||||||
"winston": "^2.4.0"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -23,7 +23,12 @@ export interface IToolbarButton {
|
|||||||
|
|
||||||
weight?: number
|
weight?: number
|
||||||
|
|
||||||
click: () => void
|
click?: () => void
|
||||||
|
|
||||||
|
submenu?: () => Promise<IToolbarButton[]>
|
||||||
|
|
||||||
|
/** @hidden */
|
||||||
|
submenuItems?: IToolbarButton[]
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -32,22 +32,48 @@ title-bar(
|
|||||||
)
|
)
|
||||||
|
|
||||||
.btn-group.background
|
.btn-group.background
|
||||||
button.btn.btn-secondary.btn-tab-bar(
|
.d-flex(
|
||||||
*ngFor='let button of leftToolbarButtons',
|
*ngFor='let button of leftToolbarButtons',
|
||||||
[title]='button.title',
|
ngbDropdown,
|
||||||
(click)='button.click()',
|
(openChange)='generateButtonSubmenu(button)',
|
||||||
[innerHTML]='button.icon',
|
|
||||||
)
|
)
|
||||||
|
button.btn.btn-secondary.btn-tab-bar(
|
||||||
|
[title]='button.title',
|
||||||
|
(click)='button.click && button.click()',
|
||||||
|
[innerHTML]='button.icon',
|
||||||
|
ngbDropdownToggle,
|
||||||
|
)
|
||||||
|
div(*ngIf='button.submenu', ngbDropdownMenu)
|
||||||
|
button.dropdown-item.d-flex.align-items-center(
|
||||||
|
*ngFor='let item of button.submenuItems',
|
||||||
|
(click)='item.click()',
|
||||||
|
ngbDropdownItem,
|
||||||
|
)
|
||||||
|
.icon-wrapper([innerHTML]='item.icon')
|
||||||
|
.ml-3 {{item.title}}
|
||||||
|
|
||||||
.drag-space.background([class.persistent]='config.store.appearance.frame == "thin" && hostApp.platform != Platform.macOS')
|
.drag-space.background([class.persistent]='config.store.appearance.frame == "thin" && hostApp.platform != Platform.macOS')
|
||||||
|
|
||||||
.btn-group.background
|
.btn-group.background
|
||||||
button.btn.btn-secondary.btn-tab-bar(
|
.d-flex(
|
||||||
*ngFor='let button of rightToolbarButtons',
|
*ngFor='let button of rightToolbarButtons',
|
||||||
[title]='button.title',
|
ngbDropdown,
|
||||||
(click)='button.click()',
|
(openChange)='generateButtonSubmenu(button)',
|
||||||
[innerHTML]='button.icon',
|
|
||||||
)
|
)
|
||||||
|
button.btn.btn-secondary.btn-tab-bar(
|
||||||
|
[title]='button.title',
|
||||||
|
(click)='button.click && button.click()',
|
||||||
|
[innerHTML]='button.icon',
|
||||||
|
ngbDropdownToggle,
|
||||||
|
)
|
||||||
|
div(*ngIf='button.submenu', ngbDropdownMenu)
|
||||||
|
button.dropdown-item.d-flex.align-items-center(
|
||||||
|
*ngFor='let item of button.submenuItems',
|
||||||
|
(click)='item.click()',
|
||||||
|
ngbDropdownItem,
|
||||||
|
)
|
||||||
|
.icon-wrapper([innerHTML]='item.icon')
|
||||||
|
.ml-3 {{item.title}}
|
||||||
|
|
||||||
button.btn.btn-secondary.btn-tab-bar.btn-update(
|
button.btn.btn-secondary.btn-tab-bar.btn-update(
|
||||||
*ngIf='updatesAvailable',
|
*ngIf='updatesAvailable',
|
||||||
|
@@ -48,6 +48,10 @@ $tab-border-radius: 4px;
|
|||||||
color: #aaa;
|
color: #aaa;
|
||||||
border: none;
|
border: none;
|
||||||
border-radius: 0;
|
border-radius: 0;
|
||||||
|
|
||||||
|
&.dropdown-toggle::after {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&>.tabs {
|
&>.tabs {
|
||||||
@@ -88,12 +92,20 @@ hotkey-hint {
|
|||||||
max-width: 300px;
|
max-width: 300px;
|
||||||
}
|
}
|
||||||
|
|
||||||
::ng-deep .btn-tab-bar svg {
|
::ng-deep .btn-tab-bar svg,
|
||||||
|
::ng-deep .btn-tab-bar + .dropdown-menu svg {
|
||||||
|
width: 16px;
|
||||||
height: 16px;
|
height: 16px;
|
||||||
fill: white;
|
fill: white;
|
||||||
fill-opacity: 0.75;
|
fill-opacity: 0.75;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.icon-wrapper {
|
||||||
|
display: flex;
|
||||||
|
width: 16px;
|
||||||
|
height: 17px;
|
||||||
|
}
|
||||||
|
|
||||||
::ng-deep .btn-update svg {
|
::ng-deep .btn-update svg {
|
||||||
fill: cyan;
|
fill: cyan;
|
||||||
}
|
}
|
||||||
|
@@ -233,6 +233,12 @@ export class AppRootComponent {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async generateButtonSubmenu (button: IToolbarButton) {
|
||||||
|
if (button.submenu) {
|
||||||
|
button.submenuItems = await button.submenu()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private getToolbarButtons (aboveZero: boolean): IToolbarButton[] {
|
private getToolbarButtons (aboveZero: boolean): IToolbarButton[] {
|
||||||
let buttons: IToolbarButton[] = []
|
let buttons: IToolbarButton[] = []
|
||||||
this.config.enabledServices(this.toolbarButtonProviders).forEach(provider => {
|
this.config.enabledServices(this.toolbarButtonProviders).forEach(provider => {
|
||||||
|
@@ -91,7 +91,7 @@ export abstract class BaseTabComponent {
|
|||||||
}
|
}
|
||||||
this.progressClearTimeout = setTimeout(() => {
|
this.progressClearTimeout = setTimeout(() => {
|
||||||
this.setProgress(null)
|
this.setProgress(null)
|
||||||
}, 5000)
|
}, 5000) as any
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -210,18 +210,21 @@ export class SplitTabComponent extends BaseTabComponent implements OnInit, OnDes
|
|||||||
case 'split-left':
|
case 'split-left':
|
||||||
this.splitTab(this.focusedTab, 'l')
|
this.splitTab(this.focusedTab, 'l')
|
||||||
break
|
break
|
||||||
case 'split-nav-left':
|
case 'pane-nav-left':
|
||||||
this.navigate('l')
|
this.navigate('l')
|
||||||
break
|
break
|
||||||
case 'split-nav-right':
|
case 'pane-nav-right':
|
||||||
this.navigate('r')
|
this.navigate('r')
|
||||||
break
|
break
|
||||||
case 'split-nav-up':
|
case 'pane-nav-up':
|
||||||
this.navigate('t')
|
this.navigate('t')
|
||||||
break
|
break
|
||||||
case 'split-nav-down':
|
case 'pane-nav-down':
|
||||||
this.navigate('b')
|
this.navigate('b')
|
||||||
break
|
break
|
||||||
|
case 'close-pane':
|
||||||
|
this.removeTab(this.focusedTab)
|
||||||
|
break
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -336,6 +339,8 @@ export class SplitTabComponent extends BaseTabComponent implements OnInit, OnDes
|
|||||||
|
|
||||||
if (this.root.children.length === 0) {
|
if (this.root.children.length === 0) {
|
||||||
this.destroy()
|
this.destroy()
|
||||||
|
} else {
|
||||||
|
this.focusAnyIn(parent)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -23,6 +23,7 @@ export class StartPageComponent {
|
|||||||
return this.config.enabledServices(this.toolbarButtonProviders)
|
return this.config.enabledServices(this.toolbarButtonProviders)
|
||||||
.map(provider => provider.provide())
|
.map(provider => provider.provide())
|
||||||
.reduce((a, b) => a.concat(b))
|
.reduce((a, b) => a.concat(b))
|
||||||
|
.filter(x => !!x.click)
|
||||||
.sort((a: IToolbarButton, b: IToolbarButton) => (a.weight || 0) - (b.weight || 0))
|
.sort((a: IToolbarButton, b: IToolbarButton) => (a.weight || 0) - (b.weight || 0))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
19
terminus-core/src/components/welcomeTab.component.pug
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
.mb-4
|
||||||
|
.terminus-logo
|
||||||
|
h1.terminus-title Terminus
|
||||||
|
sup α
|
||||||
|
|
||||||
|
.container
|
||||||
|
.text-center.mb-5 Thank you for downloading Terminus!
|
||||||
|
|
||||||
|
.form-line
|
||||||
|
.header
|
||||||
|
.title Enable analytics
|
||||||
|
.description Help us track the number of Terminus installs across the world!
|
||||||
|
toggle(
|
||||||
|
[(ngModel)]='config.store.enableAnalytics',
|
||||||
|
(ngModelChange)='config.save(); config.requestRestart()',
|
||||||
|
)
|
||||||
|
|
||||||
|
.text-center.mt-5
|
||||||
|
button.btn.btn-primary((click)='closeAndDisable()') Close and never show again
|
6
terminus-core/src/components/welcomeTab.component.scss
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
:host {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
margin: auto;
|
||||||
|
flex: 0 1 500px;
|
||||||
|
}
|
26
terminus-core/src/components/welcomeTab.component.ts
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
import { Component } from '@angular/core'
|
||||||
|
import { BaseTabComponent } from './baseTab.component'
|
||||||
|
import { ConfigService } from '../services/config.service'
|
||||||
|
import { AppService } from '../services/app.service'
|
||||||
|
|
||||||
|
/** @hidden */
|
||||||
|
@Component({
|
||||||
|
selector: 'welcome-page',
|
||||||
|
template: require('./welcomeTab.component.pug'),
|
||||||
|
styles: [require('./welcomeTab.component.scss')],
|
||||||
|
})
|
||||||
|
export class WelcomeTabComponent extends BaseTabComponent {
|
||||||
|
constructor (
|
||||||
|
private app: AppService,
|
||||||
|
public config: ConfigService,
|
||||||
|
) {
|
||||||
|
super()
|
||||||
|
this.setTitle('Welcome')
|
||||||
|
}
|
||||||
|
|
||||||
|
closeAndDisable () {
|
||||||
|
this.config.store.enableWelcomeTab = false
|
||||||
|
this.config.save()
|
||||||
|
this.app.closeTab(this)
|
||||||
|
}
|
||||||
|
}
|
@@ -42,12 +42,13 @@ hotkeys:
|
|||||||
- 'Ctrl-Shift-D'
|
- 'Ctrl-Shift-D'
|
||||||
split-left: []
|
split-left: []
|
||||||
split-top: []
|
split-top: []
|
||||||
split-nav-right:
|
pane-nav-right:
|
||||||
- 'Ctrl-Alt-ArrowRight'
|
- 'Ctrl-Alt-ArrowRight'
|
||||||
split-nav-down:
|
pane-nav-down:
|
||||||
- 'Ctrl-Alt-ArrowDown'
|
- 'Ctrl-Alt-ArrowDown'
|
||||||
split-nav-up:
|
pane-nav-up:
|
||||||
- 'Ctrl-Alt-ArrowUp'
|
- 'Ctrl-Alt-ArrowUp'
|
||||||
split-nav-left:
|
pane-nav-left:
|
||||||
- 'Ctrl-Alt-ArrowLeft'
|
- 'Ctrl-Alt-ArrowLeft'
|
||||||
|
close-pane: []
|
||||||
pluginBlacklist: ['ssh']
|
pluginBlacklist: ['ssh']
|
||||||
|
@@ -40,12 +40,14 @@ hotkeys:
|
|||||||
- '⌘-D'
|
- '⌘-D'
|
||||||
split-left: []
|
split-left: []
|
||||||
split-top: []
|
split-top: []
|
||||||
split-nav-right:
|
pane-nav-right:
|
||||||
- '⌘-⌥-ArrowRight'
|
- '⌘-⌥-ArrowRight'
|
||||||
split-nav-down:
|
pane-nav-down:
|
||||||
- '⌘-⌥-ArrowDown'
|
- '⌘-⌥-ArrowDown'
|
||||||
split-nav-up:
|
pane-nav-up:
|
||||||
- '⌘-⌥-ArrowUp'
|
- '⌘-⌥-ArrowUp'
|
||||||
split-nav-left:
|
pane-nav-left:
|
||||||
- '⌘-⌥-ArrowLeft'
|
- '⌘-⌥-ArrowLeft'
|
||||||
|
close-pane:
|
||||||
|
- '⌘-Shift-W'
|
||||||
pluginBlacklist: ['ssh']
|
pluginBlacklist: ['ssh']
|
||||||
|
@@ -42,12 +42,13 @@ hotkeys:
|
|||||||
- 'Ctrl-Shift-D'
|
- 'Ctrl-Shift-D'
|
||||||
split-left: []
|
split-left: []
|
||||||
split-top: []
|
split-top: []
|
||||||
split-nav-right:
|
pane-nav-right:
|
||||||
- 'Ctrl-Alt-ArrowRight'
|
- 'Ctrl-Alt-ArrowRight'
|
||||||
split-nav-down:
|
pane-nav-down:
|
||||||
- 'Ctrl-Alt-ArrowDown'
|
- 'Ctrl-Alt-ArrowDown'
|
||||||
split-nav-up:
|
pane-nav-up:
|
||||||
- 'Ctrl-Alt-ArrowUp'
|
- 'Ctrl-Alt-ArrowUp'
|
||||||
split-nav-left:
|
pane-nav-left:
|
||||||
- 'Ctrl-Alt-ArrowLeft'
|
- 'Ctrl-Alt-ArrowLeft'
|
||||||
|
close-pane: []
|
||||||
pluginBlacklist: []
|
pluginBlacklist: []
|
||||||
|
@@ -11,3 +11,4 @@ appearance:
|
|||||||
vibrancy: false
|
vibrancy: false
|
||||||
vibrancyType: 'blur'
|
vibrancyType: 'blur'
|
||||||
enableAnalytics: true
|
enableAnalytics: true
|
||||||
|
enableWelcomeTab: true
|
||||||
|
@@ -94,21 +94,25 @@ export class AppHotkeyProvider extends HotkeyProvider {
|
|||||||
name: 'Split to the top',
|
name: 'Split to the top',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'split-nav-up',
|
id: 'pane-nav-up',
|
||||||
name: 'Focus the pane above',
|
name: 'Focus the pane above',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'split-nav-down',
|
id: 'pane-nav-down',
|
||||||
name: 'Focus the pane below',
|
name: 'Focus the pane below',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'split-nav-left',
|
id: 'pane-nav-left',
|
||||||
name: 'Focus the pane on the left',
|
name: 'Focus the pane on the left',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'split-nav-right',
|
id: 'pane-nav-right',
|
||||||
name: 'Focus the pane on the right',
|
name: 'Focus the pane on the right',
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
id: 'close-pane',
|
||||||
|
name: 'Close focused pane',
|
||||||
|
},
|
||||||
]
|
]
|
||||||
|
|
||||||
async provide (): Promise<IHotkeyDescription[]> {
|
async provide (): Promise<IHotkeyDescription[]> {
|
||||||
|
@@ -18,6 +18,7 @@ import { WindowControlsComponent } from './components/windowControls.component'
|
|||||||
import { RenameTabModalComponent } from './components/renameTabModal.component'
|
import { RenameTabModalComponent } from './components/renameTabModal.component'
|
||||||
import { SplitTabComponent, SplitTabRecoveryProvider } from './components/splitTab.component'
|
import { SplitTabComponent, SplitTabRecoveryProvider } from './components/splitTab.component'
|
||||||
import { SplitTabSpannerComponent } from './components/splitTabSpanner.component'
|
import { SplitTabSpannerComponent } from './components/splitTabSpanner.component'
|
||||||
|
import { WelcomeTabComponent } from './components/welcomeTab.component'
|
||||||
|
|
||||||
import { AutofocusDirective } from './directives/autofocus.directive'
|
import { AutofocusDirective } from './directives/autofocus.directive'
|
||||||
|
|
||||||
@@ -27,6 +28,9 @@ import { Theme } from './api/theme'
|
|||||||
import { TabContextMenuItemProvider } from './api/tabContextMenuProvider'
|
import { TabContextMenuItemProvider } from './api/tabContextMenuProvider'
|
||||||
import { TabRecoveryProvider } from './api/tabRecovery'
|
import { TabRecoveryProvider } from './api/tabRecovery'
|
||||||
|
|
||||||
|
import { AppService } from './services/app.service'
|
||||||
|
import { ConfigService } from './services/config.service'
|
||||||
|
|
||||||
import { StandardTheme, StandardCompactTheme, PaperTheme } from './theme'
|
import { StandardTheme, StandardCompactTheme, PaperTheme } from './theme'
|
||||||
import { CoreConfigProvider } from './config'
|
import { CoreConfigProvider } from './config'
|
||||||
import { AppHotkeyProvider } from './hotkeys'
|
import { AppHotkeyProvider } from './hotkeys'
|
||||||
@@ -72,11 +76,13 @@ const PROVIDERS = [
|
|||||||
AutofocusDirective,
|
AutofocusDirective,
|
||||||
SplitTabComponent,
|
SplitTabComponent,
|
||||||
SplitTabSpannerComponent,
|
SplitTabSpannerComponent,
|
||||||
|
WelcomeTabComponent,
|
||||||
],
|
],
|
||||||
entryComponents: [
|
entryComponents: [
|
||||||
RenameTabModalComponent,
|
RenameTabModalComponent,
|
||||||
SafeModeModalComponent,
|
SafeModeModalComponent,
|
||||||
SplitTabComponent,
|
SplitTabComponent,
|
||||||
|
WelcomeTabComponent,
|
||||||
],
|
],
|
||||||
exports: [
|
exports: [
|
||||||
CheckboxComponent,
|
CheckboxComponent,
|
||||||
@@ -85,6 +91,14 @@ const PROVIDERS = [
|
|||||||
]
|
]
|
||||||
})
|
})
|
||||||
export default class AppModule {
|
export default class AppModule {
|
||||||
|
constructor (app: AppService, config: ConfigService) {
|
||||||
|
app.ready$.subscribe(() => {
|
||||||
|
if (config.store.enableWelcomeTab) {
|
||||||
|
app.openNewTabRaw(WelcomeTabComponent)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
static forRoot (): ModuleWithProviders {
|
static forRoot (): ModuleWithProviders {
|
||||||
return {
|
return {
|
||||||
ngModule: AppModule,
|
ngModule: AppModule,
|
||||||
|
@@ -16,7 +16,7 @@ class CompletionObserver {
|
|||||||
private interval: number
|
private interval: number
|
||||||
|
|
||||||
constructor (private tab: BaseTabComponent) {
|
constructor (private tab: BaseTabComponent) {
|
||||||
this.interval = setInterval(() => this.tick(), 1000)
|
this.interval = setInterval(() => this.tick(), 1000) as any
|
||||||
this.tab.destroyed$.pipe(takeUntil(this.destroyed$)).subscribe(() => this.stop())
|
this.tab.destroyed$.pipe(takeUntil(this.destroyed$)).subscribe(() => this.stop())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -2,12 +2,13 @@ import * as os from 'os'
|
|||||||
import { Injectable } from '@angular/core'
|
import { Injectable } from '@angular/core'
|
||||||
import { ElectronService } from './electron.service'
|
import { ElectronService } from './electron.service'
|
||||||
import { ConfigService } from './config.service'
|
import { ConfigService } from './config.service'
|
||||||
import ua = require('universal-analytics')
|
import mixpanel = require('mixpanel')
|
||||||
import uuidv4 = require('uuid/v4')
|
import uuidv4 = require('uuid/v4')
|
||||||
|
|
||||||
@Injectable({ providedIn: 'root' })
|
@Injectable({ providedIn: 'root' })
|
||||||
export class HomeBaseService {
|
export class HomeBaseService {
|
||||||
appVersion: string
|
appVersion: string
|
||||||
|
mixpanel: any
|
||||||
|
|
||||||
/** @hidden */
|
/** @hidden */
|
||||||
constructor (
|
constructor (
|
||||||
@@ -16,7 +17,7 @@ export class HomeBaseService {
|
|||||||
) {
|
) {
|
||||||
this.appVersion = electron.app.getVersion()
|
this.appVersion = electron.app.getVersion()
|
||||||
|
|
||||||
if (this.config.store.enableAnalytics) {
|
if (this.config.store.enableAnalytics && !this.config.store.enableWelcomeTab) {
|
||||||
this.enableAnalytics()
|
this.enableAnalytics()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -42,9 +43,20 @@ export class HomeBaseService {
|
|||||||
if (!window.localStorage.analyticsUserID) {
|
if (!window.localStorage.analyticsUserID) {
|
||||||
window.localStorage.analyticsUserID = uuidv4()
|
window.localStorage.analyticsUserID = uuidv4()
|
||||||
}
|
}
|
||||||
const session = ua('UA-3278102-20', window.localStorage.analyticsUserID)
|
this.mixpanel = mixpanel.init('bb4638b0860eef14c04d4fbc5eb365fa')
|
||||||
session.set('cd1', this.appVersion)
|
if (!window.localStorage.installEventSent) {
|
||||||
session.set('cd2', process.platform)
|
this.mixpanel.track('freshInstall', this.getAnalyticsProperties())
|
||||||
session.pageview('/').send()
|
window.localStorage.installEventSent = true
|
||||||
|
}
|
||||||
|
this.mixpanel.track('launch', this.getAnalyticsProperties())
|
||||||
|
}
|
||||||
|
|
||||||
|
getAnalyticsProperties () {
|
||||||
|
return {
|
||||||
|
distinct_id: window.localStorage.analyticsUserID,
|
||||||
|
platform: process.platform,
|
||||||
|
os: os.release(),
|
||||||
|
version: this.appVersion,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -28,6 +28,7 @@ export class HostAppService {
|
|||||||
*/
|
*/
|
||||||
shown = new EventEmitter<any>()
|
shown = new EventEmitter<any>()
|
||||||
isFullScreen = false
|
isFullScreen = false
|
||||||
|
isPortable = !!process.env.PORTABLE_EXECUTABLE_FILE
|
||||||
|
|
||||||
private preferencesMenu = new Subject<void>()
|
private preferencesMenu = new Subject<void>()
|
||||||
private secondInstance = new Subject<void>()
|
private secondInstance = new Subject<void>()
|
||||||
@@ -251,6 +252,15 @@ export class HostAppService {
|
|||||||
this.electron.ipcRenderer.send('window-close')
|
this.electron.ipcRenderer.send('window-close')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
relaunch () {
|
||||||
|
if (this.isPortable) {
|
||||||
|
this.electron.app.relaunch({ execPath: process.env.PORTABLE_EXECUTABLE_FILE })
|
||||||
|
} else {
|
||||||
|
this.electron.app.relaunch()
|
||||||
|
}
|
||||||
|
this.electron.app.exit()
|
||||||
|
}
|
||||||
|
|
||||||
quit () {
|
quit () {
|
||||||
this.logger.info('Quitting')
|
this.logger.info('Quitting')
|
||||||
this.electron.app.quit()
|
this.electron.app.quit()
|
||||||
|
@@ -11,22 +11,15 @@ const initializeWinston = (electron: ElectronService) => {
|
|||||||
fs.mkdirSync(logDirectory)
|
fs.mkdirSync(logDirectory)
|
||||||
}
|
}
|
||||||
|
|
||||||
return new winston.Logger({
|
return winston.createLogger({
|
||||||
transports: [
|
transports: [
|
||||||
new winston.transports.File({
|
new winston.transports.File({
|
||||||
level: 'debug',
|
level: 'debug',
|
||||||
filename: path.join(logDirectory, 'log.txt'),
|
filename: path.join(logDirectory, 'log.txt'),
|
||||||
|
format: winston.format.simple(),
|
||||||
handleExceptions: false,
|
handleExceptions: false,
|
||||||
json: false,
|
|
||||||
maxsize: 5242880,
|
maxsize: 5242880,
|
||||||
maxFiles: 5,
|
maxFiles: 5,
|
||||||
colorize: false
|
|
||||||
}),
|
|
||||||
new winston.transports.Console({
|
|
||||||
level: 'debug',
|
|
||||||
handleExceptions: false,
|
|
||||||
json: false,
|
|
||||||
colorize: true
|
|
||||||
})
|
})
|
||||||
],
|
],
|
||||||
exitOnError: false
|
exitOnError: false
|
||||||
|
@@ -1,11 +1,14 @@
|
|||||||
import * as path from 'path'
|
import * as path from 'path'
|
||||||
import * as fs from 'mz/fs'
|
import * as fs from 'mz/fs'
|
||||||
import { Registry } from 'rage-edit'
|
|
||||||
import { exec } from 'mz/child_process'
|
import { exec } from 'mz/child_process'
|
||||||
import { Injectable } from '@angular/core'
|
import { Injectable } from '@angular/core'
|
||||||
import { ElectronService } from './electron.service'
|
import { ElectronService } from './electron.service'
|
||||||
import { HostAppService, Platform } from './hostApp.service'
|
import { HostAppService, Platform } from './hostApp.service'
|
||||||
|
|
||||||
|
try {
|
||||||
|
var wnr = require('windows-native-registry') // tslint:disable-line
|
||||||
|
} catch (_) { } // tslint:disable-line
|
||||||
|
|
||||||
@Injectable({ providedIn: 'root' })
|
@Injectable({ providedIn: 'root' })
|
||||||
export class ShellIntegrationService {
|
export class ShellIntegrationService {
|
||||||
private automatorWorkflows = ['Open Terminus here.workflow', 'Paste path into Terminus.workflow']
|
private automatorWorkflows = ['Open Terminus here.workflow', 'Paste path into Terminus.workflow']
|
||||||
@@ -13,11 +16,11 @@ export class ShellIntegrationService {
|
|||||||
private automatorWorkflowsDestination: string
|
private automatorWorkflowsDestination: string
|
||||||
private registryKeys = [
|
private registryKeys = [
|
||||||
{
|
{
|
||||||
path: 'HKCU\\Software\\Classes\\Directory\\Background\\shell\\Open Terminus here',
|
path: 'Software\\Classes\\Directory\\Background\\shell\\Open Terminus here',
|
||||||
command: 'open "%V"'
|
command: 'open "%V"'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'HKCU\\Software\\Classes\\*\\shell\\Paste path into Terminus',
|
path: 'Software\\Classes\\*\\shell\\Paste path into Terminus',
|
||||||
command: 'paste "%V"'
|
command: 'paste "%V"'
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
@@ -50,20 +53,35 @@ export class ShellIntegrationService {
|
|||||||
if (this.hostApp.platform === Platform.macOS) {
|
if (this.hostApp.platform === Platform.macOS) {
|
||||||
return fs.exists(path.join(this.automatorWorkflowsDestination, this.automatorWorkflows[0]))
|
return fs.exists(path.join(this.automatorWorkflowsDestination, this.automatorWorkflows[0]))
|
||||||
} else if (this.hostApp.platform === Platform.Windows) {
|
} else if (this.hostApp.platform === Platform.Windows) {
|
||||||
return Registry.has(this.registryKeys[0].path)
|
return !!wnr.getRegistryKey(wnr.HK.CU, this.registryKeys[0].path)
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
async install () {
|
async install () {
|
||||||
|
const exe = process.env.PORTABLE_EXECUTABLE_FILE || this.electron.app.getPath('exe')
|
||||||
if (this.hostApp.platform === Platform.macOS) {
|
if (this.hostApp.platform === Platform.macOS) {
|
||||||
for (let wf of this.automatorWorkflows) {
|
for (let wf of this.automatorWorkflows) {
|
||||||
await exec(`cp -r "${this.automatorWorkflowsLocation}/${wf}" "${this.automatorWorkflowsDestination}"`)
|
await exec(`cp -r "${this.automatorWorkflowsLocation}/${wf}" "${this.automatorWorkflowsDestination}"`)
|
||||||
}
|
}
|
||||||
} else if (this.hostApp.platform === Platform.Windows) {
|
} else if (this.hostApp.platform === Platform.Windows) {
|
||||||
for (let registryKey of this.registryKeys) {
|
for (let registryKey of this.registryKeys) {
|
||||||
await Registry.set(registryKey.path, 'Icon', this.electron.app.getPath('exe'))
|
wnr.createRegistryKey(wnr.HK.CU, registryKey.path)
|
||||||
await Registry.set(registryKey.path + '\\command', '', this.electron.app.getPath('exe') + ' ' + registryKey.command)
|
wnr.createRegistryKey(wnr.HK.CU, registryKey.path + '\\command')
|
||||||
|
wnr.setRegistryValue(wnr.HK.CU, registryKey.path, 'Icon', wnr.REG.SZ, exe)
|
||||||
|
wnr.setRegistryValue(wnr.HK.CU, registryKey.path + '\\command', '', wnr.REG.SZ, exe + ' ' + registryKey.command)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async remove () {
|
||||||
|
if (this.hostApp.platform === Platform.macOS) {
|
||||||
|
for (let wf of this.automatorWorkflows) {
|
||||||
|
await exec(`rm -rf "${this.automatorWorkflowsDestination}/${wf}"`)
|
||||||
|
}
|
||||||
|
} else if (this.hostApp.platform === Platform.Windows) {
|
||||||
|
for (let registryKey of this.registryKeys) {
|
||||||
|
wnr.deleteRegistryKey(wnr.HK.CU, registryKey.path)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -10,6 +10,7 @@ import { IToolbarButton, ToolbarButtonProvider } from '../api'
|
|||||||
@Injectable({ providedIn: 'root' })
|
@Injectable({ providedIn: 'root' })
|
||||||
export class TouchbarService {
|
export class TouchbarService {
|
||||||
private tabsSegmentedControl: TouchBarSegmentedControl
|
private tabsSegmentedControl: TouchBarSegmentedControl
|
||||||
|
private buttonsSegmentedControl: TouchBarSegmentedControl
|
||||||
private tabSegments: SegmentedControlSegment[] = []
|
private tabSegments: SegmentedControlSegment[] = []
|
||||||
private nsImageCache: {[id: string]: Electron.NativeImage} = {}
|
private nsImageCache: {[id: string]: Electron.NativeImage} = {}
|
||||||
|
|
||||||
@@ -24,16 +25,37 @@ export class TouchbarService {
|
|||||||
if (this.hostApp.platform !== Platform.macOS) {
|
if (this.hostApp.platform !== Platform.macOS) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
app.tabsChanged$.subscribe(() => this.update())
|
app.tabsChanged$.subscribe(() => this.updateTabs())
|
||||||
app.activeTabChange$.subscribe(() => this.update())
|
app.activeTabChange$.subscribe(() => this.updateTabs())
|
||||||
|
|
||||||
|
let activityIconPath = `${electron.app.getAppPath()}/assets/activity.png`
|
||||||
|
let activityIcon = this.electron.nativeImage.createFromPath(activityIconPath)
|
||||||
app.tabOpened$.subscribe(tab => {
|
app.tabOpened$.subscribe(tab => {
|
||||||
tab.titleChange$.subscribe(title => {
|
tab.titleChange$.subscribe(title => {
|
||||||
this.tabSegments[app.tabs.indexOf(tab)].label = this.shortenTitle(title)
|
let segment = this.tabSegments[app.tabs.indexOf(tab)]
|
||||||
this.tabsSegmentedControl.segments = this.tabSegments
|
if (segment) {
|
||||||
|
segment.label = this.shortenTitle(title)
|
||||||
|
this.tabsSegmentedControl.segments = this.tabSegments
|
||||||
|
}
|
||||||
|
})
|
||||||
|
tab.activity$.subscribe(hasActivity => {
|
||||||
|
let showIcon = this.app.activeTab !== tab && hasActivity
|
||||||
|
let segment = this.tabSegments[app.tabs.indexOf(tab)]
|
||||||
|
if (segment) {
|
||||||
|
segment.icon = showIcon ? activityIcon : null
|
||||||
|
}
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
updateTabs () {
|
||||||
|
this.tabSegments = this.app.tabs.map(tab => ({
|
||||||
|
label: this.shortenTitle(tab.title),
|
||||||
|
}))
|
||||||
|
this.tabsSegmentedControl.segments = this.tabSegments
|
||||||
|
this.tabsSegmentedControl.selectedIndex = this.app.tabs.indexOf(this.app.activeTab)
|
||||||
|
}
|
||||||
|
|
||||||
update () {
|
update () {
|
||||||
if (this.hostApp.platform !== Platform.macOS) {
|
if (this.hostApp.platform !== Platform.macOS) {
|
||||||
return
|
return
|
||||||
@@ -43,10 +65,12 @@ export class TouchbarService {
|
|||||||
this.config.enabledServices(this.toolbarButtonProviders).forEach(provider => {
|
this.config.enabledServices(this.toolbarButtonProviders).forEach(provider => {
|
||||||
buttons = buttons.concat(provider.provide())
|
buttons = buttons.concat(provider.provide())
|
||||||
})
|
})
|
||||||
|
buttons = buttons.filter(x => !!x.touchBarNSImage)
|
||||||
buttons.sort((a, b) => (a.weight || 0) - (b.weight || 0))
|
buttons.sort((a, b) => (a.weight || 0) - (b.weight || 0))
|
||||||
this.tabSegments = this.app.tabs.map(tab => ({
|
this.tabSegments = this.app.tabs.map(tab => ({
|
||||||
label: this.shortenTitle(tab.title),
|
label: this.shortenTitle(tab.title),
|
||||||
}))
|
}))
|
||||||
|
|
||||||
this.tabsSegmentedControl = new this.electron.TouchBar.TouchBarSegmentedControl({
|
this.tabsSegmentedControl = new this.electron.TouchBar.TouchBarSegmentedControl({
|
||||||
segments: this.tabSegments,
|
segments: this.tabSegments,
|
||||||
selectedIndex: this.app.tabs.indexOf(this.app.activeTab),
|
selectedIndex: this.app.tabs.indexOf(this.app.activeTab),
|
||||||
@@ -54,23 +78,32 @@ export class TouchbarService {
|
|||||||
this.app.selectTab(this.app.tabs[selectedIndex])
|
this.app.selectTab(this.app.tabs[selectedIndex])
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
this.buttonsSegmentedControl = new this.electron.TouchBar.TouchBarSegmentedControl({
|
||||||
|
segments: buttons.map(button => this.getButton(button)),
|
||||||
|
mode: 'buttons',
|
||||||
|
change: (selectedIndex) => this.zone.run(() => {
|
||||||
|
buttons[selectedIndex].click()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
let touchBar = new this.electron.TouchBar({
|
let touchBar = new this.electron.TouchBar({
|
||||||
items: [
|
items: [
|
||||||
this.tabsSegmentedControl,
|
this.tabsSegmentedControl,
|
||||||
new this.electron.TouchBar.TouchBarSpacer({ size: 'flexible' }),
|
new this.electron.TouchBar.TouchBarSpacer({ size: 'flexible' }),
|
||||||
new this.electron.TouchBar.TouchBarSpacer({ size: 'small' }),
|
new this.electron.TouchBar.TouchBarSpacer({ size: 'small' }),
|
||||||
...buttons.map(button => this.getButton(button))
|
this.buttonsSegmentedControl,
|
||||||
]
|
]
|
||||||
})
|
})
|
||||||
this.hostApp.setTouchBar(touchBar)
|
this.hostApp.setTouchBar(touchBar)
|
||||||
}
|
}
|
||||||
|
|
||||||
private getButton (button: IToolbarButton): Electron.TouchBarButton {
|
private getButton (button: IToolbarButton): Electron.SegmentedControlSegment {
|
||||||
return new this.electron.TouchBar.TouchBarButton({
|
return {
|
||||||
label: button.touchBarNSImage ? null : this.shortenTitle(button.touchBarTitle || button.title),
|
label: button.touchBarNSImage ? null : this.shortenTitle(button.touchBarTitle || button.title),
|
||||||
icon: button.touchBarNSImage ? this.getCachedNSImage(button.touchBarNSImage) : null,
|
icon: button.touchBarNSImage ? this.getCachedNSImage(button.touchBarNSImage) : null,
|
||||||
click: () => this.zone.run(() => button.click()),
|
// click: () => this.zone.run(() => button.click()),
|
||||||
})
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private getCachedNSImage (name: string) {
|
private getCachedNSImage (name: string) {
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
import axios from 'axios'
|
import axios from 'axios'
|
||||||
import * as os from 'os'
|
|
||||||
import { Injectable } from '@angular/core'
|
import { Injectable } from '@angular/core'
|
||||||
import { Logger, LogService } from './log.service'
|
import { Logger, LogService } from './log.service'
|
||||||
import { ElectronService } from './electron.service'
|
import { ElectronService } from './electron.service'
|
||||||
@@ -11,8 +11,9 @@ const UPDATES_URL = 'https://api.github.com/repos/eugeny/terminus/releases/lates
|
|||||||
export class UpdaterService {
|
export class UpdaterService {
|
||||||
private logger: Logger
|
private logger: Logger
|
||||||
private downloaded: Promise<boolean>
|
private downloaded: Promise<boolean>
|
||||||
private isSquirrel = true
|
private electronUpdaterAvailable = true
|
||||||
private updateURL: string
|
private updateURL: string
|
||||||
|
private autoUpdater
|
||||||
|
|
||||||
constructor (
|
constructor (
|
||||||
log: LogService,
|
log: LogService,
|
||||||
@@ -20,38 +21,33 @@ export class UpdaterService {
|
|||||||
) {
|
) {
|
||||||
this.logger = log.create('updater')
|
this.logger = log.create('updater')
|
||||||
|
|
||||||
try {
|
this.autoUpdater = electron.remote.require('electron-updater').autoUpdater
|
||||||
electron.autoUpdater.setFeedURL(`https://terminus-updates.herokuapp.com/update/${os.platform()}/${electron.app.getVersion()}`)
|
|
||||||
} catch (e) {
|
|
||||||
this.isSquirrel = false
|
|
||||||
this.logger.info('Squirrel updater unavailable, falling back')
|
|
||||||
}
|
|
||||||
|
|
||||||
this.electron.autoUpdater.on('update-available', () => {
|
this.autoUpdater.on('update-available', () => {
|
||||||
this.logger.info('Update available')
|
this.logger.info('Update available')
|
||||||
})
|
})
|
||||||
this.electron.autoUpdater.once('update-not-available', () => {
|
this.autoUpdater.once('update-not-available', () => {
|
||||||
this.logger.info('No updates')
|
this.logger.info('No updates')
|
||||||
})
|
})
|
||||||
|
|
||||||
this.downloaded = new Promise<boolean>(resolve => {
|
this.downloaded = new Promise<boolean>(resolve => {
|
||||||
this.electron.autoUpdater.once('update-downloaded', () => resolve(true))
|
this.autoUpdater.once('update-downloaded', () => resolve(true))
|
||||||
})
|
})
|
||||||
|
|
||||||
this.logger.debug('Checking for updates')
|
this.logger.debug('Checking for updates')
|
||||||
|
|
||||||
if (this.isSquirrel) {
|
if (this.electronUpdaterAvailable && !process.env.TERMINUS_DEV) {
|
||||||
try {
|
try {
|
||||||
this.electron.autoUpdater.checkForUpdates()
|
this.autoUpdater.checkForUpdates()
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
this.isSquirrel = false
|
this.electronUpdaterAvailable = false
|
||||||
this.logger.info('Squirrel updater unavailable, falling back')
|
this.logger.info('Electron updater unavailable, falling back', e)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async check (): Promise<boolean> {
|
async check (): Promise<boolean> {
|
||||||
if (!this.isSquirrel) {
|
if (!this.electronUpdaterAvailable) {
|
||||||
this.logger.debug('Checking for updates')
|
this.logger.debug('Checking for updates')
|
||||||
let response = await axios.get(UPDATES_URL)
|
let response = await axios.get(UPDATES_URL)
|
||||||
let data = response.data
|
let data = response.data
|
||||||
@@ -68,11 +64,11 @@ export class UpdaterService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async update () {
|
async update () {
|
||||||
if (!this.isSquirrel) {
|
if (!this.electronUpdaterAvailable) {
|
||||||
this.electron.shell.openExternal(this.updateURL)
|
this.electron.shell.openExternal(this.updateURL)
|
||||||
} else {
|
} else {
|
||||||
await this.downloaded
|
await this.downloaded
|
||||||
this.electron.autoUpdater.quitAndInstall()
|
this.autoUpdater.quitAndInstall()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -6,6 +6,10 @@ app-root {
|
|||||||
|
|
||||||
.btn-tab-bar {
|
.btn-tab-bar {
|
||||||
line-height: 29px !important;
|
line-height: 29px !important;
|
||||||
|
|
||||||
|
svg {
|
||||||
|
height: 14px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -51,13 +51,13 @@ $input-disabled-bg: #333;
|
|||||||
$input-color: $body-color;
|
$input-color: $body-color;
|
||||||
$input-color-placeholder: #333;
|
$input-color-placeholder: #333;
|
||||||
$input-border-color: #344;
|
$input-border-color: #344;
|
||||||
$input-border-width: 0;
|
$input-border-width: 1px;
|
||||||
//$input-box-shadow: inset 0 1px 1px rgba($black,.075);
|
//$input-box-shadow: inset 0 1px 1px rgba($black,.075);
|
||||||
$input-border-radius: 0;
|
$input-border-radius: 0;
|
||||||
$custom-select-border-radius: 0;
|
$custom-select-border-radius: 0;
|
||||||
$input-bg-focus: $input-bg;
|
$input-bg-focus: $input-bg;
|
||||||
//$input-border-focus: lighten($brand-primary, 25%);
|
$input-border-focus: lighten($blue, 25%);
|
||||||
//$input-box-shadow-focus: $input-box-shadow, rgba($input-border-focus, .6);
|
$input-focus-box-shadow: none;
|
||||||
$input-color-focus: $input-color;
|
$input-color-focus: $input-color;
|
||||||
$input-group-addon-bg: $body-bg;
|
$input-group-addon-bg: $body-bg;
|
||||||
$input-group-addon-border-color: $input-border-color;
|
$input-group-addon-border-color: $input-border-color;
|
||||||
@@ -136,6 +136,10 @@ app-root {
|
|||||||
background: transparent;
|
background: transparent;
|
||||||
&:hover { background: rgba(0, 0, 0, .25) !important; }
|
&:hover { background: rgba(0, 0, 0, .25) !important; }
|
||||||
&:active { background: rgba(0, 0, 0, .5) !important; }
|
&:active { background: rgba(0, 0, 0, .5) !important; }
|
||||||
|
|
||||||
|
&::after {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&>.tabs {
|
&>.tabs {
|
||||||
|
@@ -3,6 +3,5 @@
|
|||||||
"exclude": ["node_modules", "dist"],
|
"exclude": ["node_modules", "dist"],
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"baseUrl": "src",
|
"baseUrl": "src",
|
||||||
"declarationDir": "dist"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
14
terminus-core/tsconfig.typings.json
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
{
|
||||||
|
"extends": "../tsconfig.json",
|
||||||
|
"exclude": ["node_modules", "dist", "typings"],
|
||||||
|
"compilerOptions": {
|
||||||
|
"baseUrl": "src",
|
||||||
|
"emitDeclarationOnly": true,
|
||||||
|
"declaration": true,
|
||||||
|
"declarationDir": "./typings",
|
||||||
|
"paths": {
|
||||||
|
"terminus-*": ["../../terminus-*"],
|
||||||
|
"*": ["../../app/node_modules/*"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -4,7 +4,7 @@ const webpack = require('webpack')
|
|||||||
module.exports = {
|
module.exports = {
|
||||||
target: 'node',
|
target: 'node',
|
||||||
entry: 'src/index.ts',
|
entry: 'src/index.ts',
|
||||||
devtool: 'source-map',
|
devtool: 'eval-source-map',
|
||||||
context: __dirname,
|
context: __dirname,
|
||||||
mode: 'development',
|
mode: 'development',
|
||||||
output: {
|
output: {
|
||||||
@@ -51,10 +51,7 @@ module.exports = {
|
|||||||
'fs',
|
'fs',
|
||||||
'os',
|
'os',
|
||||||
'path',
|
'path',
|
||||||
'deepmerge',
|
'windows-native-registry',
|
||||||
'untildify',
|
|
||||||
'winston',
|
|
||||||
'js-yaml',
|
|
||||||
/^rxjs/,
|
/^rxjs/,
|
||||||
/^@angular/,
|
/^@angular/,
|
||||||
/^@ng-bootstrap/,
|
/^@ng-bootstrap/,
|
||||||
|
@@ -1,12 +1,12 @@
|
|||||||
{
|
{
|
||||||
"name": "terminus-plugin-manager",
|
"name": "terminus-plugin-manager",
|
||||||
"version": "1.0.68-c17-g8b64a81",
|
"version": "1.0.73-c4-ga7d62b0",
|
||||||
"description": "Terminus' plugin manager",
|
"description": "Terminus' plugin manager",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"terminus-builtin-plugin"
|
"terminus-builtin-plugin"
|
||||||
],
|
],
|
||||||
"main": "dist/index.js",
|
"main": "dist/index.js",
|
||||||
"typings": "dist/index.d.ts",
|
"typings": "typings/index.d.ts",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "webpack --progress --color --display-modules",
|
"build": "webpack --progress --color --display-modules",
|
||||||
"watch": "webpack --progress --color --watch"
|
"watch": "webpack --progress --color --watch"
|
||||||
@@ -17,13 +17,15 @@
|
|||||||
"author": "Eugene Pankov",
|
"author": "Eugene Pankov",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/mz": "0.0.31",
|
"@types/mz": "0.0.32",
|
||||||
"@types/node": "7.0.12",
|
"@types/node": "12.0.7",
|
||||||
"@types/semver": "^5.3.32",
|
"@types/semver": "^6.0.0",
|
||||||
"@types/webpack-env": "1.13.0",
|
"@types/webpack-env": "1.13.9",
|
||||||
|
"axios": "^0.19.0",
|
||||||
"css-loader": "^0.28.0",
|
"css-loader": "^0.28.0",
|
||||||
|
"mz": "^2.6.0",
|
||||||
"ngx-pipes": "^1.6.1",
|
"ngx-pipes": "^1.6.1",
|
||||||
"semver": "^5.3.0"
|
"semver": "^6.1.0"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@angular/common": "4.0.1",
|
"@angular/common": "4.0.1",
|
||||||
@@ -34,11 +36,5 @@
|
|||||||
"rxjs": "5.3.0",
|
"rxjs": "5.3.0",
|
||||||
"terminus-core": "*",
|
"terminus-core": "*",
|
||||||
"terminus-settings": "*"
|
"terminus-settings": "*"
|
||||||
},
|
}
|
||||||
"dependencies": {
|
|
||||||
"axios": "^0.16.2",
|
|
||||||
"mz": "^2.6.0",
|
|
||||||
"npm": "^6.7.0"
|
|
||||||
},
|
|
||||||
"false": {}
|
|
||||||
}
|
}
|
||||||
|
@@ -40,7 +40,7 @@ export class PluginManagerService {
|
|||||||
if (!this.npm) {
|
if (!this.npm) {
|
||||||
if (!this.npmReady) {
|
if (!this.npmReady) {
|
||||||
this.npmReady = new Promise(resolve => {
|
this.npmReady = new Promise(resolve => {
|
||||||
const npm = require('npm')
|
const npm = (global as any).require('npm')
|
||||||
npm.load({
|
npm.load({
|
||||||
prefix: this.userPluginsPath,
|
prefix: this.userPluginsPath,
|
||||||
}, err => {
|
}, err => {
|
||||||
|
@@ -3,6 +3,5 @@
|
|||||||
"exclude": ["node_modules", "dist"],
|
"exclude": ["node_modules", "dist"],
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"baseUrl": "src",
|
"baseUrl": "src",
|
||||||
"declarationDir": "dist"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
14
terminus-plugin-manager/tsconfig.typings.json
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
{
|
||||||
|
"extends": "../tsconfig.json",
|
||||||
|
"exclude": ["node_modules", "dist", "typings"],
|
||||||
|
"compilerOptions": {
|
||||||
|
"baseUrl": "src",
|
||||||
|
"emitDeclarationOnly": true,
|
||||||
|
"declaration": true,
|
||||||
|
"declarationDir": "./typings",
|
||||||
|
"paths": {
|
||||||
|
"terminus-*": ["../../terminus-*"],
|
||||||
|
"*": ["../../app/node_modules/*"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -4,7 +4,7 @@ const webpack = require('webpack')
|
|||||||
module.exports = {
|
module.exports = {
|
||||||
target: 'node',
|
target: 'node',
|
||||||
entry: 'src/index.ts',
|
entry: 'src/index.ts',
|
||||||
devtool: 'source-map',
|
devtool: 'eval-source-map',
|
||||||
context: __dirname,
|
context: __dirname,
|
||||||
output: {
|
output: {
|
||||||
path: path.resolve(__dirname, 'dist'),
|
path: path.resolve(__dirname, 'dist'),
|
||||||
@@ -43,11 +43,9 @@ module.exports = {
|
|||||||
},
|
},
|
||||||
externals: [
|
externals: [
|
||||||
'fs',
|
'fs',
|
||||||
'font-manager',
|
'net',
|
||||||
'npm',
|
'npm',
|
||||||
'path',
|
'path',
|
||||||
'mz/fs',
|
|
||||||
'mz/child_process',
|
|
||||||
/^rxjs/,
|
/^rxjs/,
|
||||||
/^@angular/,
|
/^@angular/,
|
||||||
/^@ng-bootstrap/,
|
/^@ng-bootstrap/,
|
||||||
|
@@ -1,12 +1,12 @@
|
|||||||
{
|
{
|
||||||
"name": "terminus-settings",
|
"name": "terminus-settings",
|
||||||
"version": "1.0.68-c17-g8b64a81",
|
"version": "1.0.73-c4-ga7d62b0",
|
||||||
"description": "Terminus terminal settings page",
|
"description": "Terminus terminal settings page",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"terminus-builtin-plugin"
|
"terminus-builtin-plugin"
|
||||||
],
|
],
|
||||||
"main": "dist/index.js",
|
"main": "dist/index.js",
|
||||||
"typings": "dist/src/index.d.ts",
|
"typings": "typings/index.d.ts",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "webpack --progress --color --display-modules",
|
"build": "webpack --progress --color --display-modules",
|
||||||
"watch": "webpack --progress --color --watch"
|
"watch": "webpack --progress --color --watch"
|
||||||
@@ -17,9 +17,9 @@
|
|||||||
"author": "Eugene Pankov",
|
"author": "Eugene Pankov",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/deep-equal": "1.0.0",
|
"@types/deep-equal": "1.0.1",
|
||||||
"@types/node": "7.0.12",
|
"@types/node": "12.0.7",
|
||||||
"@types/webpack-env": "1.13.0",
|
"@types/webpack-env": "1.13.9",
|
||||||
"ngx-pipes": "^1.6.1"
|
"ngx-pipes": "^1.6.1"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
|
@@ -34,7 +34,7 @@ export class ButtonProvider extends ToolbarButtonProvider {
|
|||||||
}
|
}
|
||||||
|
|
||||||
open (): void {
|
open (): void {
|
||||||
let settingsTab = this.app.tabs.find((tab) => tab instanceof SettingsTabComponent)
|
let settingsTab = this.app.tabs.find(tab => tab instanceof SettingsTabComponent)
|
||||||
if (settingsTab) {
|
if (settingsTab) {
|
||||||
this.app.selectTab(settingsTab)
|
this.app.selectTab(settingsTab)
|
||||||
} else {
|
} else {
|
||||||
|
@@ -20,14 +20,6 @@ ngb-tabset.vertical(type='pills', [activeId]='activeTab')
|
|||||||
i.fas.fa-bug
|
i.fas.fa-bug
|
||||||
span Report a problem
|
span Report a problem
|
||||||
|
|
||||||
.form-line(*ngIf='!isShellIntegrationInstalled')
|
|
||||||
.header
|
|
||||||
.title Shell integration
|
|
||||||
.description Allows quickly opening a terminal in the selected folder
|
|
||||||
button.btn.btn-primary((click)='installShellIntegration()')
|
|
||||||
i.fas.fa-check
|
|
||||||
span Install
|
|
||||||
|
|
||||||
.form-line
|
.form-line
|
||||||
.header
|
.header
|
||||||
.title Theme
|
.title Theme
|
||||||
@@ -106,6 +98,12 @@ ngb-tabset.vertical(type='pills', [activeId]='activeTab')
|
|||||||
step='0.01'
|
step='0.01'
|
||||||
)
|
)
|
||||||
|
|
||||||
|
.form-line(*ngIf='hostApp.platform !== Platform.Linux')
|
||||||
|
.header
|
||||||
|
.title Shell integration
|
||||||
|
.description Allows quickly opening a terminal in the selected folder
|
||||||
|
toggle([ngModel]='isShellIntegrationInstalled', (ngModelChange)='toggleShellIntegration()')
|
||||||
|
|
||||||
.form-line
|
.form-line
|
||||||
.header
|
.header
|
||||||
.title Window frame
|
.title Window frame
|
||||||
@@ -232,7 +230,7 @@ ngb-tabset.vertical(type='pills', [activeId]='activeTab')
|
|||||||
.form-line
|
.form-line
|
||||||
.header
|
.header
|
||||||
.title Enable analytics
|
.title Enable analytics
|
||||||
.description We use Google Analytics
|
.description We're only tracking your Terminus and OS versions.
|
||||||
toggle(
|
toggle(
|
||||||
[(ngModel)]='config.store.enableAnalytics',
|
[(ngModel)]='config.store.enableAnalytics',
|
||||||
(ngModelChange)='config.save(); config.requestRestart()',
|
(ngModelChange)='config.save(); config.requestRestart()',
|
||||||
|
@@ -2,6 +2,8 @@
|
|||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
flex: auto;
|
flex: auto;
|
||||||
|
overflow: auto;
|
||||||
|
height: 100%;
|
||||||
|
|
||||||
>.btn-block {
|
>.btn-block {
|
||||||
margin: 20px;
|
margin: 20px;
|
||||||
|
@@ -81,6 +81,15 @@ export class SettingsTabComponent extends BaseTabComponent {
|
|||||||
this.isShellIntegrationInstalled = await this.shellIntegration.isInstalled()
|
this.isShellIntegrationInstalled = await this.shellIntegration.isInstalled()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async toggleShellIntegration () {
|
||||||
|
if (!this.isShellIntegrationInstalled) {
|
||||||
|
await this.shellIntegration.install()
|
||||||
|
} else {
|
||||||
|
await this.shellIntegration.remove()
|
||||||
|
}
|
||||||
|
this.isShellIntegrationInstalled = await this.shellIntegration.isInstalled()
|
||||||
|
}
|
||||||
|
|
||||||
async getRecoveryToken (): Promise<any> {
|
async getRecoveryToken (): Promise<any> {
|
||||||
return { type: 'app:settings' }
|
return { type: 'app:settings' }
|
||||||
}
|
}
|
||||||
@@ -91,8 +100,7 @@ export class SettingsTabComponent extends BaseTabComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
restartApp () {
|
restartApp () {
|
||||||
this.electron.app.relaunch()
|
this.hostApp.relaunch()
|
||||||
this.electron.app.exit()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
saveConfigFile () {
|
saveConfigFile () {
|
||||||
@@ -114,11 +122,6 @@ export class SettingsTabComponent extends BaseTabComponent {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async installShellIntegration () {
|
|
||||||
await this.shellIntegration.install()
|
|
||||||
this.isShellIntegrationInstalled = true
|
|
||||||
}
|
|
||||||
|
|
||||||
getHotkey (id: string) {
|
getHotkey (id: string) {
|
||||||
let ptr = this.config.store.hotkeys
|
let ptr = this.config.store.hotkeys
|
||||||
for (let token of id.split(/\./g)) {
|
for (let token of id.split(/\./g)) {
|
||||||
|
@@ -3,6 +3,5 @@
|
|||||||
"exclude": ["node_modules", "dist"],
|
"exclude": ["node_modules", "dist"],
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"baseUrl": "src",
|
"baseUrl": "src",
|
||||||
"declarationDir": "dist"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
14
terminus-settings/tsconfig.typings.json
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
{
|
||||||
|
"extends": "../tsconfig.json",
|
||||||
|
"exclude": ["node_modules", "dist", "typings"],
|
||||||
|
"compilerOptions": {
|
||||||
|
"baseUrl": "src",
|
||||||
|
"emitDeclarationOnly": true,
|
||||||
|
"declaration": true,
|
||||||
|
"declarationDir": "./typings",
|
||||||
|
"paths": {
|
||||||
|
"terminus-*": ["../../terminus-*"],
|
||||||
|
"*": ["../../app/node_modules/*"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -4,7 +4,7 @@ const webpack = require('webpack')
|
|||||||
module.exports = {
|
module.exports = {
|
||||||
target: 'node',
|
target: 'node',
|
||||||
entry: 'src/index.ts',
|
entry: 'src/index.ts',
|
||||||
devtool: 'source-map',
|
devtool: 'eval-source-map',
|
||||||
context: __dirname,
|
context: __dirname,
|
||||||
mode: 'development',
|
mode: 'development',
|
||||||
output: {
|
output: {
|
||||||
|
@@ -2,22 +2,22 @@
|
|||||||
# yarn lockfile v1
|
# yarn lockfile v1
|
||||||
|
|
||||||
|
|
||||||
"@types/deep-equal@1.0.0":
|
"@types/deep-equal@1.0.1":
|
||||||
version "1.0.0"
|
version "1.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/@types/deep-equal/-/deep-equal-1.0.0.tgz#9ebeaa73d1fc4791f038a5f1440e0449ea968495"
|
resolved "https://registry.yarnpkg.com/@types/deep-equal/-/deep-equal-1.0.1.tgz#71cfabb247c22bcc16d536111f50c0ed12476b03"
|
||||||
integrity sha1-nr6qc9H8R5HwOKXxRA4ESeqWhJU=
|
integrity sha512-mMUu4nWHLBlHtxXY17Fg6+ucS/MnndyOWyOe7MmwkoMYxvfQU2ajtRaEvqSUv+aVkMqH/C0NCI8UoVfRNQ10yg==
|
||||||
|
|
||||||
"@types/node@7.0.12":
|
"@types/node@12.0.7":
|
||||||
version "7.0.12"
|
version "12.0.7"
|
||||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-7.0.12.tgz#ae5f67a19c15f752148004db07cbbb372e69efc9"
|
resolved "https://registry.yarnpkg.com/@types/node/-/node-12.0.7.tgz#4f2563bad652b2acb1722d7e7aae2b0ff62d192c"
|
||||||
integrity sha1-rl9noZwV91IUgATbB8u7Ny5p78k=
|
integrity sha512-1YKeT4JitGgE4SOzyB9eMwO0nGVNkNEsm9qlIt1Lqm/tG2QEiSMTD4kS3aO6L+w5SClLVxALmIBESK6Mk5wX0A==
|
||||||
|
|
||||||
"@types/webpack-env@1.13.0":
|
"@types/webpack-env@1.13.9":
|
||||||
version "1.13.0"
|
version "1.13.9"
|
||||||
resolved "https://registry.yarnpkg.com/@types/webpack-env/-/webpack-env-1.13.0.tgz#3044381647e11ee973c5af2e925323930f691d80"
|
resolved "https://registry.yarnpkg.com/@types/webpack-env/-/webpack-env-1.13.9.tgz#a67287861c928ebf4159a908d1fb1a2a34d4097a"
|
||||||
integrity sha1-MEQ4FkfhHulzxa8uklMjkw9pHYA=
|
integrity sha512-p8zp5xqkly3g4cCmo2mKOHI9+Z/kObmDj0BmjbDDJQlgDTiEGTbm17MEwTAusV6XceCy+bNw9q/ZHXHyKo3zkg==
|
||||||
|
|
||||||
ngx-pipes@^1.6.1:
|
ngx-pipes@^1.6.1:
|
||||||
version "1.6.5"
|
version "1.6.6"
|
||||||
resolved "https://registry.yarnpkg.com/ngx-pipes/-/ngx-pipes-1.6.5.tgz#7dfe7bf1425b2e661ecde0e8a419e82be575dfa1"
|
resolved "https://registry.yarnpkg.com/ngx-pipes/-/ngx-pipes-1.6.6.tgz#32bb80906c220f1e84d5cce7d6dae002cffead4b"
|
||||||
integrity sha512-CtiDGlQITKUszBrHo6JoBOiS8iAuqoEm7ptHMEfD3iJvzRK9tNK4ZEmmBxqUPwzAPyjeGW8ALlul1QdqFrOoSg==
|
integrity sha512-mRV0xOZDd6/Jlvti4W0pDepZRIHLHd3kZ6ZzdqyGCU0dxbKVWWLTR1jlNlxN1ruMk8eO0Y8lNh6a1bEW7dJP1w==
|
||||||
|
@@ -1,12 +1,12 @@
|
|||||||
{
|
{
|
||||||
"name": "terminus-ssh",
|
"name": "terminus-ssh",
|
||||||
"version": "1.0.68-c17-g8b64a81",
|
"version": "1.0.73-c4-ga7d62b0",
|
||||||
"description": "SSH connection manager for Terminus",
|
"description": "SSH connection manager for Terminus",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"terminus-builtin-plugin"
|
"terminus-builtin-plugin"
|
||||||
],
|
],
|
||||||
"main": "dist/index.js",
|
"main": "dist/index.js",
|
||||||
"typings": "dist/index.d.ts",
|
"typings": "typings/index.d.ts",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "webpack --progress --color",
|
"build": "webpack --progress --color",
|
||||||
"watch": "webpack --progress --color --watch"
|
"watch": "webpack --progress --color --watch"
|
||||||
@@ -19,28 +19,24 @@
|
|||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/ssh2": "^0.5.35",
|
"@types/ssh2": "^0.5.35",
|
||||||
"@types/webpack-env": "^1.13.0",
|
"@types/webpack-env": "^1.13.0",
|
||||||
"electron": "^1.6.11",
|
|
||||||
"ngx-toastr": "^8.0.0",
|
"ngx-toastr": "^8.0.0",
|
||||||
"rxjs": "^5.4.0",
|
"ssh2": "^0.8.2",
|
||||||
"typescript": "^2.2.2",
|
"ssh2-streams": "^0.4.2"
|
||||||
"webpack": "^2.3.3"
|
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@angular/common": "^4.1.3",
|
"@angular/common": "^4.1.3",
|
||||||
"@angular/core": "^4.1.3",
|
"@angular/core": "^4.1.3",
|
||||||
"@angular/forms": "^4.1.3",
|
"@angular/forms": "^4.1.3",
|
||||||
"@ng-bootstrap/ng-bootstrap": "^1.0.0-alpha.29",
|
"@ng-bootstrap/ng-bootstrap": "^1.0.0-alpha.29",
|
||||||
|
"rxjs": "^5.4.0",
|
||||||
"terminus-core": "*",
|
"terminus-core": "*",
|
||||||
"terminus-settings": "*",
|
"terminus-settings": "*",
|
||||||
"terminus-terminal": "*"
|
"terminus-terminal": "*"
|
||||||
},
|
},
|
||||||
"optionalDependencies": {
|
"optionalDependencies": {
|
||||||
"wincredmgr": "^2.0.0",
|
"windows-process-tree": "^0.2.3"
|
||||||
"windows-process-tree": "^0.2.3",
|
|
||||||
"xkeychain": "^0.0.6"
|
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"ssh2": "^0.8.2",
|
"keytar": "^4.7.0"
|
||||||
"ssh2-streams": "^0.4.2"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -27,24 +27,19 @@ export class EditConnectionModalComponent {
|
|||||||
this.newScript = { expect: '', send: '' }
|
this.newScript = { expect: '', send: '' }
|
||||||
|
|
||||||
for (let k of Object.values(SSHAlgorithmType)) {
|
for (let k of Object.values(SSHAlgorithmType)) {
|
||||||
this.supportedAlgorithms[k] = ALGORITHMS[
|
this.supportedAlgorithms[k] = ALGORITHMS[{
|
||||||
{
|
[SSHAlgorithmType.KEX]: 'SUPPORTED_KEX',
|
||||||
[SSHAlgorithmType.KEX]: 'SUPPORTED_KEX',
|
[SSHAlgorithmType.HOSTKEY]: 'SUPPORTED_SERVER_HOST_KEY',
|
||||||
[SSHAlgorithmType.HOSTKEY]: 'SUPPORTED_SERVER_HOST_KEY',
|
[SSHAlgorithmType.CIPHER]: 'SUPPORTED_CIPHER',
|
||||||
[SSHAlgorithmType.CIPHER]: 'SUPPORTED_CIPHER',
|
[SSHAlgorithmType.HMAC]: 'SUPPORTED_HMAC',
|
||||||
[SSHAlgorithmType.HMAC]: 'SUPPORTED_HMAC',
|
}[k]]
|
||||||
}[k]
|
this.defaultAlgorithms[k] = ALGORITHMS[{
|
||||||
]
|
[SSHAlgorithmType.KEX]: 'KEX',
|
||||||
this.defaultAlgorithms[k] = ALGORITHMS[
|
[SSHAlgorithmType.HOSTKEY]: 'SERVER_HOST_KEY',
|
||||||
{
|
[SSHAlgorithmType.CIPHER]: 'CIPHER',
|
||||||
[SSHAlgorithmType.KEX]: 'KEX',
|
[SSHAlgorithmType.HMAC]: 'HMAC',
|
||||||
[SSHAlgorithmType.HOSTKEY]: 'SERVER_HOST_KEY',
|
}[k]]
|
||||||
[SSHAlgorithmType.CIPHER]: 'CIPHER',
|
|
||||||
[SSHAlgorithmType.HMAC]: 'HMAC',
|
|
||||||
}[k]
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
console.log(this)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async ngOnInit () {
|
async ngOnInit () {
|
||||||
|
@@ -1,6 +1,7 @@
|
|||||||
:host {
|
:host {
|
||||||
flex: auto;
|
flex: auto;
|
||||||
display: flex;
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
|
||||||
&> .content {
|
&> .content {
|
||||||
|
@@ -12,7 +12,8 @@ import { SSHConnection, SSHSession } from '../api'
|
|||||||
class="content"
|
class="content"
|
||||||
></div>
|
></div>
|
||||||
`,
|
`,
|
||||||
styles: [require('./sshTab.component.scss')],
|
styles: [require('./sshTab.component.scss'), ...BaseTerminalTabComponent.styles],
|
||||||
|
animations: BaseTerminalTabComponent.animations,
|
||||||
})
|
})
|
||||||
export class SSHTabComponent extends BaseTerminalTabComponent {
|
export class SSHTabComponent extends BaseTerminalTabComponent {
|
||||||
connection: SSHConnection
|
connection: SSHConnection
|
||||||
|
@@ -1,74 +1,18 @@
|
|||||||
import { Injectable, NgZone } from '@angular/core'
|
import { Injectable } from '@angular/core'
|
||||||
import { SSHConnection } from '../api'
|
import { SSHConnection } from '../api'
|
||||||
|
import * as keytar from 'keytar'
|
||||||
|
|
||||||
let xkeychain
|
|
||||||
let wincredmgr
|
|
||||||
try {
|
|
||||||
xkeychain = require('xkeychain')
|
|
||||||
} catch (error) {
|
|
||||||
try {
|
|
||||||
wincredmgr = require('wincredmgr')
|
|
||||||
} catch (error2) {
|
|
||||||
console.warn('No keychain manager available')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** @hidden */
|
|
||||||
@Injectable({ providedIn: 'root' })
|
@Injectable({ providedIn: 'root' })
|
||||||
export class PasswordStorageService {
|
export class PasswordStorageService {
|
||||||
constructor (
|
async savePassword (connection: SSHConnection, password: string): Promise<void> {
|
||||||
private zone: NgZone,
|
return keytar.setPassword(`ssh@${connection.host}`, connection.user, password)
|
||||||
) { }
|
|
||||||
|
|
||||||
savePassword (connection: SSHConnection, password: string) {
|
|
||||||
if (xkeychain) {
|
|
||||||
xkeychain.setPassword({
|
|
||||||
account: connection.user,
|
|
||||||
service: `ssh@${connection.host}`,
|
|
||||||
password
|
|
||||||
}, () => null)
|
|
||||||
} else {
|
|
||||||
wincredmgr.WriteCredentials(
|
|
||||||
'user',
|
|
||||||
password,
|
|
||||||
`ssh:${connection.user}@${connection.host}`,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
deletePassword (connection: SSHConnection) {
|
async deletePassword (connection: SSHConnection): Promise<void> {
|
||||||
if (xkeychain) {
|
await keytar.deletePassword(`ssh@${connection.host}`, connection.user)
|
||||||
xkeychain.deletePassword({
|
|
||||||
account: connection.user,
|
|
||||||
service: `ssh@${connection.host}`,
|
|
||||||
}, () => null)
|
|
||||||
} else {
|
|
||||||
wincredmgr.DeleteCredentials(
|
|
||||||
`ssh:${connection.user}@${connection.host}`,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
loadPassword (connection: SSHConnection): Promise<string> {
|
async loadPassword (connection: SSHConnection): Promise<string> {
|
||||||
return new Promise(resolve => {
|
return keytar.getPassword(`ssh@${connection.host}`, connection.user)
|
||||||
if (!wincredmgr && !xkeychain.isSupported()) {
|
|
||||||
return resolve(null)
|
|
||||||
}
|
|
||||||
if (xkeychain) {
|
|
||||||
xkeychain.getPassword(
|
|
||||||
{
|
|
||||||
account: connection.user,
|
|
||||||
service: `ssh@${connection.host}`,
|
|
||||||
},
|
|
||||||
(_, result) => this.zone.run(() => resolve(result))
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
try {
|
|
||||||
resolve(wincredmgr.ReadCredentials(`ssh:${connection.user}@${connection.host}`).password)
|
|
||||||
} catch (error) {
|
|
||||||
resolve(null)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,12 +1,7 @@
|
|||||||
{
|
{
|
||||||
"extends": "../tsconfig.json",
|
"extends": "../tsconfig.json",
|
||||||
"exclude": ["node_modules", "dist"],
|
"exclude": ["node_modules", "dist", "typings"],
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"baseUrl": "src",
|
"baseUrl": "src"
|
||||||
"declarationDir": "dist",
|
|
||||||
"paths": {
|
|
||||||
"terminus-*": ["terminus-*"],
|
|
||||||
"*": ["app/node_modules/*"]
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
15
terminus-ssh/tsconfig.typings.json
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
{
|
||||||
|
"extends": "../tsconfig.json",
|
||||||
|
"exclude": ["node_modules", "dist", "typings"],
|
||||||
|
"include": ["src"],
|
||||||
|
"compilerOptions": {
|
||||||
|
"baseUrl": "src",
|
||||||
|
"emitDeclarationOnly": true,
|
||||||
|
"declaration": true,
|
||||||
|
"declarationDir": "./typings",
|
||||||
|
"paths": {
|
||||||
|
"terminus-*": ["../../terminus-*"],
|
||||||
|
"*": ["../../app/node_modules/*"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -3,7 +3,7 @@ const path = require('path')
|
|||||||
module.exports = {
|
module.exports = {
|
||||||
target: 'node',
|
target: 'node',
|
||||||
entry: 'src/index.ts',
|
entry: 'src/index.ts',
|
||||||
devtool: 'source-map',
|
devtool: 'eval-source-map',
|
||||||
context: __dirname,
|
context: __dirname,
|
||||||
output: {
|
output: {
|
||||||
path: path.resolve(__dirname, 'dist'),
|
path: path.resolve(__dirname, 'dist'),
|
||||||
@@ -43,10 +43,7 @@ module.exports = {
|
|||||||
},
|
},
|
||||||
externals: [
|
externals: [
|
||||||
'fs',
|
'fs',
|
||||||
'node-ssh',
|
'keytar',
|
||||||
'ssh2-streams',
|
|
||||||
'xkeychain',
|
|
||||||
'wincredmgr',
|
|
||||||
'path',
|
'path',
|
||||||
'ngx-toastr',
|
'ngx-toastr',
|
||||||
'windows-process-tree/build/Release/windows_process_tree.node',
|
'windows-process-tree/build/Release/windows_process_tree.node',
|
||||||
|
@@ -1,12 +1,12 @@
|
|||||||
{
|
{
|
||||||
"name": "terminus-terminal",
|
"name": "terminus-terminal",
|
||||||
"version": "1.0.68-c17-g8b64a81",
|
"version": "1.0.73-c4-ga7d62b0",
|
||||||
"description": "Terminus' terminal emulation core",
|
"description": "Terminus' terminal emulation core",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"terminus-builtin-plugin"
|
"terminus-builtin-plugin"
|
||||||
],
|
],
|
||||||
"main": "dist/index.js",
|
"main": "dist/index.js",
|
||||||
"typings": "dist/src/index.d.ts",
|
"typings": "typings/index.d.ts",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "webpack --progress --color --display-modules",
|
"build": "webpack --progress --color --display-modules",
|
||||||
"watch": "webpack --progress --color --watch"
|
"watch": "webpack --progress --color --watch"
|
||||||
@@ -18,17 +18,21 @@
|
|||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/deep-equal": "^1.0.0",
|
"@types/deep-equal": "^1.0.0",
|
||||||
"@types/mz": "0.0.31",
|
"@types/mz": "0.0.32",
|
||||||
"@types/node": "7.0.12",
|
"@types/node": "12.0.7",
|
||||||
"@types/slug": "^0.9.1",
|
"@types/slug": "^0.9.1",
|
||||||
"@types/webpack-env": "1.13.0",
|
"@types/webpack-env": "1.13.9",
|
||||||
"dataurl": "0.1.0",
|
"dataurl": "0.1.0",
|
||||||
"deep-equal": "1.0.1",
|
"deep-equal": "1.0.1",
|
||||||
"file-loader": "^0.11.2",
|
"file-loader": "^0.11.2",
|
||||||
"slug": "^0.9.3",
|
"hterm-umdjs": "1.4.1",
|
||||||
|
"mz": "^2.6.0",
|
||||||
|
"ps-node": "^0.1.6",
|
||||||
|
"runes": "^0.4.2",
|
||||||
|
"slug": "^1.1.0",
|
||||||
"uuid": "^3.3.2",
|
"uuid": "^3.3.2",
|
||||||
"xterm": "3.10.1",
|
"xterm": "https://registry.npmjs.org/@terminus-term/xterm/-/xterm-3.14.1.tgz",
|
||||||
"xterm-addon-ligatures-tmp": "^0.1.0-beta-1"
|
"xterm-addon-ligatures": "^0.1.0-beta-2"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@angular/common": "4.0.1",
|
"@angular/common": "4.0.1",
|
||||||
@@ -41,17 +45,12 @@
|
|||||||
"terminus-settings": "*"
|
"terminus-settings": "*"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@terminus-term/node-pty": "^0.8.1",
|
"fontmanager-redux": "0.3.2",
|
||||||
"font-manager": "0.3.0",
|
"node-pty": "^0.9.0-beta9"
|
||||||
"hterm-umdjs": "1.4.1",
|
|
||||||
"mz": "^2.6.0",
|
|
||||||
"ps-node": "^0.1.6",
|
|
||||||
"runes": "^0.4.2"
|
|
||||||
},
|
},
|
||||||
"optionalDependencies": {
|
"optionalDependencies": {
|
||||||
"macos-native-processlist": "^1.0.0",
|
"@terminus-term/windows-process-tree": "^0.2.4",
|
||||||
"windows-native-registry": "^1.0.6",
|
"macos-native-processlist": "^1.0.1",
|
||||||
"windows-process-tree": "^0.2.3"
|
"windows-native-registry": "^1.0.14"
|
||||||
},
|
}
|
||||||
"false": {}
|
|
||||||
}
|
}
|
||||||
|
@@ -1,83 +0,0 @@
|
|||||||
import { BaseTerminalTabComponent } from './components/baseTerminalTab.component'
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Extend to automatically run actions on new terminals
|
|
||||||
*/
|
|
||||||
export abstract class TerminalDecorator {
|
|
||||||
/**
|
|
||||||
* Called when a new terminal tab starts
|
|
||||||
*/
|
|
||||||
attach (terminal: BaseTerminalTabComponent): void { } // tslint:disable-line no-empty
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Called before a terminal tab is destroyed
|
|
||||||
*/
|
|
||||||
detach (terminal: BaseTerminalTabComponent): void { } // tslint:disable-line no-empty
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface ResizeEvent {
|
|
||||||
columns: number
|
|
||||||
rows: number
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface SessionOptions {
|
|
||||||
name?: string
|
|
||||||
command: string
|
|
||||||
args: string[]
|
|
||||||
cwd?: string
|
|
||||||
env?: {[id: string]: string}
|
|
||||||
width?: number
|
|
||||||
height?: number
|
|
||||||
pauseAfterExit?: boolean
|
|
||||||
runAsAdministrator?: boolean
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface Profile {
|
|
||||||
name: string,
|
|
||||||
sessionOptions: SessionOptions,
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface ITerminalColorScheme {
|
|
||||||
name: string
|
|
||||||
foreground: string
|
|
||||||
background: string
|
|
||||||
cursor: string
|
|
||||||
colors: string[]
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Extend to add more terminal color schemes
|
|
||||||
*/
|
|
||||||
export abstract class TerminalColorSchemeProvider {
|
|
||||||
abstract async getSchemes (): Promise<ITerminalColorScheme[]>
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Extend to add more terminal context menu items
|
|
||||||
*/
|
|
||||||
export abstract class TerminalContextMenuItemProvider {
|
|
||||||
weight: number
|
|
||||||
|
|
||||||
abstract async getItems (tab: BaseTerminalTabComponent): Promise<Electron.MenuItemConstructorOptions[]>
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface IShell {
|
|
||||||
id: string
|
|
||||||
name?: string
|
|
||||||
command: string
|
|
||||||
args?: string[]
|
|
||||||
env?: {[id: string]: string}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Base path to which shell's internal FS is relative
|
|
||||||
* Currently used for WSL only
|
|
||||||
*/
|
|
||||||
fsBase?: string
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Extend to add support for more shells
|
|
||||||
*/
|
|
||||||
export abstract class ShellProvider {
|
|
||||||
abstract async provide (): Promise<IShell[]>
|
|
||||||
}
|
|
@@ -2,30 +2,38 @@ import { Observable, Subject, Subscription } from 'rxjs'
|
|||||||
import { first } from 'rxjs/operators'
|
import { first } from 'rxjs/operators'
|
||||||
import { ToastrService } from 'ngx-toastr'
|
import { ToastrService } from 'ngx-toastr'
|
||||||
import { NgZone, OnInit, OnDestroy, Inject, Injector, Optional, ViewChild, HostBinding, Input, ElementRef } from '@angular/core'
|
import { NgZone, OnInit, OnDestroy, Inject, Injector, Optional, ViewChild, HostBinding, Input, ElementRef } from '@angular/core'
|
||||||
|
import { trigger, transition, style, animate, AnimationTriggerMetadata } from '@angular/animations'
|
||||||
import { AppService, ConfigService, BaseTabComponent, ElectronService, HostAppService, HotkeysService, Platform, LogService, Logger } from 'terminus-core'
|
import { AppService, ConfigService, BaseTabComponent, ElectronService, HostAppService, HotkeysService, Platform, LogService, Logger } from 'terminus-core'
|
||||||
|
|
||||||
import { BaseSession, SessionsService } from '../services/sessions.service'
|
import { BaseSession, SessionsService } from '../services/sessions.service'
|
||||||
import { TerminalFrontendService } from '../services/terminalFrontend.service'
|
import { TerminalFrontendService } from '../services/terminalFrontend.service'
|
||||||
|
|
||||||
import { TerminalDecorator, ResizeEvent, TerminalContextMenuItemProvider } from '../api'
|
|
||||||
import { Frontend } from '../frontends/frontend'
|
import { Frontend } from '../frontends/frontend'
|
||||||
|
import { ResizeEvent } from './interfaces'
|
||||||
|
import { TerminalDecorator } from './decorator'
|
||||||
|
import { TerminalContextMenuItemProvider } from './contextMenuProvider'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A class to base your custom terminal tabs on
|
* A class to base your custom terminal tabs on
|
||||||
*/
|
*/
|
||||||
export class BaseTerminalTabComponent extends BaseTabComponent implements OnInit, OnDestroy {
|
export class BaseTerminalTabComponent extends BaseTabComponent implements OnInit, OnDestroy {
|
||||||
static template = `
|
static template = require('../components/baseTerminalTab.component.pug')
|
||||||
<div
|
static styles = [require('../components/terminalTab.component.scss')]
|
||||||
#content
|
static animations: AnimationTriggerMetadata[] = [trigger('slideInOut', [
|
||||||
class="content"
|
transition(':enter', [
|
||||||
[style.opacity]="frontendIsReady ? 1 : 0"
|
style({ transform: 'translateY(-25%)' }),
|
||||||
></div>
|
animate('100ms ease-in-out', style({ transform: 'translateY(0%)' }))
|
||||||
`
|
]),
|
||||||
static styles = [require('./terminalTab.component.scss')]
|
transition(':leave', [
|
||||||
|
animate('100ms ease-in-out', style({ transform: 'translateY(-25%)' }))
|
||||||
|
])
|
||||||
|
])]
|
||||||
|
|
||||||
session: BaseSession
|
session: BaseSession
|
||||||
@Input() zoom = 0
|
@Input() zoom = 0
|
||||||
|
|
||||||
|
@Input() showSearchPanel = false
|
||||||
|
|
||||||
/** @hidden */
|
/** @hidden */
|
||||||
@ViewChild('content') content
|
@ViewChild('content') content
|
||||||
|
|
||||||
@@ -110,12 +118,6 @@ export class BaseTerminalTabComponent extends BaseTabComponent implements OnInit
|
|||||||
case 'reset-zoom':
|
case 'reset-zoom':
|
||||||
this.resetZoom()
|
this.resetZoom()
|
||||||
break
|
break
|
||||||
case 'home':
|
|
||||||
this.sendInput('\x1bOH')
|
|
||||||
break
|
|
||||||
case 'end':
|
|
||||||
this.sendInput('\x1bOF')
|
|
||||||
break
|
|
||||||
case 'previous-word':
|
case 'previous-word':
|
||||||
this.sendInput('\x1bb')
|
this.sendInput('\x1bb')
|
||||||
break
|
break
|
||||||
@@ -128,6 +130,12 @@ export class BaseTerminalTabComponent extends BaseTabComponent implements OnInit
|
|||||||
case 'delete-next-word':
|
case 'delete-next-word':
|
||||||
this.sendInput('\x1bd')
|
this.sendInput('\x1bd')
|
||||||
break
|
break
|
||||||
|
case 'search':
|
||||||
|
this.showSearchPanel = true
|
||||||
|
setImmediate(() => {
|
||||||
|
this.element.nativeElement.querySelector('.search-input').focus()
|
||||||
|
})
|
||||||
|
break
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
this.bellPlayer = document.createElement('audio')
|
this.bellPlayer = document.createElement('audio')
|
8
terminus-terminal/src/api/colorSchemeProvider.ts
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
import { ITerminalColorScheme } from './interfaces'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extend to add more terminal color schemes
|
||||||
|
*/
|
||||||
|
export abstract class TerminalColorSchemeProvider {
|
||||||
|
abstract async getSchemes (): Promise<ITerminalColorScheme[]>
|
||||||
|
}
|
10
terminus-terminal/src/api/contextMenuProvider.ts
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
import { BaseTerminalTabComponent } from './baseTerminalTab.component'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extend to add more terminal context menu items
|
||||||
|
*/
|
||||||
|
export abstract class TerminalContextMenuItemProvider {
|
||||||
|
weight: number
|
||||||
|
|
||||||
|
abstract async getItems (tab: BaseTerminalTabComponent): Promise<Electron.MenuItemConstructorOptions[]>
|
||||||
|
}
|
16
terminus-terminal/src/api/decorator.ts
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
import { BaseTerminalTabComponent } from './baseTerminalTab.component'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extend to automatically run actions on new terminals
|
||||||
|
*/
|
||||||
|
export abstract class TerminalDecorator {
|
||||||
|
/**
|
||||||
|
* Called when a new terminal tab starts
|
||||||
|
*/
|
||||||
|
attach (terminal: BaseTerminalTabComponent): void { } // tslint:disable-line no-empty
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called before a terminal tab is destroyed
|
||||||
|
*/
|
||||||
|
detach (terminal: BaseTerminalTabComponent): void { } // tslint:disable-line no-empty
|
||||||
|
}
|
54
terminus-terminal/src/api/interfaces.ts
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
import { SafeHtml } from '@angular/platform-browser'
|
||||||
|
|
||||||
|
export interface ResizeEvent {
|
||||||
|
columns: number
|
||||||
|
rows: number
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface SessionOptions {
|
||||||
|
name?: string
|
||||||
|
command: string
|
||||||
|
args: string[]
|
||||||
|
cwd?: string
|
||||||
|
env?: {[id: string]: string}
|
||||||
|
width?: number
|
||||||
|
height?: number
|
||||||
|
pauseAfterExit?: boolean
|
||||||
|
runAsAdministrator?: boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface Profile {
|
||||||
|
name: string,
|
||||||
|
sessionOptions: SessionOptions,
|
||||||
|
isBuiltin?: boolean
|
||||||
|
icon?: SafeHtml
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ITerminalColorScheme {
|
||||||
|
name: string
|
||||||
|
foreground: string
|
||||||
|
background: string
|
||||||
|
cursor: string
|
||||||
|
colors: string[]
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IShell {
|
||||||
|
id: string
|
||||||
|
name?: string
|
||||||
|
command: string
|
||||||
|
args?: string[]
|
||||||
|
env: {[id: string]: string}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Base path to which shell's internal FS is relative
|
||||||
|
* Currently used for WSL only
|
||||||
|
*/
|
||||||
|
fsBase?: string
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SVG icon
|
||||||
|
*/
|
||||||
|
icon?: SafeHtml
|
||||||
|
|
||||||
|
hidden?: boolean
|
||||||
|
}
|
8
terminus-terminal/src/api/shellProvider.ts
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
import { IShell } from './interfaces'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extend to add support for more shells
|
||||||
|
*/
|
||||||
|
export abstract class ShellProvider {
|
||||||
|
abstract async provide (): Promise<IShell[]>
|
||||||
|
}
|
@@ -2,7 +2,7 @@
|
|||||||
module.exports = function patchPTYModule (mod) {
|
module.exports = function patchPTYModule (mod) {
|
||||||
const oldSpawn = mod.spawn
|
const oldSpawn = mod.spawn
|
||||||
if (mod.patched) {
|
if (mod.patched) {
|
||||||
return mod
|
return
|
||||||
}
|
}
|
||||||
mod.patched = true
|
mod.patched = true
|
||||||
mod.spawn = (file, args, opt) => {
|
mod.spawn = (file, args, opt) => {
|
||||||
@@ -51,5 +51,4 @@ module.exports = function patchPTYModule (mod) {
|
|||||||
})
|
})
|
||||||
return terminal
|
return terminal
|
||||||
}
|
}
|
||||||
return mod
|
|
||||||
}
|
}
|
||||||
|
@@ -31,13 +31,27 @@ export class ButtonProvider extends ToolbarButtonProvider {
|
|||||||
}
|
}
|
||||||
|
|
||||||
provide (): IToolbarButton[] {
|
provide (): IToolbarButton[] {
|
||||||
return [{
|
return [
|
||||||
icon: this.domSanitizer.bypassSecurityTrustHtml(require('./icons/plus.svg')),
|
{
|
||||||
title: 'New terminal',
|
icon: this.domSanitizer.bypassSecurityTrustHtml(require('./icons/plus.svg')),
|
||||||
touchBarNSImage: 'NSTouchBarAddDetailTemplate',
|
title: 'New terminal',
|
||||||
click: async () => {
|
touchBarNSImage: 'NSTouchBarAddDetailTemplate',
|
||||||
this.terminal.openTab()
|
click: async () => {
|
||||||
}
|
this.terminal.openTab()
|
||||||
}]
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
icon: this.domSanitizer.bypassSecurityTrustHtml(require('./icons/profiles.svg')),
|
||||||
|
title: 'New terminal with profile',
|
||||||
|
submenu: async () => {
|
||||||
|
let profiles = await this.terminal.getProfiles()
|
||||||
|
return profiles.map(profile => ({
|
||||||
|
icon: profile.icon,
|
||||||
|
title: profile.name,
|
||||||
|
click: () => this.terminal.openTab(profile),
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
},
|
||||||
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,7 +1,8 @@
|
|||||||
import * as fs from 'mz/fs'
|
import * as fs from 'mz/fs'
|
||||||
import * as path from 'path'
|
import * as path from 'path'
|
||||||
import { Injectable } from '@angular/core'
|
import { Injectable } from '@angular/core'
|
||||||
import { TerminalColorSchemeProvider, ITerminalColorScheme } from './api'
|
import { TerminalColorSchemeProvider } from './api/colorSchemeProvider'
|
||||||
|
import { ITerminalColorScheme } from './api/interfaces'
|
||||||
|
|
||||||
/** @hidden */
|
/** @hidden */
|
||||||
@Injectable()
|
@Injectable()
|
||||||
|
@@ -12,6 +12,7 @@ h3.mb-3 Appearance
|
|||||||
)
|
)
|
||||||
option(value='hterm') hterm
|
option(value='hterm') hterm
|
||||||
option(value='xterm') xterm
|
option(value='xterm') xterm
|
||||||
|
option(value='xterm-webgl') xterm (WebGL)
|
||||||
|
|
||||||
.form-line
|
.form-line
|
||||||
.header
|
.header
|
||||||
|