These are new command ideas for LIBGED.
Keep them sorted alphabetically.
They are not all vetted.
Be specific.

--- REFACTORING ---

* merge prcolor, color, hsv_to_rgb, and rgb_to_hsv commands

* merge bot_* commands into bot command subcommands

* merge get_eyemodel's functionality as "view eyemodel" sub-command

* convert garbage_collect Tcl to libged.  naming options include
  "compact", "purge", "compress". possibly as subcommand to "db".
  possible generalization to remove unused/unreferenced objects of
  particular type (e.g., prims, combs, regions, all).

* some common shorthand aliases from Dwayne
  ** smk -- make --edit
  ** scp -- copy --edit


--- NEW COMMANDS ---

* 'about' command: display version, contents of various doc files,
  customizable brlcad.msg file.  could also report summary information
  about the currently displayed geometry (possibly as a 'stats'
  command alternatively).  this would include the number of objects,
  types of objects, triangle counts, surface counts, extents, classes
  of geometry representation types used, and potentially more.
  options to disable version or object info.  consider merging with
  'summary' command.  provide option for writing results out to a
  file.

  loosely related, would be useful to have some command (e.g., "fs"
  command) that reports extrinsic capacity such as amount of disk
  space remaining where current .g or db cache files are housed,
  memory allocation sizes, object cache size, cache utilization, etc.

* 'align' command: taking a from 3d pt and a to 3d pt target.
  moves/rotates the source object into alignment.

* 'analyze' command: add per-face analysis of primitives like tgc, arb
  to their respective analyze commands in libged.  See end of file for
  some thoughts on a more ambitious re-think about the analyze command,
  but bear in mind that these are preliminary thoughts only and not a
  finished design that is ready to be implemented.

  Consider inside/on/outside subcommands that report back where a
  given point is with respect to another object.  Could use ray
  tracing to determine result.

  Consider a subcommand that reports distance to surface from a given
  point.  Ray tracing method similar to gqa (shooting spherically
  through point and in a gqa-style grid) would give an approximation
  that could be adaptively refined to a specified tolerance.

* 'array' command: to create a shallow copy of geometry in a
  rectangular or polar pattern.  similar to clone, perhaps mergeable
  with clone as an option.  takes #rows+dist and #cols+dist, or
  centerpt+#items and angle <360 to fill, angle between items, rotate
  each item boolean.

* 'batch' command: apply a given command template to all lines in a
  given input text file.  could be very similar to exec but instead of
  inspecting the current .g, it walks lines in file(s).  this would
  let you do things like:

  # same as mvall -f file.txt
  batch file.txt -exec "mvall {*}"

  # create an alternate hierarchy based on some mapping file
  batch -m line file.txt -exec "g {line}"

  # for all lines in 3 files, kill first symbol, rename second to it
  batch A.txt B.txt C.txt -exec "kill {1}" -exec "mv {2} {1}"

  # keep all objects in an edcodes file with region ID > 1000
  batch A.txt -field 2 -ne 1000 -exec "keep subset.g {5}"

  # for all regions, if they are listed in file.txt, add them to a
  # parent assembly and set a specified material ID
  search . -name "*.r" -exec batch -m line file.txt -field 1 -eq {} -exec "g {1} {}" -exec "mater {} {3}" ;

  # run awk, get 4th column, run sed to change name from r123 to 123.r,
  batch file.txt -awk '{print $4}' -sed 's/^r(.*)/\1\.r/g' -exec "mv {1} {$}"

  # outside of MGED, the above would have been similar to:
  cat file.txt | awk '{print $4}' | sed 's/^r(.*)/r\1 \1\.r/g' | xargs mged test.g mv

  The command becomes more of a stream processor on the input file, as
  if piped on the shell line.  To embed awk, sed, cut, see qse:
	  https://github.com/hyung-hwan/qse

  Batch needs some syntax like $*, $1, $2, or {*}, {1}, {2}, etc., to
  represent file columns (in a poor man's awk fashion) and search
  simply using "{}" as the object name replacement marker (unless we
  specify a -m {marker_name}).  Using the same positional markers will
  help keep the interface consistent for the user, but it will require
  forethought on how batch interfacts with the search and repeat
  commands.

* 'calc' command: geometry calculator for scalar values, points,
  vectors, and maybe matrices.  units aware with options for
  converting between units, angles, with support for std funcs like
  sin, cos, log, abs.  also supporting view values, points on a line,
  normals, distances, ... powerful calculator for those places where
  the user needs some value we don't display for them (like needing to
  calculate a distance between two nirt rays, or something that always
  prints mm, or a command that print radians instead of
  degrees). basically a geometric version of 'expr'.  alternate names
  include calc, gcalc, expr, gexpr, gc.  merge with "units_conversion"
  command.

  List of calc-related commands currently supported that may need to
  become sub-commands:

    bn_dist_pt2_lseg2
    bn_isect_line2_line2
    bn_isect_line3_line3
    mat_mul
    mat_inv
    mat_trn
    matXvec
    mat4x3vec
    mat4x3pnt
    hdivide
    vjoin1
    vblend
    mat_ae
    mat_ae_vec
    mat_aet_vec
    mat_angles
    mat_eigen2x2
    mat_fromto
    mat_xrot
    mat_yrot
    mat_zrot
    mat_lookat
    mat_vec_ortho
    mat_vec_perp
    mat_scale_about_pt
    mat_xform_about_pt
    mat_arb_rot
    quat_mat2quat
    quat_quat2mat
    quat_distance
    quat_double
    quat_bisect
    quat_make_nearest
    quat_slerp
    quat_sberp
    quat_exp
    quat_log

* 'cg' command: "compile" i.e., evaluate and cache results of geometry
  computations for improved performance.  this could be a variety of
  cache-worthy actions such as wireframes at given levels of detail,
  raytrace prep results, default tessellations, geometry validation
  (see 'glint' command), or shape analysis (surface area, volume,
  moments of inertia, etc).

  'glint' / 'rtcheck' / 'audit' functionality: determine if the model
  is valid, provide option(s) to fix any errors encountered.  this
  could be a refactoring or calling of glint and/or other tools.  this
  ideally needs to separate geometric validation (e.g., defines a
  solid volume, no overlaps) from policy/business/convention
  validation (e.g., uses proper naming convention, unique region IDs),
  possibly providing predefined auditing profiles similar to nirt's
  predefined output formats.


* 'edit' command: review and test so we can replace oed+tra/sca/rot
  functionality consistently in libged as translate/scale/rotate with
  a signature similar to (review this against what the edit command
  ended up with):

  {translate|rotate|scale} [--keypoint {bb_corner|bb_center}:\
    {object_name} | {3d position}] [--relative xdist [ydist [zdist]] \
    | --absolute xpos [ypos [zpos]]] object_name(s)

  where 'oed' is basically converted into the --keypoint option and
  object(s) to work on.

* 'image' command: import/export an image.  similar to 'text' command,
  need option to crop, position, scale, and orient the image.  should
  default to a view-oriented "underlay" but permanently stored in the
  .g file as a proper image object (top-level TODO entry).

* 'import' and 'export' commands: import/export image, text, csv, and
  other file types.  possibly catch-all alternative to keep/dbconcat
  that could also work for importing other data files as objects.  a
  specific use-case needed is ability create/import combinations that
  are described in a text file in some specific structured format
  (e.g., sysdef or regmap) that would be good to generically support.

* 'gsort' or 'tables' or 'filter' command.  Distinction is that this
  comamnd is object-aware and can process geometry by name in a given
  column or list.  This way, one could sort output from search, nirt,
  idents, and other table/list-based commands. Examples:

  Sort by data size: [gsort -size [search .]])
  Reverse sort of col4 by vol: [gsort -volume -k4 -r [search .]])

  Desirable to intentionally pattern after POSIX sort
  (https://pubs.opengroup.org/onlinepubs/9699919799/utilities/sort.html),
  adding geometry extensions similar to BSD sort(1).

* 'layer' command: to create, select, delete, list enable/disable
  on/off, lock/unlock, and set other properties (e.g., color, style).
  need subcommand(s) to move geometry to/from layers, perhaps
  implemented as combs with a special flag like regions.

* 'env' command.  Reports bu_dir style path information, memory, user,
  date/time information.

  'memory' sub-command: reports memory and disk usage statistics.  for
  out-of-core memory (disk), report amount of available disk space,
  cache object / scratch space, and geometry file size.  for in-core
  memory, report virtual memory allocation size, % resident, total
  memory available, swap size, page faults, swap writes, etc.
  Obviously need libbu infrastructure for many of these features.
  merge prmem command.

* 'menu' command: to load/unload menu descriptions from a file
  (e.g. file.mnu) where we bind text, icons, images, descriptions, and
  key bindings to actions.  would serve as a place to move
  existing menu-related commands (e.g., press command becomes
  subcommand) and allow for interface customization.

* 'offset' command: given an input 3D volume, constructs an interior
  or exterior surface.  this can be used to expand or hollow out an
  object.  probably implementable as 1) get brep tree, 2) evaluate
  brep, 3) expand/shrink per offset, 4) optionally apply boolean.

  # expand and hollow a sphere
  make sph sph
  offset sph 1.0 sph.bigger
  comb hollow_sph.c u sph.bigger - sph

  # hollow an object
  offset piston -5.0 piston.interior
  comb hollow_piston u piston - piston.interior

  # hollow object, perform edit
  offset piston -1.0 piston.interior piston.old
  # piston is now "u piston.old - piston.interior"

* 'pipe from' subcommand that generates a pipe given an input object
  (e.g., a BoT mesh).  Candidate synopsis:

  pipe from {input.object} [-s startpt] [-e endpt] [-n npts] [output.pipe]

  So that would look something like this in mged/archer:

  mged> pipe from shaft4.bot
  or
  mged> pipe from shaft4.bot my_new.pipe
  or
  mged> pipe from -file shaft4.stl -s 1.3 3.21 9123.2 -e 1.3 3.21 0 shaft4.s
  etc

  This would allow the command to be extended to other input sources
  or primitive types, but a default implementation could simply
  tessellate the input object and work generically with a mesh form
  under the hood.  Using ray tracing instead of mesh for calculating a
  centerline is also a possibility.

  Note the motivating need consists of only linear pipes without any
  turns/bends/curves, but with changing inner/outer diameters.

* 'redo' command: redoes the previous undone command(s).  Basically
  move forward in an undo chain.  See undo below.

* 'reduce' command: to perform model reduction.  should perform
  automatic simplification of geometry to reduce complexity by
  (potentially) orders of magnitude.  this is level of detail for
  non-viewing purposes, for export.  possibly automatable by replacing
  leave-node geometry with bounding box (arb8s), but collapsing and
  combining up the hierarchy to a prescribed tree depth.  however, it
  model includes BoTs/NURBS, more advanced spatial logic will be
  needed.  should/could also detect any unused/unreferenced geometry
  objects with options to select on a specific type (prims, combs,
  regions, all), perhaps as a purge or unused subcommand.

# 'render' command: to perform different kinds of rendering.  this may
  simply be a renaming of rtwizard, but the intent would be to make
  sure rt, rtedge, and rtwizard are encapsulated under one simplified
  command.  options for quick preview and full-detail rendering,
  without or with shaders, in color or B&W.

* 'repeat' command: perform an action multiple times.  this is similar
  to the search -exec option but instead of being limited to object
  substitutions, it lets you run the same action with any
  substitution.  it's basically a for loop construct over one command.

  # create a bunch of spheres
  repeat 1 2 3 -exec make sph sph.{}

  # create 9 objects
  repeat -m obj sph arb8 tor -exec "repeat -m cnt 1 2 3 -exec \"make {obj} {obj}.{cnt}\""

  # create 3 separate tessellations of an object
  repeat 0.1 0.01 0.001 -exec "tol abs {}" -exec "facetize sph.bot sph"

  Need to make sure that the repeat, search, and batch commands all
  have consistent/compatible marker syntax.  Also need to consider
  arguments or objects with '-' at the beginning of the name and how
  argv processing will be handled.

* 'rm' command: replace most or all of the kill* commands with a
  UNIX style rm command.  Before we can complete this, we need:

  - URI/filesystem model method for addressing non-uniquely named
    instances in object combs.  For example, if comb.c has three
    different instances of obj.s, could address them by number:

     comb.c
	|
	u obj.s -> comb.c/obj.s@1
	|
	u obj.s -> comb.c/obj.s@2
	|
	u obj.s -> comb.c/obj.s@3

   - An equivalent to the UNIX ability to do glob matching on .g
     paths.  OpenBSD glob code offers a possible starting point -
     libbu repo history has commits with some work on this, e.g
     r72153.

  Existing rm command work is reverted in commit r67394

  Notes from Sean:

  rm deletes an object/primitive/instance iff
     1) it exists
     2) it is not externally instanced
     3) it has no children

  rm -f deletes an object/primitive/instance iff
     1) it exists

  rm -r deletes an object/primitive/instance and all children recursively iff
     1) it exists
     2) it is not externally instanced
     3) all children instances could be deleted ("safe" delete)

  * Makes "rm -f" akin to "kill"
  * "rm obj" will succeed on most top-level primitives but shouldn't on extrude,
    dsp, ebm,... maybe new callback
  * No difference between "rm path/to/inst" and "rm -f path/to/inst" other than
    error suppression on non-existent paths/instances

  Common cases (have some questions here... CY):
  "rm prim" -> deletes prim if no */prim instance exists
  "rm -f prim" -> deletes prim (children untouched)
  "rm -rf prim" -> deletes prim and any children without */child ref.
  "rm comb" -> always fails unless comb is empty and no */comb instance exists
  "rm -f comb" -> deletes comb object
  "rm -rf comb" -> deletes comb and safe-deletes children
  "rm path/inst" -> deletes inst (if no */path/inst exists??)
  "rm -f path/inst" -> deletes inst
  "rm -rf path/inst" -> deletes inst

* 'select' command: creates a selection set based on specified
  sampling parameters or object lists.  Should also provide a basic
  command-line mechanism for implementing band selection based on
  current view, volume-based selections, and object highlighting.
  Would encapsulate or replace the unpublished 'sphgroup' command.
  Some examples:

  # select objects within a given distance from a 3d point
  select -point 12.3 23.1 31.2 -dist 100.0

  # select two objects,  create/return a temporary reference name
  select foo bar

* "simulate" command: for applying physics deformations to geometry.
  Each timestep (default steps==1) would get recorded as new geometry
  unless updating the existing is requested.  Usage might be something
  like this:

     simulate [-k] [-g|-G] [-f x y z N] <time> [steps]

  Examples:
     simulate 10.5  # simulate 10.5s of time (default gravity)
     simulate 3 10  # simulate 30s of time, 10s per timestep
     simulate -f 0 0 -1.0 9.807 3.0  # earth's gravity for 3s
     simulate -k 1.0  # simulate 1s of gravity, overwriting original
     simulate -G -f 1 2 3 .4 5  # no gravity, custom force, 5s

* 'text' command: imports a text file (as geometry).  have options to
  specify the spacing between lines, first line, #lines,
  underline/overline each line, convert to all upper/lower, position.
  probably best to create either a 'plot' or 'annotation' object
  (described in top-level TODO).  need some convention for symbols,
  degree, +-tol, null diam, etc.

* 'time' command: reports the current date and time, a user timer,
  file creation time, last modification time, #writes, and accumulated
  editing time.  the user timer is a generic stopwatch for scripting
  use.  The rest requires the timestamping architecture and a runtime
  clock to track accumulation between writes.  basically, every time
  an object is written or the file is explicitly "saved", we'd write
  out time information.

  the non-timer aspects may better fit with the db or about commands.

* 'transact' command: describes a transaction as a series of commands
  to be run in succession which must all succeed for any to apply.
  this can be viewed as a meta-command or basic user script which can
  have parameterized arguments (providing a basic macro system).

  # basic export transaction, stateful (bleh, but familiar)
  transact begin dump_geometry
  make {sph} {sph}
  facetize {sph}.bot {sph}
  bot_dump {sph}.{dxf} {sph}.bot
  transact end dump_geometry
  transact run dump_geometry
  transact run dump_geometry sph=tor dxf=obj
  transact rm dump_geometry
  transact ls

  # non-stateful transaction
  transact run -exec "make {sph} {sph}" -exec "facetize {sph}.bot {sph}" -exec "bot_dump {sph}.{dxf} {sph}.bot"

* 'tree' command: accept a full path, not just a combination

* 'undo' command: undo the previous command or previous N commands.
  Should be stored as a chain or tree of events so you can cycle
  forwards or backwards vim/emacs style.  See redo command above.

* composable API, so you can pass results down similar to this
  database transaction, but less verbose:

  records = db::select(
              "products",
              db::intersection(
                db::intersection(
                  db::compare(
                    db::field("category"),
                    db::equal,
                    db::string("book")),
                  db::compare(
                    db::field("desc"),
                    db::like,
                    db::string("%algorithms%"))),
                db::compare(
                  db::field("stock"),
                  db::greater_than_or_equal,
                  db::integer(1))));

  which amounts to the following in SQL syntax:

    SELECT * FROM products
    WHERE category = 'book' AND desc LIKE '%algorithms%' AND stock >= 1;


--- ANALYZE command design thoughts ---

  If we consider consolidating what are currently "special purpose"
  analysis commands (bounding box calculators, convex hull, gqa's
  functionality, etc.)  all underneath a single unified analyze
  command, we would need a different command option structure.  The
  outline below captures some early stage thoughts on how such a
  command might be organized.

  analyze

  --visualize

  --tolerance #

  --component:
           default when unspecified is whole shape (only option currently for combs)

           F (default all faces, accept number lists and ranges)
           S (default all surfaces, "")
           E (default all 3D edges, "")
           V (default all 3d verts, "")

           (primitive specific components as appropriate - for example, voxel data might allow
            specified value ranges)


  --property: (accept 1 or a comma separated list, can specify multiple --property options as well)
           volume (default for volume component if no property specified)
           surface_area (default for surface component (F, S) if no property specified)
           projected surface area
           length (default for edge component if no property specified)

           bounding-box[=bbox.s] (alias for aabb)
           bbox[=bbox.s]
           aabb[=bbox.s]
           obb[=bbox.s]
           convex-hull=obj.s
           concave-hull=obj.s

           inside-outside=obj.s (relative to another object)
           centroid
           moment-of-inertia
           weight
           overlaps[=<name_template>] (optionally generate volumes bounding overlaps)
           voids[=<name_template>] (optionally generate volumes bounding voids)
           exposed-air[=<name_template>]
           adjacent-air[=<name_template>]

  --report-format:
           default when unspecified would be ascii text

           ascii
           csv
           json
           xml
           ...

  [args] obj1 [obj2 ...]

  Sample invocations:

    analyze --visualize --property bounding-box,centroid obj1.s
    analyze --component F 1-10,23-30 --property surface_area mesh.s
    analyze --property overlaps=overlap.s obj1.c obj2.c

Alternative usage possibility:

  analyze [format] {area|mass|moments|surface|volume}[,more] [options] [objects]

  The "options" include most if not all of the ones described above
  with the main distinction being that specifying a property is
  required, hence making it the dominant subcommand (as a csv list of
  properties to report).  The "format" options would include any
  options that are global to all output types, such as requesting json
  vs csv vs text output formatting.

  Sample invocations:

    analyze --visualize aabb,centroid obj1.s
    analyze surface --component F:1-10,23-30 mesh.s
    analyze overlap --create=overlap.s  obj1.c obj2.c


--- SEARCH command ideas ---

* rewrite search code for better performance, consistency, hide flat
  searches (base it on supplied filters), make above/below searches
  faster, lazy depth building on paths, see if the experimental logic
  for fast size calculations can be finished...

* reinstate 'stat' and search -size, see r67636 through r67646

* the lt [-c] obj command looks like it should be replaceable with
  a search command (search obj -depth 1) and a more powerful -print
  option that can do things like mimic tcl style output and create
  lists with user specified character separation.  Enhance search 
  to do more powerful printing, then make lt an alias to a search
  call.

* dbfind's behavior can be emulated by search, but the
  speed of dbfind is not practical in search due to the potential
  generality of search's filters.  search should pre-process
  its plan and prove it needed to examine only a subset of the full
  hierarchy in advance.

* update search depth options (above + below) to make sure the logic
  supports depth=0 / above=0 / below=0 meaning the current node.

* implement -exec support for 'search' command

* implement -param support for 'search' command


--- thoughts on SEARCH path modifiers ---

This is a slight iteration on the results of Cliff and Nick trying to
work through what "preferred" meanings and conventions are for path
specifier modifiers.

A path modifier is a single or multiple character pattern specified at the head
of an object name, path, or glob pattern:

[modifer]object_pattern[/object_pattern]

Valid single character modifiers and their behaviors:

  /object_pattern[/object_pattern]
  .object_pattern[/object_pattern]
  _object_pattern
  |object_pattern[/object_pattern]

  / → print option, full path.  If specified without modifier, uses tops
      objects as input list
  . → print option, last object in path only.  Default print mode if full path
      is not specified.  If specified without modifier, uses "tops" command
      objects as input list
  _ → modifier specifying flat object search, with no hierarchy walking.  All
      specifiers that require hierarchy are incompatible with this modifier.
      By default it will use the tops output - if a glob pattern is supplied
      as the object pattern, it will match all database objects against that
      pattern and use the matching set as its input set.  An object_pattern
      including hierarchy will produce an error.
  | → use all objects in the database as starting points for a hierarchical
      search.  Overrides default behavior of using tops objects as input list.
      Without other modifiers, this is essentially an implicit "|." specifier,
      since the output will default to the "." mode of printing without paths.

Modifier pairs:

       /     .     _     |
    +---------------------
  / | //    /.    /_    /|
  . | ./    ..    ._    .|
  _ | _/    _.    __    _|
  | | |/    |.    |_    ||


Rules for pair combination and simplification:
  // → /        /. → error    /_ → error    /| → |/
  ./ → error    .. → .        ._ → _        .| → |
  _/ → error    _. → _        __ → _        _| → |_
  |/ → |/       |. → |        |_ → |_       || → |

If more than two print/modifier characters are present at the head of the
path specifier, they will be collapsed using the above rules until either a
single valid pairing is arrived at, a single valid character is arrived at,
or an error condition occurs.  (Any larger combination which which evaluates
to more than two valid specification characters is defined to be erroneous.)

Note: the simplification process is allowed to reorder individual characters
within a longer specification string when attempting to collapse characters,
since none of the valid combined behavior specifications is dependent on
modifier position in the string under the above rules.

Per the above rules, all possible valid path specifier combinations collapse
into one of the four atomic rules, with the exception of "|/" and "|_":

"|/" -  this paring will produce a search output that both uses all objects in
the database as starting points and reports full paths.

"|_" -  this paring will produce a search output that uses all objects in the
database as starting points and performs a flat search.  It is equivalent to
the full pattern "_*" but may be slightly faster in that it doesn't require the
evaluation of the glob expression to build the object set.


--- COMMAND PATTERNS ---

Here are notes on command parsing infrastructure, how to unify our
commands so that parsing can be consistent across embeddings including
GED instances like mged/archer and unix command lines.

One idea being considered is having commands publish their argument
interface, in code, into some simple standard format (e.g., json or
docbook).  from that description, we could derive documentation and
inform interfaces how to automatically provide or validate arguments.

Here's a list of typical BRL-CAD command arguments in EBNF form
related to INPUT specification:

geometry ::= gfile objects
 objects ::= object *(object)
  object ::= <PRINT>           ; need to verify which chars are excluded
 gfile ::= <FILE>             ; does not need to exist

view ::= 0*1(viewsize) 0*1(orientation) 0*1(eye_point)
 viewsize ::= <POSITIVE>
 orientation ::= quaternion | matrix | 0*1(azimuth) 0*1(elevation)
  quaternion ::= <HVECT>
  matrix ::= <MATRIX>
  azimuth ::= <ANGLE>
  elevation ::= <ANGLE>
 eye_point ::= <POINT> | <FLOAT>  ; specific point or distance to model rpp center
perspective ::= 0 | <ANGLE>
cutting_plane ::= <PLANE>
use_air ::= <BOOL>
ambient_intensity ::= <FLOAT>

tolerance ::= distance_tol | perpendicular_tol
 distance_tol ::= <DISTANCE>
 perpendicular_tol ::= <ANGLE>

num_procs ::= <POSITIVE>

Here's a list of typical BRL-CAD command arguments in EBNF form
related to OUTPUT specification (intentionally omitting options
related to debugging and text output):

image ::= (pixel_coordinates | pixel_dimensions | grid_dimensions) bgcolor output
 pixel_coordinates ::= (pixel_x pixel_y) 0*1(pixel_x pixel_y) ; pixel or subrect
  pixel_x ::= <NON_NEG>
  pixel_y ::= <NOT_NEG>
 pixel_dimensions ::= pixel_width pixel_height  ; aka size
  pixel_width ::= <POSITIVE>
  pixel_height ::= <POSITIVE>
 grid_dimensions ::= cell_width cell_height
  cell_width ::= <FLOAT>
  cell_height ::= <FLOAT>
 bgcolor ::= <COLOR>
 output ::= framebuffer | imagefile
  framebuffer ::= <FB_FILE>
  imagefile ::= <FILE>

render_type ::= <LIGHTING_MODEL>
hypersample ::= <UINT>
jitter ::= <JITTER_TYPE>


--- READ/WRITE access management ---

To make things safer for multi-process subcommand execution mode, we need to
implement some sort of multi-process awareness of when a command is interacting
with the database and needs other processes to not change the database.  In
other words, write processes need to wait if one or more reading processes are
pulling data and read processes need to wait if a writing process in currently
changing the data.

As a starting point, look into fcntl with non blocking, advisory modes of
F_SETLK on POSIX and LockFileEx on Windows - try to come up with some libbu
wrapper that will give us the semantics we need to prevent commands from
running when they shouldn't.


--- core shell commands ---

Here are GNU core utilities grouped logically as they could pertain to
geometry.  It's not to suggest that we'll implement any of these, but
it's useful to see all in context when considering new commands and
common conventions we could adopt.

arch/uname/set/env/printenv/date/df/hostid/hostname/logname/nproc/tty/uptime/whoami
        displays runtime environment
        set/delete variables
        get/set environment vars
        current date/time
        available disk space
        host identifier
        avail processors
        tty name
        uptime
        username
base64/od/expand/unexpand
        encode/compress
basename/dirname/realpath
        extracts portion of path names
cat/head/tail/nl/pr/readlink
        displays contents
chgrp/chmod/chown/groups/id/users/who
        permissions
chroot/dir/pathchk/pwd
        switch absolute path context
        get path context
cksum/md5/md5sum/shasum
        hash an entity to a number
comm/csplit/join/paste/shred/shuf/sort/split/truncate/tsort/uniq
        select/reject lines that are in both/either/neigther
        split file into pieces / interleave lines together
        topological sort of graph
        get/count uniq lines
cp/dd/install/mv/rm/rmdir/touch/unlink
        copy objects/data
        delete objects/data
cut/tr
        extract fields from lines
du/stat/wc
        file/object size usage
echo/fmt/fold/printf
        print line / format lines
expr/factor
        do math
kill/nice/nohup/runcon/sleep/stdbuf/timeout/yes/true/false
        task management
link/ln
        create reference to an object
ls
        display listing of objcts
mkdir/mkfifo/mknod/mktemp
        make combination directory
seq
        sequence of numbers
