@jdeighan/coffee-utils 7.0.59 → 7.0.62

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.59",
4
+ "version": "7.0.62",
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,14 +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) ->
37
+ enter: (funcName, lArgs=[], isLogged) ->
40
38
  # --- funcName might be <object>.<method>
41
39
 
40
+ assert isArray(lArgs), "missing lArgs"
41
+ assert isBoolean(isLogged), "missing isLogged"
42
+
42
43
  if doDebugStack
43
44
  LOG "[--> ENTER #{funcName}]"
44
45
 
@@ -52,24 +53,31 @@ export class CallStack
52
53
  assert defined(lMatches), "Bad funcName: #{OL(funcName)}"
53
54
  [_, ident1, ident2] = lMatches
54
55
  if ident2
55
- @lStack.push({
56
+ hStackItem = {
56
57
  fullName: funcName # "#{ident1}.#{ident2}"
57
58
  funcName: ident2
58
- isLogged: false
59
- })
59
+ isLogged
60
+ lArgs: deepCopy(lArgs)
61
+ }
60
62
  else
61
- @lStack.push({
63
+ hStackItem = {
62
64
  fullName: funcName
63
65
  funcName: ident1
64
- isLogged: false
65
- })
66
- return
66
+ isLogged
67
+ lArgs: deepCopy(lArgs)
68
+ }
69
+ @lStack.push hStackItem
70
+ return hStackItem
67
71
 
68
72
  # ........................................................................
69
73
 
70
74
  getLevel: () ->
71
75
 
72
- return @level
76
+ level = 0
77
+ for item in @lStack
78
+ if item.isLogged
79
+ level += 1
80
+ return level
73
81
 
74
82
  # ........................................................................
75
83
 
@@ -80,32 +88,6 @@ export class CallStack
80
88
  else
81
89
  return @lStack[@lStack.length - 1].isLogged
82
90
 
83
- # ........................................................................
84
-
85
- isLoggingPrev: () ->
86
-
87
- if (@lStack.length < 2)
88
- return false
89
- else
90
- return @lStack[@lStack.length - 2].isLogged
91
-
92
- # ........................................................................
93
-
94
- logCurFunc: (funcName) ->
95
-
96
- # --- funcName must be the current function
97
- # and the isLogged flag must currently be false
98
-
99
- cur = @lStack[@lStack.length - 1]
100
- assert (cur.isLogged == false), "isLogged is already true"
101
- if (funcName != cur.fullName)
102
- LOG "cur func #{cur.fullName} is not #{funcName}"
103
- LOG @dump()
104
- croak "BAD"
105
- cur.isLogged = true
106
- @level += 1
107
- return
108
-
109
91
  # ........................................................................
110
92
  # --- if stack is empty, log the error, but continue
111
93
 
@@ -119,19 +101,10 @@ export class CallStack
119
101
  return
120
102
 
121
103
  {fullName, isLogged} = @lStack.pop()
122
- if isLogged && (@level > 0)
123
- @level -= 1
124
-
125
- # --- This should do nothing
126
- while (fullName != fName) && (@lStack.length > 0)
127
- LOG "[MISSING RETURN FROM #{fullName} (return from #{fName})]"
128
- {fullName, isLogged} = @lStack.pop()
129
- if isLogged && (@level > 0)
130
- @level -= 1
131
-
132
- if fullName != fName
133
- @dump()
134
- LOG "BAD BAD BAD BAD returnFrom('#{fName}')"
104
+ if (fullName != fName)
105
+ LOG "ERROR: returnFrom('#{fName}') but TOS is #{fullName}"
106
+ return
107
+
135
108
  return
136
109
 
137
110
  # ........................................................................
@@ -156,15 +129,25 @@ export class CallStack
156
129
 
157
130
  # ........................................................................
158
131
 
159
- dump: (prefix='', label='CALL STACK') ->
132
+ dump: (label="CALL STACK") ->
160
133
 
161
- lLines = ["#{label}:"]
134
+ lLines = [label]
162
135
  if @lStack.length == 0
163
136
  lLines.push " <EMPTY>"
164
137
  else
165
138
  for item, i in @lStack
166
- lLines.push " #{i}: #{item.fullName} #{item.isLogged}"
167
- 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
168
151
 
169
152
  # ........................................................................
170
153
 
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,13 +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) {
49
- var _, ident1, ident2, lMatches;
43
+ enter(funcName, lArgs = [], isLogged) {
44
+ var _, hStackItem, ident1, ident2, lMatches;
50
45
  // --- funcName might be <object>.<method>
46
+ assert(isArray(lArgs), "missing lArgs");
47
+ assert(isBoolean(isLogged), "missing isLogged");
51
48
  if (doDebugStack) {
52
49
  LOG(`[--> ENTER ${funcName}]`);
53
50
  }
@@ -55,23 +52,36 @@ export var CallStack = class CallStack {
55
52
  assert(defined(lMatches), `Bad funcName: ${OL(funcName)}`);
56
53
  [_, ident1, ident2] = lMatches;
57
54
  if (ident2) {
58
- this.lStack.push({
55
+ hStackItem = {
59
56
  fullName: funcName, // "#{ident1}.#{ident2}"
60
57
  funcName: ident2,
61
- isLogged: false
62
- });
58
+ isLogged,
59
+ lArgs: deepCopy(lArgs)
60
+ };
63
61
  } else {
64
- this.lStack.push({
62
+ hStackItem = {
65
63
  fullName: funcName,
66
64
  funcName: ident1,
67
- isLogged: false
68
- });
65
+ isLogged,
66
+ lArgs: deepCopy(lArgs)
67
+ };
69
68
  }
69
+ this.lStack.push(hStackItem);
70
+ return hStackItem;
70
71
  }
71
72
 
72
73
  // ........................................................................
73
74
  getLevel() {
74
- return this.level;
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
+ }
83
+ }
84
+ return level;
75
85
  }
76
86
 
77
87
  // ........................................................................
@@ -83,31 +93,6 @@ export var CallStack = class CallStack {
83
93
  }
84
94
  }
85
95
 
86
- // ........................................................................
87
- isLoggingPrev() {
88
- if (this.lStack.length < 2) {
89
- return false;
90
- } else {
91
- return this.lStack[this.lStack.length - 2].isLogged;
92
- }
93
- }
94
-
95
- // ........................................................................
96
- logCurFunc(funcName) {
97
- var cur;
98
- // --- funcName must be the current function
99
- // and the isLogged flag must currently be false
100
- cur = this.lStack[this.lStack.length - 1];
101
- assert(cur.isLogged === false, "isLogged is already true");
102
- if (funcName !== cur.fullName) {
103
- LOG(`cur func ${cur.fullName} is not ${funcName}`);
104
- LOG(this.dump());
105
- croak("BAD");
106
- }
107
- cur.isLogged = true;
108
- this.level += 1;
109
- }
110
-
111
96
  // ........................................................................
112
97
  // --- if stack is empty, log the error, but continue
113
98
  returnFrom(fName) {
@@ -120,20 +105,9 @@ export var CallStack = class CallStack {
120
105
  return;
121
106
  }
122
107
  ({fullName, isLogged} = this.lStack.pop());
123
- if (isLogged && (this.level > 0)) {
124
- this.level -= 1;
125
- }
126
- // --- This should do nothing
127
- while ((fullName !== fName) && (this.lStack.length > 0)) {
128
- LOG(`[MISSING RETURN FROM ${fullName} (return from ${fName})]`);
129
- ({fullName, isLogged} = this.lStack.pop());
130
- if (isLogged && (this.level > 0)) {
131
- this.level -= 1;
132
- }
133
- }
134
108
  if (fullName !== fName) {
135
- this.dump();
136
- LOG(`BAD BAD BAD BAD returnFrom('${fName}')`);
109
+ LOG(`ERROR: returnFrom('${fName}') but TOS is ${fullName}`);
110
+ return;
137
111
  }
138
112
  }
139
113
 
@@ -162,19 +136,32 @@ export var CallStack = class CallStack {
162
136
  }
163
137
 
164
138
  // ........................................................................
165
- dump(prefix = '', label = 'CALL STACK') {
139
+ dump(label = "CALL STACK") {
166
140
  var i, item, j, lLines, len, ref;
167
- lLines = [`${label}:`];
141
+ lLines = [label];
168
142
  if (this.lStack.length === 0) {
169
143
  lLines.push(" <EMPTY>");
170
144
  } else {
171
145
  ref = this.lStack;
172
146
  for (i = j = 0, len = ref.length; j < len; i = ++j) {
173
147
  item = ref[i];
174
- lLines.push(` ${i}: ${item.fullName} ${item.isLogged}`);
148
+ lLines.push(" " + this.callStr(i, item));
175
149
  }
176
150
  }
177
- return lLines.join("\n") + "\n";
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;
178
165
  }
179
166
 
180
167
  // ........................................................................
@@ -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
  // ---------------------------------------------------------------------------