@jdeighan/coffee-utils 7.0.50 → 7.0.53
Sign up to get free protection for your applications and to get access to all the features.
- package/package.json +2 -2
- package/src/arrow.coffee +40 -4
- package/src/arrow.js +46 -5
- package/src/call_stack.coffee +91 -46
- package/src/call_stack.js +92 -47
- package/src/coffee_utils.coffee +12 -0
- package/src/coffee_utils.js +11 -0
- package/src/debug_utils.coffee +207 -149
- package/src/debug_utils.js +244 -141
- package/src/log_utils.coffee +49 -26
- package/src/log_utils.js +48 -27
package/src/debug_utils.coffee
CHANGED
@@ -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, sep_dash,
|
6
6
|
OL, escapeStr, isNumber, isArray, words, pass,
|
7
7
|
} from '@jdeighan/coffee-utils'
|
8
8
|
import {blockToArray} from '@jdeighan/coffee-utils/block'
|
@@ -10,17 +10,134 @@ 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
|
-
|
13
|
+
getPrefix, addArrow, removeLastVbar,
|
14
|
+
} from '@jdeighan/coffee-utils/arrow'
|
15
|
+
import {
|
16
|
+
log, logItem, LOG, shortEnough,
|
14
17
|
} from '@jdeighan/coffee-utils/log'
|
15
18
|
|
16
|
-
|
17
|
-
export debugging = false
|
18
|
-
shouldLogFunc = (func) -> return debugging
|
19
|
-
shouldLogString = (str) -> return debugging
|
20
|
-
|
21
|
-
stack = new CallStack()
|
19
|
+
callStack = new CallStack()
|
22
20
|
doDebugDebug = false
|
23
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
|
140
|
+
|
24
141
|
# ---------------------------------------------------------------------------
|
25
142
|
|
26
143
|
export debugDebug = (flag=true) ->
|
@@ -34,183 +151,124 @@ export debugDebug = (flag=true) ->
|
|
34
151
|
|
35
152
|
resetDebugging = () ->
|
36
153
|
|
37
|
-
debugging = false
|
38
154
|
if doDebugDebug
|
39
|
-
LOG "resetDebugging()
|
40
|
-
|
41
|
-
|
42
|
-
shouldLogString = (str) -> return debugging
|
155
|
+
LOG "resetDebugging()"
|
156
|
+
callStack.reset()
|
157
|
+
shouldLog = (label, type, funcName, stack) -> undef
|
43
158
|
return
|
44
159
|
|
45
160
|
# ---------------------------------------------------------------------------
|
46
161
|
|
47
|
-
export setDebugging = (
|
162
|
+
export setDebugging = (option) ->
|
48
163
|
|
49
164
|
resetDebugging()
|
50
|
-
if isBoolean(
|
51
|
-
|
165
|
+
if isBoolean(option)
|
166
|
+
if option
|
167
|
+
shouldLog = (label, type, funcName, stack) -> label
|
168
|
+
else
|
169
|
+
shouldLog = (label, type, funcName, stack) -> undef
|
52
170
|
if doDebugDebug
|
53
|
-
LOG "setDebugging
|
54
|
-
else if isString(
|
55
|
-
|
56
|
-
|
57
|
-
assert isArray(lFuncNames), "words('#{funcDoDebug}') returned non-array"
|
58
|
-
shouldLogFunc = (funcName) ->
|
59
|
-
funcMatch(funcName, lFuncNames)
|
171
|
+
LOG "setDebugging = #{option}"
|
172
|
+
else if isString(option)
|
173
|
+
lFuncList = getFuncList(option)
|
174
|
+
shouldLog = stdShouldLog
|
60
175
|
if doDebugDebug
|
61
|
-
LOG "setDebugging FUNCS: #{
|
62
|
-
|
63
|
-
|
176
|
+
LOG "setDebugging FUNCS: #{option}"
|
177
|
+
LOG 'lFuncList', lFuncList
|
178
|
+
else if isFunction(option)
|
179
|
+
shouldLog = option
|
64
180
|
if doDebugDebug
|
65
181
|
LOG "setDebugging to custom func"
|
66
182
|
else
|
67
|
-
croak "
|
68
|
-
|
69
|
-
if isFunction(funcDoLog)
|
70
|
-
assert isFunction(funcDoLog), "setDebugging: arg 2 not a function"
|
71
|
-
shouldLogString = funcDoLog
|
183
|
+
croak "bad parameter #{OL(option)}"
|
72
184
|
return
|
73
185
|
|
74
186
|
# ---------------------------------------------------------------------------
|
75
187
|
# --- export only to allow unit tests
|
76
188
|
|
77
|
-
export
|
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
|
78
216
|
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
217
|
+
# ---------------------------------------------------------------------------
|
218
|
+
# --- export only to allow unit tests
|
219
|
+
|
220
|
+
export funcMatch = (stack, lFuncList) ->
|
221
|
+
|
222
|
+
assert isArray(lFuncList), "not an array #{OL(lFuncList)}"
|
223
|
+
|
224
|
+
curFunc = stack.curFunc()
|
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
|
89
242
|
|
90
243
|
# ---------------------------------------------------------------------------
|
91
|
-
#
|
92
|
-
# 2. adjust debugging flag
|
93
|
-
# 3. return [mainPrefix, auxPrefix, hEnv, type] - hEnv can be undef
|
94
|
-
# 4. disable logging by setting type to undef
|
244
|
+
# --- type is one of: 'enter', 'return', 'string', 'object'
|
95
245
|
|
96
|
-
|
246
|
+
export getType = (str, nObjects) ->
|
97
247
|
|
98
|
-
if
|
248
|
+
if lMatches = str.match(///^
|
99
249
|
\s*
|
100
250
|
enter
|
101
251
|
\s+
|
102
252
|
([A-Za-z_][A-Za-z0-9_\.]*)
|
103
|
-
///)
|
253
|
+
///)
|
104
254
|
|
105
255
|
# --- We are entering function curFunc
|
106
|
-
|
107
|
-
|
108
|
-
hEnv = {
|
109
|
-
debugging
|
110
|
-
shouldLogFunc
|
111
|
-
shouldLogString
|
112
|
-
}
|
256
|
+
return ['enter', lMatches[1]]
|
113
257
|
|
114
|
-
|
115
|
-
if doDebugDebug
|
116
|
-
trans = "#{hEnv.debugging} => #{debugging}"
|
117
|
-
LOG " ENTER #{curFunc}, debugging: #{trans}"
|
118
|
-
[mainPre, auxPre] = stack.doCall(curFunc, hEnv, debugging)
|
119
|
-
return [
|
120
|
-
mainPre
|
121
|
-
auxPre
|
122
|
-
undef
|
123
|
-
if shouldLogFunc(curFunc) then 'enter' else undef
|
124
|
-
]
|
125
|
-
else if (lMatches = str.match(///^
|
258
|
+
else if lMatches = str.match(///^
|
126
259
|
\s*
|
127
260
|
return
|
128
261
|
.+
|
129
262
|
from
|
130
263
|
\s+
|
131
264
|
([A-Za-z_][A-Za-z0-9_\.]*)
|
132
|
-
///)
|
133
|
-
|
134
|
-
[mainPre, auxPre, hEnv] = stack.returnFrom(curFunc)
|
135
|
-
if doDebugDebug
|
136
|
-
LOG " RETURN FROM #{curFunc}"
|
137
|
-
return [
|
138
|
-
mainPre
|
139
|
-
auxPre
|
140
|
-
hEnv
|
141
|
-
if shouldLogFunc(curFunc) then 'return' else undef
|
142
|
-
]
|
143
|
-
else
|
144
|
-
[mainPre, auxPre, _] = stack.logStr()
|
145
|
-
return [
|
146
|
-
mainPre
|
147
|
-
auxPre
|
148
|
-
undef
|
149
|
-
if shouldLogString(str) then 'string' else undef
|
150
|
-
]
|
151
|
-
|
152
|
-
# ---------------------------------------------------------------------------
|
153
|
-
|
154
|
-
export debug = (lArgs...) ->
|
155
|
-
|
156
|
-
# --- We want to allow item to be undef. Therefore, we need to
|
157
|
-
# distinguish between 1 arg sent vs. 2 args sent
|
158
|
-
nArgs = lArgs.length
|
159
|
-
assert (nArgs==1) || (nArgs==2), "debug(): #{nArgs} args"
|
265
|
+
///)
|
266
|
+
return ['return', lMatches[1]]
|
160
267
|
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
"debug(): 1st arg #{OL(label)} should be a string"
|
166
|
-
|
167
|
-
if doDebugDebug
|
168
|
-
if nArgs==1
|
169
|
-
LOG "debug('#{escapeStr(label)}') - 1 arg"
|
170
|
-
else
|
171
|
-
LOG "debug('#{escapeStr(label)}', #{typeof item}) - 2 args"
|
172
|
-
LOG "debugging flag = #{OL(debugging)}"
|
173
|
-
|
174
|
-
# --- We always need to manipulate the stack when we encounter
|
175
|
-
# either "enter X" or "return from X", so we can't short-circuit
|
176
|
-
# when debugging is off
|
177
|
-
|
178
|
-
lResult = adjustStack(label)
|
179
|
-
if doDebugDebug
|
180
|
-
LOG 'lResult', lResult
|
181
|
-
[mainPre, auxPre, hEnv, type] = lResult
|
182
|
-
if doDebugDebug && (type == undef)
|
183
|
-
LOG "type is undef - NOT LOGGING"
|
184
|
-
|
185
|
-
hOptions = {
|
186
|
-
prefix: mainPre
|
187
|
-
itemPrefix: auxPre
|
188
|
-
}
|
189
|
-
|
190
|
-
switch type
|
191
|
-
when 'enter'
|
192
|
-
log label, hOptions
|
193
|
-
if (nArgs==2)
|
194
|
-
# --- don't repeat the label
|
195
|
-
logItem undef, item, hOptions
|
196
|
-
when 'return'
|
197
|
-
log label, hOptions
|
198
|
-
if (nArgs==2)
|
199
|
-
# --- don't repeat the label
|
200
|
-
logItem undef, item, hOptions
|
201
|
-
when 'string'
|
202
|
-
if (nArgs==2)
|
203
|
-
logItem label, item, hOptions
|
204
|
-
else
|
205
|
-
log label, hOptions
|
206
|
-
|
207
|
-
if hEnv
|
208
|
-
orgDebugging = debugging
|
209
|
-
{debugging, shouldLogFunc, shouldLogString} = hEnv
|
210
|
-
if doDebugDebug
|
211
|
-
trans = "#{orgDebugging} => #{debugging}"
|
212
|
-
LOG " Restore hEnv: debugging: #{trans}"
|
213
|
-
return true # allow use in boolean expressions
|
268
|
+
else if (nObjects > 0)
|
269
|
+
return ['objects', undef]
|
270
|
+
else
|
271
|
+
return ['string', undef]
|
214
272
|
|
215
273
|
# ---------------------------------------------------------------------------
|
216
274
|
|