1'use strict'; 2 3const { 4 NumberIsNaN, 5} = primordials; 6 7const { 8 codes: { 9 ERR_INVALID_ARG_VALUE, 10 ERR_INVALID_CURSOR_POS, 11 }, 12} = require('internal/errors'); 13 14const { 15 validateFunction, 16} = require('internal/validators'); 17const { 18 CSI, 19} = require('internal/readline/utils'); 20 21const { 22 kClearLine, 23 kClearScreenDown, 24 kClearToLineBeginning, 25 kClearToLineEnd, 26} = CSI; 27 28 29/** 30 * moves the cursor to the x and y coordinate on the given stream 31 */ 32 33function cursorTo(stream, x, y, callback) { 34 if (callback !== undefined) { 35 validateFunction(callback, 'callback'); 36 } 37 38 if (typeof y === 'function') { 39 callback = y; 40 y = undefined; 41 } 42 43 if (NumberIsNaN(x)) throw new ERR_INVALID_ARG_VALUE('x', x); 44 if (NumberIsNaN(y)) throw new ERR_INVALID_ARG_VALUE('y', y); 45 46 if (stream == null || (typeof x !== 'number' && typeof y !== 'number')) { 47 if (typeof callback === 'function') process.nextTick(callback, null); 48 return true; 49 } 50 51 if (typeof x !== 'number') throw new ERR_INVALID_CURSOR_POS(); 52 53 const data = typeof y !== 'number' ? CSI`${x + 1}G` : CSI`${y + 1};${x + 1}H`; 54 return stream.write(data, callback); 55} 56 57/** 58 * moves the cursor relative to its current location 59 */ 60 61function moveCursor(stream, dx, dy, callback) { 62 if (callback !== undefined) { 63 validateFunction(callback, 'callback'); 64 } 65 66 if (stream == null || !(dx || dy)) { 67 if (typeof callback === 'function') process.nextTick(callback, null); 68 return true; 69 } 70 71 let data = ''; 72 73 if (dx < 0) { 74 data += CSI`${-dx}D`; 75 } else if (dx > 0) { 76 data += CSI`${dx}C`; 77 } 78 79 if (dy < 0) { 80 data += CSI`${-dy}A`; 81 } else if (dy > 0) { 82 data += CSI`${dy}B`; 83 } 84 85 return stream.write(data, callback); 86} 87 88/** 89 * clears the current line the cursor is on: 90 * -1 for left of the cursor 91 * +1 for right of the cursor 92 * 0 for the entire line 93 */ 94 95function clearLine(stream, dir, callback) { 96 if (callback !== undefined) { 97 validateFunction(callback, 'callback'); 98 } 99 100 if (stream === null || stream === undefined) { 101 if (typeof callback === 'function') process.nextTick(callback, null); 102 return true; 103 } 104 105 const type = 106 dir < 0 ? kClearToLineBeginning : dir > 0 ? kClearToLineEnd : kClearLine; 107 return stream.write(type, callback); 108} 109 110/** 111 * clears the screen from the current position of the cursor down 112 */ 113 114function clearScreenDown(stream, callback) { 115 if (callback !== undefined) { 116 validateFunction(callback, 'callback'); 117 } 118 119 if (stream === null || stream === undefined) { 120 if (typeof callback === 'function') process.nextTick(callback, null); 121 return true; 122 } 123 124 return stream.write(kClearScreenDown, callback); 125} 126 127module.exports = { 128 clearLine, 129 clearScreenDown, 130 cursorTo, 131 moveCursor, 132}; 133