@electerm/electerm-react 1.37.6 → 1.37.16
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/client/common/constants.js +1 -0
- package/client/common/resolve.js +2 -2
- package/client/components/setting-panel/keywords-form.jsx +16 -1
- package/client/components/setting-panel/setting-terminal.jsx +13 -4
- package/client/components/sftp/zip.js +4 -4
- package/client/components/shortcuts/shortcut-control.jsx +6 -7
- package/client/components/shortcuts/shortcut-handler.js +3 -2
- package/client/components/terminal/highlight-addon.js +6 -2
- package/client/components/terminal/index.jsx +38 -13
- package/package.json +1 -1
|
@@ -307,6 +307,7 @@ export const localAddrBookmarkLsKey = 'local-addr-bookmark-keys'
|
|
|
307
307
|
export const sshTunnelHelpLink = 'https://github.com/electerm/electerm/wiki/How-to-use-ssh-tunnel'
|
|
308
308
|
export const batchOpHelpLink = 'https://github.com/electerm/electerm/wiki/batch-operation'
|
|
309
309
|
export const proxyHelpLink = 'https://github.com/electerm/electerm/wiki/proxy-format'
|
|
310
|
+
export const regexHelpLink = 'https://github.com/electerm/electerm/wiki/Terminal-keywords-highlight-regular-expression-exmaples'
|
|
310
311
|
export const modals = {
|
|
311
312
|
hide: 0,
|
|
312
313
|
setting: 1,
|
package/client/common/resolve.js
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
8
|
export default (basePath, nameOrDot) => {
|
|
9
|
-
const sep = basePath.includes('\\') || basePath.includes('
|
|
9
|
+
const sep = basePath.includes('\\') || basePath.includes(':\\')
|
|
10
10
|
? '\\'
|
|
11
11
|
: '/'
|
|
12
12
|
if (nameOrDot === '..') {
|
|
@@ -18,7 +18,7 @@ export default (basePath, nameOrDot) => {
|
|
|
18
18
|
const res = arr.slice(0, length - 1).join(sep)
|
|
19
19
|
return res || '/'
|
|
20
20
|
}
|
|
21
|
-
const pre = nameOrDot.includes('
|
|
21
|
+
const pre = nameOrDot.includes(':\\') && basePath === '/'
|
|
22
22
|
? ''
|
|
23
23
|
: basePath
|
|
24
24
|
return pre +
|
|
@@ -30,16 +30,31 @@ export default function KeywordForm (props) {
|
|
|
30
30
|
props.submit(data)
|
|
31
31
|
}
|
|
32
32
|
|
|
33
|
+
function checker (_, value) {
|
|
34
|
+
try {
|
|
35
|
+
return Promise.resolve(!!new RegExp(`(${value})`, 'gi'))
|
|
36
|
+
} catch (e) {
|
|
37
|
+
console.log(e)
|
|
38
|
+
return Promise.reject(e)
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
33
42
|
function renderItem (field, i, add, remove) {
|
|
34
43
|
return (
|
|
35
44
|
<Space
|
|
36
45
|
align='center'
|
|
37
46
|
key={field.key}
|
|
47
|
+
className='mg3r'
|
|
38
48
|
>
|
|
39
49
|
<FormItem
|
|
40
50
|
hasFeedback
|
|
41
51
|
>
|
|
42
|
-
<FormItem
|
|
52
|
+
<FormItem
|
|
53
|
+
noStyle
|
|
54
|
+
required
|
|
55
|
+
name={[field.name, 'keyword']}
|
|
56
|
+
rules={[{ validator: checker }]}
|
|
57
|
+
>
|
|
43
58
|
<Input
|
|
44
59
|
addonBefore={renderBefore(field.name)}
|
|
45
60
|
/>
|
|
@@ -17,7 +17,8 @@ import {
|
|
|
17
17
|
import deepCopy from 'json-deep-copy'
|
|
18
18
|
import {
|
|
19
19
|
noTerminalBgValue,
|
|
20
|
-
rendererTypes
|
|
20
|
+
rendererTypes,
|
|
21
|
+
regexHelpLink
|
|
21
22
|
} from '../../common/constants'
|
|
22
23
|
import defaultSettings from '../../common/default-setting'
|
|
23
24
|
import ShowItem from '../common/show-item'
|
|
@@ -25,6 +26,7 @@ import { osResolve } from '../../common/resolve'
|
|
|
25
26
|
import { isNumber, isNaN } from 'lodash-es'
|
|
26
27
|
import mapper from '../../common/auto-complete-data-mapper'
|
|
27
28
|
import KeywordForm from './keywords-form'
|
|
29
|
+
import Link from '../common/external-link'
|
|
28
30
|
import HelpIcon from '../common/help-icon'
|
|
29
31
|
import './setting.styl'
|
|
30
32
|
|
|
@@ -406,7 +408,15 @@ export default class SettingTerminal extends Component {
|
|
|
406
408
|
},
|
|
407
409
|
submit: this.handleSubmitKeywords
|
|
408
410
|
}
|
|
409
|
-
const terminalLogPath = appPath
|
|
411
|
+
const terminalLogPath = appPath
|
|
412
|
+
? osResolve(appPath, 'electerm', 'session_logs')
|
|
413
|
+
: window.et.sessionLogPath
|
|
414
|
+
const tip = (
|
|
415
|
+
<div>
|
|
416
|
+
<span className='mg1r'>{f('supportRegexp')}</span>
|
|
417
|
+
<Link to={regexHelpLink}>wiki</Link>
|
|
418
|
+
</div>
|
|
419
|
+
)
|
|
410
420
|
return (
|
|
411
421
|
<div className='form-wrap pd1y pd2x'>
|
|
412
422
|
<div className='pd1y font16 bold'>
|
|
@@ -451,7 +461,7 @@ export default class SettingTerminal extends Component {
|
|
|
451
461
|
<div className='pd1b'>
|
|
452
462
|
<span className='inline-title mg1r'>{f('keywordsHighlight')}</span>
|
|
453
463
|
<HelpIcon
|
|
454
|
-
title={
|
|
464
|
+
title={tip}
|
|
455
465
|
/>
|
|
456
466
|
</div>
|
|
457
467
|
<KeywordForm
|
|
@@ -480,7 +490,6 @@ export default class SettingTerminal extends Component {
|
|
|
480
490
|
))}
|
|
481
491
|
{
|
|
482
492
|
[
|
|
483
|
-
'addTimeStampToTermLog',
|
|
484
493
|
'cursorBlink',
|
|
485
494
|
'rightClickSelectsWord',
|
|
486
495
|
'pasteWhenContextMenu',
|
|
@@ -12,17 +12,17 @@ const isRemote = true
|
|
|
12
12
|
const temp = '/tmp'
|
|
13
13
|
|
|
14
14
|
export async function zipCmd (pid, sessionId, filePath) {
|
|
15
|
-
// tar -czf bin.tar
|
|
15
|
+
// tar -czf bin.tar bin
|
|
16
16
|
const id = generate()
|
|
17
17
|
const { path, name } = getFolderFromFilePath(filePath, isRemote)
|
|
18
|
-
const np = resolve(temp, `electerm-${id}.tar
|
|
19
|
-
const cmd = `tar -C ${path} -
|
|
18
|
+
const np = resolve(temp, `electerm-${id}.tar`)
|
|
19
|
+
const cmd = `tar -C ${path} -cf ${np} ${name}`
|
|
20
20
|
await runCmd(pid, sessionId, cmd)
|
|
21
21
|
return np
|
|
22
22
|
}
|
|
23
23
|
|
|
24
24
|
export function unzipCmd (pid, sessionId, from, to) {
|
|
25
|
-
const cmd = `tar -
|
|
25
|
+
const cmd = `tar -xf "${from}" -C "${to}"`
|
|
26
26
|
return runCmd(pid, sessionId, cmd)
|
|
27
27
|
}
|
|
28
28
|
|
|
@@ -5,7 +5,6 @@
|
|
|
5
5
|
|
|
6
6
|
import React from 'react'
|
|
7
7
|
import { shortcutExtend } from './shortcut-handler.js'
|
|
8
|
-
import { throttle } from 'lodash-es'
|
|
9
8
|
|
|
10
9
|
class ShortcutControl extends React.PureComponent {
|
|
11
10
|
componentDidMount () {
|
|
@@ -28,18 +27,18 @@ class ShortcutControl extends React.PureComponent {
|
|
|
28
27
|
window.store.onNewSsh()
|
|
29
28
|
}
|
|
30
29
|
|
|
31
|
-
togglefullscreenShortcut =
|
|
30
|
+
togglefullscreenShortcut = (e) => {
|
|
32
31
|
e.stopPropagation()
|
|
33
32
|
const x = document.querySelector('.term-fullscreen-control') ||
|
|
34
|
-
document.querySelector('.term-fullscreen-control1')
|
|
33
|
+
document.querySelector('.session-current .term-fullscreen-control1')
|
|
35
34
|
x && x.click()
|
|
36
|
-
}
|
|
35
|
+
}
|
|
37
36
|
|
|
38
|
-
splitShortcut =
|
|
37
|
+
splitShortcut = (e) => {
|
|
39
38
|
e.stopPropagation()
|
|
40
|
-
const x = document.querySelector('.icon-split')
|
|
39
|
+
const x = document.querySelector('.session-current .icon-split')
|
|
41
40
|
x && x.click()
|
|
42
|
-
}
|
|
41
|
+
}
|
|
43
42
|
|
|
44
43
|
zoominShortcut = (e) => {
|
|
45
44
|
e.stopPropagation()
|
|
@@ -3,6 +3,7 @@ import shortcutsDefaultsGen from './shortcuts-defaults.js'
|
|
|
3
3
|
import {
|
|
4
4
|
isMacJs
|
|
5
5
|
} from '../../common/constants'
|
|
6
|
+
import { throttle } from 'lodash-es'
|
|
6
7
|
|
|
7
8
|
function buildConfig (config, filter = d => d) {
|
|
8
9
|
const defs = shortcutsDefaultsGen().filter(filter)
|
|
@@ -23,7 +24,7 @@ function buildConfig (config, filter = d => d) {
|
|
|
23
24
|
}
|
|
24
25
|
|
|
25
26
|
export function shortcutExtend (Cls) {
|
|
26
|
-
Cls.prototype.handleKeyboardEvent = function (event) {
|
|
27
|
+
Cls.prototype.handleKeyboardEvent = throttle(function (event) {
|
|
27
28
|
const {
|
|
28
29
|
code,
|
|
29
30
|
ctrlKey,
|
|
@@ -60,7 +61,7 @@ export function shortcutExtend (Cls) {
|
|
|
60
61
|
}
|
|
61
62
|
}
|
|
62
63
|
}
|
|
63
|
-
}
|
|
64
|
+
}, 300)
|
|
64
65
|
return Cls
|
|
65
66
|
}
|
|
66
67
|
|
|
@@ -35,8 +35,12 @@ export class KeywordHighlighterAddon {
|
|
|
35
35
|
color = 'red'
|
|
36
36
|
} = obj || {}
|
|
37
37
|
if (keyword) {
|
|
38
|
-
|
|
39
|
-
|
|
38
|
+
try {
|
|
39
|
+
const regex = new RegExp(`(${keyword})`, 'gi')
|
|
40
|
+
text = text.replace(regex, this.colorize(color))
|
|
41
|
+
} catch (e) {
|
|
42
|
+
window.store.onError(e)
|
|
43
|
+
}
|
|
40
44
|
}
|
|
41
45
|
}
|
|
42
46
|
return text
|
|
@@ -41,6 +41,7 @@ import { WebLinksAddon } from 'xterm-addon-web-links'
|
|
|
41
41
|
import { SerializeAddon } from 'xterm-addon-serialize'
|
|
42
42
|
import { CanvasAddon } from 'xterm-addon-canvas'
|
|
43
43
|
import { WebglAddon } from 'xterm-addon-webgl'
|
|
44
|
+
import { LigaturesAddon } from 'xterm-addon-ligatures'
|
|
44
45
|
import getProxy from '../../common/get-proxy'
|
|
45
46
|
import { Zmodem, AddonZmodem } from './xterm-zmodem'
|
|
46
47
|
import { Unicode11Addon } from 'xterm-addon-unicode11'
|
|
@@ -767,12 +768,32 @@ class Term extends Component {
|
|
|
767
768
|
}
|
|
768
769
|
}
|
|
769
770
|
|
|
771
|
+
parse (rawText) {
|
|
772
|
+
let result = ''
|
|
773
|
+
const len = rawText.length
|
|
774
|
+
for (let i = 0; i < len; i++) {
|
|
775
|
+
if (rawText[i] === '\b') {
|
|
776
|
+
result = result.slice(0, -1)
|
|
777
|
+
} else {
|
|
778
|
+
result += rawText[i]
|
|
779
|
+
}
|
|
780
|
+
}
|
|
781
|
+
return result
|
|
782
|
+
}
|
|
783
|
+
|
|
784
|
+
onKey = ({ key }) => {
|
|
785
|
+
if (key === '\x7F') {
|
|
786
|
+
this.dataCache = this.dataCache.slice(0, -1)
|
|
787
|
+
} else {
|
|
788
|
+
this.dataCache += key
|
|
789
|
+
}
|
|
790
|
+
}
|
|
791
|
+
|
|
770
792
|
onData = (d) => {
|
|
771
|
-
if (!d.includes('\r')
|
|
772
|
-
this.dataCache += d
|
|
793
|
+
if (!d.includes('\r')) {
|
|
773
794
|
delete this.userTypeExit
|
|
774
795
|
} else {
|
|
775
|
-
const data = this.dataCache.trim()
|
|
796
|
+
const data = this.parse(this.dataCache.trim())
|
|
776
797
|
this.dataCache = ''
|
|
777
798
|
if (data === 'exit') {
|
|
778
799
|
this.userTypeExit = true
|
|
@@ -815,27 +836,31 @@ class Term extends Component {
|
|
|
815
836
|
fontSize: tab.fontSize || config.fontSize,
|
|
816
837
|
screenReaderMode: config.screenReaderMode
|
|
817
838
|
})
|
|
839
|
+
|
|
840
|
+
// term.onLineFeed(this.onLineFeed)
|
|
841
|
+
// term.onTitleChange(this.onTitleChange)
|
|
842
|
+
term.onSelectionChange(this.onSelection)
|
|
843
|
+
this.loadState(term)
|
|
844
|
+
term.open(document.getElementById(id), true)
|
|
845
|
+
this.loadRenderer(term, config)
|
|
846
|
+
term.textarea.addEventListener('focus', this.setActive)
|
|
847
|
+
term.onKey(this.onKey)
|
|
848
|
+
// term.textarea.addEventListener('blur', this.onBlur)
|
|
849
|
+
|
|
850
|
+
// term.on('keydown', this.handleEvent)
|
|
818
851
|
this.fitAddon = new FitAddon()
|
|
819
852
|
this.searchAddon = new SearchAddon()
|
|
853
|
+
const ligtureAddon = new LigaturesAddon()
|
|
820
854
|
this.searchAddon.onDidChangeResults(this.onSearchResultsChange)
|
|
821
855
|
const unicode11Addon = new Unicode11Addon()
|
|
822
856
|
this.serializeAddon = new SerializeAddon()
|
|
823
857
|
term.loadAddon(this.serializeAddon)
|
|
824
858
|
term.loadAddon(unicode11Addon)
|
|
859
|
+
term.loadAddon(ligtureAddon)
|
|
825
860
|
// activate the new version
|
|
826
861
|
term.unicode.activeVersion = '11'
|
|
827
862
|
term.loadAddon(this.fitAddon)
|
|
828
863
|
term.loadAddon(this.searchAddon)
|
|
829
|
-
// term.onLineFeed(this.onLineFeed)
|
|
830
|
-
// term.onTitleChange(this.onTitleChange)
|
|
831
|
-
term.onSelectionChange(this.onSelection)
|
|
832
|
-
this.loadState(term)
|
|
833
|
-
term.open(document.getElementById(id), true)
|
|
834
|
-
this.loadRenderer(term, config)
|
|
835
|
-
term.textarea.addEventListener('focus', this.setActive)
|
|
836
|
-
// term.textarea.addEventListener('blur', this.onBlur)
|
|
837
|
-
|
|
838
|
-
// term.on('keydown', this.handleEvent)
|
|
839
864
|
term.onData(this.onData)
|
|
840
865
|
this.term = term
|
|
841
866
|
term.attachCustomKeyEventHandler(this.handleKeyboardEvent.bind(this))
|