UNPKG

8.97 kBJavaScriptView Raw
1/*
2
3 miniwrite
4
5 https://github.com/Bartvds/miniwrite
6
7 Copyright (c) 2013 Bart van der Schoor
8
9 Permission is hereby granted, free of charge, to any person
10 obtaining a copy of this software and associated documentation
11 files (the "Software"), to deal in the Software without
12 restriction, including without limitation the rights to use,
13 copy, modify, merge, publish, distribute, sublicense, and/or sell
14 copies of the Software, and to permit persons to whom the
15 Software is furnished to do so, subject to the following
16 conditions:
17
18 The above copyright notice and this permission notice shall be
19 included in all copies or substantial portions of the Software.
20
21 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
23 OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
25 HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
26 WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
27 FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
28 OTHER DEALINGS IN THE SOFTWARE.
29 */
30
31// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
32
33//TODO decide how to support monkey patch/mixin
34//TODO freeze some props
35
36// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
37
38/*jshint -W003*/
39
40(function () {
41 'use strict';
42
43 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
44
45 function isArray(obj) {
46 return (Object.prototype.toString.call(obj) === '[object Array]');
47 }
48
49 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
50
51 function isMiniWrite(target) {
52 return !!(target && typeof target === 'object' && typeof target.writeln === 'function');
53 }
54
55 function assertMiniWrite(target) {
56 if (!target || !(typeof target === 'object' && typeof target.writeln === 'function')) {
57 throw new Error('target is not a miniwrite: required methods: writeln()');
58 }
59 }
60
61 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
62
63 var miniRoot = {
64 writeln: function (/* line */) {
65 //abstract
66 },
67 toString: function () {
68 return '<miniwrite>';
69 }
70 };
71
72 var miniBase = Object.create(miniRoot);
73
74 function setBase(def) {
75 assertMiniWrite(def);
76 miniBase = def;
77 }
78
79 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
80
81 function base() {
82 return Object.create(miniBase);
83 }
84
85 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
86
87 // allow writing per character, auto flush per line
88 function chars(target, splitExp) {
89 var inst = core.base();
90 inst.textBuffer = '';
91 inst.enabled = true;
92 inst.splitExp = (splitExp || /(.*?)\r?\n/g);
93
94 inst.useTarget = function (target) {
95 inst.target = (target || {
96 // dummy
97 writeln: function () {
98 //nothing
99 }
100 });
101 };
102
103 inst.clear = function () {
104 inst.textBuffer = '';
105 inst.splitExp.lastIndex = 0;
106 };
107
108 inst.write = function (str) {
109 if (str === '') {
110 return;
111 }
112 if (inst.enabled) {
113 //fast path
114 inst.textBuffer += str;
115 inst.flush(true);
116 }
117 };
118
119 inst.writeln = function (str) {
120 if (inst.enabled) {
121 //fast path
122 if (arguments.length === 0) {
123 inst.textBuffer += '\n';
124 }
125 else {
126 inst.textBuffer += str + '\n';
127 }
128 inst.flush(true);
129 }
130 };
131
132 inst.flush = function (linesOnly) {
133 if (inst.textBuffer.length > 0) {
134 var match;
135 var end = 0;
136 //TODO verify if we really need a capture group?
137 // instead not search for line break and use index + length of match + substing
138 while ((match = inst.splitExp.exec(inst.textBuffer))) {
139 inst.target.writeln(match[1]);
140 end = match.index + (match[0].length || 1);
141 inst.splitExp.lastIndex = end;
142 }
143 if (end > 0) {
144 inst.textBuffer = inst.textBuffer.substring(end);
145 inst.splitExp.lastIndex = 0;
146 }
147 if (!linesOnly && inst.textBuffer.length > 0) {
148 inst.target.writeln(inst.textBuffer);
149 inst.textBuffer = 0;
150 inst.splitExp.lastIndex = 0;
151 }
152 }
153 };
154
155 inst.has = function () {
156 return inst.textBuffer.length > 0;
157 };
158
159 inst.toString = function () {
160 return '<miniwrite-chars>';
161 };
162 // use target
163 inst.useTarget(target);
164 return inst;
165 }
166
167 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
168
169 // allow writing per character, auto flush per line
170 function splitter(target, splitExp) {
171 var mw = core.base();
172 mw.enabled = true;
173 mw.splitExp = (splitExp || /\r?\n/g);
174 mw.target = target;
175 mw.writeln = function (str) {
176 if (mw.enabled) {
177 str = String(str);
178 var start = 0;
179 var match;
180
181 mw.splitExp.lastIndex = 0;
182 while ((match = mw.splitExp.exec(str))) {
183 var line = str.substring(start, match.index);
184 start = match.index + match[0].length;
185 mw.splitExp.lastIndex = start;
186 mw.target.writeln(line);
187 }
188 // append piece after final linebreak (or final blank line)
189 if (start < str.length || start === str.length) {
190 mw.target.writeln(str.substr(start));
191 }
192 }
193 };
194 mw.toString = function () {
195 return '<miniwrite-splitter>';
196 };
197 return mw;
198 }
199
200 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
201
202 // control output
203 function toggle(main, alt) {
204 var mw = core.base();
205 mw.main = main;
206 mw.alt = (alt || function () {
207
208 });
209 mw.active = mw.main;
210 mw.enabled = true;
211 mw.swap = function () {
212 mw.active = (mw.active !== mw.main ? mw.main : mw.alt);
213 };
214 mw.writeln = function (line) {
215 if (!mw.enabled) {
216 return;
217 }
218 if (mw.enabled) {
219 mw.active.writeln(line);
220 }
221 };
222 mw.toString = function () {
223 return '<miniwrite-toggle>';
224 };
225 return mw;
226 }
227
228 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
229
230 // call multiple other writers
231 function multi(list /*, ... */) {
232 var mw = core.base();
233 mw.targets = (isArray(list) ? list : Array.prototype.slice.call(arguments.length, 0));
234 mw.enabled = true;
235 mw.writeln = function (line) {
236 if (mw.enabled) {
237 for (var i = 0, ii = mw.targets.length; i < ii; i++) {
238 mw.targets[i].writeln(line);
239 }
240 }
241 };
242 mw.toString = function () {
243 return '<miniwrite-multi>';
244 };
245 return mw;
246 }
247
248 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
249
250 // use callback to transform
251 function peek(target, callback) {
252 var mw = core.base();
253 mw.enabled = true;
254 mw.target = target;
255 mw.callback = (callback || function (line /*, mw*/) {
256 return line;
257 });
258 mw.writeln = function (line) {
259 if (mw.enabled && mw.callback) {
260 line = mw.callback(line, mw);
261 if (typeof line === 'string') {
262 mw.target.writeln(line);
263 }
264 }
265 };
266 mw.toString = function () {
267 return '<miniwrite-peek>';
268 };
269 return mw;
270 }
271
272 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
273
274 // to extract as string (can wrap others)
275 function buffer(patch) {
276 var mw = (patch || core.base());
277 mw.lines = [];
278 mw.enabled = true;
279 mw.writeln = function (line) {
280 if (mw.enabled) {
281 mw.lines.push(String(line));
282 }
283 };
284 //TODO add wordwrap?
285 mw.concat = function (seperator, indent, sepAfter) {
286 if (mw.lines.length > 0) {
287 sepAfter = (typeof sepAfter !== 'undefined' ? sepAfter : true);
288 seperator = (typeof seperator !== 'undefined' ? seperator : '\n');
289 indent = (typeof indent !== 'undefined' ? indent : '');
290 return indent + mw.lines.join(seperator + indent) + (sepAfter ? seperator : '');
291 }
292 return '';
293 };
294 mw.clear = function () {
295 mw.lines.length = 0;
296 };
297 if (!patch) {
298 mw.toString = function () {
299 return '<miniwrite-buffer>';
300 };
301 }
302 return mw;
303 }
304
305 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
306
307 // assemble exports
308 var core = {
309 assertMiniWrite: assertMiniWrite,
310 isMiniWrite: isMiniWrite,
311
312 setBase: setBase,
313
314 base: base,
315 chars: chars,
316 buffer: buffer,
317 splitter: splitter,
318
319 toggle: toggle,
320 multi: multi,
321 peek: peek
322 };
323
324 module.exports = core;
325
326}).call();