@jdeighan/coffee-utils 16.0.24 → 17.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.
@@ -1,199 +0,0 @@
1
- # indent.coffee
2
-
3
- import {assert, croak} from '@jdeighan/base-utils/exceptions'
4
- import {
5
- undef, defined, notdefined, toArray, toBlock,
6
- OL, isInteger, isString, isArray, isEmpty, rtrim,
7
- } from '@jdeighan/base-utils'
8
-
9
- # ---------------------------------------------------------------------------
10
-
11
- export getOneIndent = (str) =>
12
-
13
- if (lMatches = str.match(/^\t+(?:\S|$)/))
14
- return "\t"
15
- else if (lMatches = str.match(/^(\x20+)(?:\S|$)/)) # space char
16
- return lMatches[1]
17
- assert notdefined(str.match(/^\s/)), "Mixed indentation types"
18
- return undef
19
-
20
- # ---------------------------------------------------------------------------
21
-
22
- export splitPrefix = (line) =>
23
-
24
- assert isString(line), "non-string #{OL(line)}"
25
- line = rtrim(line)
26
- lMatches = line.match(/^(\s*)(.*)$/)
27
- return [lMatches[1], lMatches[2]]
28
-
29
- # ---------------------------------------------------------------------------
30
- # splitLine - separate a line into [level, line]
31
-
32
- export splitLine = (line, oneIndent=undef) =>
33
-
34
- [prefix, str] = splitPrefix(line)
35
- return [indentLevel(prefix, oneIndent), str]
36
-
37
- # ---------------------------------------------------------------------------
38
- # indentLevel - determine indent level of a string
39
- # it's OK if the string is ONLY indentation
40
-
41
- export indentLevel = (line, oneIndent=undef) =>
42
-
43
- assert isString(line), "not a string"
44
-
45
- # --- This will always match, and it's greedy
46
- if lMatches = line.match(/^\s*/)
47
- prefix = lMatches[0]
48
- prefixLen = prefix.length
49
-
50
- if (prefixLen == 0)
51
- return 0
52
-
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
57
- else
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
78
- else
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"
92
- return level
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
-
103
- # ---------------------------------------------------------------------------
104
- # isUndented - true iff indentLevel(line) == 0
105
-
106
- export isUndented = (line) =>
107
-
108
- assert isString(line), "non-string #{OL(line)}"
109
- return notdefined(line.match(/^\s/))
110
-
111
- # ---------------------------------------------------------------------------
112
- # indented - add indentation to each string in a block or array
113
- # - returns the same type as input, i.e. array or string
114
-
115
- export indented = (input, level=1, oneIndent="\t") =>
116
-
117
- # --- level can be a string, in which case it is
118
- # pre-pended to each line of input
119
- if isString(level)
120
- if (level == '')
121
- return input
122
- toAdd = level
123
- else if isInteger(level)
124
- if (level == 0)
125
- return input
126
- assert (level > 0), "Invalid level #{OL(level)}"
127
- toAdd = indentation(level, oneIndent)
128
- else
129
- croak "Invalid level #{OL(level)}"
130
-
131
- # --- NOTE: toArray(input) just returns input if it's an array
132
- # else it splits the string into an array of lines
133
- lLines = []
134
- for line in toArray(input)
135
- if isEmpty(line)
136
- lLines.push ''
137
- else
138
- lLines.push "#{toAdd}#{line}"
139
-
140
- if isArray(input)
141
- return lLines
142
- else if isString(input)
143
- return toBlock(lLines)
144
- croak "Invalid input; #{OL(input)}"
145
-
146
- # ---------------------------------------------------------------------------
147
- # undented - string with 1st line indentation removed for each line
148
- # - ignore leading empty lines
149
- # - returns same type as text, i.e. either string or array
150
-
151
- export undented = (input) =>
152
-
153
- # --- If a string, convert to an array
154
- if isString(input)
155
- lLines = toArray(input)
156
- else if isArray(input)
157
- lLines = input
158
- else
159
- croak "input not a string or array"
160
-
161
- # --- Remove leading blank lines
162
- while (lLines.length > 0) && isEmpty(lLines[0])
163
- lLines.shift() # remove
164
-
165
- if (lLines.length == 0)
166
- if isString(input)
167
- return ''
168
- else
169
- return []
170
-
171
- # --- determine what to remove from beginning of each line
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
- )
184
-
185
- if isString(input)
186
- return toBlock(lLines)
187
- else
188
- return lLines
189
-
190
- # ---------------------------------------------------------------------------
191
- # enclose - indent text, surround with pre and post
192
-
193
- export enclose = (text, pre, post, oneIndent="\t") =>
194
-
195
- return toBlock([
196
- pre
197
- indented(text, 1, oneIndent)
198
- post
199
- ])
package/src/lib/indent.js DELETED
@@ -1,216 +0,0 @@
1
- // Generated by CoffeeScript 2.7.0
2
- // indent.coffee
3
- import {
4
- assert,
5
- croak
6
- } from '@jdeighan/base-utils/exceptions';
7
-
8
- import {
9
- undef,
10
- defined,
11
- notdefined,
12
- toArray,
13
- toBlock,
14
- OL,
15
- isInteger,
16
- isString,
17
- isArray,
18
- isEmpty,
19
- rtrim
20
- } from '@jdeighan/base-utils';
21
-
22
- // ---------------------------------------------------------------------------
23
- export var getOneIndent = (str) => {
24
- var lMatches;
25
- if ((lMatches = str.match(/^\t+(?:\S|$)/))) {
26
- return "\t";
27
- } else if ((lMatches = str.match(/^(\x20+)(?:\S|$)/))) { // space char
28
- return lMatches[1];
29
- }
30
- assert(notdefined(str.match(/^\s/)), "Mixed indentation types");
31
- return undef;
32
- };
33
-
34
- // ---------------------------------------------------------------------------
35
- export var splitPrefix = (line) => {
36
- var lMatches;
37
- assert(isString(line), `non-string ${OL(line)}`);
38
- line = rtrim(line);
39
- lMatches = line.match(/^(\s*)(.*)$/);
40
- return [lMatches[1], lMatches[2]];
41
- };
42
-
43
- // ---------------------------------------------------------------------------
44
- // splitLine - separate a line into [level, line]
45
- export var splitLine = (line, oneIndent = undef) => {
46
- var prefix, str;
47
- [prefix, str] = splitPrefix(line);
48
- return [indentLevel(prefix, oneIndent), str];
49
- };
50
-
51
- // ---------------------------------------------------------------------------
52
- // indentLevel - determine indent level of a string
53
- // it's OK if the string is ONLY indentation
54
- export var indentLevel = (line, oneIndent = undef) => {
55
- var i, lMatches, len, level, nSpaces, nTabs, prefix, prefixLen, ref, str;
56
- assert(isString(line), "not a string");
57
- // --- This will always match, and it's greedy
58
- if (lMatches = line.match(/^\s*/)) {
59
- prefix = lMatches[0];
60
- prefixLen = prefix.length;
61
- }
62
- if (prefixLen === 0) {
63
- return 0;
64
- }
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;
69
- } else {
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`);
105
- }
106
- }
107
- return level;
108
- };
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
-
118
- // ---------------------------------------------------------------------------
119
- // isUndented - true iff indentLevel(line) == 0
120
- export var isUndented = (line) => {
121
- assert(isString(line), `non-string ${OL(line)}`);
122
- return notdefined(line.match(/^\s/));
123
- };
124
-
125
- // ---------------------------------------------------------------------------
126
- // indented - add indentation to each string in a block or array
127
- // - returns the same type as input, i.e. array or string
128
- export var indented = (input, level = 1, oneIndent = "\t") => {
129
- var i, lLines, len, line, ref, toAdd;
130
- // --- level can be a string, in which case it is
131
- // pre-pended to each line of input
132
- if (isString(level)) {
133
- if (level === '') {
134
- return input;
135
- }
136
- toAdd = level;
137
- } else if (isInteger(level)) {
138
- if (level === 0) {
139
- return input;
140
- }
141
- assert(level > 0, `Invalid level ${OL(level)}`);
142
- toAdd = indentation(level, oneIndent);
143
- } else {
144
- croak(`Invalid level ${OL(level)}`);
145
- }
146
- // --- NOTE: toArray(input) just returns input if it's an array
147
- // else it splits the string into an array of lines
148
- lLines = [];
149
- ref = toArray(input);
150
- for (i = 0, len = ref.length; i < len; i++) {
151
- line = ref[i];
152
- if (isEmpty(line)) {
153
- lLines.push('');
154
- } else {
155
- lLines.push(`${toAdd}${line}`);
156
- }
157
- }
158
- if (isArray(input)) {
159
- return lLines;
160
- } else if (isString(input)) {
161
- return toBlock(lLines);
162
- }
163
- return croak(`Invalid input; ${OL(input)}`);
164
- };
165
-
166
- // ---------------------------------------------------------------------------
167
- // undented - string with 1st line indentation removed for each line
168
- // - ignore leading empty lines
169
- // - returns same type as text, i.e. either string or array
170
- export var undented = (input) => {
171
- var lLines, lMatches, nToRemove, toRemove;
172
- // --- If a string, convert to an array
173
- if (isString(input)) {
174
- lLines = toArray(input);
175
- } else if (isArray(input)) {
176
- lLines = input;
177
- } else {
178
- croak("input not a string or array");
179
- }
180
- // --- Remove leading blank lines
181
- while ((lLines.length > 0) && isEmpty(lLines[0])) {
182
- lLines.shift(); // remove
183
- }
184
- if (lLines.length === 0) {
185
- if (isString(input)) {
186
- return '';
187
- } else {
188
- return [];
189
- }
190
- }
191
- // --- determine what to remove from beginning of each 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);
202
- }
203
- });
204
- }
205
- if (isString(input)) {
206
- return toBlock(lLines);
207
- } else {
208
- return lLines;
209
- }
210
- };
211
-
212
- // ---------------------------------------------------------------------------
213
- // enclose - indent text, surround with pre and post
214
- export var enclose = (text, pre, post, oneIndent = "\t") => {
215
- return toBlock([pre, indented(text, 1, oneIndent), post]);
216
- };