Skip to content

Commit

Permalink
Improved the repl binding
Browse files Browse the repository at this point in the history
  • Loading branch information
ldaniels528 committed Mar 31, 2017
1 parent 890f0ce commit 390a49f
Show file tree
Hide file tree
Showing 5 changed files with 112 additions and 18 deletions.
2 changes: 1 addition & 1 deletion src/main/scala/io/scalajs/nodejs/Process.scala
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ trait Process extends IEventEmitter {
/**
* An object containing the user environment.
*/
def env: js.Dictionary[String] = js.native
def env: Environment = js.native

/**
* This is the set of Node.js-specific command line options from the executable that started the process.
Expand Down
2 changes: 2 additions & 0 deletions src/main/scala/io/scalajs/nodejs/package.scala
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ package object nodejs {
*/
type FileDescriptor = Integer

type Environment = js.Dictionary[String]

/////////////////////////////////////////////////////////////////////////////////
// Built-in Properties
/////////////////////////////////////////////////////////////////////////////////
Expand Down
2 changes: 1 addition & 1 deletion src/main/scala/io/scalajs/nodejs/repl/REPL.scala
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import scala.scalajs.js.|
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_MAGIC: String = js.native

/**
* @example repl.start([options])
Expand Down
36 changes: 20 additions & 16 deletions src/main/scala/io/scalajs/nodejs/repl/REPLServer.scala
Original file line number Diff line number Diff line change
Expand Up @@ -15,30 +15,34 @@ trait REPLServer extends IEventEmitter with Interface {
/**
* The REPL's context
*/
// TODO find document for this property
val context: js.Dynamic = js.native
val context: REPLContext = js.native

/**
* Makes a command available in the REPL. The command is invoked by typing a . followed by the keyword.
* The cmd is an object with the following values:
* 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
* or an object with the following properties:
* <ul>
* <li>help - help text to be displayed when .help is entered (Optional).</li>
* <li>action - a function to execute, potentially taking in a string argument, when the command is invoked,
* bound to the REPLServer instance (Required).</li>
* <li>help (string) Help text to be displayed when .help is entered (Optional).</li>
* <li>action (Function) The function to execute, optionally accepting a single string argument.</li>
* </ul>
* If a function is provided instead of an object for cmd, it is treated as the action.
* @example replServer.defineCommand(keyword, cmd)
* @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.Any): Unit = js.native
def defineCommand(keyword: String, cmd: js.Function0[Any]): Unit = js.native

/**
* Like readline.prompt except also adding indents with ellipses when inside blocks. The preserveCursor argument
* is passed to readline.prompt. This is used primarily with defineCommand. It's also used internally to render
* each prompt line.
* @example replServer.displayPrompt([preserveCursor])
* @see [[prompt()]]
* The replServer.displayPrompt() method readies the REPL instance for input from the user, printing the
* configured prompt to a new line in the output and resuming the input to accept new input.
*
* When multi-line input is being entered, an ellipsis is printed rather than the 'prompt'.
* *
* When preserveCursor is true, the cursor placement will not be reset to 0.
*
* The replServer.displayPrompt method is primarily intended to be called from within the action function
* for commands registered using the replServer.defineCommand() method.
* @param preserveCursor indicates whether to preserver the cursor (position?)
*/
def displayPrompt(preserveCursor: Boolean): Unit = js.native
def displayPrompt(preserveCursor: Boolean = js.native): Unit = js.native

/**
* Like readline.prompt except also adding indents with ellipses when inside blocks. The preserveCursor argument
Expand Down
88 changes: 88 additions & 0 deletions src/main/scala/io/scalajs/nodejs/repl/package.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
package io.scalajs.nodejs

import scala.scalajs.js

/**
* repl package object
* @author [email protected]
*/
package object repl {

type REPLContext = js.Dynamic

/**
* REPL Server events
* @param server the given [[REPLServer instance]]
*/
final implicit class REPLServerEvents(val server: REPLServer) extends AnyVal {

@inline
def contextAs[T]: T = server.context.asInstanceOf[T]

/**
* The 'exit' event is emitted when the REPL is exited either by receiving the .exit command as input,
* the user pressing CTRL-C twice to signal SIGINT, or by pressing CTRL-D to signal 'end' on the input stream.
* The listener callback is invoked without any arguments.
* @param listener The listener callback
*/
@inline
def onExit(listener: () => Any): server.type = server.on("exit", listener)

/**
* The 'reset' event is emitted when the REPL's context is reset. This occurs whenever the .clear command
* is received as input unless the REPL is using the default evaluator and the repl.REPLServer instance
* was created with the useGlobal option set to true. The listener callback will be called with a reference
* to the context object as the only argument.
* @param listener The listener callback
*/
@inline
def onReset(listener: REPLContext => Any): server.type = server.on("reset", listener)

}

/**
* Various behaviors of the Node.js REPL can be customized using the following environment variables:
* <ul>
* <li>NODE_REPL_HISTORY</li>
* <li>NODE_REPL_HISTORY_SIZE</li>
* <li>NODE_REPL_MODE</li>
* </ul>
*/
final implicit class EnvironmentVariableOptions(val env: Environment) extends AnyVal {

/**
* When a valid path is given, persistent REPL history will be saved to the specified file rather
* than .node_repl_history in the user's home directory. Setting this value to "" will disable persistent
* REPL history. Whitespace will be trimmed from the value.
*/
@inline
def NODE_REPL_HISTORY: Option[String] = env.get("NODE_REPL_HISTORY")

/**
* Previously in Node.js/io.js v2.x, REPL history was controlled by using a NODE_REPL_HISTORY_FILE environment
* variable, and the history was saved in JSON format. This variable has now been deprecated, and the old
* JSON REPL history file will be automatically converted to a simplified plain text format. This new file
* will be saved to either the user's home directory, or a directory defined by the NODE_REPL_HISTORY variable,
* as documented in the Environment Variable Options.
*/
@inline
@deprecated("Use NODE_REPL_HISTORY instead.", since = "3.0.0")
def NODE_REPL_HISTORY_FILE: Option[String] = env.get("NODE_REPL_HISTORY_FILE")

/**
* Defaults to 1000. Controls how many lines of history will be persisted if history is available.
* Must be a positive number.
*/
@inline
def NODE_REPL_HISTORY_SIZE: Option[Int] = env.get("NODE_REPL_HISTORY_SIZE").map(_.toInt)

/**
* May be any of sloppy, strict, or magic. Defaults to magic, which will automatically run "strict mode only"
* statements in strict mode.
*/
@inline
def NODE_REPL_MODE: Option[String] = env.get("NODE_REPL_MODE")

}

}

0 comments on commit 390a49f

Please sign in to comment.