@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.
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
  // ---------------------------------------------------------------------------