Skip to content

Field selection #1226

@rgoldberg

Description

@rgoldberg

Field-Selection Options

--fields … & associated options allow commands that support --json to:

  • Select fields
  • Order fields
  • Rename fields
  • Format field values
  • Sort rows

--fields … & associated options affect all output formats (currently: tabular
& JSON).

Remove --price from search after field addition implemented.

Custom EBNF Syntax Definition

This custom flavor of EBNF (Extended Backus-Naur Form) is later used to describe
the command-line syntax for field-selection options & their values.

All values are case-sensitive in this custom EBNF syntax definition & in uses of
it.

Whitespace is ignored in this custom EBNF syntax definition & in uses of it.

Escaped Characters

Characters used in any usage of any syntax defined via this custom EBNF syntax
definition may be escaped with a \ prefix.

  • \ escapes the following character to itself (e.g., \n results in a literal
    n).
  • \ must be escaped unless it is the final character, in which case it is
    considered a literal \.

Escaped whitespace used in any usage of any syntax defined via this custom EBNF
syntax definition is always preserved as significant.

Except as detailed below, unescaped whitespace used in any usage of any syntax
defined via this custom EBNF syntax definition is ignored as insignificant.

Wildcard / EBNF Placeholder

*

Literal Text

"*"

"" is the escape for a literal ".

Value Description

{*}

* describes valid literal values, e.g., {non-negative integer}.

Value Placeholder (aka Non-Terminal Symbol)

<*>

* is the name of the value's type.

Escaping Text Placeholder

{text}

Non-empty string input that is literal except for \-escaped characters.

Significant characters are those that either are non-whitespace or are escaped
whitespace.

  • Unescaped whitespace before the first significant character, or after the last
    significant character, of {text} is ignored as insignificant.
  • Unescaped whitespace between the first significant character & the last
    significant character of {text} is preserved as significant.
{text\*}
{text\\*}
{text\*\\*}

Extends {text} specifying additional characters besides \ that must be
escaped:

  • Characters in * from \* must be escaped when they are the first character.
  • Characters in * from \\* must be escaped everywhere.
  • The contents of \* & \\* are unescaped literals, except for:
    • \>, which is an escaped >.
    • Character classes referenced via [:*:] where * is the class name. A [:
      must have a subsequent matching :]. All standard
      POSIX character classes
      are supported. Other character classes must be defined.
  • \ must always be escaped, so, besides \>, \ must not be in any * for
    either \* or \\*.

Example

{text\@.+\\=:/,}
  • @, . & + must be escaped if first.
  • \, =, :, / & , must be escaped throughout.

Grouping

( * )

Optional Singleton (0 or 1)

[ * ]

Optional Repetition (0 or More)

*…

Choice

* | *

Headers Option Spec

Controls the visibility & format of the headers row.

headers-option ::= "--no-headers" | "--headers" [ "=" <headers-format> ]

Standard: --no-headers

<headers-format> is reserved for future implementation (e.g., csv, bold,
underline).

Fields Option Spec

Contexts

A context exists for each command in a command stack:

Command Stack Most Specific Context Least Specific Context
mas config mas.config mas
mas list mas.list mas
mas lookup mas.lookup mas
mas outdated mas.outdated mas
mas search mas.search mas

The context stack for each command is ordered from most specific to least
specific context (e.g., the context stack for mas outdated is
mas.outdated, mas).

Field Specs

Configure how a field is included in the output, containing:

  • Required field name
  • Optional output label (defaults to the field name)
  • Optional value formatting (default formatting based on field name)
  • Optional row sorting

Field Spec Lists

A field spec list is an ordered group of field specs.

Effective List

The field spec list actually used for output for a command line.

Named Field Spec Lists

Field spec lists stored in a persistent configuration under a case-sensitive
name that is unique for a context.

mas provides Immutable Standard Named Field Spec
Lists
.

Users can define named field spec lists in any context.

Named field spec lists are found by:

  • Returning the first named field spec list found with a given name while
    iterating through the context stack for the current command from most to least
    specific context.
  • If no match is found, an error is reported.
Immutable Standard Named Field Spec Lists

Provided for each leaf command:

  • standard: The command's default tabular output field specs.
  • all: Field specs for all of the command's fields.

Provided for mas:

  • none (alias empty): No field specs.
Base List

The base named field spec list for computing the effective list.

The base list is set to:

  • A named field spec list referenced in the command line.
  • If no named field spec list is referenced in the command line: a
    user-configured per-output-format per-command default base list.
  • If no default base list is configured by the user: standard for tabular
    output & all for JSON output.

Fields Option

fields-option       ::= "--fields " <fields-option-value>
fields-option-value ::= <standalone-spec> | <based-spec>

The effective list is:

  • If <fields-option> is omitted: the default base list.
  • If --fields <standalone-spec> is supplied: sourced solely from
    <standalone-spec>; this is the equivalent of the base list being set to
    none.
  • If --fields <based-spec> is supplied: sourced from a base list as modified
    by the <based-spec>.

<standalone-spec> & <based-spec> are overlaid on top of the base list for
the current command line only; they do not persistently affect named field spec
lists.

Custom Character Class

[:subsequent-section-prefix:] matches:

  • . & + inside <base-list-section> & descendants
  • + inside <edits-section> & descendants
  • nothing elsewhere

Standalone Spec

standalone-spec             ::= <first-standalone-field-spec> [ "," <subsequent-standalone-field-spec> ]…
first-standalone-field-spec ::= <first-standalone-field-name> <field-modifiers>
first-standalone-field-name ::= {text\@.+\\=:/,}

subsequent-standalone-field-spec ::= <subsequent-standalone-field-name> <field-modifiers>
subsequent-standalone-field-name ::= {text\\=:/,}

Each field spec in a <standalone-spec> appends a new output for its field.

Based Spec

based-spec ::= [ <base-list-section> ] [ <edits-section> ] [ <appends-section> ]
  • Computes the effective list from a resolved base list adjusted by
    modifications from the command line.
  • If <base-list-section> is omitted, the default base list is used.
Base List Selection
base-list-section    ::= <base-list-prefix> [ <field-spec-list-name> ]
base-list-prefix     ::= "@"
field-spec-list-name ::= {text\\[:subsequent-section-prefix:]}
  • If <field-spec-list-name> is omitted, the base list is all.
  • If no field spec list is named <field-spec-list-name> in the context stack,
    an error is reported.
In-Place Edits
edits-section ::= <edits-prefix> <based-field-spec> [ "," <based-field-spec> ]…
edits-prefix  ::= "."

based-field-spec ::= <based-field-name> <field-modifiers>
based-field-name ::= {text\+\\=:/,[:subsequent-section-prefix:]}
Appends (Moves & Additions)
appends-section ::= <appends-prefix> <append-field-spec> [ "," <append-field-spec> ]…
appends-prefix  ::= "+"

append-field-spec    ::= [ <add-output-indicator> ] <based-field-spec>
add-output-indicator ::= "+"
  • Appends field specs to the base list. If a field spec already exists for the
    field name, and if the field spec:
    • Does not have an <add-output-indicator>, then the existing field is moved to
      be appended to the effective list.
    • Has an <add-output-indicator>, then a new output is appended for the same
      field.
  • The rightmost field spec for the same field takes precedence.

Field Modifiers

field-modifiers ::= [ <label-part> ] [ <format-part> ] [ <sort-part> ]
Labelling
label-part ::= "=" [ <label> ]
label      ::= {text\\:/,}
  • A field without an effective <label-part> uses its field name as its label.
  • Labels are used as:
    • Headers for tabular output.
    • Keys for JSON output.
Formatting
format-part   ::= ":" [ <format> ]
format        ::= <format-type> [ ":" <format-config> ]
format-type   ::= {text\\:/,}
format-config ::= {text\\/,}

Pre-existing <format-type>s:

  • default (used if no <format-part> was supplied): user-configurable default
    formatting per field name per context
  • standard: formatting used for default if none was configured by the user
  • verbatim (used if no <format> was supplied): outputs field value verbatim
    from input
  • hidden: omits field from output; useful to sort by the field without
    displaying it
  • by-value-map (format-config ::= <value-map-name> ::= {text\\/,}): formats
    values by mapping from their respective values to a format. <value-map-name>
    defaults to default, which maps to a per-command user-configurable value map
    name, which defaults to standard if not set by the user
Sorting
sort-part ::= "/" <sort-spec>
sort-spec ::= [ <sort-priority> ] [ <sort-option> ]…
  • An empty sort (/) clears inherited sorting for the field.
  • A field without an effective sort spec does not affect row sorting.
Sort Priority
sort-priority ::= {non-negative 64-bit integer}
  • A field with an effective sort spec takes sort precedence over fields:
    • With a numerically higher <sort-priority>.
    • To its right with the same <sort-priority>.
Sort Options
sort-option ::= <source> | <direction> | <case-sensitivity> | <localization> | <grouping> | <interpretation> | <boundaries>
  • Each sort option of the same type (e.g., each <source> value) is
    functionally mutually exclusive with all other values of the same type.
  • If multiple sort options of the same type are supplied (e.g., <ascending> &
    <descending>), the rightmost overrides the others.
source ::= <input> | <output>
input  ::= "I"
output ::= "O"

If an input value is modified by a format for output, <input> sorts based on
the input, not the output. <output> is the opposite.

e.g., for an input timestamp being output as an ISO date (without time):

  • <input> sorts by the input timestamp.
  • <output> sorts by the output ISO date (without time).
direction  ::= <ascending> | <descending>
ascending  ::= "a"
descending ::= "d"
case-sensitivity ::= <sensitive> | <insensitive>
sensitive        ::= "s"
insensitive      ::= "i"
localization     ::= <canonical> | <localized>
canonical        ::= "c"
localized        ::= <localized-prefix> [ "~" [ <locale-name> ] "~" ]
localized-prefix ::= "l"
locale-name      ::= {text\~}

<canonical> uses a locale-independent comparison, while <localized> uses a
locale-dependent comparison. This also affects numeric fractional part & integer
grouping separators.

localized without a <locale-name> uses the system default locale.

grouping  ::= <ungrouped> | <grouped>
ungrouped ::= "u"
grouped   ::= "g"
interpretation ::= <lexical> | <numeric> | <price> | <version>
lexical        ::= "x"
numeric        ::= "n"
price          ::= "p"
version        ::= "v"
boundaries        ::= <boundaries-prefix> [ "~" [ <boundary-list> ] "~" ]
boundaries-prefix ::= "b"
boundary-list     ::= {text\~}

A <boundaries-prefix> without a <boundary-list> removes all existing
boundaries (reverting to whitespace-only splitting).

Characters in a <boundary-list> take precedence for boundary splitting over
all other characters to their right.

Whitespace characters not in the <boundary-list> take precedence for boundary
splitting over all characters in the <boundary-list>.

The rightmost occurrence of a character in a <boundary-list> overrides all
existing precedences for boundary splitting for that character.

Default Sort Options
Format Type Default
Tabular Text Iailgnb
Tabular Price Iailgpb
Tabular Version Iailuvb
Tabular Path Iailgnb_/\_
JSON Text Iascgnb
JSON Price Iascgpb
JSON Version Iascuvb
JSON Path Iascgnb_/\_

Metadata

Metadata

Assignees

No fields configured for Feature.

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions