@electerm/electerm-react 1.39.109 → 1.40.1
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 +0 -1
- package/client/components/bookmark-form/bookmark-select.jsx +96 -0
- package/client/components/bookmark-form/color-picker.jsx +18 -9
- package/client/components/bookmark-form/form-ssh-common.jsx +4 -2
- package/client/components/bookmark-form/profile-form-item.jsx +43 -0
- package/client/components/bookmark-form/rdp-form-ui.jsx +10 -9
- package/client/components/bookmark-form/render-auth-ssh.jsx +6 -3
- package/client/components/bookmark-form/render-connection-hopping.jsx +15 -1
- package/client/components/bookmark-form/render-profile-item.jsx +0 -0
- package/client/components/bookmark-form/telnet-form-ui.jsx +19 -40
- package/client/components/bookmark-form/vnc-form-ui.jsx +6 -1
- package/client/components/bookmark-form/web-form-ui.jsx +1 -1
- package/client/components/profile/profile-form-elem.jsx +14 -28
- package/client/components/profile/profile-form-rdp.jsx +31 -0
- package/client/components/profile/profile-form-ssh.jsx +41 -0
- package/client/components/profile/profile-form-telnet.jsx +35 -0
- package/client/components/profile/profile-form-vnc.jsx +31 -0
- package/client/components/profile/profile-tabs.jsx +32 -0
- package/client/components/quick-commands/on-drop.js +19 -0
- package/client/components/quick-commands/quick-commands-box.jsx +2 -17
- package/client/components/quick-commands/quick-commands-list.jsx +4 -19
- package/client/components/rdp/rdp-session.jsx +3 -9
- package/client/components/setting-panel/keywords-form.jsx +5 -0
- package/client/components/setting-panel/keywords-transport.jsx +32 -0
- package/client/components/setting-panel/setting-terminal.jsx +16 -1
- package/client/components/setting-panel/tab-themes.jsx +2 -2
- package/client/components/sftp/file-item.jsx +2 -2
- package/client/components/terminal/attach-addon-custom.js +12 -11
- package/client/components/terminal/index.jsx +40 -6
- package/client/components/theme/theme-edit-slot.jsx +28 -0
- package/client/components/theme/theme-editor.jsx +37 -0
- package/client/components/{terminal-theme/index.jsx → theme/theme-form.jsx} +103 -34
- package/client/components/theme/theme-form.styl +10 -0
- package/client/components/vnc/vnc-session.jsx +2 -1
- package/client/store/common.js +25 -4
- package/client/store/sync.js +4 -4
- package/package.json +1 -1
- /package/client/components/{terminal-theme → theme}/terminal-theme-list.styl +0 -0
- /package/client/components/{terminal-theme → theme}/theme-list.jsx +0 -0
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Form,
|
|
3
|
+
Input
|
|
4
|
+
} from 'antd'
|
|
5
|
+
import { formItemLayout } from '../../common/form-layout'
|
|
6
|
+
|
|
7
|
+
const FormItem = Form.Item
|
|
8
|
+
const e = window.translate
|
|
9
|
+
|
|
10
|
+
export default function ProfileFormVnc (props) {
|
|
11
|
+
return (
|
|
12
|
+
<>
|
|
13
|
+
<FormItem
|
|
14
|
+
{...formItemLayout}
|
|
15
|
+
label={e('username')}
|
|
16
|
+
hasFeedback
|
|
17
|
+
name={['vnc', 'username']}
|
|
18
|
+
>
|
|
19
|
+
<Input />
|
|
20
|
+
</FormItem>
|
|
21
|
+
<FormItem
|
|
22
|
+
{...formItemLayout}
|
|
23
|
+
label={e('password')}
|
|
24
|
+
hasFeedback
|
|
25
|
+
name={['vnc', 'password']}
|
|
26
|
+
>
|
|
27
|
+
<Input.Password />
|
|
28
|
+
</FormItem>
|
|
29
|
+
</>
|
|
30
|
+
)
|
|
31
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { Tabs } from 'antd'
|
|
2
|
+
import ProfileFormSsh from './profile-form-ssh'
|
|
3
|
+
import ProfileFormRdp from './profile-form-rdp'
|
|
4
|
+
import ProfileFormVnc from './profile-form-vnc'
|
|
5
|
+
import ProfileFormTelnet from './profile-form-telnet'
|
|
6
|
+
|
|
7
|
+
const { TabPane } = Tabs
|
|
8
|
+
|
|
9
|
+
export default function ProfileTabs (props) {
|
|
10
|
+
const { activeTab, onChangeTab, form, store } = props
|
|
11
|
+
const tabsProps = {
|
|
12
|
+
activeKey: activeTab,
|
|
13
|
+
onChange: onChangeTab
|
|
14
|
+
}
|
|
15
|
+
return (
|
|
16
|
+
<Tabs {...tabsProps}>
|
|
17
|
+
<TabPane tab='ssh' key='ssh' forceRender>
|
|
18
|
+
<ProfileFormSsh form={form} store={store} />
|
|
19
|
+
</TabPane>
|
|
20
|
+
<TabPane tab='telnet' key='telnet' forceRender>
|
|
21
|
+
<ProfileFormTelnet form={form} store={store} />
|
|
22
|
+
</TabPane>
|
|
23
|
+
<TabPane tab='vnc' key='vnc' forceRender>
|
|
24
|
+
<ProfileFormVnc />
|
|
25
|
+
</TabPane>
|
|
26
|
+
<TabPane tab='rdp' key='rdp' forceRender>
|
|
27
|
+
<ProfileFormRdp />
|
|
28
|
+
</TabPane>
|
|
29
|
+
</Tabs>
|
|
30
|
+
|
|
31
|
+
)
|
|
32
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export default function onDrop (e, cls) {
|
|
2
|
+
e.preventDefault()
|
|
3
|
+
const { store } = window
|
|
4
|
+
const { quickCommands } = store
|
|
5
|
+
const idDragged = e.dataTransfer.getData('idDragged')
|
|
6
|
+
const tar = cls ? e.target.closest(cls) : e.target
|
|
7
|
+
const idDrop = tar.getAttribute('data-id')
|
|
8
|
+
const idDraggedIndex = quickCommands.findIndex(
|
|
9
|
+
({ id }) => id === idDragged
|
|
10
|
+
)
|
|
11
|
+
const targetIndex = quickCommands.findIndex(
|
|
12
|
+
({ id }) => id === idDrop
|
|
13
|
+
)
|
|
14
|
+
if (idDraggedIndex !== targetIndex) {
|
|
15
|
+
const [removed] = quickCommands.splice(idDraggedIndex, 1)
|
|
16
|
+
quickCommands.splice(targetIndex, 0, removed)
|
|
17
|
+
store.setItems('quickCommands', quickCommands)
|
|
18
|
+
}
|
|
19
|
+
}
|
|
@@ -14,6 +14,7 @@ import {
|
|
|
14
14
|
PushpinOutlined
|
|
15
15
|
} from '@ant-design/icons'
|
|
16
16
|
import classNames from 'classnames'
|
|
17
|
+
import onDrop from './on-drop'
|
|
17
18
|
import './qm.styl'
|
|
18
19
|
|
|
19
20
|
const e = window.translate
|
|
@@ -90,23 +91,7 @@ export default class QuickCommandsFooterBox extends Component {
|
|
|
90
91
|
|
|
91
92
|
// sort quick commands array when drop, so that the dragged item will be placed at the right position, e.target.getAttribute('data-id') would target item id, e.dataTransfer.getData('idDragged') would target dragged item id, then set window.store.quickCommands use window.store.setItems
|
|
92
93
|
onDrop = e => {
|
|
93
|
-
e.
|
|
94
|
-
const { store } = window
|
|
95
|
-
const { quickCommands } = store
|
|
96
|
-
const idDragged = e.dataTransfer.getData('idDragged')
|
|
97
|
-
const idDrop = e.target.getAttribute('data-id')
|
|
98
|
-
const idDraggedIndex = quickCommands.findIndex(
|
|
99
|
-
({ id }) => id === idDragged
|
|
100
|
-
)
|
|
101
|
-
const targetIndex = quickCommands.findIndex(
|
|
102
|
-
({ id }) => id === idDrop
|
|
103
|
-
)
|
|
104
|
-
if (idDraggedIndex < targetIndex) {
|
|
105
|
-
quickCommands.splice(targetIndex, 0, quickCommands.splice(idDraggedIndex, 1)[0])
|
|
106
|
-
} else {
|
|
107
|
-
quickCommands.splice(targetIndex + 1, 0, quickCommands.splice(idDraggedIndex, 1)[0])
|
|
108
|
-
}
|
|
109
|
-
store.setItems('quickCommands', quickCommands)
|
|
94
|
+
onDrop(e, '.qm-item')
|
|
110
95
|
}
|
|
111
96
|
|
|
112
97
|
renderNoCmd = () => {
|
|
@@ -8,6 +8,7 @@ import { Select } from 'antd'
|
|
|
8
8
|
import classnames from 'classnames'
|
|
9
9
|
import highlight from '../common/highlight'
|
|
10
10
|
import QmTransport from './quick-command-transport'
|
|
11
|
+
import onDrop from './on-drop'
|
|
11
12
|
|
|
12
13
|
const { Option } = Select
|
|
13
14
|
const e = window.translate
|
|
@@ -22,7 +23,7 @@ export default class QuickCommandsList extends List {
|
|
|
22
23
|
this.props.onClickItem(item)
|
|
23
24
|
}
|
|
24
25
|
|
|
25
|
-
|
|
26
|
+
handleChangeLabel = v => {
|
|
26
27
|
this.setState({
|
|
27
28
|
labels: v
|
|
28
29
|
})
|
|
@@ -42,23 +43,7 @@ export default class QuickCommandsList extends List {
|
|
|
42
43
|
|
|
43
44
|
// adjust window.store.quickCommands array order when drop, so that the dragged item will be placed at the right position, e.target.getAttribute('data-id') would target item id, e.dataTransfer.getData('idDragged') would target dragged item id
|
|
44
45
|
handleDrop = e => {
|
|
45
|
-
e
|
|
46
|
-
const { store } = window
|
|
47
|
-
const { quickCommands } = store
|
|
48
|
-
const idDragged = e.dataTransfer.getData('idDragged')
|
|
49
|
-
const idDrop = e.target.getAttribute('data-id')
|
|
50
|
-
const idDraggedIndex = quickCommands.findIndex(
|
|
51
|
-
({ id }) => id === idDragged
|
|
52
|
-
)
|
|
53
|
-
const targetIndex = quickCommands.findIndex(
|
|
54
|
-
({ id }) => id === idDrop
|
|
55
|
-
)
|
|
56
|
-
if (idDraggedIndex < targetIndex) {
|
|
57
|
-
quickCommands.splice(targetIndex, 0, quickCommands.splice(idDraggedIndex, 1)[0])
|
|
58
|
-
} else {
|
|
59
|
-
quickCommands.splice(targetIndex + 1, 0, quickCommands.splice(idDraggedIndex, 1)[0])
|
|
60
|
-
}
|
|
61
|
-
store.setItems('quickCommands', quickCommands)
|
|
46
|
+
onDrop(e)
|
|
62
47
|
}
|
|
63
48
|
|
|
64
49
|
renderItem = (item, i) => {
|
|
@@ -116,7 +101,7 @@ export default class QuickCommandsList extends List {
|
|
|
116
101
|
placeholder: e('labels'),
|
|
117
102
|
mode: 'multiple',
|
|
118
103
|
value: this.state.labels,
|
|
119
|
-
onChange: this.
|
|
104
|
+
onChange: this.handleChangeLabel,
|
|
120
105
|
style: {
|
|
121
106
|
width: '100%'
|
|
122
107
|
}
|
|
@@ -4,8 +4,7 @@ import deepCopy from 'json-deep-copy'
|
|
|
4
4
|
import clone from '../../common/to-simple-obj'
|
|
5
5
|
import { handleErr } from '../../common/fetch'
|
|
6
6
|
import {
|
|
7
|
-
statusMap
|
|
8
|
-
rdpHelpLink
|
|
7
|
+
statusMap
|
|
9
8
|
} from '../../common/constants'
|
|
10
9
|
import {
|
|
11
10
|
notification,
|
|
@@ -17,7 +16,6 @@ import {
|
|
|
17
16
|
ReloadOutlined,
|
|
18
17
|
EditOutlined
|
|
19
18
|
} from '@ant-design/icons'
|
|
20
|
-
import HelpIcon from '../common/help-icon'
|
|
21
19
|
import * as ls from '../../common/safe-local-storage'
|
|
22
20
|
import scanCode from './code-scan'
|
|
23
21
|
import resolutions from './resolutions'
|
|
@@ -84,7 +82,7 @@ export default class RdpSession extends Component {
|
|
|
84
82
|
server = ''
|
|
85
83
|
} = config
|
|
86
84
|
const { sessionId, id } = this.props
|
|
87
|
-
const tab = deepCopy(this.props.tab || {})
|
|
85
|
+
const tab = window.store.applyProfile(deepCopy(this.props.tab || {}))
|
|
88
86
|
const {
|
|
89
87
|
type,
|
|
90
88
|
term: terminalType
|
|
@@ -347,11 +345,7 @@ export default class RdpSession extends Component {
|
|
|
347
345
|
}
|
|
348
346
|
|
|
349
347
|
renderHelp = () => {
|
|
350
|
-
return
|
|
351
|
-
<HelpIcon
|
|
352
|
-
link={rdpHelpLink}
|
|
353
|
-
/>
|
|
354
|
-
)
|
|
348
|
+
return null
|
|
355
349
|
}
|
|
356
350
|
|
|
357
351
|
renderControl = () => {
|
|
@@ -10,6 +10,7 @@ import {
|
|
|
10
10
|
MinusCircleOutlined,
|
|
11
11
|
PlusOutlined
|
|
12
12
|
} from '@ant-design/icons'
|
|
13
|
+
import { useEffect } from 'react'
|
|
13
14
|
|
|
14
15
|
const FormItem = Form.Item
|
|
15
16
|
const FormList = Form.List
|
|
@@ -101,6 +102,10 @@ export default function KeywordForm (props) {
|
|
|
101
102
|
)
|
|
102
103
|
}
|
|
103
104
|
|
|
105
|
+
useEffect(() => {
|
|
106
|
+
formChild.resetFields()
|
|
107
|
+
}, [props.keywordFormReset])
|
|
108
|
+
|
|
104
109
|
return (
|
|
105
110
|
<div>
|
|
106
111
|
<Form
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import BookmarkTransport from '../tree-list/bookmark-transport'
|
|
2
|
+
import download from '../../common/download'
|
|
3
|
+
import time from '../../common/time'
|
|
4
|
+
|
|
5
|
+
export default class KeywordsTransport extends BookmarkTransport {
|
|
6
|
+
name = 'keywords-highlight'
|
|
7
|
+
beforeUpload = async (file) => {
|
|
8
|
+
const { store } = this.props
|
|
9
|
+
const txt = await window.fs.readFile(file.path)
|
|
10
|
+
try {
|
|
11
|
+
store.setConfig({
|
|
12
|
+
keywords: JSON.parse(txt)
|
|
13
|
+
})
|
|
14
|
+
} catch (e) {
|
|
15
|
+
store.onError(e)
|
|
16
|
+
}
|
|
17
|
+
setTimeout(this.props.resetKeywordForm, 100)
|
|
18
|
+
return false
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
renderEdit () {
|
|
22
|
+
return null
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
handleDownload = () => {
|
|
26
|
+
const { store } = this.props
|
|
27
|
+
const arr = store.config.keywords || []
|
|
28
|
+
const txt = JSON.stringify(arr, null, 2)
|
|
29
|
+
const stamp = time(undefined, 'YYYY-MM-DD-HH-mm-ss')
|
|
30
|
+
download('electerm-' + this.name + '-' + stamp + '.json', txt)
|
|
31
|
+
}
|
|
32
|
+
}
|
|
@@ -28,6 +28,7 @@ import mapper from '../../common/auto-complete-data-mapper'
|
|
|
28
28
|
import KeywordForm from './keywords-form'
|
|
29
29
|
import Link from '../common/external-link'
|
|
30
30
|
import HelpIcon from '../common/help-icon'
|
|
31
|
+
import KeywordsTransport from './keywords-transport'
|
|
31
32
|
import './setting.styl'
|
|
32
33
|
|
|
33
34
|
const { Option } = Select
|
|
@@ -35,7 +36,8 @@ const e = window.translate
|
|
|
35
36
|
|
|
36
37
|
export default class SettingTerminal extends Component {
|
|
37
38
|
state = {
|
|
38
|
-
ready: false
|
|
39
|
+
ready: false,
|
|
40
|
+
keywordFormReset: 1
|
|
39
41
|
}
|
|
40
42
|
|
|
41
43
|
componentDidMount () {
|
|
@@ -50,6 +52,12 @@ export default class SettingTerminal extends Component {
|
|
|
50
52
|
clearTimeout(this.timer)
|
|
51
53
|
}
|
|
52
54
|
|
|
55
|
+
resetKeywordForm = () => {
|
|
56
|
+
this.setState({
|
|
57
|
+
keywordFormReset: Date.now()
|
|
58
|
+
})
|
|
59
|
+
}
|
|
60
|
+
|
|
53
61
|
handleResetAll = () => {
|
|
54
62
|
this.saveConfig(
|
|
55
63
|
deepCopy(defaultSettings)
|
|
@@ -411,6 +419,7 @@ export default class SettingTerminal extends Component {
|
|
|
411
419
|
formData: {
|
|
412
420
|
keywords
|
|
413
421
|
},
|
|
422
|
+
keywordFormReset: this.state.keywordFormReset,
|
|
414
423
|
submit: this.handleSubmitKeywords,
|
|
415
424
|
themeConfig: getThemeConfig()
|
|
416
425
|
}
|
|
@@ -469,6 +478,12 @@ export default class SettingTerminal extends Component {
|
|
|
469
478
|
<HelpIcon
|
|
470
479
|
title={tip}
|
|
471
480
|
/>
|
|
481
|
+
<span className='mg1l'>
|
|
482
|
+
<KeywordsTransport
|
|
483
|
+
store={this.props.store}
|
|
484
|
+
resetKeywordForm={this.resetKeywordForm}
|
|
485
|
+
/>
|
|
486
|
+
</span>
|
|
472
487
|
</div>
|
|
473
488
|
<KeywordForm
|
|
474
489
|
{...ps}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import SettingCol from './col'
|
|
2
|
-
import TerminalThemeForm from '../
|
|
3
|
-
import TerminalThemeList from '../
|
|
2
|
+
import TerminalThemeForm from '../theme/theme-form'
|
|
3
|
+
import TerminalThemeList from '../theme/theme-list'
|
|
4
4
|
import {
|
|
5
5
|
settingMap
|
|
6
6
|
} from '../../common/constants'
|
|
@@ -722,12 +722,12 @@ export default class FileSection extends React.Component {
|
|
|
722
722
|
path,
|
|
723
723
|
text,
|
|
724
724
|
mode
|
|
725
|
-
)
|
|
725
|
+
).catch(window.store.onError)
|
|
726
726
|
: await fs.writeFile(
|
|
727
727
|
path,
|
|
728
728
|
text,
|
|
729
729
|
mode
|
|
730
|
-
)
|
|
730
|
+
).catch(window.store.onError)
|
|
731
731
|
const data = {
|
|
732
732
|
loading: false
|
|
733
733
|
}
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* customize AttachAddon
|
|
3
3
|
*/
|
|
4
4
|
import { AttachAddon } from 'xterm-addon-attach'
|
|
5
|
-
import
|
|
5
|
+
import regEscape from 'escape-string-regexp'
|
|
6
6
|
|
|
7
7
|
export default class AttachAddonCustom extends AttachAddon {
|
|
8
8
|
constructor (term, socket, isWindowsShell) {
|
|
@@ -54,6 +54,7 @@ export default class AttachAddonCustom extends AttachAddon {
|
|
|
54
54
|
onRead = (ev) => {
|
|
55
55
|
const data = ev.target.result
|
|
56
56
|
const { term } = this
|
|
57
|
+
term?.parent?.notifyOnData()
|
|
57
58
|
const str = this.decoder.decode(data)
|
|
58
59
|
if (term?.parent?.props.sftpPathFollowSsh && term?.buffer.active.type !== 'alternate') {
|
|
59
60
|
const {
|
|
@@ -62,16 +63,16 @@ export default class AttachAddonCustom extends AttachAddon {
|
|
|
62
63
|
const nss = str.split('\r')
|
|
63
64
|
const nnss = []
|
|
64
65
|
for (const str1 of nss) {
|
|
65
|
-
const ns =
|
|
66
|
-
if (
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
(
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
nnss.push(
|
|
66
|
+
const ns = str1.trim()
|
|
67
|
+
if (cwdId) {
|
|
68
|
+
const cwdIdEscaped = regEscape(cwdId)
|
|
69
|
+
const dirRegex = new RegExp(`${cwdIdEscaped}([^\\n]+?)${cwdIdEscaped}`, 'g')
|
|
70
|
+
if (ns.match(dirRegex)) {
|
|
71
|
+
const cwd = dirRegex.exec(ns)[1].trim()
|
|
72
|
+
if (cwd === '~' || cwd === '%d' || cwd === '%/' || cwd === '$PWD') term.parent.setCwd('')
|
|
73
|
+
else term.parent.setCwd(cwd)
|
|
74
|
+
nnss.push(ns.replaceAll(dirRegex, ''))
|
|
75
|
+
} else nnss.push(str1)
|
|
75
76
|
} else {
|
|
76
77
|
nnss.push(str1)
|
|
77
78
|
}
|
|
@@ -4,7 +4,7 @@ import generate from '../../common/uid'
|
|
|
4
4
|
import { isEqual, pick, debounce, throttle } from 'lodash-es'
|
|
5
5
|
import postMessage from '../../common/post-msg'
|
|
6
6
|
import clone from '../../common/to-simple-obj'
|
|
7
|
-
import runIdle from '../../common/run-idle'
|
|
7
|
+
// import runIdle from '../../common/run-idle'
|
|
8
8
|
import {
|
|
9
9
|
ReloadOutlined
|
|
10
10
|
} from '@ant-design/icons'
|
|
@@ -125,6 +125,34 @@ class Term extends Component {
|
|
|
125
125
|
if (themeChanged) {
|
|
126
126
|
this.term.options.theme = deepCopy(this.props.themeConfig)
|
|
127
127
|
}
|
|
128
|
+
|
|
129
|
+
const sftpPathFollowSshChanged = !isEqual(
|
|
130
|
+
this.props.sftpPathFollowSsh,
|
|
131
|
+
prevProps.sftpPathFollowSsh
|
|
132
|
+
)
|
|
133
|
+
|
|
134
|
+
if (sftpPathFollowSshChanged) {
|
|
135
|
+
const ps1Cmd = `\recho $0|grep csh >/dev/null && set prompt_bak="$prompt" && set prompt="$prompt${cwdId}%/${cwdId}"\r
|
|
136
|
+
echo $0|grep zsh >/dev/null && PS1_bak=$PS1&&PS1=$PS1'${cwdId}%d${cwdId}'\r
|
|
137
|
+
echo $0|grep ash >/dev/null && PS1_bak=$PS1&&PS1=$PS1'\`echo ${cwdId}$PWD${cwdId}\`'\r
|
|
138
|
+
echo $0|grep ksh >/dev/null && PS1_bak=$PS1&&PS1=$PS1'\`echo ${cwdId}$PWD${cwdId}\`'\r
|
|
139
|
+
echo $0|grep '^sh' >/dev/null && PS1_bak=$PS1&&PS1=$PS1'\`echo ${cwdId}$PWD${cwdId}\`'\r
|
|
140
|
+
clear\r`
|
|
141
|
+
const ps1RestoreCmd = `\recho $0|grep csh >/dev/null && set prompt="$prompt_bak"\r
|
|
142
|
+
echo $0|grep zsh >/dev/null && PS1="$PS1_bak"\r
|
|
143
|
+
echo $0|grep ash >/dev/null && PS1="$PS1_bak"\r
|
|
144
|
+
echo $0|grep ksh >/dev/null && PS1="$PS1_bak"\r
|
|
145
|
+
echo $0|grep '^sh' >/dev/null && PS1="$PS1_bak"\r
|
|
146
|
+
clear\r`
|
|
147
|
+
|
|
148
|
+
if (this.props.sftpPathFollowSsh) {
|
|
149
|
+
this.socket.send(ps1Cmd)
|
|
150
|
+
this.term.cwdId = cwdId
|
|
151
|
+
} else {
|
|
152
|
+
this.socket.send(ps1RestoreCmd)
|
|
153
|
+
delete this.term.cwdId
|
|
154
|
+
}
|
|
155
|
+
}
|
|
128
156
|
}
|
|
129
157
|
|
|
130
158
|
componentWillUnmount () {
|
|
@@ -783,7 +811,7 @@ class Term extends Component {
|
|
|
783
811
|
onClear = () => {
|
|
784
812
|
this.term.clear()
|
|
785
813
|
this.term.focus()
|
|
786
|
-
this.notifyOnData('')
|
|
814
|
+
// this.notifyOnData('')
|
|
787
815
|
}
|
|
788
816
|
|
|
789
817
|
isRemote = () => {
|
|
@@ -908,11 +936,17 @@ class Term extends Component {
|
|
|
908
936
|
getCwd = () => {
|
|
909
937
|
if (
|
|
910
938
|
this.props.sftpPathFollowSsh &&
|
|
911
|
-
this.term.buffer.active.type !== 'alternate'
|
|
939
|
+
this.term.buffer.active.type !== 'alternate' && !this.term.cwdId
|
|
912
940
|
) {
|
|
913
|
-
const cmd = `\recho "${cwdId}$PWD"\r`
|
|
914
941
|
this.term.cwdId = cwdId
|
|
915
|
-
|
|
942
|
+
|
|
943
|
+
const ps1Cmd = `\recho $0|grep csh >/dev/null && set prompt_bak="$prompt" && set prompt="$prompt${cwdId}%/${cwdId}"\r
|
|
944
|
+
echo $0|grep zsh >/dev/null && PS1_bak=$PS1&&PS1=$PS1'${cwdId}%d${cwdId}'\r
|
|
945
|
+
echo $0|grep ash >/dev/null && PS1_bak=$PS1&&PS1=$PS1'\`echo ${cwdId}$PWD${cwdId}\`'\r
|
|
946
|
+
echo $0|grep ksh >/dev/null && PS1_bak=$PS1&&PS1=$PS1'\`echo ${cwdId}$PWD${cwdId}\`'\r
|
|
947
|
+
clear\r`
|
|
948
|
+
|
|
949
|
+
this.socket.send(ps1Cmd)
|
|
916
950
|
}
|
|
917
951
|
}
|
|
918
952
|
|
|
@@ -921,7 +955,7 @@ class Term extends Component {
|
|
|
921
955
|
}
|
|
922
956
|
|
|
923
957
|
onData = (d) => {
|
|
924
|
-
runIdle(this.notifyOnData)
|
|
958
|
+
// runIdle(this.notifyOnData)
|
|
925
959
|
if (!d.includes('\r')) {
|
|
926
960
|
delete this.userTypeExit
|
|
927
961
|
} else {
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { ColorPicker } from '../bookmark-form/color-picker'
|
|
2
|
+
|
|
3
|
+
export default function ThemeEditSlot (props) {
|
|
4
|
+
const {
|
|
5
|
+
name,
|
|
6
|
+
value,
|
|
7
|
+
disabled
|
|
8
|
+
} = props
|
|
9
|
+
function onChange (v) {
|
|
10
|
+
props.onChange(v, name)
|
|
11
|
+
}
|
|
12
|
+
const pickerProps = {
|
|
13
|
+
value,
|
|
14
|
+
onChange,
|
|
15
|
+
isRgba: value.startsWith('rgba'),
|
|
16
|
+
disabled
|
|
17
|
+
}
|
|
18
|
+
return (
|
|
19
|
+
<div className='theme-edit-slot'>
|
|
20
|
+
<span className='iblock mg1r'>{name}</span>
|
|
21
|
+
<span className='iblock'>
|
|
22
|
+
<ColorPicker
|
|
23
|
+
{...pickerProps}
|
|
24
|
+
/>
|
|
25
|
+
</span>
|
|
26
|
+
</div>
|
|
27
|
+
)
|
|
28
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
// import { buildDefaultThemes } from '../../common/terminal-theme'
|
|
2
|
+
import ThemeEditSlot from './theme-edit-slot'
|
|
3
|
+
|
|
4
|
+
export default function ThemeEditor (props) {
|
|
5
|
+
const { themeText, disabled } = props
|
|
6
|
+
const obj = themeText.split('\n').reduce((prev, line) => {
|
|
7
|
+
let [key = '', value = ''] = line.split('=')
|
|
8
|
+
key = key.trim()
|
|
9
|
+
value = value.trim()
|
|
10
|
+
if (!key || !value) {
|
|
11
|
+
return prev
|
|
12
|
+
}
|
|
13
|
+
prev[key] = value
|
|
14
|
+
return prev
|
|
15
|
+
}, {})
|
|
16
|
+
const keys = Object.keys(obj)
|
|
17
|
+
function onChange (value, name) {
|
|
18
|
+
props.onChange(value, name)
|
|
19
|
+
}
|
|
20
|
+
return (
|
|
21
|
+
<div className='editor-u-picker'>
|
|
22
|
+
{
|
|
23
|
+
keys.map(k => {
|
|
24
|
+
return (
|
|
25
|
+
<ThemeEditSlot
|
|
26
|
+
key={k}
|
|
27
|
+
name={k}
|
|
28
|
+
value={obj[k]}
|
|
29
|
+
disabled={disabled}
|
|
30
|
+
onChange={onChange}
|
|
31
|
+
/>
|
|
32
|
+
)
|
|
33
|
+
})
|
|
34
|
+
}
|
|
35
|
+
</div>
|
|
36
|
+
)
|
|
37
|
+
}
|