@jdeighan/coffee-utils 7.0.58 → 7.0.61

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.58",
4
+ "version": "7.0.61",
5
5
  "description": "A set of utility functions for CoffeeScript",
6
6
  "main": "coffee_utils.js",
7
7
  "exports": {
package/src/arrow.coffee CHANGED
@@ -1,6 +1,6 @@
1
1
  # arrow.coffee
2
2
 
3
- import {undef, OL, setCharsAt} from '@jdeighan/coffee-utils'
3
+ import {undef, assert, OL, setCharsAt} from '@jdeighan/coffee-utils'
4
4
 
5
5
  # --- We use spaces here because Windows Terminal handles TAB chars badly
6
6
 
@@ -16,50 +16,41 @@ export clearIndent = space + space + space + space
16
16
 
17
17
  # ---------------------------------------------------------------------------
18
18
 
19
- export getPrefix = (level, option='none') ->
19
+ export prefix = (level, option='none') ->
20
20
 
21
- if level==0
22
- if (option == 'object')
23
- return clearIndent
24
- else
25
- return ''
26
21
  switch option
27
22
  when 'withArrow'
28
- result = oneIndent.repeat(level-1) + arrow
29
- when 'object'
30
- result = oneIndent.repeat(level) + clearIndent
31
- when 'none'
32
- result = oneIndent.repeat(level)
23
+ if (level == 0)
24
+ return arrow
25
+ else
26
+ return oneIndent.repeat(level-1) + arrow
27
+ when 'noLastVbar'
28
+ assert (level >= 1), "prefix(), noLastVbar but level=#{OL(level)}"
29
+ return oneIndent.repeat(level-1) + clearIndent
30
+ when 'noLast2Vbars'
31
+ assert (level >= 2), "prefix(), noLast2Vbars but level=#{OL(level)}"
32
+ return oneIndent.repeat(level-2) + clearIndent + clearIndent
33
33
  else
34
- throw new Error("getPrefix(): Bad option: '#{option}'")
35
- if result.length % 4 != 0
36
- throw new Error("getPrefix(): Bad prefix '#{result}'")
37
- return result
34
+ return oneIndent.repeat(level)
38
35
 
39
36
  # ---------------------------------------------------------------------------
40
37
 
41
38
  export addArrow = (prefix) ->
42
39
 
43
- # console.log "in addArrow(#{OL(prefix)})"
44
40
  pos = prefix.lastIndexOf(vbar)
45
- # console.log "pos = #{pos}"
46
41
  if (pos == -1)
47
42
  result = prefix
48
43
  else
49
44
  result = setCharsAt(prefix, pos, arrow)
50
- # console.log "result = #{OL(result)}"
51
45
  return result
52
46
 
53
47
  # ---------------------------------------------------------------------------
54
48
 
55
49
  export removeLastVbar = (prefix) ->
56
50
 
57
- # console.log "in removeLastVbar(#{OL(prefix)})"
58
51
  pos = prefix.lastIndexOf(vbar)
59
- # console.log "pos = #{pos}"
60
52
  if (pos == -1)
61
53
  result = prefix
62
54
  else
63
55
  result = setCharsAt(prefix, pos, ' ')
64
- # console.log "result = #{OL(result)}"
65
56
  return result
package/src/arrow.js CHANGED
@@ -2,6 +2,7 @@
2
2
  // arrow.coffee
3
3
  import {
4
4
  undef,
5
+ assert,
5
6
  OL,
6
7
  setCharsAt
7
8
  } from '@jdeighan/coffee-utils';
@@ -24,60 +25,46 @@ export var arrow = corner + hbar + arrowhead + space;
24
25
  export var clearIndent = space + space + space + space;
25
26
 
26
27
  // ---------------------------------------------------------------------------
27
- export var getPrefix = function(level, option = 'none') {
28
- var result;
29
- if (level === 0) {
30
- if (option === 'object') {
31
- return clearIndent;
32
- } else {
33
- return '';
34
- }
35
- }
28
+ export var prefix = function(level, option = 'none') {
36
29
  switch (option) {
37
30
  case 'withArrow':
38
- result = oneIndent.repeat(level - 1) + arrow;
39
- break;
40
- case 'object':
41
- result = oneIndent.repeat(level) + clearIndent;
42
- break;
43
- case 'none':
44
- result = oneIndent.repeat(level);
31
+ if (level === 0) {
32
+ return arrow;
33
+ } else {
34
+ return oneIndent.repeat(level - 1) + arrow;
35
+ }
45
36
  break;
37
+ case 'noLastVbar':
38
+ assert(level >= 1, `prefix(), noLastVbar but level=${OL(level)}`);
39
+ return oneIndent.repeat(level - 1) + clearIndent;
40
+ case 'noLast2Vbars':
41
+ assert(level >= 2, `prefix(), noLast2Vbars but level=${OL(level)}`);
42
+ return oneIndent.repeat(level - 2) + clearIndent + clearIndent;
46
43
  default:
47
- throw new Error(`getPrefix(): Bad option: '${option}'`);
44
+ return oneIndent.repeat(level);
48
45
  }
49
- if (result.length % 4 !== 0) {
50
- throw new Error(`getPrefix(): Bad prefix '${result}'`);
51
- }
52
- return result;
53
46
  };
54
47
 
55
48
  // ---------------------------------------------------------------------------
56
49
  export var addArrow = function(prefix) {
57
50
  var pos, result;
58
- // console.log "in addArrow(#{OL(prefix)})"
59
51
  pos = prefix.lastIndexOf(vbar);
60
- // console.log "pos = #{pos}"
61
52
  if (pos === -1) {
62
53
  result = prefix;
63
54
  } else {
64
55
  result = setCharsAt(prefix, pos, arrow);
65
56
  }
66
- // console.log "result = #{OL(result)}"
67
57
  return result;
68
58
  };
69
59
 
70
60
  // ---------------------------------------------------------------------------
71
61
  export var removeLastVbar = function(prefix) {
72
62
  var pos, result;
73
- // console.log "in removeLastVbar(#{OL(prefix)})"
74
63
  pos = prefix.lastIndexOf(vbar);
75
- // console.log "pos = #{pos}"
76
64
  if (pos === -1) {
77
65
  result = prefix;
78
66
  } else {
79
67
  result = setCharsAt(prefix, pos, ' ');
80
68
  }
81
- // console.log "result = #{OL(result)}"
82
69
  return result;
83
70
  };
@@ -1,10 +1,10 @@
1
1
  # call_stack.coffee
2
2
 
3
3
  import {
4
- undef, defined, croak, assert, OL, isBoolean, escapeStr,
4
+ undef, defined, croak, assert, OL, escapeStr, deepCopy,
5
+ isArray, isBoolean,
5
6
  } from '@jdeighan/coffee-utils'
6
- import {log, LOG} from '@jdeighan/coffee-utils/log'
7
- import {getPrefix} from '@jdeighan/coffee-utils/arrow'
7
+ import {LOG} from '@jdeighan/coffee-utils/log'
8
8
 
9
9
  doDebugStack = false
10
10
 
@@ -22,7 +22,6 @@ export class CallStack
22
22
  constructor: () ->
23
23
 
24
24
  @lStack = []
25
- @level = 0
26
25
 
27
26
  # ........................................................................
28
27
 
@@ -31,15 +30,16 @@ export class CallStack
31
30
  if doDebugStack
32
31
  LOG "RESET STACK"
33
32
  @lStack = []
34
- @level = 0
35
33
  return
36
34
 
37
35
  # ........................................................................
38
36
 
39
- enter: (funcName, oldFlag=undef) ->
37
+ enter: (funcName, lArgs=[], isLogged) ->
40
38
  # --- funcName might be <object>.<method>
41
39
 
42
- assert (oldFlag == undef), "enter() takes only 1 arg"
40
+ assert isArray(lArgs), "missing lArgs"
41
+ assert isBoolean(isLogged), "missing isLogged"
42
+
43
43
  if doDebugStack
44
44
  LOG "[--> ENTER #{funcName}]"
45
45
 
@@ -53,48 +53,40 @@ export class CallStack
53
53
  assert defined(lMatches), "Bad funcName: #{OL(funcName)}"
54
54
  [_, ident1, ident2] = lMatches
55
55
  if ident2
56
- @lStack.push({
57
- fullName: "#{ident1}.#{ident2}"
56
+ hStackItem = {
57
+ fullName: funcName # "#{ident1}.#{ident2}"
58
58
  funcName: ident2
59
- isLogged: false
60
- })
59
+ isLogged
60
+ lArgs: deepCopy(lArgs)
61
+ }
61
62
  else
62
- @lStack.push({
63
- fullName: ident1
63
+ hStackItem = {
64
+ fullName: funcName
64
65
  funcName: ident1
65
- isLogged: false
66
- })
67
- return
66
+ isLogged
67
+ lArgs: deepCopy(lArgs)
68
+ }
69
+ @lStack.push hStackItem
70
+ return hStackItem
68
71
 
69
72
  # ........................................................................
70
73
 
71
- isLogging: () ->
74
+ getLevel: () ->
72
75
 
73
- if (@lStack.length == 0)
74
- return false
75
- else
76
- return @lStack[@lStack.length - 1].isLogged
76
+ level = 0
77
+ for item in @lStack
78
+ if item.isLogged
79
+ level += 1
80
+ return level
77
81
 
78
82
  # ........................................................................
79
83
 
80
- isLoggingPrev: () ->
84
+ isLogging: () ->
81
85
 
82
- if (@lStack.length < 2)
86
+ if (@lStack.length == 0)
83
87
  return false
84
88
  else
85
- return @lStack[@lStack.length - 2].isLogged
86
-
87
- # ........................................................................
88
-
89
- logCurFunc: () ->
90
-
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
89
+ return @lStack[@lStack.length - 1].isLogged
98
90
 
99
91
  # ........................................................................
100
92
  # --- if stack is empty, log the error, but continue
@@ -109,26 +101,11 @@ export class CallStack
109
101
  return
110
102
 
111
103
  {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
126
-
127
- # ........................................................................
128
-
129
- getLevel: () ->
104
+ if (fullName != fName)
105
+ LOG "ERROR: returnFrom('#{fName}') but TOS is #{fullName}"
106
+ return
130
107
 
131
- return @level
108
+ return
132
109
 
133
110
  # ........................................................................
134
111
 
@@ -151,14 +128,38 @@ export class CallStack
151
128
  return false
152
129
 
153
130
  # ........................................................................
154
- # ........................................................................
155
131
 
156
- dump: (prefix='', label='CALL STACK') ->
132
+ dump: (label="CALL STACK") ->
157
133
 
158
- lLines = ["#{label}:"]
134
+ lLines = [label]
159
135
  if @lStack.length == 0
160
136
  lLines.push " <EMPTY>"
161
137
  else
162
138
  for item, i in @lStack
163
- lLines.push " #{i}: #{item.fullName} #{item.isLogged}"
164
- return lLines.join("\n") + "\n"
139
+ lLines.push " " + @callStr(i, item)
140
+ return lLines.join("\n")
141
+
142
+ # ........................................................................
143
+
144
+ callStr: (i, item) ->
145
+
146
+ sym = if item.isLogged then '*' else '-'
147
+ str = "#{i}: #{sym}#{item.fullName}"
148
+ for arg in item.lArgs
149
+ str += " #{OL(arg)}"
150
+ return str
151
+
152
+ # ........................................................................
153
+
154
+ sdump: (label='CALL STACK') ->
155
+
156
+ lFuncNames = []
157
+ for item in @lStack
158
+ if item.isLogged
159
+ lFuncNames.push '*' + item.fullName
160
+ else
161
+ lFuncNames.push item.fullName
162
+ if @lStack.length == 0
163
+ return "#{label} <EMPTY>"
164
+ else
165
+ return "#{label} #{lFuncNames.join(' ')}"
package/src/call_stack.js CHANGED
@@ -8,19 +8,16 @@ import {
8
8
  croak,
9
9
  assert,
10
10
  OL,
11
- isBoolean,
12
- escapeStr
11
+ escapeStr,
12
+ deepCopy,
13
+ isArray,
14
+ isBoolean
13
15
  } from '@jdeighan/coffee-utils';
14
16
 
15
17
  import {
16
- log,
17
18
  LOG
18
19
  } from '@jdeighan/coffee-utils/log';
19
20
 
20
- import {
21
- getPrefix
22
- } from '@jdeighan/coffee-utils/arrow';
23
-
24
21
  doDebugStack = false;
25
22
 
26
23
  // ---------------------------------------------------------------------------
@@ -32,7 +29,6 @@ export var debugStack = function(flag = true) {
32
29
  export var CallStack = class CallStack {
33
30
  constructor() {
34
31
  this.lStack = [];
35
- this.level = 0;
36
32
  }
37
33
 
38
34
  // ........................................................................
@@ -41,14 +37,14 @@ export var CallStack = class CallStack {
41
37
  LOG("RESET STACK");
42
38
  }
43
39
  this.lStack = [];
44
- this.level = 0;
45
40
  }
46
41
 
47
42
  // ........................................................................
48
- enter(funcName, oldFlag = undef) {
49
- var _, ident1, ident2, lMatches;
43
+ enter(funcName, lArgs = [], isLogged) {
44
+ var _, hStackItem, ident1, ident2, lMatches;
50
45
  // --- funcName might be <object>.<method>
51
- assert(oldFlag === undef, "enter() takes only 1 arg");
46
+ assert(isArray(lArgs), "missing lArgs");
47
+ assert(isBoolean(isLogged), "missing isLogged");
52
48
  if (doDebugStack) {
53
49
  LOG(`[--> ENTER ${funcName}]`);
54
50
  }
@@ -56,49 +52,47 @@ export var CallStack = class CallStack {
56
52
  assert(defined(lMatches), `Bad funcName: ${OL(funcName)}`);
57
53
  [_, ident1, ident2] = lMatches;
58
54
  if (ident2) {
59
- this.lStack.push({
60
- fullName: `${ident1}.${ident2}`,
55
+ hStackItem = {
56
+ fullName: funcName, // "#{ident1}.#{ident2}"
61
57
  funcName: ident2,
62
- isLogged: false
63
- });
58
+ isLogged,
59
+ lArgs: deepCopy(lArgs)
60
+ };
64
61
  } else {
65
- this.lStack.push({
66
- fullName: ident1,
62
+ hStackItem = {
63
+ fullName: funcName,
67
64
  funcName: ident1,
68
- isLogged: false
69
- });
65
+ isLogged,
66
+ lArgs: deepCopy(lArgs)
67
+ };
70
68
  }
69
+ this.lStack.push(hStackItem);
70
+ return hStackItem;
71
71
  }
72
72
 
73
73
  // ........................................................................
74
- isLogging() {
75
- if (this.lStack.length === 0) {
76
- return false;
77
- } else {
78
- return this.lStack[this.lStack.length - 1].isLogged;
74
+ getLevel() {
75
+ var item, j, len, level, ref;
76
+ level = 0;
77
+ ref = this.lStack;
78
+ for (j = 0, len = ref.length; j < len; j++) {
79
+ item = ref[j];
80
+ if (item.isLogged) {
81
+ level += 1;
82
+ }
79
83
  }
84
+ return level;
80
85
  }
81
86
 
82
87
  // ........................................................................
83
- isLoggingPrev() {
84
- if (this.lStack.length < 2) {
88
+ isLogging() {
89
+ if (this.lStack.length === 0) {
85
90
  return false;
86
91
  } else {
87
- return this.lStack[this.lStack.length - 2].isLogged;
92
+ return this.lStack[this.lStack.length - 1].isLogged;
88
93
  }
89
94
  }
90
95
 
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
96
  // ........................................................................
103
97
  // --- if stack is empty, log the error, but continue
104
98
  returnFrom(fName) {
@@ -111,28 +105,12 @@ export var CallStack = class CallStack {
111
105
  return;
112
106
  }
113
107
  ({fullName, isLogged} = this.lStack.pop());
114
- if (isLogged && (this.level > 0)) {
115
- this.level -= 1;
116
- }
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());
121
- if (isLogged && (this.level > 0)) {
122
- this.level -= 1;
123
- }
124
- }
125
108
  if (fullName !== fName) {
126
- this.dump();
127
- LOG(`BAD BAD BAD BAD returnFrom('${fName}')`);
109
+ LOG(`ERROR: returnFrom('${fName}') but TOS is ${fullName}`);
110
+ return;
128
111
  }
129
112
  }
130
113
 
131
- // ........................................................................
132
- getLevel() {
133
- return this.level;
134
- }
135
-
136
114
  // ........................................................................
137
115
  curFunc() {
138
116
  if (this.lStack.length === 0) {
@@ -158,20 +136,52 @@ export var CallStack = class CallStack {
158
136
  }
159
137
 
160
138
  // ........................................................................
161
- // ........................................................................
162
- dump(prefix = '', label = 'CALL STACK') {
139
+ dump(label = "CALL STACK") {
163
140
  var i, item, j, lLines, len, ref;
164
- lLines = [`${label}:`];
141
+ lLines = [label];
165
142
  if (this.lStack.length === 0) {
166
143
  lLines.push(" <EMPTY>");
167
144
  } else {
168
145
  ref = this.lStack;
169
146
  for (i = j = 0, len = ref.length; j < len; i = ++j) {
170
147
  item = ref[i];
171
- lLines.push(` ${i}: ${item.fullName} ${item.isLogged}`);
148
+ lLines.push(" " + this.callStr(i, item));
149
+ }
150
+ }
151
+ return lLines.join("\n");
152
+ }
153
+
154
+ // ........................................................................
155
+ callStr(i, item) {
156
+ var arg, j, len, ref, str, sym;
157
+ sym = item.isLogged ? '*' : '-';
158
+ str = `${i}: ${sym}${item.fullName}`;
159
+ ref = item.lArgs;
160
+ for (j = 0, len = ref.length; j < len; j++) {
161
+ arg = ref[j];
162
+ str += ` ${OL(arg)}`;
163
+ }
164
+ return str;
165
+ }
166
+
167
+ // ........................................................................
168
+ sdump(label = 'CALL STACK') {
169
+ var item, j, lFuncNames, len, ref;
170
+ lFuncNames = [];
171
+ ref = this.lStack;
172
+ for (j = 0, len = ref.length; j < len; j++) {
173
+ item = ref[j];
174
+ if (item.isLogged) {
175
+ lFuncNames.push('*' + item.fullName);
176
+ } else {
177
+ lFuncNames.push(item.fullName);
172
178
  }
173
179
  }
174
- return lLines.join("\n") + "\n";
180
+ if (this.lStack.length === 0) {
181
+ return `${label} <EMPTY>`;
182
+ } else {
183
+ return `${label} ${lFuncNames.join(' ')}`;
184
+ }
175
185
  }
176
186
 
177
187
  };
@@ -73,17 +73,11 @@ getCallers = (stackTrace, lExclude=[]) ->
73
73
  export assert = (cond, msg) ->
74
74
 
75
75
  if ! cond
76
- # try
77
- # throw new Error()
78
- # catch e
79
- # stackTrace = e.stack
80
76
  stackTrace = new Error().stack
81
77
  lCallers = getCallers(stackTrace, ['assert'])
82
78
 
83
- # console.log 'STACK'
84
- # console.log stackTrace
85
79
  console.log '--------------------'
86
- console.log 'CALL STACK:'
80
+ console.log 'JavaScript CALL STACK:'
87
81
  for caller in lCallers
88
82
  console.log " #{caller}"
89
83
  console.log '--------------------'
@@ -118,6 +112,16 @@ export getClassName = (obj) ->
118
112
 
119
113
  # ---------------------------------------------------------------------------
120
114
 
115
+ export patchStr = (bigstr, pos, str) ->
116
+
117
+ endpos = pos + str.length
118
+ if (endpos < bigstr.length)
119
+ return bigstr.substring(0, pos) + str + bigstr.substring(endpos)
120
+ else
121
+ return bigstr.substring(0, pos) + str
122
+
123
+ # ---------------------------------------------------------------------------
124
+
121
125
  export isString = (x) ->
122
126
 
123
127
  return typeof x == 'string' || x instanceof String
@@ -349,7 +353,15 @@ export ltrunc = (str, nChars) ->
349
353
 
350
354
  export deepCopy = (obj) ->
351
355
 
352
- return JSON.parse(JSON.stringify(obj))
356
+ if (obj == undef)
357
+ return undef
358
+ objStr = JSON.stringify(obj)
359
+ try
360
+ newObj = JSON.parse(objStr)
361
+ catch err
362
+ croak "ERROR: err.message", objStr
363
+
364
+ return newObj
353
365
 
354
366
  # ---------------------------------------------------------------------------
355
367
  # escapeStr - escape newlines, TAB chars, etc.
@@ -68,16 +68,10 @@ getCallers = function(stackTrace, lExclude = []) {
68
68
  export var assert = function(cond, msg) {
69
69
  var caller, i, lCallers, len, stackTrace;
70
70
  if (!cond) {
71
- // try
72
- // throw new Error()
73
- // catch e
74
- // stackTrace = e.stack
75
71
  stackTrace = new Error().stack;
76
72
  lCallers = getCallers(stackTrace, ['assert']);
77
- // console.log 'STACK'
78
- // console.log stackTrace
79
73
  console.log('--------------------');
80
- console.log('CALL STACK:');
74
+ console.log('JavaScript CALL STACK:');
81
75
  for (i = 0, len = lCallers.length; i < len; i++) {
82
76
  caller = lCallers[i];
83
77
  console.log(` ${caller}`);
@@ -112,6 +106,17 @@ export var getClassName = function(obj) {
112
106
  return obj.constructor.name;
113
107
  };
114
108
 
109
+ // ---------------------------------------------------------------------------
110
+ export var patchStr = function(bigstr, pos, str) {
111
+ var endpos;
112
+ endpos = pos + str.length;
113
+ if (endpos < bigstr.length) {
114
+ return bigstr.substring(0, pos) + str + bigstr.substring(endpos);
115
+ } else {
116
+ return bigstr.substring(0, pos) + str;
117
+ }
118
+ };
119
+
115
120
  // ---------------------------------------------------------------------------
116
121
  export var isString = function(x) {
117
122
  return typeof x === 'string' || x instanceof String;
@@ -347,7 +352,18 @@ export var ltrunc = function(str, nChars) {
347
352
  // ---------------------------------------------------------------------------
348
353
  // deepCopy - deep copy an array or object
349
354
  export var deepCopy = function(obj) {
350
- return JSON.parse(JSON.stringify(obj));
355
+ var err, newObj, objStr;
356
+ if (obj === undef) {
357
+ return undef;
358
+ }
359
+ objStr = JSON.stringify(obj);
360
+ try {
361
+ newObj = JSON.parse(objStr);
362
+ } catch (error1) {
363
+ err = error1;
364
+ croak("ERROR: err.message", objStr);
365
+ }
366
+ return newObj;
351
367
  };
352
368
 
353
369
  // ---------------------------------------------------------------------------