@@ -55,8 +55,8 @@ import TViewerTable from "~/components/TViewerTable.vue";
55
55
import THelpBox from " ~/components/THelpBox.vue" ;
56
56
import TEditor from " ~/components/TEditor.vue" ;
57
57
58
- import themeDark from " ~/css/theme/dark.css"
59
- import themeLight from " ~/css/theme/light.css"
58
+ import themeDark from " ~/css/theme/dark.css?inline "
59
+ import themeLight from " ~/css/theme/light.css?inline "
60
60
61
61
// 对应css变量 --t-font-height
62
62
const FONT_HEIGHT = 19 ;
@@ -285,23 +285,23 @@ const tips = reactive({
285
285
})
286
286
287
287
// references
288
- const terminalContainerRef = ref (null )
289
- const terminalHeaderRef = ref (null )
290
- const terminalWindowRef = ref (null )
291
- const terminalCmdInputRef = ref (null )
292
- const terminalAskInputRef = ref (null )
293
- const terminalInputBoxRef = ref (null )
294
- const terminalInputPromptRef = ref (null )
295
- const terminalEnFlagRef = ref (null )
296
- const terminalCnFlagRef = ref (null )
297
- const terminalTextEditorRef = ref (null )
298
- const terminalCursorRef = ref (null )
299
- const terminalHelpBoxRef = ref (null )
300
- const resizeLTRef = ref (null )
301
- const resizeRTRef = ref (null )
302
- const resizeLBRef = ref (null )
303
- const resizeRBRef = ref (null )
304
- const terminalCmdTipsRef = ref (null )
288
+ const terminalContainerRef = ref < HTMLDivElement > (null )
289
+ const terminalHeaderRef = ref < HTMLDivElement > (null )
290
+ const terminalWindowRef = ref < HTMLDivElement > (null )
291
+ const terminalCmdInputRef = ref < HTMLInputElement > (null )
292
+ const terminalAskInputRef = ref < HTMLInputElement > (null )
293
+ const terminalInputBoxRef = ref < HTMLParagraphElement > (null )
294
+ const terminalInputPromptRef = ref < HTMLSpanElement > (null )
295
+ const terminalEnFlagRef = ref < HTMLSpanElement > (null )
296
+ const terminalCnFlagRef = ref < HTMLSpanElement > (null )
297
+ const terminalTextEditorRef = ref < InstanceType < TEditor >> (null )
298
+ const terminalCursorRef = ref < HTMLSpanElement > (null )
299
+ const terminalHelpBoxRef = ref < InstanceType < THelpBox >> (null )
300
+ const resizeLTRef = ref < HTMLDivElement > (null )
301
+ const resizeRTRef = ref < HTMLDivElement > (null )
302
+ const resizeLBRef = ref < HTMLDivElement > (null )
303
+ const resizeRBRef = ref < HTMLDivElement > (null )
304
+ const terminalCmdTipsRef = ref < HTMLSpanElement > (null )
305
305
306
306
// listeners
307
307
const clickListener = ref ()
@@ -421,8 +421,10 @@ onMounted(() => {
421
421
return ;
422
422
}
423
423
text = text .trim ()
424
+ .replace (/ \r\n / g , ' \n ' )
425
+ .replace (/ \r / g , ' \n ' )
424
426
const cmd = command .value ;
425
- command .value = cmd && cmd .length ? ` ${cmd }${text } ` : text ;
427
+ command .value = cmd && cmd .length > 0 ? ` ${cmd }${text } ` : text ;
426
428
_focus ()
427
429
}).catch (error => {
428
430
console .error (error );
@@ -949,6 +951,38 @@ const _printHelp = (regExp: RegExp, srcStr: string) => {
949
951
})
950
952
}
951
953
954
+ const _inputEnter = (e : KeyboardEvent ) => {
955
+ e .preventDefault ()
956
+ if (e .ctrlKey ) {
957
+ if (command .value .length > 0 ) {
958
+ let cursorIdx = cursorConf .idx
959
+ command .value = command .value .substring (0 , cursorIdx ) + ' \n ' + command .value .substring (cursorIdx )
960
+
961
+ cursorIdx ++
962
+ // 恢复光标位置
963
+ nextTick (() => {
964
+ terminalCmdInputRef .value .selectionStart = cursorIdx
965
+ terminalCmdInputRef .value .selectionEnd = cursorIdx
966
+ cursorConf .idx = cursorIdx
967
+ })
968
+ }
969
+ } else {
970
+ // 因无法阻止回车输入,这里手动删掉前后一个回车
971
+ let cursorIdx = terminalCmdInputRef .value .selectionStart
972
+ let enterIdx = - 1
973
+ if (command .value [cursorIdx ] == ' \n ' ) {
974
+ enterIdx = cursorIdx
975
+ } else if (command .value [cursorIdx - 1 ] == ' \n ' ) {
976
+ enterIdx = cursorIdx - 1
977
+ }
978
+
979
+ if (enterIdx >= 0 ) {
980
+ command .value = command .value .substring (0 , enterIdx ) + command .value .substring (enterIdx + 1 )
981
+ }
982
+ _execute ()
983
+ }
984
+ }
985
+
952
986
const _execute = () => {
953
987
_closeTips (true )
954
988
_saveCurCommand ();
@@ -1209,22 +1243,25 @@ const _jumpToBottom = () => {
1209
1243
nextTick (() => {
1210
1244
let box = terminalWindowRef .value
1211
1245
if (box != null ) {
1212
- box .scrollTo ({top: box .scrollHeight , behavior: props .scrollMode })
1246
+ box .scrollTo ({
1247
+ top: box .scrollHeight ,
1248
+ behavior: props .scrollMode
1249
+ })
1213
1250
}
1214
1251
}).then (() => {
1215
1252
})
1216
1253
}
1217
1254
1218
1255
const _saveCurCommand = () => {
1219
- if (_nonEmpty (command .value )) {
1220
- store .push (getName (), command .value )
1256
+ let cmd = command .value = command .value .trim ()
1257
+ if (cmd .length > 0 ) {
1258
+ store .push (getName (), cmd )
1221
1259
}
1222
1260
1223
1261
let group = _newTerminalLogGroup ()
1224
-
1225
1262
group .logs .push ({
1226
1263
type: " cmdLine" ,
1227
- content: ` ${_html (props .context )}${props .contextSuffix }${_commandFormatter (command . value )} `
1264
+ content: ` ${_html (props .context )}${props .contextSuffix }${_commandFormatter (cmd )} `
1228
1265
});
1229
1266
_jumpToBottom ()
1230
1267
}
@@ -1246,13 +1283,14 @@ const _resetCursorPos = (cmd?: string) => {
1246
1283
}
1247
1284
1248
1285
const _calculateCursorPos = (cmdStr ? : string ) => {
1286
+ let cmd = cmdStr ? cmdStr : command .value
1249
1287
// idx可以认为是需要光标覆盖字符的索引
1250
1288
let idx = cursorConf .idx
1251
- let cmd = cmdStr ? cmdStr : command .value
1252
1289
1253
1290
_calculateByteLen ()
1254
1291
1255
1292
if (idx < 0 || idx >= cmd .length ) {
1293
+ console .debug (` reset cursor, idx: ${idx }, cmd.length: ${cmd .length } ` )
1256
1294
_resetCursorPos ()
1257
1295
return
1258
1296
}
@@ -1266,14 +1304,32 @@ const _calculateCursorPos = (cmdStr?: string) => {
1266
1304
let pos = {left: 0 , top: 0 }
1267
1305
// 当前字符长度
1268
1306
let charWidth = cursorConf .defaultWidth
1269
- // 前一个字符的长度
1270
- let preWidth = inputBoxParam .promptWidth
1307
+ // 前面字符的长度
1308
+ let lastCharWidth = inputBoxParam .promptWidth
1309
+ // 前一个字符是否是回车换行
1310
+ let lastCharIsEnter = false
1271
1311
1272
1312
// 先找到被覆盖字符的位置
1273
1313
for (let i = 0 ; i <= idx ; i ++ ) {
1314
+ let char = cmd [i ]
1315
+
1316
+ if (lastCharIsEnter ) {
1317
+ pos .top += FONT_HEIGHT
1318
+ pos .left = 0
1319
+ lastCharWidth = 0
1320
+ }
1321
+
1322
+ if (char === ' \n ' ) {
1323
+ pos .left += lastCharWidth
1324
+ lastCharIsEnter = true
1325
+ continue
1326
+ } else {
1327
+ lastCharIsEnter = false
1328
+ }
1329
+
1274
1330
charWidth = _calculateStringWidth (cmd [i ])
1275
- pos .left += preWidth
1276
- preWidth = charWidth
1331
+ pos .left += lastCharWidth
1332
+ lastCharWidth = charWidth
1277
1333
if (pos .left > lineWidth ) {
1278
1334
// 行高 对应 css 变量 --t-font-height
1279
1335
pos .top += FONT_HEIGHT
@@ -1351,6 +1407,7 @@ const _switchPreCmd = () => {
1351
1407
_resetCursorPos ()
1352
1408
store .setIdx (getName (), cmdIdx )
1353
1409
_searchCmd ()
1410
+ _jumpToBottom ()
1354
1411
}
1355
1412
1356
1413
const _switchNextCmd = () => {
@@ -1366,6 +1423,7 @@ const _switchNextCmd = () => {
1366
1423
_resetCursorPos ()
1367
1424
store .setIdx (getName (), cmdIdx )
1368
1425
_searchCmd ()
1426
+ _jumpToBottom ()
1369
1427
}
1370
1428
1371
1429
const _calculateStringWidth = (str : string ): number => {
@@ -1662,7 +1720,12 @@ const _commandFormatter = (cmd: string): string => {
1662
1720
if (props .commandFormatter ) {
1663
1721
return props .commandFormatter (cmd )
1664
1722
}
1665
- return _defaultMergedCommandFormatter (cmd )
1723
+ let splitsCode = []
1724
+ let splits = cmd .split (/ \r\n | \n | \r / g )
1725
+ for (let c of splits ) {
1726
+ splitsCode .push (_defaultMergedCommandFormatter (c ))
1727
+ }
1728
+ return splitsCode .join (" <br/>" )
1666
1729
}
1667
1730
1668
1731
const _onAskInput = () => {
@@ -2018,20 +2081,19 @@ defineExpose({
2018
2081
Press <strong >Tab</strong > to choose the selected suggestion.
2019
2082
</span >
2020
2083
</span >
2021
- <input type =" text"
2022
- autofocus
2023
- v-model =" command"
2024
- class =" t-cmd-input t-disable-select"
2025
- ref =" terminalCmdInputRef"
2026
- autocomplete =" off"
2027
- auto-complete =" new-password"
2028
- @keydown =" _onInputKeydown"
2029
- @keyup =" _onInputKeyup"
2030
- @input =" _onInput"
2031
- @focusin =" cursorConf.show = true"
2032
- @keyup.up.exact =" _inputKeyUp"
2033
- @keyup.down.exact =" _inputKeyDown"
2034
- @keyup.enter =" _execute" >
2084
+ <textarea autofocus
2085
+ v-model =" command"
2086
+ class =" t-cmd-input t-disable-select"
2087
+ ref =" terminalCmdInputRef"
2088
+ autocomplete =" off"
2089
+ auto-complete =" new-password"
2090
+ @keydown =" _onInputKeydown"
2091
+ @keyup =" _onInputKeyup"
2092
+ @input =" _onInput"
2093
+ @focusin =" cursorConf.show = true"
2094
+ @keyup.up.exact =" _inputKeyUp"
2095
+ @keyup.down.exact =" _inputKeyDown"
2096
+ @keyup.enter =" _inputEnter" />
2035
2097
</p >
2036
2098
</div >
2037
2099
</div >
0 commit comments