@jdeighan/coffee-utils 7.0.49 → 7.0.52

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/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@jdeighan/coffee-utils",
3
3
  "type": "module",
4
- "version": "7.0.49",
4
+ "version": "7.0.52",
5
5
  "description": "A set of utility functions for CoffeeScript",
6
6
  "main": "coffee_utils.js",
7
7
  "exports": {
@@ -52,6 +52,6 @@
52
52
  "svelte": "^3.48.0"
53
53
  },
54
54
  "devDependencies": {
55
- "@jdeighan/unit-tester": "^2.0.3"
55
+ "@jdeighan/unit-tester": "^2.0.5"
56
56
  }
57
57
  }
package/src/arrow.coffee CHANGED
@@ -1,5 +1,9 @@
1
1
  # arrow.coffee
2
2
 
3
+ import {undef, OL, setCharsAt} from '@jdeighan/coffee-utils'
4
+
5
+ # --- We use spaces here because Windows Terminal handles TAB chars badly
6
+
3
7
  export vbar = '│' # unicode 2502
4
8
  export hbar = '─' # unicode 2500
5
9
  export corner = '└' # unicode 2514
@@ -8,18 +12,22 @@ export space = ' '
8
12
 
9
13
  export oneIndent = vbar + space + space + space
10
14
  export arrow = corner + hbar + arrowhead + space
11
- export fourSpaces = space + space + space + space
15
+ export clearIndent = space + space + space + space
12
16
 
13
17
  # ---------------------------------------------------------------------------
14
18
 
15
19
  export getPrefix = (level, option='none') ->
16
20
 
17
- if level==0 then return ''
21
+ if level==0
22
+ if (option == 'object')
23
+ return clearIndent
24
+ else
25
+ return ''
18
26
  switch option
19
27
  when 'withArrow'
20
28
  result = oneIndent.repeat(level-1) + arrow
21
- when 'returnVal'
22
- result = oneIndent.repeat(level-1) + fourSpaces
29
+ when 'object'
30
+ result = oneIndent.repeat(level) + clearIndent
23
31
  when 'none'
24
32
  result = oneIndent.repeat(level)
25
33
  else
@@ -27,3 +35,31 @@ export getPrefix = (level, option='none') ->
27
35
  if result.length % 4 != 0
28
36
  throw new Error("getPrefix(): Bad prefix '#{result}'")
29
37
  return result
38
+
39
+ # ---------------------------------------------------------------------------
40
+
41
+ export addArrow = (prefix) ->
42
+
43
+ # console.log "in addArrow(#{OL(prefix)})"
44
+ pos = prefix.lastIndexOf(vbar)
45
+ # console.log "pos = #{pos}"
46
+ if (pos == -1)
47
+ result = prefix
48
+ else
49
+ result = setCharsAt(prefix, pos, arrow)
50
+ # console.log "result = #{OL(result)}"
51
+ return result
52
+
53
+ # ---------------------------------------------------------------------------
54
+
55
+ export removeLastVbar = (prefix) ->
56
+
57
+ # console.log "in removeLastVbar(#{OL(prefix)})"
58
+ pos = prefix.lastIndexOf(vbar)
59
+ # console.log "pos = #{pos}"
60
+ if (pos == -1)
61
+ result = prefix
62
+ else
63
+ result = setCharsAt(prefix, pos, ' ')
64
+ # console.log "result = #{OL(result)}"
65
+ return result
package/src/arrow.js CHANGED
@@ -1,5 +1,12 @@
1
1
  // Generated by CoffeeScript 2.7.0
2
- // arrow.coffee
2
+ // arrow.coffee
3
+ import {
4
+ undef,
5
+ OL,
6
+ setCharsAt
7
+ } from '@jdeighan/coffee-utils';
8
+
9
+ // --- We use spaces here because Windows Terminal handles TAB chars badly
3
10
  export var vbar = '│'; // unicode 2502
4
11
 
5
12
  export var hbar = '─'; // unicode 2500
@@ -14,20 +21,24 @@ export var oneIndent = vbar + space + space + space;
14
21
 
15
22
  export var arrow = corner + hbar + arrowhead + space;
16
23
 
17
- export var fourSpaces = space + space + space + space;
24
+ export var clearIndent = space + space + space + space;
18
25
 
19
26
  // ---------------------------------------------------------------------------
20
27
  export var getPrefix = function(level, option = 'none') {
21
28
  var result;
22
29
  if (level === 0) {
23
- return '';
30
+ if (option === 'object') {
31
+ return clearIndent;
32
+ } else {
33
+ return '';
34
+ }
24
35
  }
25
36
  switch (option) {
26
37
  case 'withArrow':
27
38
  result = oneIndent.repeat(level - 1) + arrow;
28
39
  break;
29
- case 'returnVal':
30
- result = oneIndent.repeat(level - 1) + fourSpaces;
40
+ case 'object':
41
+ result = oneIndent.repeat(level) + clearIndent;
31
42
  break;
32
43
  case 'none':
33
44
  result = oneIndent.repeat(level);
@@ -40,3 +51,33 @@ export var getPrefix = function(level, option = 'none') {
40
51
  }
41
52
  return result;
42
53
  };
54
+
55
+ // ---------------------------------------------------------------------------
56
+ export var addArrow = function(prefix) {
57
+ var pos, result;
58
+ // console.log "in addArrow(#{OL(prefix)})"
59
+ pos = prefix.lastIndexOf(vbar);
60
+ // console.log "pos = #{pos}"
61
+ if (pos === -1) {
62
+ result = prefix;
63
+ } else {
64
+ result = setCharsAt(prefix, pos, arrow);
65
+ }
66
+ // console.log "result = #{OL(result)}"
67
+ return result;
68
+ };
69
+
70
+ // ---------------------------------------------------------------------------
71
+ export var removeLastVbar = function(prefix) {
72
+ var pos, result;
73
+ // console.log "in removeLastVbar(#{OL(prefix)})"
74
+ pos = prefix.lastIndexOf(vbar);
75
+ // console.log "pos = #{pos}"
76
+ if (pos === -1) {
77
+ result = prefix;
78
+ } else {
79
+ result = setCharsAt(prefix, pos, ' ');
80
+ }
81
+ // console.log "result = #{OL(result)}"
82
+ return result;
83
+ };
@@ -1,6 +1,8 @@
1
1
  # call_stack.coffee
2
2
 
3
- import {undef, croak, assert} from '@jdeighan/coffee-utils'
3
+ import {
4
+ undef, defined, croak, assert, OL, isBoolean, escapeStr,
5
+ } from '@jdeighan/coffee-utils'
4
6
  import {log, LOG} from '@jdeighan/coffee-utils/log'
5
7
  import {getPrefix} from '@jdeighan/coffee-utils/arrow'
6
8
 
@@ -19,7 +21,8 @@ export class CallStack
19
21
 
20
22
  constructor: () ->
21
23
 
22
- @reset()
24
+ @lStack = []
25
+ @level = 0
23
26
 
24
27
  # ........................................................................
25
28
 
@@ -27,86 +30,130 @@ export class CallStack
27
30
 
28
31
  if doDebugStack
29
32
  LOG "RESET STACK"
30
-
31
33
  @lStack = []
32
34
  @level = 0
33
35
  return
34
36
 
35
37
  # ........................................................................
36
38
 
37
- addCall: (funcName, hInfo, isLogged) ->
39
+ enter: (funcName, oldFlag=undef) ->
40
+ # --- funcName might be <object>.<method>
38
41
 
39
- @lStack.push({funcName, hInfo, isLogged})
40
- if isLogged
41
- @level += 1
42
+ assert (oldFlag == undef), "enter() takes only 1 arg"
43
+ if doDebugStack
44
+ LOG "[--> ENTER #{funcName}]"
45
+
46
+ lMatches = funcName.match(///^
47
+ ([A-Za-z_][A-Za-z0-9_]*)
48
+ (?:
49
+ \.
50
+ ([A-Za-z_][A-Za-z0-9_]*)
51
+ )?
52
+ $///)
53
+ assert defined(lMatches), "Bad funcName: #{OL(funcName)}"
54
+ [_, ident1, ident2] = lMatches
55
+ if ident2
56
+ @lStack.push({
57
+ fullName: "#{ident1}.#{ident2}"
58
+ funcName: ident2
59
+ isLogged: false
60
+ })
61
+ else
62
+ @lStack.push({
63
+ fullName: ident1
64
+ funcName: ident1
65
+ isLogged: false
66
+ })
42
67
  return
43
68
 
44
69
  # ........................................................................
45
70
 
46
- removeCall: (fName) ->
47
-
48
- {funcName, hInfo, isLogged} = @lStack.pop()
49
- if isLogged && (@level > 0)
50
- @level -= 1
51
- while (funcName != fName) && (@lStack.length > 0)
52
- LOG "[MISSING RETURN FROM #{funcName} (return from #{fName})]"
53
- {funcName, hInfo, isLogged} = @lStack.pop()
54
- if isLogged && (@level > 0)
55
- @level -= 1
71
+ isLogging: () ->
56
72
 
57
- if funcName == fName
58
- return hInfo
73
+ if (@lStack.length == 0)
74
+ return false
59
75
  else
60
- @dump()
61
- LOG "BAD BAD BAD BAD returnFrom('#{fName}')"
62
- return undef
76
+ return @lStack[@lStack.length - 1].isLogged
63
77
 
64
78
  # ........................................................................
79
+
80
+ isLoggingPrev: () ->
81
+
82
+ if (@lStack.length < 2)
83
+ return false
84
+ else
85
+ return @lStack[@lStack.length - 2].isLogged
86
+
65
87
  # ........................................................................
66
88
 
67
- call: (funcName, hInfo, isLogged=undef) ->
89
+ logCurFunc: () ->
68
90
 
69
- assert isLogged != undef, "CallStack.call(): 3 args required"
70
- mainPre = getPrefix(@level)
91
+ # --- funcName must be the current function
92
+ # and the isLogged flag must currently be false
93
+ cur = @lStack[@lStack.length - 1]
94
+ assert (cur.isLogged == false), "isLogged is already true"
95
+ cur.isLogged = true
96
+ @level += 1
97
+ return
98
+
99
+ # ........................................................................
100
+ # --- if stack is empty, log the error, but continue
101
+
102
+ returnFrom: (fName) ->
71
103
 
72
104
  if doDebugStack
73
- prefix = ' '.repeat(@lStack.length)
74
- LOG "#{prefix}[--> CALL #{funcName}]"
105
+ LOG "[<-- BACK #{fName}]"
75
106
 
76
- @addCall funcName, hInfo, isLogged
77
- auxPre = getPrefix(@level)
78
- return [mainPre, auxPre, undef]
107
+ if @lStack.length == 0
108
+ LOG "ERROR: returnFrom('#{funcName}') but stack is empty"
109
+ return
110
+
111
+ {fullName, isLogged} = @lStack.pop()
112
+ if isLogged && (@level > 0)
113
+ @level -= 1
114
+
115
+ # --- This should do nothing
116
+ while (fullName != fName) && (@lStack.length > 0)
117
+ LOG "[MISSING RETURN FROM #{fullName} (return from #{fName})]"
118
+ {fullName, isLogged} = @lStack.pop()
119
+ if isLogged && (@level > 0)
120
+ @level -= 1
121
+
122
+ if fullName != fName
123
+ @dump()
124
+ LOG "BAD BAD BAD BAD returnFrom('#{fName}')"
125
+ return
79
126
 
80
127
  # ........................................................................
81
128
 
82
- logStr: () ->
129
+ getLevel: () ->
83
130
 
84
- pre = getPrefix(@level)
85
- return [pre, pre, undef]
131
+ return @level
86
132
 
87
133
  # ........................................................................
88
134
 
89
- returnFrom: (funcName) ->
135
+ curFunc: () ->
90
136
 
91
- # --- Prefixes are based on level before stack adjustment
92
- mainPre = getPrefix(@level, 'withArrow')
93
- auxPre = getPrefix(@level, 'returnVal')
137
+ if (@lStack.length == 0)
138
+ return 'main'
139
+ else
140
+ return @lStack[@lStack.length - 1].funcName
94
141
 
95
- if @lStack.length == 0
96
- LOG "returnFrom('#{funcName}') but stack is empty"
97
- return [mainPre, auxPre, undef]
142
+ # ........................................................................
98
143
 
99
- hInfo = @removeCall(funcName)
100
- if doDebugStack
101
- prefix = ' '.repeat(@lStack.length)
102
- LOG "#{prefix}[<-- BACK #{funcName}]"
144
+ isActive: (funcName) ->
145
+ # --- funcName won't be <obj>.<method>
146
+ # but the stack might contain that form
103
147
 
104
- return [mainPre, auxPre, hInfo]
148
+ for h in @lStack
149
+ if (h.funcName == funcName)
150
+ return true
151
+ return false
105
152
 
106
153
  # ........................................................................
107
154
  # ........................................................................
108
155
 
109
- dump: (label='CALL STACK') ->
156
+ dump: (prefix='', label='CALL STACK') ->
110
157
 
111
158
  LOG "#{label}:"
112
159
  if @lStack.length == 0
package/src/call_stack.js CHANGED
@@ -4,8 +4,12 @@ var doDebugStack;
4
4
 
5
5
  import {
6
6
  undef,
7
+ defined,
7
8
  croak,
8
- assert
9
+ assert,
10
+ OL,
11
+ isBoolean,
12
+ escapeStr
9
13
  } from '@jdeighan/coffee-utils';
10
14
 
11
15
  import {
@@ -27,7 +31,8 @@ export var debugStack = function(flag = true) {
27
31
  // ---------------------------------------------------------------------------
28
32
  export var CallStack = class CallStack {
29
33
  constructor() {
30
- this.reset();
34
+ this.lStack = [];
35
+ this.level = 0;
31
36
  }
32
37
 
33
38
  // ........................................................................
@@ -40,79 +45,121 @@ export var CallStack = class CallStack {
40
45
  }
41
46
 
42
47
  // ........................................................................
43
- addCall(funcName, hInfo, isLogged) {
44
- this.lStack.push({funcName, hInfo, isLogged});
45
- if (isLogged) {
46
- this.level += 1;
48
+ enter(funcName, oldFlag = undef) {
49
+ var _, ident1, ident2, lMatches;
50
+ // --- funcName might be <object>.<method>
51
+ assert(oldFlag === undef, "enter() takes only 1 arg");
52
+ if (doDebugStack) {
53
+ LOG(`[--> ENTER ${funcName}]`);
54
+ }
55
+ lMatches = funcName.match(/^([A-Za-z_][A-Za-z0-9_]*)(?:\.([A-Za-z_][A-Za-z0-9_]*))?$/);
56
+ assert(defined(lMatches), `Bad funcName: ${OL(funcName)}`);
57
+ [_, ident1, ident2] = lMatches;
58
+ if (ident2) {
59
+ this.lStack.push({
60
+ fullName: `${ident1}.${ident2}`,
61
+ funcName: ident2,
62
+ isLogged: false
63
+ });
64
+ } else {
65
+ this.lStack.push({
66
+ fullName: ident1,
67
+ funcName: ident1,
68
+ isLogged: false
69
+ });
47
70
  }
48
71
  }
49
72
 
50
73
  // ........................................................................
51
- removeCall(fName) {
52
- var funcName, hInfo, isLogged;
53
- ({funcName, hInfo, isLogged} = this.lStack.pop());
74
+ isLogging() {
75
+ if (this.lStack.length === 0) {
76
+ return false;
77
+ } else {
78
+ return this.lStack[this.lStack.length - 1].isLogged;
79
+ }
80
+ }
81
+
82
+ // ........................................................................
83
+ isLoggingPrev() {
84
+ if (this.lStack.length < 2) {
85
+ return false;
86
+ } else {
87
+ return this.lStack[this.lStack.length - 2].isLogged;
88
+ }
89
+ }
90
+
91
+ // ........................................................................
92
+ logCurFunc() {
93
+ var cur;
94
+ // --- funcName must be the current function
95
+ // and the isLogged flag must currently be false
96
+ cur = this.lStack[this.lStack.length - 1];
97
+ assert(cur.isLogged === false, "isLogged is already true");
98
+ cur.isLogged = true;
99
+ this.level += 1;
100
+ }
101
+
102
+ // ........................................................................
103
+ // --- if stack is empty, log the error, but continue
104
+ returnFrom(fName) {
105
+ var fullName, isLogged;
106
+ if (doDebugStack) {
107
+ LOG(`[<-- BACK ${fName}]`);
108
+ }
109
+ if (this.lStack.length === 0) {
110
+ LOG(`ERROR: returnFrom('${funcName}') but stack is empty`);
111
+ return;
112
+ }
113
+ ({fullName, isLogged} = this.lStack.pop());
54
114
  if (isLogged && (this.level > 0)) {
55
115
  this.level -= 1;
56
116
  }
57
- while ((funcName !== fName) && (this.lStack.length > 0)) {
58
- LOG(`[MISSING RETURN FROM ${funcName} (return from ${fName})]`);
59
- ({funcName, hInfo, isLogged} = this.lStack.pop());
117
+ // --- This should do nothing
118
+ while ((fullName !== fName) && (this.lStack.length > 0)) {
119
+ LOG(`[MISSING RETURN FROM ${fullName} (return from ${fName})]`);
120
+ ({fullName, isLogged} = this.lStack.pop());
60
121
  if (isLogged && (this.level > 0)) {
61
122
  this.level -= 1;
62
123
  }
63
124
  }
64
- if (funcName === fName) {
65
- return hInfo;
66
- } else {
125
+ if (fullName !== fName) {
67
126
  this.dump();
68
127
  LOG(`BAD BAD BAD BAD returnFrom('${fName}')`);
69
- return undef;
70
128
  }
71
129
  }
72
130
 
73
131
  // ........................................................................
74
- // ........................................................................
75
- call(funcName, hInfo, isLogged = undef) {
76
- var auxPre, mainPre, prefix;
77
- assert(isLogged !== undef, "CallStack.call(): 3 args required");
78
- mainPre = getPrefix(this.level);
79
- if (doDebugStack) {
80
- prefix = ' '.repeat(this.lStack.length);
81
- LOG(`${prefix}[--> CALL ${funcName}]`);
82
- }
83
- this.addCall(funcName, hInfo, isLogged);
84
- auxPre = getPrefix(this.level);
85
- return [mainPre, auxPre, undef];
132
+ getLevel() {
133
+ return this.level;
86
134
  }
87
135
 
88
136
  // ........................................................................
89
- logStr() {
90
- var pre;
91
- pre = getPrefix(this.level);
92
- return [pre, pre, undef];
137
+ curFunc() {
138
+ if (this.lStack.length === 0) {
139
+ return 'main';
140
+ } else {
141
+ return this.lStack[this.lStack.length - 1].funcName;
142
+ }
93
143
  }
94
144
 
95
145
  // ........................................................................
96
- returnFrom(funcName) {
97
- var auxPre, hInfo, mainPre, prefix;
98
- // --- Prefixes are based on level before stack adjustment
99
- mainPre = getPrefix(this.level, 'withArrow');
100
- auxPre = getPrefix(this.level, 'returnVal');
101
- if (this.lStack.length === 0) {
102
- LOG(`returnFrom('${funcName}') but stack is empty`);
103
- return [mainPre, auxPre, undef];
104
- }
105
- hInfo = this.removeCall(funcName);
106
- if (doDebugStack) {
107
- prefix = ' '.repeat(this.lStack.length);
108
- LOG(`${prefix}[<-- BACK ${funcName}]`);
146
+ isActive(funcName) {
147
+ var h, j, len, ref;
148
+ ref = this.lStack;
149
+ // --- funcName won't be <obj>.<method>
150
+ // but the stack might contain that form
151
+ for (j = 0, len = ref.length; j < len; j++) {
152
+ h = ref[j];
153
+ if (h.funcName === funcName) {
154
+ return true;
155
+ }
109
156
  }
110
- return [mainPre, auxPre, hInfo];
157
+ return false;
111
158
  }
112
159
 
113
160
  // ........................................................................
114
161
  // ........................................................................
115
- dump(label = 'CALL STACK') {
162
+ dump(prefix = '', label = 'CALL STACK') {
116
163
  var i, item, j, len, ref;
117
164
  LOG(`${label}:`);
118
165
  if (this.lStack.length === 0) {
@@ -503,3 +503,15 @@ export className = (aClass) ->
503
503
  export range = (n) ->
504
504
 
505
505
  return [0..n-1]
506
+
507
+ # ---------------------------------------------------------------------------
508
+
509
+ export setCharsAt = (str, pos, str2) ->
510
+
511
+ assert (pos >= 0), "negative pos #{pos} not allowed"
512
+ assert (pos < str.length), "pos #{pos} not in #{OL(str)}"
513
+ if (pos + str2.length >= str.length)
514
+ return str.substring(0, pos) + str2
515
+ else
516
+ return str.substring(0, pos) + str2 + str.substring(pos + str2.length)
517
+
@@ -543,3 +543,14 @@ export var range = function(n) {
543
543
  return results;
544
544
  }).apply(this);
545
545
  };
546
+
547
+ // ---------------------------------------------------------------------------
548
+ export var setCharsAt = function(str, pos, str2) {
549
+ assert(pos >= 0, `negative pos ${pos} not allowed`);
550
+ assert(pos < str.length, `pos ${pos} not in ${OL(str)}`);
551
+ if (pos + str2.length >= str.length) {
552
+ return str.substring(0, pos) + str2;
553
+ } else {
554
+ return str.substring(0, pos) + str2 + str.substring(pos + str2.length);
555
+ }
556
+ };