or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

index.md
tile.json

tessl/npm-external-editor

Edit a string with the users preferred text editor using $VISUAL or $ENVIRONMENT

Workspace
tessl
Visibility
Public
Created
Last updated
Describes
npmpkg:npm/external-editor@3.1.x

To install, run

npx @tessl/cli install tessl/npm-external-editor@3.1.0

index.mddocs/

External Editor

External Editor is a Node.js library that enables applications to launch external text editors (using $VISUAL or $EDITOR environment variables) for user text input. It handles temporary file creation, editor process management, and content retrieval with comprehensive error handling.

Package Information

  • Package Name: external-editor
  • Package Type: npm
  • Language: TypeScript
  • Installation: npm install external-editor

Core Imports

import { edit, editAsync, ExternalEditor, CreateFileError, LaunchEditorError, ReadFileError, RemoveFileError } from "external-editor";

For CommonJS:

const { edit, editAsync, ExternalEditor, CreateFileError, LaunchEditorError, ReadFileError, RemoveFileError } = require("external-editor");

Basic Usage

import { edit } from "external-editor";

// Simple synchronous editing
const result = edit("Initial text content");
console.log(result); // User's edited text

// With file options
const result2 = edit("# Please write your message", {
  postfix: ".md",
  prefix: "message-"
});

Architecture

External Editor provides two primary usage patterns:

  • Convenience Functions: edit() and editAsync() for simple, one-off text editing
  • Class-based Interface: ExternalEditor class for more control over the editing lifecycle
  • Error Handling: Specific error types for different failure scenarios
  • Editor Detection: Automatic detection from $VISUAL, $EDITOR, or platform defaults

Capabilities

Synchronous Text Editing

Simple function for immediate text editing with automatic cleanup.

/**
 * Edit text using the user's preferred external editor synchronously
 * @param text - Initial text content (defaults to empty string)
 * @param fileOptions - Optional temporary file configuration
 * @returns Edited text content
 * @throws CreateFileError, LaunchEditorError, ReadFileError, RemoveFileError
 */
function edit(text?: string, fileOptions?: IFileOptions): string;

Asynchronous Text Editing

Asynchronous function for text editing with callback-based result handling.

/**
 * Edit text using the user's preferred external editor asynchronously
 * @param text - Initial text content (defaults to empty string)
 * @param callback - Callback function for handling results
 * @param fileOptions - Optional temporary file configuration
 */
function editAsync(text?: string, callback: StringCallback, fileOptions?: IFileOptions): void;

Class-based Editor Interface

Full-featured class providing complete control over the editing lifecycle.

/**
 * External editor class providing complete control over editing lifecycle
 */
class ExternalEditor {
  /** Current text content */
  text: string;
  /** Path to temporary file */
  tempFile: string;
  /** Editor configuration (binary and arguments) */
  editor: IEditorParams;
  /** Last exit status from editor process */
  lastExitStatus: number;
  /** @deprecated Use tempFile instead */
  readonly temp_file: string;
  /** @deprecated Use lastExitStatus instead */
  readonly last_exit_status: number;

  /**
   * Create a new ExternalEditor instance
   * @param text - Initial text content (defaults to empty string)
   * @param fileOptions - Optional temporary file configuration
   * @throws CreateFileError
   */
  constructor(text?: string, fileOptions?: IFileOptions);

  /**
   * Run editor synchronously and read result
   * @returns Edited text content
   * @throws LaunchEditorError, ReadFileError
   */
  run(): string;

  /**
   * Run editor asynchronously
   * @param callback - Callback function for handling results
   */
  runAsync(callback: StringCallback): void;

  /**
   * Clean up temporary file
   * @throws RemoveFileError
   */
  cleanup(): void;
}

Usage Examples:

import { ExternalEditor } from "external-editor";

// Class-based usage with full control
const editor = new ExternalEditor("Initial content");

try {
  const result = editor.run();
  
  if (editor.lastExitStatus !== 0) {
    console.warn("Editor exited with non-zero status");
  }
  
  console.log("Edited text:", result);
} catch (error) {
  console.error("Editor failed:", error.message);
} finally {
  editor.cleanup();
}

// Async usage
const editor2 = new ExternalEditor("Start here...");
editor2.runAsync((error, result) => {
  if (error) {
    console.error("Error:", error.message);
  } else {
    console.log("Result:", result);
  }
  editor2.cleanup();
});

Error Handling

Comprehensive error types for different failure scenarios.

/**
 * Error thrown when temporary file creation fails
 */
class CreateFileError extends Error {
  /** Original underlying error */
  originalError: Error;
  constructor(originalError: Error);
}

/**
 * Error thrown when editor launch fails
 */
class LaunchEditorError extends Error {
  /** Original underlying error */
  originalError: Error;
  constructor(originalError: Error);
}

/**
 * Error thrown when temporary file reading fails
 */
class ReadFileError extends Error {
  /** Original underlying error */
  originalError: Error;
  constructor(originalError: Error);
}

/**
 * Error thrown when temporary file removal fails
 */
class RemoveFileError extends Error {
  /** Original underlying error */
  originalError: Error;
  constructor(originalError: Error);
}

Error Handling Example:

import { ExternalEditor, CreateFileError, LaunchEditorError, ReadFileError, RemoveFileError } from "external-editor";

try {
  const editor = new ExternalEditor();
  const result = editor.run();
  editor.cleanup();
} catch (error) {
  if (error instanceof CreateFileError) {
    console.error("Failed to create temporary file:", error.originalError);
  } else if (error instanceof LaunchEditorError) {
    console.error("Failed to launch editor:", error.originalError);
  } else if (error instanceof ReadFileError) {
    console.error("Failed to read temporary file:", error.originalError);
  } else if (error instanceof RemoveFileError) {
    console.error("Failed to remove temporary file:", error.originalError);
  } else {
    throw error;
  }
}

Types

/**
 * Configuration for the external editor command
 */
interface IEditorParams {
  /** Command line arguments for the editor */
  args: string[];
  /** Path to editor binary */
  bin: string;
}

/**
 * Options for temporary file creation
 */
interface IFileOptions {
  /** File name prefix */
  prefix?: string;
  /** File name postfix (useful for extensions like .md) */
  postfix?: string;
  /** File permission mode (e.g., 0o644) */
  mode?: number;
  /** File name template (see tmp package documentation) */
  template?: string;
  /** Directory for temporary file */
  dir?: string;
}

/**
 * Callback function type for async operations with string results
 */
type StringCallback = (err: Error, result: string) => void;

/**
 * Callback function type for void async operations
 */
type VoidCallback = () => void;