Go to file
2022-03-05 19:21:40 -05:00
.github Add GitHub sponsorship info 2022-02-17 23:17:05 -05:00
check Add check.IsDir 2022-02-25 23:28:43 -05:00
comp Complete golden comp.File completer 2022-02-27 01:34:51 -05:00
each Add each package to replace loop 2022-02-26 19:35:57 -05:00
filt Drop loop 2022-02-27 02:02:28 -05:00
fn Improve organization of functional packages 2022-02-27 01:17:49 -05:00
inc Add scan.R.Parse*, z.P->z.Y, z.P for parse 2022-03-04 21:20:54 -05:00
json Add PrintAsJSON interface 2022-03-02 03:11:09 -05:00
mapf Improve organization of functional packages 2022-02-27 01:17:49 -05:00
maps Improve organization of functional packages 2022-02-27 01:17:49 -05:00
scan Start factor Expect into methods instead 2022-03-05 08:20:10 -05:00
set Factor out functional (fn), sets, loops 2022-02-25 21:46:36 -05:00
term Add full term attribute support 2022-02-28 13:37:00 -05:00
tools Add tools including goprintasjson vim filter 2022-03-02 03:13:53 -05:00
tree More BPEGN additions and examples 2022-03-03 19:06:12 -05:00
typ Fix typ package name 2022-03-01 04:27:16 -05:00
util Add util.Stack 2022-03-05 19:21:40 -05:00
bonzai_test.go Add variadic completer arguments and clean 2022-02-24 20:21:39 -05:00
bonzai.go Add variadic completer arguments and clean 2022-02-24 20:21:39 -05:00
cmd_test.go Move cmd/ to inc/ for consistency 2022-02-27 18:31:40 -05:00
cmd.go Drop loop 2022-02-27 02:02:28 -05:00
CONTRIBUTING Add legal stuff 2022-02-17 17:47:28 -05:00
doc.go Shorten legal stuff 2022-02-19 19:22:03 -05:00
go.mod Add go.mod 2022-02-14 22:58:43 -05:00
go.work Add go.work (i <3 1.18) 2022-02-17 18:11:27 -05:00
LICENSE Add legal stuff 2022-02-17 17:47:28 -05:00
README.md Update information about BPEGN 2022-03-02 21:34:00 -05:00

Bonzai! Dominate the Command Line

Go Version GoDoc License Go Report
Card

Installation

🎉 Bonzai shamelessly requires Go 1.18+ 💋

  1. Install Go 1.18 and the tooling your require for it
  2. go install github.com/rwxrob/bonzai@latest
  3. import "github.com/rwxrob/bonzai"
  4. Consider using the template to get started

😎 Yes, we use the wonderful new generics all over. 👍

Welcome to Bonzai

Yes, "banzai" is something people yell going into battle. But isn't that what making command line utilities in Go (instead of your favorite shell script) actually is?

And yes, "bonsai" trees are well-manicured, meticulously crafted, miniature trees that rival their larger cousins, just like Bonzai command and data node trees. They are unlike anything you've probably encountered so far, no getopt dashes (we kind of hate them), no ugly commander interface to learn, no 12637 lines of shell tab completion bloat to source before your command will complete, just well manicured nested-tab-complete-with-magical-aliases-enabled commands organized into rooted node trees for your command-line enjoyment. Your right-pinky will be particularly grateful.

But wait, there's more! What about all those other tasks you need to do to make a command line application honorable in anyone's eyes? Tools are needed.

BPEGN: Generate Powerful Parsers Easily

BPEGN is a PEGN syntax implementation in pure Go using mostly slices and structs. The Bonzai scan.Expect function produces verbose, specific error messages that will make your users bow to your attentiveness. Build complex parsers that are easily read and generated from any number of meta-languages including PEGN, PEG, EBNF, and ABNF. Spend your time working with the beautiful and standardized abstract syntax trees instead of grinding out parser code. Domain language specifications are a breeze, which is good, because you can customize any completer for any nested command node or your application enabling powerful, intelligent, and intuitive grammars you enable for your users directly from the command line, hell, why not directly from your favorite chat integration. After all, Bonzai commands are perfectly doable directly from a chat client.

A JSON Package Without Unnecessary Limitations

The standard Go json package is not what most people want. It uses reflection which unnecessarily slows everything down, and produces marshaled JSON output that escapes every single Unicode character making the output impossible to read and virtual useless for any use with languages that depend heavily on Unicode. It's really unfortunate since the JSON standard fully supports Unicode characters as they are. Bonzai JSON overcomes these limitations and is used to marshal everything in the module and fulfill all fmt.Stringer interfaces as 2-space indented JSON instead of Go's virtually unusable default string marshaling format.

Why have we put all of this stuff into one module? It's simple, if you understand how enterprise software legal teams work. They are required to track the legal pedigree of every single package that is included into any software project. This task is laborious enough and we have done everything to simplify it by providing most of the parts and tools you would need to create almost any command-line utility, from simple bash script port to monoliths with 100s of composed commands, even our own BusyBox-like container Linux distro.

Embedded Text or Web Docs FTW!

And, all the documentation for your command tree goes inside the binary (if you want). That's right. Portable, text or web-enabled "man" pages without the man page. You can use one of the composable interactive-color-terminal-sensing help documentation commands like help.Cmd that will easily marshal into JSON, or text, or well-styled HTML locally while enabling you to write your embedded docs in simplified CommonMark. Think "readthedocs" but without the Internet dependency. And if you don't want help.Cmd you don't need it. You can even write your own composable Bonzai command or pick from a rich ecosystem of embeddable Bonzai command trees available from anywhere on the Internet or maintained by the Bonzai project. No registries to worry about. Just use good 'ol Go module imports are all that are need to share your creations.

Contributors/PRs Welcome

... especially for "Completers" and Runtime Detection.

Speaking of sharing, why not send a PR for your addition to the ever growing collection of comp subpackage Completers for everything from days of the week, to tab-driven inline math calculations, to a list of all the listening ports running on your current system.

CONTRIBUTING

"It's spelled bonsai/banzai."

We know. The domains were taken. Plus, this makes it more unique and easier to find once you know the strange spelling we chose to use. Sorry if that triggers your OCD.

If you must know, the primary motivator was the similarity to a well-manicured tree (since it is for creating trees of commands). And Buckaroo Banzai was always a favorite. We like to think he would use Bonzai today to make amazing things.

On a lighter note, it just so happens that "banzai" means 'a traditional Japanese idiom meaning "ten thousand years" of long life,' a cheer used in celebrations. So combining the notion of a happy, little, well-manicured, beautiful tree and "ten thousand years of long life" works out just fine for us.

It turns out that the "call to war" associated with Bonzai is not entirely without merit as well. Bonzai makes short work of creating offensive and defensive tool kits all wrapping into one nice Go binary, popular for building single-binary Linux container distros (like BusyBox and Alpine, watch for Bonzai Linux soon), as well as root kits, and other security tools

What People Are Saying

"It's like a modular, multicall BusyBox builder for Go with built in completion and embedded documentation support."

"The utility here is that Bonzai lets you maintain your own personal 'toolbox' with built in auto-complete that you can assemble from various Go modules. Individual commands are isolated and unaware of each other and possibly maintained by other people." (tadasv123)

Example GitHub Template

https://github.com/rwxrob/bonzai-template

Design Considerations

  • Promote high-level package library API calls over Cmd bloat. Code belongs in package libraries, not Cmds. While Bonzai allows for rapid applications development by putting everything initially in Cmd Methods, Cmds are most designed for documentation and completion, not heavy Method implementations. Eventually, most Method implementations should be moved into their own package libraries, perhaps even in the same Go module. Cmds should never be communicating with each other directly. While the idea of adding a Channel attribute was intriguing, it quickly became clear that doing so would promote too much code and tight coupling --- even with channels --- between specific commands. Cmds should be very light. In fact, most Cmds should assign their Method directly from one matching the Method function signature in a callable, high-level library.

  • Only bash completion planned. Zsh, Powershell, and Fish have no equivalent to complete -C (which allows any executable to provide its own completion) This forces inferior dependencies on overly verbose external "completer" scripts written in only those languages for those specific shells. This dependency completely negates any possibility of providing modular completers and composable commands that carry their own completion logic. This one objective fact alone should give every pause before opting to use one of these inferior shells for their command line interactions. Bonzai commands leverage this best-of-breed completion functionality of bash to provide an unlimited number of completion methods and combinations. The equivalent implementations, perhaps as an export collected from all composed commands providing their shell equivalent of completion scripts, would be preposterously large (even though kubectl requires 12637 lines of bash just for its basic completion). Bonzai uses Go itself to manage that completion --- drawing on a rich collection of completers included in the standard Bonzai module --- and provides documented shortcut aliases when completion is not available (h|help, for example).

  • Bonzai commands may default to shell.Cmd or help.Cmd These provide help information and optional interactive assistance including tab completion in runtime environments that do not have complete -C foo foo enabled.

  • Scanner implementation as a struct with no interface. In order to better tilt the scale toward Scanner performance the decision was made to keep it as a struct with tight coupling to the scanner.Cur and scanner.Pos structs as well.

  • Decided to use branch/leaf instead of parent/child. The anthropomorphic metaphor breaks down when choosing names for "children" who don't have any any children of their own. What, are we going to call them "barren"? The only other option is "terminal" (the mathematically correct term) and mixing that just should bad. "This child is 'terminal'" while the others are not. Besides, the bonsai tree is one of our namesakes and you cannot have a branch and a leaf in the same node. Every node is one or the other. Trees are much simper to grok and walk this way.

Style Guidelines

  • Everything through go fmt or equiv, no exceptions
  • In Vim set textwidth=72 (not 80 to line numbers fit)
  • Use /* */ for package documentation comment, // elsewhere
  • Smallest possible names for given scope while still clear
  • Package globals that will be used a lot can be single capital
  • Must be good reason to use more than 4 character pkg name
  • Avoid unnecessary comments

Acknowledgements

The https://twitch.tv/rwxrob community has been constantly involved with the development of this project, making suggestions about everything from my use of init, to the name "bonzai". While all their contributions are too numerous to name specifically, they more than deserve a huge thank you here.

  • Quint
  • Greg

Copyright 2022 Robert S. Muhlestein (mailto:rob@rwx.gg)
SPDX-License-Identifier: Apache-2.0

"Bonzai" and "bonzai" are legal trademarks of Robert S. Muhlestein but can be used freely to refer to the Bonzai project https://github.com/rwxrob/bonzai without limitation. To avoid potential developer confusion, intentionally using these trademarks to refer to other projects --- free or proprietary --- is prohibited.