jsir 1.3.2 → 2.0.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.
@@ -1,10 +1,11 @@
1
1
  #!/usr/bin/env node
2
2
  const {
3
3
  getLibDataDir, trim, regEach, getConfig, mkdir, reget,
4
- getCbText, e, sleep, objDataFile, setConfig, vl, md5, BigNumber,
4
+ getCbText, e, sleep, objDataFile, vl, md5, BigNumber,
5
5
  info, warn, error, arrayDataFile, infoStr, warnStr, errorStack,
6
6
  getInfo, ei, pad, msgStr, getType,
7
- errorTag, isArgsMatch, draftQuery
7
+ errorTag, isArgsMatch, draftQuery, setConfig,
8
+ $log, $draft, $config, getTextComments
8
9
  } = require('../util')
9
10
  const evalCode = require('../evalCode')
10
11
 
@@ -16,38 +17,32 @@ const _types = {
16
17
  const _chokidar = require('chokidar');
17
18
  const _fs = require('fs')
18
19
  const _libDataDir = getLibDataDir()
19
- const _home = _libDataDir + '/ooa'
20
20
  const _args = process.argv.slice(2).map(trim)
21
21
  const _history9 = []
22
22
  const _tipsOnRm = {}
23
23
  const readline = require("readline");
24
24
  const _fileWatcherMap = {}
25
-
25
+ const setting = require('../setting')
26
+ let _cmdMapFile = setting.name + 'CmdMap.json'
26
27
  let _cmdMap = {}
27
28
  let _rl
28
29
  let _rlHistory = []
29
30
  let _haveWrapperInput = true
30
- let _repos = arrayDataFile('repos.json')
31
+ let _workspaceConfigFile = 'workspace.json';
32
+ let _workspaces = arrayDataFile(_workspaceConfigFile)
31
33
  let _exit = false
32
34
 
33
35
  const $data = {}
36
+ const $homeDir = getLibDataDir()
37
+ const $lib = {...require('../util')}
34
38
 
35
- global.$lib = {}
36
39
  global.$tips = {}
37
40
  global.$newInput = false
38
-
39
- try {
40
- getConfig("jsLibSource")
41
- } catch (e) {
42
- error(e)
43
- }
41
+ global.$workspaceMap = {}
42
+ global.$defaultSpace = 'local'
44
43
 
45
44
  let _noAppendNextLine = true
46
45
 
47
- function initRuntime() {
48
- global.$lib = {...require('../util')}
49
- }
50
-
51
46
  function getFileOpenExe(fileName) {
52
47
  fileName = trim(fileName);
53
48
  let strs = fileName.split('.')
@@ -63,17 +58,34 @@ function getFileOpenExe(fileName) {
63
58
  return exe || 'idea';
64
59
  }
65
60
 
61
+ function checkWorkspaces() {
62
+ let localWorkspace = _libDataDir + '/local';
63
+ $workspaceMap['local'] = localWorkspace;
64
+ mkdir(localWorkspace)
65
+ for (let workspace of _workspaces) {
66
+ workspace = workspace.replace(/\/+$/, '')
67
+ let space = getSpaceFromDir(workspace);
68
+ if (space === 'local') {
69
+ continue
70
+ }
71
+ if (_fs.existsSync(workspace)) {
72
+ $workspaceMap[space] = workspace;
73
+ }
74
+ }
75
+ _workspaces = Object.values($workspaceMap);
76
+ arrayDataFile(_workspaceConfigFile, () => _workspaces)
77
+ initWorkspace()
78
+ }
79
+
66
80
  async function start() {
67
- mkdir(_home)
68
- dealSourceCmds()
81
+ checkWorkspaces()
69
82
 
70
83
  if (_args[0] === '--repl') {
71
- initRuntime()
72
84
  _noAppendNextLine = false
73
- console.log(warnStr("You can start with .help"))
85
+ console.log(warnStr("You can start with .help, use * to expand context"))
74
86
  } else if (_args[0]) {
75
87
  if (_noAppendNextLine) {
76
- _cmdMap = objDataFile('ooaCmdMap.json')
88
+ _cmdMap = objDataFile(_cmdMapFile)
77
89
  }
78
90
  let line = _args.map(i => {
79
91
  if (/\s+/.test(i) || !i) {
@@ -81,21 +93,16 @@ async function start() {
81
93
  }
82
94
  return i
83
95
  }).join(' ')
84
- if (/^\d+$/.test(_args[0])) {
85
- if (_args[0] === '0' || (_cmdMap[_args[0]] && ['e ', 'f '].filter(i => _cmdMap[_args[0]].startsWith(i)).length > 0)) {
86
- initRuntime()
87
- }
88
- }
89
96
  await wrapperInput(line)
90
97
  } else {
91
98
  if (_noAppendNextLine) {
92
- _cmdMap = objDataFile('ooaCmdMap.json')
99
+ _cmdMap = objDataFile(_cmdMapFile)
93
100
  }
94
101
  listCmd();
95
102
  }
96
103
  }
97
104
 
98
- async function getFileWatcher(fileName, workFilePath, text) {
105
+ async function getFileWatcher(workFilePath, text) {
99
106
  info("workFile open " + workFilePath)
100
107
  if (!_fileWatcherMap[workFilePath]) {
101
108
  _fs.unlinkSync(workFilePath)
@@ -118,22 +125,21 @@ function closeFileWatcher(workFilePath) {
118
125
  delete _fileWatcherMap[workFilePath]
119
126
  }
120
127
 
121
- async function workFile(name) {
122
- name = trim(name)
123
- if (!name) {
124
- name = 'workFile'
128
+ async function workFile(uniqueName) {
129
+ uniqueName = trim(uniqueName)
130
+ if (!uniqueName) {
131
+ uniqueName = toUniqueName('f workFile')
125
132
  }
126
- let fileName = `f ${toJsirFileName(name)}`
127
- await watchFile(fileName)
133
+ await watchFile(uniqueName)
128
134
  }
129
135
 
130
- async function watchFile(fileName) {
131
- let workFilePath = `${_home}/${fileName}`;
136
+ async function watchFile(uniqueName) {
137
+ let workFilePath = getFullPath(uniqueName);
132
138
  if (!_fs.existsSync(workFilePath)) {
133
139
  _fs.writeFileSync(workFilePath, '');
134
140
  }
135
141
  let text = String(_fs.readFileSync(workFilePath))
136
- let watcher = await getFileWatcher(fileName, workFilePath, text)
142
+ let watcher = await getFileWatcher(workFilePath, text)
137
143
 
138
144
  if (watcher) {
139
145
  watcher.on('change', async () => {
@@ -152,7 +158,7 @@ async function watchFile(fileName) {
152
158
  closeFileWatcher(workFilePath);
153
159
  });
154
160
  }
155
- await e(`"${getFileOpenExe(fileName)}" "${workFilePath}"`)
161
+ await e(`"${getFileOpenExe(parseUniqueName(uniqueName)[1])}" "${workFilePath}"`)
156
162
  }
157
163
 
158
164
  function getExeStr(oldText, newText) {
@@ -227,12 +233,11 @@ function initRl(callback, preStr, hidden) {
227
233
  _rl.history = _rlHistory
228
234
  }
229
235
 
230
- let repoTip = trim(trim(getConfig("jsLibSource")).split('/').map(trim).reverse().filter(i => i)[0])
231
236
  let promptStr = preStr
232
237
  if (promptStr !== '') {
233
238
  promptStr = (preStr
234
239
  || ((callback && callback !== wrapperInput) ? "-> ":"")
235
- || [Object.values(global.$tips).filter(i => String(i)).join(','), repoTip].filter(i => i).join(':') + `> `)
240
+ || [Object.values(global.$tips).filter(i => String(i)).join(','), $defaultSpace].filter(i => i).join(':') + `> `)
236
241
  promptStr = infoStr(promptStr)
237
242
  }
238
243
  if (hidden) {
@@ -318,24 +323,13 @@ async function nextText(callback, end, hidden) {
318
323
  })
319
324
  }
320
325
 
321
- function dealSourceCmds() {
322
- let source = trim(getConfig("jsLibSource"));
323
- if (source && _fs.existsSync(source)) {
324
- _fs.readdirSync(source).filter(isJsirFileName).forEach(item => {
325
- if (!_fs.existsSync(_home + "/" + item)) {
326
- _fs.writeFileSync(_home + "/" + item, String(_fs.readFileSync(source + "/" + item)))
327
- }
328
- })
329
- }
330
- }
331
-
332
326
  async function save(args) {
333
- let name = toJsirFileName(args.join(' '))
334
- let path = `${_home}/${name}`
327
+ let uniqueName = toUniqueName(toJsirFileName(args.join(' ')))
328
+ let path = getFullPath(uniqueName)
335
329
  if (_fs.existsSync(path)) {
336
330
  warn(`${path} already exist`)
337
331
  _cmdMap = {
338
- 1: name
332
+ 1: uniqueName
339
333
  }
340
334
  listCmd()
341
335
  return
@@ -374,32 +368,24 @@ return {}
374
368
  _fs.writeFileSync(path, resp)
375
369
  info(`${path} created`)
376
370
  _cmdMap = {
377
- 1: name
371
+ 1: uniqueName
378
372
  }
379
373
  listCmd()
380
374
  }
381
375
 
382
- function rename(dir, oldName, newName, isOoa) {
376
+ function rename(dir, oldName, newName) {
383
377
  let old = dir + '/' + oldName;
384
378
  let _new = dir + '/' + newName;
385
379
  if (_fs.existsSync(_new)) {
386
- if (isOoa) {
387
- warn(`${_new} already exist`)
388
- _cmdMap = {
389
- 1: newName
390
- }
391
- listCmd()
392
- }
393
- return
394
- }
395
- _fs.rename(old, _new, ()=>{})
396
- if (isOoa) {
380
+ warn(`${_new} already exist`)
381
+ } else {
382
+ _fs.rename(old, _new, ()=>{})
397
383
  info(`${_new} renamed`)
398
- _cmdMap = {
399
- 1: newName
400
- }
401
- listCmd()
402
384
  }
385
+ _cmdMap = {
386
+ 1: toUniqueName(newName)
387
+ }
388
+ listCmd()
403
389
  }
404
390
 
405
391
  function putHis(x) {
@@ -422,85 +408,57 @@ function hisToCmdMap() {
422
408
  _cmdMap = cmdMap
423
409
  }
424
410
 
425
- function listCmd(prefixKey, inputCmdMap) {
426
- let currCmdMap = _cmdMap
427
- if (inputCmdMap) {
428
- currCmdMap =inputCmdMap;
429
- }
430
- let newCmdMap = {}
431
- let prefixMap = {}
432
- for (let i of Object.keys(currCmdMap)) {
433
- let jsLib = trim(getConfig("jsLibSource"))
434
- let sourceFile = jsLib + "/" + currCmdMap[i]
435
- let prefix = [' ', ' ']
436
- prefixMap[currCmdMap[i]] = prefix;
437
- if (jsLib && _fs.existsSync(sourceFile)) {
438
- prefix[1] = '#'
439
- let text1 = String(_fs.readFileSync(_home + "/" + currCmdMap[i]))
440
- let text2 = String(_fs.readFileSync(sourceFile))
441
- if (text1 !== text2) {
442
- prefix[0] = '*'
443
- }
444
- }
445
- }
446
- let items = Object.values(currCmdMap)
447
- .filter(item => _fs.existsSync(_home + "/" + item)
448
- && ((prefixKey === '' && prefixMap[item].filter(i => trim(i)).length <= 0)
449
- || (trim(prefixKey) && prefixMap[item].indexOf(trim(prefixKey)) !== -1)
450
- || (!prefixKey && prefixKey !== '')))
411
+ function listCmd() {
412
+ let items = Object.values(_cmdMap)
413
+ .filter(item => _fs.existsSync(getFullPath(item)))
451
414
  .sort((a,b) => {
415
+ a = parseUniqueName(a)[1];
416
+ b = parseUniqueName(b)[1];
452
417
  let typeKeys = Object.keys(_types);
453
418
  let orderA = typeKeys.indexOf(a.split(/\s+/)[0]);
454
419
  let orderB = typeKeys.indexOf(b.split(/\s+/)[0]);
455
- orderA = orderA === -1 ? 999:orderA;
456
- orderB = orderB === -1 ? 999:orderB;
420
+ orderA = orderA === -1 ? 999999:orderA;
421
+ orderB = orderB === -1 ? 999999:orderB;
457
422
  return orderA - orderB
458
423
  })
459
- for(let i = 0; i< items.length; i++) {
460
- newCmdMap[i + 1] =items[i]
461
- }
462
424
 
463
- currCmdMap = newCmdMap
464
- if (!inputCmdMap) {
465
- _cmdMap = newCmdMap
466
- if (_noAppendNextLine) {
467
- objDataFile('ooaCmdMap.json', () => _cmdMap)
468
- }
469
- } else {
470
- for (let key of Object.keys(inputCmdMap)) {
471
- delete inputCmdMap[key]
472
- }
473
- Object.assign(inputCmdMap, newCmdMap)
425
+ _cmdMap = arrayToCmdMap(items)
426
+ if (_noAppendNextLine) {
427
+ objDataFile(_cmdMapFile, () => _cmdMap)
474
428
  }
475
429
 
476
430
  items = []
477
- for (let i of Object.keys(currCmdMap)) {
478
- let prefix = prefixMap[currCmdMap[i]]
479
- let text = String(_fs.readFileSync(_home + "/" + currCmdMap[i]))
480
- let name = trimJsirFileName(currCmdMap[i])
481
- let suffix = getJsirFileSuffix(currCmdMap[i])
431
+ for (let i of Object.keys(_cmdMap)) {
432
+ let text = String(_fs.readFileSync(getFullPath(_cmdMap[i])))
433
+ let pair = parseUniqueName(_cmdMap[i])
434
+ let name = trimJsirFileName(pair[1])
435
+ let suffix = getJsirFileSuffix(pair[1])
482
436
  let item = {
483
- key: prefix.join('') + i,
484
- name: name.replace(/^[eif]\s+/, ''),
437
+ key: ' ' + i,
438
+ name: pair[0] + '/' + name.replace(/^[eif]\s+/, ''),
485
439
  type: [_types[name.split(/\s+/)[0]] || 'note', suffix].map(trim).join(".")
486
440
  }
487
441
  items.push(item)
488
442
 
489
443
  if (!text) {
490
- text = String(_fs.readFileSync(_home + "/" + currCmdMap[i]))
444
+ text = String(_fs.readFileSync(getFullPath(_cmdMap[i])))
491
445
  }
492
- getComments(i, currCmdMap[i], text, items, item)
446
+ getComments(i, _cmdMap[i], text, items, item)
493
447
  }
494
448
  if (Object.keys(items).length === 0) {
495
449
  warn("no items")
496
450
  } else {
497
451
  items.forEach(item => {
498
452
  if (item.type) {
453
+ let pair = parseUniqueName(item.name);
499
454
  if (item.type.startsWith('exe.')) {
500
- item.name = infoStr(item.name)
455
+ item.name = infoStr(pair[1])
501
456
  } else if (item.type.startsWith('init.')) {
502
- item.name = msgStr(item.name)
457
+ item.name = msgStr(pair[1])
458
+ } else {
459
+ item.name = pair[1]
503
460
  }
461
+ item.name = pair[0] + '/' + item.name
504
462
  }
505
463
  })
506
464
  console.table(items)
@@ -527,7 +485,7 @@ async function _wrapperInput(str) {
527
485
  let cmdStr = trim(str.substr(1));
528
486
  if (/^\d+$/.test(cmdStr) && _cmdMap[cmdStr]) {
529
487
  if (_cmdMap[cmdStr]) {
530
- ei('vi', [getLibDataDir() + '/ooa/' + _cmdMap[cmdStr]])
488
+ ei('vi', [getFullPath(_cmdMap[cmdStr])])
531
489
  } else {
532
490
  warn("no items")
533
491
  }
@@ -558,6 +516,9 @@ async function _wrapperInput(str) {
558
516
  if (is$) {
559
517
  console.log(await evalText('return ' + text))
560
518
  } else if (isStar) {
519
+ if (!text) {
520
+ text = '$context';
521
+ }
561
522
  let items = text.split(/\s+/).map(trim).filter(i => i)
562
523
  let result = await evalText('return ' + items[0])
563
524
  if (!result || typeof result === 'string' || Object.keys(result).length === 0) {
@@ -567,7 +528,7 @@ async function _wrapperInput(str) {
567
528
  let rows = []
568
529
  let matchs = items.slice(1)
569
530
  for (let key of Object.keys(result)) {
570
- if (matchs.length === 0 || isArgsMatch(key, matchs)){
531
+ if (matchs.length === 0 || isArgsMatch(key, [matchs.join(' ')])){
571
532
  rows.push(getInfo(result[key], key))
572
533
  }
573
534
  }
@@ -587,17 +548,18 @@ async function _wrapperInput(str) {
587
548
  help()
588
549
  }
589
550
  } else if (!str.split(/\s+/)[0].match(/^\d+$/)) {
590
- _cmdMap = filterCmd(str.split(/\s+/))
551
+ _cmdMap = arrayToCmdMap(filterCmd(str))
591
552
  listCmd()
592
553
  } else {
593
554
  let strs = str.split(/\s+/)
594
555
  if (_cmdMap[strs[0]]) {
595
556
  putHis(_cmdMap[strs[0]])
596
- let path = _home + '/' + _cmdMap[strs[0]]
597
- let fileName = trim(_cmdMap[strs[0]]);
557
+ let path = getFullPath(_cmdMap[strs[0]])
558
+ let uniqueName = trim(_cmdMap[strs[0]]);
559
+ let fileName = parseUniqueName(uniqueName)[1]
598
560
  let firstName = fileName.split(/\s+/)[0]
599
561
  if (firstName === 'f') {
600
- await workFile(fileName.replace(/^\s*f\s*/, ''))
562
+ await workFile(uniqueName)
601
563
  } else if (firstName !== 'e') {
602
564
  console.log(String(_fs.readFileSync(path)));
603
565
  } else {
@@ -609,6 +571,13 @@ async function _wrapperInput(str) {
609
571
  }
610
572
  }
611
573
 
574
+ function arrayToCmdMap(cmds) {
575
+ let cmdMap = {}
576
+ for (let i = 0; i < cmds.length; i++) {
577
+ cmdMap[i + 1] = cmds[i];
578
+ }
579
+ return cmdMap
580
+ }
612
581
 
613
582
  function help() {
614
583
  console.nable(Object.keys(keywordDef).map(key => {
@@ -640,6 +609,82 @@ function delTipsByIndex(idxs) {
640
609
  delTips(...params)
641
610
  }
642
611
 
612
+ function copyToSpace(uniqueName) {
613
+ let path = getFullPath(uniqueName)
614
+ let text = String(_fs.readFileSync(path))
615
+ let fileName = parseUniqueName(uniqueName)[1];
616
+ let targetPath = $workspaceMap[$defaultSpace] + '/' + fileName;
617
+ if (_fs.existsSync(targetPath)) {
618
+ warn(`${fileName} already exist in ${$defaultSpace}`)
619
+ } else {
620
+ _fs.writeFileSync(targetPath, text)
621
+ info(`get ${uniqueName} to ${$defaultSpace}`)
622
+ }
623
+ }
624
+
625
+ let compareMode = {
626
+ 'a=': (aSpace, bSpace, as, bs) => {
627
+ let result = []
628
+ for (let a of as) {
629
+ if (bs.indexOf(a) !== -1) {
630
+ result.push(aSpace + '/' + a)
631
+ }
632
+ }
633
+ return result
634
+ },
635
+ 'b=': (aSpace, bSpace, as, bs) => {
636
+ let result = []
637
+ for (let a of as) {
638
+ if (bs.indexOf(a) !== -1) {
639
+ result.push(bSpace + '/' + a)
640
+ }
641
+ }
642
+ return result
643
+ },
644
+ 'ab=': (aSpace, bSpace, a, b, as, bs) => {
645
+ let result = []
646
+ for (let a of as) {
647
+ if (bs.indexOf(a) !== -1) {
648
+ result.push(aSpace + '/' + a)
649
+ result.push(bSpace + '/' + a)
650
+ }
651
+ }
652
+ return result
653
+ },
654
+ 'a+': (aSpace, bSpace, as, bs) => {
655
+ let result = []
656
+ for(let a of as) {
657
+ if (bs.indexOf(a) === -1) {
658
+ result.push(aSpace + '/' + a)
659
+ }
660
+ }
661
+ return result
662
+ },
663
+ 'b+': (aSpace, bSpace, as, bs) => {
664
+ let result = []
665
+ for(let b of bs) {
666
+ if (as.indexOf(b) === -1) {
667
+ result.push(bSpace + '/' + b)
668
+ }
669
+ }
670
+ return result
671
+ },
672
+ 'ab+': (aSpace, bSpace, as, bs) => {
673
+ let result = []
674
+ for(let a of as) {
675
+ if (bs.indexOf(a) === -1) {
676
+ result.push(aSpace + '/' + a)
677
+ }
678
+ }
679
+ for(let b of bs) {
680
+ if (as.indexOf(b) === -1) {
681
+ result.push(bSpace + '/' + b)
682
+ }
683
+ }
684
+ return result
685
+ }
686
+ }
687
+
643
688
  const keywordDef = {
644
689
  help: {
645
690
  comment: '帮助文档',
@@ -649,9 +694,9 @@ const keywordDef = {
649
694
  short: 'H'
650
695
  },
651
696
  list: {
652
- comment: '查看本地文件列表',
697
+ comment: '查看文件列表',
653
698
  exeFn: (args) => {
654
- _cmdMap = filterCmd(args.length > 0 ? args:[','])
699
+ _cmdMap = arrayToCmdMap(filterCmd(args.length > 0 ? args.join(' '):[',']))
655
700
  listCmd()
656
701
  },
657
702
  args: {
@@ -670,13 +715,13 @@ const keywordDef = {
670
715
  short: 'C'
671
716
  },
672
717
  see: {
673
- comment: '查看本地文件',
718
+ comment: '查看文件',
674
719
  exeFn: (args) => {
675
- let name = _cmdMap[args[0]]
676
- if (!name) {
720
+ let uniqueName = _cmdMap[args[0]]
721
+ if (!uniqueName) {
677
722
  warn("no items")
678
723
  } else {
679
- let path = _home + '/' + name
724
+ let path = getFullPath(uniqueName)
680
725
  let sourceStr = String(_fs.readFileSync(path))
681
726
  console.log(sourceStr)
682
727
  }
@@ -687,147 +732,74 @@ const keywordDef = {
687
732
  short: 's'
688
733
  },
689
734
  rm: {
690
- comment: '删除本地文件以及其源文件',
735
+ comment: '删除文件',
691
736
  exeFn: (args) => {
692
- let name = _cmdMap[args[0]]
693
- if (!name) {
737
+ let uniqueName = _cmdMap[args[0]]
738
+ if (args[0] === 'ALL') {
739
+ for (let value of Object.values(_cmdMap)) {
740
+ let path = getFullPath(value)
741
+ _fs.unlinkSync(path)
742
+ info(`${path} removed`)
743
+ }
744
+ } else if (!uniqueName) {
694
745
  warn("no items")
695
746
  } else {
696
- let path = _home + '/' + name
747
+ let path = getFullPath(uniqueName)
697
748
  _fs.unlinkSync(path)
698
- let jsLibDir = trim(getConfig("jsLibSource"))
699
- if (jsLibDir && _fs.existsSync(jsLibDir)) {
700
- if (_fs.existsSync(jsLibDir + '/' + name)) {
701
- _fs.unlinkSync(jsLibDir + '/' + name)
702
- }
703
- }
704
749
  info(`${path} removed`)
705
750
  }
706
751
  },
707
752
  args: {
708
- fileIndex: '文件下标'
753
+ fileIndex: '文件下标, ALL代表全部'
709
754
  },
710
755
  short: 'R'
711
756
  },
712
- rename: {
713
- comment: '重命名本地文件以及其源文件',
714
- exeFn: (args) => {
715
- let name = _cmdMap[args[0]]
716
- if (!name) {
717
- warn("no items")
718
- } else {
719
- let newName =trim(args.slice(1).join(" "))
720
- if (newName) {
721
- newName = toJsirFileName(newName)
722
- let jsLibDir = trim(getConfig("jsLibSource"))
723
- if (jsLibDir && _fs.existsSync(jsLibDir)) {
724
- if (_fs.existsSync(jsLibDir + '/' + name)) {
725
- rename(jsLibDir, name, newName)
726
- }
727
- }
728
- rename(_home, name, newName, true)
729
- }
730
- }
731
- },
732
- args: {
733
- fileIndex: '文件下标',
734
- newName: '新名字'
735
- },
736
- short: 'r'
737
- },
738
- source: {
739
- comment: '查看源文件',
740
- exeFn: (args) => {
741
- let name = _cmdMap[args[0]]
742
- if (!name) {
743
- warn("no items")
744
- } else {
745
- let jsLibDir = trim(getConfig("jsLibSource"))
746
- if (jsLibDir && _fs.existsSync(jsLibDir)) {
747
- let sFile = jsLibDir + "/" + name
748
- if (_fs.existsSync(sFile)) {
749
- let sourceStr = String(_fs.readFileSync(sFile))
750
- console.log(sourceStr)
751
- }
752
- } else {
753
- warn('require origin workspace')
754
- }
755
- }
756
- },
757
- args: {
758
- fileIndex: '文件下标'
759
- },
760
- short: 'S'
761
- },
762
757
  get: {
763
- comment: '将源文件内容覆盖到本地文件',
758
+ comment: '获取文件',
764
759
  exeFn: (args) => {
765
- let name = _cmdMap[args[0]]
766
- if (!args[0]) {
767
- listCmd('*')
768
- } else if (!name) {
760
+ let uniqueName = _cmdMap[args[0]]
761
+ if (args[0] === 'ALL') {
762
+ for (let value of Object.values(_cmdMap)) {
763
+ copyToSpace(value)
764
+ }
765
+ } else if (!uniqueName) {
769
766
  warn("no items")
770
767
  } else {
771
- let jsLibDir = trim(getConfig("jsLibSource"))
772
- if (jsLibDir && _fs.existsSync(jsLibDir)) {
773
- let sFile = jsLibDir + "/" + name
774
- if (_fs.existsSync(sFile)) {
775
- let sourceStr = String(_fs.readFileSync(sFile))
776
- let path = _home + '/' + name
777
- if (sourceStr) {
778
- _fs.writeFileSync(path, sourceStr)
779
- }
780
- }
781
- info(`${name} pulled`)
782
- } else {
783
- warn('require origin workspace')
784
- }
768
+ copyToSpace(uniqueName)
785
769
  }
786
770
  },
787
771
  args: {
788
- fileIndex: '文件下标'
772
+ fileIndex: '文件下标, ALL代表全部'
789
773
  },
790
774
  short: 'g'
791
775
  },
792
- push: {
793
- comment: '将本地文件内容覆盖到源文件',
776
+ rename: {
777
+ comment: '重命名文件',
794
778
  exeFn: (args) => {
795
- let name = _cmdMap[args[0]]
796
- if (!args[0]) {
797
- listCmd('#')
798
- } else if (!name) {
779
+ let uniqueName = _cmdMap[args[0]]
780
+ if (!uniqueName) {
799
781
  warn("no items")
800
782
  } else {
801
- let jsLibDir = trim(getConfig("jsLibSource"))
802
- if (jsLibDir && _fs.existsSync(jsLibDir)) {
803
- _fs.writeFileSync(jsLibDir + "/" + name, String(_fs.readFileSync(_home + '/' + name)))
804
- info(`${name} pushed`)
805
- } else {
806
- warn('require origin workspace')
807
- }
783
+ let pair = parseUniqueName(uniqueName)
784
+ let newName =trim(args.slice(1).join(" "))
785
+ rename($workspaceMap[pair[0]], pair[1], toJsirFileName(newName), true)
808
786
  }
809
787
  },
810
788
  args: {
811
- fileIndex: '文件下标'
812
- },
813
- short: 'p'
814
- },
815
- unsync: {
816
- comment: '查看未同步源文件的本地文件列表',
817
- exeFn: (args) => {
818
- listCmd('')
789
+ fileIndex: '文件下标',
790
+ newName: '新名字'
819
791
  },
820
- short: 'u'
792
+ short: 'r'
821
793
  },
822
794
  edit: {
823
- comment: '编辑本地文件',
795
+ comment: '编辑文件',
824
796
  exeFn: async (args) => {
825
- let name = _cmdMap[args[0]]
826
- if (!name) {
797
+ let uniqueName = _cmdMap[args[0]]
798
+ if (!uniqueName) {
827
799
  warn("no items")
828
800
  } else {
829
- let path = _home + '/' + name
830
- await e(`"${getFileOpenExe(name)}" "${path}"`)
801
+ let path = getFullPath(uniqueName)
802
+ await e(`"${getFileOpenExe(parseUniqueName(uniqueName)[1])}" "${path}"`)
831
803
  }
832
804
  },
833
805
  args: {
@@ -836,44 +808,61 @@ const keywordDef = {
836
808
  short: 'e'
837
809
  },
838
810
  compare: {
839
- comment: '比较本地文件和源文件',
811
+ comment: '比较文件',
840
812
  exeFn: async (args) => {
841
- let name = _cmdMap[args[0]]
842
- if (!name) {
843
- warn("no items")
844
- } else {
845
- let path = _home + '/' + name
846
- let jsLibDir = trim(getConfig("jsLibSource"))
847
- if (jsLibDir && _fs.existsSync(jsLibDir)) {
848
- let sPath = jsLibDir + "/" + name
849
- await e(`idea diff "${sPath}" "${path}"`)
850
- } else {
851
- warn('require origin workspace')
813
+ let aUniqueName = _cmdMap[args[0]]
814
+ let bUniqueName = _cmdMap[args[1]]
815
+ let aSpace = args[0]
816
+ let bSpace = args[1]
817
+
818
+ if (aUniqueName && bUniqueName) {
819
+ await e(`idea diff "${getFullPath(aUniqueName)}" "${getFullPath(bUniqueName)}"`)
820
+ } else if (aSpace && bSpace) {
821
+ if (!args[2]) {
822
+ warn('require mode')
823
+ return
852
824
  }
853
- }
854
- },
855
- args: {
856
- fileIndex: '文件下标',
857
- },
858
- short: 'c'
859
- },
860
- deps: {
861
- comment: '查看文件依赖',
862
- exeFn: (args) => {
863
- let name = _cmdMap[args[0]]
864
- if (!name) {
865
- warn("no items")
866
- } else {
867
- let md5Keys = getScriptRequires(name);
868
- _cmdMap = filterCmd(md5Keys)
825
+
826
+ let mode = args[2]
827
+ if (Object.keys(compareMode).indexOf(mode) === -1) {
828
+ warn('invalid mode')
829
+ return;
830
+ }
831
+
832
+ let aFiles = _fs.readdirSync($workspaceMap[aSpace]).filter(isJsirFileName)
833
+ let bFiles = _fs.readdirSync($workspaceMap[bSpace]).filter(isJsirFileName)
834
+
835
+ let result = compareMode[mode](aSpace, bSpace, aFiles, bFiles);
836
+ _cmdMap = arrayToCmdMap(result)
869
837
  listCmd()
838
+ } else {
839
+ warn('invalid args')
870
840
  }
871
841
  },
872
842
  args: {
873
- fileIndex: '文件下标'
843
+ a: '文件/工作空间',
844
+ b: '文件/工作空间',
845
+ mode: 'a=, b=, ab=, a+, b+, ab+'
874
846
  },
875
- short: 'd'
847
+ short: 'c'
876
848
  },
849
+ // deps: {
850
+ // comment: '查看文件依赖',
851
+ // exeFn: (args) => {
852
+ // let uniqueName = _cmdMap[args[0]]
853
+ // if (!uniqueName) {
854
+ // warn("no items")
855
+ // } else {
856
+ // let md5Keys = getScriptRequires(uniqueName);
857
+ // _cmdMap = arrayToCmdMap(filterCmd(md5Keys))
858
+ // listCmd()
859
+ // }
860
+ // },
861
+ // args: {
862
+ // fileIndex: '文件下标'
863
+ // },
864
+ // short: 'd'
865
+ // },
877
866
  history: {
878
867
  comment: '查看执行记录',
879
868
  exeFn: (args) => {
@@ -902,37 +891,47 @@ const keywordDef = {
902
891
  short: 'f'
903
892
  },
904
893
  workspace: {
905
- comment: '源空间管理',
894
+ comment: '工作空间管理',
906
895
  exeFn: async (args) => {
907
- let newRepo = args.join(' ')
908
- let currRepo = getConfig('jsLibSource');
909
- if (!newRepo) {
910
- console.log(`current: ${currRepo}`)
911
- _repos = _repos.filter(i => _fs.existsSync(i))
912
- for(let i = 0; i<_repos.length; i++) {
913
- console.log(`${i+1}: ${_repos[i]}`)
914
- }
915
- let repoStr = trim(await nextLine(line => line, 'reset(or blank): '))
916
- if (/^\d+$/.test(repoStr)) {
917
- repoStr = _repos[Number(repoStr) - 1]
918
- }
919
- newRepo = repoStr
896
+ let newWorkspace = args.join(' ')
897
+ if (newWorkspace) {
898
+ _workspaces.push(newWorkspace)
920
899
  }
921
- if (newRepo && newRepo !== currRepo) {
922
- if (_fs.existsSync(newRepo)) {
923
- setConfig('jsLibSource', newRepo)
924
- if (_repos.indexOf(newRepo) === -1) {
925
- _repos.push(newRepo)
926
- }
927
- arrayDataFile('repos.json', () => _repos)
928
- dealSourceCmds()
929
- } else {
930
- warn(`repo ${newRepo} not exist`)
900
+ checkWorkspaces()
901
+ let items = _workspaces.map((path, index) => {
902
+ return {
903
+ index: ' ' + (index + 1),
904
+ name: getSpaceFromDir(path),
905
+ path
931
906
  }
932
- }
907
+ })
908
+ console.table(items)
909
+ },
910
+ args: {
911
+ workspacePath: '新增工作空间路径'
933
912
  },
934
913
  short: 'w'
935
914
  },
915
+ switch: {
916
+ comment: '切换工作空间',
917
+ exeFn: async (args) => {
918
+ checkWorkspaces()
919
+ let items = _workspaces.map((path, index) => {
920
+ return {
921
+ index: ' ' + (index + 1),
922
+ name: getSpaceFromDir(path),
923
+ path
924
+ }
925
+ })
926
+ console.table(items)
927
+ let index = trim(await nextLine(line => line, "switch workspace: "));
928
+ if (index && _workspaces[index - 1]) {
929
+ let workspace = _workspaces[index - 1];
930
+ initWorkspace(getSpaceFromDir(workspace))
931
+ }
932
+ },
933
+ short: 'S'
934
+ },
936
935
  add: {
937
936
  comment: '新增文件',
938
937
  exeFn: async (args) => {
@@ -973,62 +972,52 @@ async function dealKeyword(str) {
973
972
  }
974
973
  }
975
974
 
976
- function getScriptMd5Map() {
977
- let files = _fs.readdirSync(_home)
978
- let md5Map = {}
979
- for (let file of files) {
980
- file = trim(file)
981
- md5Map['0x' + md5(file).substr(0, 8)] = file;
982
- }
983
- return md5Map
984
- }
985
-
986
- function _getScriptRequires(md5Map, scriptName, md5Keys, links) {
987
- let path = _home + '/' + scriptName;
988
- let text = String(_fs.readFileSync(path))
989
- let temp = []
990
- regEach(text, /(0x[0-9a-f]{8})/g, r=> {
991
- temp.push(r[1])
992
- });
993
- temp = [...new Set(temp)]
994
- temp = temp.filter(i => {
995
- let have = md5Map[i];
996
- if (have && links.indexOf(i) !== -1) {
997
- let items = [...links, i];
998
- let errorStr = items.map(item => item === i ? warnStr(item):item).join("->")
999
- throw `circle deps: ${errorStr}`
1000
- }
1001
- return have;
1002
- })
1003
- md5Keys.push(...temp)
1004
- for (let md5Key of temp) {
1005
- _getScriptRequires(md5Map, md5Map[md5Key], md5Keys, [...links, md5Key])
1006
- }
1007
- }
1008
-
1009
- function getScriptRequires(scriptName) {
1010
- let md5Keys = [];
1011
- _getScriptRequires(getScriptMd5Map(), scriptName, md5Keys, ['0x' + md5(scriptName).substr(0, 8)]);
1012
- return md5Keys
1013
- }
975
+ // function getScriptMd5Map() {
976
+ // let md5Map = {}
977
+ // _workspaces.forEach(i => _getScriptMd5Map(i, md5Map))
978
+ // return md5Map
979
+ // }
980
+
981
+ // function _getScriptMd5Map(dir, md5Map) {
982
+ // let files = _fs.readdirSync(dir).filter(isJsirFileName)
983
+ // for (let file of files) {
984
+ // md5Map[getCmdMd5Key(file)] = file;
985
+ // }
986
+ // }
987
+
988
+ // function _getScriptRequires(uniqueName, matchStrs, links) {
989
+ // let path = getFullPath(uniqueName);
990
+ // let text = String(_fs.readFileSync(path))
991
+ // let temp = []
992
+ // regEach(text, /\$require\s*\([^()]+\)/g, r=> {
993
+ // temp.push(r[1])
994
+ // });
995
+ // temp = [...new Set(temp)]
996
+ // temp = temp.filter(i => {
997
+ // let have = md5Map[i];
998
+ // if (have && links.indexOf(i) !== -1) {
999
+ // let items = [...links, i];
1000
+ // let errorStr = items.map(item => item === i ? warnStr(item):item).join("->")
1001
+ // throw `circle deps: ${errorStr}`
1002
+ // }
1003
+ // return have;
1004
+ // })
1005
+ // md5Keys.push(...temp)
1006
+ // for (let md5Key of temp) {
1007
+ // _getScriptRequires(md5Map, md5Map[md5Key], md5Keys, [...links, md5Key])
1008
+ // }
1009
+ // }
1010
+
1011
+ // function getScriptRequires(uniqueName) {
1012
+ // let matchStrs = [];
1013
+ // _getScriptRequires(uniqueName, matchStrs, [getCmdMd5Key(uniqueName)]);
1014
+ // return md5Keys
1015
+ // }
1014
1016
 
1015
1017
  function getComments(i, cmdName, text, cols = [], col) {
1016
- let docLines = [infoStr('0x' + md5(cmdName).substr(0, 8)) + " - " + infoStr(i)]
1018
+ let docLines = [infoStr(getCmdMd5Key(parseUniqueName(cmdName)[1])) + " - " + infoStr(i)]
1017
1019
  text = trim(text)
1018
- if (text.startsWith("/*")) {
1019
- for (let line of text.split("\n")) {
1020
- let trimLine = trim(line)
1021
- if (trimLine.startsWith("/*")) {
1022
- continue
1023
- }
1024
- if (trimLine.endsWith("*/")) {
1025
- break
1026
- }
1027
- if (trimLine) {
1028
- docLines.push(line)
1029
- }
1030
- }
1031
- }
1020
+ docLines.push(...getTextComments(text))
1032
1021
  let argDef = getArgDef(text)
1033
1022
  let comments = getArgComments(argDef)
1034
1023
  if (comments) {
@@ -1046,8 +1035,43 @@ function getComments(i, cmdName, text, cols = [], col) {
1046
1035
  }
1047
1036
  }
1048
1037
 
1038
+ function getFullPath(name) {
1039
+ name = trim(name)
1040
+ if (!name) {
1041
+ return name;
1042
+ }
1043
+ let uniqueName = toUniqueName(name)
1044
+ let pair = parseUniqueName(uniqueName)
1045
+ let space = $workspaceMap[pair[0]]
1046
+ if (!space) {
1047
+ return ''
1048
+ }
1049
+ return `${space}/${pair[1]}`
1050
+ }
1051
+
1052
+ function toUniqueName(name, space) {
1053
+ name = trim(name)
1054
+ if (!name) {
1055
+ throw `invalid name`
1056
+ }
1057
+ let uniqueName
1058
+ if (name.startsWith('/')) {
1059
+ let items = name.split('/').map(trim).filter(i => i).reverse()
1060
+ uniqueName = items[1] + '/' + items[0]
1061
+ } else if (name.indexOf('/') !== -1) {
1062
+ uniqueName = name;
1063
+ } else {
1064
+ uniqueName = (space || $defaultSpace) + '/' + name;
1065
+ }
1066
+ let pair = parseUniqueName(uniqueName);
1067
+ return (pair[0] || space || $defaultSpace) + '/' + toJsirFileName(pair[1])
1068
+ }
1069
+
1049
1070
  function toJsirFileName(name) {
1050
1071
  name = trim(name)
1072
+ if (!name) {
1073
+ throw `invalid name`
1074
+ }
1051
1075
  if (isJsirFileName(name)) {
1052
1076
  return name;
1053
1077
  }
@@ -1059,14 +1083,13 @@ function toJsirFileName(name) {
1059
1083
  }
1060
1084
 
1061
1085
  function isJsirFileName(name) {
1062
- name = trim(name)
1063
- return /^[^.]*[^.\s]\.[^.\s]+$/.test(name)
1086
+ return /^[^./]*[^./\s]\.[^./\s]+$/.test(name)
1064
1087
  }
1065
1088
 
1066
1089
  function trimJsirFileName(name) {
1067
1090
  name = trim(name)
1068
1091
  if (isJsirFileName(name)) {
1069
- return trim(name.replace(/\.[^.\s]+$/, ''))
1092
+ return trim(name.replace(/\.[^./\s]+$/, ''))
1070
1093
  }
1071
1094
  return name
1072
1095
  }
@@ -1079,23 +1102,60 @@ function getJsirFileSuffix(name) {
1079
1102
  return ''
1080
1103
  }
1081
1104
 
1082
- function filterCmd(args){
1105
+ function initWorkspace(space) {
1106
+ let current = getConfig("workspace");
1107
+ if (current && space && current === space) {
1108
+ // 值没有改变
1109
+ return;
1110
+ }
1111
+ let workspace = space || current || 'local'
1112
+ if (workspace) {
1113
+ setConfig("workspace", workspace)
1114
+ global.$defaultSpace = workspace;
1115
+ } else {
1116
+ global.$defaultSpace = workspace;
1117
+ }
1118
+ }
1119
+
1120
+ function filterCmd(arg){
1121
+ arg = trim(arg)
1122
+ let spaceName
1123
+ if (arg.indexOf('/') !== -1) {
1124
+ let index = arg.indexOf('/');
1125
+ spaceName = arg.substring(0, index) || $defaultSpace
1126
+ arg = trim(arg.substring(index + 1))
1127
+ }
1128
+ let cmds = []
1129
+ for (let workspace of _workspaces) {
1130
+ let spaceTmp = getSpaceFromDir(workspace);
1131
+ if (!spaceName || spaceName === spaceTmp) {
1132
+ cmds.push(..._filterCmd(workspace, arg));
1133
+ }
1134
+ }
1135
+ return cmds;
1136
+ }
1137
+
1138
+ function _filterCmd(dirPath, arg) {
1083
1139
  let cmdMap = {}
1084
- let files = _fs.readdirSync(_home)
1085
- let i = 1
1140
+ let files = _fs.readdirSync(dirPath).filter(isJsirFileName)
1086
1141
  for (let file of files) {
1087
1142
  file = trim(file)
1088
- if (!isJsirFileName(file)) {
1089
- continue
1090
- }
1091
- isArgsMatch(file, args, () => {
1092
- if (Object.values(cmdMap).indexOf(file) === -1) {
1093
- cmdMap[i] = file
1094
- i ++
1095
- }
1096
- }, true)
1143
+ let uniqueName = toUniqueName(dirPath + '/' + file)
1144
+ isArgsMatch(file, [arg], () => {
1145
+ cmdMap[uniqueName] = null;
1146
+ }, true, file)
1097
1147
  }
1098
- return cmdMap
1148
+ return Object.keys(cmdMap)
1149
+ }
1150
+
1151
+ function getSpaceFromDir(dirPath) {
1152
+ return trim(trim(dirPath).split('/').map(trim).filter(i => i).reverse()[0])
1153
+ }
1154
+
1155
+ function parseUniqueName(uniqueName) {
1156
+ let pair = uniqueName.split('/').map(trim).filter(i => i)
1157
+ let len = pair.length;
1158
+ return [pair[len - 2], pair[len - 1]]
1099
1159
  }
1100
1160
 
1101
1161
  function getArgComments(argDef) {
@@ -1124,25 +1184,25 @@ function getArgComments(argDef) {
1124
1184
  return comments
1125
1185
  }
1126
1186
 
1127
- async function runCmd(str = '', scriptName = '', text = '') {
1128
- let path = _home + '/' + scriptName;
1129
- if (scriptName || text) {
1187
+ async function runCmd(str = '', uniqueName = '', text = '') {
1188
+ let path = getFullPath(uniqueName);
1189
+ if (uniqueName || text) {
1130
1190
  str = `0 ${str}`
1131
1191
  }
1132
1192
  if (!text) {
1133
1193
  let strs = str.split(/\s+/)
1134
- if (!scriptName) {
1194
+ if (!uniqueName) {
1135
1195
  if (!_cmdMap[strs[0]] && strs[0] !== '0') {
1136
1196
  warn('no items')
1137
1197
  return
1138
1198
  }
1139
1199
  if (_cmdMap[strs[0]]) {
1140
- scriptName = _cmdMap[strs[0]];
1200
+ uniqueName = _cmdMap[strs[0]];
1141
1201
  }
1142
1202
  }
1143
1203
 
1144
- if (scriptName) {
1145
- path = _home + '/' + scriptName;
1204
+ if (uniqueName) {
1205
+ path = getFullPath(uniqueName);
1146
1206
  text = String(_fs.readFileSync(path))
1147
1207
  } else {
1148
1208
  text = await getCbText()
@@ -1223,7 +1283,7 @@ async function runCmd(str = '', scriptName = '', text = '') {
1223
1283
  }
1224
1284
 
1225
1285
  process.argv = [process.argv[0], path, ...scriptArgs]
1226
- return await evalText(text, scriptName, scriptArgs)
1286
+ return await evalText(text, uniqueName, scriptArgs)
1227
1287
  }
1228
1288
 
1229
1289
  // 使用空格作为可执行的标志
@@ -1328,32 +1388,50 @@ function tipsOnRmCallback(key) {
1328
1388
  }
1329
1389
  }
1330
1390
 
1331
- async function _requireSource(cmdMatchStr, printLog = false) {
1391
+ function getCmdMd5Key(str) {
1392
+ return '0x' + md5(str).substr(0, 8);
1393
+ }
1394
+
1395
+ async function _requireSource(currSpace, cmdMatchStr, printLog = false) {
1332
1396
  cmdMatchStr = trim(cmdMatchStr);
1333
1397
  let nullable = false;
1334
1398
  if (cmdMatchStr.startsWith("*")) {
1335
1399
  nullable = true;
1336
1400
  cmdMatchStr = trim(cmdMatchStr.substr(1));
1337
1401
  }
1338
- if (_fs.existsSync(_home + '/' + cmdMatchStr)) {
1339
- cmdMatchStr = '0x' + md5(cmdMatchStr).substr(0, 8);
1340
- }
1341
1402
 
1342
- let cmdMap = filterCmd(cmdMatchStr.split(/\s+/))
1343
- if (Object.keys(cmdMap).length !== 1) {
1403
+ let cmds;
1404
+ let uName = toUniqueName(cmdMatchStr, currSpace)
1405
+ let pr = parseUniqueName(uName)
1406
+ let fullPath;
1407
+ if (!/^[eif]\s+/.test(pr[1])) {
1408
+ uName = pr[0] + "/i " + pr[1]
1409
+ fullPath = getFullPath(uName)
1410
+ }
1411
+ if (fullPath && _fs.existsSync(fullPath)) {
1412
+ cmds = [uName]
1413
+ } else {
1414
+ let appointSpace = parseUniqueName(cmdMatchStr)[0]
1415
+ cmds = filterCmd(cmdMatchStr);
1416
+ if (cmds.length > 0) {
1417
+ cmds = cmds.filter(cmd => parseUniqueName(cmd)[0] === (appointSpace || currSpace))
1418
+ }
1419
+ }
1420
+ if (cmds.length !== 1) {
1344
1421
  if (nullable) {
1345
1422
  return null;
1346
1423
  }
1347
- throw `none match: ${cmdMatchStr}`
1424
+ throw `none unique match: ${cmdMatchStr}`
1348
1425
  }
1349
- let cmdName = Object.values(cmdMap)[0];
1350
1426
 
1351
1427
  let result
1352
- let path = _home + '/' + cmdName
1428
+ let uniqueName = cmds[0];
1429
+ let path = getFullPath(uniqueName)
1353
1430
  let text = String(_fs.readFileSync(path))
1354
- if (cmdName.startsWith('i ')) {
1431
+ let pair = parseUniqueName(uniqueName)
1432
+ if (pair[1].startsWith('i ')) {
1355
1433
  try {
1356
- result = await evalText(text, cmdName)
1434
+ result = await evalText(text, uniqueName)
1357
1435
  } catch (e) {
1358
1436
  if (nullable) {
1359
1437
  warn(`require [${cmdMatchStr}] failed`)
@@ -1363,9 +1441,9 @@ async function _requireSource(cmdMatchStr, printLog = false) {
1363
1441
  throw e
1364
1442
  }
1365
1443
  }
1366
- } else if (cmdName.startsWith('e ')) {
1444
+ } else if (pair[1].startsWith('e ')) {
1367
1445
  result = async (argsStr) => {
1368
- return await runCmd(trim(argsStr), cmdName, text)
1446
+ return await runCmd(trim(argsStr), uniqueName, text)
1369
1447
  }
1370
1448
  }
1371
1449
  if (!vl(result)) {
@@ -1381,7 +1459,7 @@ async function _requireSource(cmdMatchStr, printLog = false) {
1381
1459
  let startTime = Date.now();
1382
1460
  let pl = () => {
1383
1461
  if (printLog) {
1384
- info(`${cmdName} finished in ${Date.now() - startTime}ms`)
1462
+ info(`${uniqueName} finished in ${Date.now() - startTime}ms`)
1385
1463
  }
1386
1464
  }
1387
1465
  try {
@@ -1392,7 +1470,7 @@ async function _requireSource(cmdMatchStr, printLog = false) {
1392
1470
  return Promise.resolve(result);
1393
1471
  }).catch(e => {
1394
1472
  pl();
1395
- return Promise.reject(errorTag(e, cmdName))
1473
+ return Promise.reject(errorTag(e, uniqueName))
1396
1474
  })
1397
1475
  } else {
1398
1476
  pl();
@@ -1400,18 +1478,18 @@ async function _requireSource(cmdMatchStr, printLog = false) {
1400
1478
  }
1401
1479
  } catch (e) {
1402
1480
  pl();
1403
- throw errorTag(e, cmdName);
1481
+ throw errorTag(e, uniqueName);
1404
1482
  }
1405
1483
  }
1406
1484
  }
1407
1485
  return result
1408
1486
  }
1409
1487
 
1410
- async function _requireSources(...matchItem) {
1488
+ async function _requireSources(currSpace, ...matchItems) {
1411
1489
  let result = []
1412
- for (let i = 0; i < matchItem.length; i++) {
1413
- let curr = matchItem[i]
1414
- let next = matchItem[i + 1]
1490
+ for (let i = 0; i < matchItems.length; i++) {
1491
+ let curr = matchItems[i]
1492
+ let next = matchItems[i + 1]
1415
1493
  if (typeof curr === 'number') {
1416
1494
  curr = '0x' + pad(8, BigNumber(curr).toString(16), '0');
1417
1495
  }
@@ -1419,20 +1497,30 @@ async function _requireSources(...matchItem) {
1419
1497
  next = '0x' + pad(8, BigNumber(next).toString(16), '0');
1420
1498
  }
1421
1499
  if (typeof curr === 'string' && typeof next !== "string") {
1422
- result.push(await _requireSource(curr, next))
1500
+ result.push(await _requireSource(currSpace, curr, next))
1423
1501
  i++
1424
1502
  } else if (typeof curr === 'string') {
1425
- result.push(await _requireSource(curr))
1503
+ result.push(await _requireSource(currSpace, curr))
1426
1504
  }
1427
1505
  }
1428
1506
  return result
1429
1507
  }
1430
1508
 
1431
1509
  async function evalText($text = '', $cmdName = '', $args = []) {
1510
+ let currSpace;
1511
+ if ($cmdName) {
1512
+ let pair = parseUniqueName($cmdName)
1513
+ currSpace = pair[0]
1514
+ } else {
1515
+ currSpace = $defaultSpace
1516
+ }
1517
+ let $require = async (...matchItems) => {
1518
+ return await _requireSources(currSpace, ...matchItems)
1519
+ }
1432
1520
  try {
1433
- return await evalCode($text, $cmdName, $args,
1434
- _home, _cmdMap, _requireSources, $data,
1435
- nextLine, nextText, setTips, delTips, wrapperInput, filterCmd)
1521
+ return await evalCode($text, $cmdName, $args, $require, $data,
1522
+ nextLine, nextText, setTips, delTips, wrapperInput, filterCmd,
1523
+ currSpace, $log, $draft, $config, $homeDir, $lib)
1436
1524
  } catch(e) {
1437
1525
  throw errorTag(e, $cmdName);
1438
1526
  }