or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

browser.mdcli.mdcompilation.mdindex.mdparsing.mdregistration.mdrepl.mdutilities.md
tile.json

repl.mddocs/

REPL & Interactive Environment

Interactive CoffeeScript interpreter with multiline support, history persistence, Node.js integration, and top-level async/await support.

REPL Functions

Start Function

Starts a CoffeeScript REPL session with configurable options.

/**
 * Start CoffeeScript REPL with custom options
 * @param options - REPL configuration options
 * @returns Node.js REPL server instance
 */
function start(options?: REPLOptions): REPLServer;

interface REPLOptions {
  /** REPL prompt string (default: 'coffee> ') */
  prompt?: string;
  /** Path to history file (default: ~/.coffee_history) */
  historyFile?: string;
  /** Maximum input size for history (default: 10240) */
  historyMaxInputSize?: number;
  /** Custom evaluation function */
  eval?: (input: string, context: any, filename: string, callback: Function) => void;
}

interface REPLServer {
  /** Add command to REPL */
  defineCommand(keyword: string, cmd: Function | { help: string, action: Function }): void;
  /** Display help message */
  displayPrompt(preserveCursor?: boolean): void;
  /** Close REPL session */
  close(): void;
}

Usage Examples:

const CoffeeScript = require('coffeescript');

// Start default REPL
const repl = CoffeeScript.start();

// Start REPL with custom options
const customRepl = CoffeeScript.start({
  prompt: 'cs> ',
  historyFile: '/path/to/custom_history',
  historyMaxInputSize: 5000
});

// Start REPL with custom evaluation
const debugRepl = CoffeeScript.start({
  prompt: 'debug> ',
  eval: function(input, context, filename, callback) {
    console.log('Evaluating:', input);
    // Use default evaluation
    this.eval(input, context, filename, callback);
  }
});

Direct REPL Access

// Access via repl.js module export
const replModule = require('coffeescript/repl');
const repl = replModule.start({ prompt: 'coffee> ' });

REPL Features

Interactive Compilation

The REPL compiles and evaluates CoffeeScript expressions interactively:

coffee> square = (x) -> x * x
[Function: square]

coffee> square 5
25

coffee> numbers = [1, 2, 3, 4, 5]
[ 1, 2, 3, 4, 5 ]

coffee> squares = (square num for num in numbers)
[ 1, 4, 9, 16, 25 ]

coffee> {name, age} = {name: 'Alice', age: 30, city: 'NYC'}
{ name: 'Alice', age: 30 }

coffee> console.log "Hello #{name}, you are #{age} years old"
Hello Alice, you are 30 years old
undefined

Multiline Input

The REPL supports multiline expressions and automatically detects incomplete input:

coffee> if true
......    console.log 'This is true'
......    result = 42
......  else
......    console.log 'This is false'
......    result = 0
......  
This is true
42

coffee> class Calculator
......   constructor: (@name) ->
......   
......   add: (a, b) ->
......     console.log "#{@name}: #{a} + #{b} = #{a + b}"
......     a + b
......   
[class Calculator]

coffee> calc = new Calculator 'MyCalc'
Calculator { name: 'MyCalc' }

coffee> calc.add 3, 4
MyCalc: 3 + 4 = 7
7

Command History

The REPL maintains persistent command history:

# History is automatically saved to ~/.coffee_history
coffee> square = (x) -> x * x
coffee> square 5
coffee> # Press Up arrow to navigate history
coffee> square 5  # Previous command recalled

History features:

  • Persistent across sessions
  • Configurable history file location
  • Maximum input size limit
  • Standard readline key bindings (Up/Down arrows, Ctrl+R search)

Tab Completion

The REPL provides tab completion for variables, properties, and methods:

coffee> myObject = {name: 'test', value: 42, calculate: -> @value * 2}
coffee> myO<TAB>     # Completes to myObject
coffee> myObject.<TAB>  # Shows: name, value, calculate
coffee> Math.<TAB>   # Shows: abs, ceil, floor, max, min, etc.
coffee> console.<TAB> # Shows: log, error, warn, info, etc.

Top-level Await

The REPL supports top-level await for asynchronous operations:

coffee> fs = require 'fs'
coffee> files = await fs.promises.readdir '.'
[ 'package.json', 'src', 'lib', 'test' ]

coffee> content = await fs.promises.readFile 'package.json', 'utf8'
coffee> JSON.parse(content).name
'my-project'

coffee> # Async function definition
coffee> fetchData = (delay) ->
......   new Promise (resolve) ->
......     setTimeout (-> resolve "Data after #{delay}ms"), delay
......   

coffee> result = await fetchData 1000
Data after 1000ms

coffee> # Multiple async operations
coffee> [result1, result2] = await Promise.all [
......   fetchData(500),
......   fetchData(300)
....... ]
Data after 300ms
Data after 500ms

Node.js Integration

The REPL has full access to Node.js APIs and modules:

coffee> path = require 'path'
coffee> path.join '/users', 'alice', 'documents'
'/users/alice/documents'

coffee> process.version
'v16.14.0'

coffee> os = require 'os'
coffee> os.platform()
'darwin'

coffee> # Global variables available
coffee> __filename
'/path/to/current/repl'

coffee> __dirname  
'/path/to/current'

coffee> global.myGlobal = 'shared data'
'shared data'

Error Handling

The REPL provides detailed error reporting with CoffeeScript context:

coffee> invalidSyntax ->
SyntaxError: unexpected ->
    at Object.<anonymous> (repl:1:15)
    at repl:1:1

coffee> undefinedVariable
ReferenceError: undefinedVariable is not defined
    at repl:1:1

coffee> # Runtime errors show helpful context
coffee> divide = (a, b) -> 
......   throw new Error "Division by zero" if b is 0
......   a / b
......   

coffee> divide 10, 0
Error: Division by zero
    at divide (repl:2:5)
    at repl:1:1

REPL Customization

Custom Commands

Add custom commands to the REPL:

const CoffeeScript = require('coffeescript');
const repl = CoffeeScript.start();

// Add custom help command
repl.defineCommand('help', {
  help: 'Show custom help',
  action: function() {
    console.log('Custom CoffeeScript REPL Commands:');
    console.log('.help - Show this help');
    console.log('.clear - Clear current context');
    console.log('.save <filename> - Save session to file');
    this.displayPrompt();
  }
});

// Add save command
repl.defineCommand('save', {
  help: 'Save session to file',
  action: function(filename) {
    const fs = require('fs');
    if (!filename) {
      console.log('Usage: .save <filename>');
    } else {
      // Save logic here
      console.log(`Session saved to ${filename}`);
    }
    this.displayPrompt();
  }
});

Custom Evaluation Function

Create a REPL with custom evaluation logic:

const CoffeeScript = require('coffeescript');

function customEval(input, context, filename, callback) {
  // Log all input
  console.log(`[DEBUG] Evaluating: ${input.trim()}`);
  
  try {
    // Pre-process input
    const processedInput = input.replace(/debug\s+/, 'console.log ');
    
    // Use CoffeeScript compilation
    const compiled = CoffeeScript.compile(processedInput, {
      bare: true,
      filename: 'repl'
    });
    
    // Evaluate in context
    const result = eval(compiled);
    callback(null, result);
  } catch (error) {
    callback(error);
  }
}

const repl = CoffeeScript.start({
  prompt: 'debug> ',
  eval: customEval
});

Environment Configuration

Configure REPL environment variables:

# Custom history file location
export COFFEE_HISTORY="/path/to/custom/history"

# Custom prompt
export COFFEE_PROMPT="cs> "

# Disable colors
export NO_COLOR=1

# Node.js options
export NODE_OPTIONS="--max-old-space-size=4096"

coffee  # Starts REPL with custom configuration

Programmatic REPL Usage

Embedded REPL

Embed CoffeeScript REPL in applications:

const CoffeeScript = require('coffeescript');
const net = require('net');

// Create TCP server with CoffeeScript REPL
const server = net.createServer(socket => {
  const repl = CoffeeScript.start({
    prompt: 'remote> ',
    input: socket,
    output: socket,
    eval: function(input, context, filename, callback) {
      // Add application context
      context.app = myApplication;
      context.db = database;
      
      // Use default evaluation
      return CoffeeScript.eval(input, context, filename, callback);
    }
  });
  
  repl.on('exit', () => socket.end());
});

server.listen(3000, () => {
  console.log('CoffeeScript REPL server listening on port 3000');
});

REPL Context Management

const CoffeeScript = require('coffeescript');

// Start REPL with pre-populated context
const repl = CoffeeScript.start();

// Add utilities to context
repl.context._ = require('underscore');
repl.context.fs = require('fs');
repl.context.path = require('path');

// Add custom functions
repl.context.loadJson = function(filename) {
  const fs = require('fs');
  return JSON.parse(fs.readFileSync(filename, 'utf8'));
};

repl.context.saveJson = function(filename, data) {
  const fs = require('fs');
  fs.writeFileSync(filename, JSON.stringify(data, null, 2));
};

// Now available in REPL:
// coffee> data = loadJson 'config.json'
// coffee> data.version = '2.0.0'  
// coffee> saveJson 'config.json', data

REPL Session Management

const CoffeeScript = require('coffeescript');
const fs = require('fs');

class REPLSession {
  constructor(options = {}) {
    this.repl = CoffeeScript.start({
      prompt: options.prompt || 'session> ',
      ...options
    });
    
    this.history = [];
    this.setupLogging();
  }
  
  setupLogging() {
    const originalEval = this.repl.eval;
    this.repl.eval = (input, context, filename, callback) => {
      this.history.push({
        input: input.trim(),
        timestamp: new Date()
      });
      
      return originalEval.call(this.repl, input, context, filename, (err, result) => {
        if (!err) {
          this.history[this.history.length - 1].result = result;
        }
        callback(err, result);
      });
    };
  }
  
  saveSession(filename) {
    fs.writeFileSync(filename, JSON.stringify(this.history, null, 2));
  }
  
  loadSession(filename) {
    const session = JSON.parse(fs.readFileSync(filename, 'utf8'));
    session.forEach(entry => {
      console.log(`${entry.timestamp}: ${entry.input}`);
      if (entry.result !== undefined) {
        console.log(`=> ${entry.result}`);
      }
    });
  }
}

// Usage
const session = new REPLSession({ prompt: 'logged> ' });
// After some interaction:
// session.saveSession('my-session.json');