@jdeighan/coffee-utils 15.0.0 → 16.0.0
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 +1 -1
- package/src/indent.coffee +66 -56
- package/src/indent.js +70 -60
package/package.json
CHANGED
package/src/indent.coffee
CHANGED
@@ -34,15 +34,6 @@ export splitLine = (line, oneIndent=undef) =>
|
|
34
34
|
[prefix, str] = splitPrefix(line)
|
35
35
|
return [indentLevel(prefix, oneIndent), str]
|
36
36
|
|
37
|
-
# ---------------------------------------------------------------------------
|
38
|
-
# indentation - return appropriate indentation string for given level
|
39
|
-
# export only to allow unit testing
|
40
|
-
|
41
|
-
export indentation = (level, oneIndent="\t") =>
|
42
|
-
|
43
|
-
assert (level >= 0), "indentation(): negative level"
|
44
|
-
return oneIndent.repeat(level)
|
45
|
-
|
46
37
|
# ---------------------------------------------------------------------------
|
47
38
|
# indentLevel - determine indent level of a string
|
48
39
|
# it's OK if the string is ONLY indentation
|
@@ -59,28 +50,56 @@ export indentLevel = (line, oneIndent=undef) =>
|
|
59
50
|
if (prefixLen == 0)
|
60
51
|
return 0
|
61
52
|
|
62
|
-
if
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
"prefix #{OL(prefix)} not a mult of #{OL(oneIndent)}"
|
67
|
-
|
68
|
-
level = prefixLen / len
|
53
|
+
# --- Match \t* followed by \x20* (error if no match)
|
54
|
+
if lMatches = prefix.match(/(\t*)(\x20*)/)
|
55
|
+
nTabs = lMatches[1].length
|
56
|
+
nSpaces = lMatches[2].length
|
69
57
|
else
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
58
|
+
croak "Invalid mix of TABs and spaces"
|
59
|
+
|
60
|
+
# --- oneIndent must be one of:
|
61
|
+
# undef
|
62
|
+
# a single TAB character
|
63
|
+
# some number of space characters
|
64
|
+
|
65
|
+
switch oneIndent
|
66
|
+
when undef
|
67
|
+
if (nTabs > 0)
|
68
|
+
level = nTabs # there may also be spaces, but we ignore them
|
69
|
+
oneIndent = "\t" # may be used at end
|
70
|
+
else
|
71
|
+
assert (nSpaces > 0), "There must be TABS or spaces"
|
72
|
+
level = 1
|
73
|
+
oneIndent = ' '.repeat(nSpaces) # may be used at end
|
74
|
+
when "\t"
|
75
|
+
assert (nTabs > 0), "Expecting TAB indentation, found spaces"
|
76
|
+
# --- NOTE: there may be spaces, but they're not indentation
|
77
|
+
level = nTabs
|
77
78
|
else
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
79
|
+
# --- oneIndent must be all space chars
|
80
|
+
assert (nTabs == 0),
|
81
|
+
"Indentation has TABs but oneIndent = #{OL(oneIndent)}"
|
82
|
+
assert (nSpaces % oneIndent.length == 0),
|
83
|
+
"prefix #{OL(prefix)} not a mult of #{OL(oneIndent)}"
|
84
|
+
level = nSpaces / oneIndent.length
|
85
|
+
|
86
|
+
# --- If a block, i.e. multi-line string, then all lines must be
|
87
|
+
# at least at this level
|
88
|
+
if (line.indexOf("\n") >= 0)
|
89
|
+
for str in toArray(line)
|
90
|
+
assert (indentLevel(str, oneIndent) >= level),
|
91
|
+
"indentLevel of #{OL(line)} can't be found"
|
82
92
|
return level
|
83
93
|
|
94
|
+
# ---------------------------------------------------------------------------
|
95
|
+
# indentation - return appropriate indentation string for given level
|
96
|
+
# export only to allow unit testing
|
97
|
+
|
98
|
+
export indentation = (level, oneIndent="\t") =>
|
99
|
+
|
100
|
+
assert (level >= 0), "indentation(): negative level"
|
101
|
+
return oneIndent.repeat(level)
|
102
|
+
|
84
103
|
# ---------------------------------------------------------------------------
|
85
104
|
# isUndented - true iff indentLevel(line) == 0
|
86
105
|
|
@@ -127,27 +146,22 @@ export indented = (input, level=1, oneIndent="\t") =>
|
|
127
146
|
# ---------------------------------------------------------------------------
|
128
147
|
# undented - string with 1st line indentation removed for each line
|
129
148
|
# - ignore leading empty lines
|
130
|
-
# - unless level is set, in which case exactly that
|
131
|
-
# indentation is removed
|
132
149
|
# - returns same type as text, i.e. either string or array
|
133
150
|
|
134
|
-
export undented = (input
|
135
|
-
|
136
|
-
if defined(level) && (level==0)
|
137
|
-
return input
|
151
|
+
export undented = (input) =>
|
138
152
|
|
139
|
-
# ---
|
153
|
+
# --- If a string, convert to an array
|
140
154
|
if isString(input)
|
141
|
-
if lMatches = input.match(///^ [\r\n]+ (.*) $///s)
|
142
|
-
input = lMatches[1]
|
143
155
|
lLines = toArray(input)
|
144
156
|
else if isArray(input)
|
145
157
|
lLines = input
|
146
|
-
while (lLines.length > 0) && isEmpty(lLines[0])
|
147
|
-
lLines.shift()
|
148
158
|
else
|
149
159
|
croak "input not a string or array"
|
150
160
|
|
161
|
+
# --- Remove leading blank lines
|
162
|
+
while (lLines.length > 0) && isEmpty(lLines[0])
|
163
|
+
lLines.shift() # remove
|
164
|
+
|
151
165
|
if (lLines.length == 0)
|
152
166
|
if isString(input)
|
153
167
|
return ''
|
@@ -155,27 +169,23 @@ export undented = (input, level=undef, oneIndent="\t") =>
|
|
155
169
|
return []
|
156
170
|
|
157
171
|
# --- determine what to remove from beginning of each line
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
else
|
171
|
-
if (line.indexOf(toRemove) != 0)
|
172
|
-
throw new Error("remove #{OL(toRemove)} from #{OL(line)}")
|
173
|
-
lNewLines.push(line.substr(nToRemove))
|
172
|
+
lMatches = lLines[0].match(/^\s*/)
|
173
|
+
toRemove = lMatches[0]
|
174
|
+
nToRemove = toRemove.length
|
175
|
+
if (nToRemove > 0)
|
176
|
+
lLines = lLines.map( (line) =>
|
177
|
+
if isEmpty(line)
|
178
|
+
return ''
|
179
|
+
else
|
180
|
+
assert (line.indexOf(toRemove)==0),
|
181
|
+
"can't remove #{OL(toRemove)} from #{OL(line)}"
|
182
|
+
return line.substr(nToRemove)
|
183
|
+
)
|
174
184
|
|
175
185
|
if isString(input)
|
176
|
-
return toBlock(
|
186
|
+
return toBlock(lLines)
|
177
187
|
else
|
178
|
-
return
|
188
|
+
return lLines
|
179
189
|
|
180
190
|
# ---------------------------------------------------------------------------
|
181
191
|
# enclose - indent text, surround with pre and post
|
package/src/indent.js
CHANGED
@@ -48,19 +48,11 @@ export var splitLine = (line, oneIndent = undef) => {
|
|
48
48
|
return [indentLevel(prefix, oneIndent), str];
|
49
49
|
};
|
50
50
|
|
51
|
-
// ---------------------------------------------------------------------------
|
52
|
-
// indentation - return appropriate indentation string for given level
|
53
|
-
// export only to allow unit testing
|
54
|
-
export var indentation = (level, oneIndent = "\t") => {
|
55
|
-
assert(level >= 0, "indentation(): negative level");
|
56
|
-
return oneIndent.repeat(level);
|
57
|
-
};
|
58
|
-
|
59
51
|
// ---------------------------------------------------------------------------
|
60
52
|
// indentLevel - determine indent level of a string
|
61
53
|
// it's OK if the string is ONLY indentation
|
62
54
|
export var indentLevel = (line, oneIndent = undef) => {
|
63
|
-
var
|
55
|
+
var i, lMatches, len, level, nSpaces, nTabs, prefix, prefixLen, ref, str;
|
64
56
|
assert(isString(line), "not a string");
|
65
57
|
// --- This will always match, and it's greedy
|
66
58
|
if (lMatches = line.match(/^\s*/)) {
|
@@ -70,27 +62,59 @@ export var indentLevel = (line, oneIndent = undef) => {
|
|
70
62
|
if (prefixLen === 0) {
|
71
63
|
return 0;
|
72
64
|
}
|
73
|
-
if
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
level = prefixLen / len;
|
65
|
+
// --- Match \t* followed by \x20* (error if no match)
|
66
|
+
if (lMatches = prefix.match(/(\t*)(\x20*)/)) {
|
67
|
+
nTabs = lMatches[1].length;
|
68
|
+
nSpaces = lMatches[2].length;
|
78
69
|
} else {
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
70
|
+
croak("Invalid mix of TABs and spaces");
|
71
|
+
}
|
72
|
+
// --- oneIndent must be one of:
|
73
|
+
// undef
|
74
|
+
// a single TAB character
|
75
|
+
// some number of space characters
|
76
|
+
switch (oneIndent) {
|
77
|
+
case undef:
|
78
|
+
if (nTabs > 0) {
|
79
|
+
level = nTabs; // there may also be spaces, but we ignore them
|
80
|
+
oneIndent = "\t"; // may be used at end
|
81
|
+
} else {
|
82
|
+
assert(nSpaces > 0, "There must be TABS or spaces");
|
83
|
+
level = 1;
|
84
|
+
oneIndent = ' '.repeat(nSpaces); // may be used at end
|
85
|
+
}
|
86
|
+
break;
|
87
|
+
case "\t":
|
88
|
+
assert(nTabs > 0, "Expecting TAB indentation, found spaces");
|
89
|
+
// --- NOTE: there may be spaces, but they're not indentation
|
90
|
+
level = nTabs;
|
91
|
+
break;
|
92
|
+
default:
|
93
|
+
// --- oneIndent must be all space chars
|
94
|
+
assert(nTabs === 0, `Indentation has TABs but oneIndent = ${OL(oneIndent)}`);
|
95
|
+
assert(nSpaces % oneIndent.length === 0, `prefix ${OL(prefix)} not a mult of ${OL(oneIndent)}`);
|
96
|
+
level = nSpaces / oneIndent.length;
|
97
|
+
}
|
98
|
+
// --- If a block, i.e. multi-line string, then all lines must be
|
99
|
+
// at least at this level
|
100
|
+
if (line.indexOf("\n") >= 0) {
|
101
|
+
ref = toArray(line);
|
102
|
+
for (i = 0, len = ref.length; i < len; i++) {
|
103
|
+
str = ref[i];
|
104
|
+
assert(indentLevel(str, oneIndent) >= level, `indentLevel of ${OL(line)} can't be found`);
|
88
105
|
}
|
89
106
|
}
|
90
|
-
assert(prefix === oneIndent.repeat(level), `prefix ${OL(prefix)} not a mult of ${OL(oneIndent)}`);
|
91
107
|
return level;
|
92
108
|
};
|
93
109
|
|
110
|
+
// ---------------------------------------------------------------------------
|
111
|
+
// indentation - return appropriate indentation string for given level
|
112
|
+
// export only to allow unit testing
|
113
|
+
export var indentation = (level, oneIndent = "\t") => {
|
114
|
+
assert(level >= 0, "indentation(): negative level");
|
115
|
+
return oneIndent.repeat(level);
|
116
|
+
};
|
117
|
+
|
94
118
|
// ---------------------------------------------------------------------------
|
95
119
|
// isUndented - true iff indentLevel(line) == 0
|
96
120
|
export var isUndented = (line) => {
|
@@ -102,7 +126,7 @@ export var isUndented = (line) => {
|
|
102
126
|
// indented - add indentation to each string in a block or array
|
103
127
|
// - returns the same type as input, i.e. array or string
|
104
128
|
export var indented = (input, level = 1, oneIndent = "\t") => {
|
105
|
-
var i, lLines,
|
129
|
+
var i, lLines, len, line, ref, toAdd;
|
106
130
|
// --- level can be a string, in which case it is
|
107
131
|
// pre-pended to each line of input
|
108
132
|
if (isString(level)) {
|
@@ -123,7 +147,7 @@ export var indented = (input, level = 1, oneIndent = "\t") => {
|
|
123
147
|
// else it splits the string into an array of lines
|
124
148
|
lLines = [];
|
125
149
|
ref = toArray(input);
|
126
|
-
for (i = 0,
|
150
|
+
for (i = 0, len = ref.length; i < len; i++) {
|
127
151
|
line = ref[i];
|
128
152
|
if (isEmpty(line)) {
|
129
153
|
lLines.push('');
|
@@ -142,28 +166,21 @@ export var indented = (input, level = 1, oneIndent = "\t") => {
|
|
142
166
|
// ---------------------------------------------------------------------------
|
143
167
|
// undented - string with 1st line indentation removed for each line
|
144
168
|
// - ignore leading empty lines
|
145
|
-
// - unless level is set, in which case exactly that
|
146
|
-
// indentation is removed
|
147
169
|
// - returns same type as text, i.e. either string or array
|
148
|
-
export var undented = (input
|
149
|
-
var
|
150
|
-
|
151
|
-
return input;
|
152
|
-
}
|
153
|
-
// --- Remove any leading blank lines, set lLines
|
170
|
+
export var undented = (input) => {
|
171
|
+
var lLines, lMatches, nToRemove, toRemove;
|
172
|
+
// --- If a string, convert to an array
|
154
173
|
if (isString(input)) {
|
155
|
-
if (lMatches = input.match(/^[\r\n]+(.*)$/s)) {
|
156
|
-
input = lMatches[1];
|
157
|
-
}
|
158
174
|
lLines = toArray(input);
|
159
175
|
} else if (isArray(input)) {
|
160
176
|
lLines = input;
|
161
|
-
while ((lLines.length > 0) && isEmpty(lLines[0])) {
|
162
|
-
lLines.shift();
|
163
|
-
}
|
164
177
|
} else {
|
165
178
|
croak("input not a string or array");
|
166
179
|
}
|
180
|
+
// --- Remove leading blank lines
|
181
|
+
while ((lLines.length > 0) && isEmpty(lLines[0])) {
|
182
|
+
lLines.shift(); // remove
|
183
|
+
}
|
167
184
|
if (lLines.length === 0) {
|
168
185
|
if (isString(input)) {
|
169
186
|
return '';
|
@@ -172,30 +189,23 @@ export var undented = (input, level = undef, oneIndent = "\t") => {
|
|
172
189
|
}
|
173
190
|
}
|
174
191
|
// --- determine what to remove from beginning of each line
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
line = lLines[i];
|
186
|
-
if (isEmpty(line)) {
|
187
|
-
lNewLines.push('');
|
188
|
-
} else {
|
189
|
-
if (line.indexOf(toRemove) !== 0) {
|
190
|
-
throw new Error(`remove ${OL(toRemove)} from ${OL(line)}`);
|
192
|
+
lMatches = lLines[0].match(/^\s*/);
|
193
|
+
toRemove = lMatches[0];
|
194
|
+
nToRemove = toRemove.length;
|
195
|
+
if (nToRemove > 0) {
|
196
|
+
lLines = lLines.map((line) => {
|
197
|
+
if (isEmpty(line)) {
|
198
|
+
return '';
|
199
|
+
} else {
|
200
|
+
assert(line.indexOf(toRemove) === 0, `can't remove ${OL(toRemove)} from ${OL(line)}`);
|
201
|
+
return line.substr(nToRemove);
|
191
202
|
}
|
192
|
-
|
193
|
-
}
|
203
|
+
});
|
194
204
|
}
|
195
205
|
if (isString(input)) {
|
196
|
-
return toBlock(
|
206
|
+
return toBlock(lLines);
|
197
207
|
} else {
|
198
|
-
return
|
208
|
+
return lLines;
|
199
209
|
}
|
200
210
|
};
|
201
211
|
|