function Presentation() { // eslint-disable-line stdlib/no-redeclare
	var options;
	var nargs;
	var text;
	var repl;
	var cmds;
	var opts;
	var self;
	var err;
	var cmd;
	var FLG;
	var d;
	var i;

	nargs = arguments.length;
	if ( !( this instanceof Presentation) ) {
		if ( nargs === 0 ) {
			throw new Error( 'invalid invocation. Insufficient arguments. Must provide a REPL instance.' );
		}
		if ( nargs === 1 ) {
			return new Presentation( arguments[ 0 ] );
		}
		if ( nargs === 2 ) {
			return new Presentation( arguments[ 0 ], arguments[ 1 ] );
		}
		return new Presentation( arguments[ 0 ], arguments[ 1 ], arguments[ 2 ] ); // eslint-disable-line max-len
	}
	if ( nargs === 0 ) {
		throw new Error( 'invalid invocation. Insufficient arguments. Must provide a REPL instance.' );
	}
	opts = defaults();
	if ( nargs === 1 ) {
		repl = arguments[ 0 ];
	} else if ( nargs === 2 ) {
		if ( isString( arguments[ 0 ] ) ) {
			text = arguments[ 0 ];
			repl = arguments[ 1 ];
		} else {
			repl = arguments[ 0 ];
			options = arguments[ 1 ];
			err = validate( opts, options );
			if ( err ) {
				throw err;
			}
		}
	} else { // nargs === 3
		text = arguments[ 0 ];
		if ( !isString( text ) ) {
			throw new TypeError( format( 'invalid argument. Presentation text must be a string. Value: `%s`.', text ) );
		}
		repl = arguments[ 1 ];
		options = arguments[ 2 ];
		err = validate( opts, options );
		if ( err ) {
			throw err;
		}
	}
	if ( constructorName( repl ) !== 'REPL' ) {
		throw new TypeError( format( 'invalid argument. REPL argument must be a REPL instance. Value: `%s`.', repl ) );
	}
	self = this;
	debug( 'Options: %s', JSON.stringify( opts ) );

	// Call the parent constructor:
	EventEmitter.call( this );

	setNonEnumerableReadOnly( this, '_repl', repl );
	setNonEnumerableReadOnly( this, '_opts', opts );
	setNonEnumerable( this, '_source', '' );
	setNonEnumerable( this, '_watcher', null );

	setNonEnumerableReadOnly( this, '_slides', [] );
	setNonEnumerable( this, '_slide', null );

	setNonEnumerable( this, '_slideCursor', -1 );
	setNonEnumerable( this, '_fragmentCursor', 0 );

	// Switch to a "presentation" workspace:
	FLG = repl._quiet;
	repl._quiet = true;
	repl._context.workspace( opts.workspace );
	repl._quiet = FLG;

	// Add presentation commands:
	cmds = commands( this );
	setCommands( repl._context, cmds );

	// Load presentation command documentation into the REPL environment...
	for ( i = 0; i < cmds.length; i++ ) {
		cmd = cmds[ i ];
		d = DOCS.help[ cmd[ 0 ] ];
		if ( d ) {
			repl._context.userDoc( cmd[ 0 ], cmd[ 2 ], d ); // full command
			repl._context.userDoc( cmd[ 1 ], cmd[ 2 ], d ); // shortcut
		}
	}
	// Check whether to parse a provided presentation text or load a presentation file...
	if ( text ) {
		parse( this._slides, text );
		this._slide = this._slides[ 0 ] || null;
		this._slideCursor = 0;
		this._fragmentCursor = 0;
	} else if ( opts.load ) {
		this.load( opts.load );
	}
	// Perform any clean-up tasks upon closing the REPL environment:
	repl.on( 'exit', onClose );

	return this;

	/**
	* Callback invoked upon closing a REPL environment.
	*
	* @private
	*/
	function onClose() {
		debug( 'REPL environment closed. Performing presentation clean-up tasks.' );
		self.unwatch();
	}
}
Presentation constructor.

@private
@constructor
@param {string} [text] - presentation text
@param {REPL} repl - REPL instance
@param {Options} [options] - function options
@param {string} [options.borderTop='*'] - top border character sequence
@param {string} [options.borderBottom='*'] - bottom border character sequence
@param {string} [options.borderLeft='* '] - left border character sequence
@param {string} [options.borderRight=' *'] - right border character sequence
@param {(boolean|string)} [options.counter=false] - slide counter
@param {(PositiveInteger|null)} [options.width=null] - presentation width
@param {(PositiveInteger|null)} [options.height=null] - presentation height
@param {string} [options.workspace="presentation"] - REPL workspace name
@param {string} [options.load] - file path specifying a presentation file to load
@param {boolean} [options.autoClear=true] - boolean indicating whether to automatically clear the screen before writing a rendered slide to the REPL
@param {boolean} [options.loop=false] - boolean indicating whether to "loop" a presentation
@throws {Error} must provide a REPL instance
@throws {TypeError} presentation text argument must be a string
@throws {TypeError} REPL argument must be a REPL instance
@throws {TypeError} options argument must be an object
@throws {TypeError} must provide valid options
@returns {Presentation} presentation instance

@example
var debug = require( '@stdlib/streams/node/debug-sink' );

// Create a new REPL:
var repl = new REPL({
    'output': debug()
});

// Create a new REPL presentation:
var pres = new Presentation( repl );

// ...

// Close the REPL:
repl.close();