@jdeighan/coffee-utils 7.0.51 → 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.51",
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
  }
@@ -1,7 +1,7 @@
1
1
  # call_stack.coffee
2
2
 
3
3
  import {
4
- undef, defined, croak, assert, isBoolean, escapeStr,
4
+ undef, defined, croak, assert, OL, isBoolean, escapeStr,
5
5
  } from '@jdeighan/coffee-utils'
6
6
  import {log, LOG} from '@jdeighan/coffee-utils/log'
7
7
  import {getPrefix} from '@jdeighan/coffee-utils/arrow'
@@ -36,14 +36,64 @@ export class CallStack
36
36
 
37
37
  # ........................................................................
38
38
 
39
- enter: (funcName, isLogged=false) ->
39
+ enter: (funcName, oldFlag=undef) ->
40
+ # --- funcName might be <object>.<method>
40
41
 
42
+ assert (oldFlag == undef), "enter() takes only 1 arg"
41
43
  if doDebugStack
42
- LOG "[--> CALL #{funcName}]"
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
+ })
67
+ return
68
+
69
+ # ........................................................................
70
+
71
+ isLogging: () ->
72
+
73
+ if (@lStack.length == 0)
74
+ return false
75
+ else
76
+ return @lStack[@lStack.length - 1].isLogged
77
+
78
+ # ........................................................................
79
+
80
+ isLoggingPrev: () ->
81
+
82
+ if (@lStack.length < 2)
83
+ return false
84
+ else
85
+ return @lStack[@lStack.length - 2].isLogged
86
+
87
+ # ........................................................................
88
+
89
+ logCurFunc: () ->
43
90
 
44
- @lStack.push({funcName, isLogged})
45
- if isLogged
46
- @level += 1
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
47
97
  return
48
98
 
49
99
  # ........................................................................
@@ -58,18 +108,18 @@ export class CallStack
58
108
  LOG "ERROR: returnFrom('#{funcName}') but stack is empty"
59
109
  return
60
110
 
61
- {funcName, isLogged} = @lStack.pop()
111
+ {fullName, isLogged} = @lStack.pop()
62
112
  if isLogged && (@level > 0)
63
113
  @level -= 1
64
114
 
65
115
  # --- This should do nothing
66
- while (funcName != fName) && (@lStack.length > 0)
67
- LOG "[MISSING RETURN FROM #{funcName} (return from #{fName})]"
68
- {funcName, isLogged} = @lStack.pop()
116
+ while (fullName != fName) && (@lStack.length > 0)
117
+ LOG "[MISSING RETURN FROM #{fullName} (return from #{fName})]"
118
+ {fullName, isLogged} = @lStack.pop()
69
119
  if isLogged && (@level > 0)
70
120
  @level -= 1
71
121
 
72
- if funcName != fName
122
+ if fullName != fName
73
123
  @dump()
74
124
  LOG "BAD BAD BAD BAD returnFrom('#{fName}')"
75
125
  return
@@ -91,17 +141,19 @@ export class CallStack
91
141
 
92
142
  # ........................................................................
93
143
 
94
- isActive: (fName) ->
144
+ isActive: (funcName) ->
145
+ # --- funcName won't be <obj>.<method>
146
+ # but the stack might contain that form
95
147
 
96
148
  for h in @lStack
97
- if (h.funcName == fName)
149
+ if (h.funcName == funcName)
98
150
  return true
99
151
  return false
100
152
 
101
153
  # ........................................................................
102
154
  # ........................................................................
103
155
 
104
- dump: (label='CALL STACK') ->
156
+ dump: (prefix='', label='CALL STACK') ->
105
157
 
106
158
  LOG "#{label}:"
107
159
  if @lStack.length == 0
package/src/call_stack.js CHANGED
@@ -7,6 +7,7 @@ import {
7
7
  defined,
8
8
  croak,
9
9
  assert,
10
+ OL,
10
11
  isBoolean,
11
12
  escapeStr
12
13
  } from '@jdeighan/coffee-utils';
@@ -44,20 +45,64 @@ export var CallStack = class CallStack {
44
45
  }
45
46
 
46
47
  // ........................................................................
47
- enter(funcName, isLogged = false) {
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");
48
52
  if (doDebugStack) {
49
- LOG(`[--> CALL ${funcName}]`);
53
+ LOG(`[--> ENTER ${funcName}]`);
50
54
  }
51
- this.lStack.push({funcName, isLogged});
52
- if (isLogged) {
53
- this.level += 1;
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
+ });
70
+ }
71
+ }
72
+
73
+ // ........................................................................
74
+ isLogging() {
75
+ if (this.lStack.length === 0) {
76
+ return false;
77
+ } else {
78
+ return this.lStack[this.lStack.length - 1].isLogged;
54
79
  }
55
80
  }
56
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
+
57
102
  // ........................................................................
58
103
  // --- if stack is empty, log the error, but continue
59
104
  returnFrom(fName) {
60
- var funcName, isLogged;
105
+ var fullName, isLogged;
61
106
  if (doDebugStack) {
62
107
  LOG(`[<-- BACK ${fName}]`);
63
108
  }
@@ -65,19 +110,19 @@ export var CallStack = class CallStack {
65
110
  LOG(`ERROR: returnFrom('${funcName}') but stack is empty`);
66
111
  return;
67
112
  }
68
- ({funcName, isLogged} = this.lStack.pop());
113
+ ({fullName, isLogged} = this.lStack.pop());
69
114
  if (isLogged && (this.level > 0)) {
70
115
  this.level -= 1;
71
116
  }
72
117
  // --- This should do nothing
73
- while ((funcName !== fName) && (this.lStack.length > 0)) {
74
- LOG(`[MISSING RETURN FROM ${funcName} (return from ${fName})]`);
75
- ({funcName, isLogged} = this.lStack.pop());
118
+ while ((fullName !== fName) && (this.lStack.length > 0)) {
119
+ LOG(`[MISSING RETURN FROM ${fullName} (return from ${fName})]`);
120
+ ({fullName, isLogged} = this.lStack.pop());
76
121
  if (isLogged && (this.level > 0)) {
77
122
  this.level -= 1;
78
123
  }
79
124
  }
80
- if (funcName !== fName) {
125
+ if (fullName !== fName) {
81
126
  this.dump();
82
127
  LOG(`BAD BAD BAD BAD returnFrom('${fName}')`);
83
128
  }
@@ -98,12 +143,14 @@ export var CallStack = class CallStack {
98
143
  }
99
144
 
100
145
  // ........................................................................
101
- isActive(fName) {
146
+ isActive(funcName) {
102
147
  var h, j, len, ref;
103
148
  ref = this.lStack;
149
+ // --- funcName won't be <obj>.<method>
150
+ // but the stack might contain that form
104
151
  for (j = 0, len = ref.length; j < len; j++) {
105
152
  h = ref[j];
106
- if (h.funcName === fName) {
153
+ if (h.funcName === funcName) {
107
154
  return true;
108
155
  }
109
156
  }
@@ -112,7 +159,7 @@ export var CallStack = class CallStack {
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) {
@@ -18,7 +18,125 @@ import {
18
18
 
19
19
  callStack = new CallStack()
20
20
  doDebugDebug = false
21
- shouldLog = undef # set in resetDebugging() and setDebugging()
21
+
22
+ export shouldLog = undef # set in resetDebugging() and setDebugging()
23
+ export lFuncList = []
24
+
25
+ # ---------------------------------------------------------------------------
26
+
27
+ export debug = (label, lObjects...) ->
28
+
29
+ assert isString(label), "1st arg #{OL(label)} should be a string"
30
+
31
+ # --- We want to allow objects to be undef. Therefore, we need to
32
+ # distinguish between 1 arg sent vs. 2 or more args sent
33
+ nObjects = lObjects.length
34
+
35
+ # --- funcName is only set for types 'enter' and 'return'
36
+ [type, funcName] = getType(label, nObjects)
37
+ if doDebugDebug
38
+ LOG "debug(): type = #{OL(type)}"
39
+ LOG "debug(): funcName = #{OL(funcName)}"
40
+
41
+ switch type
42
+ when 'enter'
43
+ callStack.enter funcName
44
+ label = shouldLog(label, type, funcName, callStack)
45
+ when 'return'
46
+ label = shouldLog(label, type, funcName, callStack)
47
+ when 'string'
48
+ label = shouldLog(label, type, undef, callStack)
49
+ assert (nObjects == 0),
50
+ "multiple objects only not allowed for #{OL(type)}"
51
+ when 'objects'
52
+ label = shouldLog(label, type, undef, callStack)
53
+ assert (nObjects > 0),
54
+ "multiple objects only not allowed for #{OL(type)}"
55
+ doLog = defined(label)
56
+
57
+ if doDebugDebug
58
+ if nObjects == 0
59
+ LOG "debug(#{OL(label)}) - 1 arg"
60
+ else
61
+ LOG "debug(#{OL(label)}), #{nObjects} args"
62
+ LOG "doLog = #{OL(doLog)}"
63
+
64
+ if doLog
65
+ level = callStack.getLevel()
66
+ prefix = getPrefix(level)
67
+
68
+ if doDebugDebug
69
+ LOG "callStack", callStack
70
+ LOG "level = #{OL(level)}"
71
+ LOG "prefix = #{OL(prefix)}"
72
+
73
+ switch type
74
+ when 'enter'
75
+ log label, {prefix}
76
+ for obj,i in lObjects
77
+ if (i > 0)
78
+ log sep_dash, {prefix: removeLastVbar(prefix)}
79
+ logItem undef, obj, {prefix: removeLastVbar(prefix)}
80
+ when 'return'
81
+ log label, {prefix: addArrow(prefix)}
82
+ for obj,i in lObjects
83
+ if (i > 0)
84
+ log sep_dash, {prefix: removeLastVbar(prefix)}
85
+ logItem undef, obj, {prefix: removeLastVbar(prefix)}
86
+ when 'string'
87
+ log label, {prefix}
88
+ when 'objects'
89
+ if (nObjects==1) && shortEnough(label, lObjects[0])
90
+ logItem label, lObjects[0], {prefix}
91
+ else
92
+ if (label.indexOf(':') != label.length - 1)
93
+ label += ':'
94
+ log label, {prefix}
95
+ for obj in lObjects
96
+ logItem undef, obj, {prefix}
97
+
98
+ if (type == 'enter') && doLog
99
+ callStack.logCurFunc()
100
+ else if (type == 'return')
101
+ callStack.returnFrom funcName
102
+
103
+ return true # allow use in boolean expressions
104
+
105
+ # ---------------------------------------------------------------------------
106
+
107
+ export stdShouldLog = (label, type, funcName, stack) ->
108
+ # --- if type is 'enter', then funcName won't be on the stack yet
109
+ # returns the (possibly modified) label to log
110
+
111
+ # --- If we're logging now,
112
+ # but we won't be logging when funcName is activated
113
+ # then change 'enter' to 'call'
114
+
115
+ assert isString(label), "label #{OL(label)} not a string"
116
+ assert isString(type), "type #{OL(type)} not a string"
117
+ if (type == 'enter') || (type == 'return')
118
+ assert isString(funcName), "func name #{OL(funcName)} not a string"
119
+ else
120
+ assert funcName == undef, "func name #{OL(funcName)} not undef"
121
+ assert stack instanceof CallStack, "not a call stack object"
122
+ if doDebugDebug
123
+ LOG "stdShouldLog(#{OL(label)}, #{OL(type)}, #{OL(funcName)}, stack)"
124
+ LOG "stack", stack
125
+ LOG "lFuncList", lFuncList
126
+ switch type
127
+ when 'enter'
128
+ if funcMatch(stack, lFuncList)
129
+ return label
130
+
131
+ # --- As a special case, if we enter a function where we will not
132
+ # be logging, but we were logging in the calling function,
133
+ # we'll log out the call itself
134
+ else if stack.isLoggingPrev()
135
+ return label.replace('enter', 'call')
136
+ else
137
+ if funcMatch(stack, lFuncList)
138
+ return label
139
+ return undef
22
140
 
23
141
  # ---------------------------------------------------------------------------
24
142
 
@@ -36,7 +154,7 @@ resetDebugging = () ->
36
154
  if doDebugDebug
37
155
  LOG "resetDebugging()"
38
156
  callStack.reset()
39
- shouldLog = (type, str, stack) -> false
157
+ shouldLog = (label, type, funcName, stack) -> undef
40
158
  return
41
159
 
42
160
  # ---------------------------------------------------------------------------
@@ -45,44 +163,82 @@ export setDebugging = (option) ->
45
163
 
46
164
  resetDebugging()
47
165
  if isBoolean(option)
48
- shouldLog = (type, str, stack) -> option
166
+ if option
167
+ shouldLog = (label, type, funcName, stack) -> label
168
+ else
169
+ shouldLog = (label, type, funcName, stack) -> undef
170
+ if doDebugDebug
171
+ LOG "setDebugging = #{option}"
49
172
  else if isString(option)
50
- shouldLog = (type, str, stack) ->
51
- lFuncs = words(option)
52
- switch type
53
- when 'enter'
54
- return funcMatch(stack, lFuncs, str)
55
- else
56
- return funcMatch(stack, lFuncs)
173
+ lFuncList = getFuncList(option)
174
+ shouldLog = stdShouldLog
57
175
  if doDebugDebug
58
176
  LOG "setDebugging FUNCS: #{option}"
177
+ LOG 'lFuncList', lFuncList
59
178
  else if isFunction(option)
60
179
  shouldLog = option
61
180
  if doDebugDebug
62
181
  LOG "setDebugging to custom func"
63
182
  else
64
- croak "setDebugging(): bad parameter #{OL(option)}"
183
+ croak "bad parameter #{OL(option)}"
65
184
  return
66
185
 
67
186
  # ---------------------------------------------------------------------------
68
187
  # --- export only to allow unit tests
69
188
 
70
- export funcMatch = (stack, lFuncNames, enteringFunc=undef) ->
189
+ export getFuncList = (str) ->
190
+
191
+ lFuncList = []
192
+ for word in words(str)
193
+ if lMatches = word.match(///^
194
+ ([A-Za-z_][A-Za-z0-9_]*)
195
+ (?:
196
+ \.
197
+ ([A-Za-z_][A-Za-z0-9_]*)
198
+ )?
199
+ (\+)?
200
+ $///)
201
+ [_, ident1, ident2, plus] = lMatches
202
+ if ident2
203
+ lFuncList.push {
204
+ name: ident2
205
+ object: ident1
206
+ plus: (plus == '+')
207
+ }
208
+ else
209
+ lFuncList.push {
210
+ name: ident1
211
+ plus: (plus == '+')
212
+ }
213
+ else
214
+ croak "Bad word in func list: #{OL(word)}"
215
+ return lFuncList
216
+
217
+ # ---------------------------------------------------------------------------
218
+ # --- export only to allow unit tests
219
+
220
+ export funcMatch = (stack, lFuncList) ->
71
221
 
72
- if defined(enteringFunc) && (enteringFunc in lFuncNames)
73
- return true
222
+ assert isArray(lFuncList), "not an array #{OL(lFuncList)}"
74
223
 
75
224
  curFunc = stack.curFunc()
76
- assert isString(curFunc), "funcMatch(): not a string #{OL(curFunc)}"
77
- assert isArray(lFuncNames), "funcMatch(): bad array #{lFuncNames}"
78
- if lFuncNames.includes(curFunc)
79
- return true
80
- else if (lMatches = curFunc.match(reMethod)) \
81
- && ([_, cls, meth] = lMatches) \
82
- && lFuncNames.includes(meth)
83
- return true
84
- else
85
- return false
225
+ if doDebugDebug
226
+ LOG "funcMatch(): curFunc = #{OL(curFunc)}"
227
+ stack.dump(' ')
228
+ LOG 'lFuncList', lFuncList
229
+ for h in lFuncList
230
+ {name, object, plus} = h
231
+ if (name == curFunc)
232
+ if doDebugDebug
233
+ LOG " curFunc in lFuncList - match successful"
234
+ return true
235
+ if plus && stack.isActive(name)
236
+ if doDebugDebug
237
+ LOG " func #{OL(name)} is active - match successful"
238
+ return true
239
+ if doDebugDebug
240
+ LOG " - no match"
241
+ return false
86
242
 
87
243
  # ---------------------------------------------------------------------------
88
244
  # --- type is one of: 'enter', 'return', 'string', 'object'
@@ -116,89 +272,6 @@ export getType = (str, nObjects) ->
116
272
 
117
273
  # ---------------------------------------------------------------------------
118
274
 
119
- export debug = (label, lObjects...) ->
120
-
121
- assert isString(label), "1st arg #{OL(label)} should be a string"
122
-
123
- # --- We want to allow objects to be undef. Therefore, we need to
124
- # distinguish between 1 arg sent vs. 2 or more args sent
125
- nObjects = lObjects.length
126
-
127
- # --- funcName is only set for types 'enter' and 'return'
128
- [type, funcName] = getType(label, nObjects)
129
- switch type
130
- when 'enter'
131
- doLog = shouldLog(type, funcName, callStack)
132
-
133
- # --- If we won't be logging when funcName is activated
134
- # then change 'enter' to 'call'
135
- callStack.enter funcName # add to call stack
136
- if ! shouldLog('string', 'abc', callStack)
137
- label = label.replace('enter', 'call')
138
- callStack.returnFrom funcName # remove from call stack
139
- when 'return'
140
- doLog = shouldLog(type, funcName, callStack)
141
- when 'string'
142
- doLog = shouldLog(type, label, callStack)
143
- assert (nObjects == 0),
144
- "multiple objects only not allowed for #{OL(type)}"
145
- when 'objects'
146
- doLog = shouldLog(type, label, callStack)
147
- assert (nObjects > 0),
148
- "multiple objects only not allowed for #{OL(type)}"
149
-
150
- if doDebugDebug
151
- if nObjects == 0
152
- LOG "debug(#{OL(label)}) - 1 arg"
153
- else
154
- LOG "debug(#{OL(label)}), #{nObjects} args"
155
- LOG "doLog = #{OL(doLog)}"
156
- LOG "type = #{OL(type)}"
157
- LOG "funcName = #{OL(funcName)}"
158
-
159
- if doLog
160
- level = callStack.getLevel()
161
- prefix = getPrefix(level)
162
-
163
- if doDebugDebug
164
- LOG "callStack", callStack
165
- LOG "level = #{OL(level)}"
166
- LOG "prefix = #{OL(prefix)}"
167
-
168
- switch type
169
- when 'enter'
170
- log label, {prefix}
171
- for obj,i in lObjects
172
- if (i > 0)
173
- log sep_dash, {prefix: removeLastVbar(prefix)}
174
- logItem undef, obj, {prefix: removeLastVbar(prefix)}
175
- when 'return'
176
- log label, {prefix: addArrow(prefix)}
177
- for obj,i in lObjects
178
- if (i > 0)
179
- log sep_dash, {prefix: removeLastVbar(prefix)}
180
- logItem undef, obj, {prefix: removeLastVbar(prefix)}
181
- when 'string'
182
- log label, {prefix}
183
- when 'objects'
184
- if (nObjects==1) && shortEnough(label, lObjects[0])
185
- logItem label, lObjects[0], {prefix}
186
- else
187
- if (label.indexOf(':') != label.length - 1)
188
- label += ':'
189
- log label, {prefix}
190
- for obj in lObjects
191
- logItem undef, obj, {prefix}
192
-
193
- if (type == 'enter')
194
- callStack.enter funcName, doLog
195
- else if (type == 'return')
196
- callStack.returnFrom funcName
197
-
198
- return true # allow use in boolean expressions
199
-
200
- # ---------------------------------------------------------------------------
201
-
202
275
  reMethod = ///^
203
276
  ([A-Za-z_][A-Za-z0-9_]*)
204
277
  \.
@@ -1,7 +1,6 @@
1
1
  // Generated by CoffeeScript 2.7.0
2
- // debug_utils.coffee
3
- var callStack, doDebugDebug, reMethod, resetDebugging, shouldLog,
4
- indexOf = [].indexOf;
2
+ // debug_utils.coffee
3
+ var callStack, doDebugDebug, reMethod, resetDebugging;
5
4
 
6
5
  import {
7
6
  assert,
@@ -55,93 +54,9 @@ callStack = new CallStack();
55
54
 
56
55
  doDebugDebug = false;
57
56
 
58
- shouldLog = undef; // set in resetDebugging() and setDebugging()
57
+ export var shouldLog = undef; // set in resetDebugging() and setDebugging()
59
58
 
60
-
61
- // ---------------------------------------------------------------------------
62
- export var debugDebug = function(flag = true) {
63
- doDebugDebug = flag;
64
- if (doDebugDebug) {
65
- LOG(`doDebugDebug = ${flag}`);
66
- }
67
- };
68
-
69
- // ---------------------------------------------------------------------------
70
- resetDebugging = function() {
71
- if (doDebugDebug) {
72
- LOG("resetDebugging()");
73
- }
74
- callStack.reset();
75
- shouldLog = function(type, str, stack) {
76
- return false;
77
- };
78
- };
79
-
80
- // ---------------------------------------------------------------------------
81
- export var setDebugging = function(option) {
82
- resetDebugging();
83
- if (isBoolean(option)) {
84
- shouldLog = function(type, str, stack) {
85
- return option;
86
- };
87
- } else if (isString(option)) {
88
- shouldLog = function(type, str, stack) {
89
- var lFuncs;
90
- lFuncs = words(option);
91
- switch (type) {
92
- case 'enter':
93
- return funcMatch(stack, lFuncs, str);
94
- default:
95
- return funcMatch(stack, lFuncs);
96
- }
97
- };
98
- if (doDebugDebug) {
99
- LOG(`setDebugging FUNCS: ${option}`);
100
- }
101
- } else if (isFunction(option)) {
102
- shouldLog = option;
103
- if (doDebugDebug) {
104
- LOG("setDebugging to custom func");
105
- }
106
- } else {
107
- croak(`setDebugging(): bad parameter ${OL(option)}`);
108
- }
109
- };
110
-
111
- // ---------------------------------------------------------------------------
112
- // --- export only to allow unit tests
113
- export var funcMatch = function(stack, lFuncNames, enteringFunc = undef) {
114
- var _, cls, curFunc, lMatches, meth;
115
- if (defined(enteringFunc) && (indexOf.call(lFuncNames, enteringFunc) >= 0)) {
116
- return true;
117
- }
118
- curFunc = stack.curFunc();
119
- assert(isString(curFunc), `funcMatch(): not a string ${OL(curFunc)}`);
120
- assert(isArray(lFuncNames), `funcMatch(): bad array ${lFuncNames}`);
121
- if (lFuncNames.includes(curFunc)) {
122
- return true;
123
- } else if ((lMatches = curFunc.match(reMethod)) && ([_, cls, meth] = lMatches) && lFuncNames.includes(meth)) {
124
- return true;
125
- } else {
126
- return false;
127
- }
128
- };
129
-
130
- // ---------------------------------------------------------------------------
131
- // --- type is one of: 'enter', 'return', 'string', 'object'
132
- export var getType = function(str, nObjects) {
133
- var lMatches;
134
- if (lMatches = str.match(/^\s*enter\s+([A-Za-z_][A-Za-z0-9_\.]*)/)) {
135
- // --- We are entering function curFunc
136
- return ['enter', lMatches[1]];
137
- } else if (lMatches = str.match(/^\s*return.+from\s+([A-Za-z_][A-Za-z0-9_\.]*)/)) {
138
- return ['return', lMatches[1]];
139
- } else if (nObjects > 0) {
140
- return ['objects', undef];
141
- } else {
142
- return ['string', undef];
143
- }
144
- };
59
+ export var lFuncList = [];
145
60
 
146
61
  // ---------------------------------------------------------------------------
147
62
  export var debug = function(label, ...lObjects) {
@@ -152,28 +67,27 @@ export var debug = function(label, ...lObjects) {
152
67
  nObjects = lObjects.length;
153
68
  // --- funcName is only set for types 'enter' and 'return'
154
69
  [type, funcName] = getType(label, nObjects);
70
+ if (doDebugDebug) {
71
+ LOG(`debug(): type = ${OL(type)}`);
72
+ LOG(`debug(): funcName = ${OL(funcName)}`);
73
+ }
155
74
  switch (type) {
156
75
  case 'enter':
157
- doLog = shouldLog(type, funcName, callStack);
158
- // --- If we won't be logging when funcName is activated
159
- // then change 'enter' to 'call'
160
- callStack.enter(funcName); // add to call stack
161
- if (!shouldLog('string', 'abc', callStack)) {
162
- label = label.replace('enter', 'call');
163
- }
164
- callStack.returnFrom(funcName); // remove from call stack
76
+ callStack.enter(funcName);
77
+ label = shouldLog(label, type, funcName, callStack);
165
78
  break;
166
79
  case 'return':
167
- doLog = shouldLog(type, funcName, callStack);
80
+ label = shouldLog(label, type, funcName, callStack);
168
81
  break;
169
82
  case 'string':
170
- doLog = shouldLog(type, label, callStack);
83
+ label = shouldLog(label, type, undef, callStack);
171
84
  assert(nObjects === 0, `multiple objects only not allowed for ${OL(type)}`);
172
85
  break;
173
86
  case 'objects':
174
- doLog = shouldLog(type, label, callStack);
87
+ label = shouldLog(label, type, undef, callStack);
175
88
  assert(nObjects > 0, `multiple objects only not allowed for ${OL(type)}`);
176
89
  }
90
+ doLog = defined(label);
177
91
  if (doDebugDebug) {
178
92
  if (nObjects === 0) {
179
93
  LOG(`debug(${OL(label)}) - 1 arg`);
@@ -181,8 +95,6 @@ export var debug = function(label, ...lObjects) {
181
95
  LOG(`debug(${OL(label)}), ${nObjects} args`);
182
96
  }
183
97
  LOG(`doLog = ${OL(doLog)}`);
184
- LOG(`type = ${OL(type)}`);
185
- LOG(`funcName = ${OL(funcName)}`);
186
98
  }
187
99
  if (doLog) {
188
100
  level = callStack.getLevel();
@@ -241,8 +153,8 @@ export var debug = function(label, ...lObjects) {
241
153
  }
242
154
  }
243
155
  }
244
- if (type === 'enter') {
245
- callStack.enter(funcName, doLog);
156
+ if ((type === 'enter') && doLog) {
157
+ callStack.logCurFunc();
246
158
  } else if (type === 'return') {
247
159
  callStack.returnFrom(funcName);
248
160
  }
@@ -250,6 +162,176 @@ export var debug = function(label, ...lObjects) {
250
162
  };
251
163
 
252
164
 
165
+ // ---------------------------------------------------------------------------
166
+ export var stdShouldLog = function(label, type, funcName, stack) {
167
+ // --- if type is 'enter', then funcName won't be on the stack yet
168
+ // returns the (possibly modified) label to log
169
+
170
+ // --- If we're logging now,
171
+ // but we won't be logging when funcName is activated
172
+ // then change 'enter' to 'call'
173
+ assert(isString(label), `label ${OL(label)} not a string`);
174
+ assert(isString(type), `type ${OL(type)} not a string`);
175
+ if ((type === 'enter') || (type === 'return')) {
176
+ assert(isString(funcName), `func name ${OL(funcName)} not a string`);
177
+ } else {
178
+ assert(funcName === undef, `func name ${OL(funcName)} not undef`);
179
+ }
180
+ assert(stack instanceof CallStack, "not a call stack object");
181
+ if (doDebugDebug) {
182
+ LOG(`stdShouldLog(${OL(label)}, ${OL(type)}, ${OL(funcName)}, stack)`);
183
+ LOG("stack", stack);
184
+ LOG("lFuncList", lFuncList);
185
+ }
186
+ switch (type) {
187
+ case 'enter':
188
+ if (funcMatch(stack, lFuncList)) {
189
+ return label;
190
+ // --- As a special case, if we enter a function where we will not
191
+ // be logging, but we were logging in the calling function,
192
+ // we'll log out the call itself
193
+ } else if (stack.isLoggingPrev()) {
194
+ return label.replace('enter', 'call');
195
+ }
196
+ break;
197
+ default:
198
+ if (funcMatch(stack, lFuncList)) {
199
+ return label;
200
+ }
201
+ }
202
+ return undef;
203
+ };
204
+
205
+ // ---------------------------------------------------------------------------
206
+ export var debugDebug = function(flag = true) {
207
+ doDebugDebug = flag;
208
+ if (doDebugDebug) {
209
+ LOG(`doDebugDebug = ${flag}`);
210
+ }
211
+ };
212
+
213
+ // ---------------------------------------------------------------------------
214
+ resetDebugging = function() {
215
+ if (doDebugDebug) {
216
+ LOG("resetDebugging()");
217
+ }
218
+ callStack.reset();
219
+ shouldLog = function(label, type, funcName, stack) {
220
+ return undef;
221
+ };
222
+ };
223
+
224
+ // ---------------------------------------------------------------------------
225
+ export var setDebugging = function(option) {
226
+ resetDebugging();
227
+ if (isBoolean(option)) {
228
+ if (option) {
229
+ shouldLog = function(label, type, funcName, stack) {
230
+ return label;
231
+ };
232
+ } else {
233
+ shouldLog = function(label, type, funcName, stack) {
234
+ return undef;
235
+ };
236
+ }
237
+ if (doDebugDebug) {
238
+ LOG(`setDebugging = ${option}`);
239
+ }
240
+ } else if (isString(option)) {
241
+ lFuncList = getFuncList(option);
242
+ shouldLog = stdShouldLog;
243
+ if (doDebugDebug) {
244
+ LOG(`setDebugging FUNCS: ${option}`);
245
+ LOG('lFuncList', lFuncList);
246
+ }
247
+ } else if (isFunction(option)) {
248
+ shouldLog = option;
249
+ if (doDebugDebug) {
250
+ LOG("setDebugging to custom func");
251
+ }
252
+ } else {
253
+ croak(`bad parameter ${OL(option)}`);
254
+ }
255
+ };
256
+
257
+ // ---------------------------------------------------------------------------
258
+ // --- export only to allow unit tests
259
+ export var getFuncList = function(str) {
260
+ var _, ident1, ident2, j, lMatches, len1, plus, ref, word;
261
+ lFuncList = [];
262
+ ref = words(str);
263
+ for (j = 0, len1 = ref.length; j < len1; j++) {
264
+ word = ref[j];
265
+ if (lMatches = word.match(/^([A-Za-z_][A-Za-z0-9_]*)(?:\.([A-Za-z_][A-Za-z0-9_]*))?(\+)?$/)) {
266
+ [_, ident1, ident2, plus] = lMatches;
267
+ if (ident2) {
268
+ lFuncList.push({
269
+ name: ident2,
270
+ object: ident1,
271
+ plus: plus === '+'
272
+ });
273
+ } else {
274
+ lFuncList.push({
275
+ name: ident1,
276
+ plus: plus === '+'
277
+ });
278
+ }
279
+ } else {
280
+ croak(`Bad word in func list: ${OL(word)}`);
281
+ }
282
+ }
283
+ return lFuncList;
284
+ };
285
+
286
+ // ---------------------------------------------------------------------------
287
+ // --- export only to allow unit tests
288
+ export var funcMatch = function(stack, lFuncList) {
289
+ var curFunc, h, j, len1, name, object, plus;
290
+ assert(isArray(lFuncList), `not an array ${OL(lFuncList)}`);
291
+ curFunc = stack.curFunc();
292
+ if (doDebugDebug) {
293
+ LOG(`funcMatch(): curFunc = ${OL(curFunc)}`);
294
+ stack.dump(' ');
295
+ LOG('lFuncList', lFuncList);
296
+ }
297
+ for (j = 0, len1 = lFuncList.length; j < len1; j++) {
298
+ h = lFuncList[j];
299
+ ({name, object, plus} = h);
300
+ if (name === curFunc) {
301
+ if (doDebugDebug) {
302
+ LOG(" curFunc in lFuncList - match successful");
303
+ }
304
+ return true;
305
+ }
306
+ if (plus && stack.isActive(name)) {
307
+ if (doDebugDebug) {
308
+ LOG(` func ${OL(name)} is active - match successful`);
309
+ }
310
+ return true;
311
+ }
312
+ }
313
+ if (doDebugDebug) {
314
+ LOG(" - no match");
315
+ }
316
+ return false;
317
+ };
318
+
319
+ // ---------------------------------------------------------------------------
320
+ // --- type is one of: 'enter', 'return', 'string', 'object'
321
+ export var getType = function(str, nObjects) {
322
+ var lMatches;
323
+ if (lMatches = str.match(/^\s*enter\s+([A-Za-z_][A-Za-z0-9_\.]*)/)) {
324
+ // --- We are entering function curFunc
325
+ return ['enter', lMatches[1]];
326
+ } else if (lMatches = str.match(/^\s*return.+from\s+([A-Za-z_][A-Za-z0-9_\.]*)/)) {
327
+ return ['return', lMatches[1]];
328
+ } else if (nObjects > 0) {
329
+ return ['objects', undef];
330
+ } else {
331
+ return ['string', undef];
332
+ }
333
+ };
334
+
253
335
  // ---------------------------------------------------------------------------
254
336
  reMethod = /^([A-Za-z_][A-Za-z0-9_]*)\.([A-Za-z_][A-Za-z0-9_]*)$/;
255
337
 
@@ -36,9 +36,9 @@ export LOG = (lArgs...) ->
36
36
  if lArgs.length > 1
37
37
  # --- There's both a label and an item
38
38
  if (item == undef)
39
- console.log "#{label}: UNDEFINED"
39
+ console.log "#{label} = undef"
40
40
  else if (item == null)
41
- console.log "#{label}: NULL"
41
+ console.log "#{label} = null"
42
42
  else
43
43
  console.log sep_dash
44
44
  console.log "#{label}:"
package/src/log_utils.js CHANGED
@@ -55,9 +55,9 @@ export var LOG = function(...lArgs) {
55
55
  if (lArgs.length > 1) {
56
56
  // --- There's both a label and an item
57
57
  if (item === undef) {
58
- console.log(`${label}: UNDEFINED`);
58
+ console.log(`${label} = undef`);
59
59
  } else if (item === null) {
60
- console.log(`${label}: NULL`);
60
+ console.log(`${label} = null`);
61
61
  } else {
62
62
  console.log(sep_dash);
63
63
  console.log(`${label}:`);