BCL Preliminary Scenarios and Concepts
Start a list of interesting scenarios where BCL could be a superstar. Also a list of concepts it might have that the scenarios reinforce.
Scenarios
File manipulation
GIT repo manipulation
Abstracting similar applications
In addition to binding a BCL noun verb to different underlying CLI commands on different OSes, BCL should abstract across similar-ish applications on the same OS.
Abstracting package managers
On Ubuntu, app packages come from snap or apt repositories.
In Python, it's pip
; Javascript/Node, it's npm
; Rust, cargo
; go, go
(of course).
Many of these can manage libraries as well as executables. I think the thing for BCL to do is focus on managing executables only. 1) the native app is the only one which can really handle the nuances of libraries and dependencies (e.g NPM updates project.json
as well as install the library) 2) BCL is about command execution, it's OK to limit its functions to that scenario.
BCL should have a single noun, like PACKAGE, or maybe EXECUTABLE. that accesses all currently installed package managers. Installed executables (from any source) should tab-complete as arguments to PACKAGE. (all files in current dir and PATH tab-complete in noun position on command line.)
Abstracting configuration management
One thing that applies to all kinds of apps is the need to manage configuration data. Persisted in Registry, INI, TOML, YAML files, Gnome settings (more files).
/abstractType/ CONFIG LIST /abstractType/ CONFIG GET, SET /pathOfConfigItem/ = /value/
Abstracting Containers, VMs, chroots
(I think there's something here, but can't drill in right now, and cannot talk much about chroots anyway.)
Binding to a thing
What does the developer do to "wrap" a subsystem into BCL?
("raw command" is the underlying native command)
example, binding to files
This one (should be) clear if not simple.
-
class name
The class name is FILES, but maybe DIR and PATHS are aliases. -
instances
The instances (noun s) are individual files (or paths that don't exist yet). You also implement tab-completion and globbing here -
invocation of a native command
You script or configure the various verbs:
file DELETE -->rm _file_
file COPY newFile -->cp _file_ _newFile_
dir LIST or simply LIST -->ls _dir_
The instance names (here, file paths) pass through unchanged.
You map standard option names to some combination of command specific flags and options, or might invoke a completely different raw command.
- parse output, errors and return value If output of command is fed into a pipe, it is parsed into an object. Object could be:
- success (with a number, for Windows)
- error (with a number and maybe text)
- values (by convention a list of objects; but (somehow) a singleton object is iterable (and returns itself, once)).
If output is not fed to a pipe, you get native command's output and error stream.
example, binding to GIT
For GIT, we might decide the class name is REPO (something new). For snap, we should decide to extend the existing class PACKAGE.
- decide what the noun s are. These are instances of class.
For GIT, the noun is a repo path (local directory or remote URI). But maybe there's also a COMMIT class with committish instances and an INDEX thing with instances that are pending changes? - script or otherwise specify how BCL noun verb maps to raw command:
- flag and option names are completely remapped from BCL to native command (e.g )
Scenario: APT upgrade error -- held back package
> sudo
> sudo
To do this manually, I:
- did some SO research to find an article I had read a few times before
- scrolled back to read the failing command,
- manually selected the list of packages held back,
- pasted the list into the augmented
apt upgrade
command.
BCL should have a command history that would have captured that list of packages as a field in the previous response, so I could easily reference it in a subsequent command.
BCL might have command-specific wrappers to handle command error retry this:
- retry the failing command, but don't take any risks.
- retry the failing command, but take some calibrated risks.
This particular apt upgrade error has a rich, reliable history online. You could imagine scripting an command-and-error-specific explanation of the error (referencing the online history) and providing a couple of options for express recovery.
Concepts
History of commands and responses
Xonsh had this, I recall.
Response history
A (durable) history of commands and the corresponding responses.
Response can be indexed by (relatve to now) index. Response can also be indexed by command name (also relative to now). So I can say "the last APT UPGRADE command". Bonus points -- the command name for the index is the same as the command currently being issued.
Response object
Responses wrapped in objects so you can programmatically refer to various interesting fields (after indexing). Means part of integrating an underlying command into BCL is specifying parsing for each and every one of those responses. (Version change of underlying command?)
Command retry
User should be able to refer to previous commands in the history and easily:
- Simply repeat it
- Retry it, based on error from previous attempt
- just retry
- try real hard, accept some side effects of making it work.
- get a whole screed explaining the error and the options for retrying, including links to definitive SO articles or other online references.
Sample syntax:
<selector> <verb> <qualifiers and arguments>
<prev command in history> REDO
<prev command in history with error response> RETRY
<prev command in history with error response> RETRY --FORCE
Shortcuts (to specific long forms above)
- last
<nth>
command - last command with an error
Integrating an external command into BCL
So, there should be a place for a lot of command-specifc scripting for each underlying command that's integrated into BCL. Basically we're talking about making an underlying command into a BCL object, exposing many trait capabilities that BCL knows how to invoke. [[clarify 'trait' vs 'object']]