##// END OF EJS Templates
retab tab to space
Matthias BUSSONNIER -
Show More
@@ -1,298 +1,298 b''
1 1 //----------------------------------------------------------------------------
2 2 // Copyright (C) 2008-2011 The IPython Development Team
3 3 //
4 4 // Distributed under the terms of the BSD License. The full license is in
5 5 // the file COPYING, distributed as part of this software.
6 6 //----------------------------------------------------------------------------
7 7
8 8 //============================================================================
9 9 // CodeCell
10 10 //============================================================================
11 11
12 12 var IPython = (function (IPython) {
13 13 "use strict";
14 14
15 15 var utils = IPython.utils;
16 16 var key = IPython.utils.keycodes;
17 17
18 18 var CodeCell = function (kernel) {
19 19 // The kernel doesn't have to be set at creation time, in that case
20 20 // it will be null and set_kernel has to be called later.
21 21 this.kernel = kernel || null;
22 22 this.code_mirror = null;
23 23 this.input_prompt_number = null;
24 24 this.tooltip_on_tab = true;
25 25 IPython.Cell.apply(this, arguments);
26 26 };
27 27
28 28
29 29 CodeCell.prototype = new IPython.Cell();
30 30
31 31
32 32 CodeCell.prototype.create_element = function () {
33 33 var cell = $('<div></div>').addClass('cell border-box-sizing code_cell vbox');
34 34 cell.attr('tabindex','2');
35 35 var input = $('<div></div>').addClass('input hbox');
36 36 input.append($('<div/>').addClass('prompt input_prompt'));
37 37 var input_area = $('<div/>').addClass('input_area box-flex1');
38 38 this.code_mirror = CodeMirror(input_area.get(0), {
39 39 indentUnit : 4,
40 40 mode: 'python',
41 41 theme: 'ipython',
42 42 readOnly: this.read_only,
43 43 onKeyEvent: $.proxy(this.handle_codemirror_keyevent,this)
44 44 });
45 45 input.append(input_area);
46 46 var output = $('<div></div>');
47 47 cell.append(input).append(output);
48 48 this.element = cell;
49 this.output_area = new IPython.OutputArea(output, true);
49 this.output_area = new IPython.OutputArea(output, true);
50 50
51 51 // construct a completer only if class exist
52 52 // otherwise no print view
53 53 if (IPython.Completer !== undefined)
54 54 {
55 55 this.completer = new IPython.Completer(this);
56 56 }
57 57 };
58 58
59 59 CodeCell.prototype.handle_codemirror_keyevent = function (editor, event) {
60 60 // This method gets called in CodeMirror's onKeyDown/onKeyPress
61 61 // handlers and is used to provide custom key handling. Its return
62 62 // value is used to determine if CodeMirror should ignore the event:
63 63 // true = ignore, false = don't ignore.
64 64
65 65 if (this.read_only){
66 66 return false;
67 67 }
68 68
69 69 var that = this;
70 70 // whatever key is pressed, first, cancel the tooltip request before
71 71 // they are sent, and remove tooltip if any, except for tab again
72 72 if (event.type === 'keydown' && event.which != key.TAB ) {
73 73 IPython.tooltip.remove_and_cancel_tooltip();
74 74 };
75 75
76 76 var cur = editor.getCursor();
77 77
78 78 if (event.keyCode === key.ENTER && (event.shiftKey || event.ctrlKey)) {
79 79 // Always ignore shift-enter in CodeMirror as we handle it.
80 80 return true;
81 81 } else if (event.which === 40 && event.type === 'keypress' && IPython.tooltip.time_before_tooltip >= 0) {
82 82 // triger on keypress (!) otherwise inconsistent event.which depending on plateform
83 83 // browser and keyboard layout !
84 84 // Pressing '(' , request tooltip, don't forget to reappend it
85 85 IPython.tooltip.pending(that);
86 86 } else if (event.which === key.UPARROW && event.type === 'keydown') {
87 87 // If we are not at the top, let CM handle the up arrow and
88 88 // prevent the global keydown handler from handling it.
89 89 if (!that.at_top()) {
90 90 event.stop();
91 91 return false;
92 92 } else {
93 93 return true;
94 94 };
95 95 } else if (event.which === key.DOWNARROW && event.type === 'keydown') {
96 96 // If we are not at the bottom, let CM handle the down arrow and
97 97 // prevent the global keydown handler from handling it.
98 98 if (!that.at_bottom()) {
99 99 event.stop();
100 100 return false;
101 101 } else {
102 102 return true;
103 103 };
104 104 } else if (event.keyCode === key.TAB && event.type == 'keydown') {
105 105 // Tab completion.
106 106 //Do not trim here because of tooltip
107 107 var pre_cursor = editor.getRange({line:cur.line,ch:0},cur);
108 108 if (pre_cursor.trim() === "") {
109 109 // Don't autocomplete if the part of the line before the cursor
110 110 // is empty. In this case, let CodeMirror handle indentation.
111 111 return false;
112 112 } else if ((pre_cursor.substr(-1) === "("|| pre_cursor.substr(-1) === " ") && that.tooltip_on_tab ) {
113 113 IPython.tooltip.request(that);
114 114 // Prevent the event from bubbling up.
115 115 event.stop();
116 116 // Prevent CodeMirror from handling the tab.
117 117 return true;
118 118 } else {
119 119 event.stop();
120 120 this.completer.startCompletion();
121 121 return true;
122 122 };
123 123 } else if (event.keyCode === key.BACKSPACE && event.type == 'keydown') {
124 124 // If backspace and the line ends with 4 spaces, remove them.
125 125 var line = editor.getLine(cur.line);
126 126 var ending = line.slice(-4);
127 127 if (ending === ' ') {
128 128 editor.replaceRange('',
129 129 {line: cur.line, ch: cur.ch-4},
130 130 {line: cur.line, ch: cur.ch}
131 131 );
132 132 event.stop();
133 133 return true;
134 134 } else {
135 135 return false;
136 136 };
137 137 } else {
138 138 // keypress/keyup also trigger on TAB press, and we don't want to
139 139 // use those to disable tab completion.
140 140 return false;
141 141 };
142 142 return false;
143 143 };
144 144
145 145
146 146 // Kernel related calls.
147 147
148 148 CodeCell.prototype.set_kernel = function (kernel) {
149 149 this.kernel = kernel;
150 150 }
151 151
152 152
153 153 CodeCell.prototype.execute = function () {
154 154 this.output_area.clear_output(true, true, true);
155 155 this.set_input_prompt('*');
156 156 this.element.addClass("running");
157 157 var callbacks = {
158 158 'execute_reply': $.proxy(this._handle_execute_reply, this),
159 159 'output': $.proxy(this.output_area.handle_output, this.output_area),
160 160 'clear_output': $.proxy(this.output_area.handle_clear_output, this.output_area),
161 161 'cell': this
162 162 };
163 163 var msg_id = this.kernel.execute(this.get_text(), callbacks, {silent: false});
164 164 };
165 165
166 166
167 167 CodeCell.prototype._handle_execute_reply = function (content) {
168 168 this.set_input_prompt(content.execution_count);
169 169 this.element.removeClass("running");
170 170 // this.dirty = true;
171 171 }
172 172
173 173 // Basic cell manipulation.
174 174
175 175 CodeCell.prototype.select = function () {
176 176 IPython.Cell.prototype.select.apply(this);
177 177 this.code_mirror.refresh();
178 178 this.code_mirror.focus();
179 179 // We used to need an additional refresh() after the focus, but
180 180 // it appears that this has been fixed in CM. This bug would show
181 181 // up on FF when a newly loaded markdown cell was edited.
182 182 };
183 183
184 184
185 185 CodeCell.prototype.select_all = function () {
186 186 var start = {line: 0, ch: 0};
187 187 var nlines = this.code_mirror.lineCount();
188 188 var last_line = this.code_mirror.getLine(nlines-1);
189 189 var end = {line: nlines-1, ch: last_line.length};
190 190 this.code_mirror.setSelection(start, end);
191 191 };
192 192
193 193
194 194 CodeCell.prototype.collapse = function () {
195 this.output_area.collapse();
195 this.output_area.collapse();
196 196 };
197 197
198 198
199 199 CodeCell.prototype.expand = function () {
200 this.output_area.expand();
200 this.output_area.expand();
201 201 };
202 202
203 203
204 204 CodeCell.prototype.toggle_output = function () {
205 this.output_area.toggle_output();
205 this.output_area.toggle_output();
206 206 };
207 207
208 208
209 209 CodeCell.prototype.set_input_prompt = function (number) {
210 210 this.input_prompt_number = number;
211 211 var ns = number || "&nbsp;";
212 212 this.element.find('div.input_prompt').html('In&nbsp;[' + ns + ']:');
213 213 };
214 214
215 215
216 216 CodeCell.prototype.clear_input = function () {
217 217 this.code_mirror.setValue('');
218 218 };
219 219
220 220
221 221 CodeCell.prototype.get_text = function () {
222 222 return this.code_mirror.getValue();
223 223 };
224 224
225 225
226 226 CodeCell.prototype.set_text = function (code) {
227 227 return this.code_mirror.setValue(code);
228 228 };
229 229
230 230
231 231 CodeCell.prototype.at_top = function () {
232 232 var cursor = this.code_mirror.getCursor();
233 233 if (cursor.line === 0) {
234 234 return true;
235 235 } else {
236 236 return false;
237 237 }
238 238 };
239 239
240 240
241 241 CodeCell.prototype.at_bottom = function () {
242 242 var cursor = this.code_mirror.getCursor();
243 243 if (cursor.line === (this.code_mirror.lineCount()-1)) {
244 244 return true;
245 245 } else {
246 246 return false;
247 247 }
248 248 };
249 249
250 250
251 251 CodeCell.prototype.clear_output = function (stdout, stderr, other) {
252 252 this.output_area.clear_output(stdout, stderr, other);
253 253 };
254 254
255 255
256 256 // JSON serialization
257 257
258 258 CodeCell.prototype.fromJSON = function (data) {
259 259 if (data.cell_type === 'code') {
260 260 if (data.input !== undefined) {
261 261 this.set_text(data.input);
262 262 }
263 263 if (data.prompt_number !== undefined) {
264 264 this.set_input_prompt(data.prompt_number);
265 265 } else {
266 266 this.set_input_prompt();
267 267 };
268 268 this.output_area.fromJSON(data.outputs);
269 269 if (data.collapsed !== undefined) {
270 270 if (data.collapsed) {
271 271 this.collapse();
272 272 } else {
273 273 this.expand();
274 274 };
275 275 };
276 276 };
277 277 };
278 278
279 279
280 280 CodeCell.prototype.toJSON = function () {
281 281 var data = {};
282 282 data.input = this.get_text();
283 283 data.cell_type = 'code';
284 284 if (this.input_prompt_number) {
285 285 data.prompt_number = this.input_prompt_number;
286 286 };
287 287 var outputs = this.output_area.toJSON();
288 288 data.outputs = outputs;
289 289 data.language = 'python';
290 290 data.collapsed = this.collapsed;
291 291 return data;
292 292 };
293 293
294 294
295 295 IPython.CodeCell = CodeCell;
296 296
297 297 return IPython;
298 298 }(IPython));
General Comments 0
You need to be logged in to leave comments. Login now