jsir 2.1.8 → 2.2.0

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/cmd/oaa.js CHANGED
@@ -5,16 +5,16 @@ const {
5
5
  getCbText, e, sleep, objDataFile, vl, md5, BigNumber,
6
6
  arrayDataFile, infoStr, warnStr, errorStack,
7
7
  getInfo, ei, pad, msgStr, getType,
8
- errorTag, isArgsMatch, draftQuery, setConfig,
8
+ isArgsMatch, draftQuery, setConfig,
9
9
  $log, $draft, getTextComments, getOr, importG, requireG,
10
- clearConsole
10
+ clearConsole, trimText
11
11
  } = $lib;
12
12
  const _args = process.argv.slice(2).map(trim);
13
13
  const evalCode = require('../deps/evalCode')
14
14
  const {evalVal} = require('../deps/cleanEval')
15
15
  const _chokidar = require('chokidar');
16
16
  const setting = require('../deps/setting')
17
- const _fs = require('fs')
17
+ const fs = require('fs')
18
18
  const readline = require("readline");
19
19
  const packageJson = require("../package.json");
20
20
  const example = require("../deps/example");
@@ -31,57 +31,70 @@ const $config = {
31
31
  get: getConfig,
32
32
  set: setConfig
33
33
  }
34
- const CONSOLE = Object.assign({}, console);
35
- const info = (msg) => $lib.info(msg, CONSOLE);
36
- const warn = (msg) => $lib.warn(msg, CONSOLE);
37
- const error = (msg, tag) => $lib.error(msg, tag, CONSOLE);
34
+ const console = Object.assign({}, global.console);
38
35
 
36
+ let lastFilterArg = '';
39
37
  let _cmdMapFile = setting.name + 'CmdMap.json'
40
38
  let _cmdMap = {}
41
39
  let _rl
42
40
  let _rlHistory = []
43
41
  let _haveWrapperInput = true
44
42
  let _noAppendNextLine = true
43
+ let _onLazyTempCode = null
45
44
 
46
45
  const _onLazyGetMap = {}
47
46
  const _data = {}
48
47
  const _lazyTime = 5 * 60 * 1000
49
- const _dealOnLazyGet = (key) => {
48
+ const _dealOnLazyGet = (key, onLazyTempCode) => {
50
49
  if (_noAppendNextLine || !_onLazyGetMap[key]) {
51
50
  return _data[key]
52
51
  }
53
- let item = _onLazyGetMap[key]
54
- if (Date.now() <= item.startTime) {
55
- item.startTime = Date.now() + _lazyTime
56
- return _data[key]
57
- }
58
- let flag = _onLazyGetMap[key].fn()
59
- if (getType(flag)=== 'Promise') {
60
- return new Promise(async (resolve, reject) => {
61
- try {
62
- await flag
63
- item.startTime = Date.now() + _lazyTime
64
- resolve(_data[key])
65
- } catch (e) {
66
- reject(e)
67
- }
68
- })
69
- } else {
70
- item.startTime = Date.now() + _lazyTime
52
+ if (Date.now() <= _onLazyGetMap[key]) {
53
+ _onLazyGetMap[key] = Date.now() + _lazyTime
71
54
  return _data[key]
72
55
  }
56
+ return new Promise(async (resolve, reject) => {
57
+ let inputCode = onLazyTempCode || await nextLine(i => i, "TEMP_CODE: ", true)
58
+ if (inputCode !== _onLazyTempCode) {
59
+ reject("tempCode check failed")
60
+ } else {
61
+ _onLazyGetMap[key] = Date.now() + _lazyTime
62
+ resolve(_data[key])
63
+ }
64
+ })
73
65
  }
74
- const _dataSet = (key, val, onLazyGet) => {
75
- if (onLazyGet) {
76
- _onLazyGetMap[key] = {
77
- fn: onLazyGet,
78
- startTime: Date.now() + _lazyTime
66
+
67
+ const _dataSet = (key, val, onLazyTempCode) => {
68
+ let useOnLazy = false;
69
+ if (typeof onLazyTempCode === 'string') {
70
+ useOnLazy = true
71
+ if (!vl(_onLazyTempCode)) {
72
+ _onLazyTempCode = trim(onLazyTempCode);
73
+ }
74
+ } else if (true === onLazyTempCode) {
75
+ useOnLazy = true
76
+ } else if (onLazyTempCode !== undefined) {
77
+ throw "invalid tempCode defined"
78
+ }
79
+ if (useOnLazy) {
80
+ _onLazyGetMap[key] = Date.now() + _lazyTime
81
+ if (!vl(_onLazyTempCode)) {
82
+ return new Promise(async (resolve, reject) => {
83
+ let tempCode = await nextLine(i => i, "SET TEMP_CODE: ", true)
84
+ if (vl(tempCode)) {
85
+ _onLazyTempCode = trim(tempCode);
86
+ resolve(_data[key] = val)
87
+ } else {
88
+ reject("invalid tempCode")
89
+ }
90
+ });
79
91
  }
80
92
  }
93
+
81
94
  return _data[key] = val
82
95
  }
83
96
  const $data = {
84
- get: (key, defaultVal) => {
97
+ get: (key, defaultVal, onLazyTempCode) => {
85
98
  if (!vl(_data[key])) {
86
99
  if (defaultVal !== undefined) {
87
100
  return defaultVal
@@ -89,17 +102,17 @@ const $data = {
89
102
  return _data[key]
90
103
  }
91
104
  }
92
- return _dealOnLazyGet(key)
105
+ return _dealOnLazyGet(key, onLazyTempCode)
93
106
  },
94
- gos: (key, defaultVal, onLazyGet) => {
107
+ gos: (key, defaultVal, onLazyTempCode) => {
95
108
  if (!vl(_data[key])) {
96
109
  if (defaultVal !== undefined) {
97
- return _dataSet(key, defaultVal, onLazyGet)
110
+ return _dataSet(key, defaultVal, onLazyTempCode)
98
111
  } else {
99
112
  return _data[key]
100
113
  }
101
114
  }
102
- return _dealOnLazyGet(key)
115
+ return _dealOnLazyGet(key, onLazyTempCode)
103
116
  },
104
117
  set: _dataSet,
105
118
  del: (key) => {
@@ -124,7 +137,7 @@ function getFileOpenExe(fileName) {
124
137
  if (strs.length > 1) {
125
138
  suffix = strs[strs.length - 1]
126
139
  }
127
- let defaultExe = getConfig("defaultExe", "idea");
140
+ let defaultExe = getConfig("defaultExe", "open");
128
141
  if (!suffix) {
129
142
  return defaultExe
130
143
  }
@@ -143,7 +156,7 @@ function checkWorkspaces() {
143
156
  if (space === 'local') {
144
157
  continue
145
158
  }
146
- if (_fs.existsSync(workspace)) {
159
+ if (fs.existsSync(workspace)) {
147
160
  $workspaceMap[space] = workspace;
148
161
  }
149
162
  }
@@ -154,7 +167,8 @@ function checkWorkspaces() {
154
167
  async function start() {
155
168
  checkWorkspaces()
156
169
 
157
- _cmdMap = objDataFile(_cmdMapFile)
170
+ lastFilterArg = getConfig("lastFilterArg");
171
+ _cmdMap = objDataFile(_cmdMapFile);
158
172
  if (_args[0]) {
159
173
  let line = _args.map(i => {
160
174
  if (/\s+/.test(i) || !i) {
@@ -169,11 +183,11 @@ async function start() {
169
183
  }
170
184
 
171
185
  async function getFileWatcher(workFilePath, text) {
172
- info("workFile open " + workFilePath)
186
+ console.info("workFile open " + workFilePath)
173
187
  if (!_fileWatcherMap[workFilePath]) {
174
- _fs.unlinkSync(workFilePath)
188
+ fs.unlinkSync(workFilePath)
175
189
  await sleep(1000)
176
- _fs.writeFileSync(workFilePath, text)
190
+ fs.writeFileSync(workFilePath, text)
177
191
  let watcher = _chokidar.watch([workFilePath]);
178
192
  _fileWatcherMap[workFilePath] = watcher;
179
193
  setTips("FILE", null, () => {
@@ -185,7 +199,7 @@ async function getFileWatcher(workFilePath, text) {
185
199
 
186
200
  function closeFileWatcher(workFilePath) {
187
201
  let watcher = _fileWatcherMap[workFilePath]
188
- info("workFile close " + workFilePath)
202
+ console.info("workFile close " + workFilePath)
189
203
  watcher.unwatch([workFilePath])
190
204
  watcher.close()
191
205
  delete _fileWatcherMap[workFilePath]
@@ -201,23 +215,23 @@ async function workFile(uniqueName) {
201
215
 
202
216
  async function watchFile(uniqueName) {
203
217
  let workFilePath = getFullPath(uniqueName);
204
- if (!_fs.existsSync(workFilePath)) {
205
- _fs.writeFileSync(workFilePath, '');
218
+ if (!fs.existsSync(workFilePath)) {
219
+ fs.writeFileSync(workFilePath, '');
206
220
  }
207
- let text = String(_fs.readFileSync(workFilePath))
221
+ let text = String(fs.readFileSync(workFilePath))
208
222
  let watcher = await getFileWatcher(workFilePath, text)
209
223
 
210
224
  if (watcher) {
211
225
  watcher.on('change', async () => {
212
- let newText = String(_fs.readFileSync(workFilePath));
226
+ let newText = String(fs.readFileSync(workFilePath));
213
227
  let exeStr = getExeStr(text, newText);
214
228
  text = newText;
215
229
  if (trim(exeStr)) {
216
230
  try {
217
- CONSOLE.log("\n" + infoStr("------ workFile run ------"))
231
+ console.log("\n" + infoStr("------ workFile run ------"))
218
232
  await wrapperInput("# " + exeStr)
219
233
  } catch (e) {
220
- error(e)
234
+ console.error(e)
221
235
  }
222
236
  }
223
237
  }).on("unlink", () => {
@@ -383,7 +397,7 @@ function _nextLine(callback, promptStr, hidden, resolve, end, isText) {
383
397
  closeRl()
384
398
  inputStr = inputStr.replace(/\s+$/, '');
385
399
  if (!isText && /^\d+$/.test(inputStr) && /^\s+/.test(textLine)) {
386
- inputStr = "& " + inputStr;
400
+ inputStr = '.e ' + inputStr;
387
401
  }
388
402
  let pro = (callback || wrapperInput)(inputStr);
389
403
  resolve && resolve(inputStr);
@@ -393,12 +407,8 @@ function _nextLine(callback, promptStr, hidden, resolve, end, isText) {
393
407
  if ((callback || wrapperInput) === wrapperInput) {
394
408
  if (!_noAppendNextLine) {
395
409
  if (/^\s+$/.test(textLine)) {
396
- if (textLine.length > 1) {
397
- clearConsole(false)
398
- } else {
399
- clearConsole();
400
- }
401
- listCmd();
410
+ clearConsole(textLine.length - 1)
411
+ filterCmdAndList();
402
412
  nextLine(null, defaultPromptStr(true))
403
413
  } else {
404
414
  nextLine()
@@ -423,11 +433,11 @@ async function nextText(callback, end, hidden) {
423
433
  async function save(args) {
424
434
  let uniqueName = toUniqueName(toJsirFileName(args.join(' ')))
425
435
  let path = getFullPath(uniqueName)
426
- if (_fs.existsSync(path)) {
427
- warn(`${path} already exist`)
428
- _cmdMap = {
436
+ if (fs.existsSync(path)) {
437
+ console.warn(`${path} already exist`)
438
+ resetCmdMap({
429
439
  1: uniqueName
430
- }
440
+ });
431
441
  listCmd()
432
442
  return
433
443
  }
@@ -439,26 +449,31 @@ async function save(args) {
439
449
  } else {
440
450
  resp = await getCbText();
441
451
  }
442
- _fs.writeFileSync(path, resp)
443
- info(`${path} created`)
444
- _cmdMap = {
452
+ fs.writeFileSync(path, resp)
453
+ console.info(`${path} created`)
454
+ resetCmdMap({
445
455
  1: uniqueName
446
- }
456
+ });
447
457
  listCmd()
448
458
  }
449
459
 
460
+ function resetCmdMap(cmdMap = {}) {
461
+ lastFilterArg = '';
462
+ _cmdMap = cmdMap;
463
+ }
464
+
450
465
  function rename(dir, oldName, newName) {
451
466
  let old = dir + '/' + oldName;
452
467
  let _new = dir + '/' + newName;
453
- if (_fs.existsSync(_new)) {
454
- warn(`${_new} already exist`)
468
+ if (fs.existsSync(_new)) {
469
+ console.warn(`${_new} already exist`)
455
470
  } else {
456
- _fs.renameSync(old, _new)
457
- info(`${_new} renamed`)
471
+ fs.renameSync(old, _new)
472
+ console.info(`${_new} renamed`)
458
473
  }
459
- _cmdMap = {
474
+ resetCmdMap({
460
475
  1: toUniqueName(_new)
461
- }
476
+ });
462
477
  listCmd()
463
478
  }
464
479
 
@@ -471,7 +486,7 @@ function listCmd(tmpMap) {
471
486
  }
472
487
 
473
488
  tmpMap = arrayToCmdMap(Object.values(tmpMap)
474
- .filter(item => _fs.existsSync(getFullPath(item)))
489
+ .filter(item => fs.existsSync(getFullPath(item)))
475
490
  .sort((a,b) => {
476
491
  a = parseUniqueName(a)[1];
477
492
  b = parseUniqueName(b)[1];
@@ -492,7 +507,7 @@ function listCmd(tmpMap) {
492
507
 
493
508
  let items = []
494
509
  for (let i of Object.keys(tmpMap)) {
495
- let text = String(_fs.readFileSync(getFullPath(tmpMap[i])))
510
+ let text = String(fs.readFileSync(getFullPath(tmpMap[i])))
496
511
  let pair = parseUniqueName(tmpMap[i])
497
512
  let name = trimJsirFileName(pair[1])
498
513
  let suffix = getJsirFileSuffix(pair[1])
@@ -504,12 +519,12 @@ function listCmd(tmpMap) {
504
519
  items.push(item)
505
520
 
506
521
  if (!text) {
507
- text = String(_fs.readFileSync(getFullPath(tmpMap[i])))
522
+ text = String(fs.readFileSync(getFullPath(tmpMap[i])))
508
523
  }
509
524
  getComments(i, tmpMap[i], text, items, item)
510
525
  }
511
526
  if (Object.keys(items).length === 0) {
512
- warn("no items")
527
+ console.warn("no items")
513
528
  } else {
514
529
  items.forEach(item => {
515
530
  if (tmpList && item.key) {
@@ -527,7 +542,7 @@ function listCmd(tmpMap) {
527
542
  item.name = pair[0] + '/' + item.name
528
543
  }
529
544
  })
530
- CONSOLE.table(items)
545
+ console.table(items)
531
546
  }
532
547
  }
533
548
 
@@ -535,10 +550,14 @@ async function wrapperInput(str) {
535
550
  try {
536
551
  await _wrapperInput(str);
537
552
  } catch (e) {
538
- error(e)
553
+ console.error(e)
539
554
  }
540
555
  }
541
556
 
557
+ function getEditor() {
558
+ return getConfig("defaultEditor", "vi")
559
+ }
560
+
542
561
  async function _wrapperInput(str) {
543
562
  _haveWrapperInput = true;
544
563
  global.$newInput = true;
@@ -547,20 +566,7 @@ async function _wrapperInput(str) {
547
566
  if (!str) {
548
567
  return;
549
568
  }
550
- if (/^&/.test(str)) {
551
- let cmdStr = trim(str.substr(1));
552
- if (/^\d+$/.test(cmdStr)) {
553
- if (_cmdMap[cmdStr]) {
554
- ei('vi', [getFullPath(_cmdMap[cmdStr])])
555
- } else {
556
- ei('vi', ['-n'])
557
- }
558
- } else if (cmdStr) {
559
- ei(cmdStr.split(/\s+/)[0], enrichArgs(trim(cmdStr.replace(/^\S+/, ''))).map(trim));
560
- } else {
561
- ei('vi', ['-n'])
562
- }
563
- } else if (/^[`'"]/.test(str)) {
569
+ if (/^[`'"]/.test(str)) {
564
570
  let fstr = str.substr(0, 1);
565
571
  if (fstr === '`') {
566
572
  let text = str.substr(1) + "\n" + await nextText(line => line, fstr)
@@ -568,7 +574,7 @@ async function _wrapperInput(str) {
568
574
  } else {
569
575
  let fLine = trim(str.substr(1))
570
576
  if (fLine) {
571
- CONSOLE.log(draftQuery(fLine).join("\n"))
577
+ console.log(draftQuery(fLine).join("\n"))
572
578
  } else {
573
579
  let text = str.substr(1) + "\n" + await nextText(line => line, fstr)
574
580
  $draft(text)
@@ -579,33 +585,16 @@ async function _wrapperInput(str) {
579
585
  let isStar = str.startsWith('*')
580
586
  let text = trim(str.replace(/^[$#*]/, ''))
581
587
  if (is$) {
582
- CONSOLE.log(await evalText('return ' + text))
588
+ console.log(await evalText('return ' + text))
583
589
  } else if (isStar) {
584
- if (!text) {
585
- text = '$context';
586
- }
587
- let result = await evalText('return ' + text)
588
- if (!result || typeof result === 'string' || Object.keys(result).length === 0) {
589
- CONSOLE.nable([getInfo(result)])
590
- return
591
- }
592
- let rows = []
593
- for (let key of Object.keys(result)) {
594
- rows.push(getInfo(result[key], key))
595
- }
596
- if (rows.length === 0) {
597
- warn("no items")
598
- } else {
599
- CONSOLE.nable(rows)
600
- }
590
+ await dealStar(text)
601
591
  } else {
602
592
  await evalText(text)
603
593
  }
604
594
  } else if (str.match(/^\./)) {
605
595
  await dealKeyword(enrichArgs(str))
606
596
  } else if (!str.split(/\s+/)[0].match(/^\d+$/)) {
607
- _cmdMap = arrayToCmdMap(filterCmd(str))
608
- listCmd()
597
+ filterCmdAndList(str);
609
598
  } else {
610
599
  let strs = str.split(/\s+/)
611
600
  if (_cmdMap[strs[0]]) {
@@ -616,7 +605,7 @@ async function _wrapperInput(str) {
616
605
  if (firstName === 'f') {
617
606
  await workFile(uniqueName)
618
607
  } else if (firstName !== 'e') {
619
- CONSOLE.log(String(_fs.readFileSync(path)));
608
+ console.log(String(fs.readFileSync(path)));
620
609
  } else {
621
610
  await runCmd(str)
622
611
  }
@@ -626,6 +615,143 @@ async function _wrapperInput(str) {
626
615
  }
627
616
  }
628
617
 
618
+ async function dealStartGlobalMode(rows, items, text) {
619
+ console.info('global search mode');
620
+ rows.push(...await dealStarCase(await evalText('return $context'), items, '$context'))
621
+ rows.push(...await dealStarCase(global, items, 'global'))
622
+ rows.push(...await dealStarCase($lib, items, '$lib'))
623
+ rows.push(...dealStarGlobal(items, text))
624
+ }
625
+
626
+ async function dealStar(text) {
627
+ if (!text) {
628
+ text = '$context';
629
+ }
630
+ let items = text.split(/\s+/);
631
+ let rows = []
632
+ if (_cmdMap[items[0]]) {
633
+ rows.push(...await dealStarCmd([], _cmdMap[items[0]], '.'))
634
+ } else if (items[0].indexOf("/") !== -1) {
635
+ await dealStartGlobalMode(rows, items, text);
636
+ } else {
637
+ try {
638
+ let result = await evalText(`return ${items[0]}`)
639
+ rows.push(...await dealStarCase(result, items.slice(1)))
640
+ } catch (e) {
641
+ await dealStartGlobalMode(rows, items, text);
642
+ }
643
+ }
644
+ if (rows.length === 0) {
645
+ console.warn("no items")
646
+ } else {
647
+ console.nable(rows)
648
+ }
649
+ }
650
+
651
+ function dealStarGlobal(items, text) {
652
+ let rows = []
653
+ let prefix = ''
654
+ let index = items[0].indexOf("/");
655
+ if (index !== -1) {
656
+ prefix = trim(items[0].substring(0, index + 1))
657
+ text = trim(text.substring(index + 1))
658
+ }
659
+ for (let cmd of filterCmd(prefix + '^i ,')) {
660
+ dealStarCmd(rows, cmd, text)
661
+ }
662
+ return rows;
663
+ }
664
+
665
+ function dealStarCmd(rows, cmd, filterStr) {
666
+ let content = String(fs.readFileSync(getFullPath(cmd)));
667
+ let capturingFunction = false;
668
+ let inMultiLineComment = false;
669
+ let potentialComments = [];
670
+ let functionLines = [];
671
+ let comments = [];
672
+ let fnName = '';
673
+ let fnType = '';
674
+
675
+ // Helper function to reset state
676
+ function resetState() {
677
+ capturingFunction = false;
678
+ fnName = '';
679
+ fnType = '';
680
+ functionLines = [];
681
+ potentialComments = [];
682
+ comments = [];
683
+ }
684
+
685
+ for (let line of content.split('\n')) {
686
+ // Handle multi-line comment start or continue
687
+ if (line.trim().startsWith('/*') || inMultiLineComment) {
688
+ inMultiLineComment = true;
689
+ potentialComments.push(line);
690
+
691
+ // Check for multi-line comment end
692
+ if (line.trim().endsWith('*/')) {
693
+ inMultiLineComment = false;
694
+ }
695
+ continue; // Continue to the next line
696
+ }
697
+
698
+ // Capture single-line comments
699
+ if (line.trim().startsWith('//')) {
700
+ potentialComments.push(line);
701
+ }
702
+
703
+ // Check for function start
704
+ if ((line.startsWith('function') || line.startsWith('async function')) && isArgsMatch(line, [filterStr])) {
705
+ fnName = reget(line, /function\s+(\w+)\s*\(/);
706
+ fnType = line.startsWith('async') ? 'AsyncFunction' : 'Function';
707
+ capturingFunction = true;
708
+ comments = [...potentialComments]; // Confirm the comments are related to the function
709
+ potentialComments = []; // Clear the potential comments as they are now confirmed
710
+ }
711
+
712
+ // Capture function lines
713
+ if (capturingFunction) {
714
+ functionLines.push(line);
715
+ }
716
+
717
+ // Check for function end and process
718
+ if (fnName && line.startsWith("}") && capturingFunction) {
719
+ let functionContent = functionLines.join('\n');
720
+ let commentContent = trimText(comments.join('\n'));
721
+ let row = getInfo(functionContent, fnName, fnType);
722
+ row.value = infoStr(cmd) + ' ' + getCmdMd5Key(parseUniqueName(cmd)[1]) + '\n' + [commentContent, row.value].filter(i => trim(i)).join("\n");
723
+ rows.push(row);
724
+
725
+ resetState();
726
+ }
727
+
728
+ // If not capturing function, reset potential comments
729
+ if (!capturingFunction && !inMultiLineComment && line.trim() !== '' && !line.trim().startsWith('//')) {
730
+ potentialComments = [];
731
+ }
732
+ }
733
+ return rows;
734
+ }
735
+
736
+ async function dealStarCase(result, matchStrs, cmd) {
737
+ let rows = []
738
+ if (!result || typeof result === 'string' || Object.keys(result).length === 0) {
739
+ rows.push(getInfo(result))
740
+ } else {
741
+ for (let key of Object.keys(result)) {
742
+ if (matchStrs.length === 0 || isArgsMatch(key, [matchStrs.join(' ')])){
743
+ rows.push(getInfo(result[key], key))
744
+ }
745
+ }
746
+ }
747
+ if (cmd) {
748
+ for (let row of rows) {
749
+ row.value = infoStr(cmd) + '\n' + row.value;
750
+ }
751
+ }
752
+ return rows;
753
+ }
754
+
629
755
  function arrayToCmdMap(cmds) {
630
756
  let cmdMap = {}
631
757
  for (let i = 0; i < cmds.length; i++) {
@@ -634,8 +760,8 @@ function arrayToCmdMap(cmds) {
634
760
  return cmdMap
635
761
  }
636
762
 
637
- function help() {
638
- CONSOLE.nable(Object.keys(keywordDef).map(key => {
763
+ function help(filterFn) {
764
+ console.nable(Object.keys(keywordDef).filter(i => filterFn ? filterFn(i):true).map(key => {
639
765
  let item = keywordDef[key];
640
766
  return {
641
767
  keyword: ' ' + warnStr(`.${key}`),
@@ -661,19 +787,23 @@ function delTipsByIndex(idxs) {
661
787
  params.push(indexKeyMap[keys.length + 1 + Number(index)])
662
788
  }
663
789
  }
790
+ if (idxs.length > 0 && params.length <= 0) {
791
+ console.warn("no items")
792
+ return;
793
+ }
664
794
  delTips(...params)
665
795
  }
666
796
 
667
797
  function copyToSpace(uniqueName) {
668
798
  let path = getFullPath(uniqueName)
669
- let text = String(_fs.readFileSync(path))
799
+ let text = String(fs.readFileSync(path))
670
800
  let fileName = parseUniqueName(uniqueName)[1];
671
801
  let targetPath = $workspaceMap[$defaultSpace] + '/' + fileName;
672
- if (_fs.existsSync(targetPath)) {
673
- warn(`${fileName} already exist in ${$defaultSpace}`)
802
+ if (fs.existsSync(targetPath)) {
803
+ console.warn(`${fileName} already exist in ${$defaultSpace}`)
674
804
  } else {
675
- _fs.writeFileSync(targetPath, text)
676
- info(`get ${uniqueName} to ${$defaultSpace}`)
805
+ fs.writeFileSync(targetPath, text)
806
+ console.info(`get ${uniqueName} to ${$defaultSpace}`)
677
807
  }
678
808
  }
679
809
 
@@ -696,7 +826,7 @@ let compareMode = {
696
826
  }
697
827
  return result
698
828
  },
699
- 'ab=': (aSpace, bSpace, a, b, as, bs) => {
829
+ 'ab=': (aSpace, bSpace, as, bs) => {
700
830
  let result = []
701
831
  for (let a of as) {
702
832
  if (bs.indexOf(a) !== -1) {
@@ -748,20 +878,10 @@ const keywordDef = {
748
878
  },
749
879
  short: 'h'
750
880
  },
751
- version: {
752
- comment: 'View version',
753
- exeFn: (args) => {
754
- CONSOLE.log(packageJson.version)
755
- },
756
- short: 'v'
757
- },
758
881
  list: {
759
882
  comment: 'View file list',
760
883
  exeFn: (args) => {
761
- if (args.length > 0) {
762
- _cmdMap = arrayToCmdMap(filterCmd(args.length > 0 ? args.join(' '):[',']))
763
- }
764
- listCmd()
884
+ filterCmdAndList(args.length > 0 ? args.join(' '):'');
765
885
  },
766
886
  args: {
767
887
  queryParams: 'string matching, [,] represents all, keywords can be omitted'
@@ -778,22 +898,22 @@ const keywordDef = {
778
898
  },
779
899
  short: 'C'
780
900
  },
781
- see: {
901
+ view: {
782
902
  comment: 'View file',
783
903
  exeFn: (args) => {
784
904
  let uniqueName = _cmdMap[args[0]]
785
905
  if (!uniqueName) {
786
- warn("no items")
906
+ console.warn("no items")
787
907
  } else {
788
908
  let path = getFullPath(uniqueName)
789
- let sourceStr = String(_fs.readFileSync(path))
790
- CONSOLE.log(sourceStr)
909
+ let sourceStr = String(fs.readFileSync(path))
910
+ console.log(sourceStr)
791
911
  }
792
912
  },
793
913
  args: {
794
914
  fileIndex: 'File index'
795
915
  },
796
- short: 's'
916
+ short: 'v'
797
917
  },
798
918
  rm: {
799
919
  comment: 'Remove file',
@@ -802,15 +922,15 @@ const keywordDef = {
802
922
  if (args[0] === 'ALL') {
803
923
  for (let value of Object.values(_cmdMap)) {
804
924
  let path = getFullPath(value)
805
- _fs.unlinkSync(path)
806
- info(`${path} removed`)
925
+ fs.unlinkSync(path)
926
+ console.info(`${path} removed`)
807
927
  }
808
928
  } else if (!uniqueName) {
809
- warn("no items")
929
+ console.warn("no items")
810
930
  } else {
811
931
  let path = getFullPath(uniqueName)
812
- _fs.unlinkSync(path)
813
- info(`${path} removed`)
932
+ fs.unlinkSync(path)
933
+ console.info(`${path} removed`)
814
934
  }
815
935
  },
816
936
  args: {
@@ -827,7 +947,7 @@ const keywordDef = {
827
947
  copyToSpace(value)
828
948
  }
829
949
  } else if (!uniqueName) {
830
- warn("no items")
950
+ console.warn("no items")
831
951
  } else {
832
952
  copyToSpace(uniqueName)
833
953
  }
@@ -842,7 +962,7 @@ const keywordDef = {
842
962
  exeFn: (args) => {
843
963
  let uniqueName = _cmdMap[args[0]]
844
964
  if (!uniqueName) {
845
- warn("no items")
965
+ console.warn("no items")
846
966
  } else {
847
967
  let pair = parseUniqueName(uniqueName)
848
968
  let newName =trim(args.slice(1).join(" "))
@@ -860,10 +980,10 @@ const keywordDef = {
860
980
  exeFn: async (args) => {
861
981
  let uniqueName = _cmdMap[args[0]]
862
982
  if (!uniqueName) {
863
- warn("no items")
983
+ console.warn("no items")
864
984
  } else {
865
985
  let path = getFullPath(uniqueName)
866
- await e(`"${getFileOpenExe(parseUniqueName(uniqueName)[1])}" "${path}"`)
986
+ ei(getEditor(), [path])
867
987
  }
868
988
  },
869
989
  args: {
@@ -871,6 +991,29 @@ const keywordDef = {
871
991
  },
872
992
  short: 'e'
873
993
  },
994
+ setting: {
995
+ comment: 'Global settings',
996
+ exeFn: async (args) => {
997
+ ei(getEditor(), [`${getLibDataDir()}/config.json`])
998
+ },
999
+ short: 's'
1000
+ },
1001
+ open: {
1002
+ comment: 'open file',
1003
+ exeFn: async (args) => {
1004
+ let uniqueName = _cmdMap[args[0]]
1005
+ if (!uniqueName) {
1006
+ console.warn("no items")
1007
+ } else {
1008
+ let path = getFullPath(uniqueName)
1009
+ await e(`"${getFileOpenExe(parseUniqueName(uniqueName)[1])}" "${path}"`)
1010
+ }
1011
+ },
1012
+ args: {
1013
+ fileIndex: 'File index'
1014
+ },
1015
+ short: 'o'
1016
+ },
874
1017
  compare: {
875
1018
  comment: 'Compare files',
876
1019
  exeFn: async (args) => {
@@ -880,27 +1023,30 @@ const keywordDef = {
880
1023
  let bSpace = args[1]
881
1024
 
882
1025
  if (aUniqueName && bUniqueName) {
883
- await e(`${getConfig("compareExe", "idea diff")} "${getFullPath(aUniqueName)}" "${getFullPath(bUniqueName)}"`)
1026
+ let result = await e(`${getConfig("compareExe", "diff")} "${getFullPath(aUniqueName)}" "${getFullPath(bUniqueName)}"`)
1027
+ if (result) {
1028
+ console.log(result)
1029
+ }
884
1030
  } else if (aSpace && bSpace) {
885
1031
  if (!args[2]) {
886
- warn('require mode')
1032
+ console.warn('require mode')
887
1033
  return
888
1034
  }
889
1035
 
890
1036
  let mode = args[2]
891
1037
  if (Object.keys(compareMode).indexOf(mode) === -1) {
892
- warn('invalid mode')
1038
+ console.warn('invalid mode')
893
1039
  return;
894
1040
  }
895
1041
 
896
- let aFiles = _fs.readdirSync($workspaceMap[aSpace]).filter(isJsirFileName)
897
- let bFiles = _fs.readdirSync($workspaceMap[bSpace]).filter(isJsirFileName)
1042
+ let aFiles = fs.readdirSync($workspaceMap[aSpace]).filter(isJsirFileName)
1043
+ let bFiles = fs.readdirSync($workspaceMap[bSpace]).filter(isJsirFileName)
898
1044
 
899
1045
  let result = compareMode[mode](aSpace, bSpace, aFiles, bFiles);
900
- _cmdMap = arrayToCmdMap(result)
1046
+ resetCmdMap(arrayToCmdMap(result))
901
1047
  listCmd()
902
1048
  } else {
903
- warn('invalid args')
1049
+ console.warn('invalid args')
904
1050
  }
905
1051
  },
906
1052
  args: {
@@ -915,23 +1061,38 @@ const keywordDef = {
915
1061
  exeFn: (args) => {
916
1062
  let uniqueName = _cmdMap[args[0]]
917
1063
  if (!uniqueName) {
918
- warn("no items")
1064
+ console.warn("no items")
919
1065
  } else {
920
1066
  let cmds = getScriptRequires(uniqueName);
921
- _cmdMap = arrayToCmdMap([uniqueName, ...cmds])
1067
+ resetCmdMap(arrayToCmdMap([uniqueName, ...cmds]))
922
1068
  listCmd()
923
1069
 
1070
+ let packages = []
924
1071
  for (let un of [uniqueName, ...cmds]) {
925
1072
  let path = getFullPath(un);
926
- let text = removeComment(String(_fs.readFileSync(path)))
927
-
928
- preLoad(text, "[\\s=;]require", requireG);
929
- preLoad(text, "^require", requireG);
1073
+ let text = removeComment(String(fs.readFileSync(path)))
930
1074
 
931
- preLoad(text, "\\$import", importG);
932
- preLoad(text, "[\\s=;]import", importG);
933
- preLoad(text, "^import", importG);
1075
+ preLoad(text, "[\\s=;]require", requireG, packages)
1076
+ preLoad(text, "^require", requireG, packages)
1077
+ preLoad(text, "\\$import", importG, packages)
1078
+ preLoad(text, "[\\s=;]import", importG, packages)
1079
+ preLoad(text, "^import", importG, packages)
934
1080
  }
1081
+ let moduleDir = $workspaceMap[global.$defaultSpace] + '/node_modules'
1082
+ let deps = {}
1083
+ packages.forEach(name => {
1084
+ if (deps[name]) {
1085
+ return;
1086
+ }
1087
+ let dir = moduleDir + "/" + name;
1088
+ if (fs.existsSync(dir) && fs.existsSync(dir + '/package.json')) {
1089
+ deps[name] = require(dir + '/package.json').version;
1090
+ } else {
1091
+ deps[name] = 'Unknown';
1092
+ }
1093
+ })
1094
+ console.info("package version")
1095
+ console.log(JSON.stringify(deps, null, 2))
935
1096
  }
936
1097
  },
937
1098
  args: {
@@ -947,7 +1108,7 @@ const keywordDef = {
947
1108
  } else {
948
1109
  let name = _cmdMap[args[0]]
949
1110
  if (!name) {
950
- warn("no items")
1111
+ console.warn("no items")
951
1112
  } else {
952
1113
  await watchFile(name)
953
1114
  }
@@ -963,73 +1124,34 @@ const keywordDef = {
963
1124
  exeFn: async (args) => {
964
1125
  let newWorkspace = args.join(' ')
965
1126
  if (newWorkspace) {
966
- let workspaces = Object.values($workspaceMap)
967
- workspaces.push(newWorkspace)
968
- arrayDataFile(_workspaceConfigFile, () => workspaces)
1127
+ if ($workspaceMap[newWorkspace]) {
1128
+ initWorkspace(newWorkspace)
1129
+ } else if (newWorkspace.startsWith('-')) {
1130
+ let name = newWorkspace.replace(/^-\s*/, '');
1131
+ arrayDataFile(_workspaceConfigFile, arr => arr.filter(path => name !== getSpaceFromDir(path)))
1132
+ } else if (newWorkspace.startsWith("/")) {
1133
+ let workspaces = Object.values($workspaceMap)
1134
+ workspaces.push(newWorkspace)
1135
+ arrayDataFile(_workspaceConfigFile, () => workspaces)
1136
+ } else {
1137
+ console.warn('invalid args')
1138
+ }
969
1139
  }
970
1140
  checkWorkspaces()
971
1141
  let workspaces = Object.values($workspaceMap)
972
1142
  let items = workspaces.map((path, index) => {
973
1143
  return {
974
- index: ' ' + (index + 1),
975
- name: getSpaceFromDir(path),
1144
+ name: (getSpaceFromDir(path) === $defaultSpace ? '*':' ') + getSpaceFromDir(path),
976
1145
  path
977
1146
  }
978
1147
  })
979
- CONSOLE.table(items)
1148
+ console.table(items)
980
1149
  },
981
1150
  args: {
982
1151
  workspacePath: 'New workspace path'
983
1152
  },
984
1153
  short: 'w'
985
1154
  },
986
- uninstall: {
987
- comment: 'Uninstall workspace',
988
- exeFn: async (args) => {
989
- let workspaces = Object.values($workspaceMap)
990
- let items = workspaces.map((path, index) => {
991
- return {
992
- index: ' ' + (index + 1),
993
- name: getSpaceFromDir(path),
994
- path
995
- }
996
- })
997
- CONSOLE.table(items)
998
- let index = await nextLine(line => line, "index: ")
999
- let workspace = workspaces[index - 1]
1000
- if (workspace) {
1001
- workspaces = workspaces.filter(i => i !== workspace);
1002
- arrayDataFile(_workspaceConfigFile, () => workspaces);
1003
- checkWorkspaces()
1004
- } else {
1005
- warn('invalid args')
1006
- }
1007
- },
1008
- short: 'u'
1009
- },
1010
- switch: {
1011
- comment: 'Switch workspace',
1012
- exeFn: async (args) => {
1013
- checkWorkspaces()
1014
- let workspaces = Object.values($workspaceMap)
1015
- let items = workspaces.map((path, index) => {
1016
- return {
1017
- index: ' ' + (index + 1),
1018
- name: getSpaceFromDir(path),
1019
- path
1020
- }
1021
- })
1022
- CONSOLE.table(items)
1023
- let index = trim(await nextLine(line => line, "switch workspace: "));
1024
- if (index && workspaces[index - 1]) {
1025
- let workspace = workspaces[index - 1];
1026
- initWorkspace(getSpaceFromDir(workspace))
1027
- } else {
1028
- warn('no items')
1029
- }
1030
- },
1031
- short: 'S'
1032
- },
1033
1155
  add: {
1034
1156
  comment: 'Add file',
1035
1157
  exeFn: async (args) => {
@@ -1044,7 +1166,7 @@ const keywordDef = {
1044
1166
  comment: 'Quick execution',
1045
1167
  exeFn: async (args) => {
1046
1168
  if (!args[0]) {
1047
- warn('invalid args')
1169
+ console.warn('invalid args')
1048
1170
  return
1049
1171
  }
1050
1172
  let keyword = args[0]
@@ -1052,13 +1174,20 @@ const keywordDef = {
1052
1174
  if (keyword.endsWith('.')) {
1053
1175
  let _tmp = trim(keyword.substring(0, keyword.length - 1));
1054
1176
  if (_tmp) {
1177
+ if (keywordDef[_tmp] || Object.values(keywordDef).map(item => item.short).indexOf(_tmp) !== -1) {
1178
+ help(i => i === _tmp || keywordDef[i].short === _tmp);
1179
+ return;
1180
+ }
1055
1181
  justList = true;
1056
1182
  keyword = _tmp;
1183
+ } else {
1184
+ console.warn('invalid keyword')
1185
+ return
1057
1186
  }
1058
1187
  }
1059
1188
  let pair = parseUniqueName(keyword)
1060
1189
  let cmds;
1061
- if (/^0x[a-z\d]{8}$/.test(pair[1]) || pair[1].indexOf(",") !== -1) {
1190
+ if (isMd5Key(pair[1]) || pair[1].indexOf(",") !== -1) {
1062
1191
  cmds = getQuickRunCmds(keyword, keyword)
1063
1192
  } else {
1064
1193
  cmds = getQuickRunCmds(keyword, '^e ' + toJsirFileName(pair[1]) + '$')
@@ -1073,7 +1202,7 @@ const keywordDef = {
1073
1202
  await runScript(cmds[0], args.slice(1))
1074
1203
  }
1075
1204
  } else {
1076
- warn(cmds.length > 1 ? "multiple match" : "no match")
1205
+ console.warn(cmds.length > 1 ? "multiple match" : "no match")
1077
1206
  }
1078
1207
  },
1079
1208
  args: {
@@ -1085,8 +1214,8 @@ const keywordDef = {
1085
1214
  comment: 'Exit',
1086
1215
  exeFn: (args) => {
1087
1216
  delTips();
1088
- CONSOLE.log(infoStr("Bye!"))
1089
- process.exit(0)
1217
+ console.log(infoStr("Bye!"));
1218
+ _noAppendNextLine = true;
1090
1219
  },
1091
1220
  short: 'q'
1092
1221
  },
@@ -1094,10 +1223,24 @@ const keywordDef = {
1094
1223
  comment: 'Interactive interface',
1095
1224
  exeFn: (args) => {
1096
1225
  _noAppendNextLine = false
1097
- _cmdMap = {}
1098
- CONSOLE.log(warnStr("You can start with .help, use * to expand context"))
1226
+ resetCmdMap()
1227
+ console.log(warnStr(`(${setting.name} ${packageJson.version}) You can start with .help, use * to expand context.`))
1099
1228
  },
1100
1229
  short: 'p'
1230
+ },
1231
+ npm: {
1232
+ comment: 'Node npm',
1233
+ exeFn: (args) => {
1234
+ let packageFile = $workspaceMap[global.$defaultSpace] + '/package.json';
1235
+ if(!fs.existsSync(packageFile)) {
1236
+ let jsonObj = {
1237
+ "dependencies": {}
1238
+ }
1239
+ fs.writeFileSync(packageFile, JSON.stringify(jsonObj, null, 2));
1240
+ }
1241
+ ei(`cd "${$workspaceMap[global.$defaultSpace]}";npm ${args.join(' ')}`, [], true)
1242
+ },
1243
+ short: 'N'
1101
1244
  }
1102
1245
  }
1103
1246
 
@@ -1111,18 +1254,28 @@ function getQuickRunCmds(input, matchStr) {
1111
1254
  return filterCmd(matchStr).filter(i => parseUniqueName(i)[1].startsWith("e "))
1112
1255
  }
1113
1256
 
1114
- function preLoad(text, fnNameMatch, fn) {
1257
+ function preLoad(text, fnNameMatch, fn, packages = []) {
1115
1258
  regEach(text, new RegExp(`${fnNameMatch}\\s*\\(([^()]+)\\)`, 'g'), r=> {
1116
1259
  let item = trim(r[1])
1117
1260
  if (item) {
1118
1261
  try {
1119
- let result = fn(evalVal(item))
1262
+ let packageName = evalVal(item);
1263
+ if (packages.indexOf(packageName) !== -1) {
1264
+ return;
1265
+ }
1266
+ packages.push(packageName)
1267
+ let result = fn(packageName)
1120
1268
  if (getType(result) === 'Promise') {
1121
- result.catch(e => {})
1269
+ result.catch(e => {
1270
+ $log(e)
1271
+ })
1122
1272
  }
1123
- } catch (e) {}
1273
+ } catch (e) {
1274
+ $log(e)
1275
+ }
1124
1276
  }
1125
1277
  });
1278
+ return packages;
1126
1279
  }
1127
1280
 
1128
1281
  async function dealKeyword(items) {
@@ -1195,7 +1348,7 @@ function removeComment(text) {
1195
1348
 
1196
1349
  function _getScriptRequires(uniqueName, cmds, links) {
1197
1350
  let path = getFullPath(uniqueName);
1198
- let text = removeComment(String(_fs.readFileSync(path)))
1351
+ let text = removeComment(String(fs.readFileSync(path)))
1199
1352
  let temp = []
1200
1353
  regEach(text, /\$require\s*\(([^()]+)\)/g, r=> {
1201
1354
  if (r[1]) {
@@ -1245,7 +1398,7 @@ function getComments(i, cmdName, text, cols = [], col) {
1245
1398
  let docLines = [getCmdMd5Key(parseUniqueName(cmdName)[1]) + " - " + i]
1246
1399
  text = trim(text)
1247
1400
  docLines.push(...getTextComments(text))
1248
- let argDef = getArgDef(text)
1401
+ let argDef = getArgDef(text, cmdName)
1249
1402
  let comments = getArgComments(argDef, true)
1250
1403
  if (comments) {
1251
1404
  docLines.push(...comments)
@@ -1284,7 +1437,7 @@ function getFullPath(name) {
1284
1437
  function toUniqueName(name, space) {
1285
1438
  name = trim(name)
1286
1439
  if (!name) {
1287
- throw `invalid name`
1440
+ throw `invalid name '${name}'`
1288
1441
  }
1289
1442
  let uniqueName
1290
1443
  if (name.startsWith('/')) {
@@ -1302,14 +1455,14 @@ function toUniqueName(name, space) {
1302
1455
  function toJsirFileName(name) {
1303
1456
  name = trim(name)
1304
1457
  if (!name) {
1305
- throw `invalid name`
1458
+ throw `invalid name '${name}'`
1306
1459
  }
1307
1460
  if (isJsirFileName(name)) {
1308
1461
  return name;
1309
1462
  }
1310
1463
  name = name + '.js'
1311
1464
  if (!isJsirFileName(name)) {
1312
- throw `invalid name`
1465
+ throw `invalid name '${name}'`
1313
1466
  }
1314
1467
  return name
1315
1468
  }
@@ -1346,15 +1499,32 @@ function initWorkspace(space) {
1346
1499
  global.$defaultSpace = workspace;
1347
1500
  }
1348
1501
 
1502
+ function filterCmdAndList(arg) {
1503
+ arg = trim(arg) || lastFilterArg;
1504
+ if (arg) {
1505
+ if (lastFilterArg !== arg) {
1506
+ lastFilterArg = arg;
1507
+ if (_noAppendNextLine) {
1508
+ setConfig("lastFilterArg", lastFilterArg)
1509
+ }
1510
+ }
1511
+ _cmdMap = arrayToCmdMap(filterCmd(arg));
1512
+ }
1513
+ listCmd();
1514
+ }
1515
+
1349
1516
  function filterCmd(arg){
1517
+ let cmds = []
1350
1518
  arg = trim(arg)
1519
+ if (!arg) {
1520
+ return cmds;
1521
+ }
1351
1522
  let spaceName
1352
1523
  if (arg.indexOf('/') !== -1) {
1353
1524
  let index = arg.indexOf('/');
1354
1525
  spaceName = trim(arg.substring(0, index)) || $defaultSpace
1355
1526
  arg = trim(arg.substring(index + 1))
1356
1527
  }
1357
- let cmds = []
1358
1528
  for (let workspace of Object.values($workspaceMap)) {
1359
1529
  let spaceTmp = getSpaceFromDir(workspace);
1360
1530
  if (!spaceName || spaceName === spaceTmp) {
@@ -1366,7 +1536,7 @@ function filterCmd(arg){
1366
1536
 
1367
1537
  function _filterCmd(dirPath, arg) {
1368
1538
  let cmdMap = {}
1369
- let files = _fs.readdirSync(dirPath).filter(isJsirFileName)
1539
+ let files = fs.readdirSync(dirPath).filter(isJsirFileName)
1370
1540
  for (let file of files) {
1371
1541
  file = trim(file)
1372
1542
  let uniqueName = toUniqueName(dirPath + '/' + file)
@@ -1457,7 +1627,7 @@ async function runCmd(str = '', uniqueName = '', text = '') {
1457
1627
  let strs = str.split(/\s+/)
1458
1628
  if (!uniqueName) {
1459
1629
  if (!_cmdMap[strs[0]] && strs[0] !== '0') {
1460
- warn('no items')
1630
+ console.warn('no items')
1461
1631
  return
1462
1632
  }
1463
1633
  if (_cmdMap[strs[0]]) {
@@ -1467,7 +1637,7 @@ async function runCmd(str = '', uniqueName = '', text = '') {
1467
1637
 
1468
1638
  if (uniqueName) {
1469
1639
  path = getFullPath(uniqueName);
1470
- text = String(_fs.readFileSync(path))
1640
+ text = String(fs.readFileSync(path))
1471
1641
  } else {
1472
1642
  text = await getCbText()
1473
1643
  }
@@ -1488,7 +1658,7 @@ async function runCmd(str = '', uniqueName = '', text = '') {
1488
1658
 
1489
1659
  async function runScript(uniqueName, oriArgs) {
1490
1660
  let path = getFullPath(uniqueName);
1491
- let text = String(_fs.readFileSync(path))
1661
+ let text = String(fs.readFileSync(path))
1492
1662
  let argDef = getArgDef(text)
1493
1663
  let scriptArgs = await getScriptArgs(argDef, oriArgs);
1494
1664
  process.argv = [process.argv[0], path, ...(scriptArgs.map(String))]
@@ -1510,7 +1680,7 @@ async function getScriptArgs(argDef, oriArgs) {
1510
1680
  }
1511
1681
  if (arg.startsWith(":") || arg.startsWith("_") && !arg.endsWith(' ')) {
1512
1682
  arg = arg.replace(/^:/, '')
1513
- if (oriArgs[i+1] && (oriArgs[i+1].endsWith(' ') || !(oriArgs[i+1].startsWith(":") || oriArgs[i+1].startsWith("_")))) {
1683
+ if (oriArgs[i+1] && (oriArgs[i+1].endsWith(' ') || !(oriArgs[i+1].startsWith(":") || oriArgs[i+1].startsWith("_") || oriArgs[i+1].startsWith("-")))) {
1514
1684
  pair = [arg, oriArgs[i+1]]
1515
1685
  i++
1516
1686
  } else {
@@ -1560,7 +1730,7 @@ async function getScriptArgs(argDef, oriArgs) {
1560
1730
  }
1561
1731
  if (scriptArgKeys.indexOf(name) === -1 || (reg && !reg.test(scriptArgs[name]))) {
1562
1732
  argAbsent = true
1563
- warn(`require ${warnStr(name)}` + (defStr ? ` <${defStr}>`:''))
1733
+ console.warn(`require ${warnStr(name)}` + (defStr ? ` <${defStr}>`:''))
1564
1734
  }
1565
1735
  }
1566
1736
  if (argAbsent) {
@@ -1600,11 +1770,39 @@ function enrichArgs(str) {
1600
1770
  return args
1601
1771
  }
1602
1772
 
1603
- function getArgDef(text) {
1604
- let exeStr = trim(reget(text, /\$defArgs\(\s*(\{[\s\S]*?\})\s*\)/))
1773
+ function parseArgDef(inputString) {
1774
+ let result = {}
1775
+ let preStr = trim(reget(inputString, /\{([\s\S]*?)}\s*=\s*\$defArgs\s*\(/))
1776
+ if (!preStr) {
1777
+ return result;
1778
+ }
1779
+ let ss = preStr.split(/[,\n]|(?<!\/)\/(?=\/)/g).map(trim).filter(i => i);
1780
+ for (let i = 0; i < ss.length; i++) {
1781
+ let s1 = trim(ss[i]);
1782
+ if (s1.startsWith("/")) {
1783
+ continue;
1784
+ }
1785
+ if (ss[i+1] && ss[i+1].startsWith("/")) {
1786
+ result[s1] = trim(ss[i+1].replace(/^\//, ""));
1787
+ i++;
1788
+ } else {
1789
+ result[s1] = '';
1790
+ }
1791
+ }
1792
+ return result;
1793
+ }
1794
+
1795
+ function getArgDef(text, uniqueName) {
1796
+ if (uniqueName && !parseUniqueName(uniqueName)[1].startsWith("e ")) {
1797
+ return {}
1798
+ }
1799
+ if (text.indexOf("$defArgs") === -1) {
1800
+ return {}
1801
+ }
1802
+ let exeStr = trim(reget(text, /\$defArgs\s*\(\s*(\{[\s\S]*?})\s*\)/))
1605
1803
  let argDef = {}
1606
1804
  try {
1607
- argDef = (exeStr ? evalVal(exeStr) : {}) || {}
1805
+ argDef = (exeStr ? evalVal(exeStr) : parseArgDef(text)) || {}
1608
1806
  let array = []
1609
1807
  for (let key of Object.keys(argDef)) {
1610
1808
  if (/\s/.test(key) || array.hasOwnProperty(key)) {
@@ -1666,7 +1864,7 @@ function tipsOnRmCallback(key) {
1666
1864
  callback()
1667
1865
  } catch (e) {
1668
1866
  $log(errorStack(e))
1669
- error(`[${key}] OnRmCallback: ${String(e)}`)
1867
+ console.error(`[${key}] OnRmCallback: ${String(e)}`)
1670
1868
  }
1671
1869
  }
1672
1870
  }
@@ -1676,6 +1874,10 @@ function getCmdMd5Key(str) {
1676
1874
  return '0x' + md5(str).substr(0, 8);
1677
1875
  }
1678
1876
 
1877
+ function isMd5Key(str) {
1878
+ return /^0x[a-z\d]{8}$/.test(str);
1879
+ }
1880
+
1679
1881
  function filterRequire(currSpace, cmdMatchStr) {
1680
1882
  if (typeof cmdMatchStr === 'number') {
1681
1883
  cmdMatchStr = '0x' + pad(8, BigNumber(cmdMatchStr).toString(16), '0');
@@ -1690,7 +1892,7 @@ function filterRequire(currSpace, cmdMatchStr) {
1690
1892
  uName = pr[0] + "/i " + pr[1]
1691
1893
  fullPath = getFullPath(uName)
1692
1894
  }
1693
- if (fullPath && _fs.existsSync(fullPath)) {
1895
+ if (fullPath && fs.existsSync(fullPath)) {
1694
1896
  cmds = [uName]
1695
1897
  } else {
1696
1898
  let appointSpace = parseUniqueName(cmdMatchStr)[0]
@@ -1711,7 +1913,7 @@ async function _requireSource(currSpace, cmdMatchStr) {
1711
1913
  let result
1712
1914
  let uniqueName = filterRequire(currSpace, cmdMatchStr);
1713
1915
  let path = getFullPath(uniqueName)
1714
- let text = String(_fs.readFileSync(path))
1916
+ let text = String(fs.readFileSync(path))
1715
1917
  let pair = parseUniqueName(uniqueName)
1716
1918
  if (pair[1].startsWith('i ')) {
1717
1919
  result = await evalText(text, uniqueName)
@@ -1725,27 +1927,31 @@ async function _requireSource(currSpace, cmdMatchStr) {
1725
1927
  if (!vl(result)) {
1726
1928
  throw `invalid result: ${cmdMatchStr}`
1727
1929
  }
1728
- if (getType(result) === 'Function' || getType(result) === 'AsyncFunction') {
1729
- let tmp = result;
1730
- result = (...args) => {
1731
- let resp
1732
- try {
1733
- resp = tmp(...args)
1734
- if (getType(resp) === 'Promise') {
1735
- return resp.then(result => {
1736
- return Promise.resolve(result);
1737
- }).catch(e => {
1738
- return Promise.reject(errorTag(e, uniqueName))
1739
- })
1740
- } else {
1741
- return resp;
1742
- }
1743
- } catch (e) {
1744
- throw errorTag(e, uniqueName);
1745
- }
1930
+ return result
1931
+ }
1932
+
1933
+ function addErrorTag(text) {
1934
+ let result = [];
1935
+ let lines = text.split(/\n/);
1936
+ let functionEnd = true;
1937
+ let fnName = '';
1938
+ for (let i = 0; i < lines.length; i++) {
1939
+ let line = lines[i];
1940
+ result.push(line);
1941
+ if (line.startsWith('async function') || line.startsWith('function')) {
1942
+ fnName = reget(line, /function\s+([\s\S]+)\s*\(/)
1943
+ }
1944
+ if (functionEnd && fnName && (/\)\s*\{$/.test(trim(line)) || (line.startsWith("{") && trim(line) === '{'))) {
1945
+ result[i] += 'try{';
1946
+ functionEnd = false;
1947
+ }
1948
+ if (line.startsWith("}") && !functionEnd) {
1949
+ result[i] = `}catch(e){throw($errorTag(e,$cmdName+'[${fnName}]'))}` + line;
1950
+ functionEnd = true;
1951
+ fnName = '';
1746
1952
  }
1747
1953
  }
1748
- return result
1954
+ return result.join('\n');
1749
1955
  }
1750
1956
 
1751
1957
  async function evalText($text = '', $cmdName = '', $args = []) {
@@ -1766,30 +1972,26 @@ async function evalText($text = '', $cmdName = '', $args = []) {
1766
1972
  let $require = async (matchItem) => {
1767
1973
  return await _requireSource(currSpace, matchItem)
1768
1974
  }
1769
- try {
1770
- return await evalCode($text, $cmdName, $args,
1771
- $data, $config,
1772
- $require, $requires,
1773
- nextLine, nextText,
1774
- setTips, delTips,
1775
- wrapperInput, filterCmd,
1776
- currSpace,
1777
- $homeDir, $lib)
1778
- } catch(e) {
1779
- throw errorTag(e, $cmdName);
1780
- }
1975
+ return await evalCode(addErrorTag($text), $cmdName, $args,
1976
+ $data, $config,
1977
+ $require, $requires,
1978
+ nextLine, nextText,
1979
+ setTips, delTips,
1980
+ wrapperInput, filterCmd,
1981
+ currSpace,
1982
+ $homeDir, $lib, _cmdMap);
1781
1983
  }
1782
1984
 
1783
1985
  process.on('uncaughtException',function(err){
1784
- error(err, 'uncaughtException', )
1986
+ console.error('uncaughtException', err)
1785
1987
  _noAppendNextLine || nextLine()
1786
1988
  })
1787
1989
  process.on('unhandledRejection',function(err){
1788
- error(err, 'unhandledRejection')
1990
+ console.error('unhandledRejection', err)
1789
1991
  _noAppendNextLine || nextLine()
1790
1992
  })
1791
1993
  process.on('rejectionHandled',function(err){
1792
- error(err, 'rejectionHandled')
1994
+ console.error('rejectionHandled', err)
1793
1995
  _noAppendNextLine || nextLine()
1794
1996
  })
1795
1997
  process.on('SIGINT', function () {