SBoudrias / Inquirer.js

A collection of common interactive command line user interfaces.
MIT License
20.28k stars 1.3k forks source link

Make bottomBar.destroy() ? #426

Closed gentunian closed 3 months ago

gentunian commented 8 years ago

From examples process.exit() is called from a spawned process in order to finish the execution:

var cmd = spawn(cmdify('npm'), ['-g', 'install', 'inquirer'], {stdio: 'pipe'});
cmd.stdout.pipe(ui.log);
cmd.on('close', function () {
  ui.updateBottomBar('Installation done!\n');
  process.exit();
});

I found this confusing when using bottom bar inside a callback without spawning a process, just like:

var download = function( opts, dest, cb ) {
    // Bottom bar showing download progress
    var ui = new inquirer.ui.BottomBar();
    ui.log.write('test');
    // Destination file
    var file = fs.createWriteStream( dest );
    // Download stats 
    var stats = progress({ time: 100 });
    stats.on( 'progress', function( p ) {
        ui.updateBottomBar(''+p.percentage);
    });
    var request = http.get( opts, function( response ) {
        response.pipe(stats).pipe( file );
        file.on( 'finish', function() {
            file.close( cb );
                        // ui.destroy() would be nice?
        });
    }).on( 'error', function( err ) {
        fs.unlink( dest );
        if ( cb ) cb( err.message );
    });
};
gentunian commented 8 years ago

After a fast code lookup I found that would be possible to create a new method in bottom-bar.js like this one:

Prompt.prototype.destroy = function() {
    this.onForceClose();
}

onForceClose() is defined in the base UI here: https://github.com/SBoudrias/Inquirer.js/blob/master/lib/ui/baseUI.js#L30

What do you think?

EDIT: or maybe just emitting the event that onForceClose() is waiting for:

Prompt.prototype.destroy = function() {
  this.rl.emit('SIGINT');
}
SBoudrias commented 8 years ago

@gentunian sounds like a potential solution. Want to try it out and send a PR?

gentunian commented 8 years ago

I'm reading more code as I'm writing this.

It seems that the functionality is already there. The baseUI has 2 methods that could be used for that purpose and they are inherited by the Prompt object (that would be our ui):

  1. ui.onForceClose()
  2. ui.close()

(1) is a method named for receiving events, so a good practice would be to not call on*() method manually. But it just works...

(2) is called by onForceClose(). The only difference is that calling the latter directly won't send a newline to our shell.

If good practice is a go, we could write a destroy() method that emits the signal that invokes onForceClose(). Anyway, the functionality is already there and I didn't find it until I read the code to find its solution :)