jsir 2.2.1 → 2.2.3

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
@@ -3,11 +3,15 @@ const $lib = require('../deps/util');
3
3
  const {
4
4
  getLibDataDir, trim, regEach, getConfig, mkdir, reget,
5
5
  getCbText, e, sleep, objDataFile, vl, md5, BigNumber,
6
- arrayDataFile, infoStr, warnStr, errorStack,
6
+ arrayDataFile, infoStr, warnStr,
7
7
  getInfo, ei, pad, msgStr, getType,
8
- isArgsMatch, draftQuery, setConfig,
9
- $log, $draft, getTextComments, getOr, importG, requireG,
10
- clearConsole, trimText
8
+ isMatch, draftQuery, setConfig,
9
+ getTextComments, importG, requireG,
10
+ clearConsole, trimText, getFnArgsStr,
11
+ createConsole, setTips, delTips,
12
+ getEditor, errorStr, getConfigDir,
13
+ getFullPath, parseUniqueName, toUniqueName, isJsirFileName, toJsirFileName,
14
+ fileJson, fileLock, getOr
11
15
  } = $lib;
12
16
  const _args = process.argv.slice(2).map(trim);
13
17
  const evalCode = require('../deps/evalCode')
@@ -15,23 +19,19 @@ const {evalVal} = require('../deps/cleanEval')
15
19
  const _chokidar = require('chokidar');
16
20
  const setting = require('../deps/setting')
17
21
  const fs = require('fs')
22
+ const fp = require('fs').promises
18
23
  const readline = require("readline");
19
24
  const packageJson = require("../package.json");
20
25
  const example = require("../deps/example");
21
26
  const _workspaceConfigFile = 'workspace.json';
22
27
  const _libDataDir = getLibDataDir()
23
- const _tipsOnRm = {}
24
28
  const _fileWatcherMap = {}
25
29
  const _types = {
26
30
  'e': "exe",
27
31
  'i': "init",
28
32
  'f': "file"
29
33
  }
30
- const $config = {
31
- get: getConfig,
32
- set: setConfig
33
- }
34
- const console = Object.assign({}, global.console);
34
+ const console = createConsole();
35
35
 
36
36
  let lastFilterArg = '';
37
37
  let _cmdMapFile = setting.name + 'CmdMap.json'
@@ -42,8 +42,8 @@ let _haveWrapperInput = true
42
42
  let _noAppendNextLine = true
43
43
  let _onLazyTempCode = null
44
44
 
45
- const _onLazyGetMap = {}
46
- const _data = {}
45
+ const _onLazyGetMap = Object.create(null)
46
+ const _data = Object.create(null)
47
47
  const _lazyTime = 5 * 60 * 1000
48
48
  const _dealOnLazyGet = (key, onLazyTempCode) => {
49
49
  if (_noAppendNextLine || !_onLazyGetMap[key]) {
@@ -120,16 +120,15 @@ const $data = {
120
120
  delete _data[key]
121
121
  return val
122
122
  },
123
- keys: () => Object.keys(_data),
124
- have: (key) => vl(_data[key])
123
+ key: () => Object.keys(_data),
124
+ has: (key) => vl(_data[key])
125
+ }
126
+ const $file = {
127
+ json: fileJson,
128
+ lock: fileLock
125
129
  }
126
130
  const $homeDir = getLibDataDir()
127
131
 
128
- global.$tips = {}
129
- global.$newInput = false
130
- global.$workspaceMap = {}
131
- global.$defaultSpace = 'local'
132
-
133
132
  function getFileOpenExe(fileName) {
134
133
  fileName = trim(fileName);
135
134
  let strs = fileName.split('.')
@@ -321,10 +320,17 @@ function initRl(callback, promptStr, hidden) {
321
320
  }
322
321
  origin_writeToOutput = _rl._writeToOutput
323
322
  if (promptStr !== '') {
324
- promptStr = (promptStr
325
- || ((callback && callback !== wrapperInput) ? "-> ":"")
326
- || defaultPromptStr())
327
- promptStr = infoStr(promptStr)
323
+ promptStr = promptStr || ((callback && callback !== wrapperInput) ? "-> ":"")
324
+ if (promptStr) {
325
+ promptStr = infoStr(promptStr);
326
+ } else {
327
+ if (global.$newError) {
328
+ global.$newError = false;
329
+ promptStr = errorStr(defaultPromptStr())
330
+ } else {
331
+ promptStr = infoStr(defaultPromptStr())
332
+ }
333
+ }
328
334
  }
329
335
  if (hidden) {
330
336
  _rl._writeToOutput = function _writeToOutput(stringToWrite){
@@ -346,7 +352,13 @@ function initRl(callback, promptStr, hidden) {
346
352
  function getTipStr(showKey = false) {
347
353
  let items = [];
348
354
  for (let key of Object.keys(global.$tips)) {
349
- let val = global.$tips[key].map(i => trim(i).replace(/,/g, '-')).join("|");
355
+ let val = global.$tips[key].map(i => {
356
+ let item = trim(i)
357
+ if (item.indexOf(',') !== -1) {
358
+ item = `[${item}]`;
359
+ }
360
+ return item;
361
+ }).join("|");
350
362
  key = trim(key)
351
363
 
352
364
  let item
@@ -470,6 +482,15 @@ function rename(dir, oldName, newName) {
470
482
  } else {
471
483
  fs.renameSync(old, _new)
472
484
  console.info(`${_new} renamed`)
485
+
486
+ let configDir = getConfigDir();
487
+ let uniqueOld = toUniqueName(old);
488
+ let uniqueNew = toUniqueName(_new);
489
+ let configFileOld = configDir + '/' + md5(uniqueOld) + '.json';
490
+ let configFileNew = configDir + '/' + md5(uniqueNew) + '.json';
491
+ if (fs.existsSync(configFileOld) && !fs.existsSync(configFileNew)) {
492
+ fs.renameSync(configFileOld, configFileNew)
493
+ }
473
494
  }
474
495
  resetCmdMap({
475
496
  1: toUniqueName(_new)
@@ -513,7 +534,7 @@ function listCmd(tmpMap) {
513
534
  let suffix = getJsirFileSuffix(pair[1])
514
535
  let item = {
515
536
  key: ' ' + i,
516
- name: pair[0] + '/' + name.replace(/^[eif]\s+/, ''),
537
+ name: pair[0] + '/' + name,
517
538
  type: [_types[name.split(/\s+/)[0]] || 'note', suffix].map(trim).join(".")
518
539
  }
519
540
  items.push(item)
@@ -554,10 +575,6 @@ async function wrapperInput(str) {
554
575
  }
555
576
  }
556
577
 
557
- function getEditor() {
558
- return getConfig("defaultEditor", "vi")
559
- }
560
-
561
578
  async function _wrapperInput(str) {
562
579
  _haveWrapperInput = true;
563
580
  global.$newInput = true;
@@ -576,8 +593,7 @@ async function _wrapperInput(str) {
576
593
  if (fLine) {
577
594
  console.log(draftQuery(fLine).join("\n"))
578
595
  } else {
579
- let text = str.substr(1) + "\n" + await nextText(line => line, fstr)
580
- $draft(text)
596
+ console.$draft(await nextText(line => line, fstr))
581
597
  }
582
598
  }
583
599
  } else if (/^[$#*]/.test(str)) {
@@ -629,8 +645,8 @@ async function dealStar(text) {
629
645
  }
630
646
  let items = text.split(/\s+/);
631
647
  let rows = []
632
- if (_cmdMap[items[0]]) {
633
- rows.push(...await dealStarCmd([], _cmdMap[items[0]], '.'))
648
+ if (_cmdMap.hasOwnProperty(items[0])) {
649
+ rows.push(...await dealStarCmd([], _cmdMap[items[0]], items.slice(1).join(' ')))
634
650
  } else if (items[0].indexOf("/") !== -1) {
635
651
  await dealStartGlobalMode(rows, items, text);
636
652
  } else {
@@ -641,6 +657,7 @@ async function dealStar(text) {
641
657
  await dealStartGlobalMode(rows, items, text);
642
658
  }
643
659
  }
660
+ rows = rows.filter(i => !i.name || (!i.name.startsWith('_') && i.name.indexOf('._') === -1));
644
661
  if (rows.length === 0) {
645
662
  console.warn("no items")
646
663
  } else {
@@ -662,8 +679,60 @@ function dealStarGlobal(items, text) {
662
679
  return rows;
663
680
  }
664
681
 
682
+ function wrapperClassLine(className, classLines) {
683
+ let str = trimText(classLines.join('\n'))
684
+ let results = []
685
+ for (let line of str.split('\n')) {
686
+ let asyncMethod = false;
687
+ if (line.startsWith("async ")) {
688
+ // 检查是否为异步方法
689
+ asyncMethod = true;
690
+ line = line.replace("async ", "").trim(); // 去除 'async ' 前缀
691
+ }
692
+ const methodMatch = line.match(/^\w+\s*\(/);
693
+ if (methodMatch) {
694
+ let prefix = `function ${className}.`;
695
+ if (asyncMethod) {
696
+ prefix = "async " + prefix;
697
+ }
698
+ results.push(prefix + line.trim());
699
+ continue;
700
+ }
701
+ results.push(line)
702
+ }
703
+ return results;
704
+ }
705
+
706
+ function wrapperClass(lines) {
707
+ let results = [];
708
+ let className = null;
709
+ let inClass = false;
710
+
711
+ let classLines = []
712
+ for (let line of lines) {
713
+ if (line.startsWith("class ")) {
714
+ inClass = true;
715
+ className = reget(line, /^class\s+(\w+)/);
716
+ continue
717
+ } else if (inClass && line.startsWith("}")) {
718
+ inClass = false
719
+ results.push(...wrapperClassLine(className, classLines));
720
+ classLines = []
721
+ continue;
722
+ }
723
+
724
+ if (inClass) {
725
+ classLines.push(line)
726
+ } else {
727
+ results.push(line);
728
+ }
729
+ }
730
+ return results;
731
+ }
732
+
665
733
  function dealStarCmd(rows, cmd, filterStr) {
666
734
  let content = String(fs.readFileSync(getFullPath(cmd)));
735
+ let lines = wrapperClass(content.split('\n'));
667
736
  let capturingFunction = false;
668
737
  let inMultiLineComment = false;
669
738
  let potentialComments = [];
@@ -682,7 +751,7 @@ function dealStarCmd(rows, cmd, filterStr) {
682
751
  comments = [];
683
752
  }
684
753
 
685
- for (let line of content.split('\n')) {
754
+ for (let [index, line] of lines.entries()) {
686
755
  // Handle multi-line comment start or continue
687
756
  if (line.trim().startsWith('/*') || inMultiLineComment) {
688
757
  inMultiLineComment = true;
@@ -701,12 +770,16 @@ function dealStarCmd(rows, cmd, filterStr) {
701
770
  }
702
771
 
703
772
  // 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
773
+ if ((line.startsWith('function ') || line.startsWith('async function '))) {
774
+ let _fnName = reget(line, /function\s+([\w.]+)\s*\(/);
775
+ let matchKey = _fnName + "(" + getFnArgsStr(lines.slice(index, index + 9).join("\n")) + ")"
776
+ if (isMatch(matchKey, filterStr)) {
777
+ fnName = _fnName;
778
+ fnType = line.startsWith('async') ? 'AsyncFunction' : 'Function';
779
+ capturingFunction = true;
780
+ comments = [...potentialComments]; // Confirm the comments are related to the function
781
+ potentialComments = []; // Clear the potential comments as they are now confirmed
782
+ }
710
783
  }
711
784
 
712
785
  // Capture function lines
@@ -719,7 +792,9 @@ function dealStarCmd(rows, cmd, filterStr) {
719
792
  let functionContent = functionLines.join('\n');
720
793
  let commentContent = trimText(comments.join('\n'));
721
794
  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");
795
+ let pair = parseUniqueName(cmd);
796
+ row.value = infoStr(pair[0] + '/' + trimJsirFileName(pair[1])) + ' ' +
797
+ getCmdMd5Key(parseUniqueName(cmd)[1]) + '\n' + [commentContent, row.value].filter(i => trim(i)).join("\n");
723
798
  rows.push(row);
724
799
 
725
800
  resetState();
@@ -739,7 +814,13 @@ async function dealStarCase(result, matchStrs, cmd) {
739
814
  rows.push(getInfo(result))
740
815
  } else {
741
816
  for (let key of Object.keys(result)) {
742
- if (matchStrs.length === 0 || isArgsMatch(key, [matchStrs.join(' ')])){
817
+ let obj = result[key];
818
+ let type = getType(obj);
819
+ let matchKey = key;
820
+ if (type === 'Function' || type === 'AsyncFunction') {
821
+ matchKey = key + "(" + getFnArgsStr(String(obj)) + ")";
822
+ }
823
+ if (matchStrs.length === 0 || isMatch(matchKey, matchStrs.join(' '))){
743
824
  rows.push(getInfo(result[key], key))
744
825
  }
745
826
  }
@@ -886,7 +967,7 @@ const keywordDef = {
886
967
  args: {
887
968
  queryParams: 'string matching, [,] represents all, keywords can be omitted'
888
969
  },
889
- short: 'l'
970
+ short: 'L'
890
971
  },
891
972
  clear: {
892
973
  comment: 'Clear task',
@@ -994,18 +1075,34 @@ const keywordDef = {
994
1075
  setting: {
995
1076
  comment: 'Global settings',
996
1077
  exeFn: async (args) => {
997
- ei(getEditor(), [`${getLibDataDir()}/config.json`])
1078
+ let uniqueName = _cmdMap[args[0]];
1079
+ if (uniqueName) {
1080
+ let configDir = `${getLibDataDir()}/config`;
1081
+ mkdir(configDir)
1082
+ ei(getEditor(), [`${configDir}/${md5(uniqueName)}.json`])
1083
+ } else {
1084
+ ei(getEditor(), [`${getLibDataDir()}/config.json`])
1085
+ }
998
1086
  },
999
1087
  short: 's'
1000
1088
  },
1001
1089
  open: {
1002
1090
  comment: 'open file',
1003
1091
  exeFn: async (args) => {
1004
- let uniqueName = _cmdMap[args[0]]
1092
+ let uniqueName = _cmdMap[args[0]] || args.join(" ");
1005
1093
  if (!uniqueName) {
1006
1094
  console.warn("no items")
1007
1095
  } else {
1008
1096
  let path = getFullPath(uniqueName)
1097
+ if (!fs.existsSync(path)) {
1098
+ let cmds = filterCmd(uniqueName);
1099
+ if (cmds.length === 1) {
1100
+ path = getFullPath(cmds[0])
1101
+ } else {
1102
+ console.warn("no items")
1103
+ return;
1104
+ }
1105
+ }
1009
1106
  await e(`"${getFileOpenExe(parseUniqueName(uniqueName)[1])}" "${path}"`)
1010
1107
  }
1011
1108
  },
@@ -1123,8 +1220,10 @@ const keywordDef = {
1123
1220
  comment: 'Workspace Management',
1124
1221
  exeFn: async (args) => {
1125
1222
  let newWorkspace = args.join(' ')
1223
+ let isSwitch = false
1126
1224
  if (newWorkspace) {
1127
1225
  if ($workspaceMap[newWorkspace]) {
1226
+ isSwitch = true;
1128
1227
  initWorkspace(newWorkspace)
1129
1228
  } else if (newWorkspace.startsWith('-')) {
1130
1229
  let name = newWorkspace.replace(/^-\s*/, '');
@@ -1145,7 +1244,9 @@ const keywordDef = {
1145
1244
  path
1146
1245
  }
1147
1246
  })
1148
- console.table(items)
1247
+ if (!isSwitch) {
1248
+ console.table(items)
1249
+ }
1149
1250
  },
1150
1251
  args: {
1151
1252
  workspacePath: 'New workspace path'
@@ -1241,6 +1342,35 @@ const keywordDef = {
1241
1342
  ei(`cd "${$workspaceMap[global.$defaultSpace]}";npm ${args.join(' ')}`, [], true)
1242
1343
  },
1243
1344
  short: 'N'
1345
+ },
1346
+ log: {
1347
+ comment: 'View log (type[[lt][le]], index)',
1348
+ exeFn: (args) => {
1349
+ let path = `${getLibDataDir()}/log/jsir`
1350
+ let type = '';
1351
+ for (let arg of args) {
1352
+ if (_cmdMap[arg]) {
1353
+ path = `${getLibDataDir()}/log/${md5(_cmdMap[trim(arg)])}`
1354
+ } else {
1355
+ type = arg;
1356
+ }
1357
+ }
1358
+ let suffix = 'log'
1359
+ let cmdStr = 'less -R'
1360
+ if (type.indexOf("e") !== -1) {
1361
+ suffix = 'error'
1362
+ }
1363
+ if (type.indexOf("t") !== -1) {
1364
+ cmdStr = 'tail -n 50 -f'
1365
+ }
1366
+ path = path + '.' + suffix;
1367
+ if (!fs.existsSync(path)) {
1368
+ console.warn('log file not found')
1369
+ return;
1370
+ }
1371
+ ei(cmdStr, [path], true)
1372
+ },
1373
+ short: 'l'
1244
1374
  }
1245
1375
  }
1246
1376
 
@@ -1267,11 +1397,11 @@ function preLoad(text, fnNameMatch, fn, packages = []) {
1267
1397
  let result = fn(packageName)
1268
1398
  if (getType(result) === 'Promise') {
1269
1399
  result.catch(e => {
1270
- $log(e)
1400
+ console.$error(e)
1271
1401
  })
1272
1402
  }
1273
1403
  } catch (e) {
1274
- $log(e)
1404
+ console.$error(e)
1275
1405
  }
1276
1406
  }
1277
1407
  });
@@ -1420,57 +1550,6 @@ function getComments(i, cmdName, text, cols = [], col) {
1420
1550
  }
1421
1551
  }
1422
1552
 
1423
- function getFullPath(name) {
1424
- name = trim(name)
1425
- if (!name) {
1426
- return name;
1427
- }
1428
- let uniqueName = toUniqueName(name)
1429
- let pair = parseUniqueName(uniqueName)
1430
- let space = $workspaceMap[pair[0]]
1431
- if (!space) {
1432
- return ''
1433
- }
1434
- return `${space}/${pair[1]}`
1435
- }
1436
-
1437
- function toUniqueName(name, space) {
1438
- name = trim(name)
1439
- if (!name) {
1440
- throw `invalid name '${name}'`
1441
- }
1442
- let uniqueName
1443
- if (name.startsWith('/')) {
1444
- let items = name.split('/').map(trim).filter(i => i).reverse()
1445
- uniqueName = items[1] + '/' + items[0]
1446
- } else if (name.indexOf('/') !== -1) {
1447
- uniqueName = name;
1448
- } else {
1449
- uniqueName = (space || $defaultSpace) + '/' + name;
1450
- }
1451
- let pair = parseUniqueName(uniqueName);
1452
- return (pair[0] || space || $defaultSpace) + '/' + toJsirFileName(pair[1])
1453
- }
1454
-
1455
- function toJsirFileName(name) {
1456
- name = trim(name)
1457
- if (!name) {
1458
- throw `invalid name '${name}'`
1459
- }
1460
- if (isJsirFileName(name)) {
1461
- return name;
1462
- }
1463
- name = name + '.js'
1464
- if (!isJsirFileName(name)) {
1465
- throw `invalid name '${name}'`
1466
- }
1467
- return name
1468
- }
1469
-
1470
- function isJsirFileName(name) {
1471
- return /^[^./]*[^./\s]\.[^./\s]+$/.test(name)
1472
- }
1473
-
1474
1553
  function trimJsirFileName(name) {
1475
1554
  name = trim(name)
1476
1555
  if (isJsirFileName(name)) {
@@ -1540,7 +1619,7 @@ function _filterCmd(dirPath, arg) {
1540
1619
  for (let file of files) {
1541
1620
  file = trim(file)
1542
1621
  let uniqueName = toUniqueName(dirPath + '/' + file)
1543
- isArgsMatch(file, [arg], () => {
1622
+ isMatch(file, arg, () => {
1544
1623
  cmdMap[uniqueName] = null;
1545
1624
  }, true)
1546
1625
  }
@@ -1551,12 +1630,6 @@ function getSpaceFromDir(dirPath) {
1551
1630
  return trim(trim(dirPath).split('/').map(trim).filter(i => i).reverse()[0])
1552
1631
  }
1553
1632
 
1554
- function parseUniqueName(uniqueName) {
1555
- let pair = uniqueName.split('/').map(trim).filter(i => i)
1556
- let len = pair.length;
1557
- return [pair[len - 2], pair[len - 1]]
1558
- }
1559
-
1560
1633
  function getArgComments(argDef, showShort = false) {
1561
1634
  let comments = []
1562
1635
  let keys = Object.keys(argDef)
@@ -1569,13 +1642,13 @@ function getArgComments(argDef, showShort = false) {
1569
1642
  }
1570
1643
  if (keys.length > 0) {
1571
1644
  for (let k of keys) {
1572
- let item = warnStr(k) + (shortMap[k] ? ` ${warnStr(shortMap[k])}`:'') + (argDef[k] ? ` <${argDef[k]}>`:'')
1645
+ let item = warnStr(k) + (shortMap[k] ? ` ${warnStr(shortMap[k])}`:'') + (argDef[k] ? ` ${argDef[k]}`:'')
1573
1646
  comments.push(item)
1574
1647
  }
1575
- comments[0] = '$args: ' + comments[0]
1648
+ comments[0] = comments[0]
1576
1649
  if (comments.length > 1) {
1577
1650
  for(let i = 1; i< comments.length; i++) {
1578
- comments[i] = ' ' + comments[i]
1651
+ comments[i] = comments[i]
1579
1652
  }
1580
1653
  }
1581
1654
  }
@@ -1652,7 +1725,6 @@ async function runCmd(str = '', uniqueName = '', text = '') {
1652
1725
  }
1653
1726
 
1654
1727
  let scriptArgs = await getScriptArgs(argDef, enrichArgs(str.replace(/^\d+\s*/, '')));
1655
- process.argv = [process.argv[0], path, ...(scriptArgs.map(String))]
1656
1728
  return await evalText(text, uniqueName, scriptArgs)
1657
1729
  }
1658
1730
 
@@ -1661,7 +1733,6 @@ async function runScript(uniqueName, oriArgs) {
1661
1733
  let text = String(fs.readFileSync(path))
1662
1734
  let argDef = getArgDef(text)
1663
1735
  let scriptArgs = await getScriptArgs(argDef, oriArgs);
1664
- process.argv = [process.argv[0], path, ...(scriptArgs.map(String))]
1665
1736
  return await evalText(text, uniqueName, scriptArgs)
1666
1737
  }
1667
1738
 
@@ -1670,7 +1741,7 @@ async function getScriptArgs(argDef, oriArgs) {
1670
1741
  oriArgs = oriArgs.map(i => shortDefMap[i] ? shortDefMap[i]:i)
1671
1742
  let argNames = Object.keys(argDef)
1672
1743
  let exactArgs = {}
1673
- let scriptArgs = []
1744
+ let scriptArgs = {}
1674
1745
  for (let i = 0; i<oriArgs.length; i++) {
1675
1746
  let arg = oriArgs[i]
1676
1747
  let needTrans
@@ -1680,7 +1751,8 @@ async function getScriptArgs(argDef, oriArgs) {
1680
1751
  }
1681
1752
  if (arg.startsWith(":") || arg.startsWith("_") && !arg.endsWith(' ')) {
1682
1753
  arg = arg.replace(/^:/, '')
1683
- if (oriArgs[i+1] && (oriArgs[i+1].endsWith(' ') || !(oriArgs[i+1].startsWith(":") || oriArgs[i+1].startsWith("_") || oriArgs[i+1].startsWith("-")))) {
1754
+ if (oriArgs[i+1] &&
1755
+ (oriArgs[i+1].endsWith(' ') || !(oriArgs[i+1].startsWith(":") || oriArgs[i+1].startsWith("_") || oriArgs[i+1].startsWith("-")))) {
1684
1756
  pair = [arg, oriArgs[i+1]]
1685
1757
  i++
1686
1758
  } else {
@@ -1701,9 +1773,7 @@ async function getScriptArgs(argDef, oriArgs) {
1701
1773
  }
1702
1774
  pair[1] = needTrans ? await evalText( 'return ' + pair[1]):pair[1]
1703
1775
 
1704
- let curIdx = scriptArgs.length
1705
- scriptArgs[curIdx] = pair[1]
1706
-
1776
+ let curIdx = Object.keys(scriptArgs).length
1707
1777
  if (argNames[curIdx]) {
1708
1778
  scriptArgs[argNames[curIdx]] = pair[1]
1709
1779
  }
@@ -1730,7 +1800,7 @@ async function getScriptArgs(argDef, oriArgs) {
1730
1800
  }
1731
1801
  if (scriptArgKeys.indexOf(name) === -1 || (reg && !reg.test(scriptArgs[name]))) {
1732
1802
  argAbsent = true
1733
- console.warn(`require ${warnStr(name)}` + (defStr ? ` <${defStr}>`:''))
1803
+ console.warn(`require ${warnStr(name)}` + (defStr ? ` ${defStr}`:''))
1734
1804
  }
1735
1805
  }
1736
1806
  if (argAbsent) {
@@ -1776,19 +1846,41 @@ function parseArgDef(inputString) {
1776
1846
  if (!preStr) {
1777
1847
  return result;
1778
1848
  }
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]);
1849
+ let ss = preStr.split(/\n|(?<!\/)\/(?=\/)/g).map(trim).filter(i => i);
1850
+ let items = []
1851
+ for (let s of ss) {
1852
+ if (s.startsWith("/")) {
1853
+ items.push(s);
1854
+ } else {
1855
+ items.push(...s.split(/,/))
1856
+ }
1857
+ }
1858
+ items = items.map(trim).filter(i => i);
1859
+ for (let i = 0; i < items.length; i++) {
1860
+ let s1 = trim(items[i]);
1782
1861
  if (s1.startsWith("/")) {
1783
1862
  continue;
1784
1863
  }
1785
- if (ss[i+1] && ss[i+1].startsWith("/")) {
1786
- result[s1] = trim(ss[i+1].replace(/^\//, ""));
1864
+ if (items[i+1] && items[i+1].startsWith("/")) {
1865
+ result[s1] = trim(items[i+1].replace(/^\//, ""));
1787
1866
  i++;
1788
1867
  } else {
1789
1868
  result[s1] = '';
1790
1869
  }
1791
1870
  }
1871
+ for (let key of Object.keys(result)) {
1872
+ let comment = result[key];
1873
+ let defaultValStr = ''
1874
+ if (key.indexOf("=") !== -1) {
1875
+ delete result[key];
1876
+ let ss = key.split('=').map(trim);
1877
+ key = ss[0]
1878
+ defaultValStr = ss[1]
1879
+ }
1880
+ if (defaultValStr) {
1881
+ result[key] = ['<' + warnStr(defaultValStr) + '>', comment].join(' ')
1882
+ }
1883
+ }
1792
1884
  return result;
1793
1885
  }
1794
1886
 
@@ -1803,14 +1895,12 @@ function getArgDef(text, uniqueName) {
1803
1895
  let argDef = {}
1804
1896
  try {
1805
1897
  argDef = (exeStr ? evalVal(exeStr) : parseArgDef(text)) || {}
1806
- let array = []
1807
1898
  for (let key of Object.keys(argDef)) {
1808
- if (/\s/.test(key) || array.hasOwnProperty(key)) {
1899
+ if (/\s/.test(key)) {
1809
1900
  throw `invalid argName ${warnStr(key)}`
1810
1901
  }
1811
1902
  }
1812
1903
  } catch (e) {
1813
- $log(errorStack(e))
1814
1904
  argDef = {'[ParseError]': String(e)}
1815
1905
  }
1816
1906
  if (typeof argDef !== 'object') {
@@ -1831,45 +1921,6 @@ function getArgDef(text, uniqueName) {
1831
1921
  return Object.assign(temp, tempOpt)
1832
1922
  }
1833
1923
 
1834
- function setTips(key, value, onRm) {
1835
- getOr(global.$tips, key, []).push(value);
1836
- if (onRm) {
1837
- getOr(_tipsOnRm, key, []).push(onRm)
1838
- }
1839
- }
1840
-
1841
- function delTips(...keys) {
1842
- for (let key of Object.keys($tips)) {
1843
- if (keys.length === 0) {
1844
- delete $tips[key]
1845
- tipsOnRmCallback(key)
1846
- } else if (keys.indexOf(key) !== -1) {
1847
- delete $tips[key]
1848
- tipsOnRmCallback(key)
1849
- }
1850
- }
1851
- if (keys.length === 0) {
1852
- for (let key of Object.keys(_tipsOnRm)) {
1853
- tipsOnRmCallback(key)
1854
- }
1855
- }
1856
- }
1857
-
1858
- function tipsOnRmCallback(key) {
1859
- let callbacks = _tipsOnRm[key]
1860
- delete _tipsOnRm[key]
1861
- if (callbacks && callbacks.length > 0) {
1862
- for (let callback of callbacks) {
1863
- try {
1864
- callback()
1865
- } catch (e) {
1866
- $log(errorStack(e))
1867
- console.error(`[${key}] OnRmCallback: ${String(e)}`)
1868
- }
1869
- }
1870
- }
1871
- }
1872
-
1873
1924
  function getCmdMd5Key(str) {
1874
1925
  return '0x' + md5(str).substr(0, 8);
1875
1926
  }
@@ -1888,8 +1939,8 @@ function filterRequire(currSpace, cmdMatchStr) {
1888
1939
  let uName = toUniqueName(cmdMatchStr, currSpace)
1889
1940
  let pr = parseUniqueName(uName)
1890
1941
  let fullPath;
1891
- if (!/^[eif]\s+/.test(pr[1])) {
1892
- uName = pr[0] + "/i " + pr[1]
1942
+ if (!/^[ef]\s+/.test(pr[1])) {
1943
+ uName = pr[0] + "/i " + pr[1].replace(/^f\s+/, '')
1893
1944
  fullPath = getFullPath(uName)
1894
1945
  }
1895
1946
  if (fullPath && fs.existsSync(fullPath)) {
@@ -1913,7 +1964,7 @@ async function _requireSource(currSpace, cmdMatchStr) {
1913
1964
  let result
1914
1965
  let uniqueName = filterRequire(currSpace, cmdMatchStr);
1915
1966
  let path = getFullPath(uniqueName)
1916
- let text = String(fs.readFileSync(path))
1967
+ let text = String(await fp.readFile(path))
1917
1968
  let pair = parseUniqueName(uniqueName)
1918
1969
  if (pair[1].startsWith('i ')) {
1919
1970
  result = await evalText(text, uniqueName)
@@ -1973,15 +2024,32 @@ async function evalText($text = '', $cmdName = '', $args = []) {
1973
2024
  return await _requireSource(currSpace, matchItem)
1974
2025
  }
1975
2026
  return await evalCode(addErrorTag($text), $cmdName, $args,
1976
- $data, $config,
2027
+ $data, $file,
1977
2028
  $require, $requires,
1978
2029
  nextLine, nextText,
1979
- setTips, delTips,
1980
2030
  wrapperInput, filterCmd,
1981
2031
  currSpace,
1982
2032
  $homeDir, $lib, _cmdMap);
1983
2033
  }
1984
2034
 
2035
+ function clearFileLock() {
2036
+ let fileLockMap = getOr(global, `$fileLock`, {})
2037
+ for (let file of Object.keys(fileLockMap)) {
2038
+ fp.rmdir(file)
2039
+ delete fileLockMap[file]
2040
+ }
2041
+ }
2042
+
2043
+ function sigExit() {
2044
+ if (_noAppendNextLine) {
2045
+ delTips();
2046
+ clearFileLock();
2047
+ process.exit(0);
2048
+ } else {
2049
+ nextLine();
2050
+ }
2051
+ }
2052
+
1985
2053
  process.on('uncaughtException',function(err){
1986
2054
  console.error('uncaughtException', err)
1987
2055
  _noAppendNextLine || nextLine()
@@ -1994,14 +2062,8 @@ process.on('rejectionHandled',function(err){
1994
2062
  console.error('rejectionHandled', err)
1995
2063
  _noAppendNextLine || nextLine()
1996
2064
  })
1997
- process.on('SIGINT', function () {
1998
- if (_noAppendNextLine) {
1999
- delTips();
2000
- process.exit(0);
2001
- } else {
2002
- nextLine();
2003
- }
2004
- });
2065
+ process.on('SIGINT', sigExit);
2066
+ process.on('SIGTERM', sigExit);
2005
2067
  process.on('beforeExit', function () {
2006
2068
  if (_noAppendNextLine) {
2007
2069
  delTips();