Hacker News new | past | comments | ask | show | jobs | submit login
Ruby terminal apps toolkit (piotrmurach.github.io)
285 points by pmurach on Jan 28, 2017 | hide | past | web | favorite | 50 comments

Ruby is a fantastic language for writing command line tools. String interpolation and regex are great on it, easy to use OO principles as well as functional principals, etc. Definitely going to be writing wrappers over some of my favorite unix commands with this!

Exactly my view. I'm planning to give a talk about Ruby scripting this year and would welcome any references to the tools that people built with tty. Please get in touch once you have anything to show.

A great toolkit -- there's a bunch of goodies here, but tty-table is amazing, from the sensible API to the configurable ASCII to Unicode renderer. It compares favorably with Hirb, the only other library I know of that draws console tables and supports Unicode box drawing characters.

Regarding tty-table, I have number of things planned including different renderer types to account for more esoteric formats and also very simple formats like tsv(table separate values) etc...

The progress bar gem looks pretty nice. I've been using the similar https://github.com/toy/progress for a long time and it's super useful.

One thing I prefer about progress is that the default config includes an ETA, which is generally the thing I care most about. It's interface is also a little nicer. It's really nice to have an estimate on when a script might complete, so I know if I have to optimize it or if I can just leave it running for a while.

Shameless plug: I wrote a progress bar gem awhile back for that exact use-case: I wanted it to be as simple as possible to use, and show me an ETA for completion. Maybe you'll find this one useful, too.


I was aware of many progress bar libraries before writing tty-progressbar. The reason I ended up coding my own was to have a dead simple codebase - literally one file that does the job well. This makes it easy to maintain and receive contributions. In addition doing job well meant very extensible way to format the progress display, virtually a string with tokens.

I wonder how easy it is to port all those libraries to mruby's mrbgems, so we can easily pack the Ruby-based CLI program as a single binary to get Go-like benefits.

Yeah, building Golang based command line tools is a big bag of pros and cons. There are so many libraries out there for Ruby and Python but having to manage packaging applications written in those languages can be kind of annoying.

Python and Ruby really shine for scripting when the OS already has the packages installed. Otherwise not so much and a mostly self contained binary like Go produces would be better.

What about Traveling Ruby? I've never used it, but it looks promising. https://github.com/phusion/traveling-ruby

Very interesting. I haven't considered mruby but it makes perfect sense. Though I don't know how the situation looks like with regards to standard library? A lot of tty packages use esoteric stuff from Ruby standard libraries including ffi or console modules.

There is still plenty of scripts that I write that are geared towards development workflow. I haven't had issues on setting up these tools on Debian servers, Ruby is usually preinstalled and all you need is bundler to get what you need.

or use something similar to Ruby like Crystal lang

What does everyone suggest for command-line options parsing? This seems to be missing from the gemset and I've never found any of the existing solutions to be very intuitive.

The choice of not writing options parser was very deliberate. As much as it is a tempting proposition I believe there are already great tools around. TTY attempts to provide glue to stitch a lot of scripting needs together without opinionated view on how they should be structured - for now at least ;-)

In my scripting experience I tend to gravitate towards two solutions. If my script is fairly small, e.i. in a single file, with no much complexity I tend to use Ruby standard library optparse. However, if my needs get a bit more complex and I need, for example, subcommands I use thor. Thor gives me a better way to structure my application logic. These two solutions so far have covered all my needs.

Other solutions that I've played in the past are:

* main - very sweet DSL (https://github.com/ahoward/main)

* clamp - (https://github.com/mdub/clamp)

* slop - (https://github.com/leejarvis/slop)

* gli - for Git-like interfaces (https://github.com/davetron5000/gli)

My recommendation before using other libraries would be to really give optparse a good spin so that you can figure out why the other options are more suitable.

Have you looked at Thor? It has amazingly simple interface for commands including short and long forms for flags and hierarchical commands

It's what rails uses by the way!

You can use OptionParser for most basic CLI apps. http://ruby-doc.org/stdlib-2.4.0/libdoc/optparse/rdoc/Option...

There are lots more options here: http://www.awesomecommandlineapps.com/gems.html

To add to the wonderful options already stated here, I wrote a gem once upon a time called "bales" (https://github.com/YellowApple/bales) that provides a reasonably-nice DSL to declaratively define command-line applications (including subcommands up to arbitrary nesting levels) without the complexity of more fully-featured command-line app libraries like Thor and Boson. I haven't done as good of a job at maintaining it as I would've liked, but it works reasonably well and I've used it for quite a few quick-and-dirty command-line programs.

Possibly this: https://github.com/docopt/docopt.rb

I've used the Python version with great success.


OptionParser. It's in the stdlib. Slightly odd API, but it does all the things.

i like trollop; it's a single file you can drop into your project and it makes the common case easy

Slop / stdlib

hand-roll it. a 3-minute programming task doesn't warrant pulling in a graph of dependencies a la leftpad.

But hand rolling is also hard and annoying to support if you want to support long-name options and short name optionals, out of order with potential spaces in odd places that still work as most users will expect them to along with reasonable usage-instruction documetantation.

See comment about Thor

Never do this. There are a basket of edge-cases and weirdness that you'll miss in your three-minute re-implementation that aren't worth that pain you'll have using or debugging later on.

There's a better alternative: don't have complex usage in the first place. You can get all the functionality you want by having multiple executables calling a common library.

Consider netcat. You read the man page, and try to do something following its advice. Often enough, it just doesn't work. Because it's trying to cover a range of unrelated usages through a single entrypoint.

It's easy to set up multiple exes cleanly. Have a non-executable module that contains the functions that your application requires (e.g. call it lib.rb). For each distinct usage, create a separate executable script that imports lib.rb, extracts a, b and c from the for just that usage and then call lib.usage(a, b, c).

Users will find this easy to discover. You will find it easy to maintain, even compared to dedicated parsing DSLs.

We don't special-case functions to do multiple things based on complex argument cases. We just create well-defined functions. We should think of executables in the same terms.

There are really only edge cases in usage models - I've found option libraries all fairly poor, because they expose a global view of the options, rather than an iterator view, for the most part.

If args are in a structure that can be peeked and shifted, you're in a good place for context sensitive options. It's just a lexer.

My tools tend towards this syntax:

    cmd [<global opt>...] subcommand [<local opt>...]
Composing the data structure for this with option libraries is often more work than iterating over a peekable stream of words.

As always this depends. In principle I agree for example I wrote pastel-cli(https://github.com/piotrmurach/pastel-cli) that doesn't use any parser to figure out arguments. However, it's super basic, for anything more complex I would look for more powerful parsers. Lexing command input as much as it is fun can be very thorny issue.

Is there something similar but for Python?

I don't think anything is missing, but you don't get it all in one package.

click ( http://click.pocoo.org/6/ ) has a lot of this stuff in one package, but not everything, eg. composable command lines, progress bars, spinners, prompts, bash completion, colors, paging, launching common applications ($EDITOR) 'n stuff like that.

pyinvoke has a somewhat different focus, but also quite some stuff similar to this.

clint ( https://github.com/kennethreitz/clint ) is another bag of tools, with things like awesome tables, colors, progress bars, ...

The Cement CLI framework for python looks similar: http://builtoncement.com/

lots of cli frameworks around... but most arent as comprehensive or well documented as the OPs.

i personally like plumbum, but its definitely not the same. https://github.com/tomerfiliba/plumbum

+1, would be great to have something like that as an integrated toolkit on the Python (more specifically, Python 3) side. I currently use tqdm for progress bar, but it'd be great to also have a spinner and the rest of the goodies.

Looks modular, well-built and well documented. I'll definitely check it out next I need a terminal app or script. Thanks.

What kind of terminal apps do you write? I havent had the need for one yet and am wondering what this tool is used for.

I have a bunch of scientific data pipelines and have found rake to be an excellent tool for these. Same for a bunch of "housekeeping" scripts.

Rake is seriously underrated I believe. It allows for dependencies and rules, figures out which steps are up-to-date and skips those, allows easy parallelisation etc. Much like make, but with the familiar and sane (ye beautiful) syntax of ruby and its extensive ecosystem.

Maybe not "apps" per se, but my three main use cases in my daily chores are:

* A ruby script that deploys our application

* A ruby script that cleans up the repository after deploy

* A terminal-based git script that runs through all modified files, shows me the diff and allows me to either [c]ommit, [d]iscard changes, [s]kip or [q] before I commit.

That last script is a prime candidate to use those tty-* gems.

I write a lot of internal tools and such, so that is where it's useful (nothing really public facing)

I've used this toolkit. It's pretty well done. The tabular ASCII capabilities tty-table are pretty neat.

Looks promising -- definitely a lot of work went into it. The closest other gem I know of is Ruby ANSI (http://rubyworks.github.io/ansi/#)

Not sure if it's welche here, but I wrote a Seminar lib for PHP:


“welche?” – the German word doesn’t make sense in this context so I presume it’s another autocorrect typo (perhaps “welcome”)? If so, I upvoted your post to show that it is welcome (and useful).

thank you, you're right about "welche"->"welcome

s/Seminar/similar/ (damn autocorrect :))

Ruby apps are by far the most time consuming to configure and install. Nothing is simple. Nothing just works.

The whole idea of exposing end users to your apps's depencies and compilation is a broken user hostile model. The potential rabbit hole of versions incompatibilities and mismatches is a time sink that cannot be justified.

Go is by far the simplest hassle free deploy followed by PHP and Python. For a unix command line tool that seeks a userbase beyond Ruby users Go or Python would be the most user friendly choice.

Many systems come preinstalled with Ruby. Bundler is a very elegant and simple solution - I don't think it is hostile. Quite often the tools that we build are written by developers for developers or system administrators. For example Puppet or Chef. In my experience, these are people how don't mind running couple commands to get started. If anything I have heard people say really positive things on how easy and pain free installation is. Of course, if you want to write portable code that works on any system then Go is a very wise solution.

Ok neat, but Ruby needs a serious and modern GUI toolkit!

Registration is open for Startup School 2019. Classes start July 22nd.

Guidelines | FAQ | Support | API | Security | Lists | Bookmarklet | Legal | Apply to YC | Contact