11cb0ef41Sopenharmony_ci'use strict';
21cb0ef41Sopenharmony_ci
31cb0ef41Sopenharmony_ciconst {
41cb0ef41Sopenharmony_ci  ArrayFrom,
51cb0ef41Sopenharmony_ci  ArrayPrototypeFilter,
61cb0ef41Sopenharmony_ci  ArrayPrototypeIndexOf,
71cb0ef41Sopenharmony_ci  ArrayPrototypeJoin,
81cb0ef41Sopenharmony_ci  ArrayPrototypeMap,
91cb0ef41Sopenharmony_ci  ArrayPrototypePop,
101cb0ef41Sopenharmony_ci  ArrayPrototypePush,
111cb0ef41Sopenharmony_ci  ArrayPrototypeReverse,
121cb0ef41Sopenharmony_ci  ArrayPrototypeSplice,
131cb0ef41Sopenharmony_ci  ArrayPrototypeShift,
141cb0ef41Sopenharmony_ci  ArrayPrototypeUnshift,
151cb0ef41Sopenharmony_ci  DateNow,
161cb0ef41Sopenharmony_ci  FunctionPrototypeCall,
171cb0ef41Sopenharmony_ci  MathCeil,
181cb0ef41Sopenharmony_ci  MathFloor,
191cb0ef41Sopenharmony_ci  MathMax,
201cb0ef41Sopenharmony_ci  MathMaxApply,
211cb0ef41Sopenharmony_ci  NumberIsFinite,
221cb0ef41Sopenharmony_ci  NumberIsNaN,
231cb0ef41Sopenharmony_ci  ObjectSetPrototypeOf,
241cb0ef41Sopenharmony_ci  RegExpPrototypeExec,
251cb0ef41Sopenharmony_ci  StringPrototypeCodePointAt,
261cb0ef41Sopenharmony_ci  StringPrototypeEndsWith,
271cb0ef41Sopenharmony_ci  StringPrototypeRepeat,
281cb0ef41Sopenharmony_ci  StringPrototypeSlice,
291cb0ef41Sopenharmony_ci  StringPrototypeStartsWith,
301cb0ef41Sopenharmony_ci  StringPrototypeTrim,
311cb0ef41Sopenharmony_ci  Symbol,
321cb0ef41Sopenharmony_ci  SymbolDispose,
331cb0ef41Sopenharmony_ci  SymbolAsyncIterator,
341cb0ef41Sopenharmony_ci  SafeStringIterator,
351cb0ef41Sopenharmony_ci} = primordials;
361cb0ef41Sopenharmony_ci
371cb0ef41Sopenharmony_ciconst { codes } = require('internal/errors');
381cb0ef41Sopenharmony_ci
391cb0ef41Sopenharmony_ciconst {
401cb0ef41Sopenharmony_ci  ERR_INVALID_ARG_VALUE,
411cb0ef41Sopenharmony_ci  ERR_USE_AFTER_CLOSE,
421cb0ef41Sopenharmony_ci} = codes;
431cb0ef41Sopenharmony_ciconst {
441cb0ef41Sopenharmony_ci  validateAbortSignal,
451cb0ef41Sopenharmony_ci  validateArray,
461cb0ef41Sopenharmony_ci  validateString,
471cb0ef41Sopenharmony_ci  validateUint32,
481cb0ef41Sopenharmony_ci} = require('internal/validators');
491cb0ef41Sopenharmony_ciconst { kEmptyObject } = require('internal/util');
501cb0ef41Sopenharmony_ciconst {
511cb0ef41Sopenharmony_ci  inspect,
521cb0ef41Sopenharmony_ci  getStringWidth,
531cb0ef41Sopenharmony_ci  stripVTControlCharacters,
541cb0ef41Sopenharmony_ci} = require('internal/util/inspect');
551cb0ef41Sopenharmony_ciconst EventEmitter = require('events');
561cb0ef41Sopenharmony_ciconst {
571cb0ef41Sopenharmony_ci  charLengthAt,
581cb0ef41Sopenharmony_ci  charLengthLeft,
591cb0ef41Sopenharmony_ci  commonPrefix,
601cb0ef41Sopenharmony_ci  kSubstringSearch,
611cb0ef41Sopenharmony_ci} = require('internal/readline/utils');
621cb0ef41Sopenharmony_cilet emitKeypressEvents;
631cb0ef41Sopenharmony_ciconst {
641cb0ef41Sopenharmony_ci  clearScreenDown,
651cb0ef41Sopenharmony_ci  cursorTo,
661cb0ef41Sopenharmony_ci  moveCursor,
671cb0ef41Sopenharmony_ci} = require('internal/readline/callbacks');
681cb0ef41Sopenharmony_ci
691cb0ef41Sopenharmony_ciconst { StringDecoder } = require('string_decoder');
701cb0ef41Sopenharmony_ci
711cb0ef41Sopenharmony_ci// Lazy load Readable for startup performance.
721cb0ef41Sopenharmony_cilet Readable;
731cb0ef41Sopenharmony_ci
741cb0ef41Sopenharmony_ciconst kHistorySize = 30;
751cb0ef41Sopenharmony_ciconst kMaxUndoRedoStackSize = 2048;
761cb0ef41Sopenharmony_ciconst kMincrlfDelay = 100;
771cb0ef41Sopenharmony_ci// \r\n, \n, or \r followed by something other than \n
781cb0ef41Sopenharmony_ciconst lineEnding = /\r?\n|\r(?!\n)/g;
791cb0ef41Sopenharmony_ci
801cb0ef41Sopenharmony_ciconst kLineObjectStream = Symbol('line object stream');
811cb0ef41Sopenharmony_ciconst kQuestionCancel = Symbol('kQuestionCancel');
821cb0ef41Sopenharmony_ci
831cb0ef41Sopenharmony_ci// GNU readline library - keyseq-timeout is 500ms (default)
841cb0ef41Sopenharmony_ciconst ESCAPE_CODE_TIMEOUT = 500;
851cb0ef41Sopenharmony_ci
861cb0ef41Sopenharmony_ci// Max length of the kill ring
871cb0ef41Sopenharmony_ciconst kMaxLengthOfKillRing = 32;
881cb0ef41Sopenharmony_ci
891cb0ef41Sopenharmony_ciconst kAddHistory = Symbol('_addHistory');
901cb0ef41Sopenharmony_ciconst kBeforeEdit = Symbol('_beforeEdit');
911cb0ef41Sopenharmony_ciconst kDecoder = Symbol('_decoder');
921cb0ef41Sopenharmony_ciconst kDeleteLeft = Symbol('_deleteLeft');
931cb0ef41Sopenharmony_ciconst kDeleteLineLeft = Symbol('_deleteLineLeft');
941cb0ef41Sopenharmony_ciconst kDeleteLineRight = Symbol('_deleteLineRight');
951cb0ef41Sopenharmony_ciconst kDeleteRight = Symbol('_deleteRight');
961cb0ef41Sopenharmony_ciconst kDeleteWordLeft = Symbol('_deleteWordLeft');
971cb0ef41Sopenharmony_ciconst kDeleteWordRight = Symbol('_deleteWordRight');
981cb0ef41Sopenharmony_ciconst kGetDisplayPos = Symbol('_getDisplayPos');
991cb0ef41Sopenharmony_ciconst kHistoryNext = Symbol('_historyNext');
1001cb0ef41Sopenharmony_ciconst kHistoryPrev = Symbol('_historyPrev');
1011cb0ef41Sopenharmony_ciconst kInsertString = Symbol('_insertString');
1021cb0ef41Sopenharmony_ciconst kLine = Symbol('_line');
1031cb0ef41Sopenharmony_ciconst kLine_buffer = Symbol('_line_buffer');
1041cb0ef41Sopenharmony_ciconst kKillRing = Symbol('_killRing');
1051cb0ef41Sopenharmony_ciconst kKillRingCursor = Symbol('_killRingCursor');
1061cb0ef41Sopenharmony_ciconst kMoveCursor = Symbol('_moveCursor');
1071cb0ef41Sopenharmony_ciconst kNormalWrite = Symbol('_normalWrite');
1081cb0ef41Sopenharmony_ciconst kOldPrompt = Symbol('_oldPrompt');
1091cb0ef41Sopenharmony_ciconst kOnLine = Symbol('_onLine');
1101cb0ef41Sopenharmony_ciconst kPreviousKey = Symbol('_previousKey');
1111cb0ef41Sopenharmony_ciconst kPrompt = Symbol('_prompt');
1121cb0ef41Sopenharmony_ciconst kPushToKillRing = Symbol('_pushToKillRing');
1131cb0ef41Sopenharmony_ciconst kPushToUndoStack = Symbol('_pushToUndoStack');
1141cb0ef41Sopenharmony_ciconst kQuestionCallback = Symbol('_questionCallback');
1151cb0ef41Sopenharmony_ciconst kRedo = Symbol('_redo');
1161cb0ef41Sopenharmony_ciconst kRedoStack = Symbol('_redoStack');
1171cb0ef41Sopenharmony_ciconst kRefreshLine = Symbol('_refreshLine');
1181cb0ef41Sopenharmony_ciconst kSawKeyPress = Symbol('_sawKeyPress');
1191cb0ef41Sopenharmony_ciconst kSawReturnAt = Symbol('_sawReturnAt');
1201cb0ef41Sopenharmony_ciconst kSetRawMode = Symbol('_setRawMode');
1211cb0ef41Sopenharmony_ciconst kTabComplete = Symbol('_tabComplete');
1221cb0ef41Sopenharmony_ciconst kTabCompleter = Symbol('_tabCompleter');
1231cb0ef41Sopenharmony_ciconst kTtyWrite = Symbol('_ttyWrite');
1241cb0ef41Sopenharmony_ciconst kUndo = Symbol('_undo');
1251cb0ef41Sopenharmony_ciconst kUndoStack = Symbol('_undoStack');
1261cb0ef41Sopenharmony_ciconst kWordLeft = Symbol('_wordLeft');
1271cb0ef41Sopenharmony_ciconst kWordRight = Symbol('_wordRight');
1281cb0ef41Sopenharmony_ciconst kWriteToOutput = Symbol('_writeToOutput');
1291cb0ef41Sopenharmony_ciconst kYank = Symbol('_yank');
1301cb0ef41Sopenharmony_ciconst kYanking = Symbol('_yanking');
1311cb0ef41Sopenharmony_ciconst kYankPop = Symbol('_yankPop');
1321cb0ef41Sopenharmony_ci
1331cb0ef41Sopenharmony_cifunction InterfaceConstructor(input, output, completer, terminal) {
1341cb0ef41Sopenharmony_ci  this[kSawReturnAt] = 0;
1351cb0ef41Sopenharmony_ci  // TODO(BridgeAR): Document this property. The name is not ideal, so we
1361cb0ef41Sopenharmony_ci  // might want to expose an alias and document that instead.
1371cb0ef41Sopenharmony_ci  this.isCompletionEnabled = true;
1381cb0ef41Sopenharmony_ci  this[kSawKeyPress] = false;
1391cb0ef41Sopenharmony_ci  this[kPreviousKey] = null;
1401cb0ef41Sopenharmony_ci  this.escapeCodeTimeout = ESCAPE_CODE_TIMEOUT;
1411cb0ef41Sopenharmony_ci  this.tabSize = 8;
1421cb0ef41Sopenharmony_ci
1431cb0ef41Sopenharmony_ci  FunctionPrototypeCall(EventEmitter, this);
1441cb0ef41Sopenharmony_ci
1451cb0ef41Sopenharmony_ci  let history;
1461cb0ef41Sopenharmony_ci  let historySize;
1471cb0ef41Sopenharmony_ci  let removeHistoryDuplicates = false;
1481cb0ef41Sopenharmony_ci  let crlfDelay;
1491cb0ef41Sopenharmony_ci  let prompt = '> ';
1501cb0ef41Sopenharmony_ci  let signal;
1511cb0ef41Sopenharmony_ci
1521cb0ef41Sopenharmony_ci  if (input?.input) {
1531cb0ef41Sopenharmony_ci    // An options object was given
1541cb0ef41Sopenharmony_ci    output = input.output;
1551cb0ef41Sopenharmony_ci    completer = input.completer;
1561cb0ef41Sopenharmony_ci    terminal = input.terminal;
1571cb0ef41Sopenharmony_ci    history = input.history;
1581cb0ef41Sopenharmony_ci    historySize = input.historySize;
1591cb0ef41Sopenharmony_ci    signal = input.signal;
1601cb0ef41Sopenharmony_ci    if (input.tabSize !== undefined) {
1611cb0ef41Sopenharmony_ci      validateUint32(input.tabSize, 'tabSize', true);
1621cb0ef41Sopenharmony_ci      this.tabSize = input.tabSize;
1631cb0ef41Sopenharmony_ci    }
1641cb0ef41Sopenharmony_ci    removeHistoryDuplicates = input.removeHistoryDuplicates;
1651cb0ef41Sopenharmony_ci    if (input.prompt !== undefined) {
1661cb0ef41Sopenharmony_ci      prompt = input.prompt;
1671cb0ef41Sopenharmony_ci    }
1681cb0ef41Sopenharmony_ci    if (input.escapeCodeTimeout !== undefined) {
1691cb0ef41Sopenharmony_ci      if (NumberIsFinite(input.escapeCodeTimeout)) {
1701cb0ef41Sopenharmony_ci        this.escapeCodeTimeout = input.escapeCodeTimeout;
1711cb0ef41Sopenharmony_ci      } else {
1721cb0ef41Sopenharmony_ci        throw new ERR_INVALID_ARG_VALUE(
1731cb0ef41Sopenharmony_ci          'input.escapeCodeTimeout',
1741cb0ef41Sopenharmony_ci          this.escapeCodeTimeout,
1751cb0ef41Sopenharmony_ci        );
1761cb0ef41Sopenharmony_ci      }
1771cb0ef41Sopenharmony_ci    }
1781cb0ef41Sopenharmony_ci
1791cb0ef41Sopenharmony_ci    if (signal) {
1801cb0ef41Sopenharmony_ci      validateAbortSignal(signal, 'options.signal');
1811cb0ef41Sopenharmony_ci    }
1821cb0ef41Sopenharmony_ci
1831cb0ef41Sopenharmony_ci    crlfDelay = input.crlfDelay;
1841cb0ef41Sopenharmony_ci    input = input.input;
1851cb0ef41Sopenharmony_ci  }
1861cb0ef41Sopenharmony_ci
1871cb0ef41Sopenharmony_ci  if (completer !== undefined && typeof completer !== 'function') {
1881cb0ef41Sopenharmony_ci    throw new ERR_INVALID_ARG_VALUE('completer', completer);
1891cb0ef41Sopenharmony_ci  }
1901cb0ef41Sopenharmony_ci
1911cb0ef41Sopenharmony_ci  if (history === undefined) {
1921cb0ef41Sopenharmony_ci    history = [];
1931cb0ef41Sopenharmony_ci  } else {
1941cb0ef41Sopenharmony_ci    validateArray(history, 'history');
1951cb0ef41Sopenharmony_ci  }
1961cb0ef41Sopenharmony_ci
1971cb0ef41Sopenharmony_ci  if (historySize === undefined) {
1981cb0ef41Sopenharmony_ci    historySize = kHistorySize;
1991cb0ef41Sopenharmony_ci  }
2001cb0ef41Sopenharmony_ci
2011cb0ef41Sopenharmony_ci  if (
2021cb0ef41Sopenharmony_ci    typeof historySize !== 'number' ||
2031cb0ef41Sopenharmony_ci      NumberIsNaN(historySize) ||
2041cb0ef41Sopenharmony_ci      historySize < 0
2051cb0ef41Sopenharmony_ci  ) {
2061cb0ef41Sopenharmony_ci    throw new ERR_INVALID_ARG_VALUE.RangeError('historySize', historySize);
2071cb0ef41Sopenharmony_ci  }
2081cb0ef41Sopenharmony_ci
2091cb0ef41Sopenharmony_ci  // Backwards compat; check the isTTY prop of the output stream
2101cb0ef41Sopenharmony_ci  //  when `terminal` was not specified
2111cb0ef41Sopenharmony_ci  if (terminal === undefined && !(output === null || output === undefined)) {
2121cb0ef41Sopenharmony_ci    terminal = !!output.isTTY;
2131cb0ef41Sopenharmony_ci  }
2141cb0ef41Sopenharmony_ci
2151cb0ef41Sopenharmony_ci  const self = this;
2161cb0ef41Sopenharmony_ci
2171cb0ef41Sopenharmony_ci  this.line = '';
2181cb0ef41Sopenharmony_ci  this[kSubstringSearch] = null;
2191cb0ef41Sopenharmony_ci  this.output = output;
2201cb0ef41Sopenharmony_ci  this.input = input;
2211cb0ef41Sopenharmony_ci  this[kUndoStack] = [];
2221cb0ef41Sopenharmony_ci  this[kRedoStack] = [];
2231cb0ef41Sopenharmony_ci  this.history = history;
2241cb0ef41Sopenharmony_ci  this.historySize = historySize;
2251cb0ef41Sopenharmony_ci
2261cb0ef41Sopenharmony_ci  // The kill ring is a global list of blocks of text that were previously
2271cb0ef41Sopenharmony_ci  // killed (deleted). If its size exceeds kMaxLengthOfKillRing, the oldest
2281cb0ef41Sopenharmony_ci  // element will be removed to make room for the latest deletion. With kill
2291cb0ef41Sopenharmony_ci  // ring, users are able to recall (yank) or cycle (yank pop) among previously
2301cb0ef41Sopenharmony_ci  // killed texts, quite similar to the behavior of Emacs.
2311cb0ef41Sopenharmony_ci  this[kKillRing] = [];
2321cb0ef41Sopenharmony_ci  this[kKillRingCursor] = 0;
2331cb0ef41Sopenharmony_ci
2341cb0ef41Sopenharmony_ci  this.removeHistoryDuplicates = !!removeHistoryDuplicates;
2351cb0ef41Sopenharmony_ci  this.crlfDelay = crlfDelay ?
2361cb0ef41Sopenharmony_ci    MathMax(kMincrlfDelay, crlfDelay) :
2371cb0ef41Sopenharmony_ci    kMincrlfDelay;
2381cb0ef41Sopenharmony_ci  this.completer = completer;
2391cb0ef41Sopenharmony_ci
2401cb0ef41Sopenharmony_ci  this.setPrompt(prompt);
2411cb0ef41Sopenharmony_ci
2421cb0ef41Sopenharmony_ci  this.terminal = !!terminal;
2431cb0ef41Sopenharmony_ci
2441cb0ef41Sopenharmony_ci
2451cb0ef41Sopenharmony_ci  function onerror(err) {
2461cb0ef41Sopenharmony_ci    self.emit('error', err);
2471cb0ef41Sopenharmony_ci  }
2481cb0ef41Sopenharmony_ci
2491cb0ef41Sopenharmony_ci  function ondata(data) {
2501cb0ef41Sopenharmony_ci    self[kNormalWrite](data);
2511cb0ef41Sopenharmony_ci  }
2521cb0ef41Sopenharmony_ci
2531cb0ef41Sopenharmony_ci  function onend() {
2541cb0ef41Sopenharmony_ci    if (
2551cb0ef41Sopenharmony_ci      typeof self[kLine_buffer] === 'string' &&
2561cb0ef41Sopenharmony_ci        self[kLine_buffer].length > 0
2571cb0ef41Sopenharmony_ci    ) {
2581cb0ef41Sopenharmony_ci      self.emit('line', self[kLine_buffer]);
2591cb0ef41Sopenharmony_ci    }
2601cb0ef41Sopenharmony_ci    self.close();
2611cb0ef41Sopenharmony_ci  }
2621cb0ef41Sopenharmony_ci
2631cb0ef41Sopenharmony_ci  function ontermend() {
2641cb0ef41Sopenharmony_ci    if (typeof self.line === 'string' && self.line.length > 0) {
2651cb0ef41Sopenharmony_ci      self.emit('line', self.line);
2661cb0ef41Sopenharmony_ci    }
2671cb0ef41Sopenharmony_ci    self.close();
2681cb0ef41Sopenharmony_ci  }
2691cb0ef41Sopenharmony_ci
2701cb0ef41Sopenharmony_ci  function onkeypress(s, key) {
2711cb0ef41Sopenharmony_ci    self[kTtyWrite](s, key);
2721cb0ef41Sopenharmony_ci    if (key && key.sequence) {
2731cb0ef41Sopenharmony_ci      // If the key.sequence is half of a surrogate pair
2741cb0ef41Sopenharmony_ci      // (>= 0xd800 and <= 0xdfff), refresh the line so
2751cb0ef41Sopenharmony_ci      // the character is displayed appropriately.
2761cb0ef41Sopenharmony_ci      const ch = StringPrototypeCodePointAt(key.sequence, 0);
2771cb0ef41Sopenharmony_ci      if (ch >= 0xd800 && ch <= 0xdfff) self[kRefreshLine]();
2781cb0ef41Sopenharmony_ci    }
2791cb0ef41Sopenharmony_ci  }
2801cb0ef41Sopenharmony_ci
2811cb0ef41Sopenharmony_ci  function onresize() {
2821cb0ef41Sopenharmony_ci    self[kRefreshLine]();
2831cb0ef41Sopenharmony_ci  }
2841cb0ef41Sopenharmony_ci
2851cb0ef41Sopenharmony_ci  this[kLineObjectStream] = undefined;
2861cb0ef41Sopenharmony_ci
2871cb0ef41Sopenharmony_ci  input.on('error', onerror);
2881cb0ef41Sopenharmony_ci
2891cb0ef41Sopenharmony_ci  if (!this.terminal) {
2901cb0ef41Sopenharmony_ci    function onSelfCloseWithoutTerminal() {
2911cb0ef41Sopenharmony_ci      input.removeListener('data', ondata);
2921cb0ef41Sopenharmony_ci      input.removeListener('error', onerror);
2931cb0ef41Sopenharmony_ci      input.removeListener('end', onend);
2941cb0ef41Sopenharmony_ci    }
2951cb0ef41Sopenharmony_ci
2961cb0ef41Sopenharmony_ci    input.on('data', ondata);
2971cb0ef41Sopenharmony_ci    input.on('end', onend);
2981cb0ef41Sopenharmony_ci    self.once('close', onSelfCloseWithoutTerminal);
2991cb0ef41Sopenharmony_ci    this[kDecoder] = new StringDecoder('utf8');
3001cb0ef41Sopenharmony_ci  } else {
3011cb0ef41Sopenharmony_ci    function onSelfCloseWithTerminal() {
3021cb0ef41Sopenharmony_ci      input.removeListener('keypress', onkeypress);
3031cb0ef41Sopenharmony_ci      input.removeListener('error', onerror);
3041cb0ef41Sopenharmony_ci      input.removeListener('end', ontermend);
3051cb0ef41Sopenharmony_ci      if (output !== null && output !== undefined) {
3061cb0ef41Sopenharmony_ci        output.removeListener('resize', onresize);
3071cb0ef41Sopenharmony_ci      }
3081cb0ef41Sopenharmony_ci    }
3091cb0ef41Sopenharmony_ci
3101cb0ef41Sopenharmony_ci    emitKeypressEvents ??= require('internal/readline/emitKeypressEvents');
3111cb0ef41Sopenharmony_ci    emitKeypressEvents(input, this);
3121cb0ef41Sopenharmony_ci
3131cb0ef41Sopenharmony_ci    // `input` usually refers to stdin
3141cb0ef41Sopenharmony_ci    input.on('keypress', onkeypress);
3151cb0ef41Sopenharmony_ci    input.on('end', ontermend);
3161cb0ef41Sopenharmony_ci
3171cb0ef41Sopenharmony_ci    this[kSetRawMode](true);
3181cb0ef41Sopenharmony_ci    this.terminal = true;
3191cb0ef41Sopenharmony_ci
3201cb0ef41Sopenharmony_ci    // Cursor position on the line.
3211cb0ef41Sopenharmony_ci    this.cursor = 0;
3221cb0ef41Sopenharmony_ci
3231cb0ef41Sopenharmony_ci    this.historyIndex = -1;
3241cb0ef41Sopenharmony_ci
3251cb0ef41Sopenharmony_ci    if (output !== null && output !== undefined)
3261cb0ef41Sopenharmony_ci      output.on('resize', onresize);
3271cb0ef41Sopenharmony_ci
3281cb0ef41Sopenharmony_ci    self.once('close', onSelfCloseWithTerminal);
3291cb0ef41Sopenharmony_ci  }
3301cb0ef41Sopenharmony_ci
3311cb0ef41Sopenharmony_ci  if (signal) {
3321cb0ef41Sopenharmony_ci    const onAborted = () => self.close();
3331cb0ef41Sopenharmony_ci    if (signal.aborted) {
3341cb0ef41Sopenharmony_ci      process.nextTick(onAborted);
3351cb0ef41Sopenharmony_ci    } else {
3361cb0ef41Sopenharmony_ci      const disposable = EventEmitter.addAbortListener(signal, onAborted);
3371cb0ef41Sopenharmony_ci      self.once('close', disposable[SymbolDispose]);
3381cb0ef41Sopenharmony_ci    }
3391cb0ef41Sopenharmony_ci  }
3401cb0ef41Sopenharmony_ci
3411cb0ef41Sopenharmony_ci  // Current line
3421cb0ef41Sopenharmony_ci  this.line = '';
3431cb0ef41Sopenharmony_ci
3441cb0ef41Sopenharmony_ci  input.resume();
3451cb0ef41Sopenharmony_ci}
3461cb0ef41Sopenharmony_ci
3471cb0ef41Sopenharmony_ciObjectSetPrototypeOf(InterfaceConstructor.prototype, EventEmitter.prototype);
3481cb0ef41Sopenharmony_ciObjectSetPrototypeOf(InterfaceConstructor, EventEmitter);
3491cb0ef41Sopenharmony_ci
3501cb0ef41Sopenharmony_ciclass Interface extends InterfaceConstructor {
3511cb0ef41Sopenharmony_ci  // eslint-disable-next-line no-useless-constructor
3521cb0ef41Sopenharmony_ci  constructor(input, output, completer, terminal) {
3531cb0ef41Sopenharmony_ci    super(input, output, completer, terminal);
3541cb0ef41Sopenharmony_ci  }
3551cb0ef41Sopenharmony_ci  get columns() {
3561cb0ef41Sopenharmony_ci    if (this.output && this.output.columns) return this.output.columns;
3571cb0ef41Sopenharmony_ci    return Infinity;
3581cb0ef41Sopenharmony_ci  }
3591cb0ef41Sopenharmony_ci
3601cb0ef41Sopenharmony_ci  /**
3611cb0ef41Sopenharmony_ci   * Sets the prompt written to the output.
3621cb0ef41Sopenharmony_ci   * @param {string} prompt
3631cb0ef41Sopenharmony_ci   * @returns {void}
3641cb0ef41Sopenharmony_ci   */
3651cb0ef41Sopenharmony_ci  setPrompt(prompt) {
3661cb0ef41Sopenharmony_ci    this[kPrompt] = prompt;
3671cb0ef41Sopenharmony_ci  }
3681cb0ef41Sopenharmony_ci
3691cb0ef41Sopenharmony_ci  /**
3701cb0ef41Sopenharmony_ci   * Returns the current prompt used by `rl.prompt()`.
3711cb0ef41Sopenharmony_ci   * @returns {string}
3721cb0ef41Sopenharmony_ci   */
3731cb0ef41Sopenharmony_ci  getPrompt() {
3741cb0ef41Sopenharmony_ci    return this[kPrompt];
3751cb0ef41Sopenharmony_ci  }
3761cb0ef41Sopenharmony_ci
3771cb0ef41Sopenharmony_ci  [kSetRawMode](mode) {
3781cb0ef41Sopenharmony_ci    const wasInRawMode = this.input.isRaw;
3791cb0ef41Sopenharmony_ci
3801cb0ef41Sopenharmony_ci    if (typeof this.input.setRawMode === 'function') {
3811cb0ef41Sopenharmony_ci      this.input.setRawMode(mode);
3821cb0ef41Sopenharmony_ci    }
3831cb0ef41Sopenharmony_ci
3841cb0ef41Sopenharmony_ci    return wasInRawMode;
3851cb0ef41Sopenharmony_ci  }
3861cb0ef41Sopenharmony_ci
3871cb0ef41Sopenharmony_ci  /**
3881cb0ef41Sopenharmony_ci   * Writes the configured `prompt` to a new line in `output`.
3891cb0ef41Sopenharmony_ci   * @param {boolean} [preserveCursor]
3901cb0ef41Sopenharmony_ci   * @returns {void}
3911cb0ef41Sopenharmony_ci   */
3921cb0ef41Sopenharmony_ci  prompt(preserveCursor) {
3931cb0ef41Sopenharmony_ci    if (this.paused) this.resume();
3941cb0ef41Sopenharmony_ci    if (this.terminal && process.env.TERM !== 'dumb') {
3951cb0ef41Sopenharmony_ci      if (!preserveCursor) this.cursor = 0;
3961cb0ef41Sopenharmony_ci      this[kRefreshLine]();
3971cb0ef41Sopenharmony_ci    } else {
3981cb0ef41Sopenharmony_ci      this[kWriteToOutput](this[kPrompt]);
3991cb0ef41Sopenharmony_ci    }
4001cb0ef41Sopenharmony_ci  }
4011cb0ef41Sopenharmony_ci
4021cb0ef41Sopenharmony_ci  question(query, cb) {
4031cb0ef41Sopenharmony_ci    if (this.closed) {
4041cb0ef41Sopenharmony_ci      throw new ERR_USE_AFTER_CLOSE('readline');
4051cb0ef41Sopenharmony_ci    }
4061cb0ef41Sopenharmony_ci    if (this[kQuestionCallback]) {
4071cb0ef41Sopenharmony_ci      this.prompt();
4081cb0ef41Sopenharmony_ci    } else {
4091cb0ef41Sopenharmony_ci      this[kOldPrompt] = this[kPrompt];
4101cb0ef41Sopenharmony_ci      this.setPrompt(query);
4111cb0ef41Sopenharmony_ci      this[kQuestionCallback] = cb;
4121cb0ef41Sopenharmony_ci      this.prompt();
4131cb0ef41Sopenharmony_ci    }
4141cb0ef41Sopenharmony_ci  }
4151cb0ef41Sopenharmony_ci
4161cb0ef41Sopenharmony_ci  [kOnLine](line) {
4171cb0ef41Sopenharmony_ci    if (this[kQuestionCallback]) {
4181cb0ef41Sopenharmony_ci      const cb = this[kQuestionCallback];
4191cb0ef41Sopenharmony_ci      this[kQuestionCallback] = null;
4201cb0ef41Sopenharmony_ci      this.setPrompt(this[kOldPrompt]);
4211cb0ef41Sopenharmony_ci      cb(line);
4221cb0ef41Sopenharmony_ci    } else {
4231cb0ef41Sopenharmony_ci      this.emit('line', line);
4241cb0ef41Sopenharmony_ci    }
4251cb0ef41Sopenharmony_ci  }
4261cb0ef41Sopenharmony_ci
4271cb0ef41Sopenharmony_ci  [kBeforeEdit](oldText, oldCursor) {
4281cb0ef41Sopenharmony_ci    this[kPushToUndoStack](oldText, oldCursor);
4291cb0ef41Sopenharmony_ci  }
4301cb0ef41Sopenharmony_ci
4311cb0ef41Sopenharmony_ci  [kQuestionCancel]() {
4321cb0ef41Sopenharmony_ci    if (this[kQuestionCallback]) {
4331cb0ef41Sopenharmony_ci      this[kQuestionCallback] = null;
4341cb0ef41Sopenharmony_ci      this.setPrompt(this[kOldPrompt]);
4351cb0ef41Sopenharmony_ci      this.clearLine();
4361cb0ef41Sopenharmony_ci    }
4371cb0ef41Sopenharmony_ci  }
4381cb0ef41Sopenharmony_ci
4391cb0ef41Sopenharmony_ci  [kWriteToOutput](stringToWrite) {
4401cb0ef41Sopenharmony_ci    validateString(stringToWrite, 'stringToWrite');
4411cb0ef41Sopenharmony_ci
4421cb0ef41Sopenharmony_ci    if (this.output !== null && this.output !== undefined) {
4431cb0ef41Sopenharmony_ci      this.output.write(stringToWrite);
4441cb0ef41Sopenharmony_ci    }
4451cb0ef41Sopenharmony_ci  }
4461cb0ef41Sopenharmony_ci
4471cb0ef41Sopenharmony_ci  [kAddHistory]() {
4481cb0ef41Sopenharmony_ci    if (this.line.length === 0) return '';
4491cb0ef41Sopenharmony_ci
4501cb0ef41Sopenharmony_ci    // If the history is disabled then return the line
4511cb0ef41Sopenharmony_ci    if (this.historySize === 0) return this.line;
4521cb0ef41Sopenharmony_ci
4531cb0ef41Sopenharmony_ci    // If the trimmed line is empty then return the line
4541cb0ef41Sopenharmony_ci    if (StringPrototypeTrim(this.line).length === 0) return this.line;
4551cb0ef41Sopenharmony_ci
4561cb0ef41Sopenharmony_ci    if (this.history.length === 0 || this.history[0] !== this.line) {
4571cb0ef41Sopenharmony_ci      if (this.removeHistoryDuplicates) {
4581cb0ef41Sopenharmony_ci        // Remove older history line if identical to new one
4591cb0ef41Sopenharmony_ci        const dupIndex = ArrayPrototypeIndexOf(this.history, this.line);
4601cb0ef41Sopenharmony_ci        if (dupIndex !== -1) ArrayPrototypeSplice(this.history, dupIndex, 1);
4611cb0ef41Sopenharmony_ci      }
4621cb0ef41Sopenharmony_ci
4631cb0ef41Sopenharmony_ci      ArrayPrototypeUnshift(this.history, this.line);
4641cb0ef41Sopenharmony_ci
4651cb0ef41Sopenharmony_ci      // Only store so many
4661cb0ef41Sopenharmony_ci      if (this.history.length > this.historySize)
4671cb0ef41Sopenharmony_ci        ArrayPrototypePop(this.history);
4681cb0ef41Sopenharmony_ci    }
4691cb0ef41Sopenharmony_ci
4701cb0ef41Sopenharmony_ci    this.historyIndex = -1;
4711cb0ef41Sopenharmony_ci
4721cb0ef41Sopenharmony_ci    // The listener could change the history object, possibly
4731cb0ef41Sopenharmony_ci    // to remove the last added entry if it is sensitive and should
4741cb0ef41Sopenharmony_ci    // not be persisted in the history, like a password
4751cb0ef41Sopenharmony_ci    const line = this.history[0];
4761cb0ef41Sopenharmony_ci
4771cb0ef41Sopenharmony_ci    // Emit history event to notify listeners of update
4781cb0ef41Sopenharmony_ci    this.emit('history', this.history);
4791cb0ef41Sopenharmony_ci
4801cb0ef41Sopenharmony_ci    return line;
4811cb0ef41Sopenharmony_ci  }
4821cb0ef41Sopenharmony_ci
4831cb0ef41Sopenharmony_ci  [kRefreshLine]() {
4841cb0ef41Sopenharmony_ci    // line length
4851cb0ef41Sopenharmony_ci    const line = this[kPrompt] + this.line;
4861cb0ef41Sopenharmony_ci    const dispPos = this[kGetDisplayPos](line);
4871cb0ef41Sopenharmony_ci    const lineCols = dispPos.cols;
4881cb0ef41Sopenharmony_ci    const lineRows = dispPos.rows;
4891cb0ef41Sopenharmony_ci
4901cb0ef41Sopenharmony_ci    // cursor position
4911cb0ef41Sopenharmony_ci    const cursorPos = this.getCursorPos();
4921cb0ef41Sopenharmony_ci
4931cb0ef41Sopenharmony_ci    // First move to the bottom of the current line, based on cursor pos
4941cb0ef41Sopenharmony_ci    const prevRows = this.prevRows || 0;
4951cb0ef41Sopenharmony_ci    if (prevRows > 0) {
4961cb0ef41Sopenharmony_ci      moveCursor(this.output, 0, -prevRows);
4971cb0ef41Sopenharmony_ci    }
4981cb0ef41Sopenharmony_ci
4991cb0ef41Sopenharmony_ci    // Cursor to left edge.
5001cb0ef41Sopenharmony_ci    cursorTo(this.output, 0);
5011cb0ef41Sopenharmony_ci    // erase data
5021cb0ef41Sopenharmony_ci    clearScreenDown(this.output);
5031cb0ef41Sopenharmony_ci
5041cb0ef41Sopenharmony_ci    // Write the prompt and the current buffer content.
5051cb0ef41Sopenharmony_ci    this[kWriteToOutput](line);
5061cb0ef41Sopenharmony_ci
5071cb0ef41Sopenharmony_ci    // Force terminal to allocate a new line
5081cb0ef41Sopenharmony_ci    if (lineCols === 0) {
5091cb0ef41Sopenharmony_ci      this[kWriteToOutput](' ');
5101cb0ef41Sopenharmony_ci    }
5111cb0ef41Sopenharmony_ci
5121cb0ef41Sopenharmony_ci    // Move cursor to original position.
5131cb0ef41Sopenharmony_ci    cursorTo(this.output, cursorPos.cols);
5141cb0ef41Sopenharmony_ci
5151cb0ef41Sopenharmony_ci    const diff = lineRows - cursorPos.rows;
5161cb0ef41Sopenharmony_ci    if (diff > 0) {
5171cb0ef41Sopenharmony_ci      moveCursor(this.output, 0, -diff);
5181cb0ef41Sopenharmony_ci    }
5191cb0ef41Sopenharmony_ci
5201cb0ef41Sopenharmony_ci    this.prevRows = cursorPos.rows;
5211cb0ef41Sopenharmony_ci  }
5221cb0ef41Sopenharmony_ci
5231cb0ef41Sopenharmony_ci  /**
5241cb0ef41Sopenharmony_ci   * Closes the `readline.Interface` instance.
5251cb0ef41Sopenharmony_ci   * @returns {void}
5261cb0ef41Sopenharmony_ci   */
5271cb0ef41Sopenharmony_ci  close() {
5281cb0ef41Sopenharmony_ci    if (this.closed) return;
5291cb0ef41Sopenharmony_ci    this.pause();
5301cb0ef41Sopenharmony_ci    if (this.terminal) {
5311cb0ef41Sopenharmony_ci      this[kSetRawMode](false);
5321cb0ef41Sopenharmony_ci    }
5331cb0ef41Sopenharmony_ci    this.closed = true;
5341cb0ef41Sopenharmony_ci    this.emit('close');
5351cb0ef41Sopenharmony_ci  }
5361cb0ef41Sopenharmony_ci
5371cb0ef41Sopenharmony_ci  /**
5381cb0ef41Sopenharmony_ci   * Pauses the `input` stream.
5391cb0ef41Sopenharmony_ci   * @returns {void | Interface}
5401cb0ef41Sopenharmony_ci   */
5411cb0ef41Sopenharmony_ci  pause() {
5421cb0ef41Sopenharmony_ci    if (this.paused) return;
5431cb0ef41Sopenharmony_ci    this.input.pause();
5441cb0ef41Sopenharmony_ci    this.paused = true;
5451cb0ef41Sopenharmony_ci    this.emit('pause');
5461cb0ef41Sopenharmony_ci    return this;
5471cb0ef41Sopenharmony_ci  }
5481cb0ef41Sopenharmony_ci
5491cb0ef41Sopenharmony_ci  /**
5501cb0ef41Sopenharmony_ci   * Resumes the `input` stream if paused.
5511cb0ef41Sopenharmony_ci   * @returns {void | Interface}
5521cb0ef41Sopenharmony_ci   */
5531cb0ef41Sopenharmony_ci  resume() {
5541cb0ef41Sopenharmony_ci    if (!this.paused) return;
5551cb0ef41Sopenharmony_ci    this.input.resume();
5561cb0ef41Sopenharmony_ci    this.paused = false;
5571cb0ef41Sopenharmony_ci    this.emit('resume');
5581cb0ef41Sopenharmony_ci    return this;
5591cb0ef41Sopenharmony_ci  }
5601cb0ef41Sopenharmony_ci
5611cb0ef41Sopenharmony_ci  /**
5621cb0ef41Sopenharmony_ci   * Writes either `data` or a `key` sequence identified by
5631cb0ef41Sopenharmony_ci   * `key` to the `output`.
5641cb0ef41Sopenharmony_ci   * @param {string} d
5651cb0ef41Sopenharmony_ci   * @param {{
5661cb0ef41Sopenharmony_ci   *   ctrl?: boolean;
5671cb0ef41Sopenharmony_ci   *   meta?: boolean;
5681cb0ef41Sopenharmony_ci   *   shift?: boolean;
5691cb0ef41Sopenharmony_ci   *   name?: string;
5701cb0ef41Sopenharmony_ci   *   }} [key]
5711cb0ef41Sopenharmony_ci   * @returns {void}
5721cb0ef41Sopenharmony_ci   */
5731cb0ef41Sopenharmony_ci  write(d, key) {
5741cb0ef41Sopenharmony_ci    if (this.paused) this.resume();
5751cb0ef41Sopenharmony_ci    if (this.terminal) {
5761cb0ef41Sopenharmony_ci      this[kTtyWrite](d, key);
5771cb0ef41Sopenharmony_ci    } else {
5781cb0ef41Sopenharmony_ci      this[kNormalWrite](d);
5791cb0ef41Sopenharmony_ci    }
5801cb0ef41Sopenharmony_ci  }
5811cb0ef41Sopenharmony_ci
5821cb0ef41Sopenharmony_ci  [kNormalWrite](b) {
5831cb0ef41Sopenharmony_ci    if (b === undefined) {
5841cb0ef41Sopenharmony_ci      return;
5851cb0ef41Sopenharmony_ci    }
5861cb0ef41Sopenharmony_ci    let string = this[kDecoder].write(b);
5871cb0ef41Sopenharmony_ci    if (
5881cb0ef41Sopenharmony_ci      this[kSawReturnAt] &&
5891cb0ef41Sopenharmony_ci      DateNow() - this[kSawReturnAt] <= this.crlfDelay
5901cb0ef41Sopenharmony_ci    ) {
5911cb0ef41Sopenharmony_ci      if (StringPrototypeCodePointAt(string) === 10) string = StringPrototypeSlice(string, 1);
5921cb0ef41Sopenharmony_ci      this[kSawReturnAt] = 0;
5931cb0ef41Sopenharmony_ci    }
5941cb0ef41Sopenharmony_ci
5951cb0ef41Sopenharmony_ci    // Run test() on the new string chunk, not on the entire line buffer.
5961cb0ef41Sopenharmony_ci    let newPartContainsEnding = RegExpPrototypeExec(lineEnding, string);
5971cb0ef41Sopenharmony_ci    if (newPartContainsEnding !== null) {
5981cb0ef41Sopenharmony_ci      if (this[kLine_buffer]) {
5991cb0ef41Sopenharmony_ci        string = this[kLine_buffer] + string;
6001cb0ef41Sopenharmony_ci        this[kLine_buffer] = null;
6011cb0ef41Sopenharmony_ci        lineEnding.lastIndex = 0; // Start the search from the beginning of the string.
6021cb0ef41Sopenharmony_ci        newPartContainsEnding = RegExpPrototypeExec(lineEnding, string);
6031cb0ef41Sopenharmony_ci      }
6041cb0ef41Sopenharmony_ci      this[kSawReturnAt] = StringPrototypeEndsWith(string, '\r') ?
6051cb0ef41Sopenharmony_ci        DateNow() :
6061cb0ef41Sopenharmony_ci        0;
6071cb0ef41Sopenharmony_ci
6081cb0ef41Sopenharmony_ci      const indexes = [0, newPartContainsEnding.index, lineEnding.lastIndex];
6091cb0ef41Sopenharmony_ci      let nextMatch;
6101cb0ef41Sopenharmony_ci      while ((nextMatch = RegExpPrototypeExec(lineEnding, string)) !== null) {
6111cb0ef41Sopenharmony_ci        ArrayPrototypePush(indexes, nextMatch.index, lineEnding.lastIndex);
6121cb0ef41Sopenharmony_ci      }
6131cb0ef41Sopenharmony_ci      const lastIndex = indexes.length - 1;
6141cb0ef41Sopenharmony_ci      // Either '' or (conceivably) the unfinished portion of the next line
6151cb0ef41Sopenharmony_ci      this[kLine_buffer] = StringPrototypeSlice(string, indexes[lastIndex]);
6161cb0ef41Sopenharmony_ci      for (let i = 1; i < lastIndex; i += 2) {
6171cb0ef41Sopenharmony_ci        this[kOnLine](StringPrototypeSlice(string, indexes[i - 1], indexes[i]));
6181cb0ef41Sopenharmony_ci      }
6191cb0ef41Sopenharmony_ci    } else if (string) {
6201cb0ef41Sopenharmony_ci      // No newlines this time, save what we have for next time
6211cb0ef41Sopenharmony_ci      if (this[kLine_buffer]) {
6221cb0ef41Sopenharmony_ci        this[kLine_buffer] += string;
6231cb0ef41Sopenharmony_ci      } else {
6241cb0ef41Sopenharmony_ci        this[kLine_buffer] = string;
6251cb0ef41Sopenharmony_ci      }
6261cb0ef41Sopenharmony_ci    }
6271cb0ef41Sopenharmony_ci  }
6281cb0ef41Sopenharmony_ci
6291cb0ef41Sopenharmony_ci  [kInsertString](c) {
6301cb0ef41Sopenharmony_ci    this[kBeforeEdit](this.line, this.cursor);
6311cb0ef41Sopenharmony_ci    if (this.cursor < this.line.length) {
6321cb0ef41Sopenharmony_ci      const beg = StringPrototypeSlice(this.line, 0, this.cursor);
6331cb0ef41Sopenharmony_ci      const end = StringPrototypeSlice(
6341cb0ef41Sopenharmony_ci        this.line,
6351cb0ef41Sopenharmony_ci        this.cursor,
6361cb0ef41Sopenharmony_ci        this.line.length,
6371cb0ef41Sopenharmony_ci      );
6381cb0ef41Sopenharmony_ci      this.line = beg + c + end;
6391cb0ef41Sopenharmony_ci      this.cursor += c.length;
6401cb0ef41Sopenharmony_ci      this[kRefreshLine]();
6411cb0ef41Sopenharmony_ci    } else {
6421cb0ef41Sopenharmony_ci      const oldPos = this.getCursorPos();
6431cb0ef41Sopenharmony_ci      this.line += c;
6441cb0ef41Sopenharmony_ci      this.cursor += c.length;
6451cb0ef41Sopenharmony_ci      const newPos = this.getCursorPos();
6461cb0ef41Sopenharmony_ci
6471cb0ef41Sopenharmony_ci      if (oldPos.rows < newPos.rows) {
6481cb0ef41Sopenharmony_ci        this[kRefreshLine]();
6491cb0ef41Sopenharmony_ci      } else {
6501cb0ef41Sopenharmony_ci        this[kWriteToOutput](c);
6511cb0ef41Sopenharmony_ci      }
6521cb0ef41Sopenharmony_ci    }
6531cb0ef41Sopenharmony_ci  }
6541cb0ef41Sopenharmony_ci
6551cb0ef41Sopenharmony_ci  async [kTabComplete](lastKeypressWasTab) {
6561cb0ef41Sopenharmony_ci    this.pause();
6571cb0ef41Sopenharmony_ci    const string = StringPrototypeSlice(this.line, 0, this.cursor);
6581cb0ef41Sopenharmony_ci    let value;
6591cb0ef41Sopenharmony_ci    try {
6601cb0ef41Sopenharmony_ci      value = await this.completer(string);
6611cb0ef41Sopenharmony_ci    } catch (err) {
6621cb0ef41Sopenharmony_ci      this[kWriteToOutput](`Tab completion error: ${inspect(err)}`);
6631cb0ef41Sopenharmony_ci      return;
6641cb0ef41Sopenharmony_ci    } finally {
6651cb0ef41Sopenharmony_ci      this.resume();
6661cb0ef41Sopenharmony_ci    }
6671cb0ef41Sopenharmony_ci    this[kTabCompleter](lastKeypressWasTab, value);
6681cb0ef41Sopenharmony_ci  }
6691cb0ef41Sopenharmony_ci
6701cb0ef41Sopenharmony_ci  [kTabCompleter](lastKeypressWasTab, { 0: completions, 1: completeOn }) {
6711cb0ef41Sopenharmony_ci    // Result and the text that was completed.
6721cb0ef41Sopenharmony_ci
6731cb0ef41Sopenharmony_ci    if (!completions || completions.length === 0) {
6741cb0ef41Sopenharmony_ci      return;
6751cb0ef41Sopenharmony_ci    }
6761cb0ef41Sopenharmony_ci
6771cb0ef41Sopenharmony_ci    // If there is a common prefix to all matches, then apply that portion.
6781cb0ef41Sopenharmony_ci    const prefix = commonPrefix(
6791cb0ef41Sopenharmony_ci      ArrayPrototypeFilter(completions, (e) => e !== ''),
6801cb0ef41Sopenharmony_ci    );
6811cb0ef41Sopenharmony_ci    if (StringPrototypeStartsWith(prefix, completeOn) &&
6821cb0ef41Sopenharmony_ci        prefix.length > completeOn.length) {
6831cb0ef41Sopenharmony_ci      this[kInsertString](StringPrototypeSlice(prefix, completeOn.length));
6841cb0ef41Sopenharmony_ci      return;
6851cb0ef41Sopenharmony_ci    } else if (!StringPrototypeStartsWith(completeOn, prefix)) {
6861cb0ef41Sopenharmony_ci      this.line = StringPrototypeSlice(this.line,
6871cb0ef41Sopenharmony_ci                                       0,
6881cb0ef41Sopenharmony_ci                                       this.cursor - completeOn.length) +
6891cb0ef41Sopenharmony_ci                  prefix +
6901cb0ef41Sopenharmony_ci                  StringPrototypeSlice(this.line,
6911cb0ef41Sopenharmony_ci                                       this.cursor,
6921cb0ef41Sopenharmony_ci                                       this.line.length);
6931cb0ef41Sopenharmony_ci      this.cursor = this.cursor - completeOn.length + prefix.length;
6941cb0ef41Sopenharmony_ci      this._refreshLine();
6951cb0ef41Sopenharmony_ci      return;
6961cb0ef41Sopenharmony_ci    }
6971cb0ef41Sopenharmony_ci
6981cb0ef41Sopenharmony_ci    if (!lastKeypressWasTab) {
6991cb0ef41Sopenharmony_ci      return;
7001cb0ef41Sopenharmony_ci    }
7011cb0ef41Sopenharmony_ci
7021cb0ef41Sopenharmony_ci    this[kBeforeEdit](this.line, this.cursor);
7031cb0ef41Sopenharmony_ci
7041cb0ef41Sopenharmony_ci    // Apply/show completions.
7051cb0ef41Sopenharmony_ci    const completionsWidth = ArrayPrototypeMap(completions, (e) =>
7061cb0ef41Sopenharmony_ci      getStringWidth(e),
7071cb0ef41Sopenharmony_ci    );
7081cb0ef41Sopenharmony_ci    const width = MathMaxApply(completionsWidth) + 2; // 2 space padding
7091cb0ef41Sopenharmony_ci    let maxColumns = MathFloor(this.columns / width) || 1;
7101cb0ef41Sopenharmony_ci    if (maxColumns === Infinity) {
7111cb0ef41Sopenharmony_ci      maxColumns = 1;
7121cb0ef41Sopenharmony_ci    }
7131cb0ef41Sopenharmony_ci    let output = '\r\n';
7141cb0ef41Sopenharmony_ci    let lineIndex = 0;
7151cb0ef41Sopenharmony_ci    let whitespace = 0;
7161cb0ef41Sopenharmony_ci    for (let i = 0; i < completions.length; i++) {
7171cb0ef41Sopenharmony_ci      const completion = completions[i];
7181cb0ef41Sopenharmony_ci      if (completion === '' || lineIndex === maxColumns) {
7191cb0ef41Sopenharmony_ci        output += '\r\n';
7201cb0ef41Sopenharmony_ci        lineIndex = 0;
7211cb0ef41Sopenharmony_ci        whitespace = 0;
7221cb0ef41Sopenharmony_ci      } else {
7231cb0ef41Sopenharmony_ci        output += StringPrototypeRepeat(' ', whitespace);
7241cb0ef41Sopenharmony_ci      }
7251cb0ef41Sopenharmony_ci      if (completion !== '') {
7261cb0ef41Sopenharmony_ci        output += completion;
7271cb0ef41Sopenharmony_ci        whitespace = width - completionsWidth[i];
7281cb0ef41Sopenharmony_ci        lineIndex++;
7291cb0ef41Sopenharmony_ci      } else {
7301cb0ef41Sopenharmony_ci        output += '\r\n';
7311cb0ef41Sopenharmony_ci      }
7321cb0ef41Sopenharmony_ci    }
7331cb0ef41Sopenharmony_ci    if (lineIndex !== 0) {
7341cb0ef41Sopenharmony_ci      output += '\r\n\r\n';
7351cb0ef41Sopenharmony_ci    }
7361cb0ef41Sopenharmony_ci    this[kWriteToOutput](output);
7371cb0ef41Sopenharmony_ci    this[kRefreshLine]();
7381cb0ef41Sopenharmony_ci  }
7391cb0ef41Sopenharmony_ci
7401cb0ef41Sopenharmony_ci  [kWordLeft]() {
7411cb0ef41Sopenharmony_ci    if (this.cursor > 0) {
7421cb0ef41Sopenharmony_ci      // Reverse the string and match a word near beginning
7431cb0ef41Sopenharmony_ci      // to avoid quadratic time complexity
7441cb0ef41Sopenharmony_ci      const leading = StringPrototypeSlice(this.line, 0, this.cursor);
7451cb0ef41Sopenharmony_ci      const reversed = ArrayPrototypeJoin(
7461cb0ef41Sopenharmony_ci        ArrayPrototypeReverse(ArrayFrom(leading)),
7471cb0ef41Sopenharmony_ci        '',
7481cb0ef41Sopenharmony_ci      );
7491cb0ef41Sopenharmony_ci      const match = RegExpPrototypeExec(/^\s*(?:[^\w\s]+|\w+)?/, reversed);
7501cb0ef41Sopenharmony_ci      this[kMoveCursor](-match[0].length);
7511cb0ef41Sopenharmony_ci    }
7521cb0ef41Sopenharmony_ci  }
7531cb0ef41Sopenharmony_ci
7541cb0ef41Sopenharmony_ci  [kWordRight]() {
7551cb0ef41Sopenharmony_ci    if (this.cursor < this.line.length) {
7561cb0ef41Sopenharmony_ci      const trailing = StringPrototypeSlice(this.line, this.cursor);
7571cb0ef41Sopenharmony_ci      const match = RegExpPrototypeExec(/^(?:\s+|[^\w\s]+|\w+)\s*/, trailing);
7581cb0ef41Sopenharmony_ci      this[kMoveCursor](match[0].length);
7591cb0ef41Sopenharmony_ci    }
7601cb0ef41Sopenharmony_ci  }
7611cb0ef41Sopenharmony_ci
7621cb0ef41Sopenharmony_ci  [kDeleteLeft]() {
7631cb0ef41Sopenharmony_ci    if (this.cursor > 0 && this.line.length > 0) {
7641cb0ef41Sopenharmony_ci      this[kBeforeEdit](this.line, this.cursor);
7651cb0ef41Sopenharmony_ci      // The number of UTF-16 units comprising the character to the left
7661cb0ef41Sopenharmony_ci      const charSize = charLengthLeft(this.line, this.cursor);
7671cb0ef41Sopenharmony_ci      this.line =
7681cb0ef41Sopenharmony_ci        StringPrototypeSlice(this.line, 0, this.cursor - charSize) +
7691cb0ef41Sopenharmony_ci        StringPrototypeSlice(this.line, this.cursor, this.line.length);
7701cb0ef41Sopenharmony_ci
7711cb0ef41Sopenharmony_ci      this.cursor -= charSize;
7721cb0ef41Sopenharmony_ci      this[kRefreshLine]();
7731cb0ef41Sopenharmony_ci    }
7741cb0ef41Sopenharmony_ci  }
7751cb0ef41Sopenharmony_ci
7761cb0ef41Sopenharmony_ci  [kDeleteRight]() {
7771cb0ef41Sopenharmony_ci    if (this.cursor < this.line.length) {
7781cb0ef41Sopenharmony_ci      this[kBeforeEdit](this.line, this.cursor);
7791cb0ef41Sopenharmony_ci      // The number of UTF-16 units comprising the character to the left
7801cb0ef41Sopenharmony_ci      const charSize = charLengthAt(this.line, this.cursor);
7811cb0ef41Sopenharmony_ci      this.line =
7821cb0ef41Sopenharmony_ci        StringPrototypeSlice(this.line, 0, this.cursor) +
7831cb0ef41Sopenharmony_ci        StringPrototypeSlice(
7841cb0ef41Sopenharmony_ci          this.line,
7851cb0ef41Sopenharmony_ci          this.cursor + charSize,
7861cb0ef41Sopenharmony_ci          this.line.length,
7871cb0ef41Sopenharmony_ci        );
7881cb0ef41Sopenharmony_ci      this[kRefreshLine]();
7891cb0ef41Sopenharmony_ci    }
7901cb0ef41Sopenharmony_ci  }
7911cb0ef41Sopenharmony_ci
7921cb0ef41Sopenharmony_ci  [kDeleteWordLeft]() {
7931cb0ef41Sopenharmony_ci    if (this.cursor > 0) {
7941cb0ef41Sopenharmony_ci      this[kBeforeEdit](this.line, this.cursor);
7951cb0ef41Sopenharmony_ci      // Reverse the string and match a word near beginning
7961cb0ef41Sopenharmony_ci      // to avoid quadratic time complexity
7971cb0ef41Sopenharmony_ci      let leading = StringPrototypeSlice(this.line, 0, this.cursor);
7981cb0ef41Sopenharmony_ci      const reversed = ArrayPrototypeJoin(
7991cb0ef41Sopenharmony_ci        ArrayPrototypeReverse(ArrayFrom(leading)),
8001cb0ef41Sopenharmony_ci        '',
8011cb0ef41Sopenharmony_ci      );
8021cb0ef41Sopenharmony_ci      const match = RegExpPrototypeExec(/^\s*(?:[^\w\s]+|\w+)?/, reversed);
8031cb0ef41Sopenharmony_ci      leading = StringPrototypeSlice(
8041cb0ef41Sopenharmony_ci        leading,
8051cb0ef41Sopenharmony_ci        0,
8061cb0ef41Sopenharmony_ci        leading.length - match[0].length,
8071cb0ef41Sopenharmony_ci      );
8081cb0ef41Sopenharmony_ci      this.line =
8091cb0ef41Sopenharmony_ci        leading +
8101cb0ef41Sopenharmony_ci        StringPrototypeSlice(this.line, this.cursor, this.line.length);
8111cb0ef41Sopenharmony_ci      this.cursor = leading.length;
8121cb0ef41Sopenharmony_ci      this[kRefreshLine]();
8131cb0ef41Sopenharmony_ci    }
8141cb0ef41Sopenharmony_ci  }
8151cb0ef41Sopenharmony_ci
8161cb0ef41Sopenharmony_ci  [kDeleteWordRight]() {
8171cb0ef41Sopenharmony_ci    if (this.cursor < this.line.length) {
8181cb0ef41Sopenharmony_ci      this[kBeforeEdit](this.line, this.cursor);
8191cb0ef41Sopenharmony_ci      const trailing = StringPrototypeSlice(this.line, this.cursor);
8201cb0ef41Sopenharmony_ci      const match = RegExpPrototypeExec(/^(?:\s+|\W+|\w+)\s*/, trailing);
8211cb0ef41Sopenharmony_ci      this.line =
8221cb0ef41Sopenharmony_ci        StringPrototypeSlice(this.line, 0, this.cursor) +
8231cb0ef41Sopenharmony_ci        StringPrototypeSlice(trailing, match[0].length);
8241cb0ef41Sopenharmony_ci      this[kRefreshLine]();
8251cb0ef41Sopenharmony_ci    }
8261cb0ef41Sopenharmony_ci  }
8271cb0ef41Sopenharmony_ci
8281cb0ef41Sopenharmony_ci  [kDeleteLineLeft]() {
8291cb0ef41Sopenharmony_ci    this[kBeforeEdit](this.line, this.cursor);
8301cb0ef41Sopenharmony_ci    const del = StringPrototypeSlice(this.line, 0, this.cursor);
8311cb0ef41Sopenharmony_ci    this.line = StringPrototypeSlice(this.line, this.cursor);
8321cb0ef41Sopenharmony_ci    this.cursor = 0;
8331cb0ef41Sopenharmony_ci    this[kPushToKillRing](del);
8341cb0ef41Sopenharmony_ci    this[kRefreshLine]();
8351cb0ef41Sopenharmony_ci  }
8361cb0ef41Sopenharmony_ci
8371cb0ef41Sopenharmony_ci  [kDeleteLineRight]() {
8381cb0ef41Sopenharmony_ci    this[kBeforeEdit](this.line, this.cursor);
8391cb0ef41Sopenharmony_ci    const del = StringPrototypeSlice(this.line, this.cursor);
8401cb0ef41Sopenharmony_ci    this.line = StringPrototypeSlice(this.line, 0, this.cursor);
8411cb0ef41Sopenharmony_ci    this[kPushToKillRing](del);
8421cb0ef41Sopenharmony_ci    this[kRefreshLine]();
8431cb0ef41Sopenharmony_ci  }
8441cb0ef41Sopenharmony_ci
8451cb0ef41Sopenharmony_ci  [kPushToKillRing](del) {
8461cb0ef41Sopenharmony_ci    if (!del || del === this[kKillRing][0]) return;
8471cb0ef41Sopenharmony_ci    ArrayPrototypeUnshift(this[kKillRing], del);
8481cb0ef41Sopenharmony_ci    this[kKillRingCursor] = 0;
8491cb0ef41Sopenharmony_ci    while (this[kKillRing].length > kMaxLengthOfKillRing)
8501cb0ef41Sopenharmony_ci      ArrayPrototypePop(this[kKillRing]);
8511cb0ef41Sopenharmony_ci  }
8521cb0ef41Sopenharmony_ci
8531cb0ef41Sopenharmony_ci  [kYank]() {
8541cb0ef41Sopenharmony_ci    if (this[kKillRing].length > 0) {
8551cb0ef41Sopenharmony_ci      this[kYanking] = true;
8561cb0ef41Sopenharmony_ci      this[kInsertString](this[kKillRing][this[kKillRingCursor]]);
8571cb0ef41Sopenharmony_ci    }
8581cb0ef41Sopenharmony_ci  }
8591cb0ef41Sopenharmony_ci
8601cb0ef41Sopenharmony_ci  [kYankPop]() {
8611cb0ef41Sopenharmony_ci    if (!this[kYanking]) {
8621cb0ef41Sopenharmony_ci      return;
8631cb0ef41Sopenharmony_ci    }
8641cb0ef41Sopenharmony_ci    if (this[kKillRing].length > 1) {
8651cb0ef41Sopenharmony_ci      const lastYank = this[kKillRing][this[kKillRingCursor]];
8661cb0ef41Sopenharmony_ci      this[kKillRingCursor]++;
8671cb0ef41Sopenharmony_ci      if (this[kKillRingCursor] >= this[kKillRing].length) {
8681cb0ef41Sopenharmony_ci        this[kKillRingCursor] = 0;
8691cb0ef41Sopenharmony_ci      }
8701cb0ef41Sopenharmony_ci      const currentYank = this[kKillRing][this[kKillRingCursor]];
8711cb0ef41Sopenharmony_ci      const head =
8721cb0ef41Sopenharmony_ci            StringPrototypeSlice(this.line, 0, this.cursor - lastYank.length);
8731cb0ef41Sopenharmony_ci      const tail =
8741cb0ef41Sopenharmony_ci            StringPrototypeSlice(this.line, this.cursor);
8751cb0ef41Sopenharmony_ci      this.line = head + currentYank + tail;
8761cb0ef41Sopenharmony_ci      this.cursor = head.length + currentYank.length;
8771cb0ef41Sopenharmony_ci      this[kRefreshLine]();
8781cb0ef41Sopenharmony_ci    }
8791cb0ef41Sopenharmony_ci  }
8801cb0ef41Sopenharmony_ci
8811cb0ef41Sopenharmony_ci  clearLine() {
8821cb0ef41Sopenharmony_ci    this[kMoveCursor](+Infinity);
8831cb0ef41Sopenharmony_ci    this[kWriteToOutput]('\r\n');
8841cb0ef41Sopenharmony_ci    this.line = '';
8851cb0ef41Sopenharmony_ci    this.cursor = 0;
8861cb0ef41Sopenharmony_ci    this.prevRows = 0;
8871cb0ef41Sopenharmony_ci  }
8881cb0ef41Sopenharmony_ci
8891cb0ef41Sopenharmony_ci  [kLine]() {
8901cb0ef41Sopenharmony_ci    const line = this[kAddHistory]();
8911cb0ef41Sopenharmony_ci    this[kUndoStack] = [];
8921cb0ef41Sopenharmony_ci    this[kRedoStack] = [];
8931cb0ef41Sopenharmony_ci    this.clearLine();
8941cb0ef41Sopenharmony_ci    this[kOnLine](line);
8951cb0ef41Sopenharmony_ci  }
8961cb0ef41Sopenharmony_ci
8971cb0ef41Sopenharmony_ci  [kPushToUndoStack](text, cursor) {
8981cb0ef41Sopenharmony_ci    if (ArrayPrototypePush(this[kUndoStack], { text, cursor }) >
8991cb0ef41Sopenharmony_ci        kMaxUndoRedoStackSize) {
9001cb0ef41Sopenharmony_ci      ArrayPrototypeShift(this[kUndoStack]);
9011cb0ef41Sopenharmony_ci    }
9021cb0ef41Sopenharmony_ci  }
9031cb0ef41Sopenharmony_ci
9041cb0ef41Sopenharmony_ci  [kUndo]() {
9051cb0ef41Sopenharmony_ci    if (this[kUndoStack].length <= 0) return;
9061cb0ef41Sopenharmony_ci
9071cb0ef41Sopenharmony_ci    ArrayPrototypePush(
9081cb0ef41Sopenharmony_ci      this[kRedoStack],
9091cb0ef41Sopenharmony_ci      { text: this.line, cursor: this.cursor },
9101cb0ef41Sopenharmony_ci    );
9111cb0ef41Sopenharmony_ci
9121cb0ef41Sopenharmony_ci    const entry = ArrayPrototypePop(this[kUndoStack]);
9131cb0ef41Sopenharmony_ci    this.line = entry.text;
9141cb0ef41Sopenharmony_ci    this.cursor = entry.cursor;
9151cb0ef41Sopenharmony_ci
9161cb0ef41Sopenharmony_ci    this[kRefreshLine]();
9171cb0ef41Sopenharmony_ci  }
9181cb0ef41Sopenharmony_ci
9191cb0ef41Sopenharmony_ci  [kRedo]() {
9201cb0ef41Sopenharmony_ci    if (this[kRedoStack].length <= 0) return;
9211cb0ef41Sopenharmony_ci
9221cb0ef41Sopenharmony_ci    ArrayPrototypePush(
9231cb0ef41Sopenharmony_ci      this[kUndoStack],
9241cb0ef41Sopenharmony_ci      { text: this.line, cursor: this.cursor },
9251cb0ef41Sopenharmony_ci    );
9261cb0ef41Sopenharmony_ci
9271cb0ef41Sopenharmony_ci    const entry = ArrayPrototypePop(this[kRedoStack]);
9281cb0ef41Sopenharmony_ci    this.line = entry.text;
9291cb0ef41Sopenharmony_ci    this.cursor = entry.cursor;
9301cb0ef41Sopenharmony_ci
9311cb0ef41Sopenharmony_ci    this[kRefreshLine]();
9321cb0ef41Sopenharmony_ci  }
9331cb0ef41Sopenharmony_ci
9341cb0ef41Sopenharmony_ci  // TODO(BridgeAR): Add underscores to the search part and a red background in
9351cb0ef41Sopenharmony_ci  // case no match is found. This should only be the visual part and not the
9361cb0ef41Sopenharmony_ci  // actual line content!
9371cb0ef41Sopenharmony_ci  // TODO(BridgeAR): In case the substring based search is active and the end is
9381cb0ef41Sopenharmony_ci  // reached, show a comment how to search the history as before. E.g., using
9391cb0ef41Sopenharmony_ci  // <ctrl> + N. Only show this after two/three UPs or DOWNs, not on the first
9401cb0ef41Sopenharmony_ci  // one.
9411cb0ef41Sopenharmony_ci  [kHistoryNext]() {
9421cb0ef41Sopenharmony_ci    if (this.historyIndex >= 0) {
9431cb0ef41Sopenharmony_ci      this[kBeforeEdit](this.line, this.cursor);
9441cb0ef41Sopenharmony_ci      const search = this[kSubstringSearch] || '';
9451cb0ef41Sopenharmony_ci      let index = this.historyIndex - 1;
9461cb0ef41Sopenharmony_ci      while (
9471cb0ef41Sopenharmony_ci        index >= 0 &&
9481cb0ef41Sopenharmony_ci        (!StringPrototypeStartsWith(this.history[index], search) ||
9491cb0ef41Sopenharmony_ci          this.line === this.history[index])
9501cb0ef41Sopenharmony_ci      ) {
9511cb0ef41Sopenharmony_ci        index--;
9521cb0ef41Sopenharmony_ci      }
9531cb0ef41Sopenharmony_ci      if (index === -1) {
9541cb0ef41Sopenharmony_ci        this.line = search;
9551cb0ef41Sopenharmony_ci      } else {
9561cb0ef41Sopenharmony_ci        this.line = this.history[index];
9571cb0ef41Sopenharmony_ci      }
9581cb0ef41Sopenharmony_ci      this.historyIndex = index;
9591cb0ef41Sopenharmony_ci      this.cursor = this.line.length; // Set cursor to end of line.
9601cb0ef41Sopenharmony_ci      this[kRefreshLine]();
9611cb0ef41Sopenharmony_ci    }
9621cb0ef41Sopenharmony_ci  }
9631cb0ef41Sopenharmony_ci
9641cb0ef41Sopenharmony_ci  [kHistoryPrev]() {
9651cb0ef41Sopenharmony_ci    if (this.historyIndex < this.history.length && this.history.length) {
9661cb0ef41Sopenharmony_ci      this[kBeforeEdit](this.line, this.cursor);
9671cb0ef41Sopenharmony_ci      const search = this[kSubstringSearch] || '';
9681cb0ef41Sopenharmony_ci      let index = this.historyIndex + 1;
9691cb0ef41Sopenharmony_ci      while (
9701cb0ef41Sopenharmony_ci        index < this.history.length &&
9711cb0ef41Sopenharmony_ci        (!StringPrototypeStartsWith(this.history[index], search) ||
9721cb0ef41Sopenharmony_ci          this.line === this.history[index])
9731cb0ef41Sopenharmony_ci      ) {
9741cb0ef41Sopenharmony_ci        index++;
9751cb0ef41Sopenharmony_ci      }
9761cb0ef41Sopenharmony_ci      if (index === this.history.length) {
9771cb0ef41Sopenharmony_ci        this.line = search;
9781cb0ef41Sopenharmony_ci      } else {
9791cb0ef41Sopenharmony_ci        this.line = this.history[index];
9801cb0ef41Sopenharmony_ci      }
9811cb0ef41Sopenharmony_ci      this.historyIndex = index;
9821cb0ef41Sopenharmony_ci      this.cursor = this.line.length; // Set cursor to end of line.
9831cb0ef41Sopenharmony_ci      this[kRefreshLine]();
9841cb0ef41Sopenharmony_ci    }
9851cb0ef41Sopenharmony_ci  }
9861cb0ef41Sopenharmony_ci
9871cb0ef41Sopenharmony_ci  // Returns the last character's display position of the given string
9881cb0ef41Sopenharmony_ci  [kGetDisplayPos](str) {
9891cb0ef41Sopenharmony_ci    let offset = 0;
9901cb0ef41Sopenharmony_ci    const col = this.columns;
9911cb0ef41Sopenharmony_ci    let rows = 0;
9921cb0ef41Sopenharmony_ci    str = stripVTControlCharacters(str);
9931cb0ef41Sopenharmony_ci    for (const char of new SafeStringIterator(str)) {
9941cb0ef41Sopenharmony_ci      if (char === '\n') {
9951cb0ef41Sopenharmony_ci        // Rows must be incremented by 1 even if offset = 0 or col = +Infinity.
9961cb0ef41Sopenharmony_ci        rows += MathCeil(offset / col) || 1;
9971cb0ef41Sopenharmony_ci        offset = 0;
9981cb0ef41Sopenharmony_ci        continue;
9991cb0ef41Sopenharmony_ci      }
10001cb0ef41Sopenharmony_ci      // Tabs must be aligned by an offset of the tab size.
10011cb0ef41Sopenharmony_ci      if (char === '\t') {
10021cb0ef41Sopenharmony_ci        offset += this.tabSize - (offset % this.tabSize);
10031cb0ef41Sopenharmony_ci        continue;
10041cb0ef41Sopenharmony_ci      }
10051cb0ef41Sopenharmony_ci      const width = getStringWidth(char, false /* stripVTControlCharacters */);
10061cb0ef41Sopenharmony_ci      if (width === 0 || width === 1) {
10071cb0ef41Sopenharmony_ci        offset += width;
10081cb0ef41Sopenharmony_ci      } else {
10091cb0ef41Sopenharmony_ci        // width === 2
10101cb0ef41Sopenharmony_ci        if ((offset + 1) % col === 0) {
10111cb0ef41Sopenharmony_ci          offset++;
10121cb0ef41Sopenharmony_ci        }
10131cb0ef41Sopenharmony_ci        offset += 2;
10141cb0ef41Sopenharmony_ci      }
10151cb0ef41Sopenharmony_ci    }
10161cb0ef41Sopenharmony_ci    const cols = offset % col;
10171cb0ef41Sopenharmony_ci    rows += (offset - cols) / col;
10181cb0ef41Sopenharmony_ci    return { cols, rows };
10191cb0ef41Sopenharmony_ci  }
10201cb0ef41Sopenharmony_ci
10211cb0ef41Sopenharmony_ci  /**
10221cb0ef41Sopenharmony_ci   * Returns the real position of the cursor in relation
10231cb0ef41Sopenharmony_ci   * to the input prompt + string.
10241cb0ef41Sopenharmony_ci   * @returns {{
10251cb0ef41Sopenharmony_ci   *   rows: number;
10261cb0ef41Sopenharmony_ci   *   cols: number;
10271cb0ef41Sopenharmony_ci   *   }}
10281cb0ef41Sopenharmony_ci   */
10291cb0ef41Sopenharmony_ci  getCursorPos() {
10301cb0ef41Sopenharmony_ci    const strBeforeCursor =
10311cb0ef41Sopenharmony_ci      this[kPrompt] + StringPrototypeSlice(this.line, 0, this.cursor);
10321cb0ef41Sopenharmony_ci    return this[kGetDisplayPos](strBeforeCursor);
10331cb0ef41Sopenharmony_ci  }
10341cb0ef41Sopenharmony_ci
10351cb0ef41Sopenharmony_ci  // This function moves cursor dx places to the right
10361cb0ef41Sopenharmony_ci  // (-dx for left) and refreshes the line if it is needed.
10371cb0ef41Sopenharmony_ci  [kMoveCursor](dx) {
10381cb0ef41Sopenharmony_ci    if (dx === 0) {
10391cb0ef41Sopenharmony_ci      return;
10401cb0ef41Sopenharmony_ci    }
10411cb0ef41Sopenharmony_ci    const oldPos = this.getCursorPos();
10421cb0ef41Sopenharmony_ci    this.cursor += dx;
10431cb0ef41Sopenharmony_ci
10441cb0ef41Sopenharmony_ci    // Bounds check
10451cb0ef41Sopenharmony_ci    if (this.cursor < 0) {
10461cb0ef41Sopenharmony_ci      this.cursor = 0;
10471cb0ef41Sopenharmony_ci    } else if (this.cursor > this.line.length) {
10481cb0ef41Sopenharmony_ci      this.cursor = this.line.length;
10491cb0ef41Sopenharmony_ci    }
10501cb0ef41Sopenharmony_ci
10511cb0ef41Sopenharmony_ci    const newPos = this.getCursorPos();
10521cb0ef41Sopenharmony_ci
10531cb0ef41Sopenharmony_ci    // Check if cursor stayed on the line.
10541cb0ef41Sopenharmony_ci    if (oldPos.rows === newPos.rows) {
10551cb0ef41Sopenharmony_ci      const diffWidth = newPos.cols - oldPos.cols;
10561cb0ef41Sopenharmony_ci      moveCursor(this.output, diffWidth, 0);
10571cb0ef41Sopenharmony_ci    } else {
10581cb0ef41Sopenharmony_ci      this[kRefreshLine]();
10591cb0ef41Sopenharmony_ci    }
10601cb0ef41Sopenharmony_ci  }
10611cb0ef41Sopenharmony_ci
10621cb0ef41Sopenharmony_ci  // Handle a write from the tty
10631cb0ef41Sopenharmony_ci  [kTtyWrite](s, key) {
10641cb0ef41Sopenharmony_ci    const previousKey = this[kPreviousKey];
10651cb0ef41Sopenharmony_ci    key = key || kEmptyObject;
10661cb0ef41Sopenharmony_ci    this[kPreviousKey] = key;
10671cb0ef41Sopenharmony_ci
10681cb0ef41Sopenharmony_ci    if (!key.meta || key.name !== 'y') {
10691cb0ef41Sopenharmony_ci      // Reset yanking state unless we are doing yank pop.
10701cb0ef41Sopenharmony_ci      this[kYanking] = false;
10711cb0ef41Sopenharmony_ci    }
10721cb0ef41Sopenharmony_ci
10731cb0ef41Sopenharmony_ci    // Activate or deactivate substring search.
10741cb0ef41Sopenharmony_ci    if (
10751cb0ef41Sopenharmony_ci      (key.name === 'up' || key.name === 'down') &&
10761cb0ef41Sopenharmony_ci      !key.ctrl &&
10771cb0ef41Sopenharmony_ci      !key.meta &&
10781cb0ef41Sopenharmony_ci      !key.shift
10791cb0ef41Sopenharmony_ci    ) {
10801cb0ef41Sopenharmony_ci      if (this[kSubstringSearch] === null) {
10811cb0ef41Sopenharmony_ci        this[kSubstringSearch] = StringPrototypeSlice(
10821cb0ef41Sopenharmony_ci          this.line,
10831cb0ef41Sopenharmony_ci          0,
10841cb0ef41Sopenharmony_ci          this.cursor,
10851cb0ef41Sopenharmony_ci        );
10861cb0ef41Sopenharmony_ci      }
10871cb0ef41Sopenharmony_ci    } else if (this[kSubstringSearch] !== null) {
10881cb0ef41Sopenharmony_ci      this[kSubstringSearch] = null;
10891cb0ef41Sopenharmony_ci      // Reset the index in case there's no match.
10901cb0ef41Sopenharmony_ci      if (this.history.length === this.historyIndex) {
10911cb0ef41Sopenharmony_ci        this.historyIndex = -1;
10921cb0ef41Sopenharmony_ci      }
10931cb0ef41Sopenharmony_ci    }
10941cb0ef41Sopenharmony_ci
10951cb0ef41Sopenharmony_ci    // Undo & Redo
10961cb0ef41Sopenharmony_ci    if (typeof key.sequence === 'string') {
10971cb0ef41Sopenharmony_ci      switch (StringPrototypeCodePointAt(key.sequence, 0)) {
10981cb0ef41Sopenharmony_ci        case 0x1f:
10991cb0ef41Sopenharmony_ci          this[kUndo]();
11001cb0ef41Sopenharmony_ci          return;
11011cb0ef41Sopenharmony_ci        case 0x1e:
11021cb0ef41Sopenharmony_ci          this[kRedo]();
11031cb0ef41Sopenharmony_ci          return;
11041cb0ef41Sopenharmony_ci        default:
11051cb0ef41Sopenharmony_ci          break;
11061cb0ef41Sopenharmony_ci      }
11071cb0ef41Sopenharmony_ci    }
11081cb0ef41Sopenharmony_ci
11091cb0ef41Sopenharmony_ci    // Ignore escape key, fixes
11101cb0ef41Sopenharmony_ci    // https://github.com/nodejs/node-v0.x-archive/issues/2876.
11111cb0ef41Sopenharmony_ci    if (key.name === 'escape') return;
11121cb0ef41Sopenharmony_ci
11131cb0ef41Sopenharmony_ci    if (key.ctrl && key.shift) {
11141cb0ef41Sopenharmony_ci      /* Control and shift pressed */
11151cb0ef41Sopenharmony_ci      switch (key.name) {
11161cb0ef41Sopenharmony_ci        // TODO(BridgeAR): The transmitted escape sequence is `\b` and that is
11171cb0ef41Sopenharmony_ci        // identical to <ctrl>-h. It should have a unique escape sequence.
11181cb0ef41Sopenharmony_ci        case 'backspace':
11191cb0ef41Sopenharmony_ci          this[kDeleteLineLeft]();
11201cb0ef41Sopenharmony_ci          break;
11211cb0ef41Sopenharmony_ci
11221cb0ef41Sopenharmony_ci        case 'delete':
11231cb0ef41Sopenharmony_ci          this[kDeleteLineRight]();
11241cb0ef41Sopenharmony_ci          break;
11251cb0ef41Sopenharmony_ci      }
11261cb0ef41Sopenharmony_ci    } else if (key.ctrl) {
11271cb0ef41Sopenharmony_ci      /* Control key pressed */
11281cb0ef41Sopenharmony_ci
11291cb0ef41Sopenharmony_ci      switch (key.name) {
11301cb0ef41Sopenharmony_ci        case 'c':
11311cb0ef41Sopenharmony_ci          if (this.listenerCount('SIGINT') > 0) {
11321cb0ef41Sopenharmony_ci            this.emit('SIGINT');
11331cb0ef41Sopenharmony_ci          } else {
11341cb0ef41Sopenharmony_ci            // This readline instance is finished
11351cb0ef41Sopenharmony_ci            this.close();
11361cb0ef41Sopenharmony_ci          }
11371cb0ef41Sopenharmony_ci          break;
11381cb0ef41Sopenharmony_ci
11391cb0ef41Sopenharmony_ci        case 'h': // delete left
11401cb0ef41Sopenharmony_ci          this[kDeleteLeft]();
11411cb0ef41Sopenharmony_ci          break;
11421cb0ef41Sopenharmony_ci
11431cb0ef41Sopenharmony_ci        case 'd': // delete right or EOF
11441cb0ef41Sopenharmony_ci          if (this.cursor === 0 && this.line.length === 0) {
11451cb0ef41Sopenharmony_ci            // This readline instance is finished
11461cb0ef41Sopenharmony_ci            this.close();
11471cb0ef41Sopenharmony_ci          } else if (this.cursor < this.line.length) {
11481cb0ef41Sopenharmony_ci            this[kDeleteRight]();
11491cb0ef41Sopenharmony_ci          }
11501cb0ef41Sopenharmony_ci          break;
11511cb0ef41Sopenharmony_ci
11521cb0ef41Sopenharmony_ci        case 'u': // Delete from current to start of line
11531cb0ef41Sopenharmony_ci          this[kDeleteLineLeft]();
11541cb0ef41Sopenharmony_ci          break;
11551cb0ef41Sopenharmony_ci
11561cb0ef41Sopenharmony_ci        case 'k': // Delete from current to end of line
11571cb0ef41Sopenharmony_ci          this[kDeleteLineRight]();
11581cb0ef41Sopenharmony_ci          break;
11591cb0ef41Sopenharmony_ci
11601cb0ef41Sopenharmony_ci        case 'a': // Go to the start of the line
11611cb0ef41Sopenharmony_ci          this[kMoveCursor](-Infinity);
11621cb0ef41Sopenharmony_ci          break;
11631cb0ef41Sopenharmony_ci
11641cb0ef41Sopenharmony_ci        case 'e': // Go to the end of the line
11651cb0ef41Sopenharmony_ci          this[kMoveCursor](+Infinity);
11661cb0ef41Sopenharmony_ci          break;
11671cb0ef41Sopenharmony_ci
11681cb0ef41Sopenharmony_ci        case 'b': // back one character
11691cb0ef41Sopenharmony_ci          this[kMoveCursor](-charLengthLeft(this.line, this.cursor));
11701cb0ef41Sopenharmony_ci          break;
11711cb0ef41Sopenharmony_ci
11721cb0ef41Sopenharmony_ci        case 'f': // Forward one character
11731cb0ef41Sopenharmony_ci          this[kMoveCursor](+charLengthAt(this.line, this.cursor));
11741cb0ef41Sopenharmony_ci          break;
11751cb0ef41Sopenharmony_ci
11761cb0ef41Sopenharmony_ci        case 'l': // Clear the whole screen
11771cb0ef41Sopenharmony_ci          cursorTo(this.output, 0, 0);
11781cb0ef41Sopenharmony_ci          clearScreenDown(this.output);
11791cb0ef41Sopenharmony_ci          this[kRefreshLine]();
11801cb0ef41Sopenharmony_ci          break;
11811cb0ef41Sopenharmony_ci
11821cb0ef41Sopenharmony_ci        case 'n': // next history item
11831cb0ef41Sopenharmony_ci          this[kHistoryNext]();
11841cb0ef41Sopenharmony_ci          break;
11851cb0ef41Sopenharmony_ci
11861cb0ef41Sopenharmony_ci        case 'p': // Previous history item
11871cb0ef41Sopenharmony_ci          this[kHistoryPrev]();
11881cb0ef41Sopenharmony_ci          break;
11891cb0ef41Sopenharmony_ci
11901cb0ef41Sopenharmony_ci        case 'y': // Yank killed string
11911cb0ef41Sopenharmony_ci          this[kYank]();
11921cb0ef41Sopenharmony_ci          break;
11931cb0ef41Sopenharmony_ci
11941cb0ef41Sopenharmony_ci        case 'z':
11951cb0ef41Sopenharmony_ci          if (process.platform === 'win32') break;
11961cb0ef41Sopenharmony_ci          if (this.listenerCount('SIGTSTP') > 0) {
11971cb0ef41Sopenharmony_ci            this.emit('SIGTSTP');
11981cb0ef41Sopenharmony_ci          } else {
11991cb0ef41Sopenharmony_ci            process.once('SIGCONT', () => {
12001cb0ef41Sopenharmony_ci              // Don't raise events if stream has already been abandoned.
12011cb0ef41Sopenharmony_ci              if (!this.paused) {
12021cb0ef41Sopenharmony_ci                // Stream must be paused and resumed after SIGCONT to catch
12031cb0ef41Sopenharmony_ci                // SIGINT, SIGTSTP, and EOF.
12041cb0ef41Sopenharmony_ci                this.pause();
12051cb0ef41Sopenharmony_ci                this.emit('SIGCONT');
12061cb0ef41Sopenharmony_ci              }
12071cb0ef41Sopenharmony_ci              // Explicitly re-enable "raw mode" and move the cursor to
12081cb0ef41Sopenharmony_ci              // the correct position.
12091cb0ef41Sopenharmony_ci              // See https://github.com/joyent/node/issues/3295.
12101cb0ef41Sopenharmony_ci              this[kSetRawMode](true);
12111cb0ef41Sopenharmony_ci              this[kRefreshLine]();
12121cb0ef41Sopenharmony_ci            });
12131cb0ef41Sopenharmony_ci            this[kSetRawMode](false);
12141cb0ef41Sopenharmony_ci            process.kill(process.pid, 'SIGTSTP');
12151cb0ef41Sopenharmony_ci          }
12161cb0ef41Sopenharmony_ci          break;
12171cb0ef41Sopenharmony_ci
12181cb0ef41Sopenharmony_ci        case 'w': // Delete backwards to a word boundary
12191cb0ef41Sopenharmony_ci        // TODO(BridgeAR): The transmitted escape sequence is `\b` and that is
12201cb0ef41Sopenharmony_ci        // identical to <ctrl>-h. It should have a unique escape sequence.
12211cb0ef41Sopenharmony_ci        // Falls through
12221cb0ef41Sopenharmony_ci        case 'backspace':
12231cb0ef41Sopenharmony_ci          this[kDeleteWordLeft]();
12241cb0ef41Sopenharmony_ci          break;
12251cb0ef41Sopenharmony_ci
12261cb0ef41Sopenharmony_ci        case 'delete': // Delete forward to a word boundary
12271cb0ef41Sopenharmony_ci          this[kDeleteWordRight]();
12281cb0ef41Sopenharmony_ci          break;
12291cb0ef41Sopenharmony_ci
12301cb0ef41Sopenharmony_ci        case 'left':
12311cb0ef41Sopenharmony_ci          this[kWordLeft]();
12321cb0ef41Sopenharmony_ci          break;
12331cb0ef41Sopenharmony_ci
12341cb0ef41Sopenharmony_ci        case 'right':
12351cb0ef41Sopenharmony_ci          this[kWordRight]();
12361cb0ef41Sopenharmony_ci          break;
12371cb0ef41Sopenharmony_ci      }
12381cb0ef41Sopenharmony_ci    } else if (key.meta) {
12391cb0ef41Sopenharmony_ci      /* Meta key pressed */
12401cb0ef41Sopenharmony_ci
12411cb0ef41Sopenharmony_ci      switch (key.name) {
12421cb0ef41Sopenharmony_ci        case 'b': // backward word
12431cb0ef41Sopenharmony_ci          this[kWordLeft]();
12441cb0ef41Sopenharmony_ci          break;
12451cb0ef41Sopenharmony_ci
12461cb0ef41Sopenharmony_ci        case 'f': // forward word
12471cb0ef41Sopenharmony_ci          this[kWordRight]();
12481cb0ef41Sopenharmony_ci          break;
12491cb0ef41Sopenharmony_ci
12501cb0ef41Sopenharmony_ci        case 'd': // delete forward word
12511cb0ef41Sopenharmony_ci        case 'delete':
12521cb0ef41Sopenharmony_ci          this[kDeleteWordRight]();
12531cb0ef41Sopenharmony_ci          break;
12541cb0ef41Sopenharmony_ci
12551cb0ef41Sopenharmony_ci        case 'backspace': // Delete backwards to a word boundary
12561cb0ef41Sopenharmony_ci          this[kDeleteWordLeft]();
12571cb0ef41Sopenharmony_ci          break;
12581cb0ef41Sopenharmony_ci
12591cb0ef41Sopenharmony_ci        case 'y': // Doing yank pop
12601cb0ef41Sopenharmony_ci          this[kYankPop]();
12611cb0ef41Sopenharmony_ci          break;
12621cb0ef41Sopenharmony_ci      }
12631cb0ef41Sopenharmony_ci    } else {
12641cb0ef41Sopenharmony_ci      /* No modifier keys used */
12651cb0ef41Sopenharmony_ci
12661cb0ef41Sopenharmony_ci      // \r bookkeeping is only relevant if a \n comes right after.
12671cb0ef41Sopenharmony_ci      if (this[kSawReturnAt] && key.name !== 'enter') this[kSawReturnAt] = 0;
12681cb0ef41Sopenharmony_ci
12691cb0ef41Sopenharmony_ci      switch (key.name) {
12701cb0ef41Sopenharmony_ci        case 'return': // Carriage return, i.e. \r
12711cb0ef41Sopenharmony_ci          this[kSawReturnAt] = DateNow();
12721cb0ef41Sopenharmony_ci          this[kLine]();
12731cb0ef41Sopenharmony_ci          break;
12741cb0ef41Sopenharmony_ci
12751cb0ef41Sopenharmony_ci        case 'enter':
12761cb0ef41Sopenharmony_ci          // When key interval > crlfDelay
12771cb0ef41Sopenharmony_ci          if (
12781cb0ef41Sopenharmony_ci            this[kSawReturnAt] === 0 ||
12791cb0ef41Sopenharmony_ci            DateNow() - this[kSawReturnAt] > this.crlfDelay
12801cb0ef41Sopenharmony_ci          ) {
12811cb0ef41Sopenharmony_ci            this[kLine]();
12821cb0ef41Sopenharmony_ci          }
12831cb0ef41Sopenharmony_ci          this[kSawReturnAt] = 0;
12841cb0ef41Sopenharmony_ci          break;
12851cb0ef41Sopenharmony_ci
12861cb0ef41Sopenharmony_ci        case 'backspace':
12871cb0ef41Sopenharmony_ci          this[kDeleteLeft]();
12881cb0ef41Sopenharmony_ci          break;
12891cb0ef41Sopenharmony_ci
12901cb0ef41Sopenharmony_ci        case 'delete':
12911cb0ef41Sopenharmony_ci          this[kDeleteRight]();
12921cb0ef41Sopenharmony_ci          break;
12931cb0ef41Sopenharmony_ci
12941cb0ef41Sopenharmony_ci        case 'left':
12951cb0ef41Sopenharmony_ci          // Obtain the code point to the left
12961cb0ef41Sopenharmony_ci          this[kMoveCursor](-charLengthLeft(this.line, this.cursor));
12971cb0ef41Sopenharmony_ci          break;
12981cb0ef41Sopenharmony_ci
12991cb0ef41Sopenharmony_ci        case 'right':
13001cb0ef41Sopenharmony_ci          this[kMoveCursor](+charLengthAt(this.line, this.cursor));
13011cb0ef41Sopenharmony_ci          break;
13021cb0ef41Sopenharmony_ci
13031cb0ef41Sopenharmony_ci        case 'home':
13041cb0ef41Sopenharmony_ci          this[kMoveCursor](-Infinity);
13051cb0ef41Sopenharmony_ci          break;
13061cb0ef41Sopenharmony_ci
13071cb0ef41Sopenharmony_ci        case 'end':
13081cb0ef41Sopenharmony_ci          this[kMoveCursor](+Infinity);
13091cb0ef41Sopenharmony_ci          break;
13101cb0ef41Sopenharmony_ci
13111cb0ef41Sopenharmony_ci        case 'up':
13121cb0ef41Sopenharmony_ci          this[kHistoryPrev]();
13131cb0ef41Sopenharmony_ci          break;
13141cb0ef41Sopenharmony_ci
13151cb0ef41Sopenharmony_ci        case 'down':
13161cb0ef41Sopenharmony_ci          this[kHistoryNext]();
13171cb0ef41Sopenharmony_ci          break;
13181cb0ef41Sopenharmony_ci
13191cb0ef41Sopenharmony_ci        case 'tab':
13201cb0ef41Sopenharmony_ci          // If tab completion enabled, do that...
13211cb0ef41Sopenharmony_ci          if (
13221cb0ef41Sopenharmony_ci            typeof this.completer === 'function' &&
13231cb0ef41Sopenharmony_ci            this.isCompletionEnabled
13241cb0ef41Sopenharmony_ci          ) {
13251cb0ef41Sopenharmony_ci            const lastKeypressWasTab =
13261cb0ef41Sopenharmony_ci              previousKey && previousKey.name === 'tab';
13271cb0ef41Sopenharmony_ci            this[kTabComplete](lastKeypressWasTab);
13281cb0ef41Sopenharmony_ci            break;
13291cb0ef41Sopenharmony_ci          }
13301cb0ef41Sopenharmony_ci        // falls through
13311cb0ef41Sopenharmony_ci        default:
13321cb0ef41Sopenharmony_ci          if (typeof s === 'string' && s) {
13331cb0ef41Sopenharmony_ci            // Erase state of previous searches.
13341cb0ef41Sopenharmony_ci            lineEnding.lastIndex = 0;
13351cb0ef41Sopenharmony_ci            let nextMatch;
13361cb0ef41Sopenharmony_ci            // Keep track of the end of the last match.
13371cb0ef41Sopenharmony_ci            let lastIndex = 0;
13381cb0ef41Sopenharmony_ci            while ((nextMatch = RegExpPrototypeExec(lineEnding, s)) !== null) {
13391cb0ef41Sopenharmony_ci              this[kInsertString](StringPrototypeSlice(s, lastIndex, nextMatch.index));
13401cb0ef41Sopenharmony_ci              ({ lastIndex } = lineEnding);
13411cb0ef41Sopenharmony_ci              this[kLine]();
13421cb0ef41Sopenharmony_ci              // Restore lastIndex as the call to kLine could have mutated it.
13431cb0ef41Sopenharmony_ci              lineEnding.lastIndex = lastIndex;
13441cb0ef41Sopenharmony_ci            }
13451cb0ef41Sopenharmony_ci            // This ensures that the last line is written if it doesn't end in a newline.
13461cb0ef41Sopenharmony_ci            // Note that the last line may be the first line, in which case this still works.
13471cb0ef41Sopenharmony_ci            this[kInsertString](StringPrototypeSlice(s, lastIndex));
13481cb0ef41Sopenharmony_ci          }
13491cb0ef41Sopenharmony_ci      }
13501cb0ef41Sopenharmony_ci    }
13511cb0ef41Sopenharmony_ci  }
13521cb0ef41Sopenharmony_ci
13531cb0ef41Sopenharmony_ci  /**
13541cb0ef41Sopenharmony_ci   * Creates an `AsyncIterator` object that iterates through
13551cb0ef41Sopenharmony_ci   * each line in the input stream as a string.
13561cb0ef41Sopenharmony_ci   * @typedef {{
13571cb0ef41Sopenharmony_ci   *   [Symbol.asyncIterator]: () => InterfaceAsyncIterator,
13581cb0ef41Sopenharmony_ci   *   next: () => Promise<string>
13591cb0ef41Sopenharmony_ci   * }} InterfaceAsyncIterator
13601cb0ef41Sopenharmony_ci   * @returns {InterfaceAsyncIterator}
13611cb0ef41Sopenharmony_ci   */
13621cb0ef41Sopenharmony_ci  [SymbolAsyncIterator]() {
13631cb0ef41Sopenharmony_ci    if (this[kLineObjectStream] === undefined) {
13641cb0ef41Sopenharmony_ci      if (Readable === undefined) {
13651cb0ef41Sopenharmony_ci        Readable = require('stream').Readable;
13661cb0ef41Sopenharmony_ci      }
13671cb0ef41Sopenharmony_ci      const readable = new Readable({
13681cb0ef41Sopenharmony_ci        objectMode: true,
13691cb0ef41Sopenharmony_ci        read: () => {
13701cb0ef41Sopenharmony_ci          this.resume();
13711cb0ef41Sopenharmony_ci        },
13721cb0ef41Sopenharmony_ci        destroy: (err, cb) => {
13731cb0ef41Sopenharmony_ci          this.off('line', lineListener);
13741cb0ef41Sopenharmony_ci          this.off('close', closeListener);
13751cb0ef41Sopenharmony_ci          this.close();
13761cb0ef41Sopenharmony_ci          cb(err);
13771cb0ef41Sopenharmony_ci        },
13781cb0ef41Sopenharmony_ci      });
13791cb0ef41Sopenharmony_ci      const lineListener = (input) => {
13801cb0ef41Sopenharmony_ci        if (!readable.push(input)) {
13811cb0ef41Sopenharmony_ci          // TODO(rexagod): drain to resume flow
13821cb0ef41Sopenharmony_ci          this.pause();
13831cb0ef41Sopenharmony_ci        }
13841cb0ef41Sopenharmony_ci      };
13851cb0ef41Sopenharmony_ci      const closeListener = () => {
13861cb0ef41Sopenharmony_ci        readable.push(null);
13871cb0ef41Sopenharmony_ci      };
13881cb0ef41Sopenharmony_ci      const errorListener = (err) => {
13891cb0ef41Sopenharmony_ci        readable.destroy(err);
13901cb0ef41Sopenharmony_ci      };
13911cb0ef41Sopenharmony_ci      this.on('error', errorListener);
13921cb0ef41Sopenharmony_ci      this.on('line', lineListener);
13931cb0ef41Sopenharmony_ci      this.on('close', closeListener);
13941cb0ef41Sopenharmony_ci      this[kLineObjectStream] = readable;
13951cb0ef41Sopenharmony_ci    }
13961cb0ef41Sopenharmony_ci
13971cb0ef41Sopenharmony_ci    return this[kLineObjectStream][SymbolAsyncIterator]();
13981cb0ef41Sopenharmony_ci  }
13991cb0ef41Sopenharmony_ci}
14001cb0ef41Sopenharmony_ci
14011cb0ef41Sopenharmony_cimodule.exports = {
14021cb0ef41Sopenharmony_ci  Interface,
14031cb0ef41Sopenharmony_ci  InterfaceConstructor,
14041cb0ef41Sopenharmony_ci  kAddHistory,
14051cb0ef41Sopenharmony_ci  kDecoder,
14061cb0ef41Sopenharmony_ci  kDeleteLeft,
14071cb0ef41Sopenharmony_ci  kDeleteLineLeft,
14081cb0ef41Sopenharmony_ci  kDeleteLineRight,
14091cb0ef41Sopenharmony_ci  kDeleteRight,
14101cb0ef41Sopenharmony_ci  kDeleteWordLeft,
14111cb0ef41Sopenharmony_ci  kDeleteWordRight,
14121cb0ef41Sopenharmony_ci  kGetDisplayPos,
14131cb0ef41Sopenharmony_ci  kHistoryNext,
14141cb0ef41Sopenharmony_ci  kHistoryPrev,
14151cb0ef41Sopenharmony_ci  kInsertString,
14161cb0ef41Sopenharmony_ci  kLine,
14171cb0ef41Sopenharmony_ci  kLine_buffer,
14181cb0ef41Sopenharmony_ci  kMoveCursor,
14191cb0ef41Sopenharmony_ci  kNormalWrite,
14201cb0ef41Sopenharmony_ci  kOldPrompt,
14211cb0ef41Sopenharmony_ci  kOnLine,
14221cb0ef41Sopenharmony_ci  kPreviousKey,
14231cb0ef41Sopenharmony_ci  kPrompt,
14241cb0ef41Sopenharmony_ci  kQuestionCallback,
14251cb0ef41Sopenharmony_ci  kQuestionCancel,
14261cb0ef41Sopenharmony_ci  kRefreshLine,
14271cb0ef41Sopenharmony_ci  kSawKeyPress,
14281cb0ef41Sopenharmony_ci  kSawReturnAt,
14291cb0ef41Sopenharmony_ci  kSetRawMode,
14301cb0ef41Sopenharmony_ci  kTabComplete,
14311cb0ef41Sopenharmony_ci  kTabCompleter,
14321cb0ef41Sopenharmony_ci  kTtyWrite,
14331cb0ef41Sopenharmony_ci  kWordLeft,
14341cb0ef41Sopenharmony_ci  kWordRight,
14351cb0ef41Sopenharmony_ci  kWriteToOutput,
14361cb0ef41Sopenharmony_ci};
1437