@jdeighan/coffee-utils 16.0.23 → 17.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
- };