@jdeighan/coffee-utils 4.1.10 → 4.1.14
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 +2 -1
- package/src/UnitTester.coffee +5 -1
- package/src/UnitTester.js +6 -1
- package/src/block_utils.coffee +1 -1
- package/src/block_utils.js +1 -1
- package/src/call_stack.coffee +43 -0
- package/src/call_stack.js +49 -0
- package/src/coffee_utils.coffee +7 -1
- package/src/coffee_utils.js +6 -1
- package/src/debug_utils.coffee +76 -90
- package/src/debug_utils.js +89 -86
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jdeighan/coffee-utils",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "4.1.
|
|
4
|
+
"version": "4.1.14",
|
|
5
5
|
"description": "A set of utility functions for CoffeeScript",
|
|
6
6
|
"main": "coffee_utils.js",
|
|
7
7
|
"exports": {
|
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
"./log": "./src/log_utils.js",
|
|
11
11
|
"./block": "./src/block_utils.js",
|
|
12
12
|
"./indent": "./src/indent_utils.js",
|
|
13
|
+
"./stack": "./src/call_stack.js",
|
|
13
14
|
"./debug": "./src/debug_utils.js",
|
|
14
15
|
"./svelte": "./src/svelte_utils.js",
|
|
15
16
|
"./test": "./src/UnitTester.js",
|
package/src/UnitTester.coffee
CHANGED
|
@@ -176,6 +176,10 @@ export class UnitTester
|
|
|
176
176
|
assert isInteger(lineNum),
|
|
177
177
|
"UnitTester.test(): arg 1 must be an integer"
|
|
178
178
|
|
|
179
|
+
if process.env.TEST_LINE_NUMBER
|
|
180
|
+
if Math.abs(lineNum) != parseInt(process.env.TEST_LINE_NUMBER)
|
|
181
|
+
return
|
|
182
|
+
|
|
179
183
|
@initialize()
|
|
180
184
|
@lineNum = lineNum # set an object property
|
|
181
185
|
|
|
@@ -196,7 +200,7 @@ export class UnitTester
|
|
|
196
200
|
got = @normalize(got)
|
|
197
201
|
catch err
|
|
198
202
|
errMsg = err.message || 'UNKNOWN ERROR'
|
|
199
|
-
log "got ERROR: #{errMsg}"
|
|
203
|
+
log "got ERROR in unit test: #{errMsg}"
|
|
200
204
|
|
|
201
205
|
expected = @transformExpected(expected)
|
|
202
206
|
if isString(expected)
|
package/src/UnitTester.js
CHANGED
|
@@ -186,6 +186,11 @@ export var UnitTester = class UnitTester {
|
|
|
186
186
|
test(lineNum, input, expected) {
|
|
187
187
|
var err, errMsg, got, whichTest;
|
|
188
188
|
assert(isInteger(lineNum), "UnitTester.test(): arg 1 must be an integer");
|
|
189
|
+
if (process.env.TEST_LINE_NUMBER) {
|
|
190
|
+
if (Math.abs(lineNum) !== parseInt(process.env.TEST_LINE_NUMBER)) {
|
|
191
|
+
return;
|
|
192
|
+
}
|
|
193
|
+
}
|
|
189
194
|
this.initialize();
|
|
190
195
|
this.lineNum = lineNum; // set an object property
|
|
191
196
|
if ((lineNum < 0) && process.env.FINALTEST) {
|
|
@@ -207,7 +212,7 @@ export var UnitTester = class UnitTester {
|
|
|
207
212
|
} catch (error1) {
|
|
208
213
|
err = error1;
|
|
209
214
|
errMsg = err.message || 'UNKNOWN ERROR';
|
|
210
|
-
log(`got ERROR: ${errMsg}`);
|
|
215
|
+
log(`got ERROR in unit test: ${errMsg}`);
|
|
211
216
|
}
|
|
212
217
|
expected = this.transformExpected(expected);
|
|
213
218
|
if (isString(expected)) {
|
package/src/block_utils.coffee
CHANGED
|
@@ -86,7 +86,7 @@ export joinBlocks = (lBlocks...) ->
|
|
|
86
86
|
|
|
87
87
|
lNonEmptyBlocks = []
|
|
88
88
|
for block in lBlocks
|
|
89
|
-
assert isString(block), "joinBlocks():
|
|
89
|
+
assert isString(block), "joinBlocks(): #{block} is not a string"
|
|
90
90
|
if nonEmpty(block)
|
|
91
91
|
lNonEmptyBlocks.push block
|
|
92
92
|
return lNonEmptyBlocks.join('\n')
|
package/src/block_utils.js
CHANGED
|
@@ -110,7 +110,7 @@ export var joinBlocks = function(...lBlocks) {
|
|
|
110
110
|
lNonEmptyBlocks = [];
|
|
111
111
|
for (i = 0, len1 = lBlocks.length; i < len1; i++) {
|
|
112
112
|
block = lBlocks[i];
|
|
113
|
-
assert(isString(block), `joinBlocks():
|
|
113
|
+
assert(isString(block), `joinBlocks(): ${block} is not a string`);
|
|
114
114
|
if (nonEmpty(block)) {
|
|
115
115
|
lNonEmptyBlocks.push(block);
|
|
116
116
|
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
# call_stack.coffee
|
|
2
|
+
|
|
3
|
+
import {undef, croak} from '@jdeighan/coffee-utils'
|
|
4
|
+
import {log} from '@jdeighan/coffee-utils/log'
|
|
5
|
+
|
|
6
|
+
# ---------------------------------------------------------------------------
|
|
7
|
+
|
|
8
|
+
export class CallStack
|
|
9
|
+
|
|
10
|
+
constructor: () ->
|
|
11
|
+
|
|
12
|
+
@reset()
|
|
13
|
+
|
|
14
|
+
# ........................................................................
|
|
15
|
+
|
|
16
|
+
call: (funcName, hInfo) ->
|
|
17
|
+
|
|
18
|
+
@lStack.push({funcName, hInfo})
|
|
19
|
+
return
|
|
20
|
+
|
|
21
|
+
# ........................................................................
|
|
22
|
+
|
|
23
|
+
returnFrom: (fName) ->
|
|
24
|
+
|
|
25
|
+
{funcName, hInfo} = @lStack.pop()
|
|
26
|
+
if funcName != fName
|
|
27
|
+
croak "returnFrom('#{fName}') but TOS is '#{funcName}'"
|
|
28
|
+
return hInfo
|
|
29
|
+
|
|
30
|
+
# ........................................................................
|
|
31
|
+
|
|
32
|
+
reset: () ->
|
|
33
|
+
|
|
34
|
+
@lStack = []
|
|
35
|
+
|
|
36
|
+
# ........................................................................
|
|
37
|
+
|
|
38
|
+
dump: (label='CALL STACK') ->
|
|
39
|
+
|
|
40
|
+
log "#{label}:"
|
|
41
|
+
for item, i in @lStack
|
|
42
|
+
log "#{i}: #{JSON.stringify(item)}"
|
|
43
|
+
return
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
// Generated by CoffeeScript 2.6.1
|
|
2
|
+
// call_stack.coffee
|
|
3
|
+
import {
|
|
4
|
+
undef,
|
|
5
|
+
croak
|
|
6
|
+
} from '@jdeighan/coffee-utils';
|
|
7
|
+
|
|
8
|
+
import {
|
|
9
|
+
log
|
|
10
|
+
} from '@jdeighan/coffee-utils/log';
|
|
11
|
+
|
|
12
|
+
// ---------------------------------------------------------------------------
|
|
13
|
+
export var CallStack = class CallStack {
|
|
14
|
+
constructor() {
|
|
15
|
+
this.reset();
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
// ........................................................................
|
|
19
|
+
call(funcName, hInfo) {
|
|
20
|
+
this.lStack.push({funcName, hInfo});
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
// ........................................................................
|
|
24
|
+
returnFrom(fName) {
|
|
25
|
+
var funcName, hInfo;
|
|
26
|
+
({funcName, hInfo} = this.lStack.pop());
|
|
27
|
+
if (funcName !== fName) {
|
|
28
|
+
croak(`returnFrom('${fName}') but TOS is '${funcName}'`);
|
|
29
|
+
}
|
|
30
|
+
return hInfo;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// ........................................................................
|
|
34
|
+
reset() {
|
|
35
|
+
return this.lStack = [];
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// ........................................................................
|
|
39
|
+
dump(label = 'CALL STACK') {
|
|
40
|
+
var i, item, j, len, ref;
|
|
41
|
+
log(`${label}:`);
|
|
42
|
+
ref = this.lStack;
|
|
43
|
+
for (i = j = 0, len = ref.length; j < len; i = ++j) {
|
|
44
|
+
item = ref[i];
|
|
45
|
+
log(`${i}: ${JSON.stringify(item)}`);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
};
|
package/src/coffee_utils.coffee
CHANGED
|
@@ -34,7 +34,7 @@ export assert = (cond, msg) ->
|
|
|
34
34
|
export croak = (err, label, obj) ->
|
|
35
35
|
|
|
36
36
|
message = if (typeof err == 'object') then err.message else err
|
|
37
|
-
log "ERROR: #{message}"
|
|
37
|
+
log "ERROR (croak): #{message}"
|
|
38
38
|
log label, obj
|
|
39
39
|
if (typeof err == 'object')
|
|
40
40
|
throw err
|
|
@@ -74,6 +74,12 @@ export isString = (x) ->
|
|
|
74
74
|
|
|
75
75
|
# ---------------------------------------------------------------------------
|
|
76
76
|
|
|
77
|
+
export isBoolean = (x) ->
|
|
78
|
+
|
|
79
|
+
return typeof x == 'boolean'
|
|
80
|
+
|
|
81
|
+
# ---------------------------------------------------------------------------
|
|
82
|
+
|
|
77
83
|
export isNumber = (x) ->
|
|
78
84
|
|
|
79
85
|
return typeof x == 'number' || x instanceof Number
|
package/src/coffee_utils.js
CHANGED
|
@@ -37,7 +37,7 @@ export var assert = function(cond, msg) {
|
|
|
37
37
|
export var croak = function(err, label, obj) {
|
|
38
38
|
var message;
|
|
39
39
|
message = (typeof err === 'object') ? err.message : err;
|
|
40
|
-
log(`ERROR: ${message}`);
|
|
40
|
+
log(`ERROR (croak): ${message}`);
|
|
41
41
|
log(label, obj);
|
|
42
42
|
if (typeof err === 'object') {
|
|
43
43
|
throw err;
|
|
@@ -77,6 +77,11 @@ export var isString = function(x) {
|
|
|
77
77
|
return typeof x === 'string' || x instanceof String;
|
|
78
78
|
};
|
|
79
79
|
|
|
80
|
+
// ---------------------------------------------------------------------------
|
|
81
|
+
export var isBoolean = function(x) {
|
|
82
|
+
return typeof x === 'boolean';
|
|
83
|
+
};
|
|
84
|
+
|
|
80
85
|
// ---------------------------------------------------------------------------
|
|
81
86
|
export var isNumber = function(x) {
|
|
82
87
|
return typeof x === 'number' || x instanceof Number;
|
package/src/debug_utils.coffee
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
# debug_utils.coffee
|
|
2
2
|
|
|
3
3
|
import {
|
|
4
|
-
assert, undef, error, croak, warn,
|
|
5
|
-
oneline, escapeStr, isNumber, isArray,
|
|
4
|
+
assert, undef, error, croak, warn, isString, isFunction, isBoolean,
|
|
5
|
+
oneline, escapeStr, isNumber, isArray, words,
|
|
6
6
|
} from '@jdeighan/coffee-utils'
|
|
7
7
|
import {blockToArray} from '@jdeighan/coffee-utils/block'
|
|
8
8
|
import {log, setLogger} from '@jdeighan/coffee-utils/log'
|
|
9
9
|
import {slurp} from '@jdeighan/coffee-utils/fs'
|
|
10
|
+
import {CallStack} from '@jdeighan/coffee-utils/stack'
|
|
10
11
|
|
|
11
12
|
vbar = '│' # unicode 2502
|
|
12
13
|
hbar = '─' # unicode 2500
|
|
@@ -17,91 +18,105 @@ indent = vbar + ' '
|
|
|
17
18
|
arrow = corner + hbar + arrowhead + ' '
|
|
18
19
|
|
|
19
20
|
debugLevel = 0 # controls amount of indentation - we ensure it's never < 0
|
|
21
|
+
stdLogger = false
|
|
20
22
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
# --- These are saved/restored in lDebugStack
|
|
23
|
+
# --- These are saved/restored on the call stack
|
|
24
24
|
export debugging = false
|
|
25
|
-
|
|
26
|
-
lDebugFuncs = undef # --- names of functions to debug
|
|
25
|
+
shouldDebug = shouldLog = undef
|
|
27
26
|
|
|
28
|
-
|
|
27
|
+
stack = new CallStack()
|
|
29
28
|
|
|
30
29
|
# ---------------------------------------------------------------------------
|
|
31
30
|
|
|
32
|
-
export
|
|
31
|
+
export resetDebugging = (funcDoDebug=undef, funcDoLog=undef) ->
|
|
33
32
|
|
|
34
|
-
|
|
33
|
+
debugging = false
|
|
34
|
+
debugLevel = 0
|
|
35
|
+
stack.reset()
|
|
36
|
+
shouldDebug = (funcName) -> debugging
|
|
37
|
+
shouldLog = (str) -> debugging
|
|
38
|
+
if funcDoDebug
|
|
39
|
+
setDebugging funcDoDebug, funcDoLog
|
|
35
40
|
return
|
|
36
41
|
|
|
37
42
|
# ---------------------------------------------------------------------------
|
|
38
43
|
|
|
39
|
-
|
|
44
|
+
export setDebugging = (funcDoDebug=undef, funcDoLog=undef) ->
|
|
40
45
|
|
|
41
|
-
if
|
|
42
|
-
|
|
46
|
+
if isBoolean(funcDoDebug)
|
|
47
|
+
debugging = funcDoDebug
|
|
48
|
+
else if isString(funcDoDebug)
|
|
49
|
+
debugging = false
|
|
50
|
+
lFuncNames = words(funcDoDebug)
|
|
51
|
+
assert isArray(lFuncNames), "words('#{funcDoDebug}') returned non-array"
|
|
52
|
+
shouldDebug = (funcName) ->
|
|
53
|
+
debugging || funcMatch(funcName, lFuncNames)
|
|
54
|
+
else if isFunction(funcDoDebug)
|
|
55
|
+
shouldDebug = funcDoDebug
|
|
43
56
|
else
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
57
|
+
croak "setDebugging(): bad parameter #{oneline(funcDoDebug)}"
|
|
58
|
+
|
|
59
|
+
if funcDoLog
|
|
60
|
+
assert isFunction(funcDoLog), "setDebugging: arg 2 not a function"
|
|
61
|
+
shouldLog = funcDoLog
|
|
47
62
|
return
|
|
48
63
|
|
|
49
64
|
# ---------------------------------------------------------------------------
|
|
65
|
+
# --- export only to allow unit tests
|
|
50
66
|
|
|
51
|
-
|
|
67
|
+
export funcMatch = (curFunc, lFuncNames) ->
|
|
52
68
|
|
|
53
|
-
|
|
69
|
+
assert isString(curFunc), "funcMatch(): not a string"
|
|
70
|
+
assert isArray(lFuncNames), "funcMatch(): bad array #{lFuncNames}"
|
|
71
|
+
if lFuncNames.includes(curFunc)
|
|
72
|
+
return true
|
|
73
|
+
else if (lMatches = curFunc.match(reMethod)) \
|
|
74
|
+
&& ([_, cls, meth] = lMatches) \
|
|
75
|
+
&& lFuncNames.includes(meth)
|
|
76
|
+
return true
|
|
77
|
+
else
|
|
78
|
+
return false
|
|
54
79
|
|
|
55
80
|
# ---------------------------------------------------------------------------
|
|
56
81
|
|
|
57
|
-
|
|
82
|
+
curEnv = () ->
|
|
58
83
|
|
|
59
|
-
|
|
60
|
-
return
|
|
84
|
+
return {debugging, shouldDebug, shouldLog}
|
|
61
85
|
|
|
62
86
|
# ---------------------------------------------------------------------------
|
|
63
87
|
|
|
64
|
-
|
|
88
|
+
setEnv = (hEnv) ->
|
|
65
89
|
|
|
66
|
-
|
|
67
|
-
debugging,
|
|
68
|
-
ifMatches,
|
|
69
|
-
lDebugFuncs,
|
|
70
|
-
})
|
|
90
|
+
{debugging, shouldDebug, shouldLog} = hEnv
|
|
71
91
|
return
|
|
72
92
|
|
|
73
|
-
|
|
93
|
+
# ---------------------------------------------------------------------------
|
|
74
94
|
|
|
75
|
-
|
|
76
|
-
debugging = false
|
|
77
|
-
ifMatches = undef
|
|
78
|
-
lDebugFuncs = undef
|
|
79
|
-
else
|
|
80
|
-
h = lDebugStack.pop()
|
|
81
|
-
{debugging, ifMatches, lDebugFuncs} = h
|
|
95
|
+
export useStdLogger = (flag=true) ->
|
|
82
96
|
|
|
97
|
+
stdLogger = flag
|
|
83
98
|
return
|
|
84
99
|
|
|
85
100
|
# ---------------------------------------------------------------------------
|
|
86
101
|
|
|
87
|
-
|
|
102
|
+
logger = (lArgs...) ->
|
|
88
103
|
|
|
89
|
-
if
|
|
90
|
-
|
|
104
|
+
if stdLogger
|
|
105
|
+
log lArgs...
|
|
91
106
|
else
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
debugging = true
|
|
96
|
-
else if isString(x)
|
|
97
|
-
debugging = false
|
|
98
|
-
lDebugFuncs = words(x)
|
|
99
|
-
else
|
|
100
|
-
croak "setDebugging(): bad parameter #{oneline(x)}"
|
|
107
|
+
orgLogger = setLogger(console.log)
|
|
108
|
+
log lArgs...
|
|
109
|
+
setLogger(orgLogger)
|
|
101
110
|
return
|
|
102
111
|
|
|
103
112
|
# ---------------------------------------------------------------------------
|
|
104
113
|
|
|
114
|
+
stripArrow = (prefix) ->
|
|
115
|
+
|
|
116
|
+
return prefix.replace(arrow, ' ')
|
|
117
|
+
|
|
118
|
+
# ---------------------------------------------------------------------------
|
|
119
|
+
|
|
105
120
|
getPrefix = (level) ->
|
|
106
121
|
|
|
107
122
|
if (level < 0)
|
|
@@ -111,17 +126,6 @@ getPrefix = (level) ->
|
|
|
111
126
|
|
|
112
127
|
# ---------------------------------------------------------------------------
|
|
113
128
|
|
|
114
|
-
export resetDebugging = () ->
|
|
115
|
-
|
|
116
|
-
debugging = false
|
|
117
|
-
debugLevel = 0
|
|
118
|
-
ifMatches = undef
|
|
119
|
-
lDebugFuncs = undef
|
|
120
|
-
lDebugStack = []
|
|
121
|
-
return
|
|
122
|
-
|
|
123
|
-
# ---------------------------------------------------------------------------
|
|
124
|
-
|
|
125
129
|
export debug = (lArgs...) ->
|
|
126
130
|
# --- either 1 or 2 args
|
|
127
131
|
|
|
@@ -130,7 +134,7 @@ export debug = (lArgs...) ->
|
|
|
130
134
|
# when debugging is off
|
|
131
135
|
|
|
132
136
|
nArgs = lArgs.length
|
|
133
|
-
assert ((nArgs
|
|
137
|
+
assert ((nArgs == 1) || (nArgs == 2)), "debug(); Bad # args #{nArgs}"
|
|
134
138
|
str = lArgs[0]
|
|
135
139
|
|
|
136
140
|
# --- str must always be a string
|
|
@@ -153,6 +157,8 @@ export debug = (lArgs...) ->
|
|
|
153
157
|
///))
|
|
154
158
|
entering = true
|
|
155
159
|
curFunc = lMatches[1]
|
|
160
|
+
stack.call(curFunc, curEnv())
|
|
161
|
+
debugging = shouldDebug(curFunc, debugging)
|
|
156
162
|
else if (lMatches = str.match(///^
|
|
157
163
|
\s*
|
|
158
164
|
return
|
|
@@ -163,11 +169,9 @@ export debug = (lArgs...) ->
|
|
|
163
169
|
///))
|
|
164
170
|
returning = true
|
|
165
171
|
curFunc = lMatches[1]
|
|
172
|
+
hInfo = stack.returnFrom(curFunc)
|
|
166
173
|
|
|
167
|
-
if
|
|
168
|
-
setDebugging true
|
|
169
|
-
|
|
170
|
-
if debugging && (! ifMatches? || str.match(ifMatches))
|
|
174
|
+
if debugging && shouldLog(str)
|
|
171
175
|
|
|
172
176
|
# --- set the prefix, i.e. indentation to use
|
|
173
177
|
if returning
|
|
@@ -186,14 +190,15 @@ export debug = (lArgs...) ->
|
|
|
186
190
|
logItem: true,
|
|
187
191
|
itemPrefix: stripArrow(prefix),
|
|
188
192
|
}
|
|
189
|
-
if returning && (debugLevel > 0)
|
|
190
|
-
debugLevel -= 1
|
|
191
193
|
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
194
|
+
# --- Adjust debug level
|
|
195
|
+
if returning
|
|
196
|
+
if debugLevel > 0
|
|
197
|
+
debugLevel -= 1
|
|
198
|
+
setEnv(hInfo)
|
|
199
|
+
else if entering
|
|
200
|
+
if debugging
|
|
201
|
+
debugLevel += 1
|
|
197
202
|
return
|
|
198
203
|
|
|
199
204
|
# ---------------------------------------------------------------------------
|
|
@@ -204,21 +209,6 @@ reMethod = ///^
|
|
|
204
209
|
([A-Za-z_][A-Za-z0-9_]*)
|
|
205
210
|
$///
|
|
206
211
|
|
|
207
|
-
# ---------------------------------------------------------------------------
|
|
208
|
-
# --- export only to allow unit tests
|
|
209
|
-
|
|
210
|
-
export funcMatch = (curFunc) ->
|
|
211
|
-
|
|
212
|
-
assert isString(curFunc), "funcMatch(): not a string"
|
|
213
|
-
if lDebugFuncs.includes(curFunc)
|
|
214
|
-
return true
|
|
215
|
-
else if (lMatches = curFunc.match(reMethod)) \
|
|
216
|
-
&& ([_, cls, meth] = lMatches) \
|
|
217
|
-
&& lDebugFuncs.includes(meth)
|
|
218
|
-
return true
|
|
219
|
-
else
|
|
220
|
-
return false
|
|
221
|
-
|
|
222
212
|
# ---------------------------------------------------------------------------
|
|
223
213
|
|
|
224
214
|
export checkTrace = (block) ->
|
|
@@ -256,9 +246,5 @@ export checkTrace = (block) ->
|
|
|
256
246
|
return
|
|
257
247
|
|
|
258
248
|
# ---------------------------------------------------------------------------
|
|
259
|
-
# --- export only to allow unit tests
|
|
260
249
|
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
checkTrace(slurp(filepath))
|
|
264
|
-
return
|
|
250
|
+
resetDebugging()
|
package/src/debug_utils.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// Generated by CoffeeScript 2.6.1
|
|
2
2
|
// debug_utils.coffee
|
|
3
|
-
var arrow, arrowhead, corner, debugLevel, getPrefix, hbar,
|
|
3
|
+
var arrow, arrowhead, corner, curEnv, debugLevel, getPrefix, hbar, indent, logger, reMethod, setEnv, shouldDebug, shouldLog, stack, stdLogger, stripArrow, vbar;
|
|
4
4
|
|
|
5
5
|
import {
|
|
6
6
|
assert,
|
|
@@ -8,13 +8,14 @@ import {
|
|
|
8
8
|
error,
|
|
9
9
|
croak,
|
|
10
10
|
warn,
|
|
11
|
-
words,
|
|
12
11
|
isString,
|
|
13
12
|
isFunction,
|
|
13
|
+
isBoolean,
|
|
14
14
|
oneline,
|
|
15
15
|
escapeStr,
|
|
16
16
|
isNumber,
|
|
17
|
-
isArray
|
|
17
|
+
isArray,
|
|
18
|
+
words
|
|
18
19
|
} from '@jdeighan/coffee-utils';
|
|
19
20
|
|
|
20
21
|
import {
|
|
@@ -30,6 +31,10 @@ import {
|
|
|
30
31
|
slurp
|
|
31
32
|
} from '@jdeighan/coffee-utils/fs';
|
|
32
33
|
|
|
34
|
+
import {
|
|
35
|
+
CallStack
|
|
36
|
+
} from '@jdeighan/coffee-utils/stack';
|
|
37
|
+
|
|
33
38
|
vbar = '│'; // unicode 2502
|
|
34
39
|
|
|
35
40
|
hbar = '─'; // unicode 2500
|
|
@@ -44,77 +49,99 @@ arrow = corner + hbar + arrowhead + ' ';
|
|
|
44
49
|
|
|
45
50
|
debugLevel = 0; // controls amount of indentation - we ensure it's never < 0
|
|
46
51
|
|
|
47
|
-
|
|
52
|
+
stdLogger = false;
|
|
48
53
|
|
|
49
|
-
// --- These are saved/restored
|
|
54
|
+
// --- These are saved/restored on the call stack
|
|
50
55
|
export var debugging = false;
|
|
51
56
|
|
|
52
|
-
|
|
57
|
+
shouldDebug = shouldLog = undef;
|
|
53
58
|
|
|
54
|
-
|
|
59
|
+
stack = new CallStack();
|
|
55
60
|
|
|
56
|
-
|
|
61
|
+
// ---------------------------------------------------------------------------
|
|
62
|
+
export var resetDebugging = function(funcDoDebug = undef, funcDoLog = undef) {
|
|
63
|
+
debugging = false;
|
|
64
|
+
debugLevel = 0;
|
|
65
|
+
stack.reset();
|
|
66
|
+
shouldDebug = function(funcName) {
|
|
67
|
+
return debugging;
|
|
68
|
+
};
|
|
69
|
+
shouldLog = function(str) {
|
|
70
|
+
return debugging;
|
|
71
|
+
};
|
|
72
|
+
if (funcDoDebug) {
|
|
73
|
+
setDebugging(funcDoDebug, funcDoLog);
|
|
74
|
+
}
|
|
75
|
+
};
|
|
57
76
|
|
|
58
77
|
// ---------------------------------------------------------------------------
|
|
59
|
-
export var
|
|
60
|
-
|
|
78
|
+
export var setDebugging = function(funcDoDebug = undef, funcDoLog = undef) {
|
|
79
|
+
var lFuncNames;
|
|
80
|
+
if (isBoolean(funcDoDebug)) {
|
|
81
|
+
debugging = funcDoDebug;
|
|
82
|
+
} else if (isString(funcDoDebug)) {
|
|
83
|
+
debugging = false;
|
|
84
|
+
lFuncNames = words(funcDoDebug);
|
|
85
|
+
assert(isArray(lFuncNames), `words('${funcDoDebug}') returned non-array`);
|
|
86
|
+
shouldDebug = function(funcName) {
|
|
87
|
+
return debugging || funcMatch(funcName, lFuncNames);
|
|
88
|
+
};
|
|
89
|
+
} else if (isFunction(funcDoDebug)) {
|
|
90
|
+
shouldDebug = funcDoDebug;
|
|
91
|
+
} else {
|
|
92
|
+
croak(`setDebugging(): bad parameter ${oneline(funcDoDebug)}`);
|
|
93
|
+
}
|
|
94
|
+
if (funcDoLog) {
|
|
95
|
+
assert(isFunction(funcDoLog), "setDebugging: arg 2 not a function");
|
|
96
|
+
shouldLog = funcDoLog;
|
|
97
|
+
}
|
|
61
98
|
};
|
|
62
99
|
|
|
63
100
|
// ---------------------------------------------------------------------------
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
101
|
+
// --- export only to allow unit tests
|
|
102
|
+
export var funcMatch = function(curFunc, lFuncNames) {
|
|
103
|
+
var _, cls, lMatches, meth;
|
|
104
|
+
assert(isString(curFunc), "funcMatch(): not a string");
|
|
105
|
+
assert(isArray(lFuncNames), `funcMatch(): bad array ${lFuncNames}`);
|
|
106
|
+
if (lFuncNames.includes(curFunc)) {
|
|
107
|
+
return true;
|
|
108
|
+
} else if ((lMatches = curFunc.match(reMethod)) && ([_, cls, meth] = lMatches) && lFuncNames.includes(meth)) {
|
|
109
|
+
return true;
|
|
68
110
|
} else {
|
|
69
|
-
|
|
70
|
-
log(...lArgs);
|
|
71
|
-
setLogger(orgLogger);
|
|
111
|
+
return false;
|
|
72
112
|
}
|
|
73
113
|
};
|
|
74
114
|
|
|
75
115
|
// ---------------------------------------------------------------------------
|
|
76
|
-
|
|
77
|
-
return
|
|
116
|
+
curEnv = function() {
|
|
117
|
+
return {debugging, shouldDebug, shouldLog};
|
|
78
118
|
};
|
|
79
119
|
|
|
80
120
|
// ---------------------------------------------------------------------------
|
|
81
|
-
|
|
82
|
-
|
|
121
|
+
setEnv = function(hEnv) {
|
|
122
|
+
({debugging, shouldDebug, shouldLog} = hEnv);
|
|
83
123
|
};
|
|
84
124
|
|
|
85
125
|
// ---------------------------------------------------------------------------
|
|
86
|
-
|
|
87
|
-
|
|
126
|
+
export var useStdLogger = function(flag = true) {
|
|
127
|
+
stdLogger = flag;
|
|
88
128
|
};
|
|
89
129
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
lDebugFuncs = undef;
|
|
130
|
+
// ---------------------------------------------------------------------------
|
|
131
|
+
logger = function(...lArgs) {
|
|
132
|
+
var orgLogger;
|
|
133
|
+
if (stdLogger) {
|
|
134
|
+
log(...lArgs);
|
|
96
135
|
} else {
|
|
97
|
-
|
|
98
|
-
(
|
|
136
|
+
orgLogger = setLogger(console.log);
|
|
137
|
+
log(...lArgs);
|
|
138
|
+
setLogger(orgLogger);
|
|
99
139
|
}
|
|
100
140
|
};
|
|
101
141
|
|
|
102
142
|
// ---------------------------------------------------------------------------
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
restoreDebugEnv();
|
|
106
|
-
} else {
|
|
107
|
-
// --- save current setting
|
|
108
|
-
saveDebugEnv();
|
|
109
|
-
if (x === true) {
|
|
110
|
-
debugging = true;
|
|
111
|
-
} else if (isString(x)) {
|
|
112
|
-
debugging = false;
|
|
113
|
-
lDebugFuncs = words(x);
|
|
114
|
-
} else {
|
|
115
|
-
croak(`setDebugging(): bad parameter ${oneline(x)}`);
|
|
116
|
-
}
|
|
117
|
-
}
|
|
143
|
+
stripArrow = function(prefix) {
|
|
144
|
+
return prefix.replace(arrow, ' ');
|
|
118
145
|
};
|
|
119
146
|
|
|
120
147
|
// ---------------------------------------------------------------------------
|
|
@@ -126,25 +153,16 @@ getPrefix = function(level) {
|
|
|
126
153
|
return ' '.repeat(level);
|
|
127
154
|
};
|
|
128
155
|
|
|
129
|
-
// ---------------------------------------------------------------------------
|
|
130
|
-
export var resetDebugging = function() {
|
|
131
|
-
debugging = false;
|
|
132
|
-
debugLevel = 0;
|
|
133
|
-
ifMatches = undef;
|
|
134
|
-
lDebugFuncs = undef;
|
|
135
|
-
lDebugStack = [];
|
|
136
|
-
};
|
|
137
|
-
|
|
138
156
|
// ---------------------------------------------------------------------------
|
|
139
157
|
export var debug = function(...lArgs) {
|
|
140
|
-
var curFunc, entering, item, lMatches, nArgs, prefix, returning, str;
|
|
158
|
+
var curFunc, entering, hInfo, item, lMatches, nArgs, prefix, returning, str;
|
|
141
159
|
// --- either 1 or 2 args
|
|
142
160
|
|
|
143
161
|
// --- We always need to manipulate the stack when we encounter
|
|
144
162
|
// either "enter X" or "return from X", so we can't short-circuit
|
|
145
163
|
// when debugging is off
|
|
146
164
|
nArgs = lArgs.length;
|
|
147
|
-
assert((nArgs
|
|
165
|
+
assert((nArgs === 1) || (nArgs === 2), `debug(); Bad # args ${nArgs}`);
|
|
148
166
|
str = lArgs[0];
|
|
149
167
|
// --- str must always be a string
|
|
150
168
|
// if 2 args, then str is meant to be a label for the item
|
|
@@ -158,14 +176,14 @@ export var debug = function(...lArgs) {
|
|
|
158
176
|
if ((lMatches = str.match(/^\s*enter\s+([A-Za-z_][A-Za-z0-9_\.]*)/))) {
|
|
159
177
|
entering = true;
|
|
160
178
|
curFunc = lMatches[1];
|
|
179
|
+
stack.call(curFunc, curEnv());
|
|
180
|
+
debugging = shouldDebug(curFunc, debugging);
|
|
161
181
|
} else if ((lMatches = str.match(/^\s*return.*from\s+([A-Za-z_][A-Za-z0-9_\.]*)/))) {
|
|
162
182
|
returning = true;
|
|
163
183
|
curFunc = lMatches[1];
|
|
184
|
+
hInfo = stack.returnFrom(curFunc);
|
|
164
185
|
}
|
|
165
|
-
if (
|
|
166
|
-
setDebugging(true);
|
|
167
|
-
}
|
|
168
|
-
if (debugging && ((ifMatches == null) || str.match(ifMatches))) {
|
|
186
|
+
if (debugging && shouldLog(str)) {
|
|
169
187
|
// --- set the prefix, i.e. indentation to use
|
|
170
188
|
if (returning) {
|
|
171
189
|
if (debugLevel === 0) {
|
|
@@ -185,35 +203,23 @@ export var debug = function(...lArgs) {
|
|
|
185
203
|
itemPrefix: stripArrow(prefix)
|
|
186
204
|
});
|
|
187
205
|
}
|
|
188
|
-
|
|
206
|
+
}
|
|
207
|
+
// --- Adjust debug level
|
|
208
|
+
if (returning) {
|
|
209
|
+
if (debugLevel > 0) {
|
|
189
210
|
debugLevel -= 1;
|
|
190
211
|
}
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
debugLevel += 1;
|
|
212
|
+
setEnv(hInfo);
|
|
213
|
+
} else if (entering) {
|
|
214
|
+
if (debugging) {
|
|
215
|
+
debugLevel += 1;
|
|
216
|
+
}
|
|
197
217
|
}
|
|
198
218
|
};
|
|
199
219
|
|
|
200
220
|
// ---------------------------------------------------------------------------
|
|
201
221
|
reMethod = /^([A-Za-z_][A-Za-z0-9_]*)\.([A-Za-z_][A-Za-z0-9_]*)$/;
|
|
202
222
|
|
|
203
|
-
// ---------------------------------------------------------------------------
|
|
204
|
-
// --- export only to allow unit tests
|
|
205
|
-
export var funcMatch = function(curFunc) {
|
|
206
|
-
var _, cls, lMatches, meth;
|
|
207
|
-
assert(isString(curFunc), "funcMatch(): not a string");
|
|
208
|
-
if (lDebugFuncs.includes(curFunc)) {
|
|
209
|
-
return true;
|
|
210
|
-
} else if ((lMatches = curFunc.match(reMethod)) && ([_, cls, meth] = lMatches) && lDebugFuncs.includes(meth)) {
|
|
211
|
-
return true;
|
|
212
|
-
} else {
|
|
213
|
-
return false;
|
|
214
|
-
}
|
|
215
|
-
};
|
|
216
|
-
|
|
217
223
|
// ---------------------------------------------------------------------------
|
|
218
224
|
export var checkTrace = function(block) {
|
|
219
225
|
var funcName, i, lMatches, lStack, len, len1, line, ref;
|
|
@@ -244,7 +250,4 @@ export var checkTrace = function(block) {
|
|
|
244
250
|
};
|
|
245
251
|
|
|
246
252
|
// ---------------------------------------------------------------------------
|
|
247
|
-
|
|
248
|
-
export var checkTraceFile = function(filepath) {
|
|
249
|
-
checkTrace(slurp(filepath));
|
|
250
|
-
};
|
|
253
|
+
resetDebugging();
|