Comments (4)
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 useargs.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.
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:
- https://github.com/wechaty/wechaty-vorpal - Extensible Interactive CLI Plugin for Wechaty ChatOps, Powered by Vorpal.
- https://github.com/wechaty/wechaty-vorpal-contrib - Wechaty Vorpal Chat CLI Extensions (Command Line Interface)
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.
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.
Closing due to inactivity.
from bandersnatch.
Related Issues (20)
- Error: Not enough non-option arguments: got 0, need at least 1 HOT 3
- Error: command option with prompt leads to an Unknown argument Error HOT 2
- REPL history is not available
- Errors are printed to stdout even with a custom error handler HOT 4
- Dependency Dashboard
- Bundles example doesn't work with typed-emitter HOT 2
- Feature Request: Yargs parser configuration HOT 2
- Action Required: Fix Renovate Configuration
- Command argument is not typed correctly HOT 2
- Default to help if no command was provided HOT 2
- Sub Commands? HOT 3
- Async `choices` for `.argument()`? HOT 7
- Setting `limit` on the config with `choices` HOT 5
- Display issue in help output for large number of choices.
- `choices` as an array of objects? HOT 2
- Explicitly provided args with default values are still being prompted
- boolean type is not inferred from default
- Automatically coerce types
- Feature Request: Subcommands and Nesting HOT 1
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
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.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from bandersnatch.