1 |
|
2 | (function() {
|
3 | var ACCESSOR, CoffeeScript, Module, REPL_PROMPT, REPL_PROMPT_CONTINUATION, REPL_PROMPT_MULTILINE, SIMPLEVAR, Script, autocomplete, backlog, completeAttribute, completeVariable, enableColours, error, getCompletions, inspect, multilineMode, pipedInput, readline, repl, run, stdin, stdout,
|
4 | __indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; };
|
5 |
|
6 | stdin = process.openStdin();
|
7 |
|
8 | stdout = process.stdout;
|
9 |
|
10 | CoffeeScript = require('./coffee-script');
|
11 |
|
12 | readline = require('readline');
|
13 |
|
14 | inspect = require('util').inspect;
|
15 |
|
16 | Script = require('vm').Script;
|
17 |
|
18 | Module = require('module');
|
19 |
|
20 | REPL_PROMPT = 'coffee> ';
|
21 |
|
22 | REPL_PROMPT_MULTILINE = '------> ';
|
23 |
|
24 | REPL_PROMPT_CONTINUATION = '......> ';
|
25 |
|
26 | enableColours = false;
|
27 |
|
28 | if (process.platform !== 'win32') {
|
29 | enableColours = !process.env.NODE_DISABLE_COLORS;
|
30 | }
|
31 |
|
32 | error = function(err) {
|
33 | return stdout.write((err.stack || err.toString()) + '\n');
|
34 | };
|
35 |
|
36 | ACCESSOR = /\s*([\w\.]+)(?:\.(\w*))$/;
|
37 |
|
38 | SIMPLEVAR = /(\w+)$/i;
|
39 |
|
40 | autocomplete = function(text) {
|
41 | return completeAttribute(text) || completeVariable(text) || [[], text];
|
42 | };
|
43 |
|
44 | completeAttribute = function(text) {
|
45 | var all, candidates, completions, key, match, obj, prefix, _i, _len, _ref;
|
46 | if (match = text.match(ACCESSOR)) {
|
47 | all = match[0], obj = match[1], prefix = match[2];
|
48 | try {
|
49 | obj = Script.runInThisContext(obj);
|
50 | } catch (e) {
|
51 | return;
|
52 | }
|
53 | if (obj == null) {
|
54 | return;
|
55 | }
|
56 | obj = Object(obj);
|
57 | candidates = Object.getOwnPropertyNames(obj);
|
58 | while (obj = Object.getPrototypeOf(obj)) {
|
59 | _ref = Object.getOwnPropertyNames(obj);
|
60 | for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
61 | key = _ref[_i];
|
62 | if (__indexOf.call(candidates, key) < 0) {
|
63 | candidates.push(key);
|
64 | }
|
65 | }
|
66 | }
|
67 | completions = getCompletions(prefix, candidates);
|
68 | return [completions, prefix];
|
69 | }
|
70 | };
|
71 |
|
72 | completeVariable = function(text) {
|
73 | var candidates, completions, free, key, keywords, r, vars, _i, _len, _ref;
|
74 | free = (_ref = text.match(SIMPLEVAR)) != null ? _ref[1] : void 0;
|
75 | if (text === "") {
|
76 | free = "";
|
77 | }
|
78 | if (free != null) {
|
79 | vars = Script.runInThisContext('Object.getOwnPropertyNames(Object(this))');
|
80 | keywords = (function() {
|
81 | var _i, _len, _ref1, _results;
|
82 | _ref1 = CoffeeScript.RESERVED;
|
83 | _results = [];
|
84 | for (_i = 0, _len = _ref1.length; _i < _len; _i++) {
|
85 | r = _ref1[_i];
|
86 | if (r.slice(0, 2) !== '__') {
|
87 | _results.push(r);
|
88 | }
|
89 | }
|
90 | return _results;
|
91 | })();
|
92 | candidates = vars;
|
93 | for (_i = 0, _len = keywords.length; _i < _len; _i++) {
|
94 | key = keywords[_i];
|
95 | if (__indexOf.call(candidates, key) < 0) {
|
96 | candidates.push(key);
|
97 | }
|
98 | }
|
99 | completions = getCompletions(free, candidates);
|
100 | return [completions, free];
|
101 | }
|
102 | };
|
103 |
|
104 | getCompletions = function(prefix, candidates) {
|
105 | var el, _i, _len, _results;
|
106 | _results = [];
|
107 | for (_i = 0, _len = candidates.length; _i < _len; _i++) {
|
108 | el = candidates[_i];
|
109 | if (0 === el.indexOf(prefix)) {
|
110 | _results.push(el);
|
111 | }
|
112 | }
|
113 | return _results;
|
114 | };
|
115 |
|
116 | process.on('uncaughtException', error);
|
117 |
|
118 | backlog = '';
|
119 |
|
120 | run = function(buffer) {
|
121 | var code, returnValue, _;
|
122 | buffer = buffer.replace(/(^|[\r\n]+)(\s*)##?(?:[^#\r\n][^\r\n]*|)($|[\r\n])/, "$1$2$3");
|
123 | buffer = buffer.replace(/[\r\n]+$/, "");
|
124 | if (multilineMode) {
|
125 | backlog += "" + buffer + "\n";
|
126 | repl.setPrompt(REPL_PROMPT_CONTINUATION);
|
127 | repl.prompt();
|
128 | return;
|
129 | }
|
130 | if (!buffer.toString().trim() && !backlog) {
|
131 | repl.prompt();
|
132 | return;
|
133 | }
|
134 | code = backlog += buffer;
|
135 | if (code[code.length - 1] === '\\') {
|
136 | backlog = "" + backlog.slice(0, -1) + "\n";
|
137 | repl.setPrompt(REPL_PROMPT_CONTINUATION);
|
138 | repl.prompt();
|
139 | return;
|
140 | }
|
141 | repl.setPrompt(REPL_PROMPT);
|
142 | backlog = '';
|
143 | try {
|
144 | _ = global._;
|
145 | returnValue = CoffeeScript["eval"]("_=(" + code + "\n)", {
|
146 | filename: 'repl',
|
147 | modulename: 'repl'
|
148 | });
|
149 | if (returnValue === void 0) {
|
150 | global._ = _;
|
151 | }
|
152 | repl.output.write("" + (inspect(returnValue, false, 2, enableColours)) + "\n");
|
153 | } catch (err) {
|
154 | error(err);
|
155 | }
|
156 | return repl.prompt();
|
157 | };
|
158 |
|
159 | if (stdin.readable && stdin.isRaw) {
|
160 | pipedInput = '';
|
161 | repl = {
|
162 | prompt: function() {
|
163 | return stdout.write(this._prompt);
|
164 | },
|
165 | setPrompt: function(p) {
|
166 | return this._prompt = p;
|
167 | },
|
168 | input: stdin,
|
169 | output: stdout,
|
170 | on: function() {}
|
171 | };
|
172 | stdin.on('data', function(chunk) {
|
173 | var line, lines, _i, _len, _ref;
|
174 | pipedInput += chunk;
|
175 | if (!/\n/.test(pipedInput)) {
|
176 | return;
|
177 | }
|
178 | lines = pipedInput.split("\n");
|
179 | pipedInput = lines[lines.length - 1];
|
180 | _ref = lines.slice(0, -1);
|
181 | for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
182 | line = _ref[_i];
|
183 | if (!(line)) {
|
184 | continue;
|
185 | }
|
186 | stdout.write("" + line + "\n");
|
187 | run(line);
|
188 | }
|
189 | });
|
190 | stdin.on('end', function() {
|
191 | var line, _i, _len, _ref;
|
192 | _ref = pipedInput.trim().split("\n");
|
193 | for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
194 | line = _ref[_i];
|
195 | if (!(line)) {
|
196 | continue;
|
197 | }
|
198 | stdout.write("" + line + "\n");
|
199 | run(line);
|
200 | }
|
201 | stdout.write('\n');
|
202 | return process.exit(0);
|
203 | });
|
204 | } else {
|
205 | if (readline.createInterface.length < 3) {
|
206 | repl = readline.createInterface(stdin, autocomplete);
|
207 | stdin.on('data', function(buffer) {
|
208 | return repl.write(buffer);
|
209 | });
|
210 | } else {
|
211 | repl = readline.createInterface(stdin, stdout, autocomplete);
|
212 | }
|
213 | }
|
214 |
|
215 | multilineMode = false;
|
216 |
|
217 | repl.input.on('keypress', function(char, key) {
|
218 | var cursorPos, newPrompt;
|
219 | if (!(key && key.ctrl && !key.meta && !key.shift && key.name === 'v')) {
|
220 | return;
|
221 | }
|
222 | cursorPos = repl.cursor;
|
223 | repl.output.cursorTo(0);
|
224 | repl.output.clearLine(1);
|
225 | multilineMode = !multilineMode;
|
226 | if (!multilineMode && backlog) {
|
227 | repl._line();
|
228 | }
|
229 | backlog = '';
|
230 | repl.setPrompt((newPrompt = multilineMode ? REPL_PROMPT_MULTILINE : REPL_PROMPT));
|
231 | repl.prompt();
|
232 | return repl.output.cursorTo(newPrompt.length + (repl.cursor = cursorPos));
|
233 | });
|
234 |
|
235 | repl.input.on('keypress', function(char, key) {
|
236 | if (!(multilineMode && repl.line)) {
|
237 | return;
|
238 | }
|
239 | if (!(key && key.ctrl && !key.meta && !key.shift && key.name === 'd')) {
|
240 | return;
|
241 | }
|
242 | multilineMode = false;
|
243 | return repl._line();
|
244 | });
|
245 |
|
246 | repl.on('attemptClose', function() {
|
247 | if (multilineMode) {
|
248 | multilineMode = false;
|
249 | repl.output.cursorTo(0);
|
250 | repl.output.clearLine(1);
|
251 | repl._onLine(repl.line);
|
252 | return;
|
253 | }
|
254 | if (backlog || repl.line) {
|
255 | backlog = '';
|
256 | repl.historyIndex = -1;
|
257 | repl.setPrompt(REPL_PROMPT);
|
258 | repl.output.write('\n(^C again to quit)');
|
259 | return repl._line((repl.line = ''));
|
260 | } else {
|
261 | return repl.close();
|
262 | }
|
263 | });
|
264 |
|
265 | repl.on('close', function() {
|
266 | repl.output.write('\n');
|
267 | return repl.input.destroy();
|
268 | });
|
269 |
|
270 | repl.on('line', run);
|
271 |
|
272 | repl.setPrompt(REPL_PROMPT);
|
273 |
|
274 | repl.prompt();
|
275 |
|
276 | }).call(this);
|