A very fast implementation of tldr in Rust

Overview

tealdeer

teal deer

Crate CI (Linux/macOS/Windows)
Crates.io GitHub CI

A very fast implementation of tldr in Rust: Simplified, example based and community-driven man pages.

Screenshot of tldr command

If you pronounce "tldr" in English, it sounds somewhat like "tealdeer". Hence the project name :)

In case you're in a hurry and just want to quickly try tealdeer, you can find static binaries on the GitHub releases page!

Docs (Installing, Usage, Configuration)

User documentation is available at https://dbrgn.github.io/tealdeer/!

The docs are generated using mdbook. They can be edited through the markdown files in the docs/src/ directory.

Goals

High level project goals:

  • Download and cache pages
  • Don't require a network connection for anything besides updating the cache
  • Command line interface similar or equivalent to the NodeJS client
  • Be fast

A tool like tldr should be as frictionless as possible to use. It should be easy to invoke (just tldr tar, not using another subcommand like tldr find tar) and it should show the output as fast as possible.

tealdeer reaches these goals. During a (highly non-scientific) test (see #38 for details), I tested the invocation speed of tldr for a few of the existing clients:

Client Times (ms) Avg of 5 (ms)
Tealdeer 15/11/5/5/11 9.4 (100%)
C client 11/5/12/11/15 10.8 (115%)
Bash client 15/19/22/25/24 21.0 (223%)
Go client by k3mist 98/96/100/95/101 98.8 (1'051%)
Python client 152/148/151/158/140 149.8 (1'594%)
NodeJS client 169/171/170/170/170 170.0 (1'809%)

tealdeer was the winner here, although the C client and the Bash client are in the same speed class. Interpreted languages are clearly much slower to invoke, a delay of 170 milliseconds is definitely noticeable and increases friction for the user.

These are the clients I tried but failed to compile or run: Haskell client, Ruby client, Perl client, Go client by anoopengineer, PHP client.

Development

Creating a debug build with logging enabled:

$ cargo build --features logging

Release build without logging:

$ cargo build --release

To enable the log output, set the RUST_LOG env variable:

$ export RUST_LOG=tldr=debug

To run tests:

$ cargo test

To run lints:

$ rustup component add clippy
$ cargo clean && cargo clippy

MSRV (Minimally Supported Rust Version)

When publishing a Tealdeer release, the Rust version required to build it should be stable for at least a month.

License

Licensed under either of

Contribution

Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.

Thanks to @SShrike for coming up with the name "tealdeer"!

Comments
  • macOS panicks with --update: MissingOrMalformedExtensions

    macOS panicks with --update: MissingOrMalformedExtensions

    This is the new 1.5.0 version:

    ❯ tldr  --version
    tealdeer 1.5.0
    
    ❯ brew info tealdeer
    tealdeer: stable 1.5.0 (bottled)
    Very fast implementation of tldr in Rust
    https://github.com/dbrgn/tealdeer
    Conflicts with:
      tldr (because both install `tldr` binaries)
    /opt/homebrew/Cellar/tealdeer/1.5.0 (12 files, 4.3MB) *
      Poured from bottle on 2022-01-01 at 11:05:57
    From: https://github.com/Homebrew/homebrew-core/blob/HEAD/Formula/tealdeer.rb
    License: Apache-2.0
    ==> Dependencies
    Build: rust ✘
    ==> Caveats
    zsh completions have been installed to:
      /opt/homebrew/share/zsh/site-functions
    

    Here's the full backtrace:

    ❯ RUST_BACKTRACE=full tldr -u
    thread 'main' panicked at 'Client::new(): reqwest::Error { kind: Builder, source: MissingOrMalformedExtensions }', /Users/brew/Library/Caches/Homebrew/cargo_cache/registry/src/github.com-1ecc6299db9ec823/reqwest-0.11.8/src/blocking/client.rs:798:38
    stack backtrace:
       0:        0x102dfd988 - <std::sys_common::backtrace::_print::DisplayBacktrace as core::fmt::Display>::fmt::ha47ac0a9192e239e
       1:        0x102c804f4 - core::fmt::write::hfbe6a7b828c32513
       2:        0x102def8ec - std::io::Write::write_fmt::h34cd061a987d18fd
       3:        0x102defe80 - std::panicking::default_hook::{{closure}}::h2b5c2a08263c3d54
       4:        0x102df09f8 - std::panicking::rust_panic_with_hook::h36a6e8d335334d30
       5:        0x102dfe020 - std::panicking::begin_panic_handler::{{closure}}::h71decad72c0b1843
       6:        0x102dfdf8c - std::sys_common::backtrace::__rust_end_short_backtrace::hfd636421a82c4798
       7:        0x102df02c4 - _rust_begin_unwind
       8:        0x102e886f4 - core::panicking::panic_fmt::hebdff93de232aa26
       9:        0x102e88c68 - core::result::unwrap_failed::hf00c663ffab666bd
      10:        0x102e180dc - tldr::cache::Cache::update::hb0cdc3544a17b6e3
      11:        0x102e2b0a0 - tldr::main::h3a2425d2761a091a
      12:        0x102e22778 - std::sys_common::backtrace::__rust_begin_short_backtrace::h5861f9871dbcaf49
      13:        0x102e28aa0 - _main
    
    bug 
    opened by storopoli 32
  • chore: download main instead of master

    chore: download main instead of master

    In relation to this tldr release, tldr clients should use the main branch and not the master branch. The master branch is simply a mirror of main right now and will be removed in the future, so I thought I might as well fix this real quick.

    waiting-for-author 
    opened by invakid404 26
  • Hyperfine benchmarks

    Hyperfine benchmarks

    Closes #129

    I started putting together a Dockerfile that gets all the clients and benches them with hyperfine. I decided to do it all in Docker, because I would not want to have all the clients on my system and to make it accessible for third parties to easily verify the results that our benchmarks produce.

    At the time of writing, only tealdeer and the C client are compared, but I will add more clients.

    Eventually, we could think about running benchmarks in CI, but this is not the focus of this PR.

    opened by niklasmohrin 24
  • Feature/improve colour contrast

    Feature/improve colour contrast

    What

    • Change default colour scheme to high contrast using terminal default colour
    • Highlight program name in code examples

    Before: screenshot_20180708_173111 After: screenshot_20180708_173320

    Why

    Right now the only reason I use a painfully slow python version of tldr is because its colour scheme makes quickly glancing at a tldr and seeing what I'm looking for much easier than when looking at the monotone low contrast produced by the current version of tealdeer. The current contrast of most likely dark background to teal is challenging for certain people with colour blindness. I understand that the project is called tealdear and removing the teal colour might make the pun obsolete. If you prefer the old colour scheme, I suggest making it an option. People that want another scheme could do alias tldr=tldr --color=teal.

    Implementation Notes

    I chose to go with string indexing over split and flat_map as I wanted to avoid a performance regression. In a micro benchmark, format_code is faster and more consistent than format_braces whilst doing more work. Yet it is seems to be only a small fraction of the overall time, which means I wouldn't be opposed to rewriting it in a more readable fashion. Pulling the command from the title isn't pretty, the command name is present when called regularly, however when using the option --render we would have to either introduce a new parameter to specify the command, which would increase usage burden and could introduce user errors, or accept different behavior for regular use vs --render which I find particular bad. This solution doesn't change the current interface and behaves the same way in regular use and --render. However I have not tested if all tldr files correctly specify the program title in their title.

    opened by Voultapher 21
  • Upload to crates.io

    Upload to crates.io

    I'd like to put a version of tldr on crates.io that supports an offline cache. The name is already taken though (rilut/rust-tldr#1).

    Therefore I'd go with another name. A few ideas:

    • toolong
    • tldr-rs

    Any other ideas? The binary name could also be different from the crate name I guess.

    cc @SShrike

    opened by dbrgn 20
  • #36 add -p --pager flag to page the output using pager crate

    #36 add -p --pager flag to page the output using pager crate

    I just added the pager crate and a flag (-p --pager) to enable or disable it.

    BTW, I have tested it with Rust 1.28.0 and it works well, maybe you can update.

    I would need help for windows and macOS testers.

    refs #36

    opened by jdvr 18
  • `tldr --update` output is displayed by pager

    `tldr --update` output is displayed by pager

    When ~~a pager is configured, e.g. less,~~ display.use_pager is set to true, the output of tldr --update is displayed in the pager.

    Info messages should be displayed as typical output, like STDERR, regardless of pager config.

    bug 
    opened by tranzystorek-io 17
  • Support custom pages and patches

    Support custom pages and patches

    Feature implementation for issue #98 This is a feature that lets you create custom tldr pages locally. You can set a directory where tealdeer will search for these local pages with the env variable TEALDEER_CUSTOM_PAGES_DIR. If this is not set then it will use the tldr-master/pages.custom

    If you give a custom tldr page the same name as an existing one, then your custom one will be appended to it.

    Example with existing tldr page:
    Example with no existing tldr page:

    I find the value added here is that overtime a person can build their own collection of common use-cases to a particular command that they use semi-frequently. I created this because I would create my own repository of command specific use-cases, and to document personalized scripts for myself.

    Side note: This is my first real open-source contribution, and I'm not super familiar w/ the ins and outs of rust. Please leave suggestions for improvements :smile: .

    Update, Dec 18. Implemented suggested changes from @dbrgn

    • Implemented .page and .patch differences. {}.page files overwrite existing tldr entries. {}.patch appends to existing entries.
    • Now using the config file for custom_pages_dir, default directory is CONFIGDIR/pages
    • ~Also added 2 flags, --patch and --overwrite. These commands create and or open the .page or .patch files in your $EDITOR. I added this because I found it was annoying to constantly switch the the custom page directory. Also this enables people to very quickly make changes to their custom patches/pages~
    Example of a .patch file in work
    Example of a new tldr page with a .page file
    Example of overwriting an existing tldr page using a .page file
    How the config looks now
    opened by dmaahs2017 14
  • --update no longer works behind proxies after switching to reqwest

    --update no longer works behind proxies after switching to reqwest

    It looks like #61 has broken cache updating behind proxies:

    Commit e73261542cc601408596fb404c57d54f8cbc6bf7 (just before switching to reqwest):

    $ git checkout e73261542cc601408596fb404c57d54f8cbc6bf7
    $ cargo build
    $ target/debug/tldr --update
    Successfully updated cache.
    

    Master branch:

    $ git checkout master
    $ cargo build
    $ target/debug/tldr --update
    Could not update cache: HTTP error: https://github.com/tldr-pages/tldr/archive/master.tar.gz: timed out
    
    
    opened by aldanor 13
  • Release with github workflow

    Release with github workflow

    image Issue: #165

    I created a workflow that puts Mac into the release. You don't have to expose the GitHub key.

    Here's how to permanently erase files from the Git History:

    git filter-branch --tree-filter 'rm -rf ./release-build.sh' HEAD
    git filter-branch --prune-empty HEAD
    git push origin --force master
    
    opened by black7375 12
  • Allow --update from a local tarball; allow disabling update warnings

    Allow --update from a local tarball; allow disabling update warnings

    Two simple changes would make tealdeer more offline-use friendly. In particular, when packaging it for use in an offline environment, one could include tldr's tarball (master.tar.gz) in the package itself, and make it run tldr --update <tarball> when installing.

    Related: it would be nice to be able to disable "Cache wasn't updated for more than 30 days" warning (maybe at build time) -- if you're in an offline environment, you can't really update it so it's just an annoyance...

    enhancement 
    opened by aldanor 12
  • Tabular compact mode

    Tabular compact mode

    It seems that even the compact mode isn't compact enough :), but more importantly, I don't like the style of commands as secondary since I'm used to all cli tools showing commands first and description second

    I'd like to suggest a tabular compact mode that is also easier to scan since the commands and comments are cleanly separated into columns (and not having to repeat the main command brew helps in increasing the tldr factor ;)):

    The first column width should have some max limit, so that very long commands would just "overflow", but due to the support of colors it'd still be easy to visually separate them from the description

    ↓brew (package manager for macOS and Linux <https://brew.sh>)
     install formula	Install the latest stable version of a formula or cask (use `--devel` for development versions)
     list           	List all installed formulae and casks
     upgrade formula	Upgrade an installed formula or cask (if none is given, all installed formulae/casks are upgraded)
     update         	Fetch the newest version of Homebrew and of all formulae and casks from the Homebrew source repository
     outdated       	Show formulae and casks that have a more recent version available
     search text    	Search for available formulae (i.e. packages) and casks (i.e. native packages)
     info formula   	Display information about a formula or a cask (version, installation path, dependencies, etc.)
     doctor         	Check the local Homebrew installation for potential problems
    

    instead of this

      Package manager for macOS and Linux.
      More information: <https://brew.sh>.
      Install the latest stable version of a formula or cask (use `--devel` for development versions):
          brew install formula
      List all installed formulae and casks:
          brew list
      Upgrade an installed formula or cask (if none is given, all installed formulae/casks are upgraded):
          brew upgrade formula
      Fetch the newest version of Homebrew and of all formulae and casks from the Homebrew source repository:
          brew update
      Show formulae and casks that have a more recent version available:
          brew outdated
      Search for available formulae (i.e. packages) and casks (i.e. native packages):
          brew search text
      Display information about a formula or a cask (version, installation path, dependencies, etc.):
          brew info formula
      Check the local Homebrew installation for potential problems:
          brew doctor
    
    opened by eugenesvk 6
  • Allow overriding via env vars custom pages/patches (just like config/cache)

    Allow overriding via env vars custom pages/patches (just like config/cache)

    opened by eugenesvk 8
  • Allow building with native-tls

    Allow building with native-tls

    Right now we only support building with Rustls. However, there are quite a few architectures that aren't yet supported by "ring" (the crypto library used by Rustls), for example MIPS, PowerPC or SPARC.

    To offer an alternative, I added the "native-tls" feature that can be used instead of "native-roots". When used, the native TLS stack is used instead of Rustls (i.e. SChannel on Windows, Secure Transport on macOS and OpenSSL otherwise).

    opened by dbrgn 0
  • Specify Multiple OS

    Specify Multiple OS

    Fix for an old issue #45 - to allow specifying multiple platforms on the cli. Behaviour is to try get the tldr page for each platform given - so if a page doesn't exist for one platform but does for another, you still get the page displayed.

    opened by jj-style 3
  • Migrate to Clap v4

    Migrate to Clap v4

    Again, this is a pretty big update with multiple breaking changes that requires changing how our argument parsing is set up. (If I ignore the effort to upgrade, this update does contain some nice API improvements, so I guess in the long term it's worth it. The blogpost is an interesting read.)

    This is still WIP, I'm opening this PR to avoid duplicate work on this.

    chore 
    opened by dbrgn 0
  • Add auto generate completions for some shells

    Add auto generate completions for some shells

    This is a requested function that solves problem #268 by generating automatic autocompletions and allows updating the cache

    • [x] Check format
    • [x] Check clippy
    • [x] test commands implementation

    Supported Shells

    • Bash
    • Zsh
    • Fish
    • Powershell
    • Elvish
    opened by SergioRibera 2
Releases(v1.6.1)
A cli based pastebin in Rust, but very insecure

pasta A cli based pastebin in Rust, but very insecure Use nightly toolchain to build rustup override set nightly When this program is running, you can

Snehit Sah 3 Mar 25, 2022
Learning Rust through Advent of Code 2021 - probably not very clean!

AoC 2021 ======== I'm using AoC2021 as an excuse to learn Rust (and maybe some other languages). Please do *not* use this repository as a good source

Andrew Zhu 0 Dec 8, 2021
🐱 HQ9C is a very serioues compiler for HQ9+, it meta-compiles with Rust.

HQ9+ Compiler HQ9c (Or HQ9+ Compiler) is a blockchain-based NFT minting AI machine-learning cloud infraestructure for the compiling of the great progr

Alex 5 Aug 28, 2022
A very basic show-case of rust on the esp32 in 2022

Readme This example code does the following: Set up a WiFi connection on the ESP32-C3 Spawn a thread using std::thread in which we listen for incoming

Mattia 13 Jan 19, 2023
F-Fetch targets low systems. Written in Rust. It's very simple, designed so you can pick it up and replace it.

F-Fetch F-Fetch targets low systems. Written in Rust. It's very simple, designed so you can pick it up and replace it. First Look ~/.config/ffetch/con

cd 3 Jul 10, 2023
A very tiny terminal snake game, purely implemented in Rust.

tiny-snake.rs A very tiny terminal snake game, purely implemented in Rust. Features Optimized binary has only 2760 bytes. No dependencies. Not even li

Rodrigo Batista de Moraes 59 Aug 16, 2023
A very simple third-party cargo subcommand to execute a custom command

cargo-x A very simple third-party cargo subcommand to execute a custom command Usage install cargo-x cargo install cargo-x or upgrade cargo install -

刘冲 9 Dec 26, 2022
A very opinionated, zero-configuration shell prompt

A very opinionated, zero-configuration shell prompt

amy null 8 Nov 4, 2021
Fls - Ferris-LS, a very bad LS replacement. Besides that, proves that I suck at clean & good code.

FLS A handy ls remake, purely for learning. Why FLS? There's no reason, at all, don't use it. I just want to learn Rust :D Usage Flags: -i = Use icons

florida 6 Jan 24, 2022
dlfile is a very simple, straightforward CLI to download a file

dlfile dlfile is a very simple, straightforward CLI to download a file, except it... Only downloads over HTTPS Requires TLS 1.2 or higher Executes in

Colin 3 Oct 21, 2022
Work out how far apart things should be (very quickly)

Kern determiner Work out how far apart things should be (very quickly) kerndeterminer is a Rust-based library for determining a kern value between two

Simon Cozens 10 Oct 29, 2022
A blazingly fast rust-based bionic reader for blazingly fast reading within a terminal console 🦀

This Rust-based CLI tool reads text and returns it back in bionic reading format for blazingly fast loading and even faster reading! Bionic reading is

Ismet Handzic 5 Aug 5, 2023
PyO3 bindings and Python interface to skani, a method for fast fast genomic identity calculation using sparse chaining.

?? ⛓️ ?? Pyskani PyO3 bindings and Python interface to skani, a method for fast fast genomic identity calculation using sparse chaining. ??️ Overview

Martin Larralde 13 Mar 21, 2023
A fast and lightweight HTTP server implementation in Rust.

server_nano A tiny, fast, and friendly web server written in rust and inspired by express. It uses may to coroutines Usage First, add this to your Car

Jonny Borges 5 May 2, 2023
Pure-Rust implementation of Fast Static Symbol Tables string compression

fsst-rs A pure-Rust, zero-dependency implementation of the FSST string compression algorithm. FSST is a string compression algorithm meant for use in

Spiral 78 Sep 29, 2024
🐎 A fast implementation of the Aho-Corasick algorithm using the compact double-array data structure. (Python wrapper for daachorse)

python-daachorse daachorse is a fast implementation of the Aho-Corasick algorithm using the compact double-array data structure. This is a Python wrap

Koichi Akabe 11 Nov 30, 2022
A SIMD implementation of Keccak256 for aarch64, forked from Remco Bloeman's Goldilocks K12 implementation.

keccak256-aarch64 Warning This crate was forked from real cryptographers (Goldilocks by Remco Bloeman), by not a real cryptographer. Do not use this k

null 6 Oct 24, 2023
A full featured, fast Command Line Argument Parser for Rust

clap Command Line Argument Parser for Rust It is a simple-to-use, efficient, and full-featured library for parsing command line arguments and subcomma

null 10.4k Jan 10, 2023
⚡️ Lightning-fast and minimal calendar command line. Written in Rust 🦀

⚡️ Lightning-fast and minimal calendar command line. It's similar to cal. Written in Rust ??

Arthur Henrique 36 Jan 1, 2023