| # Command-line Tools Rubric |
| |
| |
| ## Overview |
| |
| This document is for command line interface (CLI) tools. Graphical User |
| Interfaces (GUI) are out of scope. |
| |
| When developing tools for Fuchsia there are specific features and styles that |
| will be used to create consistency. This document walks through those |
| requirements. |
| |
| The goal is to maintain a uniform fit and finish for Fuchsia developer tools so |
| that developers can know what to expect. They can most easily see how to |
| accomplish common tasks and there is a well lit path to discover rarer used |
| tools. |
| |
| |
| ## Guide |
| |
| The experience developers have writing software for Fuchsia will impact their |
| general feelings toward writing for the platform and our tools are a significant |
| part of that experience. Providing tools that are inconsistent (with one |
| another) creates a poor developer experience. |
| |
| This guide provides a rubric that Fuchsia tools must follow. |
| |
| > **IDK** |
| > |
| > Some sections have an "IDK" call-out, like this one. These detail specific |
| > rules that apply to tools included with the Fuchsia Integrator Development Kit distribution. |
| |
| ## Considerations |
| |
| Before embarking on the creation of a new tool, consider these factors to |
| determine if the tool is a good fit for Fuchsia or the Fuchsia SDK. |
| |
| > **IDK** |
| > |
| > IDK tools are specific to Fuchsia in some way. Generic tools or tools that are |
| > widely available should not be part of Fuchsia and will not be included in the |
| > Fuchsia IDK. For example, a tool that verifies generic JSON files would not be |
| > a good addition. However a tool that verifies Fuchsia `.cmx` files, which |
| > happen to use the JSON format, would be okay. |
| |
| > **ffx** |
| > |
| > [ffx](/docs/development/tools/ffx/overview.md) is Fuchsia's unified CLI |
| > tool platform for host to target interactions. It provides a logical |
| > subcommand based grouping that maps to high-level Fuchsia workflows. |
| > It also provides a plugin framework to allow contributors to expand the |
| > `ffx` command surface. `ffx` is distributed as part of the Fuchsia IDK. |
| |
| ### Audience |
| |
| Tools may be used for different development tasks. On a large team these roles |
| may be separate people. Some categories are: |
| |
| - Component development |
| - Driver development (DDK) |
| - Fuchsia development (SDK) |
| - Build integration (GN, etc.) |
| - Quality assurance (QA) |
| - System integrators (e.g., on-device network tools) |
| - Publishing (from dev host to server) |
| - Deployment (from server to customers) |
| |
| Consider which users may use a tool and cater the tool to the audience. |
| |
| Tools may have different integration expectations. For example, a developer |
| doing component development may expect tools to integrate with their Integrated |
| Development Environment (IDE), while a build integration tool may be called from |
| a script. |
| |
| ### Grouping Related Tools |
| |
| Prefer to put related commands under a common tool, such as `ffx`. |
| As an example, `git`, `ffx`, or `fx` present many features (or, |
| "sub-tools") under a single user-facing command. This helps encourage |
| the team toward a shared workflow and provides a single point of |
| discovery. |
| |
| Prefer subcommands to multiple tools. E.g. don't create tools with hyphenated |
| names like `package-create` and `package-publish`, instead create a `package` |
| command that accepts create and publish subcommands. |
| |
| Keep the number of commands under a tool organized and reasonable. I.e. avoid |
| adding unrelated commands to a tool and provide sensible organization of the |
| commands in the help and documentation. |
| |
| ### Scope of Work |
| |
| Command line tools can be divided into two groups: simple single purpose tools |
| and larger more featureful tools. Create tools that are ergonomic for their |
| purpose. Simple tools should be quick to start up, while more complex tools will |
| lean toward the more featureful. |
| |
| Larger tools will encompass an entire task at the user (developer) level. Avoid |
| making a tool that accomplishes one small step of a task; instead make a tool |
| that will perform a complete task. |
| |
| For example, when: |
| |
| - developing a C++ application: run the preprocessor, run the compiler, run the |
| linker, start the built executable. |
| - working on a unit test: build the tests and run the tests being worked on |
| - developing a mod: compile the code, move the code and resources to the device, |
| start the mod (or hot-reload) |
| |
| Lean toward a tool that will accomplish all the steps needed by default, but |
| allow for an advanced user to do a partial step (for example, passing an |
| argument to ask the C++ compiler to only run the preprocessor). |
| |
| > **IDK** |
| > |
| > For development environment integrators and EngProd teams, separate tools. |
| > The build integrators will learn each and piece them together to make a |
| > working system. |
| |
| > **ffx** |
| > |
| > `ffx` introduces many subgroupings and related subcommands. |
| > In general for tools that fall in the categories such as host to target |
| > interaction, system integration, and publishing, prefer extending the |
| > existing `ffx` service instead of a new standalone tool. This can be accomplished |
| > by extending `ffx` via additional flags, options or subcommands to take |
| > advantage of shared code and functionality. For considerations and |
| > additional details refer to the `ffx` development |
| > [overview](/docs/development/tools/ffx/overview.md). |
| |
| #### Sharing common functionality |
| |
| If a small step of a task will be needed by several tools, it doesn't make sense |
| to duplicate that code. Consider making a small support tool or create a library |
| to share the code. |
| |
| Making a small tool that performs one step of the task can make sense to promote |
| code reuse. If the user is not expected to run this small tool individually, |
| place the support tool in a directory that is not added to the `$PATH`. I.e. |
| avoid polluting the environment path unnecessarily. |
| |
| Providing a library to share code may be preferable, so that a subprocess isn't |
| needed. |
| |
| |
| ## Implementation |
| |
| Here is some guidance for the nuts and bolts of creating a tool. We'll cover |
| which language to write the tool in, what style to use in that language, and so |
| on. |
| |
| > **ffx** |
| > |
| > `ffx` follows the rubric and conventions laid out below and provides |
| > a reference implementation for the outlined recommendations. |
| |
| ### Naming |
| |
| The following applies to names of binaries, tools, sub-commands, and long |
| parameter flags. |
| |
| Use well-known US English terms or nouns for names. Well-known nouns includes |
| those in common use for the subject matter, or the names of whole subsystems. |
| If a name does not appear in documentation, it is likely not well-known. If |
| it does not appear in any implementation, it is definitely not well-known. |
| |
| Only use lower-case letters (`a-z`) in the US-ASCII character set and hyphens. |
| A single hyphen (`-`) is used to separate words in a name. A Platform |
| required extension is an exception (such as `.exe`). |
| |
| Name CLI tools with more than three characters. Keep the short file names |
| available for user shortcuts (aliases). If you believe a tool should have |
| a very short name, request approval from the Fuchsia API Council. |
| |
| Keeping the points above in mind: |
| |
| - Prefer whole words rather than abbreviations. |
| - Prefer shorter names where a user is expected type the name frequently. For |
| less frequently typed names bias to more explicit names. |
| - Prefer a single word to multiple words |
| - Prefer subcommands to multiple tools that are hyphenated (e.g. avoid |
| `foo-start`, `foo-stop`, `foo-reset`; instead have `foo` that accepts |
| commands `start|stop|reset`). |
| - Prefer symmetry (particularly in verbs) with other similar commands or |
| sub-systems, unless that introduces a broken metaphor. |
| |
| ### Programming Languages |
| |
| Tools may be written in C++, Rust, and Go. For clarity, here are some languages |
| not approved: Bash, Python, Perl, JavaScript, and Dart (see exceptions below). |
| |
| No language is preferred between C++, Rust, and Go. The choice between these |
| languages is up to the author of the tool. |
| |
| > **IDK** |
| > |
| > If a SDK that is an integration of the Fuchsia IDK includes a specific language |
| > (e.g. Dart), that language may be used for tools that are distributed with |
| > that SDK. In other words, do not include a Dart tool in a SDK that |
| > wouldn't otherwise include the Dart runtime, but if it's already there, |
| > that's okay. |
| |
| ### Style Guides |
| |
| Follow the corresponding [style guide](/docs/development/languages/README.md) |
| for the language and area of Fuchsia being developed. For example, if the tool |
| is included with Zircon and written in C++, use the style guide for C++ in |
| Zircon. Specifically, avoid creating a separate style guide for tools. |
| |
| ### Runtime Link Dependencies |
| |
| Try to minimize runtime link dependencies (statically link dependencies |
| instead). On Linux it is acceptable to runtime link against the glibc suite of |
| libraries (libm, etc.); other runtime link dependencies are not allowed. |
| |
| ### Building from Source |
| |
| Keep in mind that some developers will want to build the tools from source. Use |
| the same build and dependency structure as the code in the Platform Source Tree. |
| Do not make a separate system to build tools. |
| |
| ## Host Platforms |
| |
| Keep an eye on how resource heavy a tool becomes and what OSes it will be |
| expected to operate on. |
| |
| ### Run on a Variety of Hardware |
| |
| Developer machines may range from a few CPU cores and moderate amount of RAM to |
| dozens of CPU cores and huge amounts of RAM. Don't assume that host machines are |
| very powerful or that a server cluster is available to offload work to. |
| |
| ### Supported OSes |
| |
| This section is for the convenience of the reader. This document is not |
| authoritative on which platforms are supported. |
| |
| We currently support |
| |
| - Linux |
| - macOS |
| |
| Tools written for developers must run on those platforms. There are other |
| platforms to consider, and while these are not required at this time, it's good |
| to keep the platforms listed below in mind. |
| |
| Tools should be built in a way that makes them easy to port to the following |
| platforms: |
| |
| - Fuchsia (self-hosted) |
| - Windows |
| |
| This is not an exhaustive list, we may support others. |
| |
| ### Case Insensitive File Systems |
| |
| Don't rely on case sensitivity in file paths. E.g. don't expect that `src/BUILD` |
| and `src/build` are different files. Conversely, don't rely on case |
| insensitivity since some platforms are case sensitive. |
| |
| ### Development Hosts Using a Non-English Locale |
| |
| There are several aspects to consider for non-English developers: |
| |
| - Whether the tool itself can be localized |
| - Whether the documentation for the tool can be localized |
| - Whether the tool can work with path names and data that include non-ASCII |
| - Whether the tool works correctly on non-English OSes |
| |
| Tools are provided in US English. It's not required that a tool be localized. |
| (This may change in the future.) |
| |
| The documentation for a tool will support non-ASCII characters. Both HTML and |
| Markdown can support Unicode (UTF-8) characters, so these are both good choices |
| for documentation. Doing the translation is not required, merely allow for the |
| possibility. |
| |
| Tools will function properly with file paths that contain binary sequences and |
| white space. Use a library to work with file paths rather than manipulating |
| paths as strings. (e.g. path.Join in Go.) |
| |
| Tools will operate correctly on non-English platforms (e.g. Japanese or French). |
| This means handling binary (e.g. UTF-8) data without corrupting it. E.g. don't |
| assume a text file is just ASCII characters. |
| |
| |
| ## Execution |
| |
| At runtime (or execution time) consider how the tool should behave. |
| |
| ### Optimize for No Work Needed |
| |
| When appropriate, such as with a build tool, have the tool exit quickly if there |
| is no work to do. If possible, go one step better by providing information to |
| the caller about the dependencies so that the caller can accurately determine |
| whether the tool needs to be called at all. |
| |
| ### Command Line Arguments |
| |
| There are three types of command line arguments: |
| |
| - exact text |
| - arguments |
| - options (i.e. switches and keys) |
| |
| #### Exact text |
| |
| Exact text is placed as-is on the command line. A piece of exact text may be |
| required or optional. Parsing exact text arguments should be restricted to cases |
| where they are needed for disambiguation (i.e. for correctly parsing other |
| arguments). For example if a `copy` command accepted multiple source and |
| destination arguments, an exact text argument may be used to clarify which is |
| which: `copy a b c` may be ambiguous; while `copy a to b c` may indicate that |
| '`a`' is copied to two destinations. |
| |
| #### Arguments |
| |
| Arguments are like function parameters or slots for data to fit into. Often, |
| their order matters. In the example `copy <from> <destination>`, both `<from>` |
| and `<destination>` are ordered arguments. In cases where a single logical |
| argument is repeated the order may not matter, such as remove `<files>...` where |
| the tool might process the `<files>` in an arbitrary order. |
| |
| #### Options |
| |
| Some arguments are known as options. Both switches and keyed (key/value pairs) |
| are options. Options tend to modify the behavior of the tool or how the tool |
| processes parameter arguments. Options consist of a dash prefixed letter or |
| word. |
| |
| Options must start with either one ('`-`') or two ('`--`') dashes followed by an |
| alphanumeric label. In the case of a single dash, the length of the label must |
| be 1. If the length of the label is two or more, then two dashes must be used. |
| For example: `-v` or `--help` are correct; `-help` is not valid. |
| |
| For option names with more than one word (for example, "foo bar"), |
| you must use a single dash ('`-`') between words. For example, "foo bar" |
| becomes `--foo-bar`. |
| |
| All choices are required to have a (`--`) option. Providing single character |
| shorthand (`-`) is optional. E.g. it's okay to provide just `--output`, or both |
| `-o` and `--output`, but it's not ok to only provide an `-o` option without a |
| long option as well. |
| |
| Do not create numeric options, such as `-1` or `-2`. E.g. rather than having |
| `-1` mean to do something once, add a `--once` option. If a numeric value is |
| needed, make a keyed option, like `--repeat <number>`. |
| |
| One (`-`) or two (`--`) dashes on their own are special cases and are not |
| allowed as a key or switch. |
| |
| #### Switches |
| |
| The presence of a switch means the feature it represents is 'on' while its |
| absence means that it is 'off'. Switches default to 'off'. Unlike keyed options, |
| a switch does not accept a value. E.g. `-v` is a common switch meaning verbose; |
| it doesn't take a value, making it switch rather than a keyed value. |
| |
| All switches must be documented (hidden switches are not allowed). |
| |
| Running switches together is not allowed. E.g. `-xzf` or `-vv`, each must be |
| separate: "`-x -z -f`" or "`-v -v`". |
| |
| #### Keyed Options |
| |
| Keyed options consist of a key and a value. Keys are similar in syntax to |
| switches except that a keyed option expects a value for the key. |
| E.g. `-o <my_output_file>` has a key '`-o`' and a value of '`my_output_file`'. |
| |
| Do not use an equals punctuation (or similar) to separate the key and value. |
| E.g. do not do `-o=<my_output_file>`. |
| |
| Note about a rare case: Avoid making optional keys (where the value appears |
| without its key) or optional values (where the key appears without its |
| value). It's clearer to consider the key/value pair optional, but inseparable. |
| I.e. if the key is present a value is required and vice versa. Consider making |
| an argument instead of a keyed option with an optional key. E.g. rather than |
| "`do-something [--config [<config_file>]]`" where not passing `[<config_file>]` |
| means don't use a config file; instead do |
| "`do-something [--config <config_file>|--no-config]`" where passing |
| `--no-config` means don't load a config file. |
| |
| ##### Mutually Exclusive Options |
| |
| Some options don't make sense with other options. We call the options mutually |
| exclusive. |
| |
| Passing mutually exclusive options is considered a user error. When this occurs |
| the tool will do one of the following: |
| |
| - Write an error message explaining the issue and exit with a non-zero result |
| code; doing no work (i.e. there was no data changed as a result of the call). |
| This is the expected handling, so no further documentation or notes are |
| required. |
| - Prioritize one option over another. E.g. "`passing -z will override -y`". In |
| this case the handling will be documented in the `--help` output. |
| - Other handling is possible (first takes precedence or last takes precedence or |
| something else) though this is discouraged. In this case the handling will |
| be documented in the Description, Options, ***and*** Notes; though |
| "`See Notes`" may be used in Description and Options with the full write-up in |
| `Notes`. |
| |
| ##### Grouping Options |
| |
| There is no specific syntax to indicate when enabling one option will also |
| affect another option. When an option implies that another option is enabled or |
| disabled, specify that in the Options. E.g. "`passing -e implies -f`" means that |
| if `-e` is enabled, `-f` will be enabled as if it were passed on the command |
| line (regardless of whether `-f` was explicitly passed). The redundant passing |
| of the implied value is harmless (not an error). |
| |
| ##### Option Delimiter |
| |
| Two dashes ('`--`') on their own indicates the end of argument options. All |
| subsequent values are given to the tool as-is. For example, with |
| "`Usage: foo [-a] <file>`", the command line "`foo -- -a`" may interpret `-a` as |
| a file name rather than a switch. Further, "`foo -a -- -a`" enables the switch |
| `-a` (the first `-a`, before the `--`) and passes the literal text `-a` (the |
| second `-a`). |
| |
| ##### Repeating Options |
| |
| Repeating switches may be used to apply more emphasis (what more emphasis means |
| is up to the tool, the description here is intentionally vague). A common |
| example is increasing verbosity by passing more `-v` switches. |
| |
| Repeating keyed options may be used to pass multiple values to the same command. |
| Often this is done to avoid calling the same command multiple times. Common |
| commands that accept repeating options are `cp`, `rm`, `cat`. Care must be taken |
| to ensure that repeating commands are unambiguous and clear. E.g. `cp` always |
| interprets the last argument as the destination; if `cp` accepted multiple |
| source and destination arguments the parsing would become ambiguous or unclear. |
| |
| #### Standard Input Alias |
| |
| In Fuchsia tools a single dash (`-`) is not interpreted as an alias to stdin. Use |
| pipes to direct data into stdin or use `/dev/stdin` as an alias for stdin. |
| (Note: `/dev/stdin` is not available on Fuchsia or Windows). |
| |
| #### Single Dash |
| |
| A single dash ('-') on its own is reserved for future use. |
| |
| #### Subcommands |
| |
| Tools may contain sub-command that accept independent command line arguments. |
| (Similar to the `git` tool). Subcommands do not begin with any dashes. E.g. in |
| `fx build` the `build` argument is a subcommand. |
| |
| When a tool has many subcommands, it should also have a help subcommand that |
| display help about other subcommands. E.g. "`fx help build`" will provide help |
| on the build subcommand. |
| |
| Subcommands may have their own arguments that are not handled by the main tool. |
| Arguments between the tool name and the subcommand are handled by the tool and |
| arguments that follow the subcommand are handled by the subcommand. E.g. in |
| `fx -a build -b` the `-a` is an argument for the `fx` tool, while the `-b` |
| argument is handled by the `build` subcommand. |
| |
| ### Common Features |
| |
| Command line tools are expected to support some common switches: |
| |
| - `--help` |
| - `--quiet` |
| - `--verbose` |
| - `--version` |
| |
| #### Interactive Help (--help) |
| |
| A tool must accept a `--help` switch and provide usage information to the |
| command line in that case. The layout and syntax of the help text is described |
| in [CLI tool help requirements](/docs/development/api/cli_help.md). |
| |
| The tool must not do other work (i.e. have side effects) when displaying help. |
| |
| Use a library that can parse the arguments as well as present help information |
| from the same source. Doing so keeps the two in sync. I.e. avoid writing command |
| line help as an independent paragraph of text. |
| |
| Keep the interactive help reasonably concise. Plan for a skilled reader, i.e. |
| someone looking for a reminder on how to use the tool or a developer experienced |
| in reading interactive help. For the novice, provide a note referring them to |
| the Markdown documentation. |
| |
| Provide an option to generate machine parsable output. |
| |
| #### Verbosity (--quiet and --verbose) |
| |
| The `--quiet` and `--verbose` switches decrease or increase informational output |
| to the user. Their implementation is optional, but all tools will accept them as |
| arguments and must not use those terms for other purposes, e.g. don't use |
| `--quiet` to turn off the audio output (use `--silence` or `--volume 0` or some |
| other synonym). |
| |
| #### Interactive Version (--version) |
| |
| A tool must accept a `--version` switch and provide an indication of the code |
| used to build the tool in that case. The layout and syntax is not specified, but |
| the version will include a version number of some kind. |
| |
| The tool must not do other work (have side effects) when reporting its version. |
| |
| ### Logging |
| |
| Logging is distinct from normal output. The audience for logging is normally the |
| tool developer or a power user trying to debug an issue. Logging may go to |
| stdout in special cases, such as when `--verbose` output is requested. |
| |
| Logging from multiple threads will not interlace words within a line, i.e. the |
| minimum unit of output is a full text line. Each line will be prefixed with an |
| indication of the severity of the line. The severity will be one of: detail, |
| info, warning, error, fatal. |
| |
| ## Metrics |
| |
| Every tool must file a Privacy Design Document (PDD) in order to collect usage |
| metrics. |
| |
| Metrics are important to drive quality and business decisions. Questions we want |
| to answer with metrics include: |
| |
| - Which OS are our users using? - so we know how to prioritize work for various |
| platforms |
| - Which tools are they using? - so we know how to prioritize investments, and to |
| learn which workflows are currently being used so we can prioritize |
| investments or identify weak spots |
| - How often do they use a tool? - so we know how to prioritize investments, and |
| to learn which workflows are currently being used so we can prioritize |
| investments or identify weak spots |
| - Do our tools crash in the wild? How often? - so we know how to prioritize |
| maintenance of tools |
| - How do they use a tool? - assuming that a tool can do one or more things, we'd |
| like to learn how to prioritize investments in particular workflows of a tool |
| |
| The type and content of the metrics collected must be carefully chosen. We will |
| go through the Google-standard PDD review process to ensure we are compliant |
| with Google's practices and policies. Tools must get approval on which metrics |
| are collected before collection. |
| |
| ## Configuration and Environment |
| |
| Tools often need to know something about the context they are running. Let's |
| look at how that context should be gathered or stored. |
| |
| #### Reading Information |
| |
| Tools should not attempt to gather or intuit settings or other state directly |
| from the environment. Information such as an attached target's IP address, the |
| out directory for build products, or a directory for writing temporary files |
| will be gathered from a platform independent source. Separating out the code that |
| performs platform-specific work will allow tools to remain portable between |
| disparate platforms. |
| |
| Where practical, configuration information should be stored in a way familiar to |
| the user of the host machine (e.g. on Windows, use the registry). Tools should |
| gather information from SDK files or platform-specific tools that encapsulate |
| the work of reading from the Windows registry, Linux environment, or Mac |
| settings. |
| |
| Tools will be unbiased towards any build system or environment as well. |
| Accessing a common file such as build input dependency file is okay. |
| |
| #### Writing Information |
| |
| Tools will not modify configuration or environment settings, except when the |
| tool is clearly for the purpose of modifying an expected portion of the |
| environment. |
| |
| If modifying the environment outside of the tool's normal scope may help the |
| user, the tool may do so with the express permission of the user. |
| |
| |
| ## Execution Success and Failure |
| |
| Command line tools return an integer value in the range [0..127] when they exit. |
| A zero represents success (no error) and 1-127 are various forms of error. The |
| value 1 is used as a general error. Any values other than 0 and 1 that may be |
| returned must be documented for the user. |
| |
| ### Succeed with Grace |
| |
| If there were no errors encountered, return a result code of zero. |
| |
| Avoid producing unnecessary output on success. Don't print "succeeded" (unless |
| the user is asking for verbose output). |
| |
| ### If Something is Unclear, Stop |
| |
| If the tool encounters an ambiguous situation or is in danger of corrupting |
| data, do not continue. E.g. if the path to the directory you're being asked to |
| delete comes back as just "`/`", there was likely an error trying to get that |
| configuration information, avoid 'soldiering on' and removing everything under |
| "`/`". |
| |
| ### Do Not Fail Silently |
| |
| Tools must clearly indicate failure by returning a non-zero error code. If |
| appropriate (if it makes sense for the tool or if the user explicitly asked for |
| verbose output) print an error message explaining what went wrong. |
| |
| ### Provide Direction on Failure |
| |
| When a tool execution fails, be clear about whether the error came from bad |
| inputs, missing dependencies, or bugs within the tool. Make error reports |
| comprehensible and actionable. |
| |
| If the error came from bad inputs |
| |
| 1. If the user gave the tool bad data, give context about the error and guide |
| the user toward fixing the input, for example, by printing the input file |
| (and line number if that's appropriate for the input) where the input error occurred. |
| - Prefer output that follows this format (for easy regex use): |
| `file_name:line:column:description`. This is a common format used by many |
| tools. Other formats are acceptable, but try to use something that is easy |
| for both humans and tools to parse. |
| 2. Provide a reference to further information. If documentation is |
| available, provide a link to documentation about the tool in general or to |
| documentation regarding the specific error. If the tool has the capacity to |
| provide more details, describe that (like how `gn` can explain how to run the |
| tool to get more help). |
| |
| If the error came from missing dependencies |
| |
| 1. Be clear that the error is from missing dependencies. Don't leave the |
| user trying to debug their input data if that is not the issue. |
| 2. Provide instruction on how to satisfy the dependencies. This can be an |
| example command to run (`apt-get install foo`) or a link to further |
| instructions (`see: http:example.com/how-to-install-foo`). |
| |
| If the error came from an unexpected state (i.e. a bug) in the tool |
| |
| 1. Apologize. Explain that the tool got into an unexpected state. Don't leave |
| the user trying to guess whether their input data was bad or they were |
| missing dependencies. |
| 2. Suggest a mailing list or forum to get help. Help the user find out if the |
| bug is fixed in the next tool version; or someone has found a workaround. |
| 3. Invite the user to enter a bug report and make that as easy as possible. |
| Provide a link that goes to the bug database with the tool and platform |
| information prepopulated. |
| |
| |
| ## Include Tests |
| |
| Tools must include tests that guarantee its correct behavior. Include both unit |
| tests and integration tests with each tool. Tests will run in Fuchsia continuous |
| integration. |
| |
| > **IDK** |
| > |
| > It's especially important that IDK tools imported from the Fuchsia build (pm, |
| > etc.) have tests that run in Fuchsia continuous integration because the IDK |
| > bot does not currently prevent breaking changes. |
| |
| > **ffx** |
| > The `ffx` platform provides a framework for introducing tests that are |
| > run automatically in Fuchsia continuous integration. Contributors can |
| > see examples of plugin tests and end-to-end self-tests in the `ffx` |
| > [source](/src/developer/ffx). |
| |
| ## Documentation |
| |
| The Markdown documentation is the right place to put more verbose usage examples |
| and explanations. |
| |
| > **IDK** |
| > |
| > All tools included in the IDK and intended to be executed directly by an end |
| > user must have a corresponding Markdown documentation file. |
| |
| ## User vs. Programmatic Interaction |
| |
| A tool may be run interactively by a human user or programmatically via a script |
| (or other tool). |
| |
| While each tool will default to interactive or non-interactive mode if they can |
| glean which is sensible, they must also accept explicit instruction to run in a |
| given mode (e.g. allow the user to execute the programmatic interface even if |
| they are running in an interactive shell). |
| |
| ### Stdin |
| |
| For tools that are not normally interactive, avoid requesting user input |
| e.g. readline or linenoise). Don't suddenly put up an unexpected prompt to |
| ask the user a question. |
| |
| For interactive tools (e.g. `zxdb`) prompting the user for input is expected. |
| |
| ### Stdout |
| |
| When sending output to the user on stdout use proper spelling, grammar, and |
| avoid unusual abbreviations. If an unusual abbreviation is used, be sure it has |
| an entry in the [glossary](/docs/glossary/README.md). |
| |
| Try to check for output to terminal, i.e. see if a user is there or whether the |
| receiver is a program. |
| |
| #### ANSI Color |
| |
| Use of color is allowed, with the following caveats: |
| |
| - Suppressing color: |
| - When possible, check whether the terminal supports color, and suppress color |
| output if not. |
| - Always allow the user to manually suppress color output, e.g. with a |
| `--no-color` flag and/or by setting the `NO_COLOR` environment variable |
| ([no-color.org](http://no-color.org)). |
| - When using color, be sure to use colors that are distinct for readers who may |
| not be able to see a full range of color (e.g. color-blindness). |
| - The best way to do this is to stick to the standard [8/16 colors](https://gist.github.com/fnky/458719343aabd01cfb17a3a4f7296797#8-16-colors). It's easy for users to remap these, unlike the [256 colors](https://gist.github.com/fnky/458719343aabd01cfb17a3a4f7296797#256-colors). |
| - Never rely solely on color to convey information. Only use color as an enhancement. |
| Seeing the color must not be needed for correct interpretation of the output. |
| |
| ### Stderr |
| |
| Use stderr for reporting invalid operation (diagnostic output) i.e. when the |
| tool is misbehaving. If the tool's purpose is to report issues (like a linter, |
| where the tool is not failing) output those results to stdout instead of stderr. |
| |
| See Success and Failure for more information on reporting errors. |
| |
| ### Full-Screen |
| |
| Avoid creating full-screen terminal applications. Use a GUI application for such |
| a tool. |
| |
| ### Non-interactive (Programmatic) |
| |
| Include a programmatic interface where reasonable to allow for automation. |
| |
| If there is an existing protocol for that domain, try to follow suit (or have a |
| good reason not to). Otherwise consider using manifest or JSON files for |
| machine input. |
| |
| ### IDE (Semi-Programmatic) |
| |
| Allow for tools to be used by an Integrated Development Environment. This |
| generally involves accepting a manifest for input and generating a manifest. |
| |
| ### Interactive (User) |
| |
| Interacting with the user while the tool is running is an uncommon case for many |
| tools. Some tools may run interactively as an option, e.g. `rm -i` will prompt |
| the user before each removal. |
| |
| ## State Files |
| |
| State files encode information for data sharing between tools. PID file and lock |
| files are examples of state files. |
| |
| Avoid using a PID file to contain the process ID of a running executable. |
| |
| Avoid using a lock file to manage mutual exclusion of resource access (i.e. a |
| mutex). |