|
167 | 167 |
|
168 | 168 | this.cursorPosition = 0; |
169 | 169 | this.history = []; |
| 170 | + this.historyBuffer = []; |
170 | 171 | this.historyIndex = -1; |
171 | 172 | this.beforeHistoryNav = ""; |
172 | 173 | } |
|
219 | 220 | this.cursorLeft(); |
220 | 221 | break; |
221 | 222 | case '[H': // home key |
222 | | - this.cursorHome(); |
| 223 | + this.cursorHome(true); |
223 | 224 | break; |
224 | 225 | case '[F': // end key |
225 | | - this.cursorEnd(); |
| 226 | + this.cursorEnd(true); |
226 | 227 | break; |
227 | 228 | case '[3~': // delete key |
228 | 229 | this.deleteAtCursor(); |
|
248 | 249 | case "\x03": // CTRL+C |
249 | 250 | this.input = ""; |
250 | 251 | this.xterm.write("\n") |
251 | | - // this is a real hack. the hard-coded 4... :\ |
252 | 252 | this.xterm.write('\x1b[' + (this.cursorPosition + 4) + 'D'); |
253 | 253 | this.cursorPosition = 0; |
254 | 254 | this.resolveInput("" + '\n'); |
|
270 | 270 | } |
271 | 271 | } else { |
272 | 272 | this.handleCursorInsert(data); |
| 273 | + this.updateHistory(); |
273 | 274 | } |
274 | 275 | }; |
275 | 276 |
|
| 277 | + clearLine(){ |
| 278 | + this.xterm.write('\x1b[K') |
| 279 | + } |
| 280 | + |
276 | 281 | writeLine(line) { |
277 | 282 | this.xterm.write(line.slice(0, -1)); |
278 | 283 | this.xterm.write("\r\n"); |
|
288 | 293 | this.xterm.write(trailing); |
289 | 294 | this.xterm.write('\x1b[' + trailing.length + 'D'); |
290 | 295 | } |
| 296 | + this.updateHistory(); |
| 297 | + } |
| 298 | + |
| 299 | + handleTab() { |
| 300 | + // handle tabs: from the current position, add spaces until |
| 301 | + // this.cursorPosition is a multiple of 4. |
| 302 | + const prefix = this.input.slice(0, this.cursorPosition); |
| 303 | + const suffix = this.input.slice(this.cursorPosition); |
| 304 | + const count = 4 - (this.cursorPosition % 4); |
| 305 | + const toAdd = " ".repeat(count); |
| 306 | + this.input = prefix + toAdd + suffix |
| 307 | + this.cursorHome(false); |
| 308 | + this.clearLine(); |
| 309 | + this.xterm.write(this.input); |
| 310 | + if (suffix){ |
| 311 | + this.xterm.write('\x1b[' + suffix.length + 'D'); |
| 312 | + } |
| 313 | + this.cursorPosition += count; |
| 314 | + this.updateHistory(false); |
291 | 315 | } |
292 | 316 |
|
293 | 317 | handleCursorErase() { |
|
300 | 324 | } |
301 | 325 | const trailing = this.input.slice(this.cursorPosition); |
302 | 326 | this.input = this.input.slice(0, this.cursorPosition - 1) + trailing; |
303 | | - this.cursorPosition -= 1; |
304 | | - this.xterm.write("\x1B[D"); |
305 | | - this.xterm.write("\x1B[K"); |
306 | | - if (trailing){ |
| 327 | + this.cursorLeft(); |
| 328 | + this.clearLine(); |
| 329 | + if (trailing.length !== 0){ |
307 | 330 | this.xterm.write(trailing); |
308 | 331 | this.xterm.write('\x1b[' + trailing.length + 'D'); |
309 | 332 | } |
| 333 | + this.updateHistory(); |
310 | 334 | } |
311 | 335 |
|
312 | 336 | deleteAtCursor(){ |
313 | 337 | if (this.cursorPosition < this.input.length){ |
314 | 338 | const trailing = this.input.slice(this.cursorPosition + 1); |
315 | 339 | this.input = this.input.slice(0, this.cursorPosition) + trailing; |
316 | | - this.xterm.write("\x1B[K"); |
317 | | - if (trailing){ |
| 340 | + this.clearLine(); |
| 341 | + if (trailing.length !== 0){ |
318 | 342 | this.xterm.write(trailing); |
319 | 343 | this.xterm.write('\x1b[' + trailing.length + 'D'); |
320 | 344 | } |
| 345 | + this.updateHistory(); |
| 346 | + } |
| 347 | + } |
| 348 | + |
| 349 | + cursorRight(){ |
| 350 | + if (this.cursorPosition < this.input.length){ |
| 351 | + this.cursorPosition += 1; |
| 352 | + this.xterm.write('\x1b[C'); |
| 353 | + } |
| 354 | + } |
| 355 | + |
| 356 | + cursorLeft(){ |
| 357 | + if (this.cursorPosition > 0){ |
| 358 | + this.cursorPosition -= 1; |
| 359 | + this.xterm.write('\x1b[D'); |
| 360 | + } |
| 361 | + } |
| 362 | + |
| 363 | + cursorHome(updatePosition) { |
| 364 | + if (this.cursorPosition > 0){ |
| 365 | + this.xterm.write('\x1b[' + this.cursorPosition + 'D'); |
| 366 | + if (updatePosition) { |
| 367 | + this.cursorPosition = 0; |
| 368 | + } |
| 369 | + } |
| 370 | + } |
| 371 | + |
| 372 | + cursorEnd() { |
| 373 | + if (this.cursorPosition < this.input.length){ |
| 374 | + this.xterm.write('\x1b[' + (this.input.length - this.cursorPosition) + 'C'); |
| 375 | + this.cursorPosition = this.input.length; |
| 376 | + } |
| 377 | + } |
| 378 | + |
| 379 | + updateHistory(){ |
| 380 | + if (this.historyIndex !== -1){ |
| 381 | + this.historyBuffer[this.historyIndex] = this.input; |
| 382 | + }else{ |
| 383 | + this.beforeHistoryNav = this.input; |
321 | 384 | } |
322 | 385 | } |
323 | 386 |
|
|
333 | 396 | }else if (this.historyIndex > 0){ |
334 | 397 | this.historyIndex -= 1; |
335 | 398 | } |
336 | | - this.input = this.history[this.historyIndex]; |
337 | | - // jump back to the start of the line |
338 | | - if (this.cursorPosition > 0){ |
339 | | - this.xterm.write('\x1b[' + (this.cursorPosition) + 'D'); |
340 | | - } |
341 | | - // clear the line |
342 | | - this.xterm.write('\x1b[K') |
| 399 | + this.input = this.historyBuffer[this.historyIndex]; |
| 400 | + this.cursorHome(false); |
| 401 | + this.clearLine(); |
343 | 402 | this.xterm.write(this.input); |
344 | 403 | this.cursorPosition = this.input.length; |
345 | 404 | } |
|
350 | 409 | return; |
351 | 410 | }else if (this.historyIndex < this.history.length - 1){ |
352 | 411 | this.historyIndex += 1; |
353 | | - this.input = this.history[this.historyIndex]; |
| 412 | + this.input = this.historyBuffer[this.historyIndex]; |
354 | 413 | }else if (this.historyIndex == this.history.length - 1){ |
355 | 414 | // we're coming back from the last history value; reset |
356 | 415 | // the input to whatever it was when we started going |
357 | 416 | // through the history |
358 | 417 | this.input = this.beforeHistoryNav; |
359 | 418 | this.historyIndex = -1; |
360 | 419 | } |
361 | | - // jump back to the start of the line |
362 | | - if (this.cursorPosition > 0){ |
363 | | - this.xterm.write('\x1b[' + (this.cursorPosition) + 'D'); |
364 | | - } |
365 | | - // clear the line |
366 | | - this.xterm.write('\x1b[K') |
| 420 | + this.cursorHome(false); |
| 421 | + this.clearLine(); |
367 | 422 | this.xterm.write(this.input); |
368 | 423 | this.cursorPosition = this.input.length; |
369 | 424 | } |
370 | 425 |
|
371 | | - cursorRight(){ |
372 | | - if (this.cursorPosition < this.input.length){ |
373 | | - this.cursorPosition += 1; |
374 | | - this.xterm.write('\x1b[C'); |
375 | | - } |
376 | | - } |
377 | | - |
378 | | - cursorLeft(){ |
379 | | - if (this.cursorPosition > 0){ |
380 | | - this.cursorPosition -= 1; |
381 | | - this.xterm.write('\x1b[D'); |
382 | | - } |
383 | | - } |
384 | | - |
385 | | - cursorHome() { |
386 | | - if (this.cursorPosition > 0){ |
387 | | - this.xterm.write('\x1b[' + this.cursorPosition + 'D'); |
388 | | - this.cursorPosition = 0; |
389 | | - } |
390 | | - } |
391 | | - |
392 | | - cursorEnd() { |
393 | | - if (this.cursorPosition < this.input.length){ |
394 | | - this.xterm.write('\x1b[' + (this.input.length - this.cursorPosition) + 'C'); |
395 | | - this.cursorPosition = this.input.length; |
396 | | - } |
397 | | - } |
398 | | - |
399 | | - handleTab() { |
400 | | - // handle tabs: from the current position, add spaces until |
401 | | - // this.cursorPosition is a multiple of 4. |
402 | | - const prefix = this.input.slice(0, this.cursorPosition); |
403 | | - const suffix = this.input.slice(this.cursorPosition); |
404 | | - const count = 4 - (this.cursorPosition % 4); |
405 | | - const toAdd = " ".repeat(count); |
406 | | - this.input = prefix + toAdd + suffix; |
407 | | - if (this.cursorPosition > 0){ |
408 | | - this.xterm.write('\x1b[' + (this.cursorPosition) + 'D'); |
409 | | - } |
410 | | - // clear the line |
411 | | - this.xterm.write('\x1b[K') |
412 | | - this.xterm.write(this.input); |
413 | | - if (suffix){ |
414 | | - this.xterm.write('\x1b[' + suffix.length + 'D'); |
415 | | - } |
416 | | - this.cursorPosition += count; |
417 | | - } |
418 | | - |
419 | 426 | prompt = async () => { |
420 | 427 | this.activeInput = true; |
421 | 428 | // Hack to allow stdout/stderr to finish before we figure out where input starts |
|
442 | 449 | } |
443 | 450 | return new Promise((resolve, reject) => { |
444 | 451 | this.resolveInput = (value) => { |
445 | | - if (value !== ""){ |
| 452 | + if (value.replace(/\s/g, '').length != 0){ |
| 453 | + if (this.historyIndex !== -1){ |
| 454 | + this.historyBuffer[this.historyIndex] = this.history[this.historyIndex]; |
| 455 | + } |
446 | 456 | this.history.push(value.slice(0, -1)); |
| 457 | + this.historyBuffer.push(value.slice(0, -1)); |
447 | 458 | this.historyIndex = -1; |
448 | 459 | this.cursorPosition = 0; |
449 | 460 | } |
|
0 commit comments