Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CLIENT_SPECIFICATION.md: Write initial client specification #2706

Merged
merged 35 commits into from
Mar 12, 2019
Merged
Changes from 2 commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
4e51358
CLIENT_SPECIFICATION.md: Write initial client specification
sbrl Jan 12, 2019
e60801d
Update CLIENT_SPECIFICATION.md
sbrl Jan 12, 2019
f0f94e6
CLIENT_SPECIFICATION.md: Update version number
sbrl Jan 14, 2019
eb8e2e4
client spec: Require clients to say what spec version they implement
sbrl Jan 14, 2019
e626bf4
client spec: Don't require --update if cache isn't supported
sbrl Jan 14, 2019
7d67830
client spec: Clarify --update description
sbrl Jan 15, 2019
2e3641d
Update CLIENT_SPECIFICATION.md
sbrl Jan 16, 2019
9206c25
client spec: Revise --list, add --pretty
sbrl Jan 18, 2019
718f8e7
client spec: Add --platform, -p, and : syntax
sbrl Jan 18, 2019
e573fbf
client spec: Tidy up optional platform specifier.
sbrl Jan 23, 2019
bba9222
client spec: Add dashes in platform: specifier
sbrl Jan 23, 2019
f22c233
rename from _ to - for consistency
Jan 23, 2019
794cbd3
Remove : syntax
Jan 23, 2019
86dd357
use spaces instead of tabs for tables
Jan 23, 2019
3841a80
Specify downloading pages from github repo
Jan 23, 2019
7f4a5ee
Show short arguments first
Jan 23, 2019
1bd331d
Allow clients to only support short options
Jan 23, 2019
cde22bd
Fill out tldr.md
Jan 23, 2019
e2a764e
Show example for subcommands
Jan 23, 2019
3eea772
Update CLIENT-SPECIFICATION.md
owenvoke Jan 23, 2019
12af654
Update pages/common/tldr.md
owenvoke Jan 23, 2019
4ae2b29
Update pages/common/tldr.md
owenvoke Jan 23, 2019
cab265e
Update pages/common/tldr.md
owenvoke Jan 23, 2019
566b0f9
remove translation requirement
Jan 23, 2019
4715e71
remove version history because this is a draft
Jan 24, 2019
83c0915
Update CLIENT-SPECIFICATION.md
sbrl Jan 26, 2019
4a2c2bf
tldr: remove -t
Jan 27, 2019
71db6de
client-spec: Add "required?" column to args table
sbrl Feb 16, 2019
0124246
client spec: Shorten description in args table
sbrl Feb 19, 2019
f200f1b
client spec: fix table markup
mebeim Feb 19, 2019
823cfa4
client spec: Update description of --platform in args table
sbrl Feb 19, 2019
af6afa2
client spec: reorder args table
sbrl Feb 19, 2019
551db32
client spec: remove todo
mebeim Mar 12, 2019
73f2bc8
Update pages/common/tldr.md
mebeim Mar 12, 2019
2077747
tldr: alter to match new client spec
sbrl Mar 12, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
194 changes: 194 additions & 0 deletions CLIENT_SPECIFICATION.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,194 @@
# tldr-pages client specification

- **Current Specification Version:** 1.1
sbrl marked this conversation as resolved.
Show resolved Hide resolved

This document contains the official specification for tldr-pages clients. It is _not_ a specification of the format of the pages themselves - only a specification of how a user should be able to interface with an official client.

The keywords "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in [RFC 2119](https://tools.ietf.org/html/rfc2119).


## Changelog
- v1.0 (18th December 2018)
- Initial draft
- v1.1 (18th December 2018)
- Refined bullet points according to comments
- Ensure the spec specifies the _interface_, not the workings
- v2.0 (12th January 2019)
- Expanded notes into full sentences


## Terminology
In order to aid the understanding of this specification document, a number of terms will be defined in this section.

### Page
tldr-pages consists of multiple _pages_ - each of which describes a specific command.

### Platform
Pages are grouped by platform. A platform is an operating system. For example, `windows`, `linux`, `osx`. The special platform `common` contains pages for commands that work identically across all platforms.


## Command-Line Interface
This section describes the standardised command-line interface (CLI) for clients implementing one. Clients that do not provide a CLI can ignore this section.

### Arguments
A number of arguments MUST be supported if a CLI is implemented:

Argument | Meaning
------------------------|--------------------
`--update` | Updates the offline cache of pages.
`--version`, `-v` | Shows the current version of the client.
`--list-all`, `-a` | Lists all the pages in the current platform to the standard output. One page name per line. Additional decoration MAY be printed to the standard error.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

how about --list, -l? This way it is similar to ls -l (one per line), and shorter to type.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hrm, you raise a good point. What do you think, @agnivade / @pxgamer / @waldyrious?

Copy link
Member

@owenvoke owenvoke Jan 15, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this was because the node client uses --list-all 🤔 I think --list is used to show pages for the current platform.

See documentation here.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think --list-all is rather confusing, actually. It implies that all pages are listed, but in reality it's only the pages in the current platform & common that are listed.

Perhaps we can disambiguate this somehow?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Personally I don't see any value in listing every possible page, crossplatform (which I would assume --list-all does as @jedahan pointed out) because that means we should print out paths to disambiguate pages covering same tool on different platforms. That essentially puts us in business of re-implementing ls -R. If user really wants that they should be able to get cache location somehow and do that on they own.
So my vote goes to -l, --list to get list of pages for assumed/specified platform.

OTOH discussion about list formatting is (sorry but I have to say it) aiming at completely wrong target. It simply does NOT matter at all how it will look and there is good background reason for that. Take our beloved ls for example. Default output of ls is columned or is it?! Pipe that through cat/less and you'll get one-per-line list. I'm too lazy to dig out proper POSIX/TAOUP/whatever spec/recommendation so rule of thumb instead:

Output of first class citizen *NIX CLI tool:

  1. MAY be aesthetically pleasing with all kind of wonders you decide to throw in
    if STDOUT is NOT TTY
  2. MUST be formatted as one-per-line list (to enable easy manipulation using *NIX tools)
    if STDOUT is a TTY

Can we just replace blah blah CLI tool with tldr client and put it inside spec? 😉

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I still think if people want to do something that technical, they could either just turn to the cache directory and get anything they need there, or, they should use the -t/--tty flag or -n/--noformat or some such. Because if people pipe their output into less, they probably don't want to automatically get no columns or colors. If you use a flag, the user can decide, if you don't, some users are going to request it as a feature.

Copy link
Contributor

@vladimyr vladimyr Jan 17, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@pepa65

If you use a flag, the user can decide, if you don't, some users are going to request it as a feature.

And that's like only thing I agree with. 😞

I still think if people want to do something that technical,

Calling list manipulation with standard cli tools technical is bit far fetched if you ask me; after all isn't one of selling points of tldr pages is to get people to that level more easily? 🙃
What so technical in grepping large lists? 🤔

or, they should use the -t/--tty

I'm very curious to see example of tool implementing given option. I never seen something like that and I highly doubt I ever will; having in mind it is not considered standard:

Because if people pipe their output into less, they probably don't want to automatically get no columns or colors.

Sorry but that's just your opinion while common practice teaches us exact opposite. I may or may not agree with you but you are actually arguing with facts:

So, yeah you are right, people like ansi colors but like and expect by default are two different things. By default colors are off. Which brings me to the next thing you said:

or -n/--noformat or some such.

Again, you are going against common practice established by *NIX cli tools. Formatting is off by default if output is tty. If you really want to retain it you need to explicitly request tool generating output to do so. And it makes perfect sense why you need extra step for colors/formatting to be outputted/preserved: not every tool you may use to process output understands and/or is able to strip out ansi escapes! If user is positive that his tool of choice (e.g. less) is capable of doing so, ok, you have choice to do --color=always, --color, --pretty, you name it...

In conclusion - to actually address your concern we should probably support --pretty option that would force colors and general formatting being preserved when output is not tty. I'm ok with that and FWIW you have my 👍 there but in form of recommendation, such thing shouldn't be a MUST but MAY instead:

  • stdout is TTY - Generate formatted output (optional)
  • stdout is NOT TTY and --pretty - Preserve formatting (optional)
  • stdout is NOT TTY - Generate \n separated list (mandatory)

That being said, please try to align your proposals with established CLI tools design practices and user expectations. TBH I understand your motivation and would sometimes give everything for a chance to rewrite history of our discipline but that's simply not possible. tldr clients are not first tools of such class and less exotic they are more successful and useful they'll become!

Copy link
Contributor

@vladimyr vladimyr Jan 17, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@pepa65

Don't you feel you are being unnecessarily redundant with tldr --list --platform macos? I just do tldr --list macos and it works. There is no need there for a --platform marker.

Yes and no 🤔

Sure it is verbose, I personally don't like it too but...
OTOH lets compare this with what man does (I like to consider tldr client as man for humans same way as httpie is curlfor humans; correct me if my understanding is wrong :bowtie:).

In order to get all man pages you need to run:

$ man -k .

where . is regex meaning everything. If you want to narrow that down using sections:

$ man -k . -s1

lists only manpages inside 1st section.

If you now swap -k . with -l and -s1 with -p <platform> you'll get original form I proposed:

$ tldr -l -p macos
$ # or if you like it more
$ tldr --list --platform macos

You could OFC argue that manpage listing I just described has mandatory search param while tldr listing does not thus putting us in better position by allowing what you suggested. Yeah, that's true but might be also an indication that we are doing something wrong ⚠️
Maybe right way to do the listing is to copy good ol' man? 🙃

@jedahan
Could not support you more in that consistency effort 💯

@sbrl
I wanted to do some wildcard like thingie and ended up doing lousy job 🤦‍♂️

I know it isn't constructive at all but this whole thing with what should list (almost) everything print is painfully convoluted and more we evolve it less value I see in it. Can someone ELI5 in what particular case user wants to print every or almost every possible command out apart from pure curiosity and explorer's spirit?
Aren't the real life usecases:
(step zero: you know what you want to do)

  1. You know which tool can help you but you don't know how to use it so you do:
$ tldr <tool>
  1. You do NOT know which tool you should use so you do:
$ tldr --search <query>

Which isn't even mentioned in the spec itself! ⚠️

In both cases you might be searching answers for a platform you are currently not working on so you'll add --platform <target_platform> too.

I mean this is exactly what man supports also:

$ man <tool>
$ man -k <query> # analogous to `--search`

while listing all pages is available by means of empty query but it certainly isn't something that is endorsed by having dedicated option like --list-(almost/maybe/platform/common)-all 🙃

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Alright then, let's go with default being current platform and having a reserved platform all.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great discussion! I'll update the spec to reflect this.

Met me know if I miss anything :P


Clients MAY support additional custom arguments not documented here.

Here are some examples invocations using the above flags:

```bash
tldr --update
tldr --version
tldr -a
```

### Page Names
The first argument that does not start with a dash (`-`) MUST be considered the page name.

In addition, page names MAY contain spaces (e.g. `git status`) - such page names MUST be transparently concatenated with dashes (`-`). For example, the page name:

```
git checkout
```

...becomes this:

```
git-checkout
```

Here are some example invocations:

```bash
tldr 7za
tldr eyeD3
tldr git checkout
# In the below, "--foo" is a custom argument that takes a parameter.
tldr --foo bar bash
```

#### Specifying the Platform
As pages are grouped by platform, a user may want to access a platform-specific version of a page. This MUST be supported by prefixing the page name as follows:

```
windows/type
linux/sh
osx/brew
```
sbrl marked this conversation as resolved.
Show resolved Hide resolved

Example invocations are as follows:

```bash
tldr windows/type
# --foo is a custom argument, as described above
tldr --foo bar common/git merge
sbrl marked this conversation as resolved.
Show resolved Hide resolved
tldr linux/notify-send
```


## Directory Structure
This section documents the directory structure that contains the pages themselves.

The master version of every page is stored inside (but not directly) the `pages` directory. Inside this directory, there is a folder for each platform - for example `windows`, `linux`, and the special `common` platform:

- `pages/`
+ `common/`
+ `linux/`
+ `windows/`
+ `osx/`
sbrl marked this conversation as resolved.
Show resolved Hide resolved
+ .....etc.

Additional platforms MAY be added in the future. Clients MAY NOT support new platforms (though such support is RECOMMENDED), but MUST NOT break if additional platforms are added.

The pages themselves sit inside the appropriate platform folder, with the extension `.md`. Here are some example mappings:

Command name | Mapped name | Filename
----------------|-------------------|-------------------
`7za` | `7za` | `7za.md`
`git checkout` | `git-checkout` | `git-checkout.md`
`tar` | `tar` | `tar.md`


### Translations
Other directories sit alongside the main `pages` directory, and contain translations of the master versions of every page - though pages MAY NOT have a translation available for a given language yet. Furthermore, a given language MAY NOT have a folder yet either. The format of these directories is `pages.{language-tag}`, where `{language-tag}` is a [BCP 47](https://tools.ietf.org/html/bcp47) conforming tag in the form of `<language>-<region>`, where:

- `<language>` is the shortest [ISO 639](https://en.wikipedia.org/wiki/ISO_639) language code for the chosen language (see [here](https://en.wikipedia.org/wiki/List_of_ISO_639-2_codes) for a complete list).
- `<region>` is the two-letter [ISO 3166-1](https://en.wikipedia.org/wiki/ISO_3166-1) region code for the chosen region (see [here](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2#Officially_assigned_code_elements) for a complete list).

Some examples:

- Chinese (Taiwan): `pages.zh-TW`.
- Portuguese (Brazil): `pages.pt-BR`.
- German (Germany): `pages.de-DE`.

You can check the validity of BCP 47 tags [here](http://schneegans.de/lv/).

The structure inside these translation folders is identical to that of the main `pages` folder.

**Note to self: A portion of this section is from [PR #2703](https://github.com/tldr-pages/tldr/pull/2703).**


## Page Structure
Although this specification is about the interface that clients must provide, it is also worth noting that pages are written in standard [CommonMark](https://commonmark.org/), which the exception of the non-standard `{{` and `}}` syntax, which surrounds values in an example that users may edit. Clients MUST NOT break if the page format is changed within the _CommonMark_ specification.


## Page Resolution
This section defines the algorithm by which a client can decide which page a user has requested.

After transparently replacing spaces (` `) with dashes (`-`), clients have several decisions to make:

- The language of a page to display to a client
- The platform to display a page from

### Platform
Clients MUST default to displaying tldr-page from the platform upon which the client is running. For example, a client running on _Windows 10_ will default to displaying pages from the `windows` platform. Clients MAY provide a user-configurable option to override this behaviour, however.

If a page is not available for the host platform, clients MUST fallback to the special `common` platform.

If a page is not available for either the host platform or the `common` platform, then clients SHOULD search other platforms and display a page from there - along with a warning message.

For example, a user has a client on windows, and requests the `apt` page. The client consults the platforms in the following order:

1. `windows` - Not available
2. `common` - Not available
3. `osx` - Not available
4. `linux` - Page found

Steps #3 and #4 may be done in either order.

#### If a page isn't found
If a page cannot be found in _any_ platform, then it is RECOMMENDED that clients display an error message with a link to create a new issue against the `tldr-pages/tldr` GitHub repository. Said link might take the following form:

```url
https://github.com/tldr-pages/tldr/issues/new?title=page%20request:%20{command_name}
```

....where `{command_name}` is the name of the command that was not found.

#### If multiple versions of a page were found
If multiple versions of a page were found for different platforms, then a client MAY choose to display a notice to the user notifying them of this.

## Language
Pages can be written in multiple languages. If a client has access to environment variables, several standard ones exist to specify the language in which a client should operate. If not, then clients MUST make reasonable assumptions based on the information provided by the environment in which they operate (e.g. consulting `navigator.languages` in a browser, etc.).

The [`LANG` environment variable](https://www.gnu.org/software/gettext/manual/html_node/Locale-Environment-Variables.html) MUST be used to determine both the language of a page to display, and the display language of any interface text shown to the user (e.g. things like `Cache updated successfully`, for example).

Additionally, the [`LC_MESSAGES` environment variable](https://www.gnu.org/software/gettext/manual/html_node/Locale-Environment-Variables.html) MAY be present. If specified, clients MUST use it's value to determine the language in which interface text is shown in (separately from the language to display the page in).

Finally, the [`LANGUAGE` environment variable](https://www.gnu.org/software/gettext/manual/html_node/The-LANGUAGE-variable.html) specifies a priority list of languages that a user wishes to read in. If present, a client MUST use the defined priority list to decide on the language that to display in.

If a page is not available in the user's preferred language, then a client MUST respect the user's priority list defined in the `LANGUAGE` variable (if specified), and MAY choose to notify the user that a page in their chosen language couldn't be found (perhaps along with a link to the [translations section of the contributing guide](https://github.com/tldr-pages/tldr/blob/master/CONTRIBUTING.md#translations)).

## Other Considerations
This section contains a number of other items that don't neatly fit into any of the sections defined above.

If appropriate, it is RECOMMENDED that clients implement a cache of pages. If implemented, clients MUST download the _entire_ archive from **UNKNOWN_LOCATION**.

Additionally, clients MAY automatically update the cache on a regular basis.