@jdeighan/coffee-utils 7.0.58 → 7.0.61

Sign up to get free protection for your applications and to get access to all the features.
@@ -2,7 +2,7 @@
2
2
 
3
3
  import {
4
4
  assert, undef, error, croak, warn, defined,
5
- isString, isFunction, isBoolean,
5
+ isString, isFunction, isBoolean, patchStr,
6
6
  OL, escapeStr, isNumber, isArray, words, pass,
7
7
  } from '@jdeighan/coffee-utils'
8
8
  import {blockToArray} from '@jdeighan/coffee-utils/block'
@@ -10,159 +10,118 @@ import {untabify} from '@jdeighan/coffee-utils/indent'
10
10
  import {slurp} from '@jdeighan/coffee-utils/fs'
11
11
  import {CallStack} from '@jdeighan/coffee-utils/stack'
12
12
  import {
13
- getPrefix, addArrow, removeLastVbar,
13
+ prefix, addArrow, removeLastVbar, vbar,
14
14
  } from '@jdeighan/coffee-utils/arrow'
15
15
  import {
16
- log, logItem, LOG, shortEnough, dashes,
16
+ log, logItem, logBareItem, LOG, shortEnough,
17
17
  } from '@jdeighan/coffee-utils/log'
18
18
 
19
- callStack = new CallStack()
20
-
21
19
  # --- set in resetDebugging() and setDebugging()
20
+ export callStack = new CallStack()
22
21
  export shouldLog = () -> undef
23
- export lFuncList = []
24
22
 
25
- # --- internal debugging
26
- doDebugDebug = false
27
- lFunctions = undef # --- only used when doDebugDebug is true
23
+ lFuncList = [] # names of functions being debugged
24
+ strFuncList = undef # original string
28
25
 
29
26
  # ---------------------------------------------------------------------------
30
27
 
31
- export setDebugDebugging = (value=true) ->
32
- # --- value can be a boolean or string of words
28
+ export debug = (orgLabel, lObjects...) ->
33
29
 
34
- if isBoolean(value)
35
- doDebugDebug = value
36
- else if isString(value)
37
- doDebugDebug = true
38
- lFunctions = words(value)
39
- else
40
- croak "Bad value: #{OL(value)}"
41
- return
30
+ assert isString(orgLabel), "1st arg #{OL(orgLabel)} should be a string"
42
31
 
43
- # ---------------------------------------------------------------------------
32
+ [type, funcName] = getType(orgLabel, lObjects)
33
+ label = shouldLog(orgLabel, type, funcName, callStack)
44
34
 
45
- logif = (label, lObjects...) ->
35
+ switch type
46
36
 
47
- if ! doDebugDebug
48
- return
37
+ when 'enter'
38
+ if defined(label)
39
+ doTheLogging type, label, lObjects
40
+ callStack.enter funcName, lObjects, defined(label)
49
41
 
50
- assert isString(label), "1st arg #{OL(label)} should be a string"
51
- nObjects = lObjects.length
52
- [type, funcName] = getType(label, nObjects)
42
+ debug2 "enter debug()", orgLabel, lObjects
43
+ debug2 "type = #{OL(type)}, funcName = #{OL(funcName)}"
44
+ debug2 "return from debug()"
53
45
 
54
- level = callStack.getLevel()
55
- prefix = getPrefix(level)
56
- itemPrefix = removeLastVbar(prefix)
57
- sep = dashes(itemPrefix, 40)
46
+ when 'return'
47
+ debug2 "enter debug()", orgLabel, lObjects
48
+ debug2 "type = #{OL(type)}, funcName = #{OL(funcName)}"
49
+ debug2 "return from debug()"
58
50
 
59
- if (type == 'enter')
60
- if defined(lFunctions) && (funcName not in lFunctions)
61
- return
62
- callStack.enter funcName
63
- else if (type == 'return')
64
- if defined(lFunctions) && (funcName not in lFunctions)
65
- return
51
+ if defined(label)
52
+ doTheLogging type, label, lObjects
53
+ callStack.returnFrom funcName
66
54
 
67
- doTheLogging type, label, lObjects
55
+ when 'string'
56
+ debug2 "enter debug()", orgLabel, lObjects
57
+ debug2 "type = #{OL(type)}, funcName = #{OL(funcName)}"
68
58
 
69
- if (type == 'return')
70
- callStack.returnFrom funcName
59
+ if defined(label)
60
+ doTheLogging type, label, lObjects
61
+ debug2 "return from debug()"
71
62
 
72
- return
63
+ return true # allow use in boolean expressions
73
64
 
74
65
  # ---------------------------------------------------------------------------
75
66
 
76
- export debug = (label, lObjects...) ->
77
-
78
- logif "enter debug(#{OL(label)})", lObjects...
79
-
80
- assert isString(label), "1st arg #{OL(label)} should be a string"
67
+ export debug2 = (orgLabel, lObjects...) ->
81
68
 
82
- # --- We want to allow objects to be undef. Therefore, we need to
83
- # distinguish between 1 arg sent vs. 2 or more args sent
84
- nObjects = lObjects.length
85
-
86
- # --- funcName is only set for types 'enter' and 'return'
87
- [type, funcName] = getType(label, nObjects)
88
- logif "type = #{OL(type)}"
89
- logif "funcName = #{OL(funcName)}"
90
-
91
- # --- function shouldLog() returns the (possibly modified) label
92
- # if we should log this, else it returns undef
69
+ [type, funcName] = getType(orgLabel, lObjects)
70
+ label = shouldLog(orgLabel, type, funcName, callStack)
93
71
 
94
72
  switch type
95
73
  when 'enter'
96
- callStack.enter funcName
97
- label = shouldLog(label, type, funcName, callStack)
74
+ if defined(label)
75
+ doTheLogging 'enter', label, lObjects
76
+ callStack.enter funcName, lObjects, defined(label)
77
+
98
78
  when 'return'
99
- label = shouldLog(label, type, funcName, callStack)
79
+ if defined(label)
80
+ doTheLogging 'return', label, lObjects
81
+ callStack.returnFrom funcName
82
+
100
83
  when 'string'
101
- label = shouldLog(label, type, undef, callStack)
102
- assert (nObjects == 0),
103
- "Objects not allowed for #{OL(type)}"
104
- when 'objects'
105
- label = shouldLog(label, type, undef, callStack)
106
- assert (nObjects > 0),
107
- "Objects required for #{OL(type)}"
108
-
109
- assert (label == undef) || isString(label),
110
- "label not a string: #{OL(label)}"
111
- doLog = defined(label)
112
- logif "doLog = #{OL(doLog)}"
113
- logif "#{nObjects} objects"
114
-
115
- if doLog
116
- doTheLogging type, label, lObjects
117
-
118
- if (type == 'enter') && doLog && (label.indexOf('call') == -1)
119
- callStack.logCurFunc()
120
- else if (type == 'return')
121
- callStack.returnFrom funcName
122
-
123
- logif "return from debug()"
84
+ if defined(label)
85
+ doTheLogging 'string', label, lObjects
86
+
124
87
  return true # allow use in boolean expressions
125
88
 
126
89
  # ---------------------------------------------------------------------------
127
90
 
128
91
  export doTheLogging = (type, label, lObjects) ->
129
92
 
93
+ assert isString(label), "non-string label #{OL(label)}"
130
94
  level = callStack.getLevel()
131
- prefix = getPrefix(level)
132
- itemPrefix = removeLastVbar(prefix)
133
- sep = dashes(itemPrefix, 40)
134
- assert isString(sep), "sep is not a string"
135
-
136
- logif "callStack", callStack
137
- logif "level = #{OL(level)}"
138
- logif "prefix = #{OL(prefix)}"
139
- logif "itemPrefix = #{OL(itemPrefix)}"
140
- logif "sep = #{OL(sep)}"
95
+ sep = '-'.repeat(40)
141
96
 
142
97
  switch type
98
+
143
99
  when 'enter'
144
- log label, {prefix}
100
+ log label, prefix(level)
101
+ pre = prefix(level+1)
102
+ itemPre = prefix(level+2, 'noLastVbar')
145
103
  for obj,i in lObjects
146
- if (i > 0)
147
- log sep
148
- logItem undef, obj, {itemPrefix}
104
+ logItem "arg[#{i}]", obj, pre, itemPre
105
+
149
106
  when 'return'
150
- log label, {prefix: addArrow(prefix)}
107
+ log label, prefix(level, 'withArrow')
108
+ pre = prefix(level, 'noLastVbar')
109
+ itemPre = prefix(level+1, 'noLast2Vbars')
151
110
  for obj,i in lObjects
152
- if (i > 0)
153
- log sep
154
- logItem undef, obj, {itemPrefix}
111
+ logItem "ret[#{i}]", obj, pre, itemPre
155
112
  when 'string'
156
- log label, {prefix}
157
- when 'objects'
158
- if (lObjects.length==1) && shortEnough(label, lObjects[0])
159
- logItem label, lObjects[0], {prefix}
113
+ pre = prefix(level)
114
+ itemPre = prefix(level+1, 'noLastVbar')
115
+ if (lObjects.length==0)
116
+ log label, pre
117
+ else if (lObjects.length==1) && shortEnough(label, lObjects[0])
118
+ logItem label, lObjects[0], pre
160
119
  else
161
120
  if (label.indexOf(':') != label.length - 1)
162
121
  label += ':'
163
- log label, {prefix}
122
+ log label, pre
164
123
  for obj in lObjects
165
- logItem undef, obj, {prefix}
124
+ logBareItem obj, itemPre
166
125
  return
167
126
 
168
127
  # ---------------------------------------------------------------------------
@@ -171,50 +130,54 @@ export stdShouldLog = (label, type, funcName, stack) ->
171
130
  # --- if type is 'enter', then funcName won't be on the stack yet
172
131
  # returns the (possibly modified) label to log
173
132
 
174
- # --- If we're logging now,
175
- # but we won't be logging when funcName is activated
176
- # then change 'enter' to 'call'
177
-
178
133
  assert isString(label), "label #{OL(label)} not a string"
179
134
  assert isString(type), "type #{OL(type)} not a string"
135
+ assert stack instanceof CallStack, "not a call stack object"
180
136
  if (type == 'enter') || (type == 'return')
181
137
  assert isString(funcName), "func name #{OL(funcName)} not a string"
182
138
  else
183
139
  assert funcName == undef, "func name #{OL(funcName)} not undef"
184
- assert stack instanceof CallStack, "not a call stack object"
185
-
186
- logif "stdShouldLog(#{OL(label)}, #{OL(type)}, #{OL(funcName)}, stack)"
187
- logif "stack", stack
188
- logif "lFuncList", lFuncList
189
140
 
190
- switch type
191
- when 'enter'
192
- if funcMatch(stack, lFuncList)
193
- return label
141
+ if funcMatch(funcName || stack.curFunc())
142
+ return label
194
143
 
195
- else
196
- # --- As a special case, if we enter a function where we will not
197
- # be logging, but we were logging in the calling function,
198
- # we'll log out the call itself
144
+ if (type == 'enter') && ! isMyFunc(funcName)
145
+ # --- As a special case, if we enter a function where we will not
146
+ # be logging, but we were logging in the calling function,
147
+ # we'll log out the call itself
199
148
 
200
- prevLogged = stack.isLoggingPrev()
201
- if prevLogged
202
- return label.replace('enter', 'call')
203
- else
204
- if funcMatch(stack, lFuncList)
205
- return label
149
+ if funcMatch(stack.curFunc())
150
+ result = label.replace('enter', 'call')
151
+ return result
206
152
  return undef
207
153
 
208
154
  # ---------------------------------------------------------------------------
209
155
 
156
+ export isMyFunc = (funcName) ->
157
+
158
+ return funcName in words('debug debug2 doTheLogging
159
+ stdShouldLog setDebugging getFuncList funcMatch
160
+ getType dumpCallStack')
161
+
162
+ # ---------------------------------------------------------------------------
163
+
164
+ export trueShouldLog = (label, type, funcName, stack) ->
165
+
166
+ if isMyFunc(funcName || stack.curFunc())
167
+ return undef
168
+ else
169
+ return label
170
+
171
+ # ---------------------------------------------------------------------------
172
+
210
173
  export setDebugging = (option) ->
211
174
 
212
175
  callStack.reset()
213
176
  if isBoolean(option)
214
177
  if option
215
- shouldLog = (label, type, funcName, stack) -> label
178
+ shouldLog = trueShouldLog
216
179
  else
217
- shouldLog = (label, type, funcName, stack) -> undef
180
+ shouldLog = () -> return undef
218
181
  else if isString(option)
219
182
  lFuncList = getFuncList(option)
220
183
  shouldLog = stdShouldLog
@@ -229,6 +192,7 @@ export setDebugging = (option) ->
229
192
 
230
193
  export getFuncList = (str) ->
231
194
 
195
+ strFuncList = str # store original string for debugging
232
196
  lFuncList = []
233
197
  for word in words(str)
234
198
  if lMatches = word.match(///^
@@ -258,29 +222,21 @@ export getFuncList = (str) ->
258
222
  # ---------------------------------------------------------------------------
259
223
  # --- export only to allow unit tests
260
224
 
261
- export funcMatch = (stack, lFuncList) ->
225
+ export funcMatch = (funcName) ->
262
226
 
263
227
  assert isArray(lFuncList), "not an array #{OL(lFuncList)}"
264
-
265
- curFunc = stack.curFunc()
266
- logif "funcMatch(): curFunc = #{OL(curFunc)}"
267
- logif stack.dump(' ')
268
- logif 'lFuncList', lFuncList
269
228
  for h in lFuncList
270
229
  {name, object, plus} = h
271
- if (name == curFunc)
272
- logif " curFunc in lFuncList - match successful"
230
+ if (name == funcName)
273
231
  return true
274
- if plus && stack.isActive(name)
275
- logif " func #{OL(name)} is active - match successful"
232
+ if plus && callStack.isActive(name)
276
233
  return true
277
- logif " - no match"
278
234
  return false
279
235
 
280
236
  # ---------------------------------------------------------------------------
281
- # --- type is one of: 'enter', 'return', 'string', 'object'
237
+ # --- type is one of: 'enter', 'return', 'string'
282
238
 
283
- export getType = (str, nObjects) ->
239
+ export getType = (str, lObjects) ->
284
240
 
285
241
  if lMatches = str.match(///^
286
242
  \s*
@@ -291,7 +247,6 @@ export getType = (str, nObjects) ->
291
247
 
292
248
  # --- We are entering function curFunc
293
249
  return ['enter', lMatches[1]]
294
-
295
250
  else if lMatches = str.match(///^
296
251
  \s*
297
252
  return
@@ -301,9 +256,6 @@ export getType = (str, nObjects) ->
301
256
  ([A-Za-z_][A-Za-z0-9_\.]*)
302
257
  ///)
303
258
  return ['return', lMatches[1]]
304
-
305
- else if (nObjects > 0)
306
- return ['objects', undef]
307
259
  else
308
260
  return ['string', undef]
309
261
 
@@ -317,3 +269,19 @@ reMethod = ///^
317
269
 
318
270
  # ---------------------------------------------------------------------------
319
271
 
272
+ export dumpDebugGlobals = () ->
273
+
274
+ LOG '='.repeat(40)
275
+ LOG callStack.dump()
276
+ if shouldLog == stdShouldLog
277
+ LOG "using stdShouldLog"
278
+ else if shouldLog == trueShouldLog
279
+ LOG "using trueShouldLog"
280
+ else
281
+ LOG "using custom shouldLog"
282
+ LOG "lFuncList:"
283
+ for funcName in lFuncList
284
+ LOG " #{OL(funcName)}"
285
+ LOG '='.repeat(40)
286
+
287
+ # ---------------------------------------------------------------------------