Skip to content
This repository has been archived by the owner on Jul 30, 2024. It is now read-only.

Overhaul repl and readline module #74

Merged
merged 2 commits into from
Sep 27, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,8 @@ The following core Node.js modules (v8.7.0+) have been implemented:
| [path](https://nodejs.org/api/path.html) | :heavy_check_mark: |
| [process](https://nodejs.org/api/process.html) | :heavy_check_mark: |
| [querystring](https://nodejs.org/api/querystring.html) | :heavy_check_mark: |
| [readline](https://nodejs.org/api/readline.html) | |
| [repl](https://nodejs.org/api/repl.html) | |
| [readline](https://nodejs.org/api/readline.html) | :heavy_check_mark: |
| [repl](https://nodejs.org/api/repl.html) | :heavy_check_mark: |
| [stream](https://nodejs.org/api/stream.html) | |
| [string-decoder](https://nodejs.org/api/string_decoder.html) | :heavy_check_mark: |
| [timers](https://nodejs.org/api/timers.html) | :heavy_check_mark: |
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ trait Interface extends IEventEmitter {
* If output is set to null or undefined when calling createInterface, nothing is displayed.
* @example rl.question(query, callback)
*/
def question(query: String, callback: js.Function): Unit = js.native
def question(query: String, callback: js.Function1[String, Any]): Unit = js.native

/**
* Resumes the readline input stream.
Expand All @@ -71,7 +71,7 @@ trait Interface extends IEventEmitter {
* This will also resume the input stream if it has been paused.
* @example rl.write(data[, key])
*/
def write(data: String, key: js.Any): Unit = js.native
def write(data: String, key: Key): Unit = js.native

/**
* Writes data to output stream, unless output is set to null or undefined when calling createInterface.
Expand All @@ -81,8 +81,16 @@ trait Interface extends IEventEmitter {
*/
def write(data: String): Unit = js.native

// TODO: [Symbol.asyncIterator]()
}

class Key(
var ctrl: js.UndefOr[Boolean] = js.undefined,
var meta: js.UndefOr[Boolean] = js.undefined,
var shift: js.UndefOr[Boolean] = js.undefined,
var name: js.UndefOr[String] = js.undefined
) extends js.Object

/**
* Readline Interface Companion
*/
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
package io.scalajs.nodejs.readline

import io.scalajs.nodejs.events.IEventEmitter
import io.scalajs.nodejs.stream.{Readable, Writable}

import scala.scalajs.js
import scala.scalajs.js.annotation.JSImport

/**
* Readline allows reading of a stream (such as process.stdin) on a line-by-line basis.
/**reading
* Readline allows of a stream (such as process.stdin) on a line-by-line basis.
* To use this module, do require('readline').
* Note that once you've invoked this module, your Node.js program will not terminate until you've closed the interface.
* @see https://nodejs.org/api/readline.html
Expand All @@ -23,13 +24,13 @@ trait Readline extends IEventEmitter {
* </ul>
* @example readline.clearLine(stream, dir)
*/
def clearLine(stream: js.Any, dir: Int): Unit = js.native
def clearLine(stream: Writable, dir: Int, callback: js.Function = js.native): Boolean = js.native

/**
* Clears the screen from the current position of the cursor down.
* @example readline.clearScreenDown(stream)
*/
def clearScreenDown(stream: js.Any): Unit = js.native
def clearScreenDown(stream: Writable, callback: js.Function = js.native): Boolean = js.native

/**
* Creates a readline Interface instance.
Expand All @@ -41,13 +42,17 @@ trait Readline extends IEventEmitter {
* Move cursor to the specified position in a given TTY stream.
* @example readline.cursorTo(stream, x, y)
*/
def cursorTo(stream: js.Any, x: Int, y: Int): Unit = js.native
def cursorTo(stream: Writable, x: Int, y: Int, callback: js.Function = js.native): Unit = js.native
def cursorTo(stream: Writable, x: Int, callback: js.Function): Unit = js.native
def cursorTo(stream: Writable, x: Int): Unit = js.native

def emitKeypressEvents(stream: Readable, interface: Interface = js.native): Unit = js.native

/**
* Move cursor relative to it's current position in a given TTY stream.
* @example readline.moveCursor(stream, dx, dy)
*/
def moveCursor(stream: js.Any, dx: Int, dy: Int): Unit = js.native
def moveCursor(stream: Writable, dx: Int, dy: Int, callback: js.Function = js.native): Unit = js.native

}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,14 @@ import scala.scalajs.js
/**
* Readline Options
*/
class ReadlineOptions(var input: js.UndefOr[Readable] = js.undefined,
var output: js.UndefOr[Writable] = js.undefined,
var completer: js.UndefOr[js.Function] = js.undefined,
var terminal: js.UndefOr[Boolean] = js.undefined,
var historySize: js.UndefOr[Int] = js.undefined)
extends js.Object
class ReadlineOptions(
var input: js.UndefOr[Readable] = js.undefined,
var output: js.UndefOr[Writable] = js.undefined,
var completer: js.UndefOr[js.Function] = js.undefined,
var terminal: js.UndefOr[Boolean] = js.undefined,
var historySize: js.UndefOr[Int] = js.undefined,
var prompt: js.UndefOr[String] = js.undefined,
var crlfDelay: js.UndefOr[Double] = js.undefined,
var removeHistoryDuplicates: js.UndefOr[Boolean] = js.undefined,
var escapeCodeTimeout: js.UndefOr[Double] = js.undefined
) extends js.Object
45 changes: 22 additions & 23 deletions app/current/src/main/scala/io/scalajs/nodejs/repl/REPL.scala
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package io.scalajs.nodejs.repl

import io.scalajs.nodejs.events.IEventEmitter
import io.scalajs.nodejs.net.Socket
import io.scalajs.nodejs.stream

import scala.scalajs.js
import scala.scalajs.js.annotation.JSImport
Expand All @@ -13,32 +13,31 @@ import scala.scalajs.js.annotation.JSImport
*/
@js.native
trait REPL extends IEventEmitter {
var REPL_MODE_SLOPPY: String = js.native
var REPL_MODE_STRICT: String = js.native
var REPL_MODE_MAGIC: String = js.native
var REPL_MODE_SLOPPY: js.Symbol = js.native
var REPL_MODE_STRICT: js.Symbol = js.native

/**
* @example repl.start([options])
*/
def start(options: REPLOptions): REPLServer = js.native

/**
* @example repl.start([options])
*/
def start(prompt: String, socket: Socket): REPLServer = js.native

/**
* @example repl.start([options])
*/
def start(prompt: String): REPLServer = js.native

/**
* @example repl.start([options])
*/
def start(): REPLServer = js.native
@deprecated("Use REPL_MODE_SLOPPY instead", "Node.js v6.0.0")
var REPL_MODE_MAGIC: js.UndefOr[js.Symbol] = js.native

def start(options: StartOptions = js.native): REPLServer = js.native
def start(prompt: String): REPLServer = js.native
}

class StartOptions(
var prompt: js.UndefOr[String] = js.undefined,
var input: js.UndefOr[stream.Readable] = js.undefined,
var output: js.UndefOr[stream.Writable] = js.undefined,
var terminal: js.UndefOr[Boolean] = js.undefined,
var eval: js.UndefOr[js.Function4[String, js.Object, String, js.Function, Any]] = js.undefined,
var useColors: js.UndefOr[Boolean] = js.undefined,
var useGlobal: js.UndefOr[Boolean] = js.undefined,
var ignoreUndefined: js.UndefOr[Boolean] = js.undefined,
var writer: js.UndefOr[js.Function1[js.Any, Any]] = js.undefined,
var completer: js.UndefOr[js.Function] = js.undefined,
var replMode: js.UndefOr[js.Symbol] = js.undefined,
var breakEvalOnSigint: js.UndefOr[Boolean] = js.undefined
) extends js.Object

/**
* REPL Singleton
*/
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
package io.scalajs.nodejs.repl

import com.thoughtworks.enableIf
import io.scalajs.nodejs.events.IEventEmitter
import io.scalajs.nodejs.readline.Interface

import scala.scalajs.js
import scala.scalajs.js.|

/**
* REPL Server
Expand All @@ -16,6 +18,9 @@ trait REPLServer extends IEventEmitter with Interface {
*/
val context: REPLContext = js.native

@enableIf(io.scalajs.nodejs.CompilerSwitches.gteNodeJs10)
def clearBufferedCommand(): Unit = js.native

/**
* The replServer.defineCommand() method is used to add new .-prefixed commands to the REPL instance.
* Such commands are invoked by typing a period (.) followed by the keyword. The cmd is either a Function
Expand All @@ -27,7 +32,7 @@ trait REPLServer extends IEventEmitter with Interface {
* @param keyword The command keyword (without a leading . character).
* @param cmd The function to invoke when the command is processed.
*/
def defineCommand(keyword: String, cmd: js.Function0[Any]): Unit = js.native
def defineCommand(keyword: String, cmd: DefinedCommand | js.Function1[String, Any]): Unit = js.native

/**
* The replServer.displayPrompt() method readies the REPL instance for input from the user, printing the
Expand All @@ -52,8 +57,16 @@ trait REPLServer extends IEventEmitter with Interface {
*/
def displayPrompt(): Unit = js.native

@enableIf(io.scalajs.nodejs.CompilerSwitches.gteNodeJs12)
def setupHistory(historyPath: String, callback: js.Function2[io.scalajs.nodejs.Error, REPLServer, Any]): Unit =
js.native
}

class DefinedCommand(
var action: js.Function1[String, Any],
var help: js.UndefOr[String] = js.undefined
) extends js.Object

/**
* REPL Server Companion
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ package object repl {
* @param listener The listener callback
*/
@inline
def onExit(listener: () => Any): server.type = server.on("exit", listener)
def onExit(listener: () => Any): REPLServer = server.on("exit", listener)

/**
* The 'reset' event is emitted when the REPL's context is reset. This occurs whenever the .clear command
Expand All @@ -35,7 +35,7 @@ package object repl {
* @param listener The listener callback
*/
@inline
def onReset(listener: REPLContext => Any): server.type = server.on("reset", listener)
def onReset(listener: REPLContext => Any): REPLServer = server.on("reset", listener)

}

Expand All @@ -47,7 +47,7 @@ package object repl {
* <li>NODE_REPL_MODE</li>
* </ul>
*/
final implicit class EnvironmentVariableOptions(val env: process.Environment) extends AnyVal {
final implicit class EnvironmentVariableOptions(private val env: process.Environment) extends AnyVal {

/**
* When a valid path is given, persistent REPL history will be saved to the specified file rather
Expand Down