@jdeighan/coffee-utils 10.0.11 → 10.0.14

Sign up to get free protection for your applications and to get access to all the features.
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@jdeighan/coffee-utils",
3
3
  "type": "module",
4
- "version": "10.0.11",
4
+ "version": "10.0.14",
5
5
  "description": "A set of utility functions for CoffeeScript",
6
6
  "main": "coffee_utils.js",
7
7
  "exports": {
@@ -22,6 +22,7 @@
22
22
  "./placeholders": "./src/placeholders.js",
23
23
  "./section": "./src/Section.js",
24
24
  "./sectionmap": "./src/SectionMap.js",
25
+ "./fsa": "./src/fsa.js",
25
26
  "./package.json": "./package.json"
26
27
  },
27
28
  "engines": {
@@ -6,6 +6,7 @@ import readline from 'readline'
6
6
  import {assert, error, croak} from '@jdeighan/unit-tester/utils'
7
7
  import {
8
8
  undef, pass, defined, isEmpty, isString, isArray, nonEmpty, rtrim,
9
+ escapeStr,
9
10
  } from '@jdeighan/coffee-utils'
10
11
 
11
12
  # ---------------------------------------------------------------------------
@@ -18,7 +18,8 @@ import {
18
18
  isString,
19
19
  isArray,
20
20
  nonEmpty,
21
- rtrim
21
+ rtrim,
22
+ escapeStr
22
23
  } from '@jdeighan/coffee-utils';
23
24
 
24
25
  // ---------------------------------------------------------------------------
@@ -21,6 +21,30 @@ export isComment = (line) ->
21
21
 
22
22
  # ---------------------------------------------------------------------------
23
23
 
24
+ export chomp = (str) ->
25
+
26
+ len = str.length
27
+ if (len == 0)
28
+ return ''
29
+ else if (len == 1)
30
+ if (str == "\r") || (str == "\n")
31
+ return ''
32
+ else
33
+ return str
34
+ else
35
+ # --- check the last 2 characters
36
+ tail = str.substring(len-2)
37
+ if (tail == "\r\n")
38
+ return str.substring(0, len-2)
39
+ else
40
+ tail = str.substring(len-1)
41
+ if (tail == "\n")
42
+ return str.substring(0, len-1)
43
+ else
44
+ return str
45
+
46
+ # ---------------------------------------------------------------------------
47
+
24
48
  export isSubclassOf = (subClass, superClass) ->
25
49
 
26
50
  return (subClass == superClass) \
@@ -61,6 +85,12 @@ export charCount = (str, ch) ->
61
85
 
62
86
  # ---------------------------------------------------------------------------
63
87
 
88
+ export oneof = (word, lWords...) ->
89
+
90
+ return (lWords.indexOf(word) >= 0)
91
+
92
+ # ---------------------------------------------------------------------------
93
+
64
94
  export isConstructor = (f) ->
65
95
 
66
96
  try
@@ -241,7 +271,10 @@ export pushCond = (lItems, item, doPush=notInArray) ->
241
271
 
242
272
  export words = (str) ->
243
273
 
244
- return str.trim().split(/\s+/)
274
+ str = str.trim()
275
+ if (str == '')
276
+ return []
277
+ return str.split(/\s+/)
245
278
 
246
279
  # ---------------------------------------------------------------------------
247
280
 
@@ -27,6 +27,34 @@ export var isComment = function(line) {
27
27
  return defined(lMatches);
28
28
  };
29
29
 
30
+ // ---------------------------------------------------------------------------
31
+ export var chomp = function(str) {
32
+ var len, tail;
33
+ len = str.length;
34
+ if (len === 0) {
35
+ return '';
36
+ } else if (len === 1) {
37
+ if ((str === "\r") || (str === "\n")) {
38
+ return '';
39
+ } else {
40
+ return str;
41
+ }
42
+ } else {
43
+ // --- check the last 2 characters
44
+ tail = str.substring(len - 2);
45
+ if (tail === "\r\n") {
46
+ return str.substring(0, len - 2);
47
+ } else {
48
+ tail = str.substring(len - 1);
49
+ if (tail === "\n") {
50
+ return str.substring(0, len - 1);
51
+ } else {
52
+ return str;
53
+ }
54
+ }
55
+ }
56
+ };
57
+
30
58
  // ---------------------------------------------------------------------------
31
59
  export var isSubclassOf = function(subClass, superClass) {
32
60
  return (subClass === superClass) || (subClass.prototype instanceof superClass);
@@ -65,6 +93,11 @@ export var charCount = function(str, ch) {
65
93
  return count;
66
94
  };
67
95
 
96
+ // ---------------------------------------------------------------------------
97
+ export var oneof = function(word, ...lWords) {
98
+ return lWords.indexOf(word) >= 0;
99
+ };
100
+
68
101
  // ---------------------------------------------------------------------------
69
102
  export var isConstructor = function(f) {
70
103
  var err;
@@ -168,13 +201,13 @@ export var isNonEmptyArray = function(x) {
168
201
 
169
202
  // ---------------------------------------------------------------------------
170
203
  export var isHash = function(x, lKeys) {
171
- var i, key, len;
204
+ var i, key, len1;
172
205
  if (!x || (getClassName(x) !== 'Object')) {
173
206
  return false;
174
207
  }
175
208
  if (defined(lKeys)) {
176
209
  assert(isArray(lKeys), "isHash(): lKeys not an array");
177
- for (i = 0, len = lKeys.length; i < len; i++) {
210
+ for (i = 0, len1 = lKeys.length; i < len1; i++) {
178
211
  key = lKeys[i];
179
212
  if (!x.hasOwnProperty(key)) {
180
213
  return false;
@@ -253,16 +286,20 @@ export var pushCond = function(lItems, item, doPush = notInArray) {
253
286
 
254
287
  // ---------------------------------------------------------------------------
255
288
  export var words = function(str) {
256
- return str.trim().split(/\s+/);
289
+ str = str.trim();
290
+ if (str === '') {
291
+ return [];
292
+ }
293
+ return str.split(/\s+/);
257
294
  };
258
295
 
259
296
  // ---------------------------------------------------------------------------
260
297
  export var isArrayOfHashes = function(lItems) {
261
- var i, item, len;
298
+ var i, item, len1;
262
299
  if (!isArray(lItems)) {
263
300
  return false;
264
301
  }
265
- for (i = 0, len = lItems.length; i < len; i++) {
302
+ for (i = 0, len1 = lItems.length; i < len1; i++) {
266
303
  item = lItems[i];
267
304
  if (!isHash(item)) {
268
305
  return false;
@@ -273,11 +310,11 @@ export var isArrayOfHashes = function(lItems) {
273
310
 
274
311
  // ---------------------------------------------------------------------------
275
312
  export var isArrayOfStrings = function(lItems) {
276
- var i, item, len;
313
+ var i, item, len1;
277
314
  if (!isArray(lItems)) {
278
315
  return false;
279
316
  }
280
- for (i = 0, len = lItems.length; i < len; i++) {
317
+ for (i = 0, len1 = lItems.length; i < len1; i++) {
281
318
  item = lItems[i];
282
319
  if (!isString(item)) {
283
320
  return false;
@@ -336,7 +373,7 @@ export var isInteger = function(x, hOptions = {}) {
336
373
 
337
374
  // ---------------------------------------------------------------------------
338
375
  export var isUniqueList = function(lItems, func = undef) {
339
- var h, i, item, len;
376
+ var h, i, item, len1;
340
377
  if (lItems == null) {
341
378
  return true; // empty list is unique
342
379
  }
@@ -344,7 +381,7 @@ export var isUniqueList = function(lItems, func = undef) {
344
381
  assert(isFunction(func), `Not a function: ${OL(func)}`);
345
382
  }
346
383
  h = {};
347
- for (i = 0, len = lItems.length; i < len; i++) {
384
+ for (i = 0, len1 = lItems.length; i < len1; i++) {
348
385
  item = lItems[i];
349
386
  if (defined(func) && !func(item)) {
350
387
  return false;
@@ -359,14 +396,14 @@ export var isUniqueList = function(lItems, func = undef) {
359
396
 
360
397
  // ---------------------------------------------------------------------------
361
398
  export var isUniqueTree = function(lItems, func = undef, hFound = {}) {
362
- var i, item, len;
399
+ var i, item, len1;
363
400
  if (isEmpty(lItems)) {
364
401
  return true; // empty list is unique
365
402
  }
366
403
  if (defined(func)) {
367
404
  assert(isFunction(func), `Not a function: ${OL(func)}`);
368
405
  }
369
- for (i = 0, len = lItems.length; i < len; i++) {
406
+ for (i = 0, len1 = lItems.length; i < len1; i++) {
370
407
  item = lItems[i];
371
408
  if (isArray(item)) {
372
409
  if (!isUniqueTree(item, func, hFound)) {
@@ -483,10 +520,10 @@ export var escapeStr = function(str, hEscape = hDefEsc) {
483
520
  var ch, lParts;
484
521
  assert(isString(str), "escapeStr(): not a string");
485
522
  lParts = (function() {
486
- var i, len, ref, results;
523
+ var i, len1, ref, results;
487
524
  ref = str.split('');
488
525
  results = [];
489
- for (i = 0, len = ref.length; i < len; i++) {
526
+ for (i = 0, len1 = ref.length; i < len1; i++) {
490
527
  ch = ref[i];
491
528
  if (hEscape[ch] != null) {
492
529
  results.push(hEscape[ch]);
@@ -530,9 +567,9 @@ export var extractMatches = function(line, regexp, convertFunc = undef) {
530
567
  var lConverted, lStrings, str;
531
568
  lStrings = [...line.matchAll(regexp)];
532
569
  lStrings = (function() {
533
- var i, len, results;
570
+ var i, len1, results;
534
571
  results = [];
535
- for (i = 0, len = lStrings.length; i < len; i++) {
572
+ for (i = 0, len1 = lStrings.length; i < len1; i++) {
536
573
  str = lStrings[i];
537
574
  results.push(str[0]);
538
575
  }
@@ -540,9 +577,9 @@ export var extractMatches = function(line, regexp, convertFunc = undef) {
540
577
  })();
541
578
  if (convertFunc != null) {
542
579
  lConverted = (function() {
543
- var i, len, results;
580
+ var i, len1, results;
544
581
  results = [];
545
- for (i = 0, len = lStrings.length; i < len; i++) {
582
+ for (i = 0, len1 = lStrings.length; i < len1; i++) {
546
583
  str = lStrings[i];
547
584
  results.push(convertFunc(str));
548
585
  }
@@ -556,14 +593,14 @@ export var extractMatches = function(line, regexp, convertFunc = undef) {
556
593
 
557
594
  // ---------------------------------------------------------------------------
558
595
  export var envVarsWithPrefix = function(prefix, hOptions = {}) {
559
- var h, i, key, len, plen, ref;
596
+ var h, i, key, len1, plen, ref;
560
597
  // --- valid options:
561
598
  // stripPrefix
562
599
  assert(prefix, "envVarsWithPrefix: empty prefix!");
563
600
  plen = prefix.length;
564
601
  h = {};
565
602
  ref = Object.keys(process.env);
566
- for (i = 0, len = ref.length; i < len; i++) {
603
+ for (i = 0, len1 = ref.length; i < len1; i++) {
567
604
  key = ref[i];
568
605
  if (key.indexOf(prefix) === 0) {
569
606
  if (hOptions.stripPrefix) {
@@ -594,9 +631,9 @@ export var getDateStr = function(date = undef) {
594
631
 
595
632
  // ---------------------------------------------------------------------------
596
633
  export var strcat = function(...lItems) {
597
- var i, item, len, str;
634
+ var i, item, len1, str;
598
635
  str = '';
599
- for (i = 0, len = lItems.length; i < len; i++) {
636
+ for (i = 0, len1 = lItems.length; i < len1; i++) {
600
637
  item = lItems[i];
601
638
  str += item.toString();
602
639
  }
package/src/fsa.coffee ADDED
@@ -0,0 +1,83 @@
1
+ # fsa.coffee
2
+
3
+ import {assert, croak} from '@jdeighan/unit-tester/utils'
4
+ import {
5
+ undef, defined, notdefined, words, isEmpty, nonEmpty,
6
+ isString, OL,
7
+ } from '@jdeighan/coffee-utils'
8
+ import {toArray} from '@jdeighan/coffee-utils/block'
9
+ import {LOG} from '@jdeighan/coffee-utils/log'
10
+ import {debug} from '@jdeighan/coffee-utils/debug'
11
+
12
+ # ---------------------------------------------------------------------------
13
+
14
+ export class FSA
15
+
16
+ constructor: (block) ->
17
+
18
+ debug "enter FSA()"
19
+ assert isString(block), "block not a string"
20
+ @hTransitions = {}
21
+ lLines = toArray(block, 'noEmptyLines')
22
+ debug 'lLines', lLines
23
+ for line,i in lLines
24
+ debug "LINE #{i}", line
25
+ lWords = words(line)
26
+ if (lWords.length == 3)
27
+ [bState, token, eState] = lWords
28
+ output = undef
29
+ else if (lWords.length == 4)
30
+ [bState, token, eState, output] = lWords
31
+ else
32
+ croak "Invalid desc: #{OL(line)}"
33
+ debug "LINE #{i}: #{OL(bState)} #{OL(token)} #{OL(eState)} #{OL(output)}"
34
+ assert nonEmpty(eState), "Invalid FSA description #{i}"
35
+
36
+ # --- tokens may be quoted (but may not contain whitespace),
37
+ # but the quotes are stripped
38
+ if (i == 0)
39
+ assert (bState == 'start'), "Invalid FSA description #{i}"
40
+ token = @fixToken(token)
41
+ debug 'token', token
42
+ if isEmpty(output)
43
+ output = undef
44
+ hTrans = @hTransitions[bState]
45
+ if notdefined(hTrans)
46
+ hTrans = @hTransitions[bState] = {}
47
+ assert notdefined(hTrans[token]), "Duplicate transition"
48
+ hTrans[token] = [eState, output]
49
+ debug 'hTransitions', @hTransitions
50
+ @curState = 'start'
51
+ debug "return from FSA()"
52
+
53
+ # ..........................................................
54
+
55
+ fixToken: (token) ->
56
+
57
+ if lMatches = token.match(/^\'(.*)\'$/)
58
+ return lMatches[1]
59
+ else if lMatches = token.match(/^\"(.*)\"$/)
60
+ return lMatches[1]
61
+ else
62
+ return token
63
+
64
+ # ..........................................................
65
+
66
+ got: (token) ->
67
+ # --- returns pair [newState, output]
68
+
69
+ hTrans = @hTransitions[@curState]
70
+ if notdefined(hTrans)
71
+ return [undef, undef]
72
+ result = hTrans[token]
73
+ if notdefined(result)
74
+ return [undef, undef]
75
+ [newState, output] = result
76
+ assert nonEmpty(newState), "Failed: #{@curState} -> #{token}"
77
+ @curState = newState
78
+ return result
79
+
80
+ # ..........................................................
81
+
82
+ state: () ->
83
+ return @curState
package/src/fsa.js ADDED
@@ -0,0 +1,111 @@
1
+ // Generated by CoffeeScript 2.7.0
2
+ // fsa.coffee
3
+ import {
4
+ assert,
5
+ croak
6
+ } from '@jdeighan/unit-tester/utils';
7
+
8
+ import {
9
+ undef,
10
+ defined,
11
+ notdefined,
12
+ words,
13
+ isEmpty,
14
+ nonEmpty,
15
+ isString,
16
+ OL
17
+ } from '@jdeighan/coffee-utils';
18
+
19
+ import {
20
+ toArray
21
+ } from '@jdeighan/coffee-utils/block';
22
+
23
+ import {
24
+ LOG
25
+ } from '@jdeighan/coffee-utils/log';
26
+
27
+ import {
28
+ debug
29
+ } from '@jdeighan/coffee-utils/debug';
30
+
31
+ // ---------------------------------------------------------------------------
32
+ export var FSA = class FSA {
33
+ constructor(block) {
34
+ var bState, eState, hTrans, i, j, lLines, lWords, len, line, output, token;
35
+ debug("enter FSA()");
36
+ assert(isString(block), "block not a string");
37
+ this.hTransitions = {};
38
+ lLines = toArray(block, 'noEmptyLines');
39
+ debug('lLines', lLines);
40
+ for (i = j = 0, len = lLines.length; j < len; i = ++j) {
41
+ line = lLines[i];
42
+ debug(`LINE ${i}`, line);
43
+ lWords = words(line);
44
+ if (lWords.length === 3) {
45
+ [bState, token, eState] = lWords;
46
+ output = undef;
47
+ } else if (lWords.length === 4) {
48
+ [bState, token, eState, output] = lWords;
49
+ } else {
50
+ croak(`Invalid desc: ${OL(line)}`);
51
+ }
52
+ debug(`LINE ${i}: ${OL(bState)} ${OL(token)} ${OL(eState)} ${OL(output)}`);
53
+ assert(nonEmpty(eState), `Invalid FSA description ${i}`);
54
+ // --- tokens may be quoted (but may not contain whitespace),
55
+ // but the quotes are stripped
56
+ if (i === 0) {
57
+ assert(bState === 'start', `Invalid FSA description ${i}`);
58
+ }
59
+ token = this.fixToken(token);
60
+ debug('token', token);
61
+ if (isEmpty(output)) {
62
+ output = undef;
63
+ }
64
+ hTrans = this.hTransitions[bState];
65
+ if (notdefined(hTrans)) {
66
+ hTrans = this.hTransitions[bState] = {};
67
+ }
68
+ assert(notdefined(hTrans[token]), "Duplicate transition");
69
+ hTrans[token] = [eState, output];
70
+ }
71
+ debug('hTransitions', this.hTransitions);
72
+ this.curState = 'start';
73
+ debug("return from FSA()");
74
+ }
75
+
76
+ // ..........................................................
77
+ fixToken(token) {
78
+ var lMatches;
79
+ if (lMatches = token.match(/^\'(.*)\'$/)) {
80
+ return lMatches[1];
81
+ } else if (lMatches = token.match(/^\"(.*)\"$/)) {
82
+ return lMatches[1];
83
+ } else {
84
+ return token;
85
+ }
86
+ }
87
+
88
+ // ..........................................................
89
+ got(token) {
90
+ var hTrans, newState, output, result;
91
+ // --- returns pair [newState, output]
92
+ hTrans = this.hTransitions[this.curState];
93
+ if (notdefined(hTrans)) {
94
+ return [undef, undef];
95
+ }
96
+ result = hTrans[token];
97
+ if (notdefined(result)) {
98
+ return [undef, undef];
99
+ }
100
+ [newState, output] = result;
101
+ assert(nonEmpty(newState), `Failed: ${this.curState} -> ${token}`);
102
+ this.curState = newState;
103
+ return result;
104
+ }
105
+
106
+ // ..........................................................
107
+ state() {
108
+ return this.curState;
109
+ }
110
+
111
+ };
@@ -173,7 +173,10 @@ export logItem = (label, item, pre='', itemPre=undef) ->
173
173
  LOG "pre = #{OL(pre)}"
174
174
  LOG "itemPre = #{OL(itemPre)}"
175
175
 
176
- labelStr = if label then "#{label} = " else ""
176
+ if label
177
+ labelStr = "#{label} = "
178
+ else
179
+ labelStr = ""
177
180
 
178
181
  if (item == undef)
179
182
  putstr "#{pre}#{labelStr}undef"
package/src/log_utils.js CHANGED
@@ -198,7 +198,11 @@ export var logItem = function(label, item, pre = '', itemPre = undef) {
198
198
  LOG(`pre = ${OL(pre)}`);
199
199
  LOG(`itemPre = ${OL(itemPre)}`);
200
200
  }
201
- labelStr = label ? `${label} = ` : "";
201
+ if (label) {
202
+ labelStr = `${label} = `;
203
+ } else {
204
+ labelStr = "";
205
+ }
202
206
  if (item === undef) {
203
207
  putstr(`${pre}${labelStr}undef`);
204
208
  } else if (item === null) {
package/src/taml.coffee CHANGED
@@ -4,7 +4,7 @@ import yaml from 'js-yaml'
4
4
 
5
5
  import {assert, error, croak} from '@jdeighan/unit-tester/utils'
6
6
  import {
7
- undef, oneline, isString,
7
+ undef, oneline, isString, chomp,
8
8
  } from '@jdeighan/coffee-utils'
9
9
  import {untabify, tabify, splitLine} from '@jdeighan/coffee-utils/indent'
10
10
  import {slurp} from '@jdeighan/coffee-utils/fs'
@@ -58,6 +58,19 @@ export taml = (text) ->
58
58
  debug "return from taml()"
59
59
  return yaml.load(arrayToBlock(lLines), {skipInvalid: true})
60
60
 
61
+ # ---------------------------------------------------------------------------
62
+
63
+ export fromTAML = taml
64
+
65
+ # ---------------------------------------------------------------------------
66
+
67
+ export toTAML = (x, useTabs=false) ->
68
+
69
+ str = yaml.dump(x, {indent:3})
70
+ if useTabs
71
+ str = str.replace(/ /g, "\t")
72
+ return "---\n" + chomp(str)
73
+
61
74
  # ---------------------------------------------------------------------------
62
75
  # slurpTAML - read TAML from a file
63
76
 
package/src/taml.js CHANGED
@@ -13,7 +13,8 @@ import {
13
13
  import {
14
14
  undef,
15
15
  oneline,
16
- isString
16
+ isString,
17
+ chomp
17
18
  } from '@jdeighan/coffee-utils';
18
19
 
19
20
  import {
@@ -84,6 +85,21 @@ export var taml = function(text) {
84
85
  });
85
86
  };
86
87
 
88
+ // ---------------------------------------------------------------------------
89
+ export var fromTAML = taml;
90
+
91
+ // ---------------------------------------------------------------------------
92
+ export var toTAML = function(x, useTabs = false) {
93
+ var str;
94
+ str = yaml.dump(x, {
95
+ indent: 3
96
+ });
97
+ if (useTabs) {
98
+ str = str.replace(/ /g, "\t");
99
+ }
100
+ return "---\n" + chomp(str);
101
+ };
102
+
87
103
  // ---------------------------------------------------------------------------
88
104
  // slurpTAML - read TAML from a file
89
105
  export var slurpTAML = function(filepath) {