jsir 1.2.9 → 1.3.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/ooa.js CHANGED
@@ -1,10 +1,12 @@
1
1
  #!/usr/bin/env node
2
2
  const {
3
- run, getLibDataDir, trim, regEach, getConfig, mkdir, requireG, reget,
3
+ run, getLibDataDir, trim, regEach, getConfig, mkdir, reget,
4
4
  getCbText, e, sleep, objDataFile, setConfig, vl, md5, BigNumber,
5
- info, warn, error, arrayDataFile, infoStr, warnStr, errorStr, errorStack,
6
- getInfo, ei, pad, msg, msgStr, isError, getType, tableStr, nableStr, objProfileRows
5
+ info, warn, error, arrayDataFile, infoStr, warnStr, errorStack,
6
+ getInfo, ei, pad, msgStr, getType, objProfileRows,
7
+ errorTag, isArgsMatch, draftQuery
7
8
  } = require('../util')
9
+ const evalCode = require('../evalCode')
8
10
 
9
11
  const _types = {
10
12
  'e': "exe",
@@ -19,12 +21,15 @@ const _args = process.argv.slice(2).map(trim)
19
21
  const _history9 = []
20
22
  const _tipsOnRm = {}
21
23
  const _setting = require('../setting')
24
+ const readline = require("readline");
22
25
  const _fileWatcherMap = {}
23
26
 
24
27
  let _cmdMap = {}
25
28
  let _rl
29
+ let _rlHistory = []
26
30
  let _haveWrapperInput = true
27
31
  let _repos = arrayDataFile('repos.json')
32
+ let _exit = false
28
33
 
29
34
  const $data = {}
30
35
 
@@ -38,27 +43,12 @@ try {
38
43
  error(e)
39
44
  }
40
45
 
41
- console.table = (...args) => {
42
- console.log(tableStr(...args))
43
- }
44
- console.nable = (rows) => {
45
- console.log(nableStr(rows))
46
- }
47
-
48
46
  let _noAppendNextLine = true
49
47
 
50
48
  const _mainCmdMap = {
51
49
  repl: {
52
50
  comment: "交互界面",
53
51
  },
54
- ls: {
55
- comment: "模糊搜索脚本",
56
- cmd: ['']
57
- },
58
- run: {
59
- comment: "执行脚本",
60
- cmd: ['']
61
- },
62
52
  add: {
63
53
  comment: "新增脚本",
64
54
  cmd: ['@e ']
@@ -129,8 +119,11 @@ function isMainCmd(mainList) {
129
119
  }
130
120
 
131
121
  async function initRuntime() {
132
- global.$lib = {...require('../util'), ...require('../ethWeb'),
133
- evalText
122
+ global.$lib = {...require('../util'), evalText}
123
+ let runtimeScript = 'e RUNTIME.js'
124
+ let runtimePath = getLibDataDir() + '/ooa/' + runtimeScript
125
+ if (_fs.existsSync(runtimePath)) {
126
+ await runCmd('', runtimeScript)
134
127
  }
135
128
  }
136
129
 
@@ -154,7 +147,7 @@ run(async () => {
154
147
  if (isMainCmd(['config'])) {
155
148
  let fileName = 'config.json';
156
149
  let configFile = getLibDataDir() + '/' + fileName;
157
- await e(`"${getFileOpenExe(fileName)}" "${configFile}"`)
150
+ ei('vi', [configFile])
158
151
  return
159
152
  }
160
153
 
@@ -163,13 +156,12 @@ run(async () => {
163
156
  if (isMainCmd(['repl'])) {
164
157
  await initRuntime()
165
158
  _noAppendNextLine = false
166
- nextLine()
167
159
  } else if (isMainCmd()){
168
160
  if (_noAppendNextLine) {
169
161
  _cmdMap = objDataFile('ooaCmdMap.json')
170
162
  }
171
163
 
172
- if (isMainCmd(['run', 'edit', 'rm', 'diff', 'push', 'pull', 'deps'])
164
+ if (isMainCmd(['edit', 'rm', 'diff', 'push', 'pull', 'deps'])
173
165
  && _args[1] && !/^\d+$/.test(_args[1])) {
174
166
  warn('wrong args')
175
167
  return
@@ -183,23 +175,15 @@ run(async () => {
183
175
  return
184
176
  }
185
177
 
186
- if (isMainCmd(['ls']) && _args[1] && /^\d+$/.test(_args[1])) {
187
- warn('wrong args')
188
- return
189
- }
190
-
191
178
  let argStr = _args.slice(1).map(i => {
192
179
  if (/\s+/.test(i) || !i) {
193
180
  i = `"${i}"`
194
181
  }
195
182
  return i
196
183
  }).join(' ').replace(/^@/, '')
197
- if (isMainCmd(['run', 'edit', 'rm', 'diff', 'push', 'pull', 'deps']) && !trim(argStr)) {
184
+ if (isMainCmd(['edit', 'rm', 'diff', 'push', 'pull', 'deps']) && !trim(argStr)) {
198
185
  _args[0] = '@'
199
186
  }
200
- if (isMainCmd(['ls']) && !trim(argStr)) {
201
- argStr = ','
202
- }
203
187
  if (isMainCmd(['file'])) {
204
188
  await initRuntime()
205
189
  }
@@ -211,7 +195,7 @@ run(async () => {
211
195
  } else {
212
196
  await wrapperInput(`${_args[0]}${argStr}`)
213
197
  }
214
- } else if (isMainCmd(['help'])) {
198
+ } else if (_args[0] && _args[0].startsWith('--')) {
215
199
  let cols = []
216
200
  for (let key of Object.keys(_mainCmdMap)) {
217
201
  cols.push({
@@ -244,97 +228,104 @@ run(async () => {
244
228
  }
245
229
  })
246
230
 
247
- async function getFileWatcher(fileName, workFile, text) {
248
- info("fileLine open " + workFile)
249
- if (!_fileWatcherMap[workFile]) {
250
- _fs.unlinkSync(workFile)
231
+ async function getFileWatcher(fileName, workFilePath, text) {
232
+ info("workFile open " + workFilePath)
233
+ if (!_fileWatcherMap[workFilePath]) {
234
+ _fs.unlinkSync(workFilePath)
251
235
  await sleep(1000)
252
- _fs.writeFileSync(workFile, text)
253
- let watcher = _chokidar.watch([workFile]);
254
- _fileWatcherMap[workFile] = watcher;
236
+ _fs.writeFileSync(workFilePath, text)
237
+ let watcher = _chokidar.watch([workFilePath]);
238
+ _fileWatcherMap[workFilePath] = watcher;
239
+ setTips("FILE", "FILE", () => {
240
+ Object.keys(_fileWatcherMap).forEach(closeFileWatcher);
241
+ })
255
242
  return watcher
256
243
  }
257
244
  }
258
- async function fileLine(name) {
245
+
246
+ function closeFileWatcher(workFilePath) {
247
+ let watcher = _fileWatcherMap[workFilePath]
248
+ info("workFile close " + workFilePath)
249
+ watcher.unwatch([workFilePath])
250
+ watcher.close()
251
+ delete _fileWatcherMap[workFilePath]
252
+ }
253
+
254
+ async function workFile(name) {
259
255
  name = trim(name)
260
256
  if (!name) {
261
- name = 'lineWorkFile'
257
+ name = 'workFile'
262
258
  }
263
259
  let fileName = `f ${toJsirFileName(name)}`
264
- let workFile = `${_home}/${fileName}`;
265
- if (!_fs.existsSync(workFile)) {
266
- _fs.writeFileSync(workFile, '');
260
+ let workFilePath = `${_home}/${fileName}`;
261
+ if (!_fs.existsSync(workFilePath)) {
262
+ _fs.writeFileSync(workFilePath, '');
267
263
  }
268
- let text = String(_fs.readFileSync(workFile))
269
- let watcher = await getFileWatcher(fileName, workFile, text)
270
- text = trim(text)
271
- let line = trim(getExeLine(text))
264
+ let text = String(_fs.readFileSync(workFilePath))
265
+ let watcher = await getFileWatcher(fileName, workFilePath, text)
266
+
272
267
  if (watcher) {
273
268
  watcher.on('change', async () => {
274
- let newText = trim(String(_fs.readFileSync(workFile)))
275
- let newLine = trim(getExeLine(newText))
276
- let tmpLine = line
277
- line = newLine
278
- if (newLine && newLine !== tmpLine) {
279
- let exeStrs
280
- if (newLine.startsWith('/*')) {
281
- exeStrs = newLine.split('\n').slice(1, -1).map(trim).filter(i => i)
282
- } else {
283
- exeStrs = ["#" + newLine]
284
- }
285
- for(let exeStr of exeStrs) {
286
- await wrapperInput(trim(exeStr))
269
+ let newText = String(_fs.readFileSync(workFilePath));
270
+ let exeStr = getExeStr(text, newText);
271
+ text = newText;
272
+ if (trim(exeStr)) {
273
+ try {
274
+ console.log("\n" + infoStr("------ workFile run ------"))
275
+ await evalText(exeStr)
276
+ } catch (e) {
277
+ error(e)
287
278
  }
288
279
  }
289
280
  }).on("unlink", () => {
290
- info("fileLine close " + workFile)
291
- watcher.unwatch([workFile])
292
- watcher.close()
293
- delete _fileWatcherMap[workFile]
281
+ closeFileWatcher(workFilePath);
294
282
  });
295
283
  }
296
- await e(`"${getFileOpenExe(fileName)}" "${workFile}"`)
284
+ await e(`"${getFileOpenExe(fileName)}" "${workFilePath}"`)
297
285
  }
298
286
 
299
- function getExeLine(text) {
300
- let lines = []
301
- let nLine = []
302
- let cLine = []
303
- for (let line of text.split("\n")
304
- .map(i => trim(i))
305
- .filter(i => i)) {
306
- if (lines.length > 1) {
307
- break
308
- }
309
- if (nLine.length > 0) {
310
- nLine.push(line)
311
- if (line.endsWith('*/')) {
312
- lines.push(nLine.join('\n'))
313
- nLine = []
314
- }
315
- continue
316
- }
287
+ function getExeStr(oldText, newText) {
288
+ let olds = oldText.split(/\n/).filter(i => trim(i));
289
+ let news = newText.split(/\n/).filter(i => trim(i));
317
290
 
318
- if (line.startsWith('/*')) {
319
- if (cLine.length > 0) {
320
- lines.push(cLine.join('\n'))
321
- cLine = []
322
- }
291
+ if (olds.length !== news.length) {
292
+ return ;
293
+ }
323
294
 
324
- if (!line.endsWith('*/')) {
325
- nLine.push(line)
295
+ let reg = /^\/\/\s*jsir(\s+.+)?$/;
296
+
297
+ let lineChange = false
298
+ let flagChange = false
299
+ let currText = []
300
+ for (let i = 0; i < news.length; i++) {
301
+ if (!flagChange && lineChange) {
302
+ break;
303
+ }
304
+ let oldLine = olds[i];
305
+ let newLine = news[i];
306
+ if (reg.test(trim(newLine))) {
307
+ if (flagChange) {
308
+ break;
309
+ }
310
+ if (reg.test(trim(oldLine))) {
311
+ if (trim(oldLine).split(/jsir/)[0] !== trim(newLine).split(/jsir/)[0]) {
312
+ flagChange = true
313
+ }
326
314
  } else {
327
- lines.push("")
315
+ break;
328
316
  }
329
- continue
317
+ currText = []
318
+ } else {
319
+ currText.push(newLine)
330
320
  }
331
321
 
332
- cLine.push(line)
322
+ if (oldLine !== newLine) {
323
+ lineChange = true;
324
+ }
333
325
  }
334
- if (cLine.length > 0) {
335
- lines.push(cLine.join('\n'))
326
+ if (flagChange) {
327
+ return currText.join("\n")
336
328
  }
337
- return lines[1]
338
329
  }
339
330
 
340
331
  async function nextLine(callback, preStr, hidden) {
@@ -343,13 +334,8 @@ async function nextLine(callback, preStr, hidden) {
343
334
  })
344
335
  }
345
336
 
346
- function _nextLine(callback, preStr, hidden, resolve, end) {
347
- end = trim(end)
348
- if (!_haveWrapperInput) {
349
- return
350
- }
337
+ function initRl(callback, preStr, hidden) {
351
338
  if (!_rl) {
352
- let readline = require('readline')
353
339
  _rl = readline.createInterface({
354
340
  input: process.stdin,
355
341
  output: process.stdout
@@ -363,23 +349,49 @@ function _nextLine(callback, preStr, hidden, resolve, end) {
363
349
  nextLine();
364
350
  }
365
351
  });
352
+ _rl.history = _rlHistory
366
353
  }
367
- _haveWrapperInput = false
368
354
 
369
- _rl._writeToOutput = function _writeToOutput(stringToWrite){
370
- if(hidden && stringToWrite.indexOf("\n") === -1 && stringToWrite !== promitStr){
371
- if (stringToWrite.indexOf(promitStr) === -1) {
372
- _rl.output.write("*");
355
+ let repoTip = trim(trim(getConfig("jsLibSource")).split('/').map(trim).reverse().filter(i => i)[0])
356
+ let promptStr = preStr
357
+ if (promptStr !== '') {
358
+ promptStr = (preStr
359
+ || ((callback && callback !== wrapperInput) ? "-> ":"")
360
+ || [Object.values(global.$tips).filter(i => String(i)).join(','), repoTip].filter(i => i).join(':') + `> `)
361
+ promptStr = infoStr(promptStr)
362
+ }
363
+ if (hidden) {
364
+ _rl._writeToOutput = function _writeToOutput(stringToWrite){
365
+ if(hidden && stringToWrite.indexOf("\n") === -1 && stringToWrite !== promptStr){
366
+ if (stringToWrite.indexOf(promptStr) === -1) {
367
+ _rl.output.write("*");
368
+ } else {
369
+ _rl.output.write(promptStr + stringToWrite.replace(promptStr, '').replace(/[\s\S]/g, '*'));
370
+ }
373
371
  } else {
374
- _rl.output.write(promitStr + stringToWrite.replace(promitStr, '').replace(/[\s\S]/g, '*'));
372
+ _rl.output.write(stringToWrite);
375
373
  }
376
- } else {
377
- _rl.output.write(stringToWrite);
378
374
  }
379
375
  }
380
- _rl.removeAllListeners('line')
376
+
377
+ _rl.setPrompt(promptStr);
378
+ }
379
+
380
+ function closeRl() {
381
+ _rlHistory = _rl.history;
382
+ _rl.close();
383
+ _rl = null;
384
+ }
385
+
386
+ function _nextLine(callback, preStr, hidden, resolve, end) {
387
+ end = trim(end)
388
+ if (!_haveWrapperInput) {
389
+ return
390
+ }
391
+ initRl(callback, preStr, hidden);
392
+ _haveWrapperInput = false
381
393
  let inputStr = ''
382
- _rl.on('line', async line => {
394
+ let lineHander = async line => {
383
395
  let textLine = line
384
396
  line = trim(line)
385
397
  if (end) {
@@ -388,37 +400,40 @@ function _nextLine(callback, preStr, hidden, resolve, end) {
388
400
  }
389
401
  } else {
390
402
  inputStr = line
403
+ if (/^\s+$/.test(textLine) && (!callback || wrapperInput === callback)) {
404
+ console.clear();
405
+ listCmd();
406
+ }
391
407
  }
392
408
  if (line && (hidden || (callback && callback !== wrapperInput))) {
393
409
  _rl.history = _rl.history.slice(1)
394
410
  }
395
411
  if (!end || line === end) {
396
412
  _haveWrapperInput = true;
397
- if (_noAppendNextLine && _rl) {
398
- _rl.close()
399
- _rl = null
400
- }
413
+ closeRl()
401
414
  inputStr = inputStr.replace(/\s+$/, '');
402
415
 
403
416
  let pro = (callback || wrapperInput)(inputStr);
404
417
 
405
418
  resolve && resolve(inputStr);
419
+ let currCallback = callback;
406
420
  callback = null;
407
421
  hidden = false;
408
422
  end = null;
409
423
  inputStr = '';
410
- await pro;
424
+
425
+ try {
426
+ await pro;
427
+ } finally {
428
+ if ((currCallback || wrapperInput) === wrapperInput) {
429
+ _noAppendNextLine || nextLine()
430
+ }
431
+ }
411
432
  }
412
- })
413
- let repoTip = trim(trim(getConfig("jsLibSource")).split('/').map(trim).reverse().filter(i => i)[0])
414
- let promitStr = preStr
415
- if (promitStr !== '') {
416
- promitStr = (preStr
417
- || ((callback && callback !== wrapperInput) ? "-> ":"")
418
- || [Object.values(global.$tips).filter(i => String(i)).join(','), repoTip].filter(i => i).join(':') + `> `)
419
- promitStr = infoStr(promitStr)
420
433
  }
421
- _rl.setPrompt(promitStr);
434
+
435
+ _rl.removeAllListeners('line')
436
+ _rl.on('line', lineHander)
422
437
  _rl.prompt()
423
438
  }
424
439
 
@@ -556,7 +571,10 @@ function listCmd(prefixKey, inputCmdMap) {
556
571
  }
557
572
  }
558
573
  let items = Object.values(currCmdMap)
559
- .filter(item => _fs.existsSync(_home + "/" + item) && (!prefixKey || prefixMap[item].indexOf(prefixKey) !== -1))
574
+ .filter(item => _fs.existsSync(_home + "/" + item)
575
+ && ((prefixKey === '' && prefixMap[item].filter(i => trim(i)).length <= 0)
576
+ || (trim(prefixKey) && prefixMap[item].indexOf(trim(prefixKey)) !== -1)
577
+ || (!prefixKey && prefixKey !== '')))
560
578
  .sort((a,b) => {
561
579
  let typeKeys = Object.keys(_types);
562
580
  let orderA = typeKeys.indexOf(a.split(/\s+/)[0]);
@@ -598,7 +616,7 @@ function listCmd(prefixKey, inputCmdMap) {
598
616
  if (!text) {
599
617
  text = String(_fs.readFileSync(_home + "/" + currCmdMap[i]))
600
618
  }
601
- getComments(currCmdMap[i], text, items, item)
619
+ getComments(i, currCmdMap[i], text, items, item)
602
620
  }
603
621
  if (Object.keys(items).length === 0) {
604
622
  warn("no items")
@@ -616,48 +634,6 @@ function listCmd(prefixKey, inputCmdMap) {
616
634
  }
617
635
  }
618
636
 
619
- function draftQuery(fLine) {
620
- let lines = []
621
- let text = String(_fs.readFileSync(getLibDataDir() + "/log/draft.log"))
622
- let temp = []
623
- for (let line of text.split("\n")) {
624
- if (!trim(line)) {
625
- continue
626
- }
627
- if (line.startsWith("---------")) {
628
- if (temp.length > 0) {
629
- lines.push(temp.join('\n'))
630
- }
631
- temp = []
632
- temp.push(warnStr(line))
633
- } else {
634
- temp.push(line)
635
- }
636
- }
637
- if (temp.length > 0) {
638
- lines.push(temp.join('\n'))
639
- }
640
-
641
- let results = []
642
- if (!/^\d+$/.test(fLine)) {
643
- let ss = fLine.split(/\s+/)
644
- fLine = ss[0]
645
- for (let line of lines) {
646
- if (new RegExp(fLine, 'i').test(line)) {
647
- results.push(line)
648
- }
649
- }
650
- fLine = ss[1]
651
- lines = results
652
- results = []
653
- }
654
- if (fLine && /^\d+$/.test(fLine)) {
655
- let index = Math.abs(parseInt(fLine));
656
- results.push(...lines.slice(- index))
657
- }
658
- console.log(results.join("\n"))
659
- }
660
-
661
637
  async function wrapperInput(str) {
662
638
  try {
663
639
  await _wrapperInput(str);
@@ -672,31 +648,23 @@ async function _wrapperInput(str) {
672
648
 
673
649
  str = trim(str)
674
650
  if (!str) {
675
- _noAppendNextLine || nextLine()
676
651
  return;
677
652
  }
678
- if (/^[&]/.test(str)) {
679
- _rl.removeAllListeners('line');
680
- try {
681
- let cmdStr = trim(str.substr(1));
682
- if (/^\d+$/.test(cmdStr) && _cmdMap[cmdStr]) {
683
- if (_cmdMap[cmdStr]) {
684
- ei('vi', [getLibDataDir() + '/ooa/' + _cmdMap[cmdStr]])
685
- } else {
686
- warn("no items")
687
- }
688
- } else if (cmdStr) {
689
- ei(cmdStr.split(/\s+/)[0],
690
- enrichArgs(trim(cmdStr.replace(/^\S+/, ''))).map(trim));
653
+ if (/^&/.test(str)) {
654
+ let cmdStr = trim(str.substr(1));
655
+ if (/^\d+$/.test(cmdStr) && _cmdMap[cmdStr]) {
656
+ if (_cmdMap[cmdStr]) {
657
+ ei('vi', [getLibDataDir() + '/ooa/' + _cmdMap[cmdStr]])
691
658
  } else {
692
- ei('vi', ['-n'])
659
+ warn("no items")
693
660
  }
694
- return;
695
- } finally {
696
- _noAppendNextLine || nextLine()
661
+ } else if (cmdStr) {
662
+ ei(cmdStr.split(/\s+/)[0],
663
+ enrichArgs(trim(cmdStr.replace(/^\S+/, ''))).map(trim));
664
+ } else {
665
+ ei('vi', ['-n'])
697
666
  }
698
- }
699
- if (/^[`'"]/.test(str)) {
667
+ } else if (/^[`'"]/.test(str)) {
700
668
  let fstr = str.substr(0, 1);
701
669
  if (fstr === '`') {
702
670
  let text = str.substr(1) + "\n" + await nextText(line => line, fstr)
@@ -704,17 +672,13 @@ async function _wrapperInput(str) {
704
672
  } else {
705
673
  let fLine = trim(str.substr(1))
706
674
  if (fLine) {
707
- draftQuery(fLine)
675
+ console.log(draftQuery(fLine).join("\n"))
708
676
  } else {
709
677
  let text = str.substr(1) + "\n" + await nextText(line => line, fstr)
710
678
  $draft(text)
711
679
  }
712
- _noAppendNextLine || nextLine()
713
680
  }
714
- return;
715
- }
716
-
717
- if (/^[$#*]/.test(str)) {
681
+ } else if (/^[$#*]/.test(str)) {
718
682
  let is$ = str.startsWith('$')
719
683
  let isStar = str.startsWith('*')
720
684
  let text = trim(str.replace(/^[$#*]/, ''))
@@ -756,11 +720,9 @@ async function _wrapperInput(str) {
756
720
  } else {
757
721
  listCmd()
758
722
  }
759
- _noAppendNextLine || nextLine()
760
723
  } else if (!str.split(/\s+/)[0].match(/^\d+$/)) {
761
724
  _cmdMap = filterCmd(str.split(/\s+/))
762
725
  listCmd()
763
- _noAppendNextLine || nextLine()
764
726
  } else {
765
727
  let strs = str.split(/\s+/)
766
728
  if (_cmdMap[strs[0]]) {
@@ -769,10 +731,9 @@ async function _wrapperInput(str) {
769
731
  let fileName = trim(_cmdMap[strs[0]]);
770
732
  let firstName = fileName.split(/\s+/)[0]
771
733
  if (firstName === 'f') {
772
- await fileLine(fileName.replace(/^\s*f\s*/, ''))
734
+ await workFile(fileName.replace(/^\s*f\s*/, ''))
773
735
  } else if (firstName !== 'e') {
774
736
  console.log(String(_fs.readFileSync(path)));
775
- _noAppendNextLine || nextLine()
776
737
  } else {
777
738
  await runCmd(str)
778
739
  }
@@ -782,8 +743,29 @@ async function _wrapperInput(str) {
782
743
  }
783
744
  }
784
745
 
746
+ function delTipsByIndex(idxs) {
747
+ let keys = Object.keys($tips)
748
+ let indexKeyMap = {}
749
+ for(let i = 1;i<=keys.length;i++) {
750
+ indexKeyMap[i] = keys[i - 1]
751
+ }
752
+ let params = []
753
+ for (const index of idxs) {
754
+ if ($tips.hasOwnProperty(index)) {
755
+ params.push(index)
756
+ } else if (indexKeyMap[Number(index)]) {
757
+ params.push(indexKeyMap[Number(index)])
758
+ } else if (indexKeyMap[keys.length + 1 + Number(index)]) {
759
+ params.push(indexKeyMap[keys.length + 1 + Number(index)])
760
+ }
761
+ }
762
+ delTips(...params)
763
+ }
764
+
785
765
  async function dealKeyword(str, strs, fstr, ostr) {
786
- if (/^\d+$/.test(fstr)) {
766
+ if (fstr.startsWith("<")) {
767
+ delTipsByIndex([fstr, ...ostr].join(" ").replace(/^</, '').split(/\s+/).filter(i => i))
768
+ } else if (/^\d+$/.test(fstr)) {
787
769
  if (!_cmdMap[fstr]) {
788
770
  warn("no items")
789
771
  } else {
@@ -904,6 +886,8 @@ async function dealKeyword(str, strs, fstr, ostr) {
904
886
  warn('require config.jsLibSource')
905
887
  }
906
888
  }
889
+ }else if (fstr === '!') {
890
+ listCmd('')
907
891
  } else if (/^w\d*$/.test(fstr)) {
908
892
  let name = _cmdMap[trim(fstr.replace(/^w/, ''))]
909
893
  if (!name) {
@@ -941,7 +925,7 @@ async function dealKeyword(str, strs, fstr, ostr) {
941
925
  hisToCmdMap()
942
926
  listCmd()
943
927
  } else if (fstr === 'f') {
944
- await fileLine(trim(ostr.join(' ')))
928
+ await workFile(trim(ostr.join(' ')))
945
929
  } else if (fstr === '%') {
946
930
  let newRepo = trim(ostr[0])
947
931
  let currRepo = getConfig('jsLibSource');
@@ -969,9 +953,9 @@ async function dealKeyword(str, strs, fstr, ostr) {
969
953
  warn(`repo ${newRepo} not exist`)
970
954
  }
971
955
  }
972
- _noAppendNextLine || nextLine()
973
956
  } else if (fstr === 'q') {
974
957
  console.log("Bye!")
958
+ _exit = true;
975
959
  process.exit(0)
976
960
  } else {
977
961
  await save(strs)
@@ -1017,8 +1001,8 @@ function getScriptRequires(scriptName) {
1017
1001
  return md5Keys
1018
1002
  }
1019
1003
 
1020
- function getComments(cmdName, text, cols = [], col) {
1021
- let docLines = [infoStr('0x' + md5(cmdName).substr(0, 8))]
1004
+ function getComments(i, cmdName, text, cols = [], col) {
1005
+ let docLines = [infoStr('0x' + md5(cmdName).substr(0, 8)) + " - " + infoStr(i)]
1022
1006
  text = trim(text)
1023
1007
  if (text.startsWith("/*")) {
1024
1008
  for (let line of text.split("\n")) {
@@ -1103,28 +1087,6 @@ function filterCmd(args){
1103
1087
  return cmdMap
1104
1088
  }
1105
1089
 
1106
- function isArgsMatch(text, args, callback, useMd5) {
1107
- let match = false
1108
- for (let arg of args) {
1109
- let r = true
1110
- for (let str of arg.split(',').filter(item => trim(item) !== '')) {
1111
- let reg = new RegExp(str, 'i')
1112
- if (!reg.test(text) && !(useMd5 && ('0x' + md5(text).substr(0, 8)) === str)) {
1113
- r = false
1114
- break
1115
- }
1116
- }
1117
- if (r) {
1118
- match = true
1119
- break
1120
- }
1121
- }
1122
- if (match && callback) {
1123
- callback()
1124
- }
1125
- return match
1126
- }
1127
-
1128
1090
  function getArgComments(argDef) {
1129
1091
  let comments = []
1130
1092
  let keys = Object.keys(argDef)
@@ -1160,7 +1122,6 @@ async function runCmd(str = '', scriptName = '', text = '') {
1160
1122
  if (!scriptName) {
1161
1123
  if (!_cmdMap[strs[0]] && strs[0] !== '0') {
1162
1124
  warn('no items')
1163
- _noAppendNextLine || nextLine()
1164
1125
  return
1165
1126
  }
1166
1127
  if (_cmdMap[strs[0]]) {
@@ -1191,9 +1152,9 @@ async function runCmd(str = '', scriptName = '', text = '') {
1191
1152
  let arg = oriArgs[i]
1192
1153
  let needTrans
1193
1154
  let pair
1194
- if (arg.endsWith(":")) {
1195
- arg = arg.replace(/:$/, '')
1196
- if (oriArgs[i+1] && !oriArgs[i+1].endsWith(":")) {
1155
+ if (arg.startsWith(":") || arg.startsWith("_")) {
1156
+ arg = arg.replace(/^:/, '')
1157
+ if (oriArgs[i+1] && !(oriArgs[i+1].startsWith(":") || oriArgs[i+1].startsWith("_"))) {
1197
1158
  pair = [arg, oriArgs[i+1]]
1198
1159
  i++
1199
1160
  } else {
@@ -1404,11 +1365,11 @@ async function _requireSource(cmdMatchStr, ignoreLog = false) {
1404
1365
  try {
1405
1366
  resp = tmp(...args)
1406
1367
  } catch (e) {
1407
- throw _errorAppend(e, cmdName);
1368
+ throw errorTag(e, cmdName);
1408
1369
  }
1409
1370
  if (getType(resp) === 'Promise') {
1410
1371
  return resp.catch(e => {
1411
- return Promise.reject(_errorAppend(e, cmdName))
1372
+ return Promise.reject(errorTag(e, cmdName))
1412
1373
  })
1413
1374
  } else {
1414
1375
  return resp;
@@ -1439,46 +1400,10 @@ async function _requireSources(...matchItem) {
1439
1400
  return result
1440
1401
  }
1441
1402
 
1442
- function _errorAppend(e, $cmdName) {
1443
- if (!$cmdName) {
1444
- return e;
1445
- }
1446
- if (!isError(e)) {
1447
- e = new Error(e)
1448
- e.stack = e.stack.split(/\n/)[0]
1449
- }
1450
- e.stack = e.stack + `\n at ${$cmdName}`
1451
- return e
1452
- }
1453
-
1454
1403
  function evalText($text = '', $cmdName = '', $args = []) {
1455
- const require = requireG;
1456
- const $nextLine = nextLine;
1457
- const $nextText = nextText;
1458
- const $setTips = setTips;
1459
- const $delTips = delTips;
1460
- const $info = info;
1461
- const $msg = msg;
1462
- const $warn = warn;
1463
- const $error = error;
1464
- const $infoStr = infoStr;
1465
- const $msgStr = msgStr;
1466
- const $warnStr = warnStr;
1467
- const $errorStr = errorStr;
1468
- const $cmdDir = _home;
1469
- const $cmdMap = _cmdMap;
1470
- const $defArgs = () => $args;
1471
- const $require = _requireSources;
1472
- const $tableStr = tableStr;
1473
- const $nableStr = nableStr;
1474
- const $table = console.table;
1475
- const $nable = console.nable;
1476
-
1477
- return eval(`(async ()=>{try {${$text};
1478
- } catch(e) {
1479
- throw _errorAppend(e, $cmdName);
1480
- }
1481
- })()`)
1404
+ return evalCode($text, $cmdName, $args,
1405
+ _home, _cmdMap, _requireSources, $data,
1406
+ nextLine, nextText, setTips, delTips, wrapperInput)
1482
1407
  }
1483
1408
 
1484
1409
  process.on('uncaughtException',function(err){
@@ -1493,3 +1418,15 @@ process.on('rejectionHandled',function(err){
1493
1418
  error(err, 'rejectionHandled')
1494
1419
  _noAppendNextLine || nextLine()
1495
1420
  })
1421
+ process.on('SIGINT', function () {
1422
+ if (_noAppendNextLine) {
1423
+ process.exit();
1424
+ } else {
1425
+ nextLine();
1426
+ }
1427
+ });
1428
+ process.on('beforeExit', function () {
1429
+ if (!_exit) {
1430
+ _noAppendNextLine || nextLine();
1431
+ }
1432
+ });