jsir 2.1.3 → 2.1.5

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.
Files changed (3) hide show
  1. package/cmd/oaa.js +187 -126
  2. package/deps/util.js +61 -15
  3. package/package.json +1 -1
package/cmd/oaa.js CHANGED
@@ -36,22 +36,21 @@ let _cmdMap = {}
36
36
  let _rl
37
37
  let _rlHistory = []
38
38
  let _haveWrapperInput = true
39
- let _exit = false
40
39
  let _noAppendNextLine = true
41
40
 
42
- const _onGetMap = {}
41
+ const _onLazyGetMap = {}
43
42
  const _data = {}
44
43
  const _tempTime = 60 * 1000
45
- const _dealOnGet = (key) => {
46
- if (_noAppendNextLine || !_onGetMap[key]) {
44
+ const _dealOnLazyGet = (key) => {
45
+ if (_noAppendNextLine || !_onLazyGetMap[key]) {
47
46
  return _data[key]
48
47
  }
49
- let item = _onGetMap[key]
48
+ let item = _onLazyGetMap[key]
50
49
  if (Date.now() <= item.startTime) {
51
50
  item.startTime = Date.now() + _tempTime
52
51
  return _data[key]
53
52
  }
54
- let flag = _onGetMap[key].fn()
53
+ let flag = _onLazyGetMap[key].fn()
55
54
  if (getType(flag)=== 'Promise') {
56
55
  return new Promise(async (resolve, reject) => {
57
56
  try {
@@ -67,6 +66,15 @@ const _dealOnGet = (key) => {
67
66
  return _data[key]
68
67
  }
69
68
  }
69
+ const _dataSet = (key, val, onLazyGet) => {
70
+ if (onLazyGet) {
71
+ _onLazyGetMap[key] = {
72
+ fn: onLazyGet,
73
+ startTime: Date.now() + _tempTime
74
+ }
75
+ }
76
+ return _data[key] = val
77
+ }
70
78
  const $data = {
71
79
  get: (key, defaultVal) => {
72
80
  if (!vl(_data[key])) {
@@ -76,34 +84,26 @@ const $data = {
76
84
  return _data[key]
77
85
  }
78
86
  }
79
- return _dealOnGet(key)
87
+ return _dealOnLazyGet(key)
80
88
  },
81
- gos: (key, defaultVal) => {
89
+ gos: (key, defaultVal, onLazyGet) => {
82
90
  if (!vl(_data[key])) {
83
91
  if (defaultVal !== undefined) {
84
- _data[key] = defaultVal
85
- return defaultVal
92
+ return _dataSet(key, defaultVal, onLazyGet)
86
93
  } else {
87
94
  return _data[key]
88
95
  }
89
96
  }
90
- return _dealOnGet(key)
91
- },
92
- set: (key, val, onGet) => {
93
- if (onGet) {
94
- _onGetMap[key] = {
95
- fn: onGet,
96
- startTime: Date.now() + _tempTime
97
- }
98
- }
99
- return _data[key] = val
97
+ return _dealOnLazyGet(key)
100
98
  },
99
+ set: _dataSet,
101
100
  del: (key) => {
102
101
  let val = _data[key]
103
102
  delete _data[key]
104
103
  return val
105
104
  },
106
- keys: () => Object.keys(_data)
105
+ keys: () => Object.keys(_data),
106
+ have: (key) => vl(_data[key])
107
107
  }
108
108
  const $homeDir = getLibDataDir()
109
109
 
@@ -171,7 +171,7 @@ async function getFileWatcher(workFilePath, text) {
171
171
  _fs.writeFileSync(workFilePath, text)
172
172
  let watcher = _chokidar.watch([workFilePath]);
173
173
  _fileWatcherMap[workFilePath] = watcher;
174
- setTips("FILE", "FILE", () => {
174
+ setTips("FILE", null, () => {
175
175
  Object.keys(_fileWatcherMap).forEach(closeFileWatcher);
176
176
  })
177
177
  return watcher
@@ -270,13 +270,18 @@ function getExeStr(oldText, newText) {
270
270
  }
271
271
  }
272
272
 
273
- async function nextLine(callback, preStr, hidden) {
273
+ async function nextLine(callback, promptStr, hidden) {
274
274
  return new Promise(resolve => {
275
- _nextLine(callback, preStr, hidden, resolve)
275
+ _nextLine(callback, promptStr, hidden, resolve)
276
276
  })
277
277
  }
278
278
 
279
- function initRl(callback, preStr, hidden) {
279
+ function defaultPromptStr(showKey = false) {
280
+ return [getTipStr(showKey), $defaultSpace].filter(i => i).join(':') + `> `;
281
+ }
282
+
283
+ function initRl(callback, promptStr, hidden) {
284
+ let origin_writeToOutput;
280
285
  if (!_rl) {
281
286
  _rl = readline.createInterface({
282
287
  input: process.stdin,
@@ -284,8 +289,10 @@ function initRl(callback, preStr, hidden) {
284
289
  })
285
290
  _rl.on("SIGINT", async () => {
286
291
  if (_noAppendNextLine) {
292
+ delTips();
287
293
  process.exit(0);
288
294
  } else {
295
+ _rl._writeToOutput = origin_writeToOutput;
289
296
  _haveWrapperInput = true;
290
297
  _rl.clearLine(0)
291
298
  nextLine();
@@ -293,12 +300,11 @@ function initRl(callback, preStr, hidden) {
293
300
  });
294
301
  _rl.history = _rlHistory
295
302
  }
296
-
297
- let promptStr = preStr
303
+ origin_writeToOutput = _rl._writeToOutput
298
304
  if (promptStr !== '') {
299
- promptStr = (preStr
305
+ promptStr = (promptStr
300
306
  || ((callback && callback !== wrapperInput) ? "-> ":"")
301
- || [Object.values(global.$tips).map(trim).filter(i => i).map(i => i.replace(/,/g, '-')).join(','), $defaultSpace].filter(i => i).join(':') + `> `)
307
+ || defaultPromptStr())
302
308
  promptStr = infoStr(promptStr)
303
309
  }
304
310
  if (hidden) {
@@ -318,69 +324,88 @@ function initRl(callback, preStr, hidden) {
318
324
  _rl.setPrompt(promptStr);
319
325
  }
320
326
 
327
+ function getTipStr(showKey = false) {
328
+ let items = [];
329
+ for (let key of Object.keys(global.$tips)) {
330
+ let val = global.$tips[key].map(i => trim(i).replace(/,/g, '-')).join("|");
331
+ key = trim(key)
332
+
333
+ let item
334
+ if (!showKey && vl(val)) {
335
+ item = val;
336
+ } else if (vl(key)) {
337
+ item = key
338
+ }
339
+ if (item) {
340
+ items.push(item)
341
+ }
342
+ }
343
+ return items.join(',');
344
+ }
345
+
321
346
  function closeRl() {
322
347
  _rlHistory = _rl.history;
323
348
  _rl.close();
324
349
  _rl = null;
325
350
  }
326
351
 
327
- function _nextLine(callback, preStr, hidden, resolve, end) {
352
+ function _nextLine(callback, promptStr, hidden, resolve, end, isText) {
328
353
  end = trim(end)
329
354
  if (!_haveWrapperInput) {
330
355
  return
331
356
  }
332
- initRl(callback, preStr, hidden);
357
+ initRl(callback, promptStr, hidden);
333
358
  _haveWrapperInput = false
334
359
  let inputStr = ''
335
- let lineHander = async line => {
360
+ let lineHandler = async line => {
336
361
  let textLine = line
337
362
  line = trim(line)
338
- if (end) {
339
- if (line !== end) {
363
+ if (isText) {
364
+ if (!end) {
365
+ end = line
366
+ line = ''
367
+ } else if (line !== end) {
340
368
  inputStr += textLine + '\n'
341
369
  }
342
370
  } else {
343
371
  inputStr = line
344
- if (/^\s+$/.test(textLine) && (!callback || wrapperInput === callback)) {
345
- process.stdout.write('\033[2J\033[H');
346
- listCmd();
347
- }
348
372
  }
349
- if (line && (hidden || (callback && callback !== wrapperInput))) {
373
+ if (trim(textLine) && (hidden || (callback && callback !== wrapperInput))) {
350
374
  _rl.history = _rl.history.slice(1)
351
375
  }
352
- if (!end || line === end) {
376
+ if (!isText || line === end) {
353
377
  _haveWrapperInput = true;
354
378
  closeRl()
355
379
  inputStr = inputStr.replace(/\s+$/, '');
356
380
 
357
381
  let pro = (callback || wrapperInput)(inputStr);
358
-
359
382
  resolve && resolve(inputStr);
360
- let currCallback = callback;
361
- callback = null;
362
- hidden = false;
363
- end = null;
364
- inputStr = '';
365
-
366
383
  try {
367
384
  await pro;
368
385
  } finally {
369
- if ((currCallback || wrapperInput) === wrapperInput) {
370
- _noAppendNextLine || nextLine()
386
+ if ((callback || wrapperInput) === wrapperInput) {
387
+ if (!_noAppendNextLine) {
388
+ if (/^\s+$/.test(textLine)) {
389
+ process.stdout.write('\033[2J\033[H');
390
+ listCmd();
391
+ nextLine(null, defaultPromptStr(true))
392
+ } else {
393
+ nextLine()
394
+ }
395
+ }
371
396
  }
372
397
  }
373
398
  }
374
399
  }
375
400
 
376
401
  _rl.removeAllListeners('line')
377
- _rl.on('line', lineHander)
402
+ _rl.on('line', lineHandler)
378
403
  _rl.prompt()
379
404
  }
380
405
 
381
406
  async function nextText(callback, end, hidden) {
382
407
  return new Promise(resolve => {
383
- _nextLine(callback, '', hidden, resolve, end)
408
+ _nextLine(callback, '', hidden, resolve, end, true)
384
409
  })
385
410
  }
386
411
 
@@ -400,13 +425,13 @@ async function save(args) {
400
425
  resp = `/*
401
426
  A test exe script
402
427
  */
403
-
428
+
404
429
  $defArgs({
405
- arg: '必填参数',
406
- _arg: '非必填参数'
430
+ arg: 'required argument',
431
+ _arg: 'optional argument'
407
432
  })
408
433
 
409
- let {} = $lib // 引用内置资源
434
+ let {} = $lib // Reference to built-in resources
410
435
 
411
436
  console.log($args)
412
437
 
@@ -417,7 +442,7 @@ return {}
417
442
  A test init script
418
443
  */
419
444
 
420
- let {} = $lib // 引用内置资源
445
+ let {} = $lib // Reference to built-in resources
421
446
 
422
447
  return {}
423
448
  `;
@@ -447,8 +472,15 @@ function rename(dir, oldName, newName) {
447
472
  listCmd()
448
473
  }
449
474
 
450
- function listCmd() {
451
- let items = Object.values(_cmdMap)
475
+ function listCmd(tmpMap) {
476
+ let tmpList = false;
477
+ if (tmpMap) {
478
+ tmpList = true;
479
+ } else {
480
+ tmpMap = _cmdMap;
481
+ }
482
+
483
+ tmpMap = arrayToCmdMap(Object.values(tmpMap)
452
484
  .filter(item => _fs.existsSync(getFullPath(item)))
453
485
  .sort((a,b) => {
454
486
  a = parseUniqueName(a)[1];
@@ -459,17 +491,19 @@ function listCmd() {
459
491
  orderA = orderA === -1 ? 999999:orderA;
460
492
  orderB = orderB === -1 ? 999999:orderB;
461
493
  return orderA - orderB
462
- })
494
+ }))
463
495
 
464
- _cmdMap = arrayToCmdMap(items)
465
- if (_noAppendNextLine) {
466
- objDataFile(_cmdMapFile, () => _cmdMap)
496
+ if (!tmpList) {
497
+ _cmdMap = tmpMap;
498
+ if (_noAppendNextLine) {
499
+ objDataFile(_cmdMapFile, () => _cmdMap)
500
+ }
467
501
  }
468
502
 
469
- items = []
470
- for (let i of Object.keys(_cmdMap)) {
471
- let text = String(_fs.readFileSync(getFullPath(_cmdMap[i])))
472
- let pair = parseUniqueName(_cmdMap[i])
503
+ let items = []
504
+ for (let i of Object.keys(tmpMap)) {
505
+ let text = String(_fs.readFileSync(getFullPath(tmpMap[i])))
506
+ let pair = parseUniqueName(tmpMap[i])
473
507
  let name = trimJsirFileName(pair[1])
474
508
  let suffix = getJsirFileSuffix(pair[1])
475
509
  let item = {
@@ -480,9 +514,9 @@ function listCmd() {
480
514
  items.push(item)
481
515
 
482
516
  if (!text) {
483
- text = String(_fs.readFileSync(getFullPath(_cmdMap[i])))
517
+ text = String(_fs.readFileSync(getFullPath(tmpMap[i])))
484
518
  }
485
- getComments(i, _cmdMap[i], text, items, item)
519
+ getComments(i, tmpMap[i], text, items, item)
486
520
  }
487
521
  if (Object.keys(items).length === 0) {
488
522
  warn("no items")
@@ -614,7 +648,7 @@ function help() {
614
648
  return {
615
649
  keyword: ' ' + warnStr(`.${key}`),
616
650
  short: ' ' + warnStr(`.${item.short}`),
617
- comment: [item.comment, item.args ? getArgComments(item.args).join('\n'):''].filter(i => i).join("\n"),
651
+ comment: [infoStr(item.comment), item.args ? getArgComments(item.args).join('\n'):''].filter(i => i).join("\n"),
618
652
  }
619
653
  }))
620
654
  }
@@ -716,21 +750,21 @@ let compareMode = {
716
750
 
717
751
  const keywordDef = {
718
752
  help: {
719
- comment: '帮助文档',
753
+ comment: 'Help documentation',
720
754
  exeFn: (args) => {
721
755
  help()
722
756
  },
723
757
  short: 'h'
724
758
  },
725
759
  version: {
726
- comment: '查看版本',
760
+ comment: 'View version',
727
761
  exeFn: (args) => {
728
762
  console.log(require("../package.json").version)
729
763
  },
730
764
  short: 'v'
731
765
  },
732
766
  list: {
733
- comment: '查看文件列表',
767
+ comment: 'View file list',
734
768
  exeFn: (args) => {
735
769
  if (args.length > 0) {
736
770
  _cmdMap = arrayToCmdMap(filterCmd(args.length > 0 ? args.join(' '):[',']))
@@ -738,22 +772,22 @@ const keywordDef = {
738
772
  listCmd()
739
773
  },
740
774
  args: {
741
- queryParams: '字符串匹配,[,]代表全部,关键字可以省略'
775
+ queryParams: 'string matching, [,] represents all, keywords can be omitted'
742
776
  },
743
777
  short: 'l'
744
778
  },
745
779
  clear: {
746
- comment: '清除任务',
780
+ comment: 'Clear task',
747
781
  exeFn: (args) => {
748
782
  delTipsByIndex(args.filter(i => i))
749
783
  },
750
784
  args: {
751
- tipIndex: '左侧提示符下标,可以多个用空格隔开'
785
+ tipIndex: 'left prompt index, can be separated by spaces for multiple'
752
786
  },
753
787
  short: 'C'
754
788
  },
755
789
  see: {
756
- comment: '查看文件',
790
+ comment: 'View file',
757
791
  exeFn: (args) => {
758
792
  let uniqueName = _cmdMap[args[0]]
759
793
  if (!uniqueName) {
@@ -765,12 +799,12 @@ const keywordDef = {
765
799
  }
766
800
  },
767
801
  args: {
768
- fileIndex: '文件下标'
802
+ fileIndex: 'File index'
769
803
  },
770
804
  short: 's'
771
805
  },
772
806
  rm: {
773
- comment: '删除文件',
807
+ comment: 'Remove file',
774
808
  exeFn: (args) => {
775
809
  let uniqueName = _cmdMap[args[0]]
776
810
  if (args[0] === 'ALL') {
@@ -788,12 +822,12 @@ const keywordDef = {
788
822
  }
789
823
  },
790
824
  args: {
791
- fileIndex: '文件下标, ALL代表全部'
825
+ fileIndex: 'File index, [ALL] for all files'
792
826
  },
793
827
  short: 'R'
794
828
  },
795
829
  get: {
796
- comment: '获取文件',
830
+ comment: 'Get file',
797
831
  exeFn: (args) => {
798
832
  let uniqueName = _cmdMap[args[0]]
799
833
  if (args[0] === 'ALL') {
@@ -807,12 +841,12 @@ const keywordDef = {
807
841
  }
808
842
  },
809
843
  args: {
810
- fileIndex: '文件下标, ALL代表全部'
844
+ fileIndex: 'File index, [ALL] for all files'
811
845
  },
812
846
  short: 'g'
813
847
  },
814
848
  rename: {
815
- comment: '重命名文件',
849
+ comment: 'Rename file',
816
850
  exeFn: (args) => {
817
851
  let uniqueName = _cmdMap[args[0]]
818
852
  if (!uniqueName) {
@@ -824,13 +858,13 @@ const keywordDef = {
824
858
  }
825
859
  },
826
860
  args: {
827
- fileIndex: '文件下标',
828
- newName: '新名字'
861
+ fileIndex: 'File index',
862
+ newName: 'New name'
829
863
  },
830
864
  short: 'n'
831
865
  },
832
866
  edit: {
833
- comment: '编辑文件',
867
+ comment: 'Edit file',
834
868
  exeFn: async (args) => {
835
869
  let uniqueName = _cmdMap[args[0]]
836
870
  if (!uniqueName) {
@@ -841,12 +875,12 @@ const keywordDef = {
841
875
  }
842
876
  },
843
877
  args: {
844
- fileIndex: '文件下标'
878
+ fileIndex: 'File index'
845
879
  },
846
880
  short: 'e'
847
881
  },
848
882
  compare: {
849
- comment: '比较文件',
883
+ comment: 'Compare files',
850
884
  exeFn: async (args) => {
851
885
  let aUniqueName = _cmdMap[args[0]]
852
886
  let bUniqueName = _cmdMap[args[1]]
@@ -878,14 +912,14 @@ const keywordDef = {
878
912
  }
879
913
  },
880
914
  args: {
881
- a: '文件/工作空间',
882
- b: '文件/工作空间',
915
+ a: 'File/workspace',
916
+ b: 'File/workspace',
883
917
  mode: 'a=, b=, ab=, a+, b+, ab+'
884
918
  },
885
919
  short: 'c'
886
920
  },
887
921
  deps: {
888
- comment: '查看文件依赖',
922
+ comment: 'View file dependencies',
889
923
  exeFn: (args) => {
890
924
  let uniqueName = _cmdMap[args[0]]
891
925
  if (!uniqueName) {
@@ -909,12 +943,12 @@ const keywordDef = {
909
943
  }
910
944
  },
911
945
  args: {
912
- fileIndex: '文件下标'
946
+ fileIndex: 'File index'
913
947
  },
914
948
  short: 'd'
915
949
  },
916
950
  file: {
917
- comment: '工作文件模式',
951
+ comment: 'Working file mode',
918
952
  exeFn: async (args) => {
919
953
  if (args.length === 0) {
920
954
  await workFile('')
@@ -928,12 +962,12 @@ const keywordDef = {
928
962
  }
929
963
  },
930
964
  args: {
931
- fileIndex: '文件下标'
965
+ fileIndex: 'File index'
932
966
  },
933
967
  short: 'f'
934
968
  },
935
969
  workspace: {
936
- comment: '工作空间管理',
970
+ comment: 'Workspace Management',
937
971
  exeFn: async (args) => {
938
972
  let newWorkspace = args.join(' ')
939
973
  if (newWorkspace) {
@@ -953,12 +987,12 @@ const keywordDef = {
953
987
  console.table(items)
954
988
  },
955
989
  args: {
956
- workspacePath: '新增工作空间路径'
990
+ workspacePath: 'New workspace path'
957
991
  },
958
992
  short: 'w'
959
993
  },
960
994
  uninstall: {
961
- comment: '卸载工作空间',
995
+ comment: 'Uninstall workspace',
962
996
  exeFn: async (args) => {
963
997
  let workspaces = Object.values($workspaceMap)
964
998
  let items = workspaces.map((path, index) => {
@@ -982,7 +1016,7 @@ const keywordDef = {
982
1016
  short: 'u'
983
1017
  },
984
1018
  switch: {
985
- comment: '切换工作空间',
1019
+ comment: 'Switch workspace',
986
1020
  exeFn: async (args) => {
987
1021
  checkWorkspaces()
988
1022
  let workspaces = Object.values($workspaceMap)
@@ -1005,54 +1039,74 @@ const keywordDef = {
1005
1039
  short: 'S'
1006
1040
  },
1007
1041
  add: {
1008
- comment: '新增文件',
1042
+ comment: 'Add file',
1009
1043
  exeFn: async (args) => {
1010
1044
  await save(args)
1011
1045
  },
1012
1046
  args: {
1013
- fileName: '文件名称(e可执行,i资源文件,f工作文件), 例:.add e test'
1047
+ fileName: 'File name (e for executable, i for resource file, f for working file), example: .add e test'
1014
1048
  },
1015
1049
  short: 'a'
1016
1050
  },
1017
1051
  run: {
1018
- comment: '快捷执行',
1052
+ comment: 'Quick execution',
1019
1053
  exeFn: async (args) => {
1020
1054
  if (!args[0]) {
1021
1055
  warn('invalid args')
1022
1056
  return
1023
1057
  }
1024
- let cmds = filterCmd('^e ' + toJsirFileName(args[0]).replace(/^[eif]\s+/, '') + '$')
1058
+ let pair = parseUniqueName(args[0])
1059
+ let cmds;
1060
+ if (/^0x[a-z\d]{8}$/.test(pair[1]) || pair[1].indexOf(",") !== -1) {
1061
+ cmds = getQuickRunCmds(args[0], args[0])
1062
+ } else {
1063
+ cmds = getQuickRunCmds(args[0], '^e ' + toJsirFileName(pair[1]) + '$')
1064
+ if (cmds.length === 0) {
1065
+ cmds = getQuickRunCmds(args[0], args[0])
1066
+ }
1067
+ }
1025
1068
  if (cmds.length === 1) {
1069
+ listCmd(arrayToCmdMap(cmds))
1026
1070
  await runCmd(args.slice(1).join(' '), cmds[0])
1071
+ } else {
1072
+ warn(cmds.length > 1 ? "multiple match" : "no match")
1027
1073
  }
1028
1074
  },
1029
1075
  args: {
1030
- fileNameReg: '文件名称匹配'
1076
+ fileNameReg: 'File name matching'
1031
1077
  },
1032
1078
  short: 'r'
1033
1079
  },
1034
1080
  quit: {
1035
- comment: '退出',
1081
+ comment: 'Exit',
1036
1082
  exeFn: (args) => {
1083
+ delTips();
1037
1084
  console.log(infoStr("Bye!"))
1038
- _exit = true;
1039
1085
  process.exit(0)
1040
1086
  },
1041
1087
  short: 'q'
1042
1088
  },
1043
1089
  repl: {
1044
- comment: '交互式界面',
1090
+ comment: 'Interactive interface',
1045
1091
  exeFn: (args) => {
1046
1092
  _noAppendNextLine = false
1093
+ _cmdMap = {}
1047
1094
  console.log(warnStr("You can start with .help, use * to expand context"))
1048
- if (Object.keys(_cmdMap).length > 0) {
1049
- listCmd()
1050
- }
1051
1095
  },
1052
1096
  short: 'p'
1053
1097
  }
1054
1098
  }
1055
1099
 
1100
+ function getQuickRunCmds(input, matchStr) {
1101
+ let pair = parseUniqueName(input)
1102
+ if (pair[0]) {
1103
+ matchStr = pair[0] + '/' + matchStr;
1104
+ } else if (input.startsWith("/")) {
1105
+ matchStr = '/' + matchStr;
1106
+ }
1107
+ return filterCmd(matchStr).filter(i => parseUniqueName(i)[1].startsWith("e "))
1108
+ }
1109
+
1056
1110
  function preLoad(text, fnNameMatch, fn) {
1057
1111
  regEach(text, new RegExp(`${fnNameMatch}\\s*\\(([^()]+)\\)`, 'g'), r=> {
1058
1112
  let item = trim(r[1])
@@ -1180,7 +1234,7 @@ function getScriptRequires(uniqueName) {
1180
1234
  }
1181
1235
 
1182
1236
  function getComments(i, cmdName, text, cols = [], col) {
1183
- let docLines = [infoStr(getCmdMd5Key(parseUniqueName(cmdName)[1])) + " - " + infoStr(i)]
1237
+ let docLines = [getCmdMd5Key(parseUniqueName(cmdName)[1]) + " - " + i]
1184
1238
  text = trim(text)
1185
1239
  docLines.push(...getTextComments(text))
1186
1240
  let argDef = getArgDef(text)
@@ -1189,12 +1243,17 @@ function getComments(i, cmdName, text, cols = [], col) {
1189
1243
  docLines.push(...comments)
1190
1244
  }
1191
1245
  if (docLines.length > 0) {
1192
- col.doc = '- ' + infoStr(trim(docLines[0]))
1246
+ col.doc = '- ' + docLines[0]
1193
1247
  if (docLines.length > 1) {
1194
- for (let line of docLines.slice(1)) {
1195
- cols.push({
1196
- doc: ' ' + line
1197
- })
1248
+ cols.push({
1249
+ doc: ' ' + infoStr(docLines[1])
1250
+ })
1251
+ if (docLines.length > 2) {
1252
+ for (let line of docLines.slice(2)) {
1253
+ cols.push({
1254
+ doc: ' ' + line
1255
+ })
1256
+ }
1198
1257
  }
1199
1258
  }
1200
1259
  }
@@ -1327,7 +1386,7 @@ function getArgComments(argDef) {
1327
1386
  let aLine = []
1328
1387
  for (let k of keys) {
1329
1388
  let item = warnStr(k) + (argDef[k] ? ` <${argDef[k]}>`:'')
1330
- if ([...aLine, item].join(', ').length > 64) {
1389
+ if (aLine.length > 0 && [...aLine, item].join(', ').length > 64) {
1331
1390
  comments.push(aLine.join(", ") + ", ")
1332
1391
  aLine = []
1333
1392
  }
@@ -1392,7 +1451,8 @@ async function runCmd(str = '', uniqueName = '', text = '') {
1392
1451
  pair = [arg, oriArgs[i+1]]
1393
1452
  i++
1394
1453
  } else {
1395
- pair = [arg, null]
1454
+ // 只传参数名称,不传参数,使用翻译赋值为true
1455
+ pair = [arg, 'true ']
1396
1456
  }
1397
1457
  } else {
1398
1458
  pair = [null, arg]
@@ -1422,7 +1482,7 @@ async function runCmd(str = '', uniqueName = '', text = '') {
1422
1482
  for (let key of Object.keys(exactArgs)) {
1423
1483
  scriptArgs[key] = exactArgs[key]
1424
1484
  }
1425
- let exit = false
1485
+ let argAbsent = false
1426
1486
  let scriptArgKeys = Object.keys(scriptArgs);
1427
1487
  for(let name of argNames) {
1428
1488
  let defStr = argDef[name]
@@ -1436,15 +1496,15 @@ async function runCmd(str = '', uniqueName = '', text = '') {
1436
1496
  continue
1437
1497
  }
1438
1498
  if (scriptArgKeys.indexOf(name) === -1 || (reg && !reg.test(scriptArgs[name]))) {
1439
- exit = true
1499
+ argAbsent = true
1440
1500
  warn(`require ${warnStr(name)}` + (defStr ? ` <${defStr}>`:''))
1441
1501
  }
1442
1502
  }
1443
- if (exit) {
1503
+ if (argAbsent) {
1444
1504
  throw 'invalid args';
1445
1505
  }
1446
1506
 
1447
- process.argv = [process.argv[0], path, ...scriptArgs]
1507
+ process.argv = [process.argv[0], path, ...(scriptArgs.map(String))]
1448
1508
  return await evalText(text, uniqueName, scriptArgs)
1449
1509
  }
1450
1510
 
@@ -1514,9 +1574,7 @@ function getArgDef(text) {
1514
1574
  }
1515
1575
 
1516
1576
  function setTips(key, value, onRm) {
1517
- let vals = getOr(global.$tips, key, []);
1518
- vals.push(value)
1519
- global.$tips[key] = [...new Set(vals)]
1577
+ getOr(global.$tips, key, []).push(value);
1520
1578
  if (onRm) {
1521
1579
  getOr(_tipsOnRm, key, []).push(onRm)
1522
1580
  }
@@ -1677,14 +1735,17 @@ process.on('rejectionHandled',function(err){
1677
1735
  })
1678
1736
  process.on('SIGINT', function () {
1679
1737
  if (_noAppendNextLine) {
1680
- process.exit();
1738
+ delTips();
1739
+ process.exit(0);
1681
1740
  } else {
1682
1741
  nextLine();
1683
1742
  }
1684
1743
  });
1685
1744
  process.on('beforeExit', function () {
1686
- if (!_exit) {
1687
- _noAppendNextLine || nextLine();
1745
+ if (_noAppendNextLine) {
1746
+ delTips();
1747
+ } else {
1748
+ nextLine();
1688
1749
  }
1689
1750
  });
1690
1751
 
package/deps/util.js CHANGED
@@ -43,13 +43,16 @@ function isArgsMatch(text, args, callback, useMd5) {
43
43
  for (let str of arg.split(',').map(trim).filter(i => i)) {
44
44
  let reg = new RegExp(str.split(/\s+/).join('\\s+'), 'i')
45
45
  if (useMd5 && /^0x[a-z\d]{8}$/.test(str)) {
46
- if (('0x' + md5(text).substr(0, 8)) === str) {
46
+ if (('0x' + md5(text).substr(0, 8)) !== str) {
47
+ r = false
48
+ break
49
+ }
50
+ } else {
51
+ if (!reg.test(text)) {
52
+ r = false
47
53
  break
48
54
  }
49
- } else if (reg.test(text)){
50
- break
51
55
  }
52
- r = false
53
56
  }
54
57
  if (r) {
55
58
  match = true
@@ -885,22 +888,69 @@ function strEq(a, b) {
885
888
 
886
889
  function wrapRows(rows) {
887
890
  let newRows = []
891
+ // 构建新的数组
888
892
  for(let row of rows) {
889
893
  let temp = []
890
894
  for(let key of Object.keys(row)) {
891
895
  let val = row[key]
892
- if (getType(val) !== "String") {
896
+ if (typeof val === 'number') {
897
+ let r = getOr(temp, 0, {})
898
+ r[key] = val;
899
+ continue;
900
+ }
901
+ if (typeof val !== "string") {
893
902
  val = JSON.stringify(val, null, 2)
894
903
  }
904
+
905
+ let r = getOr(temp, 0, {})
906
+ r[key] = val;
907
+ }
908
+ newRows.push(...temp)
909
+ }
910
+
911
+ // 排序
912
+ if (newRows.length > 0) {
913
+ newRows.sort((a,b) => {
914
+ for (let key of Object.keys(newRows[0])) {
915
+ if (a[key] < b[key]) {
916
+ return -1;
917
+ } else if (a[key] > b[key]) {
918
+ return 1;
919
+ }
920
+ }
921
+ return 0;
922
+ })
923
+ let keyMap = {}
924
+ for (let newRow of newRows) {
925
+ let lastKey
926
+ for (let key of Object.keys(newRows[0])) {
927
+ if (keyMap[key] === newRow[key]) {
928
+ if (!lastKey || newRow[lastKey] === ' - ') {
929
+ newRow[key] = ' - '
930
+ }
931
+ } else {
932
+ keyMap[key] = newRow[key]
933
+ }
934
+ lastKey = key;
935
+ }
936
+ }
937
+ }
938
+
939
+ // 换行处理
940
+ let result = []
941
+ for(let row of newRows) {
942
+ let temp = []
943
+ for(let key of Object.keys(row)) {
944
+ let val = row[key]
895
945
  let items = String(val).split('\n')
896
946
  for(let i = 0; i<items.length; i++) {
897
947
  let r = getOr(temp, i, {})
898
948
  r[key] = items[i]
899
949
  }
900
950
  }
901
- newRows.push(...temp)
951
+ result.push(...temp)
902
952
  }
903
- return newRows
953
+ return result
904
954
  }
905
955
 
906
956
  function info(msg) {
@@ -1123,7 +1173,6 @@ function errorTag(e, tag) {
1123
1173
  function getTextComments(text) {
1124
1174
  let results = []
1125
1175
  text = text.replace(/\r/g, '\n')
1126
- text = text.replace(/\n+/g, '\n')
1127
1176
  let lines = text.split(/\n/);
1128
1177
 
1129
1178
  if (text.startsWith("/*")) {
@@ -1141,17 +1190,14 @@ function getTextComments(text) {
1141
1190
  results.push(line)
1142
1191
  }
1143
1192
  } else {
1144
- for (let key of ['#', '/', '-', ';']) {
1145
- if (!text.startsWith(key)) {
1146
- continue
1147
- }
1193
+ let firstReg = /^[#/\-;]+/;
1194
+ if (firstReg.test(text)) {
1148
1195
  for (let line of lines) {
1149
1196
  let trimLine = trim(line)
1150
1197
  if (!trimLine) {
1151
- continue
1198
+ break
1152
1199
  }
1153
- if (trimLine.startsWith(key)) {
1154
- let line = trimLine.replace(new RegExp(`^[${key}]+`), '');
1200
+ if (firstReg.test(trimLine)) {
1155
1201
  if (trim(line)) {
1156
1202
  results.push(line)
1157
1203
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "jsir",
3
- "version": "2.1.3",
3
+ "version": "2.1.5",
4
4
  "description": "js script manager tool",
5
5
  "main": "index.js",
6
6
  "scripts": {