Code Monkey home page Code Monkey logo

Comments (4)

hongaar avatar hongaar commented on August 25, 2024

That's correct. I intentionally left out this feature. There are multiple reasons:

  • I'm not familiar with it and never used it (which also means I could be slightly misinformed 😉)
  • Having an additional application layer to deal with stdin/stdout and piping adds quite some complexity. Some things which come to mind: I don't know if Vorpal supports dealing with both native (process) stdin as well as 'emulated' stdin piped from within Vorpal? The Vorpal implementation looks inconsistent. In the Piping example on https://vorpal.js.org/ it's not very clear to me why some command handlers use args.words and others use args.stdin.
  • I personally ran into quite some problems with dealing with errors inside a command, carrying this.log around the app, async commands, etc. I feel adding support for pipes could introduce some of these complexities into the codebase.

More in general, an important goal for Vorpal was supporting things like vantage and cash. While these projects are awesome, they also make Vorpal a bit harder to work with (especially the source code). Fun fact: actually one of the projects in the vorpaljs org is a bash parser. I designed bandersnatch to be used as a command-line parser (with REPL as a bonus) primarily, not as a shell replacement like Vorpal + Cash.

I'm curious, however, how you would design the API for piping stdout/stdin in commands. And can you elaborate a bit on your specific use-case?

from bandersnatch.

huan avatar huan commented on August 25, 2024

Hi @hongaar , it's great to hear from you about your think of the design and your opinions of Vorpal!

Let me explain my use case at first.

Use Case: Vorpal with Chatbot

I'm trying to implement CLI inside Chatbot so that users can send commands via the chat window in WeChat (and also Slack, Telegram, etc).

The basic idea was to write a plugin for my Chatbot SDK Wechaty so that we can integrate Vorpal in WeChat dialogs which can enable other developers to easily writing Vorpal Extensions to extend their own commands for Chatbots.

In order to archive that, I have published the following two projects so far:

The Problem

The biggest problem that I'm struggling with is stdin/stdout.

In a chatbot environment, it's not like a TTY that one Vorpal can only have one interactive user... Vorpal with chatbot can be parallel used by many chat contacts, for example, two users send two different commands to the chatbot at the same time.

And also if we want to deal with the prompt feature in the chatbot environment, it will be more situation and states that we have to manage.

So there's a lot of code that needs to be re-designed to fit the chatbot environment usage, and that's the reason why I'm trying to study the Vorpal source codes so hard.

The Solution

After I studied the Vorpal, Vorpal Reforged, and Bandersnatch, I'm trying to build a standard input/output layer for my Wechaty chatbot environment, and today I have just finished my first design.

The basic idea to solve this problem is to build a stdin/stdout layer for the chatbot conversation, and this layer will be in charge of manage all the states.

In my implementation, I encapsulated them into Observables, and add stdin and stdout into the CommandInstance so that we can just use the following code in the command action functions:

vorpal.command('test')
.action(function action () {
    this.stdout.next('Hello, World!')
    this.stdout.next('Bye bye!')
})

I call the module with this implementation VorpalIo

The Source Code of VorpalIo

You are welcome to review my source code at https://github.com/wechaty/wechaty-vorpal/blob/master/src/vorpal-io.ts, and it might be easy to understand to read the unit tests, you can find them at https://github.com/wechaty/wechaty-vorpal/blob/master/src/vorpal-io.spec.ts

At last, the pipe feature is very useful in the chatbot use case, because we can do something like this:

find -name 'Huan' | send_message -t hello

Which the find command can find the id of the name, and then the send_message command can read the stdin then send some message to those ids.

from bandersnatch.

hongaar avatar hongaar commented on August 25, 2024

Very interesting! Does this setup allows using pipes between different commands in Vorpal, with your VorpalIo implementation sitting in the middle?

Bandersnatch is agnostic to a stdin/stdout implementation, and is only concerned with parsing process.argv. This means there is currently no way for bandersnatch to redirect or pipe any input or output from commands.

However, the program and repl classes are decoupled, so it should be possible to create a layer in between the two which exposes a mechanism for commands to redirect their stdout/stderr to and read stdin from, and also parses the repl line, extracts the piped segments and runs each command in order and connecting the pipes, a bit like VorpalIo.

Quick and dirty:

class Pipeline {
  private stdout = ''
  private stdin = ''

  public constructor(private program: Program) {}

  public write(message: string) {
    this.stdout = message
  }

  public read() {
    return this.stdin
  }

  public async run(line: string) {
    const commands = this.parsePipes(line) // as string[]
    await asyncForEach(commands, async (command) => {      
      this.stdin = this.stdout
      this.stdout = ''
      await this.program.run(command, pipeline)
    })
  }

  private parsePipes(line: string) {
    // ...
  }
}

// repl would be modified here
// https://github.com/hongaar/bandersnatch/blob/master/src/repl.ts#L98

const pipeline = new Pipeline(this.program)
const result = await pipeline.run(line.trim())

// commands could read/write data by using pipeline

command('test').action((args, pipeline) => {
  const stdin = pipeline.read()
  pipeline.write('hello world')  
})

All output will be fully buffered, as I think is also the case with Vorpal? Missing multiple calls to write, forwarding to console.log when not in a pipeline, stderr, etc. etc.

I'm also not sure how this would work with multi-user/multi-session scenario's like in your case...

from bandersnatch.

hongaar avatar hongaar commented on August 25, 2024

Closing due to inactivity.

from bandersnatch.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.