53 comments

[ 3.8 ms ] story [ 93.8 ms ] thread
And now you have two problems.
Hah! I have to admit that I spent quite some time thinking about whether I wanted to use this or switch to a "real" language.

For all its shortcomings, I find that shell scripting is still the easiest way to put together a tool that needs to interact with a lot of other commands, no matter how large it ends up being. I love Python to death, but using `subprocess` for everything is the opposite of my idea of a good time.

The syntax for basically every "real" programming language is amazingly unurgonomic at interoperating with the outside world and moving/transforming data which is why shells are still super popular.

You would think there would be more effort supporting this since it's so tedious to have a billion libraries that are just wrappers around http apis and external utility calls.

"Real" programming languages are leagues ahead of shell scripting languages in terms of transforming and moving data around.

Most shell utilities are focused on text processing or are thin wrappers around system calls. If you're using something like python's `subprocess` module to get at these, you're doing it wrong.

Interactivity is where shells have an advantage. Their syntax lends itself well to that. It's also why the syntax sucks for regular programming.

Before there are 10 people with "there is a library for that in Python" (because they are not and can not be ergonomic enough):

Next Generation Shell is a "real" programming language. It also has syntax for calling external programs. It handles exit codes properly. It has facility for constructing command line arguments.

Project - https://github.com/ngs-lang/ngs

Motivation related to the above - https://ilya-sher.org/2017/10/10/why-i-have-no-favorite-prog...

edit: ah, yes, NGS also supports command line arguments automatic parsing when main() is called; augmenting this facility would be the sane way to solve the problem.

All we need a C++ build step to really achieve footgun criticality.
That will be fixed by introducing Yamly.
What are some concrete use cases for this?
In my case, I used it to build an all-in-one tool for a local dev environment. It wraps all kinds of operations for starting/stopping things, extracting and modifying data, etc. while providing some useful tips when things go wrong.

At its core it's just interacting with existing software like docker-compose, git, and some internal tools, which I find is still much, much easier to do with shell scripting than "proper" languages.

Have you tried Perl?
I have, and I quite like it! That doesn't seem to be the way most people feel about it though.

I need to build things that pass the bus audit: other people also have to understand them and work on them and, for better or for worse, Bash is a very popular lowest common denominator for many devs.

I usually use Ansible for that. Check it out!
Ansible is awesome, but would largely be overkill for something like this. I'm not doing much more than ensuring a few things are in place, merging a couple files, and then running docker-compose up/down, or exec-ing into running containers to run commands. I certainly wouldn't want people to have to run an entire playbook just to do all this: it's slow, requires even more setup, and is not really well suited for quick CLI-like use.
Like `make`?
make is powerful, but it has some weaknesses. The syntax and macros are complicated to parse and troubleshoot. There are some common gotchas like .PHONY and indentation.

There are of course other alternatives such as `doit`

The parent's use case is exactly what I use make for, with the added benefit that it is already available on developer machines in my org.
Very neat. I have written custom Ruby scripts for this kind of thing in the past. There's also an `sh` library for Python that makes it easier to call external commands inline, although it has some issues in non-trivial cases. Thanks for sharing!
I created bashly to support a simple use case:

When you want to create a bash script - and you choose bash for portability or for whatever reason - and still want to have a decent-looking command line interface, without investing effort in creating argument parsers and usage help.

The examples page shows real-world examples, and per-feature examples: https://bashly.dannyb.co/examples/

I really dislike the animated gif. Let me stare at what it says as long as I want/need to. Not allowing the user to move at their own pace is bad UX.
I really liked it because it drew my attention when I might have skipped over a block of text.

However, I wanted to go back and see what was earlier or view the source input and output. So I would also like it if the contents of the gif was printed out below for easier access.

Well - there is a documentation site if you want to stare... the animated gif is for people who want a "drive-by" look at what it does.
Pretty landing page, but I'm going to be honest, it took me a while to understand what this project does and the gif did not help unfortunately.
Sooo.. it's a yaml-based bash DSL that manually cross-compiles back to .. bash?

It's probably clever, sure, but it seems like this would wind up more declarative than imperative?

No. No DSL.

1. Define your commands + flags + args in YAML (`bashly init` creates this YAML).

2. Bashly generates the standalone script and empty "placeholder" scripts for your actual bash code (`bashly generate`).

3. You plug in your bash code.

4. Bashly merges it all back to the same single final script (`bashly generate`).

5. Rinse and repeat.

The yaml schema is in essence a DSL. It has required terms that have a specific meaning, in this case specific to CLI UX.

What happens when I get to 5 and want to change an arg for cdm/foo? Does step 3 need to be repeated in its entirety?

1. Am I the only one who gets annoyed by the abundance of software being described as "beautiful" (or some other vague, subjective term)? And, honestly, Bash is probably the least "beautiful" "programming language" I can think of.

2. If you need this level of complexity, I feel like you should be reaching for Python or Go or something else that definitely isn't Bash

For 1, I do agree that the term is overused, but in this case it's not really about the beauty of the code itself: it's about the fact that the final generated script acts in a predictable way and prints information and help messages in a format that people are already familiar with. You don't have to write your own usage message: it does it for you, and it looks the way I would expect a usage message to look.

I also see argument 2 a lot, and I've already addressed this in other comments, but sometimes you really just need to call a couple of commands while prepping some env vars or config files for convenience.

In those cases, reaching for Python or Go ends up being a lot of boilerplate for very little advantage, especially when you want to pass control over to other applications once you're done setting things up.

Re 1, the problem is that "beautiful" doesn’t tell you anything useful, other than (being uncharitable) the author having succumbed to tech marketing hype speech.
And then I have to learn Python or Go. Bash is ubiquitous and for the things I'm doing scripting for, something like this would be a pretty good use-case. Usually my scripts start out simple, but then become unwieldy monsters over time. I could use something like Bashly to refactor my monster Bash script to something more manageable.
> 1. Am I the only one who gets annoyed by the...

No you aren't. This irritates me also. Bash is about as beautiful as perl.

> 2. If you need this level of complexity, I feel like you should be reaching for Python or Go or something else that definitely isn't Bash

This is true. Otherwise you risk [in bash] creating something very difficult to maintain for future contributors. The lengths people will go to avoid "programming" can be quite staggering.

If this tool could actually create beautiful bash scripts, that would be quite an accomplishment!
One could make a Venn diagram of positive adjectives used frequently in Hacker News headlines and positive adjectives used frequently by a certain US ex-president.

"Beautiful" would be in the intersection. "Modern" is popular on HN, but not so much with the ex-president.

Since the landing page is not the clearest, you can think of this as an argparse equivalent for Bash.

You provide a YAML file listing commands, subcommands, arguments, and flags, and it automatically generates a Bash script that can parse and validate them, provide help messages, and run your code for each command.

It also lets you keep the actual code for each command and subcommand in separate files, which are merged together into one distributable Bash script at generation time.

It's basically a templating system to auto-generate argument parsing so you don't have to solve that again or deal with things like optparse.

Have you considered submitting your 3 sentences to the project?? Because in the mere moments that it took me to read your 3 sentences i got the gist of what this does instantly! Thanks for providing this, and please do consider submitting this so that others can learn from you and benefit the creator of their app.!
(comment deleted)
I appreciate that this exists. Writing the CLI is the most annoying parts starting a new bash script.
The mistake here is assuming that every shell script needs complex argument parsing, subcommand support, and a verbose usage message. I would even go so far as to say they're _rarely_ needed.
I've used the following to get 80% of the way there

> ${1:?help message}

Using python more these days however

I'm a tiny bit disappointed to see that the tool itself is written in Ruby - writing it in Bash (with a command-line interface that was generated by itself) would be deeply nerdily pleasing to me.

Totally understand why you would write this in Ruby instead though!

Heh. Yeah, this would be a satisfying nerdy accomplishment.

Note there is a docker image if you want to use it without having Ruby.

Idk but this doesn’t sound like a good idea
Although bash-specific, Bashly falls into the "Task Runner" category. As such, I would like to chime in with my entry:

Run : https://github.com/TekWizely/run

It has its own DSL for describing tasks, along with help strings and argument descriptors, and can manages generating help screens, parsing args and invoking tasks (sub-commands).

Each task can be written in its own language, one task could be Bash, one could be zsh, one could be python, etc.

If you're in the market for a flexible task runner, I hope you'll give it a chance.