mirror of https://github.com/rwxrob/bonzai
Move design.md to book
parent
d219f79b9f
commit
4ad14d6290
@ -1,278 +0,0 @@
|
|||||||
# Style and Design
|
|
||||||
|
|
||||||
* Use "deciduous tree" emoji 🌳 to mark Bonzai stuff
|
|
||||||
* 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
|
|
||||||
* Favor additional packages (possibly in `internal`) over long names
|
|
||||||
* 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
|
|
||||||
|
|
||||||
## Design Considerations
|
|
||||||
|
|
||||||
Here is a summary of the thinking behind important design decisions
|
|
||||||
when creating Bonzai.
|
|
||||||
|
|
||||||
### 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 Call first-class function, Cmds are most
|
|
||||||
designed for documentation and completion, not heavy Call
|
|
||||||
implementations (even though many will organically start there from
|
|
||||||
people's personal Bonzai trees).
|
|
||||||
|
|
||||||
Eventually, most Call implementations should be moved into their own
|
|
||||||
package libraries, perhaps even in the same Go module. Cmds should
|
|
||||||
*never* communicate with each other directly (other than calling one
|
|
||||||
another on occasion). While the idea of adding a Channel attribute was
|
|
||||||
intriguing, it quickly became clear that doing so would promote
|
|
||||||
undesirable tight coupling --- even with channels --- between
|
|
||||||
specific commands.
|
|
||||||
|
|
||||||
### Cmds should be very light
|
|
||||||
|
|
||||||
Most Cmds should assign their first-class Call function to one that
|
|
||||||
lightly wraps a similar function signature in a callable, high-level
|
|
||||||
library that works entirely independently from the bonzai package.
|
|
||||||
It's best to promote strong support for sustainable API packages.
|
|
||||||
|
|
||||||
### Only bash completion and shell.Cmd planned
|
|
||||||
|
|
||||||
If it doesn't work with `complete -C` or equivalent then just run the
|
|
||||||
Bonzai command tree monolith as a temporary shell (shell.Cmd) and use
|
|
||||||
its cross-platform support for tab completion.
|
|
||||||
|
|
||||||
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 everyone 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 just for its
|
|
||||||
basic completion tree). Instead, 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.
|
|
||||||
|
|
||||||
### Target users replacing shell scripts in "dot files" collections
|
|
||||||
|
|
||||||
By creating a `cmd` subdirectory of a dot files repo a multi-call
|
|
||||||
Bonzai command named `cmd` can be easily maintained and added to just
|
|
||||||
as quickly as any shell script. This has the added bonus of allowing
|
|
||||||
others to quickly add one of your little commands with just a simple
|
|
||||||
import (for example, `import github.com/rwxrob/dot/cmd` and then
|
|
||||||
`cmd.Isosec`) from their own `cmd` monoliths. This also enables the
|
|
||||||
fastest possible prototyping of code that would otherwise require
|
|
||||||
significant, problematic mocks. Developers can work out the details of
|
|
||||||
a thing just as fast as with shell scripting --- but with the power of
|
|
||||||
all the Go standard library --- and then factor out their favorites as
|
|
||||||
they grow into their own Bonzai command repos. This approach keeps "Go
|
|
||||||
on the brain" (instead of having to port a bunch of bash later) and
|
|
||||||
promotes the massive benefits of rapid applications development the
|
|
||||||
fullest extent.
|
|
||||||
|
|
||||||
### Use either `foo.Cmd` or `cmd.Foo` convention
|
|
||||||
|
|
||||||
People may decide to put all their Bonzai commands into a single `cmd`
|
|
||||||
package or to put each command into its own package. Both are
|
|
||||||
perfectly acceptable and allow the developer making the import to
|
|
||||||
alias the packages as needed using Go's excellent package import
|
|
||||||
design.
|
|
||||||
|
|
||||||
### Default capital "Z" import name
|
|
||||||
|
|
||||||
People can easily change the default "Z" import name to whatever else
|
|
||||||
if they don't like it (or worse, if has conflicts). But, we actually
|
|
||||||
want naming conflicts even though this seems counter-intuitive.
|
|
||||||
Developers should be putting most of their code into their own `pkg`
|
|
||||||
libraries and calling into them from their wrapping Bonzai trees and
|
|
||||||
branches that import Z. If someone is importing Z into their package
|
|
||||||
library they are likely doing something they shouldn't. Bonzai should
|
|
||||||
*only* be imported into the composable branch or standalone command
|
|
||||||
(`main`). This is a reminder as well to Bonzai developers not to stuff
|
|
||||||
things into the Z package that would never be used outside a Bonzai
|
|
||||||
command, tree or `main.go` standalone.
|
|
||||||
|
|
||||||
### Promote lower "z" personal Bonzai trees
|
|
||||||
|
|
||||||
Just as "dotfiles" has become a convention, use of the simple "z"
|
|
||||||
GitHub repo should be promoted as a common, "ez" way to find people's
|
|
||||||
personal monoliths. Obviously, people can use what they want. This is
|
|
||||||
also consistent with the capital "Z" import name of the `bonzai`
|
|
||||||
package.
|
|
||||||
|
|
||||||
### Use simple regular expressions for usage
|
|
||||||
|
|
||||||
Bonzai takes a fundamentally different approach to the command line
|
|
||||||
and usage documentation. Any command line is a minimal domain specific
|
|
||||||
language. As such, usage notation simple is not enough. Regular
|
|
||||||
expressions allow the quick understanding of what is allowed and
|
|
||||||
should become mandatory learning in a world of minimal domain specific
|
|
||||||
grammars. Only the most basic regular expressions are required to
|
|
||||||
produce rich usage strings for any Bonzai command. However, those
|
|
||||||
wanting traditional usage notation can easily override the
|
|
||||||
`DefaultUsageFunc` with their own.
|
|
||||||
|
|
||||||
### Prioritize output to VT100-compatible terminals
|
|
||||||
|
|
||||||
Every modern terminal supports VT100 compatibility. If it doesn't,
|
|
||||||
people should just not use it. This means emphasis and formatting are
|
|
||||||
dependent on the [`rwxrob/term`](https://github.com/rwxrob/term)
|
|
||||||
package for the main output. Bonzai tree developers will likely want
|
|
||||||
terminal output helpers more than anything (yes even web rendering).
|
|
||||||
|
|
||||||
### Secondary output to local web browser
|
|
||||||
|
|
||||||
Bonzai will eventually provide the option to enable use of the local
|
|
||||||
web browser instead of terminal output for help and other
|
|
||||||
documentation output. This will allow graphic application executables
|
|
||||||
to simple be double-clicked from graphic desktops. Bonzai will ship
|
|
||||||
with an embedded web template for such applications, but will also
|
|
||||||
allow users to granularly customize their own modifications to the
|
|
||||||
default theme. Bonzai branch creators are encouraged to provide
|
|
||||||
downloadable themes in this regard. In this way, Bonzai will provide
|
|
||||||
the web shell to encapsulate other web applications.
|
|
||||||
|
|
||||||
### Prefer local web apps over other GUI platforms
|
|
||||||
|
|
||||||
While it is obviously possible to create any graphic application with
|
|
||||||
Bonzai, the creation of localized web applications should be the
|
|
||||||
preferred convention of the Bonzai GUI applications community. This
|
|
||||||
simplifies application development and takes aim at bloated
|
|
||||||
alternatives that embed full GUI web clients (such as Electron) while
|
|
||||||
still providing a rich terminal interface for those who prefer it.
|
|
||||||
Every Bonzai binary is its own local web server which Go's rich
|
|
||||||
standard library to draw on.
|
|
||||||
|
|
||||||
### []Section instead of map[string]string for Other
|
|
||||||
|
|
||||||
This allows composition notation and ensures the author has control of
|
|
||||||
how the Other sections appear.
|
|
||||||
|
|
||||||
### Move `help.Cmd` into its own package
|
|
||||||
|
|
||||||
Although it breaks backward compatibility for many applications
|
|
||||||
updating between `v0.1` and `v0.2` the decision to put `help.Cmd` into
|
|
||||||
it's own Bonzai branch git repo was the right one. It is now on equal
|
|
||||||
footing with every other potential Bonzai branch and can keep its
|
|
||||||
`Version` in sync with Git version (as all Bonzai branches should). It
|
|
||||||
is highly likely that GUI/web/hybrid help commands will be preferred
|
|
||||||
by some and including one over another --- when not used --- ends up
|
|
||||||
just being unnecessary bloat. This also serves to clarify that the
|
|
||||||
legal information is related to that specific `help.Cmd` Bonzai branch
|
|
||||||
and not Bonzai itself. It's conceivable that another `help.Cmd`
|
|
||||||
creator may wish another legal agreement.
|
|
||||||
|
|
||||||
### Leave hidden default command params
|
|
||||||
|
|
||||||
When the default command is invoked any of it's params will be
|
|
||||||
automatically passed as if the command specified them. But they are
|
|
||||||
not included in the tab completion. This is because there will
|
|
||||||
inevitably be conflicts between default command params and other
|
|
||||||
potential completions at that level for other commands. Rather than
|
|
||||||
disable this, or add tab completion, it was decided to keep them as a
|
|
||||||
useful shortcut side-effect without calling direct attention to them.
|
|
||||||
When and if dependencies on them become an issue it can be addressed
|
|
||||||
then.
|
|
||||||
|
|
||||||
### Not exporting Dynamic FuncMap builtins
|
|
||||||
|
|
||||||
Since those builtins will land in `mark` subpackage eventually, don't
|
|
||||||
want to build any dependencies on them now that will break. The
|
|
||||||
builtins themselves can obviously be used immediately and has a much
|
|
||||||
smaller chance of changing in the future.
|
|
||||||
|
|
||||||
### Custom errors as package globals
|
|
||||||
|
|
||||||
When it became clear that there are a number of canned error
|
|
||||||
conditions that we want to allow Cmd developers to use quickly and
|
|
||||||
easily, and that not all of them directly relate to a particular Cmd
|
|
||||||
(`x`) is was decided to move all errors into a central `errors.go`
|
|
||||||
file as package global custom error structures that implement `error`
|
|
||||||
interface (`Error() string`) and have concrete, public fields so that
|
|
||||||
composition notation can be used (instead of forcing an unnecessary
|
|
||||||
function call). The benefits of custom errors that can be interrogated
|
|
||||||
with the `errors` functions are obvious and this also consolidates
|
|
||||||
most English language usage for later when we add full
|
|
||||||
language-by-locale support.
|
|
||||||
|
|
||||||
Note that this was a breaking change (added in `v0.10.0`) with
|
|
||||||
high-impact because so many have hard-coded `x.UsageError` (which is
|
|
||||||
why the full `v1.0` is not expected until December 25th 2022, some
|
|
||||||
months after things should feel settled and finished).
|
|
||||||
|
|
||||||
### Move package global Aliases/Shortcuts into Cmd
|
|
||||||
|
|
||||||
In Cmd they can be documented. They also tend to be long and eat up
|
|
||||||
too much of the command line when using them with completion. Better
|
|
||||||
to just have them in the help docs to lookup when the full path is
|
|
||||||
wanted.
|
|
||||||
|
|
||||||
### Allow dashes, but discourage
|
|
||||||
|
|
||||||
Being able to put a command anywhere in the commands tree path of
|
|
||||||
arguments will never be allowed since it is fundamentally against the
|
|
||||||
entire raison d'etre of Bonzai. We want people to memorize specific
|
|
||||||
paths and create the occasional alias and shortcut, not just through
|
|
||||||
whatever onto the command line hoping it will work. This is why `getopt`
|
|
||||||
things are so problematic, they all deal with the "end of options and
|
|
||||||
switch" and the "beginning of arguments" differently. Not Bonzai, where
|
|
||||||
the arguments are *always* consistent as well as the command paths.
|
|
||||||
Because of this, dashes should never be used by any Bonzai command or
|
|
||||||
alias. In fact, the only time a dash will exist is when passing on
|
|
||||||
arguments to the underlying command shell. For example, when delegating
|
|
||||||
to `gh` which requires it (although every effort should be made to
|
|
||||||
remake the entire UI for such things to be Bonzai friendly).
|
|
||||||
|
|
||||||
However, the no-getopt approach is so foreign to those training in
|
|
||||||
decades of this insanity that we need to support dashed aliases (and
|
|
||||||
other options) that will be intuitive to these people for a very long
|
|
||||||
time. Of particular note are things like `-h`, `--help`, `-help`, and
|
|
||||||
`/?` all of which are indelibly marked into most of our muscle memory.
|
|
||||||
will be intuitive to such people. The addition of support for aliases
|
|
||||||
that begin with dashes --- but that do not appear in the help
|
|
||||||
documentation --- is specifically to address this issue. Like all
|
|
||||||
aliases, the bash shell will dynamically change the `-h` into `help`
|
|
||||||
when the user taps tab prompting them with the correct word, but, also
|
|
||||||
like all aliases, if they execute the command with `-h` it will just
|
|
||||||
work.
|
|
||||||
|
|
||||||
Allowing dashed aliases does carry the risk that some will permanently
|
|
||||||
use them in their scripts. But not allowing them in most help
|
|
||||||
documentation should be enough to discourage it. Theoretically, it is
|
|
||||||
entirely possible to create a Bonzai command that does parse its
|
|
||||||
arguments and parameters using getopt notation. Having this freedom is a
|
|
||||||
part of FOSS and for those who insist is supported. It is simply
|
|
||||||
strongly discouraged by the Bonzai project itself which will make
|
|
||||||
specific design decisions based on the assumptions that dashes are never
|
|
||||||
used in command names.
|
|
||||||
|
|
||||||
### Abandon plans for Bonzai "shell" and double-dash pipes
|
|
||||||
|
|
||||||
At one point the thought that allowing a PipeToken to be set would allow
|
|
||||||
an internal unix-like pipeline construct in the Shortcuts as well as
|
|
||||||
from the command line, which would easily be expandable into its own
|
|
||||||
scripting language, but these plans have been abandoned for the sake of
|
|
||||||
simplicity and anti-bloatware. We want to encourage creation of other
|
|
||||||
commands that combine the input and output in their own ways and have
|
|
||||||
added `Input io.Reader` instead. Commands can check this in addition to
|
|
||||||
checking for `args` to determine what to do with such input.
|
|
Loading…
Reference in New Issue