jsir 2.2.9 → 2.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/cmd/oaa.js CHANGED
@@ -4,14 +4,14 @@ const {
4
4
  getLibDataDir, trim, regEach, getConfig, mkdir, reget,
5
5
  getCbText, e, sleep, objDataFile, vl, md5, BigNumber,
6
6
  arrayDataFile, infoStr, warnStr,
7
- getInfo, ei, pad, msgStr, getType,
7
+ getInfo, pad, msgStr, getType,
8
8
  isMatch, draftQuery, setConfig,
9
9
  getTextComments, importG, requireG,
10
10
  clearConsole, trimText, getFnArgsStr,
11
11
  createConsole, setTips, delTips,
12
12
  getEditor, errorStr, getConfigDir,
13
13
  getFullPath, parseUniqueName, toUniqueName, isJsirFileName, toJsirFileName,
14
- getOr, getAlias, wrapperJsirText
14
+ getOr, getAlias, wrapperJsirText, eia
15
15
  } = $lib;
16
16
  const _args = process.argv.slice(2).map(trim);
17
17
  const evalCode = require('../deps/evalCode')
@@ -26,11 +26,7 @@ const example = require("../deps/example");
26
26
  const _workspaceConfigFile = 'workspace.json';
27
27
  const _libDataDir = getLibDataDir()
28
28
  const _fileWatcherMap = {}
29
- const _types = {
30
- 'e': "exe",
31
- 'i': "init",
32
- 'f': "file"
33
- }
29
+ const _types = setting.fileType
34
30
  const console = createConsole();
35
31
 
36
32
  let lastFilterArg = '';
@@ -41,6 +37,7 @@ let _rlHistory = []
41
37
  let _haveWrapperInput = true
42
38
  let _noAppendNextLine = true
43
39
  let _onLazyTempCode = null
40
+ let _isTipsDoneShowKey = false
44
41
 
45
42
  const _onLazyGetMap = Object.create(null)
46
43
  const _data = Object.create(null)
@@ -291,7 +288,9 @@ async function nextLine(callback, promptStr, hidden) {
291
288
  }
292
289
 
293
290
  function defaultPromptStr(showKey = false) {
294
- return [getTipStr(showKey), $defaultSpace].filter(i => i).join(':') + `> `;
291
+ let tips = [getTipStr(showKey), $defaultSpace].filter(i => i).join(':') + `> `;
292
+ _isTipsDoneShowKey = showKey;
293
+ return tips;
295
294
  }
296
295
 
297
296
  function initRl(callback, promptStr, hidden) {
@@ -367,7 +366,11 @@ function getTipStr(showKey = false) {
367
366
  items.push(item)
368
367
  }
369
368
  }
370
- return items.join(',');
369
+ let tips = items.join(',')
370
+ if (!showKey && !_isTipsDoneShowKey && tips.length > 64) {
371
+ return '...'
372
+ }
373
+ return tips;
371
374
  }
372
375
 
373
376
  function closeRl() {
@@ -450,9 +453,9 @@ async function save(args) {
450
453
  return
451
454
  }
452
455
  let resp;
453
- if (args[0] === 'e') {
456
+ if (args[0].startsWith(setting.exeKey)) {
454
457
  resp = example.exeFile;
455
- } else if (args[0] === 'i') {
458
+ } else if (args[0].startsWith(setting.initKey)) {
456
459
  resp = example.initFile;
457
460
  } else {
458
461
  resp = await getCbText();
@@ -534,7 +537,7 @@ function listCmd(tmpMap) {
534
537
  let item = {
535
538
  key: ' ' + i,
536
539
  name: pair[0] + '/' + name,
537
- type: [_types[name.split(/\s+/)[0]] || 'note', suffix].map(trim).join(".")
540
+ type: [_types[name.substring(0, 1)] || setting.defaultType, suffix].map(trim).join(".")
538
541
  }
539
542
  items.push(item)
540
543
 
@@ -552,9 +555,9 @@ function listCmd(tmpMap) {
552
555
  }
553
556
  if (item.type) {
554
557
  let pair = parseUniqueName(item.name);
555
- if (item.type.startsWith('exe.')) {
558
+ if (item.type.startsWith(_types[setting.exeKey] + '.')) {
556
559
  item.name = infoStr(pair[1])
557
- } else if (item.type.startsWith('init.')) {
560
+ } else if (item.type.startsWith(_types[setting.initKey] + '.')) {
558
561
  item.name = msgStr(pair[1])
559
562
  } else {
560
563
  item.name = pair[1]
@@ -574,6 +577,21 @@ async function wrapperInput(str) {
574
577
  }
575
578
  }
576
579
 
580
+ function wrapperAlias(str) {
581
+ let aliasMap = {};
582
+ try {
583
+ aliasMap = getConfig("alias");
584
+ } catch (e) {
585
+ console.$error("getAlias failed ", e);
586
+ }
587
+ if (Object.keys(aliasMap).length <= 0) {
588
+ return str;
589
+ }
590
+ let fstr = str.split(/\s+/)[0];
591
+ fstr = getAlias(aliasMap, fstr);
592
+ return [fstr, str.substring(fstr.length)].map(trim).filter(i => i).join(' ')
593
+ }
594
+
577
595
  async function _wrapperInput(str) {
578
596
  _haveWrapperInput = true;
579
597
  global.$newInput = true;
@@ -582,6 +600,8 @@ async function _wrapperInput(str) {
582
600
  if (!str) {
583
601
  return;
584
602
  }
603
+ str = wrapperAlias(str);
604
+
585
605
  if (/^[`'"]/.test(str)) {
586
606
  let fstr = str.substr(0, 1);
587
607
  if (fstr === '`') {
@@ -616,10 +636,10 @@ async function _wrapperInput(str) {
616
636
  let path = getFullPath(_cmdMap[strs[0]])
617
637
  let uniqueName = trim(_cmdMap[strs[0]]);
618
638
  let fileName = parseUniqueName(uniqueName)[1]
619
- let firstName = fileName.split(/\s+/)[0]
620
- if (firstName === 'f') {
639
+ let firstName = fileName.substring(0, 1)
640
+ if (firstName === setting.fileKey) {
621
641
  await workFile(uniqueName)
622
- } else if (firstName !== 'e') {
642
+ } else if (firstName !== setting.exeKey) {
623
643
  console.log(String(fs.readFileSync(path)));
624
644
  } else {
625
645
  await runCmd(str)
@@ -1073,7 +1093,7 @@ const keywordDef = {
1073
1093
  console.warn("no items")
1074
1094
  } else {
1075
1095
  let path = getFullPath(uniqueName)
1076
- ei(getEditor(), [path])
1096
+ await eia(getEditor(), [path])
1077
1097
  }
1078
1098
  },
1079
1099
  args: {
@@ -1088,9 +1108,9 @@ const keywordDef = {
1088
1108
  if (uniqueName) {
1089
1109
  let configDir = `${getLibDataDir()}/config`;
1090
1110
  mkdir(configDir)
1091
- ei(getEditor(), [`${configDir}/${md5(uniqueName)}.json`])
1111
+ await eia(getEditor(), [`${configDir}/${md5(uniqueName)}.json`])
1092
1112
  } else {
1093
- ei(getEditor(), [`${getLibDataDir()}/config.json`])
1113
+ await eia(getEditor(), [`${getLibDataDir()}/config.json`])
1094
1114
  }
1095
1115
  },
1096
1116
  short: 's'
@@ -1283,7 +1303,7 @@ const keywordDef = {
1283
1303
  let keyword = args[0]
1284
1304
  let justList = false;
1285
1305
  if (keyword.endsWith('.')) {
1286
- let _tmp = getAlias(keyword.substring(0, keyword.length - 1));
1306
+ let _tmp = trim(keyword.substring(0, keyword.length - 1));
1287
1307
  if (_tmp) {
1288
1308
  if (keywordDef[_tmp] || Object.values(keywordDef).map(item => item.short).indexOf(_tmp) !== -1) {
1289
1309
  help(i => i === _tmp || keywordDef[i].short === _tmp);
@@ -1295,8 +1315,6 @@ const keywordDef = {
1295
1315
  console.warn('invalid keyword')
1296
1316
  return
1297
1317
  }
1298
- } else {
1299
- keyword = getAlias(keyword)
1300
1318
  }
1301
1319
  let pair = parseUniqueName(keyword)
1302
1320
  let cmds;
@@ -1343,7 +1361,7 @@ const keywordDef = {
1343
1361
  },
1344
1362
  exe: {
1345
1363
  comment: 'System execute',
1346
- exeFn: (args) => {
1364
+ exeFn: async (args) => {
1347
1365
  let cmd = ''
1348
1366
  let _args = []
1349
1367
  if (args.length > 0) {
@@ -1352,13 +1370,13 @@ const keywordDef = {
1352
1370
  if (args.length > 1) {
1353
1371
  _args = args.slice(1)
1354
1372
  }
1355
- ei(`cd "${$workspaceMap[global.$defaultSpace]}";${cmd}`, _args, true)
1373
+ await eia(`cd "${$workspaceMap[global.$defaultSpace]}";${cmd}`, _args, true)
1356
1374
  },
1357
1375
  short: 'E'
1358
1376
  },
1359
1377
  log: {
1360
1378
  comment: 'View log (type[[lt][le]], index)',
1361
- exeFn: (args) => {
1379
+ exeFn: async (args) => {
1362
1380
  let path = `${getLibDataDir()}/log/jsir`
1363
1381
  let type = '';
1364
1382
  for (let arg of args) {
@@ -1383,7 +1401,7 @@ const keywordDef = {
1383
1401
  console.warn('log file not found')
1384
1402
  return;
1385
1403
  }
1386
- ei(cmdStr, [`"${path}"`], true)
1404
+ await eia(cmdStr, [`"${path}"`], true)
1387
1405
  },
1388
1406
  short: 'l'
1389
1407
  },
@@ -1408,7 +1426,7 @@ function getQuickRunCmds(input, matchStr) {
1408
1426
  } else if (input.startsWith("/")) {
1409
1427
  matchStr = '/' + matchStr;
1410
1428
  }
1411
- return filterCmd(matchStr).filter(i => parseUniqueName(i)[1].startsWith("e "))
1429
+ return filterCmd(matchStr).filter(i => parseUniqueName(i)[1].startsWith(setting.exeKey))
1412
1430
  }
1413
1431
 
1414
1432
  async function preLoad(text, fnNameMatch, fn, packages = [], space) {
@@ -1432,7 +1450,7 @@ async function preLoad(text, fnNameMatch, fn, packages = [], space) {
1432
1450
  };
1433
1451
  await fn(packageName, space)
1434
1452
  } catch (e) {
1435
- console.$error(e)
1453
+ console.$error('preLoad failed', e)
1436
1454
  }
1437
1455
  }
1438
1456
  return packages;
@@ -1471,14 +1489,17 @@ async function _dealKeyword(keyword, args) {
1471
1489
  if (item.short === shortKey) {
1472
1490
  unMatched = false;
1473
1491
  if (item === keywordDef.run) {
1492
+ console.$log('execute', key)
1474
1493
  await item.exeFn(args);
1475
1494
  } else {
1495
+ console.$log('execute', key)
1476
1496
  await item.exeFn(args.map(trim));
1477
1497
  }
1478
1498
  break;
1479
1499
  }
1480
1500
  }
1481
1501
  if (unMatched) {
1502
+ console.$log('execute run', keyword)
1482
1503
  await keywordDef.run.exeFn([keyword, ...args])
1483
1504
  }
1484
1505
  }
@@ -1918,7 +1939,7 @@ function parseArgDef(inputString) {
1918
1939
  }
1919
1940
 
1920
1941
  function getArgDef(text, uniqueName) {
1921
- if (uniqueName && !parseUniqueName(uniqueName)[1].startsWith("e ")) {
1942
+ if (uniqueName && !parseUniqueName(uniqueName)[1].startsWith(setting.exeKey)) {
1922
1943
  return {}
1923
1944
  }
1924
1945
  if (text.indexOf("$defArgs") === -1) {
@@ -1970,12 +1991,7 @@ function filterRequire(currSpace, cmdMatchStr) {
1970
1991
 
1971
1992
  let cmds;
1972
1993
  let uName = toUniqueName(cmdMatchStr, currSpace)
1973
- let pr = parseUniqueName(uName)
1974
- let fullPath;
1975
- if (!/^[ef]\s+/.test(pr[1])) {
1976
- uName = pr[0] + "/i " + pr[1].replace(/^f\s+/, '')
1977
- fullPath = getFullPath(uName)
1978
- }
1994
+ let fullPath = getFullPath(uName)
1979
1995
  if (fullPath && fs.existsSync(fullPath)) {
1980
1996
  cmds = [uName]
1981
1997
  } else {
@@ -1984,6 +2000,9 @@ function filterRequire(currSpace, cmdMatchStr) {
1984
2000
  if (cmds.length > 0) {
1985
2001
  cmds = cmds.filter(cmd => parseUniqueName(cmd)[0] === (appointSpace || currSpace))
1986
2002
  }
2003
+ if (cmds.length > 0) {
2004
+ cmds = cmds.filter(cmd => parseUniqueName(cmd)[1].startsWith(setting.initKey))
2005
+ }
1987
2006
  }
1988
2007
  if (cmds.length > 1) {
1989
2008
  throw `multiple match: ${cmdMatchStr}`
@@ -1999,9 +2018,9 @@ async function _requireSource(currSpace, cmdMatchStr) {
1999
2018
  let path = getFullPath(uniqueName)
2000
2019
  let text = String(await fp.readFile(path))
2001
2020
  let pair = parseUniqueName(uniqueName)
2002
- if (pair[1].startsWith('i ')) {
2021
+ if (pair[1].startsWith(setting.initKey)) {
2003
2022
  result = await evalText(text, uniqueName)
2004
- } else if (pair[1].startsWith('e ')) {
2023
+ } else if (pair[1].startsWith(setting.exeKey)) {
2005
2024
  result = async (argsStr) => {
2006
2025
  return await runCmd(trim(argsStr), uniqueName, text)
2007
2026
  }
@@ -2084,15 +2103,15 @@ function sigExit() {
2084
2103
  }
2085
2104
 
2086
2105
  process.on('uncaughtException',function(err){
2087
- console.error('uncaughtException', err)
2106
+ console.$error('uncaughtException', err)
2088
2107
  _noAppendNextLine || nextLine()
2089
2108
  })
2090
2109
  process.on('unhandledRejection',function(err){
2091
- console.error('unhandledRejection', err)
2110
+ console.$error('unhandledRejection', err)
2092
2111
  _noAppendNextLine || nextLine()
2093
2112
  })
2094
2113
  process.on('rejectionHandled',function(err){
2095
- console.error('rejectionHandled', err)
2114
+ console.$error('rejectionHandled', err)
2096
2115
  _noAppendNextLine || nextLine()
2097
2116
  })
2098
2117
  process.on('SIGINT', sigExit);
package/deps/setting.js CHANGED
@@ -1,4 +1,21 @@
1
+
2
+ const exeKey = 'e';
3
+ const initKey = 'i';
4
+ const fileKey = 'f';
5
+
6
+ const fileType = {};
7
+ fileType[exeKey] = "exe";
8
+ fileType[initKey] = "init";
9
+ fileType[fileKey] = "file";
10
+
11
+ const defaultType = 'note';
12
+
1
13
  module.exports = {
2
14
  name: 'jsir',
3
- libDataDir: '.jsirData'
4
- }
15
+ libDataDir: '.jsirData',
16
+ fileType,
17
+ exeKey,
18
+ initKey,
19
+ fileKey,
20
+ defaultType
21
+ }
package/deps/util.js CHANGED
@@ -1,7 +1,7 @@
1
1
  const setting = require('./setting')
2
2
  const os = require('os')
3
3
  const home = os.homedir()
4
- const {exec, spawnSync} = require('child_process');
4
+ const {exec, spawnSync, spawn} = require('child_process');
5
5
  const readline = require('readline')
6
6
  const fs = require('fs')
7
7
  const fp = require('fs').promises
@@ -12,6 +12,8 @@ const dayJs = require('dayjs')
12
12
  const table = require('console.table')
13
13
  const initModulePaths = Object.assign([], module.paths)
14
14
  const path = require('path')
15
+ const _types = setting.fileType
16
+ const _typeKeys = Object.keys(_types)
15
17
 
16
18
  global.$newInput = false
17
19
  global.$workspaceMap = {}
@@ -23,6 +25,7 @@ global.$packages = {}
23
25
  let libDataDir;
24
26
  let lockDir;
25
27
  let logDir;
28
+ let tempDir;
26
29
  let configDir;
27
30
 
28
31
  class SyncQueue {
@@ -68,7 +71,8 @@ const $log = createLimitLogger(`${setting.name}.log`, {
68
71
  });
69
72
  const $error = createLimitLogger(`${setting.name}.error`, {
70
73
  logInfo: false,
71
- error: true
74
+ error: true,
75
+ syncLogs: [$log]
72
76
  });
73
77
  let _globalDraft= createLimitLogger(`draft.log`, {
74
78
  logInfo: false,
@@ -206,7 +210,8 @@ function createConsole(uniqueName) {
206
210
  });
207
211
  result.$error = createLimitLogger(fileName + '.error', {
208
212
  logInfo: false,
209
- error: true
213
+ error: true,
214
+ syncLogs: [result.$log]
210
215
  });
211
216
  }
212
217
  let quite = false
@@ -227,7 +232,6 @@ function createConsole(uniqueName) {
227
232
  }
228
233
  let _args = _consoleFns[key].args(args);
229
234
  if ("error" === key) {
230
- result.$log(..._args)
231
235
  result.$error(..._args)
232
236
  } else {
233
237
  result.$log(..._args)
@@ -300,7 +304,10 @@ function toJsirFileName(name) {
300
304
  }
301
305
 
302
306
  function isJsirFileName(name) {
303
- return /^[^./]*[^./\s]\.[^./\s]+$/.test(name) && name.indexOf(".") > 1
307
+ if (name.indexOf(".") === 1) {
308
+ return _typeKeys.indexOf(name.substring(0, 1)) === -1
309
+ }
310
+ return /^[^./]*[^./\s]\.[^./\s]+$/.test(name)
304
311
  }
305
312
 
306
313
  function isMatch(text,
@@ -496,7 +503,7 @@ function getEditor() {
496
503
  try {
497
504
  defaultEditor = getConfig("defaultEditor", "vi");
498
505
  } catch (e) {
499
- console.$error('getConfig failed', e);
506
+ console.$error('getEditor failed', e);
500
507
  }
501
508
  return defaultEditor
502
509
  }
@@ -607,6 +614,15 @@ function getLogDir() {
607
614
  return logDir;
608
615
  }
609
616
 
617
+ function getTempDir() {
618
+ if (tempDir) {
619
+ return tempDir;
620
+ }
621
+ tempDir = getLibDataDir() + "/temp"
622
+ mkdir(tempDir)
623
+ return tempDir;
624
+ }
625
+
610
626
  /**
611
627
  * 根据文件完整路径,检查并创建其父级目录
612
628
  * 示例:/a/b/c/d.txt -> 检查并创建 /a/b/c
@@ -625,7 +641,8 @@ function createLimitLogger(fileName, {
625
641
  maxChars = 49 * 1024 * 1024,
626
642
  logInfo = true,
627
643
  time = true,
628
- error = false
644
+ error = false,
645
+ syncLogs = []
629
646
  } = {}) {
630
647
  fileName = trim(fileName)
631
648
  if (!fileName) {
@@ -642,10 +659,16 @@ function createLimitLogger(fileName, {
642
659
  }
643
660
  let minNum = (Date.now()/(1000 * 60 * 10)).toFixed(0)
644
661
  return (...args) => {
645
- let text = args.join(" ")
646
- if (!text) {
662
+ if (args.length <= 0) {
647
663
  return
648
664
  }
665
+ // 处理参数
666
+ args = args.map(i => isError(i) ? errorStack(i):i);
667
+
668
+ // 处理同步函数
669
+ syncLogs.forEach(i => i(...args));
670
+
671
+ let text = args.join(" ")
649
672
  if (error) {
650
673
  global.$newError = true;
651
674
  }
@@ -679,7 +702,7 @@ function getInitName(fileName) {
679
702
  fileName = trim(fileName)
680
703
  let homeDir = global.$workspaceMap[$defaultSpace]
681
704
  if (!fileName.startsWith("/")) {
682
- fileName = 'i ' + fileName.replace(/i\s+/, '')
705
+ fileName = setting.initKey + ' ' + fileName.replace(new RegExp(`^${setting.initKey}\\s+`), '')
683
706
  if (!/\..+/.test(fileName)) {
684
707
  fileName = fileName + '.js'
685
708
  }
@@ -687,6 +710,7 @@ function getInitName(fileName) {
687
710
  }
688
711
  return fileName;
689
712
  }
713
+
690
714
  function dataFile(fileName, fn, fmt, defaultObj = {}, returnStr = false) {
691
715
  let dataDir = getLibDataDir() + "/data"
692
716
  fileName = trim(fileName)
@@ -746,7 +770,7 @@ async function fileJson(key, fn, fmt = true) {
746
770
  let fileName = trim(key)
747
771
  let path = dataDir + "/" + fileName;
748
772
  let homeDir = global.$workspaceMap[$defaultSpace]
749
- let isInit = fileName.startsWith("i ");
773
+ let isInit = fileName.startsWith(setting.initKey);
750
774
  if (isInit) {
751
775
  path = homeDir + '/' + toJsirFileName(fileName);
752
776
  }
@@ -846,7 +870,7 @@ function aesCipher(str, key){
846
870
  const cipher = crypto.createCipheriv('aes-128-ecb', pad(key, 16, '0'), null);
847
871
  return cipher.update(str, 'utf8', 'hex') + cipher.final('hex');
848
872
  } catch(err) {
849
- $log(errorStack(err))
873
+ $error(err)
850
874
  throw 'aesCipher failed: ' + String(err)
851
875
  }
852
876
  }
@@ -863,7 +887,7 @@ function aesDecipher(str, key){
863
887
  const decipher = crypto.createDecipheriv('aes-128-ecb', pad(key, 16, '0'), null);
864
888
  return decipher.update(str, 'hex', 'utf8') + decipher.final('utf8');
865
889
  } catch(err) {
866
- $log(errorStack(err))
890
+ $error(err)
867
891
  throw 'aesDecipher failed: ' + String(err)
868
892
  }
869
893
  }
@@ -881,12 +905,11 @@ function getConfigDir() {
881
905
  return configDir;
882
906
  }
883
907
 
884
- function getAlias(key) {
908
+ function getAlias(aliasMap, key) {
885
909
  key = trim(key)
886
910
  if (!key) {
887
911
  return key;
888
912
  }
889
- let aliasMap = getConfig('alias', {});
890
913
  if (aliasMap.hasOwnProperty(key) && vl(aliasMap[key])) {
891
914
  return aliasMap[key].trim();
892
915
  }
@@ -1090,6 +1113,9 @@ function setTips(key, value, onRm) {
1090
1113
  `
1091
1114
  可以设置相同的key, value值,会在左侧提示符体现出来
1092
1115
  `
1116
+ if (!vl(key) || key.indexOf(",") !== -1) {
1117
+ throw "invalid tip key";
1118
+ }
1093
1119
  getOr(global.$tips, key, []).push(value);
1094
1120
  if (onRm) {
1095
1121
  getOr(_tipsOnRm, key, []).push(onRm)
@@ -1121,8 +1147,7 @@ function tipsOnRmCallback(key) {
1121
1147
  try {
1122
1148
  callback()
1123
1149
  } catch (e) {
1124
- $log(errorStack(e))
1125
- console.error(`[${key}] OnRmCallback: ${String(e)}`)
1150
+ $error(`[${key}] OnRmCallback`, e)
1126
1151
  }
1127
1152
  }
1128
1153
  }
@@ -1193,7 +1218,7 @@ function cleanFile(path, maxChars = 9 * 1024 * 1024) {
1193
1218
  try {
1194
1219
  stats = await fp.stat(path);
1195
1220
  } catch (e) {
1196
- console.$error('cleanFile stat failed', errorMsg(e));
1221
+ console.$error('cleanFile stat failed', e);
1197
1222
  return;
1198
1223
  }
1199
1224
  const fileSize = stats.size;
@@ -1274,8 +1299,7 @@ function timeLoop(fn, timestamp, lastIds = []){
1274
1299
  try {
1275
1300
  val = fn()
1276
1301
  } catch (e) {
1277
- console.error(String(e))
1278
- $log(new Error(errorStack(e)).stack)
1302
+ $error(e)
1279
1303
  }
1280
1304
  if (vl(val) && getType(val) === 'Promise') {
1281
1305
  return val.then(result => {
@@ -1284,8 +1308,7 @@ function timeLoop(fn, timestamp, lastIds = []){
1284
1308
  }
1285
1309
  return lastIds
1286
1310
  }).catch(e => {
1287
- console.error(String(e))
1288
- $log(new Error(errorStack(e)).stack)
1311
+ $error(e)
1289
1312
 
1290
1313
  if (lastIds[0] !== false) {
1291
1314
  lastIds[0] = setTimeout(() => timeLoop(fn, timestamp, lastIds), timestamp)
@@ -1330,13 +1353,13 @@ function mkdir(dir) {
1330
1353
  try {
1331
1354
  fs.mkdirSync(dir)
1332
1355
  } catch (e) {
1333
- console.$error(errorStack(e))
1356
+ console.$error(e)
1334
1357
  }
1335
1358
  }
1336
1359
 
1337
1360
  function e(cmd, mbNum = 3, doTrim = true){
1338
1361
  `
1339
- return Promise(result)
1362
+ return Promise(resolve, reject)
1340
1363
  `
1341
1364
  return new Promise((resolve, reject) => {
1342
1365
  exec(`${cmd}`, {
@@ -1353,7 +1376,7 @@ function e(cmd, mbNum = 3, doTrim = true){
1353
1376
 
1354
1377
  function ee(cmd, mbNum = 3, doTrim = true){
1355
1378
  `
1356
- return Promise([stdout, stderr])
1379
+ return Promise(resolve([stdout, stderr]))
1357
1380
  `
1358
1381
  return new Promise((resolve, reject) => {
1359
1382
  exec(`${cmd}`, {
@@ -1372,6 +1395,23 @@ function ei(cmd, args = [], shell = false) {
1372
1395
  spawnSync(cmd, args, {stdio:"inherit", shell});
1373
1396
  }
1374
1397
 
1398
+ async function eia(cmd, args = [], shell = false) {
1399
+ `
1400
+ 当前进程不会卡住,输入输出由cmd进程持有
1401
+ `
1402
+ let child = spawn(cmd, args, {stdio:"inherit", shell});
1403
+ return new Promise((resolve, reject) => {
1404
+ // 监听子进程的关闭事件
1405
+ child.on('close', (code) => {
1406
+ resolve(code);
1407
+ });
1408
+ // 可选:监听子进程的错误事件
1409
+ child.on('error', (err) => {
1410
+ reject(err)
1411
+ });
1412
+ })
1413
+ }
1414
+
1375
1415
  async function getCbText(mbNum) {
1376
1416
  return await e(`pbpaste`, mbNum, false)
1377
1417
  }
@@ -1806,6 +1846,24 @@ function wrapperJsirText(text) {
1806
1846
  ;
1807
1847
  }
1808
1848
 
1849
+ async function terminalRun(cmd) {
1850
+ `
1851
+ 打开新的苹果终端并执行命令
1852
+ `
1853
+ const scriptText = `tell application "Terminal"
1854
+ activate
1855
+ do script "${cmd}"
1856
+ end tell
1857
+ `;
1858
+ let tempScriptPath = getTempDir() + `/terminalRun_${Date.now()}.scpt`
1859
+ fs.writeFileSync(tempScriptPath, scriptText);
1860
+ try {
1861
+ console.log(await e(`osascript ${tempScriptPath}`))
1862
+ } finally {
1863
+ fs.unlinkSync(tempScriptPath)
1864
+ }
1865
+ }
1866
+
1809
1867
  module.exports = {
1810
1868
  wrapperJsirText,
1811
1869
  run,
@@ -1903,5 +1961,8 @@ module.exports = {
1903
1961
  fileJson,
1904
1962
  debugStr,
1905
1963
  getAlias,
1906
- createDirs
1964
+ createDirs,
1965
+ getTempDir,
1966
+ terminalRun,
1967
+ eia
1907
1968
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "jsir",
3
- "version": "2.2.9",
3
+ "version": "2.3.1",
4
4
  "description": "JavaScript Script Management Tool",
5
5
  "main": "index.js",
6
6
  "scripts": {