From 7187c026cdf36f61cd6e0f4ff05dcb9f1770bde1 Mon Sep 17 00:00:00 2001 From: Alexis Opolka <53085471+alexis-opolka@users.noreply.github.com> Date: Thu, 6 Feb 2025 09:06:35 +0100 Subject: [PATCH 01/63] Update docs Create a folder for the configuration of navi --- docs/configuration/README.md | 1 + 1 file changed, 1 insertion(+) create mode 100644 docs/configuration/README.md diff --git a/docs/configuration/README.md b/docs/configuration/README.md new file mode 100644 index 0000000..6946aa3 --- /dev/null +++ b/docs/configuration/README.md @@ -0,0 +1 @@ +# Configuration of Navi \ No newline at end of file From 37a2ea7550c31b3901f7dcf65e232d890d2465fe Mon Sep 17 00:00:00 2001 From: Alexis Opolka <53085471+alexis-opolka@users.noreply.github.com> Date: Thu, 6 Feb 2025 09:07:26 +0100 Subject: [PATCH 02/63] Update docs Created an installation documentation --- docs/installation/README.md | 1 + 1 file changed, 1 insertion(+) create mode 100644 docs/installation/README.md diff --git a/docs/installation/README.md b/docs/installation/README.md new file mode 100644 index 0000000..b5a512c --- /dev/null +++ b/docs/installation/README.md @@ -0,0 +1 @@ +# Installation of navi \ No newline at end of file From 56e39587eb7827fc4221501ac4c7044d32202b8d Mon Sep 17 00:00:00 2001 From: Alexis Opolka <53085471+alexis-opolka@users.noreply.github.com> Date: Thu, 6 Feb 2025 09:09:06 +0100 Subject: [PATCH 03/63] Moved content from docs/installation to docs/installation/ --- docs/installation/README.md | 161 +++++++++++++++++++++++++++++++++++- 1 file changed, 160 insertions(+), 1 deletion(-) diff --git a/docs/installation/README.md b/docs/installation/README.md index b5a512c..e3c223d 100644 --- a/docs/installation/README.md +++ b/docs/installation/README.md @@ -1 +1,160 @@ -# Installation of navi \ No newline at end of file +# Installation of navi + + +--- + +WIP below + + +## Installation + +- [Installing the main binary](#installing-the-main-binary) + - [Using Homebrew](#using-homebrew) + - [Using Gentoo](#using-gentoo) + - [Using nix](#using-nix) + - [Using cargo](#using-cargo) + - [Using install script](#using-install-script) + - [Downloading pre-compiled binaries](#downloading-pre-compiled-binaries) + - [Building from source](#building-from-source) + - [Other package managers](#other-package-managers) +- [Installing the shell widget](#installing-the-shell-widget) + +### Installing the main binary + +#### Using [Homebrew](http://brew.sh/) + +```sh +brew install navi +``` + +#### Using [Gentoo](https://gentoo.org/) + +Be sure to [enable](https://wiki.gentoo.org/wiki/Ebuild_repository) the [GURU overlay](https://gpo.zugaina.org/Overlays/guru/app-misc/navi). + +```sh +emerge -a app-misc/navi +``` + +#### Using [pacman](https://wiki.archlinux.org/title/Pacman) + +```sh +pacman -S navi +``` + +#### Using [nix](https://nixos.org/) + +```sh +nix-env -iA nixpkgs.navi +``` + +#### Using [cargo](https://github.com/rust-lang/cargo) + +```bash +cargo install --locked navi +``` + +#### Using [choco](https://community.chocolatey.org/packages/navi) + +For Windows user, using powershell + +1. Install package via choco + ```bash + choco install navi + ``` +2. Create `$env:USERPROFILE\AppData\Roaming\navi\config.yaml` and override `shell.command` as per [config_file_example.yaml](./config_file_example.yaml) + + ``` + style: + tag: + color: cyan + comment: + color: grey + snippet: + color: white + + shell: + command: powershell + ``` + + Remark: Above example also adds custom colors for better readability in case you use standard blue for your Powershell + +#### Using install script + +```bash +bash <(curl -sL https://raw.githubusercontent.com/denisidoro/navi/master/scripts/install) + +# (optional) to set directories: +# BIN_DIR=/usr/local/bin bash <(curl -sL https://raw.githubusercontent.com/denisidoro/navi/master/scripts/install) +``` + +#### Downloading pre-compiled binaries + +- download the correct binary [here](https://github.com/denisidoro/navi/releases/latest) +- extract the content to your `$PATH` + +#### Building from source + +```bash +git clone https://github.com/denisidoro/navi ~/.navi +cd ~/.navi +make install + +# (optional) to set the install directory: +# make BIN_DIR=/usr/local/bin install +``` + +##### Compile time environment variables + +**navi** supports environment variables at compile time that modify the behavior of the binary at runtime: + +- `NAVI_PATH` (directory path value): If the `cheats` directory in the user's directory does not exist, **navi** uses this path (if it exists), as a fallback location to look for cheat files. Use case: system-wide installed, shared used cheatsheets folder. +- `NAVI_CONFIG` (file path value): If the `config.yaml` file in the user's directory does not exist, **navi** uses this path (if it exists), as a fallback location to look for a configuration file. Use case: system-wide installed, shared used configuration file. + +#### Other package managers + +You can find **navi** for more package managers by clicking on the image below: + +[![Packaging status](https://repology.org/badge/vertical-allrepos/navi.svg)](https://repology.org/project/navi/versions) + +Feel free to be the maintainer of **navi** for any package manager you'd like! + +### Installing the shell widget + +If you want to install it, add this line to your `.bashrc`-like file: + +```sh +# bash +eval "$(navi widget bash)" + +# zsh +eval "$(navi widget zsh)" + +# fish +navi widget fish | source + +# elvish +eval (navi widget elvish | slurp) + +# xonsh +# xpip install xontrib-navi # ← run in your xonsh session to install xontrib +xontrib load navi # ← add to your xonsh run control file +``` + +#### Nushell + +Due to Nushell's [unique design](https://www.nushell.sh/book/thinking_in_nu.html#think-of-nushell-as-a-compiled-language), it is not possible to `eval` a piece of code dynamically like in other shells therefore the integration process is a bit more involved. Here is an example: +1. run `^navi widget nushell | save ($nu.default-config-dir | path join "navi-integration.nu")` +2. add the following lines to `config.nu`: + ```nushell + source ($nu.default-config-dir | path join "navi-integration.nu") + ``` + + +By default, `Ctrl+G` is assigned to launching **navi** (in xonsh can be customized with `$X_NAVI_KEY`, see [xontrib-navi](https://github.com/eugenesvk/xontrib-navi) for details). + +There's currently no way to customize the widget behavior out-of-the-box. If you want to change the keybinding or the **navi** flags used by the widget, please: + +1. run, e.g., `navi widget bash` in your terminal +2. copy the output +3. paste the output in your `.bashrc`-like file +4. edit the contents accordingly From 21b9e3202801ef30b27d224d083456619f55b62b Mon Sep 17 00:00:00 2001 From: Alexis Opolka <53085471+alexis-opolka@users.noreply.github.com> Date: Thu, 6 Feb 2025 09:11:04 +0100 Subject: [PATCH 04/63] Update docs Created a cheatsheet folder --- docs/cheatsheet/README.md | 1 + 1 file changed, 1 insertion(+) create mode 100644 docs/cheatsheet/README.md diff --git a/docs/cheatsheet/README.md b/docs/cheatsheet/README.md new file mode 100644 index 0000000..c8eca6e --- /dev/null +++ b/docs/cheatsheet/README.md @@ -0,0 +1 @@ +# Navi cheatsheets \ No newline at end of file From 64f6016d6ab043f8ee12c612a66f814d25ca1170 Mon Sep 17 00:00:00 2001 From: Alexis Opolka <53085471+alexis-opolka@users.noreply.github.com> Date: Thu, 6 Feb 2025 09:12:12 +0100 Subject: [PATCH 05/63] Update cheatsheet --- docs/cheatsheet/src/example.cheat | 44 +++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 docs/cheatsheet/src/example.cheat diff --git a/docs/cheatsheet/src/example.cheat b/docs/cheatsheet/src/example.cheat new file mode 100644 index 0000000..0e68698 --- /dev/null +++ b/docs/cheatsheet/src/example.cheat @@ -0,0 +1,44 @@ +% cheatsheets + +# Download default cheatsheets +navi repo add denisidoro/cheats + +# Browse for cheatsheet repos +navi repo browse + +# Edit main local cheatsheets +f="$(navi info cheats-path)/main.cheat" +[ -f "$f" ] || navi info cheats-example > "$f" +${EDITOR:-nano} "$f" + + +% config + +# Edit config file +f="$(navi info config-path)" +[ -f "$f" ] || navi info config-example > "$f" +${EDITOR:-nano} "$f" + + +% 3rd-party + +# Search using tldr +navi --tldr "" + +# Search using cheatsh +navi --cheatsh "" + + +% widget + +# Load shell widget +shell="$(basename $SHELL)"; eval "$(navi widget $shell)" + + +% help + +# Read command-line help text +navi --help + +# Read project README.md +navi fn url::open "https://github.com/denisidoro/navi" From 4acd555436e45ed59227574dc69c7c4b1ce534fb Mon Sep 17 00:00:00 2001 From: Alexis Opolka <53085471+alexis-opolka@users.noreply.github.com> Date: Thu, 6 Feb 2025 09:12:53 +0100 Subject: [PATCH 06/63] Update docs --- docs/deprecated/Alfred/README.md | 1 + 1 file changed, 1 insertion(+) create mode 100644 docs/deprecated/Alfred/README.md diff --git a/docs/deprecated/Alfred/README.md b/docs/deprecated/Alfred/README.md new file mode 100644 index 0000000..9c696e8 --- /dev/null +++ b/docs/deprecated/Alfred/README.md @@ -0,0 +1 @@ +# Alfred \ No newline at end of file From fc60240876240b53dc53aa8024b8ea3962e7cc1e Mon Sep 17 00:00:00 2001 From: Alexis Opolka <53085471+alexis-opolka@users.noreply.github.com> Date: Thu, 6 Feb 2025 09:14:25 +0100 Subject: [PATCH 07/63] Update README.md --- docs/deprecated/Alfred/README.md | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/docs/deprecated/Alfred/README.md b/docs/deprecated/Alfred/README.md index 9c696e8..49858a9 100644 --- a/docs/deprecated/Alfred/README.md +++ b/docs/deprecated/Alfred/README.md @@ -1 +1,22 @@ -# Alfred \ No newline at end of file +# Alfred + +> [!CAUTION] +> This feature has been deprecated + + +This is _experimental_. If you face any issues, please report [here](https://github.com/denisidoro/navi/issues/348). + +![Alfred demo](https://user-images.githubusercontent.com/3226564/80294838-582b1b00-8743-11ea-9eb5-a335d8eed833.gif) + +### Note + +Support for alfred has been removed. + +The latest version which has some support for it is [2.15.1](https://github.com/denisidoro/navi/releases/tag/v2.15.1). + +### Instructions + +- make sure you have [Alfred Powerpack](https://www.alfredapp.com/powerpack/) +- make sure **navi** [2.15.1](https://github.com/denisidoro/navi/releases/tag/v2.15.1) is installed +- make sure that the `navi` binary is in the `$PATH` determined by `~/.bashrc` +- download and install the [latest .alfredworkflow available](https://github.com/denisidoro/navi/releases/tag/v2.15.1) From abe6d5b112cd84a542eff2fa523601148c9326f4 Mon Sep 17 00:00:00 2001 From: Alexis Opolka <53085471+alexis-opolka@users.noreply.github.com> Date: Thu, 6 Feb 2025 09:16:49 +0100 Subject: [PATCH 08/63] Update README.md --- docs/deprecated/Alfred/README.md | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/docs/deprecated/Alfred/README.md b/docs/deprecated/Alfred/README.md index 49858a9..357c567 100644 --- a/docs/deprecated/Alfred/README.md +++ b/docs/deprecated/Alfred/README.md @@ -1,19 +1,15 @@ # Alfred > [!CAUTION] -> This feature has been deprecated +> This feature has been deprecated and support has been dropped since 2.16.0. +> +> The latest version with support is [2.15.1](https://github.com/denisidoro/navi/releases/tag/v2.15.1). This is _experimental_. If you face any issues, please report [here](https://github.com/denisidoro/navi/issues/348). ![Alfred demo](https://user-images.githubusercontent.com/3226564/80294838-582b1b00-8743-11ea-9eb5-a335d8eed833.gif) -### Note - -Support for alfred has been removed. - -The latest version which has some support for it is [2.15.1](https://github.com/denisidoro/navi/releases/tag/v2.15.1). - ### Instructions - make sure you have [Alfred Powerpack](https://www.alfredapp.com/powerpack/) From d8261c4e2da52e68cb1a39e07cf314c8ae6a0b46 Mon Sep 17 00:00:00 2001 From: Alexis Opolka <53085471+alexis-opolka@users.noreply.github.com> Date: Thu, 6 Feb 2025 09:22:08 +0100 Subject: [PATCH 09/63] Update docs Created a folder for widgets. --- docs/widgets/README.md | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 docs/widgets/README.md diff --git a/docs/widgets/README.md b/docs/widgets/README.md new file mode 100644 index 0000000..e8f344d --- /dev/null +++ b/docs/widgets/README.md @@ -0,0 +1,14 @@ +# Navi widgets + +You want to launch Navi with a shortcut?\ +Widgets are here for you! + +Widgets are 3rd-party contributions and integrates Navi with 3rd-party software such as shells. + +## List of shell widgets + +- Navi widget for Bash +- Navi widget for Fish +- Navi widget for Ash +- Navi widget for NuShell +- Navi widget for PowerShell \ No newline at end of file From 7c126b6657dd1df796a43aad57c57281ca849420 Mon Sep 17 00:00:00 2001 From: Alexis Opolka <53085471+alexis-opolka@users.noreply.github.com> Date: Thu, 6 Feb 2025 09:24:36 +0100 Subject: [PATCH 10/63] Update cheatsheet with a getting started guide --- docs/cheatsheet/getting-started/README.md | 1 + 1 file changed, 1 insertion(+) create mode 100644 docs/cheatsheet/getting-started/README.md diff --git a/docs/cheatsheet/getting-started/README.md b/docs/cheatsheet/getting-started/README.md new file mode 100644 index 0000000..15af170 --- /dev/null +++ b/docs/cheatsheet/getting-started/README.md @@ -0,0 +1 @@ +# How to get started with navi \ No newline at end of file From 6a0c3285b7a5057d7ad0fe21b98fcb19284ca433 Mon Sep 17 00:00:00 2001 From: Alexis Opolka <53085471+alexis-opolka@users.noreply.github.com> Date: Thu, 6 Feb 2025 09:25:38 +0100 Subject: [PATCH 11/63] Update cheatsheet with a syntax document --- docs/cheatsheet/syntax/README.md | 1 + 1 file changed, 1 insertion(+) create mode 100644 docs/cheatsheet/syntax/README.md diff --git a/docs/cheatsheet/syntax/README.md b/docs/cheatsheet/syntax/README.md new file mode 100644 index 0000000..d1efa22 --- /dev/null +++ b/docs/cheatsheet/syntax/README.md @@ -0,0 +1 @@ +# The syntax of a Navi cheatsheet \ No newline at end of file From 3c75e3b74ac320a31fc95db980b53b8242f3ad70 Mon Sep 17 00:00:00 2001 From: Alexis Opolka <53085471+alexis-opolka@users.noreply.github.com> Date: Thu, 6 Feb 2025 09:26:26 +0100 Subject: [PATCH 12/63] Update configuration --- docs/configuration/reference/README.md | 1 + 1 file changed, 1 insertion(+) create mode 100644 docs/configuration/reference/README.md diff --git a/docs/configuration/reference/README.md b/docs/configuration/reference/README.md new file mode 100644 index 0000000..50eb9c7 --- /dev/null +++ b/docs/configuration/reference/README.md @@ -0,0 +1 @@ +# Configuration file reference \ No newline at end of file From 01767538f078e004056017f9436e02d2fce0999e Mon Sep 17 00:00:00 2001 From: Alexis Opolka <53085471+alexis-opolka@users.noreply.github.com> Date: Thu, 6 Feb 2025 09:26:56 +0100 Subject: [PATCH 13/63] Update docs --- docs/contributions/README.md | 1 + 1 file changed, 1 insertion(+) create mode 100644 docs/contributions/README.md diff --git a/docs/contributions/README.md b/docs/contributions/README.md new file mode 100644 index 0000000..0542b2e --- /dev/null +++ b/docs/contributions/README.md @@ -0,0 +1 @@ +# How to contribute to Navi \ No newline at end of file From c66e67159f80d68ec2144e68976a9776470cae4e Mon Sep 17 00:00:00 2001 From: Alexis Opolka <53085471+alexis-opolka@users.noreply.github.com> Date: Thu, 6 Feb 2025 09:30:03 +0100 Subject: [PATCH 14/63] Update README.md --- docs/widgets/README.md | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/docs/widgets/README.md b/docs/widgets/README.md index e8f344d..926cc80 100644 --- a/docs/widgets/README.md +++ b/docs/widgets/README.md @@ -7,8 +7,15 @@ Widgets are 3rd-party contributions and integrates Navi with 3rd-party software ## List of shell widgets -- Navi widget for Bash -- Navi widget for Fish -- Navi widget for Ash -- Navi widget for NuShell -- Navi widget for PowerShell \ No newline at end of file +| Shell | Navi support | +|-------|--------------| +| Bash | :white_check_mark: | +| Fish || +| Zsh || +| NuShell || +| PowerShell || + +## Other widgets + +- Tmux +- Vim \ No newline at end of file From e18469516dd8278f2835170c4c647a742587c6e7 Mon Sep 17 00:00:00 2001 From: alexis-opolka <53085471+alexis-opolka@users.noreply.github.com> Date: Thu, 6 Feb 2025 12:45:58 +0100 Subject: [PATCH 15/63] Moved, Deleted and Added files and their documentation Signed-off-by: alexis-opolka <53085471+alexis-opolka@users.noreply.github.com> --- docs/alfred.md | 18 -- .../examples/example.cheat} | 12 +- docs/{ => cheatsheet/examples}/navi.cheat | 0 .../repositories/README.md} | 150 +++++++------- docs/cheatsheet/src/example.cheat | 44 ---- docs/cheatsheet/syntax/README.md | 188 +++++++++++++++++- docs/cheatsheet_syntax.md | 187 ----------------- docs/configuration/README.md | 97 ++++++++- .../examples}/config_file_example.yaml | 0 docs/installation.md | 152 -------------- docs/navi_config.md | 94 --------- docs/utilisation/README.md | 0 .../shell-scripting/README.md} | 80 ++++---- docs/{tmux.md => widgets/howto/TMUX.md} | 74 +++---- docs/{vim.md => widgets/howto/VIM.md} | 26 +-- 15 files changed, 454 insertions(+), 668 deletions(-) delete mode 100644 docs/alfred.md rename docs/{cheat_example.cheat => cheatsheet/examples/example.cheat} (74%) rename docs/{ => cheatsheet/examples}/navi.cheat (100%) rename docs/{cheatsheet_repositories.md => cheatsheet/repositories/README.md} (97%) delete mode 100644 docs/cheatsheet/src/example.cheat delete mode 100644 docs/cheatsheet_syntax.md rename docs/{ => configuration/examples}/config_file_example.yaml (100%) delete mode 100644 docs/installation.md delete mode 100644 docs/navi_config.md create mode 100644 docs/utilisation/README.md rename docs/{shell_scripting.md => utilisation/shell-scripting/README.md} (96%) rename docs/{tmux.md => widgets/howto/TMUX.md} (95%) rename docs/{vim.md => widgets/howto/VIM.md} (96%) diff --git a/docs/alfred.md b/docs/alfred.md deleted file mode 100644 index ea6e3ee..0000000 --- a/docs/alfred.md +++ /dev/null @@ -1,18 +0,0 @@ -## Alfred - -This is _experimental_. If you face any issues, please report [here](https://github.com/denisidoro/navi/issues/348). - -![Alfred demo](https://user-images.githubusercontent.com/3226564/80294838-582b1b00-8743-11ea-9eb5-a335d8eed833.gif) - -### Note - -Support for alfred has been removed. - -The latest version which has some support for it is [2.15.1](https://github.com/denisidoro/navi/releases/tag/v2.15.1). - -### Instructions - -- make sure you have [Alfred Powerpack](https://www.alfredapp.com/powerpack/) -- make sure **navi** [2.15.1](https://github.com/denisidoro/navi/releases/tag/v2.15.1) is installed -- make sure that the `navi` binary is in the `$PATH` determined by `~/.bashrc` -- download and install the [latest .alfredworkflow available](https://github.com/denisidoro/navi/releases/tag/v2.15.1) diff --git a/docs/cheat_example.cheat b/docs/cheatsheet/examples/example.cheat similarity index 74% rename from docs/cheat_example.cheat rename to docs/cheatsheet/examples/example.cheat index 972e0d6..2b22f55 100644 --- a/docs/cheat_example.cheat +++ b/docs/cheatsheet/examples/example.cheat @@ -1,6 +1,6 @@ -% first cheat - -# print something -echo "My name is !" - -$ name: whoami \ No newline at end of file +% first cheat + +# print something +echo "My name is !" + +$ name: whoami diff --git a/docs/navi.cheat b/docs/cheatsheet/examples/navi.cheat similarity index 100% rename from docs/navi.cheat rename to docs/cheatsheet/examples/navi.cheat diff --git a/docs/cheatsheet_repositories.md b/docs/cheatsheet/repositories/README.md similarity index 97% rename from docs/cheatsheet_repositories.md rename to docs/cheatsheet/repositories/README.md index dc60ac0..dfc5a45 100644 --- a/docs/cheatsheet_repositories.md +++ b/docs/cheatsheet/repositories/README.md @@ -1,75 +1,75 @@ -## Cheatsheet repositories - -- [Browsing through cheatsheet repositories](#browsing-through-cheatsheet-repositories) -- [Importing cheatsheets](#importing-cheatsheets) -- [Adding your own cheatsheets](#adding-your-own-cheatsheets) -- [Submitting cheatsheets](#submitting-cheatsheets) -- [Using cheatsheets from other tools](#using-cheatsheets-from-other-tools) -- [Auto-updating repositories](#auto-updating-repositories) - -### Browsing through cheatsheet repositories - -You can find cheatsheet repositories with: - -```sh -navi repo browse -``` - -### Importing cheatsheets - -You can import cheatsheets from any git repository that includes `.cheat` files: - -```sh -navi repo add https://github.com/denisidoro/cheats -``` - -### Adding your own cheatsheets - -You can either start a git repo with cheatsheets and import it as described above or you can add them directly to [data_dir](https://github.com/soc/dirs-rs#Features)`/navi`. - -### Submitting cheatsheets - -The main repository for cheatsheets is [denisidoro/cheats](https://github.com/denisidoro/cheats). Feel free to open a PR there for me to include your contributions. - -In order to add your own repository as a featured cheatsheet repo, please [edit this file](https://github.com/denisidoro/cheats/edit/master/featured_repos.txt). This list will be displayed when `navi repo browse` is run. - -### Using cheatsheets from other tools - -![Demo](https://user-images.githubusercontent.com/3226564/91878474-bae27500-ec55-11ea-8b19-17876178e887.gif) - -You can use cheatsheets from [tldr](https://github.com/tldr-pages/tldr) by running: - -```sh -navi --tldr -``` - -You can use cheatsheets from [cheat.sh](https://github.com/chubin/cheat.sh) by running: - -```sh -navi --cheatsh -``` - -### Auto-updating repositories - -Right now, **navi** doesn't have support for auto-updating out of the box. However, you can achieve this by using `git` and `crontab`. - -First make sure you cloned your repo using `git` to the correct folder: - -```sh -user="" -repo="" -git clone "https://github.com/${user}/${repo}" "$(navi info cheats-path)/${user}__${repo}" -``` - -Then, add a cron job: - -```sh -crontab -e -*/0 11 * * * bash -c 'cd "$(/usr/local/bin/navi info cheats-path)/__" && /usr/local/bin/git pull -q origin master' -``` - -Please note the cron job above is just an example and you should edit it accordingly: - -- In this example, the cron job is triggered every day at 11am. [crontab guru](https://crontab.guru/) may come in handy if you want to change this value -- The full paths to `navi` and `git` may differ in your setup. Check their actual values using `which navi` and `which git` -- Don't forget to replace `__` with the actual folder name +## Cheatsheet repositories + +- [Browsing through cheatsheet repositories](#browsing-through-cheatsheet-repositories) +- [Importing cheatsheets](#importing-cheatsheets) +- [Adding your own cheatsheets](#adding-your-own-cheatsheets) +- [Submitting cheatsheets](#submitting-cheatsheets) +- [Using cheatsheets from other tools](#using-cheatsheets-from-other-tools) +- [Auto-updating repositories](#auto-updating-repositories) + +### Browsing through cheatsheet repositories + +You can find cheatsheet repositories with: + +```sh +navi repo browse +``` + +### Importing cheatsheets + +You can import cheatsheets from any git repository that includes `.cheat` files: + +```sh +navi repo add https://github.com/denisidoro/cheats +``` + +### Adding your own cheatsheets + +You can either start a git repo with cheatsheets and import it as described above or you can add them directly to [data_dir](https://github.com/soc/dirs-rs#Features)`/navi`. + +### Submitting cheatsheets + +The main repository for cheatsheets is [denisidoro/cheats](https://github.com/denisidoro/cheats). Feel free to open a PR there for me to include your contributions. + +In order to add your own repository as a featured cheatsheet repo, please [edit this file](https://github.com/denisidoro/cheats/edit/master/featured_repos.txt). This list will be displayed when `navi repo browse` is run. + +### Using cheatsheets from other tools + +![Demo](https://user-images.githubusercontent.com/3226564/91878474-bae27500-ec55-11ea-8b19-17876178e887.gif) + +You can use cheatsheets from [tldr](https://github.com/tldr-pages/tldr) by running: + +```sh +navi --tldr +``` + +You can use cheatsheets from [cheat.sh](https://github.com/chubin/cheat.sh) by running: + +```sh +navi --cheatsh +``` + +### Auto-updating repositories + +Right now, **navi** doesn't have support for auto-updating out of the box. However, you can achieve this by using `git` and `crontab`. + +First make sure you cloned your repo using `git` to the correct folder: + +```sh +user="" +repo="" +git clone "https://github.com/${user}/${repo}" "$(navi info cheats-path)/${user}__${repo}" +``` + +Then, add a cron job: + +```sh +crontab -e +*/0 11 * * * bash -c 'cd "$(/usr/local/bin/navi info cheats-path)/__" && /usr/local/bin/git pull -q origin master' +``` + +Please note the cron job above is just an example and you should edit it accordingly: + +- In this example, the cron job is triggered every day at 11am. [crontab guru](https://crontab.guru/) may come in handy if you want to change this value +- The full paths to `navi` and `git` may differ in your setup. Check their actual values using `which navi` and `which git` +- Don't forget to replace `__` with the actual folder name diff --git a/docs/cheatsheet/src/example.cheat b/docs/cheatsheet/src/example.cheat deleted file mode 100644 index 0e68698..0000000 --- a/docs/cheatsheet/src/example.cheat +++ /dev/null @@ -1,44 +0,0 @@ -% cheatsheets - -# Download default cheatsheets -navi repo add denisidoro/cheats - -# Browse for cheatsheet repos -navi repo browse - -# Edit main local cheatsheets -f="$(navi info cheats-path)/main.cheat" -[ -f "$f" ] || navi info cheats-example > "$f" -${EDITOR:-nano} "$f" - - -% config - -# Edit config file -f="$(navi info config-path)" -[ -f "$f" ] || navi info config-example > "$f" -${EDITOR:-nano} "$f" - - -% 3rd-party - -# Search using tldr -navi --tldr "" - -# Search using cheatsh -navi --cheatsh "" - - -% widget - -# Load shell widget -shell="$(basename $SHELL)"; eval "$(navi widget $shell)" - - -% help - -# Read command-line help text -navi --help - -# Read project README.md -navi fn url::open "https://github.com/denisidoro/navi" diff --git a/docs/cheatsheet/syntax/README.md b/docs/cheatsheet/syntax/README.md index d1efa22..ddd1b75 100644 --- a/docs/cheatsheet/syntax/README.md +++ b/docs/cheatsheet/syntax/README.md @@ -1 +1,187 @@ -# The syntax of a Navi cheatsheet \ No newline at end of file +# The syntax of a Navi cheatsheet + +- [Syntax overview](#syntax-overview) +- [Folder structure](#folder-structure) +- [Variables](#variables) +- [Advanced variable options](#advanced-variable-options) +- [Variable dependency](#variable-dependency) +- [Multiline snippets](#multiline-snippets) +- [Variable as multiple arguments](#variable-as-multiple-arguments) +- [Aliases](#aliases) + +### Syntax overview + +Cheatsheets are described in `.cheat` files that look like this: + +```sh +% git, code + +# Change branch +git checkout + +$ branch: git branch | awk '{print $NF}' +``` + +Lines starting with: + +- `%`: determine the start of a new cheatsheet and should contain tags +- `#`: should be descriptions of commands +- `;`: are ignored. You can use them for metacomments +- `$`: should contain commands that generate a list of possible values for a given argument [:information_source:](#variables) +- `@`: should contain tags whose associated cheatsheet you want to base on [:information_source:](#extending-cheatsheets) + +All the other non-empty lines are considered as executable commands. + +Tip: if you are editing cheatsheets in Visual Studio Code, you could enable syntax highlighting +by installing [this extension](https://marketplace.visualstudio.com/items?itemName=yanivmo.navi-cheatsheet-language). + +### Variables + +The interface prompts for variable names inside brackets (eg ``). + +Variable names should only include alphanumeric characters and `_`. + +If there's a corresponding line starting with `$` for a variable, suggestions will be displayed. Otherwise, the user will be able to type any value for it. + +If you hit `` the query typed will be preferred. If you hit `` the selection will be preferred. + +### Advanced variable options + +For lines starting with `$` you can use `---` to customize the behavior of `fzf` or how the value is going to be used: + +```sh +# This will pick the 3rd column and use the first line as header +docker rmi + +# Even though "false/true" is displayed, this will print "0/1" +echo + +$ image_id: docker images --- --column 3 --header-lines 1 --delimiter '\s\s+' +$ mapped: echo 'false true' | tr ' ' '\n' --- --map "grep -q t && echo 1 || echo 0" +``` + +The supported parameters are: + +- `--column `: extracts a single column from the selected result +- `--map `: _(experimental)_ applies a map function to the selected variable value +- `--prevent-extra`: _(experimental)_ limits the user to select one of the suggestions +- `--fzf-overrides `: _(experimental)_ applies arbitrary `fzf` overrides +- `--expand`: _(experimental)_ converts each line into a separate argument + +In addition, it's possible to forward the following parameters to `fzf`: + +- `--multi` +- `--header-lines ` +- `--delimiter ` +- `--query ` +- `--filter ` +- `--header ` +- `--preview ` +- `--preview-window ` + +### Variable dependency + +The command for generating possible inputs can implicitly refer other variables by using the `` syntax: + +```sh +# Should print /my/pictures/wallpapers +echo "" + +$ pictures_folder: echo "/my/pictures" +$ wallpaper_folder: echo "/wallpapers" +``` + +If you want to make dependencies explicit, you can use the `$varname` syntax: + +```sh +# If you select "hello" for , the possible values of will be "hello foo" and "hello bar" +echo + +# If you want to ignore the contents of and only print +: ; echo + +$ x: echo "hello hi" | tr ' ' '\n' +$ y: echo "$x foo;$x bar" | tr ';' '\n' +``` + +### Extending cheatsheets + +With the `@ same tags from other cheatsheet` syntax you can reuse the same variable in multiple cheatsheets. + +```sh +% dirs, common + +$ pictures_folder: echo "/my/pictures" + +% wallpapers +@ dirs, common + +# Should print /my/pictures/wallpapers +echo "/wallpapers" + +% screenshots +@ dirs, common + +# Should print /my/pictures/screenshots +echo "/screenshots" +``` + +### Multiline snippets + +Commands may be multiline: + +```sh +# This will output "foo\nyes" +echo foo +true \ + && echo yes \ + || echo no +``` + +### Variable as multiple arguments + +```sh +# This will result into: cat "file1.json" "file2.json" +cat + +$ jsons: find . -iname '*.json' -type f -print --- --multi --expand +``` +### Aliases + +**navi** doesn't have support for aliases as first-class citizens at the moment. + +However, it is trivial to create aliases using **navi** + a few conventions. + +For example, suppose you decide to end some of your commands with `:: `: + +```bash +% aliases + +# This is one command :: el +echo lorem ipsum + +# This is another command :: ef +echo foo bar +``` + +Then, if you use **navi** as a [shell scripting tool](shell_scripting.md), you could add something similar to this in your `.bashrc`-like file: + +```bash +navialias() { + navi --query ":: $1" --best-match +} + +alias el="navialias el" +alias ef="navialias ef" +``` + +If you don't want to use these conventions, you can even add full comments in your aliases: + +```bash +navibestmatch() { + navi --query "$1" --best-match +} + +alias el="navibestmatch 'This is one command'" +alias ef="navibestmatch 'This is another command'" +``` diff --git a/docs/cheatsheet_syntax.md b/docs/cheatsheet_syntax.md deleted file mode 100644 index 78d8a5e..0000000 --- a/docs/cheatsheet_syntax.md +++ /dev/null @@ -1,187 +0,0 @@ -## Cheatsheet syntax - -- [Syntax overview](#syntax-overview) -- [Folder structure](#folder-structure) -- [Variables](#variables) -- [Advanced variable options](#advanced-variable-options) -- [Variable dependency](#variable-dependency) -- [Multiline snippets](#multiline-snippets) -- [Variable as multiple arguments](#variable-as-multiple-arguments) -- [Aliases](#aliases) - -### Syntax overview - -Cheatsheets are described in `.cheat` files that look like this: - -```sh -% git, code - -# Change branch -git checkout - -$ branch: git branch | awk '{print $NF}' -``` - -Lines starting with: - -- `%`: determine the start of a new cheatsheet and should contain tags -- `#`: should be descriptions of commands -- `;`: are ignored. You can use them for metacomments -- `$`: should contain commands that generate a list of possible values for a given argument [:information_source:](#variables) -- `@`: should contain tags whose associated cheatsheet you want to base on [:information_source:](#extending-cheatsheets) - -All the other non-empty lines are considered as executable commands. - -Tip: if you are editing cheatsheets in Visual Studio Code, you could enable syntax highlighting -by installing [this extension](https://marketplace.visualstudio.com/items?itemName=yanivmo.navi-cheatsheet-language). - -### Variables - -The interface prompts for variable names inside brackets (eg ``). - -Variable names should only include alphanumeric characters and `_`. - -If there's a corresponding line starting with `$` for a variable, suggestions will be displayed. Otherwise, the user will be able to type any value for it. - -If you hit `` the query typed will be preferred. If you hit `` the selection will be preferred. - -### Advanced variable options - -For lines starting with `$` you can use `---` to customize the behavior of `fzf` or how the value is going to be used: - -```sh -# This will pick the 3rd column and use the first line as header -docker rmi - -# Even though "false/true" is displayed, this will print "0/1" -echo - -$ image_id: docker images --- --column 3 --header-lines 1 --delimiter '\s\s+' -$ mapped: echo 'false true' | tr ' ' '\n' --- --map "grep -q t && echo 1 || echo 0" -``` - -The supported parameters are: - -- `--column `: extracts a single column from the selected result -- `--map `: _(experimental)_ applies a map function to the selected variable value -- `--prevent-extra`: _(experimental)_ limits the user to select one of the suggestions -- `--fzf-overrides `: _(experimental)_ applies arbitrary `fzf` overrides -- `--expand`: _(experimental)_ converts each line into a separate argument - -In addition, it's possible to forward the following parameters to `fzf`: - -- `--multi` -- `--header-lines ` -- `--delimiter ` -- `--query ` -- `--filter ` -- `--header ` -- `--preview ` -- `--preview-window ` - -### Variable dependency - -The command for generating possible inputs can implicitly refer other variables by using the `` syntax: - -```sh -# Should print /my/pictures/wallpapers -echo "" - -$ pictures_folder: echo "/my/pictures" -$ wallpaper_folder: echo "/wallpapers" -``` - -If you want to make dependencies explicit, you can use the `$varname` syntax: - -```sh -# If you select "hello" for , the possible values of will be "hello foo" and "hello bar" -echo - -# If you want to ignore the contents of and only print -: ; echo - -$ x: echo "hello hi" | tr ' ' '\n' -$ y: echo "$x foo;$x bar" | tr ';' '\n' -``` - -### Extending cheatsheets - -With the `@ same tags from other cheatsheet` syntax you can reuse the same variable in multiple cheatsheets. - -```sh -% dirs, common - -$ pictures_folder: echo "/my/pictures" - -% wallpapers -@ dirs, common - -# Should print /my/pictures/wallpapers -echo "/wallpapers" - -% screenshots -@ dirs, common - -# Should print /my/pictures/screenshots -echo "/screenshots" -``` - -### Multiline snippets - -Commands may be multiline: - -```sh -# This will output "foo\nyes" -echo foo -true \ - && echo yes \ - || echo no -``` - -### Variable as multiple arguments - -```sh -# This will result into: cat "file1.json" "file2.json" -cat - -$ jsons: find . -iname '*.json' -type f -print --- --multi --expand -``` -### Aliases - -**navi** doesn't have support for aliases as first-class citizens at the moment. - -However, it is trivial to create aliases using **navi** + a few conventions. - -For example, suppose you decide to end some of your commands with `:: `: - -```bash -% aliases - -# This is one command :: el -echo lorem ipsum - -# This is another command :: ef -echo foo bar -``` - -Then, if you use **navi** as a [shell scripting tool](shell_scripting.md), you could add something similar to this in your `.bashrc`-like file: - -```bash -navialias() { - navi --query ":: $1" --best-match -} - -alias el="navialias el" -alias ef="navialias ef" -``` - -If you don't want to use these conventions, you can even add full comments in your aliases: - -```bash -navibestmatch() { - navi --query "$1" --best-match -} - -alias el="navibestmatch 'This is one command'" -alias ef="navibestmatch 'This is another command'" -``` diff --git a/docs/configuration/README.md b/docs/configuration/README.md index 6946aa3..88ac3c4 100644 --- a/docs/configuration/README.md +++ b/docs/configuration/README.md @@ -1 +1,96 @@ -# Configuration of Navi \ No newline at end of file +# Configuration of Navi + +- [Paths and Environment Variables](#paths-and-environment-variables) + - [Config file path](#config-file-path) + - [Cheat sheet paths](#cheat-sheet-paths) +- [Logging](#logging) +- [Customization](#customization) + - [Changing colors](#changing-colors) + - [Resizing columns](#resizing-columns) + - [Overriding fzf options](#overriding-fzf-options) + +# Paths and Environment Variables + +Navi uses the [`directories-next`](https://crates.io/crates/directories-next) package, which +defines platform-specific standard locations of directories for config, cache and other data (Mac users, this is why your files are being stored in `~/Library/Application Support/navi`). + +## Config file path + +The default config file path is set by the `$NAVI_CONFIG` environment variable. If it is not set, it fallbacks to `~/.config/navi/config.yaml`. The command +```sh +navi info config-path +``` +prints which config file path is being used. You can get a config file example by running +```sh +navi info config-example +``` +or by clicking [here](examples/config_file_example.yaml). To turn this example your config file, run + +```sh +navi info config-example > "$(navi info config-path)" +``` +## Cheat sheet paths + +The default `.cheat` files paths are defined in the `$NAVI_PATH` environment variable in a colon-separated list, e.g., +```sh +export NAVI_PATH='/path/to/a/dir:/path/to/another/dir:/yet/another/dir' +``` +If this environment variable is unset or if all directories do not exist, `navi` uses the [paths defined in the config file](https://github.com/denisidoro/navi/blob/master/docs/config_file_example.yaml#L21-L24). Finally, if there is no config file or if the `.cheat` file paths was not set, the default `.cheat` file paths fallbacks to `~/.local/share/navi/cheats/`. The command +```sh +navi info cheats-path +``` +prints to you all paths used to search for `.cheat` files. + +You can also add other paths at runtime by running `navi` with the `--path` option and a colon-separated paths list, e.g., +```sh +navi --path '/some/dir:/other/dir' +``` +It's irrelevant the directory structure within each path. They can even be all in a single file if you wish, as long as you split them accordingly with lines starting with `%`. + +Despite `$NAVI_PATH` being set, it will not be used when installing cheat sheets directly via navi's own commands. For example when running `navi add repo `, the default paths as per the `directories-next` package will still be used. To avoid this, you may simply clone repos via a regular `git clone` command, directly into `$NAVI_PATH`. + +Note! `navi info cheats-path` and `navi info config-path` display the *default* path, not +the path set by the user. [It is known that this is a little misleading!](https://github.com/denisidoro/navi/issues/664#issuecomment-1004721178). + +# Logging + +The log file will be created under the same directory where the config locates. + +And you can use the `RUST_LOG` env to set the log level, e.g. `RUST_LOG=debug navi`. + +# Customization + +## Changing colors + +You can change the [color scheme](https://github.com/junegunn/fzf/wiki/Color-schemes) by [overriding fzf options](#overriding-fzf-options). + +In addition, you can change the text color for each column by properly configuring _navi_'s `config.yaml`. Please check `navi --help` for more instructions. + +## Resizing columns + +You can change the column widths by properly configuring _navi_'s `config.yaml`. Please check `navi --help` for more instructions. + +## Overriding fzf options + +Let's say you want to override [$FZF_DEFAULT_OPTS](https://github.com/junegunn/fzf#layout) with `--height 3`. + +This can be overridden in the following ways: + +```sh +# if you want to override only when selecting snippets +navi --fzf-overrides '--height 3' + +# alternatively, using an environment variable in your .bashrc-like file: +export NAVI_FZF_OVERRIDES='--height 3' + +# if you want to override only when selecting argument values +navi --fzf-overrides-var '--height 3' + +# alternatively, using an environment variable in your .bashrc-like file: +export NAVI_FZF_OVERRIDES_VAR='--height 3' + +# if you want to override for all cases +FZF_DEFAULT_OPTS="--height 3" navi +``` + +In addition, this can be set by properly configuring _navi_'s `config.yaml`. Please check `navi --help` for more instructions. diff --git a/docs/config_file_example.yaml b/docs/configuration/examples/config_file_example.yaml similarity index 100% rename from docs/config_file_example.yaml rename to docs/configuration/examples/config_file_example.yaml diff --git a/docs/installation.md b/docs/installation.md deleted file mode 100644 index 72a8e64..0000000 --- a/docs/installation.md +++ /dev/null @@ -1,152 +0,0 @@ -## Installation - -- [Installing the main binary](#installing-the-main-binary) - - [Using Homebrew](#using-homebrew) - - [Using Gentoo](#using-gentoo) - - [Using nix](#using-nix) - - [Using cargo](#using-cargo) - - [Using install script](#using-install-script) - - [Downloading pre-compiled binaries](#downloading-pre-compiled-binaries) - - [Building from source](#building-from-source) - - [Other package managers](#other-package-managers) -- [Installing the shell widget](#installing-the-shell-widget) - -### Installing the main binary - -#### Using [Homebrew](http://brew.sh/) - -```sh -brew install navi -``` - -#### Using [Gentoo](https://gentoo.org/) - -Be sure to [enable](https://wiki.gentoo.org/wiki/Ebuild_repository) the [GURU overlay](https://gpo.zugaina.org/Overlays/guru/app-misc/navi). - -```sh -emerge -a app-misc/navi -``` - -#### Using [pacman](https://wiki.archlinux.org/title/Pacman) - -```sh -pacman -S navi -``` - -#### Using [nix](https://nixos.org/) - -```sh -nix-env -iA nixpkgs.navi -``` - -#### Using [cargo](https://github.com/rust-lang/cargo) - -```bash -cargo install --locked navi -``` - -#### Using [choco](https://community.chocolatey.org/packages/navi) - -For Windows user, using powershell - -1. Install package via choco - ```bash - choco install navi - ``` -2. Create `$env:USERPROFILE\AppData\Roaming\navi\config.yaml` and override `shell.command` as per [config_file_example.yaml](./config_file_example.yaml) - - ``` - style: - tag: - color: cyan - comment: - color: grey - snippet: - color: white - - shell: - command: powershell - ``` - - Remark: Above example also adds custom colors for better readability in case you use standard blue for your Powershell - -#### Using install script - -```bash -bash <(curl -sL https://raw.githubusercontent.com/denisidoro/navi/master/scripts/install) - -# (optional) to set directories: -# BIN_DIR=/usr/local/bin bash <(curl -sL https://raw.githubusercontent.com/denisidoro/navi/master/scripts/install) -``` - -#### Downloading pre-compiled binaries - -- download the correct binary [here](https://github.com/denisidoro/navi/releases/latest) -- extract the content to your `$PATH` - -#### Building from source - -```bash -git clone https://github.com/denisidoro/navi ~/.navi -cd ~/.navi -make install - -# (optional) to set the install directory: -# make BIN_DIR=/usr/local/bin install -``` - -##### Compile time environment variables - -**navi** supports environment variables at compile time that modify the behavior of the binary at runtime: - -- `NAVI_PATH` (directory path value): If the `cheats` directory in the user's directory does not exist, **navi** uses this path (if it exists), as a fallback location to look for cheat files. Use case: system-wide installed, shared used cheatsheets folder. -- `NAVI_CONFIG` (file path value): If the `config.yaml` file in the user's directory does not exist, **navi** uses this path (if it exists), as a fallback location to look for a configuration file. Use case: system-wide installed, shared used configuration file. - -#### Other package managers - -You can find **navi** for more package managers by clicking on the image below: - -[![Packaging status](https://repology.org/badge/vertical-allrepos/navi.svg)](https://repology.org/project/navi/versions) - -Feel free to be the maintainer of **navi** for any package manager you'd like! - -### Installing the shell widget - -If you want to install it, add this line to your `.bashrc`-like file: - -```sh -# bash -eval "$(navi widget bash)" - -# zsh -eval "$(navi widget zsh)" - -# fish -navi widget fish | source - -# elvish -eval (navi widget elvish | slurp) - -# xonsh -# xpip install xontrib-navi # ← run in your xonsh session to install xontrib -xontrib load navi # ← add to your xonsh run control file -``` - -#### Nushell - -Due to Nushell's [unique design](https://www.nushell.sh/book/thinking_in_nu.html#think-of-nushell-as-a-compiled-language), it is not possible to `eval` a piece of code dynamically like in other shells therefore the integration process is a bit more involved. Here is an example: -1. run `^navi widget nushell | save ($nu.default-config-dir | path join "navi-integration.nu")` -2. add the following lines to `config.nu`: - ```nushell - source ($nu.default-config-dir | path join "navi-integration.nu") - ``` - - -By default, `Ctrl+G` is assigned to launching **navi** (in xonsh can be customized with `$X_NAVI_KEY`, see [xontrib-navi](https://github.com/eugenesvk/xontrib-navi) for details). - -There's currently no way to customize the widget behavior out-of-the-box. If you want to change the keybinding or the **navi** flags used by the widget, please: - -1. run, e.g., `navi widget bash` in your terminal -2. copy the output -3. paste the output in your `.bashrc`-like file -4. edit the contents accordingly diff --git a/docs/navi_config.md b/docs/navi_config.md deleted file mode 100644 index 553c850..0000000 --- a/docs/navi_config.md +++ /dev/null @@ -1,94 +0,0 @@ -- [Paths and Environment Variables](#paths-and-environment-variables) - - [Config file path](#config-file-path) - - [Cheat sheet paths](#cheat-sheet-paths) -- [Logging](#logging) -- [Customization](#customization) - - [Changing colors](#changing-colors) - - [Resizing columns](#resizing-columns) - - [Overriding fzf options](#overriding-fzf-options) - -# Paths and Environment Variables - -Navi uses the [`directories-next`](https://crates.io/crates/directories-next) package, which -defines platform-specific standard locations of directories for config, cache and other data (Mac users, this is why your files are being stored in `~/Library/Application Support/navi`). - -## Config file path - -The default config file path is set by the `$NAVI_CONFIG` environment variable. If it is not set, it fallbacks to `~/.config/navi/config.yaml`. The command -```sh -navi info config-path -``` -prints which config file path is being used. You can get a config file example by running -```sh -navi info config-example -``` -or by clicking [here](./config_file_example.yaml). To turn this example your config file, run - -```sh -navi info config-example > "$(navi info config-path)" -``` -## Cheat sheet paths - -The default `.cheat` files paths are defined in the `$NAVI_PATH` environment variable in a colon-separated list, e.g., -```sh -export NAVI_PATH='/path/to/a/dir:/path/to/another/dir:/yet/another/dir' -``` -If this environment variable is unset or if all directories do not exist, `navi` uses the [paths defined in the config file](https://github.com/denisidoro/navi/blob/master/docs/config_file_example.yaml#L21-L24). Finally, if there is no config file or if the `.cheat` file paths was not set, the default `.cheat` file paths fallbacks to `~/.local/share/navi/cheats/`. The command -```sh -navi info cheats-path -``` -prints to you all paths used to search for `.cheat` files. - -You can also add other paths at runtime by running `navi` with the `--path` option and a colon-separated paths list, e.g., -```sh -navi --path '/some/dir:/other/dir' -``` -It's irrelevant the directory structure within each path. They can even be all in a single file if you wish, as long as you split them accordingly with lines starting with `%`. - -Despite `$NAVI_PATH` being set, it will not be used when installing cheat sheets directly via navi's own commands. For example when running `navi add repo `, the default paths as per the `directories-next` package will still be used. To avoid this, you may simply clone repos via a regular `git clone` command, directly into `$NAVI_PATH`. - -Note! `navi info cheats-path` and `navi info config-path` display the *default* path, not -the path set by the user. [It is known that this is a little misleading!](https://github.com/denisidoro/navi/issues/664#issuecomment-1004721178). - -# Logging - -The log file will be created under the same directory where the config locates. - -And you can use the `RUST_LOG` env to set the log level, e.g. `RUST_LOG=debug navi`. - -# Customization - -## Changing colors - -You can change the [color scheme](https://github.com/junegunn/fzf/wiki/Color-schemes) by [overriding fzf options](#overriding-fzf-options). - -In addition, you can change the text color for each column by properly configuring _navi_'s `config.yaml`. Please check `navi --help` for more instructions. - -## Resizing columns - -You can change the column widths by properly configuring _navi_'s `config.yaml`. Please check `navi --help` for more instructions. - -## Overriding fzf options - -Let's say you want to override [$FZF_DEFAULT_OPTS](https://github.com/junegunn/fzf#layout) with `--height 3`. - -This can be overridden in the following ways: - -```sh -# if you want to override only when selecting snippets -navi --fzf-overrides '--height 3' - -# alternatively, using an environment variable in your .bashrc-like file: -export NAVI_FZF_OVERRIDES='--height 3' - -# if you want to override only when selecting argument values -navi --fzf-overrides-var '--height 3' - -# alternatively, using an environment variable in your .bashrc-like file: -export NAVI_FZF_OVERRIDES_VAR='--height 3' - -# if you want to override for all cases -FZF_DEFAULT_OPTS="--height 3" navi -``` - -In addition, this can be set by properly configuring _navi_'s `config.yaml`. Please check `navi --help` for more instructions. diff --git a/docs/utilisation/README.md b/docs/utilisation/README.md new file mode 100644 index 0000000..e69de29 diff --git a/docs/shell_scripting.md b/docs/utilisation/shell-scripting/README.md similarity index 96% rename from docs/shell_scripting.md rename to docs/utilisation/shell-scripting/README.md index 5a90ec8..83eb136 100644 --- a/docs/shell_scripting.md +++ b/docs/utilisation/shell-scripting/README.md @@ -1,40 +1,40 @@ -## Using it for shell scripting - -For a real world scenario example, please check this [blog post](https://denisidoro.github.io/posts/cli-templates/). - -Let's say you want to write a bash script that, among other things, asks the user to write the name of a git branch that should be checked out. - -If you already have the [cheatsheet above](#cheatsheet-syntax), then you could write the following in your script: - -```sh -navi --query "change branch" --best-match -``` - -**navi** will ask the user to fill all arguments needed. - -If you want to set the `` beforehand in your script: - -```sh -branch="master" navi --query "change branch" --best-match -``` - -- no interactive input will be shown -- the value for `` will be exactly the one passed as argument - -If you want to filter some results for ``: - -```sh -branch__query="master" navi --query "change branch" --best-match -``` - -- an interactive input will be shown, unless a single entry is autoselected -- the value for `` will be the one selected - -If you want to select the best match for ``: - -```sh -branch__best="master" navi --query "change branch" --best-match -``` - -- no interactive input will be shown -- the value for `` will be the one that best matches the one passed as argument +## Using it for shell scripting + +For a real world scenario example, please check this [blog post](https://denisidoro.github.io/posts/cli-templates/). + +Let's say you want to write a bash script that, among other things, asks the user to write the name of a git branch that should be checked out. + +If you already have the [cheatsheet above](#cheatsheet-syntax), then you could write the following in your script: + +```sh +navi --query "change branch" --best-match +``` + +**navi** will ask the user to fill all arguments needed. + +If you want to set the `` beforehand in your script: + +```sh +branch="master" navi --query "change branch" --best-match +``` + +- no interactive input will be shown +- the value for `` will be exactly the one passed as argument + +If you want to filter some results for ``: + +```sh +branch__query="master" navi --query "change branch" --best-match +``` + +- an interactive input will be shown, unless a single entry is autoselected +- the value for `` will be the one selected + +If you want to select the best match for ``: + +```sh +branch__best="master" navi --query "change branch" --best-match +``` + +- no interactive input will be shown +- the value for `` will be the one that best matches the one passed as argument diff --git a/docs/tmux.md b/docs/widgets/howto/TMUX.md similarity index 95% rename from docs/tmux.md rename to docs/widgets/howto/TMUX.md index 657561e..a9d2fb0 100644 --- a/docs/tmux.md +++ b/docs/widgets/howto/TMUX.md @@ -1,37 +1,37 @@ -## Tmux - -You can use **navi** as a [Tmux](https://github.com/tmux/tmux/wiki) widget to reach your Vim commands, often used SQL queries, etc. in any command-line app even in SSH sessions. - -Add these lines to your Tmux config file to access **navi** by pressing `prefix + C-g`. - -```sh -bind-key -N "Open Navi (cheat sheets)" -T prefix C-g split-window \ - "$SHELL --login -i -c 'navi --print | head -n 1 | tmux load-buffer -b tmp - ; tmux paste-buffer -p -t {last} -b tmp -d'" -``` - -Example cheatsheet: - -```sh -% vim - -# Quit without save -qa! - -# Delete a paragraph -normal dap - -# Generate sequence of numbers -put =range(, ) - -% postgresql - -# Describe table columns in `psql` or `pgcli` -select - table_name, - column_name, - data_type -from - information_schema.columns -where - table_name = ''; -``` +## Tmux + +You can use **navi** as a [Tmux](https://github.com/tmux/tmux/wiki) widget to reach your Vim commands, often used SQL queries, etc. in any command-line app even in SSH sessions. + +Add these lines to your Tmux config file to access **navi** by pressing `prefix + C-g`. + +```sh +bind-key -N "Open Navi (cheat sheets)" -T prefix C-g split-window \ + "$SHELL --login -i -c 'navi --print | head -n 1 | tmux load-buffer -b tmp - ; tmux paste-buffer -p -t {last} -b tmp -d'" +``` + +Example cheatsheet: + +```sh +% vim + +# Quit without save +qa! + +# Delete a paragraph +normal dap + +# Generate sequence of numbers +put =range(, ) + +% postgresql + +# Describe table columns in `psql` or `pgcli` +select + table_name, + column_name, + data_type +from + information_schema.columns +where + table_name = '
'; +``` diff --git a/docs/vim.md b/docs/widgets/howto/VIM.md similarity index 96% rename from docs/vim.md rename to docs/widgets/howto/VIM.md index 914da75..97c75d0 100644 --- a/docs/vim.md +++ b/docs/widgets/howto/VIM.md @@ -1,13 +1,13 @@ -## vim - -If you want syntax highlighting support for Navi in Vim, add those syntax rules -to your syntax files such as at `$VIMRUNTIME/syntax/navi.vim`. -The rules are defined based on the [Cheatsheet syntax](cheatsheet_syntax.md). - -```vim -syntax match Comment "\v^;.*$" -syntax match Statement "\v^\%.*$" -syntax match Operator "\v^\#.*$" -syntax match String "\v\<.*\>" -syntax match String "\v^\$.*$" -``` +## vim + +If you want syntax highlighting support for Navi in Vim, add those syntax rules +to your syntax files such as at `$VIMRUNTIME/syntax/navi.vim`. +The rules are defined based on the [Cheatsheet syntax](cheatsheet_syntax.md). + +```vim +syntax match Comment "\v^;.*$" +syntax match Statement "\v^\%.*$" +syntax match Operator "\v^\#.*$" +syntax match String "\v\<.*\>" +syntax match String "\v^\$.*$" +``` From 70f63237c996f7a1a0a2aa86990189a583e96fa5 Mon Sep 17 00:00:00 2001 From: alexis-opolka <53085471+alexis-opolka@users.noreply.github.com> Date: Thu, 6 Feb 2025 13:23:39 +0100 Subject: [PATCH 16/63] Update Navi contribution documentation Signed-off-by: alexis-opolka <53085471+alexis-opolka@users.noreply.github.com> --- docs/contributions/README.md | 12 +++++++- docs/contributions/code/README.md | 50 +++++++++++++++++++++++++++++++ 2 files changed, 61 insertions(+), 1 deletion(-) create mode 100644 docs/contributions/code/README.md diff --git a/docs/contributions/README.md b/docs/contributions/README.md index 0542b2e..1dbf420 100644 --- a/docs/contributions/README.md +++ b/docs/contributions/README.md @@ -1 +1,11 @@ -# How to contribute to Navi \ No newline at end of file +# How to contribute to Navi + +This section is about the ways you can contribute to Navi and its ecosystem. + +You have multiple ways to contribute to navi, here are the documented ones: + +- [Write code for Navi](code/README.md) +- [Write documentation for Navi](documentation/README.md) +- [Open Bug tickets](bugs/README.md) + +Please see each section for more details. diff --git a/docs/contributions/code/README.md b/docs/contributions/code/README.md new file mode 100644 index 0000000..c5a2227 --- /dev/null +++ b/docs/contributions/code/README.md @@ -0,0 +1,50 @@ +# Contribute code to Navi + +Navi is written in Rust, the widgets may be written in any language given it can be integrated with Navi. + +If you take the example of the most common widgets for Navi they are written in their shell scripting language +because they intend to integrate Navi with the shell in question (Fish, Zsh, NuShell, PowerShell, etc.). + +We separate Navi into two categories: + +- `Navi Core` which refers to Navi's code in Rust +- `Navi Widgets` which refers to code that intends to integrate Navi with a 3rd-party software + +## Contribute to Navi Core + +If you want to contribute to Navi Core there are certain steps you need to follow for +your changes to be accepted. + +1. First, open an issue if no opened issues are related to the change you want to contribute. +2. [Optional] Wait to have an opinion from the maintainers, developers or contributors from Navi. + > [!NOTE] + > This step is marked as *Optional* as you can open a Merge Request (MR)/Pull Request (PR) + > without having to open an issue beforehand, although it is recommended to not do so. + + We ask you to wait before working on a PR as the way you see a feature and its implementation + might not be similar on how a maintainer or Navi sees it. + + This will save you and the maintainers time. + +3. Fork the repository and iterate over your changes. +4. Update Navi documentation + + If you implement a new feature, you will need to create a new entry in the project's + documentation for users to know what has changed. + + No significant modification in Navi's behaviour should be merged without being + documented. For more details I recommend you to see [contributions/documentation/](../documentation/README.md). + +5. Open a PR on [denisidoro/navi](https://github.com/denisidoro/navi/pulls) and request a review +6. [Optional] Your PR needs revisions and changes before it can be merged + + It's not rare that your PR will need changes before it can be accepted by the maintainers + and then merged into the main branch. + +7. Your PR has been merged + + Congratulations! Your PR has been reviewed and merged, you should be proud of it, + and we thank you for your contribution. + + The following release cycle will package your contributions and users throughout the + world will be able to use your new feature. From 94bcd4678b832bb64733cbd9fbdb6bd187ec041b Mon Sep 17 00:00:00 2001 From: Alexis Opolka <53085471+alexis-opolka@users.noreply.github.com> Date: Thu, 6 Feb 2025 13:25:10 +0100 Subject: [PATCH 17/63] Update README.md --- docs/contributions/code/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/contributions/code/README.md b/docs/contributions/code/README.md index c5a2227..f957f37 100644 --- a/docs/contributions/code/README.md +++ b/docs/contributions/code/README.md @@ -17,10 +17,10 @@ your changes to be accepted. 1. First, open an issue if no opened issues are related to the change you want to contribute. 2. [Optional] Wait to have an opinion from the maintainers, developers or contributors from Navi. - > [!NOTE] + > This step is marked as *Optional* as you can open a Merge Request (MR)/Pull Request (PR) > without having to open an issue beforehand, although it is recommended to not do so. - + We ask you to wait before working on a PR as the way you see a feature and its implementation might not be similar on how a maintainer or Navi sees it. From 2e80251c8f9afa62935ebe2e7cadd3033a05b66c Mon Sep 17 00:00:00 2001 From: Alexis Opolka <53085471+alexis-opolka@users.noreply.github.com> Date: Thu, 6 Feb 2025 13:26:02 +0100 Subject: [PATCH 18/63] Update README.md --- docs/contributions/code/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/contributions/code/README.md b/docs/contributions/code/README.md index f957f37..10e173d 100644 --- a/docs/contributions/code/README.md +++ b/docs/contributions/code/README.md @@ -22,7 +22,7 @@ your changes to be accepted. > without having to open an issue beforehand, although it is recommended to not do so. We ask you to wait before working on a PR as the way you see a feature and its implementation - might not be similar on how a maintainer or Navi sees it. + might not be similar on how a maintainer of Navi sees it. This will save you and the maintainers time. From 89850460bf3ba86374a1226b4dcc7b510b6be7fe Mon Sep 17 00:00:00 2001 From: alexis-opolka <53085471+alexis-opolka@users.noreply.github.com> Date: Thu, 6 Feb 2025 13:27:20 +0100 Subject: [PATCH 19/63] Fixes small rendering issue Signed-off-by: alexis-opolka <53085471+alexis-opolka@users.noreply.github.com> --- docs/contributions/code/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/contributions/code/README.md b/docs/contributions/code/README.md index 10e173d..24e4455 100644 --- a/docs/contributions/code/README.md +++ b/docs/contributions/code/README.md @@ -32,8 +32,8 @@ your changes to be accepted. If you implement a new feature, you will need to create a new entry in the project's documentation for users to know what has changed. - No significant modification in Navi's behaviour should be merged without being - documented. For more details I recommend you to see [contributions/documentation/](../documentation/README.md). + No significant modification in Navi's behaviour should be merged without being documented.\ + For more details I recommend you to see [contributions/documentation/](../documentation/README.md). 5. Open a PR on [denisidoro/navi](https://github.com/denisidoro/navi/pulls) and request a review 6. [Optional] Your PR needs revisions and changes before it can be merged From 3aeca266a79ca4841250625e9c475687f0034db9 Mon Sep 17 00:00:00 2001 From: alexis-opolka <53085471+alexis-opolka@users.noreply.github.com> Date: Thu, 6 Feb 2025 13:44:09 +0100 Subject: [PATCH 20/63] Fixes typos Signed-off-by: alexis-opolka <53085471+alexis-opolka@users.noreply.github.com> --- docs/contributions/code/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/contributions/code/README.md b/docs/contributions/code/README.md index 24e4455..628892f 100644 --- a/docs/contributions/code/README.md +++ b/docs/contributions/code/README.md @@ -46,5 +46,5 @@ your changes to be accepted. Congratulations! Your PR has been reviewed and merged, you should be proud of it, and we thank you for your contribution. - The following release cycle will package your contributions and users throughout the - world will be able to use your new feature. + The next release cycle will package all contributions into a new release and users + throughout the world will be able to use your new feature(s). From 5827fc04a2a031e18771bbf71d6a7378e13bc719 Mon Sep 17 00:00:00 2001 From: alexis-opolka <53085471+alexis-opolka@users.noreply.github.com> Date: Thu, 6 Feb 2025 13:49:29 +0100 Subject: [PATCH 21/63] Update docs Signed-off-by: alexis-opolka <53085471+alexis-opolka@users.noreply.github.com> --- docs/contributions/bugs/README.md | 7 +++++++ docs/contributions/documentation/README.md | 8 ++++++++ 2 files changed, 15 insertions(+) create mode 100644 docs/contributions/bugs/README.md create mode 100644 docs/contributions/documentation/README.md diff --git a/docs/contributions/bugs/README.md b/docs/contributions/bugs/README.md new file mode 100644 index 0000000..5a889e9 --- /dev/null +++ b/docs/contributions/bugs/README.md @@ -0,0 +1,7 @@ +# Contribute in opening bug tickets + +Like any other software, navi has bugs. + +If you encounter an issue with Navi, we encourage you to open a bug ticket. + +## A bug ticket structure diff --git a/docs/contributions/documentation/README.md b/docs/contributions/documentation/README.md new file mode 100644 index 0000000..9d3243f --- /dev/null +++ b/docs/contributions/documentation/README.md @@ -0,0 +1,8 @@ +# Contribute documentation to Navi + +If you don't want or can't code in Rust, we welcome all contributions, +even more so if it's related to documentation. + +The documentation of Navi is currently made in Markdown. + +## Markdown documentation From 9ab374d3180cfca14083d6dd27704e396899545e Mon Sep 17 00:00:00 2001 From: alexis-opolka <53085471+alexis-opolka@users.noreply.github.com> Date: Sat, 15 Feb 2025 21:27:28 +0100 Subject: [PATCH 22/63] Update the documentation for contributions Signed-off-by: alexis-opolka <53085471+alexis-opolka@users.noreply.github.com> --- docs/contributions/bugs/README.md | 5 ++--- docs/contributions/documentation/README.md | 24 ++++++++++++++++++++++ 2 files changed, 26 insertions(+), 3 deletions(-) diff --git a/docs/contributions/bugs/README.md b/docs/contributions/bugs/README.md index 5a889e9..8e0b3ac 100644 --- a/docs/contributions/bugs/README.md +++ b/docs/contributions/bugs/README.md @@ -2,6 +2,5 @@ Like any other software, navi has bugs. -If you encounter an issue with Navi, we encourage you to open a bug ticket. - -## A bug ticket structure +If you encounter an issue with Navi, we encourage you to open a bug ticket.\ +Please see [https://github.com/denisidoro/navi/issues/](https://github.com/denisidoro/navi/issues/) to open an issue. diff --git a/docs/contributions/documentation/README.md b/docs/contributions/documentation/README.md index 9d3243f..325873d 100644 --- a/docs/contributions/documentation/README.md +++ b/docs/contributions/documentation/README.md @@ -6,3 +6,27 @@ even more so if it's related to documentation. The documentation of Navi is currently made in Markdown. ## Markdown documentation + +The documentation source files are located in the `docs/` folder and are mainly grouped by features. +The current documentation follows a structure where one folder equals one topic. + +Here is a quick representation of the folder structure this documentation currently follows: + +```txt +. ++-- docs +| +-- examples +| | +-- +| +-- src +| | +-- +| | | +-- +| +-- +| | +-- README.md +``` + +You can see that we have separated the `src` and `examples` folder from the topic with the intent to make it +easier to find each type of documentation. + +> [!NOTE] +> It is recommended to not go deeper than 3 levels in the documentation. + From f9bc3d2e269a87fad8d51b7dcb69655051b7080d Mon Sep 17 00:00:00 2001 From: alexis-opolka <53085471+alexis-opolka@users.noreply.github.com> Date: Sun, 16 Feb 2025 12:04:52 +0100 Subject: [PATCH 23/63] Moved a bit of information from the base README to the docs README Signed-off-by: alexis-opolka <53085471+alexis-opolka@users.noreply.github.com> --- README.md | 25 +++++++------------------ docs/README.md | 41 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 48 insertions(+), 18 deletions(-) create mode 100644 docs/README.md diff --git a/README.md b/README.md index 1fec742..9a7ecdc 100644 --- a/README.md +++ b/README.md @@ -29,17 +29,18 @@ It uses [fzf](https://github.com/junegunn/fzf), [skim](https://github.com/lotabo ## Installation -**navi** can be installed with the following package managers: - -[![Packaging status](https://repology.org/badge/vertical-allrepos/navi.svg)](https://repology.org/project/navi/versions) - The recommended way to install **navi** is by running: ```sh brew install navi ``` -If `brew` isn't available, you can check [alternative install instructions](docs/installation.md). +> [!NOTE] +> For more details on how to install Navi, see [docs/installation](docs/installation/README.md) + +**navi** can be installed with the following package managers: + +[![Packaging status](https://repology.org/badge/vertical-allrepos/navi.svg)](https://repology.org/project/navi/versions) ## Usage @@ -103,17 +104,5 @@ Please run the following command to read more about all possible options: navi --help ``` -In addition, please check the [/docs](docs) folder. +In addition, please check the [/docs](docs) folder or the website. -## Similar tools - -There are many similar projects out there ([beavr](https://github.com/denisidoro/beavr), [bro](https://github.com/hubsmoke/bro), [cheat](https://github.com/cheat/cheat), [cheat.sh](https://github.com/chubin/cheat.sh), [cmdmenu](https://github.com/amacfie/cmdmenu), [eg](https://github.com/srsudar/eg), [how2](https://github.com/santinic/how2), [howdoi](https://github.com/gleitz/howdoi), [Command Line Interface Pages](https://github.com/command-line-interface-pages) and [tldr](https://github.com/tldr-pages/tldr), to name a few). - -They are excellent projects, but **navi** remains unique in the following ways: - -- it's natural to write cheatsheets tailored to your needs -- arguments are neither hardcoded nor a simple template - -## Etymology - -[Navi](https://zelda.gamepedia.com/Navi) is a character from [The Legend of Zelda Ocarina of Time](https://zelda.gamepedia.com/Ocarina_of_Time) that provides [Link](https://zelda.gamepedia.com/Link) with a variety of clues to help him solve puzzles and make progress in his quest. diff --git a/docs/README.md b/docs/README.md new file mode 100644 index 0000000..2ddc246 --- /dev/null +++ b/docs/README.md @@ -0,0 +1,41 @@ +# Navi icon [![Actions Status](https://github.com/denisidoro/navi/workflows/CI/badge.svg)](https://github.com/denisidoro/navi/actions) ![GitHub release](https://img.shields.io/github/v/release/denisidoro/navi?include_prereleases) + +## Table of Contents + + +* [Navi icon ![Actions Status](https://github.com/denisidoro/navi/workflows/CI/badge.svg) ![GitHub release](https://img.shields.io/github/v/release/denisidoro/navi?include_prereleases)](#navi-img-srchttpsrawgithubusercontentcomdenisidoronavimasterassetsiconpng-alticon-height28px--) + * [Table of Contents](#table-of-contents) + * [About](#about) + * [Navi Pros](#navi-pros) + * [Similar tools](#similar-tools) + * [Etymology](#etymology) + + +## About + +Navi is an interactive cheatsheet tool for the command-line.\ +It allows you to browse through cheatsheets (that you may write yourself or download from maintainers) and execute commands. + +[![Demo](https://asciinema.org/a/406461.svg)](https://asciinema.org/a/406461) + +It uses [fzf](https://github.com/junegunn/fzf), [skim](https://github.com/lotabout/skim), or [Alfred](https://www.alfredapp.com/) under the hood and it can be either used as a command or as a shell widget (_à la_ Ctrl-R). + +## Navi Pros + +- it will spare you from knowing CLIs by heart +- it will spare you from copy-pasting output from intermediate commands +- it will make you type less +- it will teach you new one-liners + +## Similar tools + +There are many similar projects out there ([beavr](https://github.com/denisidoro/beavr), [bro](https://github.com/hubsmoke/bro), [cheat](https://github.com/cheat/cheat), [cheat.sh](https://github.com/chubin/cheat.sh), [cmdmenu](https://github.com/amacfie/cmdmenu), [eg](https://github.com/srsudar/eg), [how2](https://github.com/santinic/how2), [howdoi](https://github.com/gleitz/howdoi), [Command Line Interface Pages](https://github.com/command-line-interface-pages) and [tldr](https://github.com/tldr-pages/tldr), to name a few). + +They are excellent projects, but **navi** remains unique in the following ways: + +- it's natural to write cheatsheets tailored to your needs +- arguments are neither hardcoded nor a simple template + +## Etymology + +[Navi](https://zelda.gamepedia.com/Navi) is a character from [The Legend of Zelda Ocarina of Time](https://zelda.gamepedia.com/Ocarina_of_Time) that provides [Link](https://zelda.gamepedia.com/Link) with a variety of clues to help him solve puzzles and make progress in his quest. From de820e01d6d5fc21352567ace2dc991131afa280 Mon Sep 17 00:00:00 2001 From: Alexis Opolka <53085471+alexis-opolka@users.noreply.github.com> Date: Wed, 5 Mar 2025 18:53:29 +0100 Subject: [PATCH 24/63] Create examples/cheatsheet/navi.cheat --- docs/examples/cheatsheet/navi.cheat | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 docs/examples/cheatsheet/navi.cheat diff --git a/docs/examples/cheatsheet/navi.cheat b/docs/examples/cheatsheet/navi.cheat new file mode 100644 index 0000000..a01fec2 --- /dev/null +++ b/docs/examples/cheatsheet/navi.cheat @@ -0,0 +1,2 @@ +% test +echo "Hello World" \ No newline at end of file From 2119921a4ebfcbd85bb80470c3132f5b545224b9 Mon Sep 17 00:00:00 2001 From: Alexis Opolka <53085471+alexis-opolka@users.noreply.github.com> Date: Wed, 5 Mar 2025 18:54:07 +0100 Subject: [PATCH 25/63] Update navi.cheat --- docs/examples/cheatsheet/navi.cheat | 46 +++++++++++++++++++++++++++-- 1 file changed, 44 insertions(+), 2 deletions(-) diff --git a/docs/examples/cheatsheet/navi.cheat b/docs/examples/cheatsheet/navi.cheat index a01fec2..0e68698 100644 --- a/docs/examples/cheatsheet/navi.cheat +++ b/docs/examples/cheatsheet/navi.cheat @@ -1,2 +1,44 @@ -% test -echo "Hello World" \ No newline at end of file +% cheatsheets + +# Download default cheatsheets +navi repo add denisidoro/cheats + +# Browse for cheatsheet repos +navi repo browse + +# Edit main local cheatsheets +f="$(navi info cheats-path)/main.cheat" +[ -f "$f" ] || navi info cheats-example > "$f" +${EDITOR:-nano} "$f" + + +% config + +# Edit config file +f="$(navi info config-path)" +[ -f "$f" ] || navi info config-example > "$f" +${EDITOR:-nano} "$f" + + +% 3rd-party + +# Search using tldr +navi --tldr "" + +# Search using cheatsh +navi --cheatsh "" + + +% widget + +# Load shell widget +shell="$(basename $SHELL)"; eval "$(navi widget $shell)" + + +% help + +# Read command-line help text +navi --help + +# Read project README.md +navi fn url::open "https://github.com/denisidoro/navi" From 4aee114b01c06064f1e57a54a575bd144b101536 Mon Sep 17 00:00:00 2001 From: Alexis Opolka <53085471+alexis-opolka@users.noreply.github.com> Date: Wed, 5 Mar 2025 18:54:45 +0100 Subject: [PATCH 26/63] Create example.cheat --- docs/examples/cheatsheet/example.cheat | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 docs/examples/cheatsheet/example.cheat diff --git a/docs/examples/cheatsheet/example.cheat b/docs/examples/cheatsheet/example.cheat new file mode 100644 index 0000000..2b22f55 --- /dev/null +++ b/docs/examples/cheatsheet/example.cheat @@ -0,0 +1,6 @@ +% first cheat + +# print something +echo "My name is !" + +$ name: whoami From 2df3f96a2aa56c5c5fad11142d9700140f29786f Mon Sep 17 00:00:00 2001 From: Alexis Opolka <53085471+alexis-opolka@users.noreply.github.com> Date: Wed, 5 Mar 2025 18:56:07 +0100 Subject: [PATCH 27/63] Create configuration/config-example.yaml --- .../configuration/config-example.yaml | 39 +++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 docs/examples/configuration/config-example.yaml diff --git a/docs/examples/configuration/config-example.yaml b/docs/examples/configuration/config-example.yaml new file mode 100644 index 0000000..ae2706f --- /dev/null +++ b/docs/examples/configuration/config-example.yaml @@ -0,0 +1,39 @@ +# THIS IS EXPERIMENTAL +# the config file schema may change at any time + +style: + tag: + color: cyan # text color. possible values: https://bit.ly/3gloNNI + width_percentage: 26 # column width relative to the terminal window + min_width: 20 # minimum column width as number of characters + comment: + color: blue + width_percentage: 42 + min_width: 45 + snippet: + color: white + +finder: + command: fzf # equivalent to the --finder option + # overrides: --tac # equivalent to the --fzf-overrides option + # overrides_var: --tac # equivalent to the --fzf-overrides-var option + # delimiter_var: \s\s+ # equivalent to the --delimiter option that is used with --column option when you extract a column from the selected result for a variable + +# cheats: +# paths: +# - /path/to/some/dir # on unix-like os +# - F:\\path\\to\\dir # on Windows +# path: /path/to/some/dir # (DEPRECATED) equivalent to the --path option + +# search: +# tags: git,!checkout # equivalent to the --tag-rules option + +# client: +# tealdeer: true # enables tealdeer support for navi --tldr + +shell: + # Shell used for shell out. Possible values: bash, zsh, dash, ... + # For Windows, use `cmd.exe` instead. + command: bash + + # finder_command: bash # similar, but for fzf's internals From e56ab84dc637fb4b18d5ed95df7c65a3e6c98637 Mon Sep 17 00:00:00 2001 From: Alexis Opolka <53085471+alexis-opolka@users.noreply.github.com> Date: Wed, 5 Mar 2025 19:01:29 +0100 Subject: [PATCH 28/63] Update README.md Removed mention to Alfred as it's support has been dropped and removed. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 9a7ecdc..cb12271 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,7 @@ An interactive cheatsheet tool for the command-line. - it will make you type less - it will teach you new one-liners -It uses [fzf](https://github.com/junegunn/fzf), [skim](https://github.com/lotabout/skim), or [Alfred](https://www.alfredapp.com/) under the hood and it can be either used as a command or as a shell widget (_à la_ Ctrl-R). +It uses [fzf](https://github.com/junegunn/fzf) or [skim](https://github.com/lotabout/skim) under the hood and it can be either used as a command or as a shell widget (_à la_ Ctrl-R). ## Table of contents From 58d58eafce807ad6665290d1d56c9747afa0394f Mon Sep 17 00:00:00 2001 From: Alexis Opolka <53085471+alexis-opolka@users.noreply.github.com> Date: Fri, 7 Mar 2025 20:06:32 +0100 Subject: [PATCH 29/63] Update README.md Added instructions on how to remove the powershell module. --- docs/widgets/README.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/docs/widgets/README.md b/docs/widgets/README.md index 926cc80..b5e8805 100644 --- a/docs/widgets/README.md +++ b/docs/widgets/README.md @@ -15,6 +15,14 @@ Widgets are 3rd-party contributions and integrates Navi with 3rd-party software | NuShell || | PowerShell || +## PowerShell Widget + +- Removal + +```powershell +Remove-Module navi.plugin +``` + ## Other widgets - Tmux From a16239582685869bd1130a2fb5702af4197dd16a Mon Sep 17 00:00:00 2001 From: alexis-opolka <53085471+alexis-opolka@users.noreply.github.com> Date: Sat, 15 Mar 2025 11:15:06 +0100 Subject: [PATCH 30/63] Updates the CODEOWNERS Signed-off-by: alexis-opolka <53085471+alexis-opolka@users.noreply.github.com> --- .github/CODEOWNERS | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 34a30c4..981dc16 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -1 +1,4 @@ * @denisidoro + +shell/navi.plugin.ps1 @alexis-opolka +docs/* @alexis-opolka From 51c474f9955f612a8de40fb99bbd8668b28c8223 Mon Sep 17 00:00:00 2001 From: alexis-opolka <53085471+alexis-opolka@users.noreply.github.com> Date: Sat, 15 Mar 2025 11:35:48 +0100 Subject: [PATCH 31/63] Update the CODEOWNERS Signed-off-by: alexis-opolka <53085471+alexis-opolka@users.noreply.github.com> --- .github/CODEOWNERS | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 981dc16..061d83a 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -1,4 +1,5 @@ * @denisidoro +/.github/ @denisidoro shell/navi.plugin.ps1 @alexis-opolka docs/* @alexis-opolka From 16c97d15c6d7f1173ee58058ffe2891e4257c2e6 Mon Sep 17 00:00:00 2001 From: alexis-opolka <53085471+alexis-opolka@users.noreply.github.com> Date: Sat, 15 Mar 2025 11:36:05 +0100 Subject: [PATCH 32/63] Removes the entry for the deprecated Alfred feature Signed-off-by: alexis-opolka <53085471+alexis-opolka@users.noreply.github.com> --- README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/README.md b/README.md index cb12271..460f914 100644 --- a/README.md +++ b/README.md @@ -54,7 +54,6 @@ There are multiple ways to use **navi**: - pros: you can use your cheatsheets in any command-line app even in SSH sessions - as [aliases](docs/cheatsheet_syntax.md#aliases) - as a [shell scripting tool](docs/shell_scripting.md) -- as an [Alfred workflow](docs/alfred.md) In particular, check [these instructions](https://github.com/denisidoro/navi/issues/491) if you want to replicate what's shown in the demo above. From d5f16642137c85bbcdd2fa0d53bdd34ccd4ce511 Mon Sep 17 00:00:00 2001 From: alexis-opolka <53085471+alexis-opolka@users.noreply.github.com> Date: Sat, 15 Mar 2025 11:53:06 +0100 Subject: [PATCH 33/63] Added a help page on how works the CODEOWNERS file Signed-off-by: alexis-opolka <53085471+alexis-opolka@users.noreply.github.com> --- .github/CODEOWNERS | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 061d83a..c34daf9 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -1,3 +1,5 @@ +# See: https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/about-code-owners + * @denisidoro /.github/ @denisidoro From fbf4c0165b00116891c07a3eb6dc7af0260c202c Mon Sep 17 00:00:00 2001 From: alexis-opolka <53085471+alexis-opolka@users.noreply.github.com> Date: Mon, 24 Mar 2025 01:54:22 +0100 Subject: [PATCH 34/63] Quick refactor Signed-off-by: alexis-opolka <53085471+alexis-opolka@users.noreply.github.com> --- docs/cheatsheet/examples/example.cheat | 6 -- docs/cheatsheet/examples/navi.cheat | 44 ---------- .../examples/config_file_example.yaml | 39 --------- docs/{utilisation => usage}/README.md | 0 .../shell-scripting/README.md | 80 +++++++++---------- 5 files changed, 40 insertions(+), 129 deletions(-) delete mode 100644 docs/cheatsheet/examples/example.cheat delete mode 100644 docs/cheatsheet/examples/navi.cheat delete mode 100644 docs/configuration/examples/config_file_example.yaml rename docs/{utilisation => usage}/README.md (100%) rename docs/{utilisation => usage}/shell-scripting/README.md (96%) diff --git a/docs/cheatsheet/examples/example.cheat b/docs/cheatsheet/examples/example.cheat deleted file mode 100644 index 2b22f55..0000000 --- a/docs/cheatsheet/examples/example.cheat +++ /dev/null @@ -1,6 +0,0 @@ -% first cheat - -# print something -echo "My name is !" - -$ name: whoami diff --git a/docs/cheatsheet/examples/navi.cheat b/docs/cheatsheet/examples/navi.cheat deleted file mode 100644 index 0e68698..0000000 --- a/docs/cheatsheet/examples/navi.cheat +++ /dev/null @@ -1,44 +0,0 @@ -% cheatsheets - -# Download default cheatsheets -navi repo add denisidoro/cheats - -# Browse for cheatsheet repos -navi repo browse - -# Edit main local cheatsheets -f="$(navi info cheats-path)/main.cheat" -[ -f "$f" ] || navi info cheats-example > "$f" -${EDITOR:-nano} "$f" - - -% config - -# Edit config file -f="$(navi info config-path)" -[ -f "$f" ] || navi info config-example > "$f" -${EDITOR:-nano} "$f" - - -% 3rd-party - -# Search using tldr -navi --tldr "" - -# Search using cheatsh -navi --cheatsh "" - - -% widget - -# Load shell widget -shell="$(basename $SHELL)"; eval "$(navi widget $shell)" - - -% help - -# Read command-line help text -navi --help - -# Read project README.md -navi fn url::open "https://github.com/denisidoro/navi" diff --git a/docs/configuration/examples/config_file_example.yaml b/docs/configuration/examples/config_file_example.yaml deleted file mode 100644 index ae2706f..0000000 --- a/docs/configuration/examples/config_file_example.yaml +++ /dev/null @@ -1,39 +0,0 @@ -# THIS IS EXPERIMENTAL -# the config file schema may change at any time - -style: - tag: - color: cyan # text color. possible values: https://bit.ly/3gloNNI - width_percentage: 26 # column width relative to the terminal window - min_width: 20 # minimum column width as number of characters - comment: - color: blue - width_percentage: 42 - min_width: 45 - snippet: - color: white - -finder: - command: fzf # equivalent to the --finder option - # overrides: --tac # equivalent to the --fzf-overrides option - # overrides_var: --tac # equivalent to the --fzf-overrides-var option - # delimiter_var: \s\s+ # equivalent to the --delimiter option that is used with --column option when you extract a column from the selected result for a variable - -# cheats: -# paths: -# - /path/to/some/dir # on unix-like os -# - F:\\path\\to\\dir # on Windows -# path: /path/to/some/dir # (DEPRECATED) equivalent to the --path option - -# search: -# tags: git,!checkout # equivalent to the --tag-rules option - -# client: -# tealdeer: true # enables tealdeer support for navi --tldr - -shell: - # Shell used for shell out. Possible values: bash, zsh, dash, ... - # For Windows, use `cmd.exe` instead. - command: bash - - # finder_command: bash # similar, but for fzf's internals diff --git a/docs/utilisation/README.md b/docs/usage/README.md similarity index 100% rename from docs/utilisation/README.md rename to docs/usage/README.md diff --git a/docs/utilisation/shell-scripting/README.md b/docs/usage/shell-scripting/README.md similarity index 96% rename from docs/utilisation/shell-scripting/README.md rename to docs/usage/shell-scripting/README.md index 83eb136..5a90ec8 100644 --- a/docs/utilisation/shell-scripting/README.md +++ b/docs/usage/shell-scripting/README.md @@ -1,40 +1,40 @@ -## Using it for shell scripting - -For a real world scenario example, please check this [blog post](https://denisidoro.github.io/posts/cli-templates/). - -Let's say you want to write a bash script that, among other things, asks the user to write the name of a git branch that should be checked out. - -If you already have the [cheatsheet above](#cheatsheet-syntax), then you could write the following in your script: - -```sh -navi --query "change branch" --best-match -``` - -**navi** will ask the user to fill all arguments needed. - -If you want to set the `` beforehand in your script: - -```sh -branch="master" navi --query "change branch" --best-match -``` - -- no interactive input will be shown -- the value for `` will be exactly the one passed as argument - -If you want to filter some results for ``: - -```sh -branch__query="master" navi --query "change branch" --best-match -``` - -- an interactive input will be shown, unless a single entry is autoselected -- the value for `` will be the one selected - -If you want to select the best match for ``: - -```sh -branch__best="master" navi --query "change branch" --best-match -``` - -- no interactive input will be shown -- the value for `` will be the one that best matches the one passed as argument +## Using it for shell scripting + +For a real world scenario example, please check this [blog post](https://denisidoro.github.io/posts/cli-templates/). + +Let's say you want to write a bash script that, among other things, asks the user to write the name of a git branch that should be checked out. + +If you already have the [cheatsheet above](#cheatsheet-syntax), then you could write the following in your script: + +```sh +navi --query "change branch" --best-match +``` + +**navi** will ask the user to fill all arguments needed. + +If you want to set the `` beforehand in your script: + +```sh +branch="master" navi --query "change branch" --best-match +``` + +- no interactive input will be shown +- the value for `` will be exactly the one passed as argument + +If you want to filter some results for ``: + +```sh +branch__query="master" navi --query "change branch" --best-match +``` + +- an interactive input will be shown, unless a single entry is autoselected +- the value for `` will be the one selected + +If you want to select the best match for ``: + +```sh +branch__best="master" navi --query "change branch" --best-match +``` + +- no interactive input will be shown +- the value for `` will be the one that best matches the one passed as argument From 8169ec4d74b78ae160da30e3842fa86730b18e1c Mon Sep 17 00:00:00 2001 From: alexis-opolka <53085471+alexis-opolka@users.noreply.github.com> Date: Mon, 24 Mar 2025 03:02:53 +0100 Subject: [PATCH 35/63] Refactor + update cheatsheets and cheatsheet repositories articles Signed-off-by: alexis-opolka <53085471+alexis-opolka@users.noreply.github.com> --- docs/cheatsheet/README.md | 54 +++++++++++- docs/cheatsheet/repositories/README.md | 116 ++++++++++++++----------- 2 files changed, 118 insertions(+), 52 deletions(-) diff --git a/docs/cheatsheet/README.md b/docs/cheatsheet/README.md index c8eca6e..a96ea96 100644 --- a/docs/cheatsheet/README.md +++ b/docs/cheatsheet/README.md @@ -1 +1,53 @@ -# Navi cheatsheets \ No newline at end of file +# Navi cheatsheets + + +* [Navi cheatsheets](#navi-cheatsheets) + * [Working with `cheatsheet repositories`](#working-with-cheatsheet-repositories) + * [Manually adding cheatsheets to navi](#manually-adding-cheatsheets-to-navi) + * [Submitting cheatsheets](#submitting-cheatsheets) + * [Using cheatsheets from other tools](#using-cheatsheets-from-other-tools) + + +## Working with `cheatsheet repositories` + +Navi works best with what we call `cheatsheet repositories`, for more details see [cheatsheet/repositories](repositories/README.md). + +## Manually adding cheatsheets to navi + +If you don't want to work with `cheatsheet repositories`, you can manually add your +cheatsheets to navi by putting them into the `cheats_path` of your platform. + +You can find out your path using the [info](/docs/usage/commands/info/README.md) subcommands +but a quick working command to go there would be: + +- Before 2.25.0 + + ```bash + cd $(navi info cheats-path) + ``` + +- After 2.25.0 + + ```bash + cd $(navi info default-cheats-path) + ``` + +## Using cheatsheets from other tools + +> [!WARNING] +> Navi **DOESN'T SUPPORT** as of now importing cheatsheets from other tools +> but is able to **work with** TLDR and CheatSH. + +![Demo](https://user-images.githubusercontent.com/3226564/91878474-bae27500-ec55-11ea-8b19-17876178e887.gif) + +You can use cheatsheets from [tldr](https://github.com/tldr-pages/tldr) by running: + +```sh +navi --tldr +``` + +You can use cheatsheets from [cheat.sh](https://github.com/chubin/cheat.sh) by running: + +```sh +navi --cheatsh +``` diff --git a/docs/cheatsheet/repositories/README.md b/docs/cheatsheet/repositories/README.md index dfc5a45..0344324 100644 --- a/docs/cheatsheet/repositories/README.md +++ b/docs/cheatsheet/repositories/README.md @@ -1,75 +1,89 @@ -## Cheatsheet repositories +# Cheatsheet repositories -- [Browsing through cheatsheet repositories](#browsing-through-cheatsheet-repositories) -- [Importing cheatsheets](#importing-cheatsheets) -- [Adding your own cheatsheets](#adding-your-own-cheatsheets) -- [Submitting cheatsheets](#submitting-cheatsheets) -- [Using cheatsheets from other tools](#using-cheatsheets-from-other-tools) -- [Auto-updating repositories](#auto-updating-repositories) +## Table of contents -### Browsing through cheatsheet repositories + +* [Cheatsheet repositories](#cheatsheet-repositories) + * [Table of contents](#table-of-contents) + * [About](#about) + * [Browsing through cheatsheet repositories](#browsing-through-cheatsheet-repositories) + * [Importing cheatsheet repositories](#importing-cheatsheet-repositories) + * [Submitting cheatsheets](#submitting-cheatsheets) + * [Auto-updating repositories](#auto-updating-repositories) + -You can find cheatsheet repositories with: +## About + +Navi lets you work with what we call `cheatsheet repositories`, they are git repositories +and mainly consists of `.cheat` files. + +This page is dedicated to the information you might need to work with `cheatsheet repositories`. + +## Browsing through cheatsheet repositories + +Navi lets you browse featured [GitHub](https://github.com) repositories registered in [@denisidoro/cheats/featured_repos.txt](https://github.com/denisidoro/cheats/blob/master/featured_repos.txt). + +You can find them within navi with the following command: ```sh navi repo browse ``` -### Importing cheatsheets +## Importing cheatsheet repositories -You can import cheatsheets from any git repository that includes `.cheat` files: +You can import `cheatsheet repositories` using a working git-clone format.\ +This includes using an HTTPS URL or an SSH URI. -```sh -navi repo add https://github.com/denisidoro/cheats -``` +- Import using HTTPS -### Adding your own cheatsheets + ```sh + navi repo add https://github.com/denisidoro/cheats + ``` -You can either start a git repo with cheatsheets and import it as described above or you can add them directly to [data_dir](https://github.com/soc/dirs-rs#Features)`/navi`. +- Import using SSH -### Submitting cheatsheets + ```shell + navi repo add git@github.com:denisidoro/cheats + ``` -The main repository for cheatsheets is [denisidoro/cheats](https://github.com/denisidoro/cheats). Feel free to open a PR there for me to include your contributions. +## Submitting cheatsheets -In order to add your own repository as a featured cheatsheet repo, please [edit this file](https://github.com/denisidoro/cheats/edit/master/featured_repos.txt). This list will be displayed when `navi repo browse` is run. +The featured repository for cheatsheets is [denisidoro/cheats](https://github.com/denisidoro/cheats), +feel free to open a PR[^1] there for me to include your contributions. -### Using cheatsheets from other tools +In order to add your own repository as a featured cheatsheet repo, please [edit this file](https://github.com/denisidoro/cheats/edit/master/featured_repos.txt) and open a PR[^1]. -![Demo](https://user-images.githubusercontent.com/3226564/91878474-bae27500-ec55-11ea-8b19-17876178e887.gif) +## Auto-updating repositories -You can use cheatsheets from [tldr](https://github.com/tldr-pages/tldr) by running: +Right now, **navi** doesn't have support for auto-updating out of the box. +However, you can achieve this by using `git` and `crontab`. -```sh -navi --tldr -``` +- First make sure you cloned your repo using `git` to the correct folder: -You can use cheatsheets from [cheat.sh](https://github.com/chubin/cheat.sh) by running: + ```sh + user="" + repo="" + git clone "https://github.com/${user}/${repo}" "$(navi info cheats-path)/${user}__${repo}" + ``` -```sh -navi --cheatsh -``` +- Then, add a cron job: -### Auto-updating repositories + ```sh + crontab -e + */0 11 * * * bash -c 'cd "$(/usr/local/bin/navi info cheats-path)/__" && /usr/local/bin/git pull -q origin master' + ``` -Right now, **navi** doesn't have support for auto-updating out of the box. However, you can achieve this by using `git` and `crontab`. +> [!NOTE] +> Please note the cron job above is just an example **AND** you should edit it accordingly: +> +>- In this example, the cron job is triggered every day at 11am. +> +> You might want to check out [crontab guru](https://crontab.guru/) regarding crontab. +> +>- The full paths to `navi` and `git` may differ in your setup. +> +> Check their actual values using `which` as `which `. +> +>- Don't forget to replace `__` with the actual folder name -First make sure you cloned your repo using `git` to the correct folder: - -```sh -user="" -repo="" -git clone "https://github.com/${user}/${repo}" "$(navi info cheats-path)/${user}__${repo}" -``` - -Then, add a cron job: - -```sh -crontab -e -*/0 11 * * * bash -c 'cd "$(/usr/local/bin/navi info cheats-path)/__" && /usr/local/bin/git pull -q origin master' -``` - -Please note the cron job above is just an example and you should edit it accordingly: - -- In this example, the cron job is triggered every day at 11am. [crontab guru](https://crontab.guru/) may come in handy if you want to change this value -- The full paths to `navi` and `git` may differ in your setup. Check their actual values using `which navi` and `which git` -- Don't forget to replace `__` with the actual folder name +[^1]: A *PR* is short for Pull Request From 97ac48d47b99cc1f687dedb75051b6ebba5e6e7b Mon Sep 17 00:00:00 2001 From: alexis-opolka <53085471+alexis-opolka@users.noreply.github.com> Date: Mon, 24 Mar 2025 03:20:45 +0100 Subject: [PATCH 36/63] Fixes small typo Signed-off-by: alexis-opolka <53085471+alexis-opolka@users.noreply.github.com> --- docs/cheatsheet/README.md | 2 +- docs/cheatsheet/repositories/README.md | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/cheatsheet/README.md b/docs/cheatsheet/README.md index a96ea96..b6c5fc5 100644 --- a/docs/cheatsheet/README.md +++ b/docs/cheatsheet/README.md @@ -36,7 +36,7 @@ but a quick working command to go there would be: > [!WARNING] > Navi **DOESN'T SUPPORT** as of now importing cheatsheets from other tools -> but is able to **work with** TLDR and CheatSH. +> but is able to **work with** TLDR and Cheat.sh. ![Demo](https://user-images.githubusercontent.com/3226564/91878474-bae27500-ec55-11ea-8b19-17876178e887.gif) diff --git a/docs/cheatsheet/repositories/README.md b/docs/cheatsheet/repositories/README.md index 0344324..df2f8aa 100644 --- a/docs/cheatsheet/repositories/README.md +++ b/docs/cheatsheet/repositories/README.md @@ -78,11 +78,11 @@ However, you can achieve this by using `git` and `crontab`. > >- In this example, the cron job is triggered every day at 11am. > -> You might want to check out [crontab guru](https://crontab.guru/) regarding crontab. +> You might want to check out [crontab guru](https://crontab.guru/) regarding crontab. > >- The full paths to `navi` and `git` may differ in your setup. > -> Check their actual values using `which` as `which `. +> Check their actual values using `which` as `which `. > >- Don't forget to replace `__` with the actual folder name From 678894c87445beefb9202363d477a43e5343c994 Mon Sep 17 00:00:00 2001 From: Alexis Opolka <53085471+alexis-opolka@users.noreply.github.com> Date: Mon, 24 Mar 2025 03:25:10 +0100 Subject: [PATCH 37/63] Update new-docs branch (#26) * Fix CI lint errors * Run ci on pull requests * Update powershell plugins metadata Signed-off-by: alexis-opolka <53085471+alexis-opolka@users.noreply.github.com> * Tries to implement the call to Signed-off-by: alexis-opolka <53085471+alexis-opolka@users.noreply.github.com> * Moves Navi plugin to its own repository https://github.com/alexis-opolka/navi.plugin.pwsh Signed-off-by: alexis-opolka <53085471+alexis-opolka@users.noreply.github.com> * Adds a check to create the profile file if it doesn't exist Signed-off-by: alexis-opolka <53085471+alexis-opolka@users.noreply.github.com> * Allow cheatsheet items with same descriptions Prior to the refactor performed in https://github.com/denisidoro/navi/pull/760, cheatsheet items could have the same tags and the same description, but a different snippet, and they would all be listed in the finder. After the refactor, this behavior has changed and such items will now be treated as non-unique. There appears to be no requirement for item descriptions to be distinct, so this patch restores the earlier behavior. Fixes: https://github.com/denisidoro/navi/issues/951 Signed-off-by: Erik Gabriel Carrillo * Revert "Moves Navi plugin to its own repository" This reverts commit 2bb57a23b89e1a08e0fc14a183177c2a7de9fb69. * Update shell.rs It should remove the need to put a "-" in the middle of the name. It's a bit impractical. * Update shell.rs Updated the link to the module. * Create navi.plugin.psm1 Moves the file to the base folder, removed cmdlets handlers and related options. Still needs modifications. * Improved vim syntax highlighting documentation * Update navi pwsh plugin Signed-off-by: alexis-opolka <53085471+alexis-opolka@users.noreply.github.com> * Integrates the shortcut key in the module definition Signed-off-by: alexis-opolka <53085471+alexis-opolka@users.noreply.github.com> * Update powershell plugin definition and exports Co-authored-by: KITAGAWA Yasutaka Signed-off-by: alexis-opolka <53085471+alexis-opolka@users.noreply.github.com> * Update Module exports Signed-off-by: alexis-opolka <53085471+alexis-opolka@users.noreply.github.com> * Fixes powershell export Signed-off-by: alexis-opolka <53085471+alexis-opolka@users.noreply.github.com> * Fixes the issue with unauthorized I/O redirection Signed-off-by: alexis-opolka <53085471+alexis-opolka@users.noreply.github.com> * Update cd.yml --------- Signed-off-by: alexis-opolka <53085471+alexis-opolka@users.noreply.github.com> Signed-off-by: Erik Gabriel Carrillo Co-authored-by: KITAGAWA Yasutaka Co-authored-by: Erik Gabriel Carrillo Co-authored-by: Denis Isidoro Co-authored-by: Rodinei Fagundes --- .github/workflows/cd.yml | 2 +- .github/workflows/ci.yml | 5 +- docs/widgets/howto/VIM.md | 26 ++++---- shell/navi.plugin.ps1 | 95 ++++++++++++++---------------- shell/navi.plugin/navi.plugin.psd1 | 25 -------- shell/navi.plugin/navi.plugin.psm1 | 56 ------------------ src/commands/shell.rs | 4 +- src/common/shell.rs | 2 +- src/common/terminal.rs | 2 +- src/parser.rs | 5 +- src/structures/item.rs | 2 +- 11 files changed, 70 insertions(+), 154 deletions(-) delete mode 100644 shell/navi.plugin/navi.plugin.psd1 delete mode 100644 shell/navi.plugin/navi.plugin.psm1 diff --git a/.github/workflows/cd.yml b/.github/workflows/cd.yml index 75a9b5d..5f40fc5 100644 --- a/.github/workflows/cd.yml +++ b/.github/workflows/cd.yml @@ -44,7 +44,7 @@ jobs: id: get_version run: echo ::set-output name=VERSION::${GITHUB_REF/refs\/tags\//} - name: Upload binaries to release - uses: svenstaro/upload-release-action@v1-release + uses: alexis-opolka/upload-release-action with: repo_token: ${{ secrets.GITHUB_TOKEN }} file: target/tar/navi.${{ steps.build.outputs.EXTENSION }} diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 9e2f261..5bc3566 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -4,7 +4,10 @@ # for simplicity we are compiling and testing everything on the Ubuntu environment only. # For multi-OS testing see the `cross.yml` workflow. -on: [push] +on: + push: + pull_request: + branches: [master] name: CI diff --git a/docs/widgets/howto/VIM.md b/docs/widgets/howto/VIM.md index 97c75d0..70af1c9 100644 --- a/docs/widgets/howto/VIM.md +++ b/docs/widgets/howto/VIM.md @@ -1,13 +1,13 @@ -## vim - -If you want syntax highlighting support for Navi in Vim, add those syntax rules -to your syntax files such as at `$VIMRUNTIME/syntax/navi.vim`. -The rules are defined based on the [Cheatsheet syntax](cheatsheet_syntax.md). - -```vim -syntax match Comment "\v^;.*$" -syntax match Statement "\v^\%.*$" -syntax match Operator "\v^\#.*$" -syntax match String "\v\<.*\>" -syntax match String "\v^\$.*$" -``` +## vim + +If you want syntax highlighting support for Navi in Vim, add those syntax rules +to your syntax files such as at `$VIMRUNTIME/syntax/navi.vim`. +The rules are defined based on the [Cheatsheet syntax](cheatsheet_syntax.md). + +```vim +syntax match Comment "\v^;.*$" +syntax match Statement "\v^\%.*$" +syntax match Operator "\v^\#.*$" +syntax match String "\v\<.{-}\>" +syntax match String "\v^\$.*$" +``` diff --git a/shell/navi.plugin.ps1 b/shell/navi.plugin.ps1 index 0cf73da..f31d74a 100644 --- a/shell/navi.plugin.ps1 +++ b/shell/navi.plugin.ps1 @@ -1,60 +1,55 @@ -### This script installs the Powershell module under the user's Powershell modules path -### For modifications of the Powershell Navi plugin, see /shell/navi.plugin/navi.plugin.psm1. - -param ( - ### Controls if we update the current module (otherwise we don't rewrite the already existing module, if present) - [Switch]$Update, - ### Should the verbosity be enabled? - [Switch]$Verbose -) -function InstallNaviWidgetModule(){ - [String]$PwshModulePath = $env:PSModulePath.Split(";")[0]; - [String]$NAVI_PLUGIN = "navi.plugin"; +$null = New-Module { - Write-Debug "Are we updating the PowerShell module: $Update" - Write-Debug "Current Root Powershell Module path is: $PwshModulePath" + function Invoke-Navi { + $startArgs = @{ + FileName = "navi"; + Arguments = $args; + RedirectStandardOutput = $true; + WorkingDirectory = $PWD; + UseShellExecute = $false; + } + $p = [System.Diagnostics.Process]@{StartInfo = $startArgs} - ### If we're updating the module, Copy the newly updated contents to the currently installed module - ### then quit with a successful exit code. - ### We're not supposed to update the shortcut binding. - if ($Update){ - Write-Debug "Updating Navi-Widget PowerShell module" - Copy-Item -Path .\navi.plugin\ -Destination $PwshModulePath -Force -Recurse - exit 0 + [void]$p.Start() + $result = $p.StandardOutput.ReadToEnd() + $p.WaitForExit() + + $result } - ### If we're not updating, check if we don't have the module already installed - if (-Not (Test-Path -Path $PwshModulePath\$NAVI_PLUGIN)) { - Write-Debug "Copying Item to the path" - Copy-Item -Path .\navi.plugin\ -Destination $PwshModulePath -Recurse - } else { - Write-Error "Navi-Widget is already installed for PowerShell!" - exit 1 + + ### Initial code from @lurebat (https://github.com/lurebat/) + ### See #570 (https://github.com/denisidoro/navi/issues/570) for its original contribution + function Invoke-NaviWidget { + $ast = $tokens = $errors = $cursor = $null + [Microsoft.PowerShell.PSConsoleReadLine]::GetBufferState([ref] $ast, [ref] $tokens, [ref] $errors, [ref] $cursor) + + $line = $ast.ToString().Trim() + $output = $null + + if ([String]::IsNullOrEmpty($line)) { + $output = (Invoke-Navi "--print" | Out-String).Trim() + } + else { + $best_match = (Invoke-Navi "--print --best-match --query `"$line`"" | Out-String).Trim() + if ([String]::IsNullOrEmpty($best_match)) { + $output = (Invoke-Navi "--print --query `"$line`"" | Out-String).Trim() + } + else { + $output = $best_match + } + } + + [Microsoft.PowerShell.PSConsoleReadLine]::InvokePrompt() + + ### Handling the case when the user escapes without selecting any entry + if (-Not([String]::IsNullOrEmpty($output))) { + [Microsoft.PowerShell.PSConsoleReadLine]::Insert([String]$output) + } } - Write-Debug "Registering the navi shortcut inside the current shell session" Set-PSReadlineKeyHandler -BriefDescription "A keybinding to open Navi Widget" -Chord Ctrl+g -ScriptBlock { Invoke-NaviWidget } - - Write-Debug "Appending the navi shortcut inside the current user's profile" - ### Adding a new line - Write-Output "Import-Module navi.plugin" >> $PROFILE - Write-Output "" >> $PROFILE - Write-Output 'Set-PSReadlineKeyHandler -BriefDescription "A keybinding to open Navi Widget" -Chord Ctrl+g -ScriptBlock { Invoke-NaviWidget }' >> $PROFILE - - - Write-Output "Navi plugin has been installed!" - exit 0 ### Succesful installation -} - -if ($Verbose) { - ### Enabling verbose/debug output at the start of the script - $DebugPreference = 'Continue' - InstallNaviWidgetModule -Update $Update - ### Disabling verbose/debug output at the end of the script - ### in order to not modify the current user's shell environment - $DebugPreference = 'SilentlyContinue' -} else { - InstallNaviWidgetModule -Update $Update + Export-ModuleMember -Function @() } diff --git a/shell/navi.plugin/navi.plugin.psd1 b/shell/navi.plugin/navi.plugin.psd1 deleted file mode 100644 index 86e8da3..0000000 --- a/shell/navi.plugin/navi.plugin.psd1 +++ /dev/null @@ -1,25 +0,0 @@ -# -# Module manifest for module 'navi.plugin' -# -# Generated by: Alexis Opolka (@alexis-opolka) - - -@{ -RootModule = './navi.plugin.psm1' -ModuleVersion = '1.0' -GUID = '59287935-a9b6-4a7f-a1f5-bd6180d9056f' -Author = 'Alexis-Opolka' -CompanyName = 'None' -Copyright = '(c) Alexis Opolka & Navi contributors. All rights reserved.' -FunctionsToExport = @('Invoke-NaviWidget') -CmdletsToExport = @() -VariablesToExport = '*' -AliasesToExport = @() -PrivateData = @{ - PSData = @{ - } -} -### Here should go the HelpInfo XML file if it's supported in -### a later version. -HelpInfoURI = '' -} diff --git a/shell/navi.plugin/navi.plugin.psm1 b/shell/navi.plugin/navi.plugin.psm1 deleted file mode 100644 index 7088afe..0000000 --- a/shell/navi.plugin/navi.plugin.psm1 +++ /dev/null @@ -1,56 +0,0 @@ - -[CmdletBinding()] -param ( - ### Should we debug this PS Script ? - ### Caution: Set-PSDebug is not limited to this script but enables session-wide calls - ### Be sure to disable Verbose output before calling any other shell modules or scripts. - [Parameter()] - [bool] - $VerboseOutput -) - -if ($VerboseOutput) { - ### Outputs the running code if required - ### - ### For more details on how it works, please see: - ### - https://stackoverflow.com/a/41334715/13025136 - ### An answer and explaination from @michael-sorens (https://stackoverflow.com/users/115690/michael-sorens) - ### on how Set-PSDebug relates to set-x in LINUX/UNIX environments. - ### - ### - https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/set-psdebug?view=powershell-7.4 - ### Microsoft's Reference and documentation for the `Set-PSDebug` function. - Set-PSDebug -Trace 1 -} else { - Set-PSDebug -Trace 0 -} - - -### Initial code from @lurebat (https://github.com/lurebat/) -### See #570 (https://github.com/denisidoro/navi/issues/570) for its original contribution -function Invoke-NaviWidget { - $ast = $tokens = $errors = $cursor = $null - [Microsoft.PowerShell.PSConsoleReadLine]::GetBufferState([ref] $ast, [ref] $tokens, [ref] $errors, [ref] $cursor) - - $line = $ast.ToString().Trim() - $output = $null - - if ([String]::IsNullOrEmpty($line)) { - $output = navi --print - } - else { - $best_match = (navi --print --best-match --query $line | Out-String).Trim() - if ([String]::IsNullOrEmpty($best_match)) { - $output = (navi --print --query "$line" | Out-String).Trim() - } - else { - $output = $best_match - } - } - - [Microsoft.PowerShell.PSConsoleReadLine]::RevertLine() - - ### Handling the case when the user escapes without selecting any entry - if (-Not([String]::IsNullOrEmpty($output))) { - [Microsoft.PowerShell.PSConsoleReadLine]::Insert([String]$output) - } -} \ No newline at end of file diff --git a/src/commands/shell.rs b/src/commands/shell.rs index 992b92b..3d932bb 100644 --- a/src/commands/shell.rs +++ b/src/commands/shell.rs @@ -14,7 +14,7 @@ impl Display for Shell { Self::Fish => "fish", Self::Elvish => "elvish", Self::Nushell => "nushell", - Self::PowerShell => "powershell", + Self::Powershell => "powershell", }; write!(f, "{s}") @@ -37,7 +37,7 @@ impl Runnable for Input { Shell::Fish => include_str!("../../shell/navi.plugin.fish"), Shell::Elvish => include_str!("../../shell/navi.plugin.elv"), Shell::Nushell => include_str!("../../shell/navi.plugin.nu"), - Shell::PowerShell => include_str!("../../shell/navi.plugin.ps1"), + Shell::Powershell => include_str!("../../shell/navi.plugin.ps1"), }; println!("{content}"); diff --git a/src/common/shell.rs b/src/common/shell.rs index 13f5bbf..c9d86a6 100644 --- a/src/common/shell.rs +++ b/src/common/shell.rs @@ -12,7 +12,7 @@ pub enum Shell { Fish, Elvish, Nushell, - PowerShell, + Powershell, } #[derive(Error, Debug)] diff --git a/src/common/terminal.rs b/src/common/terminal.rs index e20432b..b88bf41 100644 --- a/src/common/terminal.rs +++ b/src/common/terminal.rs @@ -50,7 +50,7 @@ pub fn parse_ansi(ansi: &str) -> Option { } #[derive(Debug, Clone)] -pub struct Color(pub style::Color); +pub struct Color(#[allow(unused)] pub style::Color); // suppress warning: field `0` is never read. impl FromStr for Color { type Err = &'static str; diff --git a/src/parser.rs b/src/parser.rs index bcdda8f..e1d4d2b 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -254,9 +254,8 @@ impl<'a> Parser<'a> { } // duplicate - if !item.tags.is_empty() { - item.comment.is_empty(); - } + // if !item.tags.is_empty() && !item.comment.is_empty() {} + // blank if line.is_empty() { if !item.snippet.is_empty() { diff --git a/src/structures/item.rs b/src/structures/item.rs index da4a181..f5eae53 100644 --- a/src/structures/item.rs +++ b/src/structures/item.rs @@ -18,6 +18,6 @@ impl Item { } pub fn hash(&self) -> u64 { - fnv(&format!("{}{}", &self.tags.trim(), &self.comment.trim())) + fnv(&format!("{}{}{}", &self.tags.trim(), &self.comment.trim(), &self.snippet.trim())) } } From 2f3889e645d9c76e017313b1d7d3bc23ae4c56a8 Mon Sep 17 00:00:00 2001 From: alexis-opolka <53085471+alexis-opolka@users.noreply.github.com> Date: Fri, 28 Mar 2025 14:54:30 +0100 Subject: [PATCH 38/63] Update Signed-off-by: alexis-opolka <53085471+alexis-opolka@users.noreply.github.com> --- docs/usage/commands/info/README.md | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 docs/usage/commands/info/README.md diff --git a/docs/usage/commands/info/README.md b/docs/usage/commands/info/README.md new file mode 100644 index 0000000..e69de29 From 577dc08de45975efc900d737621ae4fc15502e4f Mon Sep 17 00:00:00 2001 From: alexis-opolka <53085471+alexis-opolka@users.noreply.github.com> Date: Sat, 29 Mar 2025 09:09:26 +0100 Subject: [PATCH 39/63] Fixes unintended changes on the CI Signed-off-by: alexis-opolka <53085471+alexis-opolka@users.noreply.github.com> --- .github/workflows/cd.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/cd.yml b/.github/workflows/cd.yml index 5f40fc5..75a9b5d 100644 --- a/.github/workflows/cd.yml +++ b/.github/workflows/cd.yml @@ -44,7 +44,7 @@ jobs: id: get_version run: echo ::set-output name=VERSION::${GITHUB_REF/refs\/tags\//} - name: Upload binaries to release - uses: alexis-opolka/upload-release-action + uses: svenstaro/upload-release-action@v1-release with: repo_token: ${{ secrets.GITHUB_TOKEN }} file: target/tar/navi.${{ steps.build.outputs.EXTENSION }} From 60a0a8482e71f71f3fee8ae1a6860a98bade72e5 Mon Sep 17 00:00:00 2001 From: alexis-opolka <53085471+alexis-opolka@users.noreply.github.com> Date: Sat, 29 Mar 2025 10:31:34 +0100 Subject: [PATCH 40/63] Refactors the cheatsheet syntax article Fixes https://github.com/alexis-opolka/navi/issues/16 Signed-off-by: alexis-opolka <53085471+alexis-opolka@users.noreply.github.com> --- docs/cheatsheet/README.md | 13 +- docs/cheatsheet/syntax/README.md | 198 ++++++++++++++++++------------- 2 files changed, 128 insertions(+), 83 deletions(-) diff --git a/docs/cheatsheet/README.md b/docs/cheatsheet/README.md index b6c5fc5..1e44720 100644 --- a/docs/cheatsheet/README.md +++ b/docs/cheatsheet/README.md @@ -4,7 +4,7 @@ * [Navi cheatsheets](#navi-cheatsheets) * [Working with `cheatsheet repositories`](#working-with-cheatsheet-repositories) * [Manually adding cheatsheets to navi](#manually-adding-cheatsheets-to-navi) - * [Submitting cheatsheets](#submitting-cheatsheets) + * [Choosing between queries and selection with variables](#choosing-between-queries-and-selection-with-variables) * [Using cheatsheets from other tools](#using-cheatsheets-from-other-tools) @@ -32,6 +32,17 @@ but a quick working command to go there would be: cd $(navi info default-cheats-path) ``` +## Choosing between queries and selection with variables + +Navi lets you use different methods to fill a variable value, when prompted. + +| Keyboard key | Preference | +|:------------------:|:--------------------------:| +| tab | The query is preferred | +| enter | The selection is preferred | + +It means if you enter the tab key, navi will let you enter the value. + ## Using cheatsheets from other tools > [!WARNING] diff --git a/docs/cheatsheet/syntax/README.md b/docs/cheatsheet/syntax/README.md index 531b411..375cfb6 100644 --- a/docs/cheatsheet/syntax/README.md +++ b/docs/cheatsheet/syntax/README.md @@ -1,17 +1,10 @@ # The syntax of a Navi cheatsheet -- [Syntax overview](#syntax-overview) -- [Folder structure](#folder-structure) -- [Variables](#variables) -- [Advanced variable options](#advanced-variable-options) -- [Variable dependency](#variable-dependency) -- [Multiline snippets](#multiline-snippets) -- [Variable as multiple arguments](#variable-as-multiple-arguments) -- [Aliases](#aliases) -### Syntax overview +## Syntax overview -Cheatsheets are described in `.cheat` (or `.cheat.md`) files that look like this: +Cheats are described in cheatsheet files.\ +A cheatsheet is a file that has a `.cheat` or `.cheat.md` extension and looks like this: ```sh % git, code @@ -22,80 +15,89 @@ git checkout $ branch: git branch | awk '{print $NF}' ``` -Lines starting with: +A cheatsheet can have the following elements: -- `%`: determine the start of a new cheatsheet and should contain tags -- `#`: should be descriptions of commands -- `;`: are ignored. You can use them for metacomments -- `$`: should contain commands that generate a list of possible values for a given argument [:information_source:](#variables) -- `@`: should contain tags whose associated cheatsheet you want to base on [:information_source:](#extending-cheatsheets) - -All the other non-empty lines are considered as executable commands. +| Element | Syntax | Description | +|:--------------------------------:|:------:|:----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------:| +| Tags as cheat titles | `%` | Lines starting with this character are considered the start of a new cheat command and should contain tags. | +| Cheat Description | `#` | Lines starting with this character should be the description of the cheat you're writing. | +| Cheat Comments (or Metacomments) | `;` | Lines starting with this character will be ignored by navi but they can be great as editor's comments. | +| Pre-defined variables | `$` | Lines starting with this character should contain commands that generate a list of possible values,

:information_source: See [#variables](#variables) for more details. | +| Extended cheatS | `@` | Lines starting with this character should contain tags associated to other defined cheats.

:information_source: See [#extending-cheats](#extending-cheats) for more details. | +| Executable commands | N/A | All other non-empty lines are considered as executable commands. | > [!TIP] > If you are editing cheatsheets in Visual Studio Code, you could enable syntax highlighting > by installing this extension: [@yanivmo/navi-cheatsheet-language](https://marketplace.visualstudio.com/items?itemName=yanivmo.navi-cheatsheet-language). -You can place commands in code blocks fenced with triple backticks (```` ``` ````). - -````sh -% git, code - -# Change branch -```sh -git checkout -``` - -$ branch: git branch | awk '{print $NF}' -```` - -### Variables - -The interface prompts for variable names inside brackets (eg ``). +## Variables +Variables are defined with brackets inside executable commands (e.g. ``).\ Variable names should only include alphanumeric characters and `_`. -If there's a corresponding line starting with `$` for a variable, suggestions will be displayed. Otherwise, the user will be able to type any value for it. - -If you hit `` the query typed will be preferred. If you hit `` the selection will be preferred. +You can show suggestions by using the Pre-defined variables lines (i.e. lines starting with`$`).\ +Otherwise, the user will be able to type any value for it. ### Advanced variable options -For lines starting with `$` you can use `---` to customize the behavior of `fzf` or how the value is going to be used: +For Pre-Defined variables lines, you can use `---` to customize the behavior of `fzf` +or how the value is going to be used. -```sh -# This will pick the 3rd column and use the first line as header -docker rmi +Below are examples of such customization: -# Even though "false/true" is displayed, this will print "0/1" -echo +- We define what column to use, the number of header lines and a delimiter between values. + + ```sh + # This will pick the 3rd column and use the first line as header + docker rmi + + $ image_id: docker images --- --column 3 --header-lines 1 --delimiter '\s\s+' + ``` + +- We modify the output values of a command + + ```shell + # Even though "false/true" is displayed, this will print "0/1" + echo + + $ mapped: echo 'false true' | tr ' ' '\n' --- --map "grep -q t && echo 1 || echo 0" + ``` -$ image_id: docker images --- --column 3 --header-lines 1 --delimiter '\s\s+' -$ mapped: echo 'false true' | tr ' ' '\n' --- --map "grep -q t && echo 1 || echo 0" -``` The supported parameters are: -- `--column `: extracts a single column from the selected result -- `--map `: _(experimental)_ applies a map function to the selected variable value -- `--prevent-extra`: _(experimental)_ limits the user to select one of the suggestions -- `--fzf-overrides `: _(experimental)_ applies arbitrary `fzf` overrides -- `--expand`: _(experimental)_ converts each line into a separate argument +| Parameter | Description | +|:------------------------|:-----------------------------------------------------------------------------------------:| +| `--column ` | `` is the column number to extract from the result. | +| `--map ` | **_[EXPERIMENTAL]_** `` is a map function to apply to the variable value. | +| `--prevent-extra` | **_[EXPERIMENTAL]_** This parameter will limit the user to select one of the suggestions. | +| `--fzf-overrides ` | **_[EXPERIMENTAL]_** `` is an arbitrary argument to override `fzf` behaviour. | +| `--expand` | **_[EXPERIMENTAL]_** This parameter will convert each line into a separate argument. | + In addition, it's possible to forward the following parameters to `fzf`: -- `--multi` -- `--header-lines ` -- `--delimiter ` -- `--query ` -- `--filter ` -- `--header ` -- `--preview ` -- `--preview-window ` +| Parameter forwarded to `fzf` | +|:----------------------------:| +| `--multi` | +| `--header-lines ` | +| `--delimiter ` | +| `--query ` | +| `--filter ` | +| `--header ` | +| `--preview ` | +| `--preview-window ` | ### Variable dependency -The command for generating possible inputs can implicitly refer other variables by using the `` syntax: +Pre-Defined variables can refer other defined variables in two different ways, an implicit and explicit way. + +#### Implicit dependencies + +An implicit dependency is when you refer another variable with the same syntax used in +executable commands (i.e. ``). + +The example below shows how we can depend on multiple variables to construct a path: ```sh # Should print /my/pictures/wallpapers @@ -105,7 +107,11 @@ $ pictures_folder: echo "/my/pictures" $ wallpaper_folder: echo "/wallpapers" ``` -If you want to make dependencies explicit, you can use the `$varname` syntax: +#### Explicit dependencies + +An explicit dependency is when you prepend a dollar sign (i.e. `$`) to the variable name. + +Below is an example of using explicit dependencies to give multiple choices: ```sh # If you select "hello" for , the possible values of will be "hello foo" and "hello bar" @@ -118,9 +124,23 @@ $ x: echo "hello hi" | tr ' ' '\n' $ y: echo "$x foo;$x bar" | tr ';' '\n' ``` -### Extending cheatsheets +### Variable as multiple arguments -With the `@ same tags from other cheatsheet` syntax you can reuse the same variable in multiple cheatsheets. +Variables can have multiple arguments, +below is an example of using multiple arguments to cat multiple files at the same time. + +```sh +# This will result into: cat "file1.json" "file2.json" +cat + +$ jsons: find . -iname '*.json' -type f -print --- --multi --expand +``` + +## Extending cheats + +Navi allows you to extend a cheat context with `Extended cheats` lines (i.e. starting with `@`).\ +If you put the same tags from another cheat, you will be able to share the same context and will +be able to use the same variables, for example. ```sh % dirs, common @@ -140,31 +160,45 @@ echo "/wallpapers" echo "/screenshots" ``` -### Multiline snippets +## Multiline commands/snippets -Commands may be multiline: +Commands can be multiline, we call them snippets. -```sh -# This will output "foo\nyes" -echo foo -true \ - && echo yes \ - || echo no -``` +- You can write them as follows: -### Variable as multiple arguments + ```sh + % bash, foo -```sh -# This will result into: cat "file1.json" "file2.json" -cat + # This will output "foo\nyes" + echo foo + true \ + && echo yes \ + || echo no + ``` -$ jsons: find . -iname '*.json' -type f -print --- --multi --expand -``` -### Aliases +- Or, you can place them inside Markdown code blocks, delimited by triple backticks (```` ``` ````): -**navi** doesn't have support for aliases as first-class citizens at the moment. + ````sh + % git, code + + # Change branch + ```sh + git checkout + ``` + + $ branch: git branch | awk '{print $NF}' + ```` -However, it is trivial to create aliases using **navi** + a few conventions. + +## Aliases + +**navi** doesn't have support for aliases as first-class citizens at the moment.\ +However, it is easy to create aliases using **navi** + a few conventions. + +> [!CAUTION] +> The examples below will only work if you use **navi** as a shell scripting tool. +> +> See [/docs/usage/shell-scripting](/docs/usage/shell-scripting/README.md) for more details. For example, suppose you decide to end some of your commands with `:: `: @@ -178,7 +212,7 @@ echo lorem ipsum echo foo bar ``` -Then, if you use **navi** as a [shell scripting tool](shell_scripting.md), you could add something similar to this in your `.bashrc`-like file: +You could add something similar to this in your `.bashrc`-like file: ```bash navialias() { From 85ff24ba70f4ac791035deee5a01d7275aa2888f Mon Sep 17 00:00:00 2001 From: alexis-opolka <53085471+alexis-opolka@users.noreply.github.com> Date: Sat, 29 Mar 2025 10:33:51 +0100 Subject: [PATCH 41/63] Adds the missing TOC Signed-off-by: alexis-opolka <53085471+alexis-opolka@users.noreply.github.com> --- docs/cheatsheet/syntax/README.md | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/docs/cheatsheet/syntax/README.md b/docs/cheatsheet/syntax/README.md index 375cfb6..2314ceb 100644 --- a/docs/cheatsheet/syntax/README.md +++ b/docs/cheatsheet/syntax/README.md @@ -1,5 +1,18 @@ # The syntax of a Navi cheatsheet + +* [The syntax of a Navi cheatsheet](#the-syntax-of-a-navi-cheatsheet) + * [Syntax overview](#syntax-overview) + * [Variables](#variables) + * [Advanced variable options](#advanced-variable-options) + * [Variable dependency](#variable-dependency) + * [Implicit dependencies](#implicit-dependencies) + * [Explicit dependencies](#explicit-dependencies) + * [Variable as multiple arguments](#variable-as-multiple-arguments) + * [Extending cheats](#extending-cheats) + * [Multiline commands/snippets](#multiline-commandssnippets) + * [Aliases](#aliases) + ## Syntax overview From 6d52bcd12096f62c423e16b74fa7156482d8cf0a Mon Sep 17 00:00:00 2001 From: alexis-opolka <53085471+alexis-opolka@users.noreply.github.com> Date: Sat, 29 Mar 2025 10:49:44 +0100 Subject: [PATCH 42/63] Fixes some typos and rendering issues Signed-off-by: alexis-opolka <53085471+alexis-opolka@users.noreply.github.com> --- docs/cheatsheet/syntax/README.md | 42 ++++++++++++++++---------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/docs/cheatsheet/syntax/README.md b/docs/cheatsheet/syntax/README.md index 2314ceb..e83d8c7 100644 --- a/docs/cheatsheet/syntax/README.md +++ b/docs/cheatsheet/syntax/README.md @@ -35,8 +35,8 @@ A cheatsheet can have the following elements: | Tags as cheat titles | `%` | Lines starting with this character are considered the start of a new cheat command and should contain tags. | | Cheat Description | `#` | Lines starting with this character should be the description of the cheat you're writing. | | Cheat Comments (or Metacomments) | `;` | Lines starting with this character will be ignored by navi but they can be great as editor's comments. | -| Pre-defined variables | `$` | Lines starting with this character should contain commands that generate a list of possible values,

:information_source: See [#variables](#variables) for more details. | -| Extended cheatS | `@` | Lines starting with this character should contain tags associated to other defined cheats.

:information_source: See [#extending-cheats](#extending-cheats) for more details. | +| Pre-defined variables | `$` | Lines starting with this character should contain commands that generate a list of possible values.

:information_source: See [#variables](#variables) for more details. | +| Extended cheats | `@` | Lines starting with this character should contain tags associated to other defined cheats.

:information_source: See [#extending-cheats](#extending-cheats) for more details. | | Executable commands | N/A | All other non-empty lines are considered as executable commands. | > [!TIP] @@ -48,12 +48,12 @@ A cheatsheet can have the following elements: Variables are defined with brackets inside executable commands (e.g. ``).\ Variable names should only include alphanumeric characters and `_`. -You can show suggestions by using the Pre-defined variables lines (i.e. lines starting with`$`).\ +You can show suggestions by using the Pre-defined variable lines (i.e. lines starting with`$`).\ Otherwise, the user will be able to type any value for it. ### Advanced variable options -For Pre-Defined variables lines, you can use `---` to customize the behavior of `fzf` +For Pre-Defined variable lines, you can use `---` to customize the behavior of `fzf` or how the value is going to be used. Below are examples of such customization: @@ -79,38 +79,38 @@ Below are examples of such customization: The supported parameters are: -| Parameter | Description | -|:------------------------|:-----------------------------------------------------------------------------------------:| -| `--column ` | `` is the column number to extract from the result. | -| `--map ` | **_[EXPERIMENTAL]_** `` is a map function to apply to the variable value. | +| Parameter | Description | +|:------------------------|:------------------------------------------------------------------------------------------| +| `--column ` | `` is the column number to extract from the result. | +| `--map ` | **_[EXPERIMENTAL]_** `` is a map function to apply to the variable value. | | `--prevent-extra` | **_[EXPERIMENTAL]_** This parameter will limit the user to select one of the suggestions. | -| `--fzf-overrides ` | **_[EXPERIMENTAL]_** `` is an arbitrary argument to override `fzf` behaviour. | -| `--expand` | **_[EXPERIMENTAL]_** This parameter will convert each line into a separate argument. | +| `--fzf-overrides ` | **_[EXPERIMENTAL]_** `` is an arbitrary argument to override `fzf` behaviour. | +| `--expand` | **_[EXPERIMENTAL]_** This parameter will convert each line into a separate argument. | In addition, it's possible to forward the following parameters to `fzf`: | Parameter forwarded to `fzf` | -|:----------------------------:| -| `--multi` | -| `--header-lines ` | -| `--delimiter ` | -| `--query ` | -| `--filter ` | -| `--header ` | -| `--preview ` | -| `--preview-window ` | +|:-----------------------------| +| `--multi` | +| `--header-lines ` | +| `--delimiter ` | +| `--query ` | +| `--filter ` | +| `--header ` | +| `--preview ` | +| `--preview-window ` | ### Variable dependency -Pre-Defined variables can refer other defined variables in two different ways, an implicit and explicit way. +Pre-Defined variables can refer other pre-defined variables in two different ways, an implicit and explicit way. #### Implicit dependencies An implicit dependency is when you refer another variable with the same syntax used in executable commands (i.e. ``). -The example below shows how we can depend on multiple variables to construct a path: +Below is an example of using implicit dependencies to construct a path: ```sh # Should print /my/pictures/wallpapers From a01b892ec432af80ebb6f341a188c264b9fd8039 Mon Sep 17 00:00:00 2001 From: alexis-opolka <53085471+alexis-opolka@users.noreply.github.com> Date: Sat, 29 Mar 2025 10:52:08 +0100 Subject: [PATCH 43/63] Fixes the getting started title Signed-off-by: alexis-opolka <53085471+alexis-opolka@users.noreply.github.com> --- docs/cheatsheet/getting-started/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/cheatsheet/getting-started/README.md b/docs/cheatsheet/getting-started/README.md index 15af170..f914b00 100644 --- a/docs/cheatsheet/getting-started/README.md +++ b/docs/cheatsheet/getting-started/README.md @@ -1 +1 @@ -# How to get started with navi \ No newline at end of file +# Cheatsheets - Getting started From 3f4726a09187ec4383d95e7574073c9f307c842e Mon Sep 17 00:00:00 2001 From: alexis-opolka <53085471+alexis-opolka@users.noreply.github.com> Date: Sat, 29 Mar 2025 11:36:51 +0100 Subject: [PATCH 44/63] Moves entries from the cheatsheet/repositories article to the usage/commands/repo article Signed-off-by: alexis-opolka <53085471+alexis-opolka@users.noreply.github.com> --- docs/cheatsheet/repositories/README.md | 30 ++------------------------ docs/usage/commands/repo/README.md | 30 ++++++++++++++++++++++++++ 2 files changed, 32 insertions(+), 28 deletions(-) create mode 100644 docs/usage/commands/repo/README.md diff --git a/docs/cheatsheet/repositories/README.md b/docs/cheatsheet/repositories/README.md index df2f8aa..bf14c1d 100644 --- a/docs/cheatsheet/repositories/README.md +++ b/docs/cheatsheet/repositories/README.md @@ -1,12 +1,8 @@ # Cheatsheet repositories -## Table of contents - * [Cheatsheet repositories](#cheatsheet-repositories) - * [Table of contents](#table-of-contents) * [About](#about) - * [Browsing through cheatsheet repositories](#browsing-through-cheatsheet-repositories) * [Importing cheatsheet repositories](#importing-cheatsheet-repositories) * [Submitting cheatsheets](#submitting-cheatsheets) * [Auto-updating repositories](#auto-updating-repositories) @@ -19,32 +15,10 @@ and mainly consists of `.cheat` files. This page is dedicated to the information you might need to work with `cheatsheet repositories`. -## Browsing through cheatsheet repositories - -Navi lets you browse featured [GitHub](https://github.com) repositories registered in [@denisidoro/cheats/featured_repos.txt](https://github.com/denisidoro/cheats/blob/master/featured_repos.txt). - -You can find them within navi with the following command: - -```sh -navi repo browse -``` - ## Importing cheatsheet repositories -You can import `cheatsheet repositories` using a working git-clone format.\ -This includes using an HTTPS URL or an SSH URI. - -- Import using HTTPS - - ```sh - navi repo add https://github.com/denisidoro/cheats - ``` - -- Import using SSH - - ```shell - navi repo add git@github.com:denisidoro/cheats - ``` +You can import `cheatsheet repositories` with the `repo add` subcommand.\ +See [/docs/usage/commands/repo](/docs/usage/commands/repo/README.md#importing-cheatsheet-repositories) for more details. ## Submitting cheatsheets diff --git a/docs/usage/commands/repo/README.md b/docs/usage/commands/repo/README.md new file mode 100644 index 0000000..d3869a1 --- /dev/null +++ b/docs/usage/commands/repo/README.md @@ -0,0 +1,30 @@ +# The repo subcommands of navi + +## Browsing through cheatsheet repositories + +Navi lets you browse featured [GitHub](https://github.com) repositories registered in [@denisidoro/cheats/featured_repos.txt](https://github.com/denisidoro/cheats/blob/master/featured_repos.txt). + +You can find them within navi with the following command: + +```sh +navi repo browse +``` + +# Importing cheatsheet repositories + +You can import `cheatsheet repositories` using a working git-clone format.\ +This includes using an HTTPS URL or an SSH URI. + +- Import using HTTPS + + ```sh + navi repo add https://github.com/denisidoro/cheats + ``` + +- Import using SSH + + ```shell + navi repo add git@github.com:denisidoro/cheats + ``` + +Despite `$NAVI_PATH` being set, it will not be used when installing cheat sheets directly via navi's own commands. For example when running `navi add repo `, the default paths as per the `directories-next` package will still be used. To avoid this, you may simply clone repos via a regular `git clone` command, directly into `$NAVI_PATH`. \ No newline at end of file From d59bd5ec3d971ba8b6bbc28abac628e751b9fced Mon Sep 17 00:00:00 2001 From: alexis-opolka <53085471+alexis-opolka@users.noreply.github.com> Date: Sat, 29 Mar 2025 12:09:21 +0100 Subject: [PATCH 45/63] Refactored the configuration article Fixes https://github.com/alexis-opolka/navi/issues/17 Signed-off-by: alexis-opolka <53085471+alexis-opolka@users.noreply.github.com> --- docs/configuration/README.md | 245 ++++++++++++------ docs/configuration/reference/README.md | 1 - .../configuration/config-example.yaml | 1 - docs/src/configuration/navi-custom-colors.png | Bin 0 -> 59184 bytes docs/usage/fzf-overrides/README.md | 16 ++ 5 files changed, 176 insertions(+), 87 deletions(-) delete mode 100644 docs/configuration/reference/README.md create mode 100644 docs/src/configuration/navi-custom-colors.png create mode 100644 docs/usage/fzf-overrides/README.md diff --git a/docs/configuration/README.md b/docs/configuration/README.md index dbbdac5..9819815 100644 --- a/docs/configuration/README.md +++ b/docs/configuration/README.md @@ -1,99 +1,181 @@ -- [Paths and Environment Variables](#paths-and-environment-variables) - - [Config file path](#config-file-path) - - [Cheat sheet paths](#cheat-sheet-paths) -- [Logging](#logging) -- [Customization](#customization) - - [Changing colors](#changing-colors) - - [Resizing columns](#resizing-columns) - - [Overriding fzf options](#overriding-fzf-options) - - [Defining your own delimiter](#defining-your-own-delimiter) +# Configuring Navi + +Navi allows you to configure it with a YAML configuration. + +## Paths and Environment Variables + +On the technical side, navi uses the `directories-next` crate for rust, +which defines platform-specific locations to store the configuration files, +the cache and other types of files an application might need. + +> [!TIPS] +> For example, this is why cheatsheets are being stored in `~/Library/Application Support/navi` on macOS. + +> [!NOTE] +> Interested on how `directories-next` works?\ +> Go see their `crates.io` page: [crates.io/crates/directories-next](https://crates.io/crates/directories-next) -# Paths and Environment Variables +### The default configuration file path -Navi uses the [`directories-next`](https://crates.io/crates/directories-next) package, which -defines platform-specific standard locations of directories for config, cache and other data (Mac users, this is why your files are being stored in `~/Library/Application Support/navi`). +During the compilation of navi, the default configuration file path is set by the `$NAVI_CONFIG` environment variable.\ +If it is not set, it fallbacks to `~/.config/navi/config.yaml`. -## Config file path +You can check your default configuration file path with the info subcommand, +see [/docs/usage/commands/info/](/docs/usage/commands/info/README.md#default-configuration-path) for more details. -The default config file path is set by the `$NAVI_CONFIG` environment variable. If it is not set, it fallbacks to `~/.config/navi/config.yaml`. The command -```sh -navi info config-path -``` -prints which config file path is being used. You can get a config file example by running -```sh -navi info config-example -``` -or by clicking [here](./config_file_example.yaml). To turn this example your config file, run +### Cheatsheets paths -```sh -navi info config-example > "$(navi info config-path)" -``` -## Cheat sheet paths +Navi checks the paths in the following order until either it finds a value: + +1. the `$NAVI_PATH` environment variable +2. the configuration file +3. The default value of navi + +#### The default cheatsheets path + +By default, navi stores the cheatsheets in the `~/.local/share/navi/cheats/` directory. + +You can check your default cheatsheets path with the info subcommand, +see [/docs/usage/commands/info/](/docs/usage/commands/info/README.md#default-cheatsheets-path) for more details. + +#### Defining the cheatsheets path with the environment variable + +The cheatsheets path can be defined using the `$NAVI_PATH` environment variable in a colon-separated list, for example: -The default `.cheat` files paths are defined in the `$NAVI_PATH` environment variable in a colon-separated list, e.g., ```sh export NAVI_PATH='/path/to/a/dir:/path/to/another/dir:/yet/another/dir' ``` -If this environment variable is unset or if all directories do not exist, `navi` uses the [paths defined in the config file](https://github.com/denisidoro/navi/blob/master/docs/config_file_example.yaml#L21-L24). Finally, if there is no config file or if the `.cheat` file paths was not set, the default `.cheat` file paths fallbacks to `~/.local/share/navi/cheats/`. The command -```sh -navi info cheats-path -``` -prints to you all paths used to search for `.cheat` files. -You can also add other paths at runtime by running `navi` with the `--path` option and a colon-separated paths list, e.g., +#### Defining the cheatsheets path in the configuration file + +You can define the cheatsheets path in the configuration file with the following syntax: + +```yaml +cheats: + paths: + - /path/to/some/dir # on unix-like os + - F:\\path\\to\\dir # on Windows +``` + +##### [DEPRECATED] - Using the `path` directive + +Until `2.17.0`, you could define your cheatsheets path with the `path` directive with the following syntax: + +```yaml +cheats: + path: /path/to/some/dir +``` + +The directive is now deprecated and will be removed in `2.27.0`. + +#### Defining the cheatsheets path at runtime + +You can define the paths to use for cheatsheets at runtime using the `--path` parameter and a colon-separated paths list + +For example, if we want to search for cheatsheets in `/some/dir` and in `/other/dir`: + ```sh navi --path '/some/dir:/other/dir' ``` -It's irrelevant the directory structure within each path. They can even be all in a single file if you wish, as long as you split them accordingly with lines starting with `%`. -Despite `$NAVI_PATH` being set, it will not be used when installing cheat sheets directly via navi's own commands. For example when running `navi add repo `, the default paths as per the `directories-next` package will still be used. To avoid this, you may simply clone repos via a regular `git clone` command, directly into `$NAVI_PATH`. +## Logging -Note! `navi info cheats-path` and `navi info config-path` display the *default* path, not -the path set by the user. [It is known that this is a little misleading!](https://github.com/denisidoro/navi/issues/664#issuecomment-1004721178). +The log file will be created under the same directory where the configuration file is located.\ +You can use the `RUST_LOG` environment variable to set the log level. -# Logging +For example, to have the logging in debug mode when running navi: -The log file will be created under the same directory where the config locates. - -And you can use the `RUST_LOG` env to set the log level, e.g. `RUST_LOG=debug navi`. - -# Customization - -## Changing colors - -You can change the [color scheme](https://github.com/junegunn/fzf/wiki/Color-schemes) by [overriding fzf options](#overriding-fzf-options). - -In addition, you can change the text color for each column by properly configuring _navi_'s `config.yaml`. Please check `navi --help` for more instructions. - -## Resizing columns - -You can change the column widths by properly configuring _navi_'s `config.yaml`. Please check `navi --help` for more instructions. - -## Overriding fzf options - -Let's say you want to override [$FZF_DEFAULT_OPTS](https://github.com/junegunn/fzf#layout) with `--height 3`. - -This can be overridden in the following ways: - -```sh -# if you want to override only when selecting snippets -navi --fzf-overrides '--height 3' - -# alternatively, using an environment variable in your .bashrc-like file: -export NAVI_FZF_OVERRIDES='--height 3' - -# if you want to override only when selecting argument values -navi --fzf-overrides-var '--height 3' - -# alternatively, using an environment variable in your .bashrc-like file: -export NAVI_FZF_OVERRIDES_VAR='--height 3' - -# if you want to override for all cases -FZF_DEFAULT_OPTS="--height 3" navi +```bash +RUST_LOG=debug navi ``` -In addition, this can be set by properly configuring _navi_'s `config.yaml`. Please check `navi --help` for more instructions. +> [!NOTE] +> If the directory of the configuration file doesn't exist, no log file +> is going to be created. + +## Customization + +### Changing colors + +#### fzf color scheme + +You can change the color scheme of `fzf` by overriding fzf options. + +> [!NOTE] +> See [@junegunn/fzf/wiki/Color-schemes](https://github.com/junegunn/fzf/wiki/Color-schemes) and +> [#overriding-fzf-options](#overriding-fzf-options) for more details. + +#### Navi colors + +You can change the text color for each column of navi in the configuration file with the following syntax: + +```yaml +style: + tag: + color: + comment: + color: + snippet: + color: +``` + +Below is an example of what to do if you'd like navi to look like the French flag: + +- `config.yaml`: + + ```yaml + style: + tag: + color: blue + comment: + color: white + snippet: + color: red + ``` + +- The result: + + ![img.png](/docs/src/configuration/navi-custom-colors.png) + +### Resizing columns + +You can change the column width of each column of navi in the configuration file with the following syntax: + +```yaml +style: + tag: + width_percentage: + min_width: + comment: + width_percentage: + min_width: + snippet: + width_percentage: + min_width: +``` + +### Overriding fzf options + +If you want to override `$FZF_DEFAULT_OPTS` with `--height 3`, +you can do it with the following syntax: + +```yaml +finder: + command: fzf + overrides: --height 3 +``` + +or + +```yaml +finder: + command: fzf + overrides_var: --height 3 +``` + +> [!NOTE] +> See [@junegunn/fzf](https://github.com/junegunn/fzf#layout) for more details on `$FZF_DEFAULT_OPTS`. ## Defining your own delimiter @@ -111,13 +193,6 @@ finder: > Defining the delimiter via the configuration file means that Navi will use this delimiter by default for > every variable using the `--column` instruction. -You can override this configuration with the `--delimiter` instruction in the variable definition of your cheatsheet. +You can override this configuration with the `--delimiter` instruction in the variable definition of your cheat.\ +See [/docs/cheatsheet/syntax/](/docs/cheatsheet/syntax/README.md#advanced-variable-options) for more details. -It can be overriden like this: - -```yaml -echo - -$ image_id: ... --- --column 3 --header-lines 1 --delimiter '\s\s+' # <-- This variable uses \s\s+ as a delimiter -$ image_tag: ... --- --column 3 --header-lines 1 # <-- This variable uses the default delimiter -``` diff --git a/docs/configuration/reference/README.md b/docs/configuration/reference/README.md deleted file mode 100644 index 50eb9c7..0000000 --- a/docs/configuration/reference/README.md +++ /dev/null @@ -1 +0,0 @@ -# Configuration file reference \ No newline at end of file diff --git a/docs/examples/configuration/config-example.yaml b/docs/examples/configuration/config-example.yaml index ae2706f..a96b494 100644 --- a/docs/examples/configuration/config-example.yaml +++ b/docs/examples/configuration/config-example.yaml @@ -23,7 +23,6 @@ finder: # paths: # - /path/to/some/dir # on unix-like os # - F:\\path\\to\\dir # on Windows -# path: /path/to/some/dir # (DEPRECATED) equivalent to the --path option # search: # tags: git,!checkout # equivalent to the --tag-rules option diff --git a/docs/src/configuration/navi-custom-colors.png b/docs/src/configuration/navi-custom-colors.png new file mode 100644 index 0000000000000000000000000000000000000000..2b3831b4ed469b87342b172b41a53b91f640359a GIT binary patch literal 59184 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∾hV%=6pQBNISrv%lK_E07YT>lBDaJ~ z2qYW^NJ0`LJK?D8)BUpF_Wh7N|0nOvWRCwk^Zwr7%n;>8ReRu)2Cud{xzg1qpu#(S zk#ijZEYYwNdB_@vmS9nvyDP=f*_;=f-Z+3&0BCA7u#`M%5`l1g6&d{4`rLAs9tU)LfBrq@=0ty&HbZl|^2e0vLRp_b-BP60ve>$w~jNRGsWQ zOFc$(mu*?d75;sdY5|{pB4&E-ShCdy1K|76{vx>@VZc!xMn8@eyCxz5=lixHlIOe{ z)Ein6$g&Bei?7#eC~g*l^JOyJvqKseR;<}K7HXC|z+cjtE{1Tydpn%v=v~XN{0uk5 z5ydLwf7kzcL=D<%^<&Qwa1C|PXC zX|qQ`@dcWwehukKVnv5P*iANsA~oJkL#zqg$%>hu?JgK`bzS~MgLtI&}+mC3m;zTE&nL`bFg@lP-lw||%76P9 z55p8qW+b;VmY97Zd`FnEF8)eYaj9X-@ZVA9%ua`vfi~F=aX{_7yHuGP1fpl-{Dc}> z^Lx;M%^ChHt86~@^x97;a=jE2T9L2x3TjB+bjo~SDV_KT~Yl@ zZ{dVLdqvp`p5iX5IIU0Nz*3s#Pi}Xljvb8COO*2kf9e&?2V{rHO=N{elD-bct9U1TL23R?u&i zel`kH$Th4UZjv#m=Yk`me%JN53dM&nTkNoz*Ta8T>ReLvfT-alM@ zuYp1FG%oJzA55Yo5^wL%9l;xlR@;;pG6ZxtKhZC-g-Tx_`a0kTd|5RrDdqGkR^J%2 zt0Nd2m{9Fp%gcS@r0IR%V022tc_)@Nb*gD^DRZ7O6VcR}h|MMiXN!^EfS_*aosb;2 zDbj%Qt^!VBPAToMP3M8bzmh&0mCNa$8Ao|t4H2xlC6TaC`_>+xXFuvyN6VViO3q6I zD(jVagso;iiJHeDoDF>!5WJ6eD+_xK%+gxkuyrm7VE;Y4z4Wfd!^qJ%F&bkSL5Tz(9fSgOf-e5k`mnm>o^hi%=83vGmGOtZctTy z5>{p#{TW6^Vw^sYacLP1;H_PJo!;CZvXpZk39aa~Buvye-`v!quA4Biipx!?(!7p~ zjS=iCCz!__90jz1F2+Z8)q*|myRM72Y|Js0gDCXzlPipbUY0eTg6?ds)9BU*B|x3*yj*9q}Td-_)(Nbdfx7tRuh> z;`n11fNl&_DIV)Dt8E* z0accK1~y(O0Lb`H;c5d`Qi4oKI=Gpq(2n3rs2Y!c0oWWZaa5yj~>X?t)Gf7Y_lYSH5An_Fp^n_xcj>d7~*$P%z)#L)SM zL`7Ht8<~>g)|UI2tB#u1Alo@|V)iJ*lbq!eouiLVOe@);-k+})Cwn9FyWJ*Yo zy$02S(B6x51OJ64MZj_060Q-bh@K(M8k=sBe?Z-{-`OiwB{Qu%)dX&+h6LwSuJdKr zwWAhe?oi)XzbSb_Rm5nt;_OfaaNnfwB?nbdN#Yb(+-~rP#mesu4wXqors*L8S#Zse z%Wh9|rgX^!kL@@*Un^Q|Bo^E#7Y6}0rB*SIQ@?nvCTHMZj$LZSGujoYq!W5XfrnOaP6( z^MKADE6m=J09N0(+XquEOwVaEY_Xo?{PqXEZ~r@`S*#gl_KPd*Qz-#IIMe8ZPgKvn zZ2Z+-ModB8lyL2uSSn+L^R#L#do=S=8vWKuIaKH+{jJ{t%dQS+7zkIiUq~Ttn$@~u zs)FZP({q{HnerIFM@O~D-<%K!bvC7o4YXeuI2`Puy31SIst>m53++)KM_`$IZR(yL z+E(&RFrDUn)R0`?W*eMs7unh~y|kN7)(_7IQ~#DkB`~b#Fd9BFx*zX5v_E=YF~s9B zN2u1xiCQCJvRQ}3yyZ=q2?jMZ=|ifU;3J#c?89?syM-=2WyUZ-EpR$Fv84vS`Qu=t zd2#j~3TFmM37F6B-Zti&;pMK2J9f*Z`|bOb;{6C)=~FNX*bJ2|Ya`alk;ntlsy_wu z)p`tT^LggsCbND0`Ml!A|LDKt|3m-%pA~t{i@@6rU;Xq7LKJp%htAP+wzoyd*JVu$ i`?pu}ABtk7)wK&(^nAkR48IjO%Vi_8i})X0?*AM5jRNZc literal 0 HcmV?d00001 diff --git a/docs/usage/fzf-overrides/README.md b/docs/usage/fzf-overrides/README.md new file mode 100644 index 0000000..b3e6d2c --- /dev/null +++ b/docs/usage/fzf-overrides/README.md @@ -0,0 +1,16 @@ +```sh +# if you want to override only when selecting snippets +navi --fzf-overrides '--height 3' + +# alternatively, using an environment variable in your .bashrc-like file: +export NAVI_FZF_OVERRIDES='--height 3' + +# if you want to override only when selecting argument values +navi --fzf-overrides-var '--height 3' + +# alternatively, using an environment variable in your .bashrc-like file: +export NAVI_FZF_OVERRIDES_VAR='--height 3' + +# if you want to override for all cases +FZF_DEFAULT_OPTS="--height 3" navi +``` \ No newline at end of file From 3d833a0aa90339179bef885a806908c06632a17c Mon Sep 17 00:00:00 2001 From: Alexis Opolka <53085471+alexis-opolka@users.noreply.github.com> Date: Sat, 29 Mar 2025 12:11:56 +0100 Subject: [PATCH 46/63] Update README.md Fixes a typo --- docs/configuration/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/configuration/README.md b/docs/configuration/README.md index 9819815..e199b85 100644 --- a/docs/configuration/README.md +++ b/docs/configuration/README.md @@ -8,7 +8,7 @@ On the technical side, navi uses the `directories-next` crate for rust, which defines platform-specific locations to store the configuration files, the cache and other types of files an application might need. -> [!TIPS] +> [!TIP] > For example, this is why cheatsheets are being stored in `~/Library/Application Support/navi` on macOS. > [!NOTE] From 87c85f40c161df1a7ee51ec097932e412aaf63f4 Mon Sep 17 00:00:00 2001 From: Alexis Opolka <53085471+alexis-opolka@users.noreply.github.com> Date: Sat, 29 Mar 2025 12:13:14 +0100 Subject: [PATCH 47/63] Update README.md --- docs/configuration/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/configuration/README.md b/docs/configuration/README.md index e199b85..eca44c0 100644 --- a/docs/configuration/README.md +++ b/docs/configuration/README.md @@ -26,7 +26,7 @@ see [/docs/usage/commands/info/](/docs/usage/commands/info/README.md#default-con ### Cheatsheets paths -Navi checks the paths in the following order until either it finds a value: +Navi checks the paths in the following order until it finds a value: 1. the `$NAVI_PATH` environment variable 2. the configuration file From 958bcc6538a652e5d15756c2fca73fa2064b4fba Mon Sep 17 00:00:00 2001 From: alexis-opolka <53085471+alexis-opolka@users.noreply.github.com> Date: Sat, 29 Mar 2025 12:29:21 +0100 Subject: [PATCH 48/63] Updated the fzf overrides part Signed-off-by: alexis-opolka <53085471+alexis-opolka@users.noreply.github.com> --- docs/configuration/README.md | 65 ++++++++++++++++++++++++++++-- docs/usage/commands/info/README.md | 46 +++++++++++++++++++++ 2 files changed, 108 insertions(+), 3 deletions(-) diff --git a/docs/configuration/README.md b/docs/configuration/README.md index 9819815..01a57a3 100644 --- a/docs/configuration/README.md +++ b/docs/configuration/README.md @@ -2,6 +2,26 @@ Navi allows you to configure it with a YAML configuration. + +* [Configuring Navi](#configuring-navi) + * [Paths and Environment Variables](#paths-and-environment-variables) + * [The default configuration file path](#the-default-configuration-file-path) + * [Cheatsheets paths](#cheatsheets-paths) + * [The default cheatsheets path](#the-default-cheatsheets-path) + * [Defining the cheatsheets path with the environment variable](#defining-the-cheatsheets-path-with-the-environment-variable) + * [Defining the cheatsheets path in the configuration file](#defining-the-cheatsheets-path-in-the-configuration-file) + * [[DEPRECATED] - Using the `path` directive](#deprecated---using-the-path-directive) + * [Defining the cheatsheets path at runtime](#defining-the-cheatsheets-path-at-runtime) + * [Logging](#logging) + * [Customization](#customization) + * [Changing colors](#changing-colors) + * [fzf color scheme](#fzf-color-scheme) + * [Navi colors](#navi-colors) + * [Resizing columns](#resizing-columns) + * [Overriding fzf options](#overriding-fzf-options) + * [Defining your own delimiter](#defining-your-own-delimiter) + + ## Paths and Environment Variables On the technical side, navi uses the `directories-next` crate for rust, @@ -157,8 +177,24 @@ style: ### Overriding fzf options -If you want to override `$FZF_DEFAULT_OPTS` with `--height 3`, -you can do it with the following syntax: +You can override fzf options for two different cases: + +- During the cheats selection + + Navi exposes the `overrides` directive in the configuration file + and the `NAVI_FZF_OVERRIDES` environment variable. + +- During the pre-defined variable values selection + + Navi exposes the `overrides_var` directive in the configuration file + and the `NAVI_FZF_OVERRIDES_VAR` environment variable. + +For all cases, navi exposes the `FZF_DEFAULT_OPTS` environment variable. + +#### Overriding during cheats selection + +If you want to override do the override with `--height 3`, +you can do it with the following syntax in the configuration file: ```yaml finder: @@ -166,7 +202,16 @@ finder: overrides: --height 3 ``` -or +But you can also define the environment variable like this: + +```bash +export NAVI_FZF_OVERRIDES='--height 3' +``` + +#### Overriding during values selection + +If you want to override do the override with `--height 3`, +you can do it with the following syntax in the configuration file: ```yaml finder: @@ -174,6 +219,20 @@ finder: overrides_var: --height 3 ``` +But you can also define the environment variable like this: + +```bash +export NAVI_FZF_OVERRIDES_VAR='--height 3' +``` + +#### Overriding for all cases + +You can define the environment variable like this: + +```bash +export FZF_DEFAULT_OPTS="--height 3" +``` + > [!NOTE] > See [@junegunn/fzf](https://github.com/junegunn/fzf#layout) for more details on `$FZF_DEFAULT_OPTS`. diff --git a/docs/usage/commands/info/README.md b/docs/usage/commands/info/README.md index e69de29..5771ecf 100644 --- a/docs/usage/commands/info/README.md +++ b/docs/usage/commands/info/README.md @@ -0,0 +1,46 @@ +# The info subcommands of navi + +Navi exposes information about its default values or examples for you to use. + +## Default configuration information + +### Default configuration path + +Navi exposes its default configuration path with: + +```sh +navi info config-path +``` + +> [!NOTE] +> See [/docs/configuration/](/docs/configuration/README.md#the-default-configuration-file-path) for more details on how the default configuration path is defined. + +### Example configuration file + +Navi lets you get an example configuration file with: + +```sh +navi info config-example +``` + +> [!NOTE] +> You can retrieve this file at the following address: [/docs/examples/configuration/config-example.yaml](/docs/examples/configuration/config-example.yaml) + +For example, you can use this command to create the default configuration file, +if not already present: + +```sh +navi info config-example > "$(navi info config-path)" +``` + +## Default cheatsheets path + +Navi exposes its default cheatsheets path with: + +```sh +navi info cheats-path +``` + +> [!NOTE] +> See [/docs/configuration/](/docs/configuration/README.md#the-default-cheatsheets-path) for more details on how the cheatsheets path is defined. + From 790aed326b7f9c331305f4c418f02f700fa62956 Mon Sep 17 00:00:00 2001 From: alexis-opolka <53085471+alexis-opolka@users.noreply.github.com> Date: Sat, 29 Mar 2025 12:31:47 +0100 Subject: [PATCH 49/63] Moved parts around and updated the TOC Signed-off-by: alexis-opolka <53085471+alexis-opolka@users.noreply.github.com> --- docs/configuration/README.md | 25 ------------------------- docs/usage/README.md | 26 ++++++++++++++++++++++++++ docs/usage/fzf-overrides/README.md | 6 ------ 3 files changed, 26 insertions(+), 31 deletions(-) diff --git a/docs/configuration/README.md b/docs/configuration/README.md index 2dc5c3a..ff74c87 100644 --- a/docs/configuration/README.md +++ b/docs/configuration/README.md @@ -89,31 +89,6 @@ cheats: The directive is now deprecated and will be removed in `2.27.0`. -#### Defining the cheatsheets path at runtime - -You can define the paths to use for cheatsheets at runtime using the `--path` parameter and a colon-separated paths list - -For example, if we want to search for cheatsheets in `/some/dir` and in `/other/dir`: - -```sh -navi --path '/some/dir:/other/dir' -``` - -## Logging - -The log file will be created under the same directory where the configuration file is located.\ -You can use the `RUST_LOG` environment variable to set the log level. - -For example, to have the logging in debug mode when running navi: - -```bash -RUST_LOG=debug navi -``` - -> [!NOTE] -> If the directory of the configuration file doesn't exist, no log file -> is going to be created. - ## Customization ### Changing colors diff --git a/docs/usage/README.md b/docs/usage/README.md index e69de29..db1b745 100644 --- a/docs/usage/README.md +++ b/docs/usage/README.md @@ -0,0 +1,26 @@ + + +#### Defining the cheatsheets path at runtime + +You can define the paths to use for cheatsheets at runtime using the `--path` parameter and a colon-separated paths list + +For example, if we want to search for cheatsheets in `/some/dir` and in `/other/dir`: + +```sh +navi --path '/some/dir:/other/dir' +``` + +## Logging + +The log file will be created under the same directory where the configuration file is located.\ +You can use the `RUST_LOG` environment variable to set the log level. + +For example, to have the logging in debug mode when running navi: + +```bash +RUST_LOG=debug navi +``` + +> [!NOTE] +> If the directory of the configuration file doesn't exist, no log file +> is going to be created. \ No newline at end of file diff --git a/docs/usage/fzf-overrides/README.md b/docs/usage/fzf-overrides/README.md index b3e6d2c..ea508ff 100644 --- a/docs/usage/fzf-overrides/README.md +++ b/docs/usage/fzf-overrides/README.md @@ -2,15 +2,9 @@ # if you want to override only when selecting snippets navi --fzf-overrides '--height 3' -# alternatively, using an environment variable in your .bashrc-like file: -export NAVI_FZF_OVERRIDES='--height 3' - # if you want to override only when selecting argument values navi --fzf-overrides-var '--height 3' -# alternatively, using an environment variable in your .bashrc-like file: -export NAVI_FZF_OVERRIDES_VAR='--height 3' - # if you want to override for all cases FZF_DEFAULT_OPTS="--height 3" navi ``` \ No newline at end of file From 3405582c8caaf8a09c6cc645827fedc1255f2692 Mon Sep 17 00:00:00 2001 From: alexis-opolka <53085471+alexis-opolka@users.noreply.github.com> Date: Sat, 29 Mar 2025 12:33:28 +0100 Subject: [PATCH 50/63] Fixed a typo Signed-off-by: alexis-opolka <53085471+alexis-opolka@users.noreply.github.com> --- docs/configuration/README.md | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/docs/configuration/README.md b/docs/configuration/README.md index ff74c87..0e1647c 100644 --- a/docs/configuration/README.md +++ b/docs/configuration/README.md @@ -11,14 +11,15 @@ Navi allows you to configure it with a YAML configuration. * [Defining the cheatsheets path with the environment variable](#defining-the-cheatsheets-path-with-the-environment-variable) * [Defining the cheatsheets path in the configuration file](#defining-the-cheatsheets-path-in-the-configuration-file) * [[DEPRECATED] - Using the `path` directive](#deprecated---using-the-path-directive) - * [Defining the cheatsheets path at runtime](#defining-the-cheatsheets-path-at-runtime) - * [Logging](#logging) * [Customization](#customization) * [Changing colors](#changing-colors) * [fzf color scheme](#fzf-color-scheme) * [Navi colors](#navi-colors) * [Resizing columns](#resizing-columns) * [Overriding fzf options](#overriding-fzf-options) + * [Overriding during cheats selection](#overriding-during-cheats-selection) + * [Overriding during values selection](#overriding-during-values-selection) + * [Overriding for all cases](#overriding-for-all-cases) * [Defining your own delimiter](#defining-your-own-delimiter) @@ -168,7 +169,7 @@ For all cases, navi exposes the `FZF_DEFAULT_OPTS` environment variable. #### Overriding during cheats selection -If you want to override do the override with `--height 3`, +If you want to do the override with `--height 3`, you can do it with the following syntax in the configuration file: ```yaml @@ -185,7 +186,7 @@ export NAVI_FZF_OVERRIDES='--height 3' #### Overriding during values selection -If you want to override do the override with `--height 3`, +If you want to do the override with `--height 3`, you can do it with the following syntax in the configuration file: ```yaml From 018378ec932a57784067674cacf7f24fffd48797 Mon Sep 17 00:00:00 2001 From: alexis-opolka <53085471+alexis-opolka@users.noreply.github.com> Date: Sat, 29 Mar 2025 12:43:50 +0100 Subject: [PATCH 51/63] Introduce a developers documentation entry Signed-off-by: alexis-opolka <53085471+alexis-opolka@users.noreply.github.com> --- docs/developers/README.md | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 docs/developers/README.md diff --git a/docs/developers/README.md b/docs/developers/README.md new file mode 100644 index 0000000..92de8e9 --- /dev/null +++ b/docs/developers/README.md @@ -0,0 +1,30 @@ +# Developers documentation + +This documentation entry is destined to contributors of the navi project +and open-source repository. + +## Versioning Scheme + +| Type | Description | +|-------|--------------------------------------------------------------------------------------------------| +| Major | Anything which introduces a major breaking change. The bash to rust rewrite was such an example. | +| Minor | Almost everything. | +| Fix | A fix, just like its name. It should be micro releases with minimal changes. | + +## Deprecation of features + +Once you introduce a feature, you need to have a clear view of when we're +going to remove its support within navi. + +In order to offer stability to the users, we prefer having 10 minor versions +between the deprecation notice and the removal of its support. + +````txt +Version where the feature is being deprecated: 0.10.0 +Version where the support is dropped: 0.20.0 +```` + +> [!NOTE] +> This rule is not absolute and each feature deprecation needs to be handled +> carefully given its own circumstances, but try to stick as close as possible +> to this rule. From e02fb9e20ddf5758390bb986da3042f165249f86 Mon Sep 17 00:00:00 2001 From: alexis-opolka <53085471+alexis-opolka@users.noreply.github.com> Date: Sat, 29 Mar 2025 23:05:19 +0100 Subject: [PATCH 52/63] Refactors the installation documentation Fixes https://github.com/alexis-opolka/navi/issues/18 Signed-off-by: alexis-opolka <53085471+alexis-opolka@users.noreply.github.com> --- docs/installation/README.md | 197 +++++++++++++++++------------------- docs/widgets/README.md | 58 +++++++++-- 2 files changed, 142 insertions(+), 113 deletions(-) diff --git a/docs/installation/README.md b/docs/installation/README.md index e3c223d..8f24fc1 100644 --- a/docs/installation/README.md +++ b/docs/installation/README.md @@ -1,160 +1,147 @@ # Installation of navi +Navi can be installed by multiple ways, here is a list of referenced ways to do so. ---- +> [!CAUTION] +> Navi, as of now, has only two official builds, the released binaries on GitHub +> and the published package on brew. +> +> All the other packages are community-maintained. -WIP below +## Using package managers - -## Installation - -- [Installing the main binary](#installing-the-main-binary) - - [Using Homebrew](#using-homebrew) - - [Using Gentoo](#using-gentoo) - - [Using nix](#using-nix) - - [Using cargo](#using-cargo) - - [Using install script](#using-install-script) - - [Downloading pre-compiled binaries](#downloading-pre-compiled-binaries) - - [Building from source](#building-from-source) - - [Other package managers](#other-package-managers) -- [Installing the shell widget](#installing-the-shell-widget) - -### Installing the main binary - -#### Using [Homebrew](http://brew.sh/) +### Homebrew ```sh brew install navi ``` -#### Using [Gentoo](https://gentoo.org/) +> [!NOTE] +> See [brew.sh](https://brew.sh/) for more details. -Be sure to [enable](https://wiki.gentoo.org/wiki/Ebuild_repository) the [GURU overlay](https://gpo.zugaina.org/Overlays/guru/app-misc/navi). +### Using Gentoo + +> [!WARNING] +> You need to enable the GURU overlay for the instructions below to work correctly. +> +> For more details see: +> +> - [wiki.gentoo.org/wiki/Ebuild_repository](https://wiki.gentoo.org/wiki/Ebuild_repository) +> - [gpo.zugaina.org/Overlays/guru/app-misc/navi](https://gpo.zugaina.org/Overlays/guru/app-misc/navi). ```sh emerge -a app-misc/navi ``` -#### Using [pacman](https://wiki.archlinux.org/title/Pacman) +> [!NOTE] +> See [Gentoo.org](https://gentoo.org/) for more details. + +### Using Pacman ```sh pacman -S navi ``` -#### Using [nix](https://nixos.org/) +> [!NOTE] +> See [wiki.archlinux.org/title/Pacman](https://wiki.archlinux.org/title/Pacman) for more details. + +### Using nix ```sh nix-env -iA nixpkgs.navi ``` -#### Using [cargo](https://github.com/rust-lang/cargo) +> [!NOTE] +> See [nixos.org](https://nixos.org/) for more details + +### Using Cargo ```bash cargo install --locked navi ``` -#### Using [choco](https://community.chocolatey.org/packages/navi) +> [!NOTE] +> See [@rust-lang/cargo](https://github.com/rust-lang/cargo) for more details. -For Windows user, using powershell +### Using Chocolatey -1. Install package via choco - ```bash - choco install navi - ``` -2. Create `$env:USERPROFILE\AppData\Roaming\navi\config.yaml` and override `shell.command` as per [config_file_example.yaml](./config_file_example.yaml) +```bash +choco install navi +``` - ``` - style: - tag: - color: cyan - comment: - color: grey - snippet: - color: white +> [!CAUTION] +> You currently need to create the config file `$env:USERPROFILE\AppData\Roaming\navi\config.yaml` +> and define the `shell.command` directive as `powershell`. +> +> ```yaml +> shell: +> command: powershell +> ``` - shell: - command: powershell - ``` +> [!NOTE] +> See [community.chocolatey.org](https://community.chocolatey.org) for more details. - Remark: Above example also adds custom colors for better readability in case you use standard blue for your Powershell +## Using the installation script -#### Using install script +Navi has an installation script ready for you to use, you can call it like this: ```bash bash <(curl -sL https://raw.githubusercontent.com/denisidoro/navi/master/scripts/install) - -# (optional) to set directories: -# BIN_DIR=/usr/local/bin bash <(curl -sL https://raw.githubusercontent.com/denisidoro/navi/master/scripts/install) ``` -#### Downloading pre-compiled binaries - -- download the correct binary [here](https://github.com/denisidoro/navi/releases/latest) -- extract the content to your `$PATH` - -#### Building from source +If you need to define the directory for the binary, you can call it like this: ```bash -git clone https://github.com/denisidoro/navi ~/.navi -cd ~/.navi -make install - -# (optional) to set the install directory: -# make BIN_DIR=/usr/local/bin install +BIN_DIR=/usr/local/bin bash <(curl -sL https://raw.githubusercontent.com/denisidoro/navi/master/scripts/install) ``` -##### Compile time environment variables +## Downloading pre-compiled binaries -**navi** supports environment variables at compile time that modify the behavior of the binary at runtime: +With each release, we try our best to build and publish a binary for each +supported platform, you can find them here: +[@denisidoro/navi/releases/latest](https://github.com/denisidoro/navi/releases/latest) -- `NAVI_PATH` (directory path value): If the `cheats` directory in the user's directory does not exist, **navi** uses this path (if it exists), as a fallback location to look for cheat files. Use case: system-wide installed, shared used cheatsheets folder. -- `NAVI_CONFIG` (file path value): If the `config.yaml` file in the user's directory does not exist, **navi** uses this path (if it exists), as a fallback location to look for a configuration file. Use case: system-wide installed, shared used configuration file. +What you need to do is: -#### Other package managers +- to download the binary corresponding to the version you want to install +- to extract the content of the archive to your `$PATH` + +## Building from source + +You can also build navi from source, it's mainly used by contributors to +test their modifications can be used by end users who want to build their own version. + +- You need to clone the repository: + + ```bash + git clone https://github.com/denisidoro/navi && cd navi + ``` + +- Call `make` + + ```bash + make install + ``` + +You can specify the binary directory with: + +```bash +make BIN_DIR=/usr/local/bin install +``` + +## Compile time environment variables + +**navi** supports environment variables at compile time that will modify the behavior of navi at runtime, they are: + +| Environment variable | Description | +|----------------------|-------------------------------------------------------------| +| `NAVI_PATH` | This defines the default path used by navi for cheatsheets. | +| `NAVI_CONFIG` | This defines the default configuration file used by navi. | + +## Other package managers You can find **navi** for more package managers by clicking on the image below: [![Packaging status](https://repology.org/badge/vertical-allrepos/navi.svg)](https://repology.org/project/navi/versions) Feel free to be the maintainer of **navi** for any package manager you'd like! - -### Installing the shell widget - -If you want to install it, add this line to your `.bashrc`-like file: - -```sh -# bash -eval "$(navi widget bash)" - -# zsh -eval "$(navi widget zsh)" - -# fish -navi widget fish | source - -# elvish -eval (navi widget elvish | slurp) - -# xonsh -# xpip install xontrib-navi # ← run in your xonsh session to install xontrib -xontrib load navi # ← add to your xonsh run control file -``` - -#### Nushell - -Due to Nushell's [unique design](https://www.nushell.sh/book/thinking_in_nu.html#think-of-nushell-as-a-compiled-language), it is not possible to `eval` a piece of code dynamically like in other shells therefore the integration process is a bit more involved. Here is an example: -1. run `^navi widget nushell | save ($nu.default-config-dir | path join "navi-integration.nu")` -2. add the following lines to `config.nu`: - ```nushell - source ($nu.default-config-dir | path join "navi-integration.nu") - ``` - - -By default, `Ctrl+G` is assigned to launching **navi** (in xonsh can be customized with `$X_NAVI_KEY`, see [xontrib-navi](https://github.com/eugenesvk/xontrib-navi) for details). - -There's currently no way to customize the widget behavior out-of-the-box. If you want to change the keybinding or the **navi** flags used by the widget, please: - -1. run, e.g., `navi widget bash` in your terminal -2. copy the output -3. paste the output in your `.bashrc`-like file -4. edit the contents accordingly diff --git a/docs/widgets/README.md b/docs/widgets/README.md index b5e8805..35c7c57 100644 --- a/docs/widgets/README.md +++ b/docs/widgets/README.md @@ -7,13 +7,13 @@ Widgets are 3rd-party contributions and integrates Navi with 3rd-party software ## List of shell widgets -| Shell | Navi support | -|-------|--------------| -| Bash | :white_check_mark: | -| Fish || -| Zsh || -| NuShell || -| PowerShell || +| Shell | Navi support | +|------------|--------------------| +| Bash | :white_check_mark: | +| Fish | | +| Zsh | | +| NuShell | | +| PowerShell | | ## PowerShell Widget @@ -26,4 +26,46 @@ Remove-Module navi.plugin ## Other widgets - Tmux -- Vim \ No newline at end of file +- Vim + + +### Installing the shell widget + +If you want to install it, add this line to your `.bashrc`-like file: + +```sh +# bash +eval "$(navi widget bash)" + +# zsh +eval "$(navi widget zsh)" + +# fish +navi widget fish | source + +# elvish +eval (navi widget elvish | slurp) + +# xonsh +# xpip install xontrib-navi # ← run in your xonsh session to install xontrib +xontrib load navi # ← add to your xonsh run control file +``` + +#### Nushell + +Due to Nushell's [unique design](https://www.nushell.sh/book/thinking_in_nu.html#think-of-nushell-as-a-compiled-language), it is not possible to `eval` a piece of code dynamically like in other shells therefore the integration process is a bit more involved. Here is an example: +1. run `^navi widget nushell | save ($nu.default-config-dir | path join "navi-integration.nu")` +2. add the following lines to `config.nu`: + ```nushell + source ($nu.default-config-dir | path join "navi-integration.nu") + ``` + + +By default, `Ctrl+G` is assigned to launching **navi** (in xonsh can be customized with `$X_NAVI_KEY`, see [xontrib-navi](https://github.com/eugenesvk/xontrib-navi) for details). + +There's currently no way to customize the widget behavior out-of-the-box. If you want to change the keybinding or the **navi** flags used by the widget, please: + +1. run, e.g., `navi widget bash` in your terminal +2. copy the output +3. paste the output in your `.bashrc`-like file +4. edit the contents accordingly From 205fc755d5bcc6c82c8596be6e5bac91994c41b8 Mon Sep 17 00:00:00 2001 From: alexis-opolka <53085471+alexis-opolka@users.noreply.github.com> Date: Sat, 29 Mar 2025 23:09:38 +0100 Subject: [PATCH 53/63] Fixes typos Signed-off-by: alexis-opolka <53085471+alexis-opolka@users.noreply.github.com> --- docs/installation/README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/installation/README.md b/docs/installation/README.md index 8f24fc1..a3587a1 100644 --- a/docs/installation/README.md +++ b/docs/installation/README.md @@ -1,6 +1,6 @@ # Installation of navi -Navi can be installed by multiple ways, here is a list of referenced ways to do so. +This is a reference of all known methods to install navi. > [!CAUTION] > Navi, as of now, has only two official builds, the released binaries on GitHub @@ -71,7 +71,7 @@ choco install navi > [!CAUTION] > You currently need to create the config file `$env:USERPROFILE\AppData\Roaming\navi\config.yaml` -> and define the `shell.command` directive as `powershell`. +> and define the `shell.command` directive as `powershell` for navi to work correctly. > > ```yaml > shell: @@ -109,7 +109,7 @@ What you need to do is: ## Building from source You can also build navi from source, it's mainly used by contributors to -test their modifications can be used by end users who want to build their own version. +test their modifications but can be used by end users who want to build their own version. - You need to clone the repository: From 179537606240ae51bf8961936dd225864faed0cf Mon Sep 17 00:00:00 2001 From: alexis-opolka <53085471+alexis-opolka@users.noreply.github.com> Date: Sat, 29 Mar 2025 23:31:55 +0100 Subject: [PATCH 54/63] Refactors shell-scripting article Signed-off-by: alexis-opolka <53085471+alexis-opolka@users.noreply.github.com> --- docs/usage/shell-scripting/README.md | 36 +++++++++++++++++----------- 1 file changed, 22 insertions(+), 14 deletions(-) diff --git a/docs/usage/shell-scripting/README.md b/docs/usage/shell-scripting/README.md index 5a90ec8..9334f55 100644 --- a/docs/usage/shell-scripting/README.md +++ b/docs/usage/shell-scripting/README.md @@ -1,40 +1,48 @@ -## Using it for shell scripting +# Navi and shell scripting -For a real world scenario example, please check this [blog post](https://denisidoro.github.io/posts/cli-templates/). +You can use Navi with shell scripting. -Let's say you want to write a bash script that, among other things, asks the user to write the name of a git branch that should be checked out. +The following blog post gives you an example of a real world scenario: [denisidoro.github.io/posts/cli-templates/](https://denisidoro.github.io/posts/cli-templates/) -If you already have the [cheatsheet above](#cheatsheet-syntax), then you could write the following in your script: +## Simply calling a cheat + +Below is an example on how to call a cheat from within navi: ```sh navi --query "change branch" --best-match ``` -**navi** will ask the user to fill all arguments needed. +> [!NOTE] +> Navi will ask the user to fill all arguments/variables needed. -If you want to set the `` beforehand in your script: +## Defining variables while calling + +If you want to set the `` beforehand in your script, you can do as follows: ```sh branch="master" navi --query "change branch" --best-match ``` -- no interactive input will be shown -- the value for `` will be exactly the one passed as argument +Navi will not show any interactive input and `` will be exactly the one defined while calling. -If you want to filter some results for ``: +## Filtering results for a variable + +If you want to filter some results for ``, you can do as follows: ```sh branch__query="master" navi --query "change branch" --best-match ``` -- an interactive input will be shown, unless a single entry is autoselected -- the value for `` will be the one selected +Navi will show any interactive input, unless a single entry is automatically selected and +the value for `` will be the one selected by the user. -If you want to select the best match for ``: +## Selecting the best match for a variable + +If you want to select the best match for ``, you can do as follows: ```sh branch__best="master" navi --query "change branch" --best-match ``` -- no interactive input will be shown -- the value for `` will be the one that best matches the one passed as argument +Navi will not show any interactive input, and the value for `` will be the one that +best matches the value passed as argument. From 8b473ccdfe86b3f5b7a41cfc4ba2f26fe0aefef6 Mon Sep 17 00:00:00 2001 From: alexis-opolka <53085471+alexis-opolka@users.noreply.github.com> Date: Sun, 30 Mar 2025 07:39:28 +0200 Subject: [PATCH 55/63] Update the usage article Signed-off-by: alexis-opolka <53085471+alexis-opolka@users.noreply.github.com> --- docs/usage/README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/usage/README.md b/docs/usage/README.md index db1b745..0454406 100644 --- a/docs/usage/README.md +++ b/docs/usage/README.md @@ -1,4 +1,6 @@ +# The usage of Navi +Navi can be used in multiple ways #### Defining the cheatsheets path at runtime @@ -23,4 +25,4 @@ RUST_LOG=debug navi > [!NOTE] > If the directory of the configuration file doesn't exist, no log file -> is going to be created. \ No newline at end of file +> is going to be created. From 64a9c0bf0127741c9873d199474d1d52b6758db3 Mon Sep 17 00:00:00 2001 From: alexis-opolka <53085471+alexis-opolka@users.noreply.github.com> Date: Tue, 1 Apr 2025 08:43:42 +0200 Subject: [PATCH 56/63] Update the examples link in commands Updated the link of navi's cheatsheet in welcome.rs Updated the link of the cheatsheet example and the configuration example in src/commands/info.rs Signed-off-by: alexis-opolka <53085471+alexis-opolka@users.noreply.github.com> --- src/commands/info.rs | 4 ++-- src/welcome.rs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/commands/info.rs b/src/commands/info.rs index 7f450e0..57d52c5 100644 --- a/src/commands/info.rs +++ b/src/commands/info.rs @@ -23,10 +23,10 @@ impl Runnable for Input { let info = &self.info; match info { - Info::CheatsExample => println!("{}", include_str!("../../docs/cheat_example.cheat")), + Info::CheatsExample => println!("{}", include_str!("../../docs/examples/cheatsheet/example.cheat")), Info::CheatsPath => println!("{}", &filesystem::default_cheat_pathbuf()?.to_string()), Info::ConfigPath => println!("{}", &filesystem::default_config_pathbuf()?.to_string()), - Info::ConfigExample => println!("{}", include_str!("../../docs/config_file_example.yaml")), + Info::ConfigExample => println!("{}", include_str!("../../docs/examples/configuration/config-example.yaml")), } Ok(()) } diff --git a/src/welcome.rs b/src/welcome.rs index 520f04f..8d9e722 100644 --- a/src/welcome.rs +++ b/src/welcome.rs @@ -3,7 +3,7 @@ use crate::prelude::*; use crate::structures::fetcher; pub fn populate_cheatsheet(parser: &mut Parser) -> Result<()> { - let cheatsheet = include_str!("../docs/navi.cheat"); + let cheatsheet = include_str!("../docs/examples/cheatsheet/navi.cheat"); let lines = cheatsheet.split('\n').map(|s| Ok(s.to_string())); parser.read_lines(lines, "welcome", None)?; From a1ca7889bb1d53c239a737322e1e6888b4ecc6e2 Mon Sep 17 00:00:00 2001 From: alexis-opolka <53085471+alexis-opolka@users.noreply.github.com> Date: Tue, 1 Apr 2025 08:45:12 +0200 Subject: [PATCH 57/63] Cargo fmt Signed-off-by: alexis-opolka <53085471+alexis-opolka@users.noreply.github.com> --- src/commands/info.rs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/commands/info.rs b/src/commands/info.rs index 57d52c5..0dea1ea 100644 --- a/src/commands/info.rs +++ b/src/commands/info.rs @@ -23,10 +23,15 @@ impl Runnable for Input { let info = &self.info; match info { - Info::CheatsExample => println!("{}", include_str!("../../docs/examples/cheatsheet/example.cheat")), + Info::CheatsExample => { + println!("{}", include_str!("../../docs/examples/cheatsheet/example.cheat")) + } Info::CheatsPath => println!("{}", &filesystem::default_cheat_pathbuf()?.to_string()), Info::ConfigPath => println!("{}", &filesystem::default_config_pathbuf()?.to_string()), - Info::ConfigExample => println!("{}", include_str!("../../docs/examples/configuration/config-example.yaml")), + Info::ConfigExample => println!( + "{}", + include_str!("../../docs/examples/configuration/config-example.yaml") + ), } Ok(()) } From fda4a2d154c4bf890fe8d13c23505dfcf785f521 Mon Sep 17 00:00:00 2001 From: alexis-opolka <53085471+alexis-opolka@users.noreply.github.com> Date: Tue, 1 Apr 2025 09:07:19 +0200 Subject: [PATCH 58/63] Update the repo subcommands docs Signed-off-by: alexis-opolka <53085471+alexis-opolka@users.noreply.github.com> --- docs/usage/commands/repo/README.md | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/docs/usage/commands/repo/README.md b/docs/usage/commands/repo/README.md index d3869a1..02e2890 100644 --- a/docs/usage/commands/repo/README.md +++ b/docs/usage/commands/repo/README.md @@ -1,5 +1,19 @@ # The repo subcommands of navi + +* [The repo subcommands of navi](#the-repo-subcommands-of-navi) + * [Commands Reference](#commands-reference) + * [Browsing through cheatsheet repositories](#browsing-through-cheatsheet-repositories) +* [Importing cheatsheet repositories](#importing-cheatsheet-repositories) + + +## Commands Reference + +| Command | Description | +|---------|-------------------------------------------------------------------| +| add | Lets you import a cheatsheet repository | +| browser | Lets you browse through a curated list of cheatsheet repositories | + ## Browsing through cheatsheet repositories Navi lets you browse featured [GitHub](https://github.com) repositories registered in [@denisidoro/cheats/featured_repos.txt](https://github.com/denisidoro/cheats/blob/master/featured_repos.txt). @@ -10,7 +24,7 @@ You can find them within navi with the following command: navi repo browse ``` -# Importing cheatsheet repositories +## Importing cheatsheet repositories You can import `cheatsheet repositories` using a working git-clone format.\ This includes using an HTTPS URL or an SSH URI. @@ -27,4 +41,8 @@ This includes using an HTTPS URL or an SSH URI. navi repo add git@github.com:denisidoro/cheats ``` -Despite `$NAVI_PATH` being set, it will not be used when installing cheat sheets directly via navi's own commands. For example when running `navi add repo `, the default paths as per the `directories-next` package will still be used. To avoid this, you may simply clone repos via a regular `git clone` command, directly into `$NAVI_PATH`. \ No newline at end of file +> [!CAUTION] +> Despite `$NAVI_PATH` being set, it will not be used when installing cheat sheets directly via navi's own commands.\ +> For example when running `navi add repo `, the default paths will still be used. +> +> To avoid this, you may simply clone repos via a regular `git clone` command, directly into `$NAVI_PATH`. From dde73701e541144c12c86f5d095d80a07dd27aba Mon Sep 17 00:00:00 2001 From: alexis-opolka <53085471+alexis-opolka@users.noreply.github.com> Date: Tue, 8 Apr 2025 09:09:54 +0200 Subject: [PATCH 59/63] [Incomplete] Add a reference for the info subcommands Signed-off-by: alexis-opolka <53085471+alexis-opolka@users.noreply.github.com> --- docs/usage/commands/info/README.md | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/docs/usage/commands/info/README.md b/docs/usage/commands/info/README.md index 5771ecf..5b3d970 100644 --- a/docs/usage/commands/info/README.md +++ b/docs/usage/commands/info/README.md @@ -2,6 +2,26 @@ Navi exposes information about its default values or examples for you to use. + +* [The info subcommands of navi](#the-info-subcommands-of-navi) + * [Commands Reference](#commands-reference) + * [Default configuration information](#default-configuration-information) + * [Default configuration path](#default-configuration-path) + * [Example configuration file](#example-configuration-file) + * [Default cheatsheets path](#default-cheatsheets-path) + + +## Commands Reference + +| Command | Description | +|---------------------|-------------| +| config-path | | +| cheats-path | | +| default-config-path | | +| default-cheats-path | | +| config-example | | +| cheats-example | | + ## Default configuration information ### Default configuration path From 1c2abfd8e8d83445d2ca33aa351e419f951d7767 Mon Sep 17 00:00:00 2001 From: alexis-opolka <53085471+alexis-opolka@users.noreply.github.com> Date: Wed, 30 Apr 2025 22:06:38 +0200 Subject: [PATCH 60/63] Updates the docs Signed-off-by: alexis-opolka <53085471+alexis-opolka@users.noreply.github.com> --- docs/usage/commands/info/README.md | 16 ++++++++-------- docs/usage/commands/repo/README.md | 2 +- docs/usage/fzf-overrides/README.md | 22 +++++++++++++++++++++- docs/usage/shell-scripting/README.md | 12 +++++++++++- 4 files changed, 41 insertions(+), 11 deletions(-) diff --git a/docs/usage/commands/info/README.md b/docs/usage/commands/info/README.md index 5b3d970..9fcdbbf 100644 --- a/docs/usage/commands/info/README.md +++ b/docs/usage/commands/info/README.md @@ -13,14 +13,14 @@ Navi exposes information about its default values or examples for you to use. ## Commands Reference -| Command | Description | -|---------------------|-------------| -| config-path | | -| cheats-path | | -| default-config-path | | -| default-cheats-path | | -| config-example | | -| cheats-example | | +| Command | Description | +|---------------------|----------------------------------------------------| +| config-path | [DEPRECATED] Lets you see the default config path | +| cheats-path | [DEPRECATED] Lets you see the default cheats path | +| default-config-path | Lets you see the default config path | +| default-cheats-path | Lets you see the default cheats path | +| config-example | Lets you see an example for the configuration file | +| cheats-example | Lets you see an example for a cheat file | ## Default configuration information diff --git a/docs/usage/commands/repo/README.md b/docs/usage/commands/repo/README.md index 02e2890..ce83054 100644 --- a/docs/usage/commands/repo/README.md +++ b/docs/usage/commands/repo/README.md @@ -4,7 +4,7 @@ * [The repo subcommands of navi](#the-repo-subcommands-of-navi) * [Commands Reference](#commands-reference) * [Browsing through cheatsheet repositories](#browsing-through-cheatsheet-repositories) -* [Importing cheatsheet repositories](#importing-cheatsheet-repositories) + * [Importing cheatsheet repositories](#importing-cheatsheet-repositories) ## Commands Reference diff --git a/docs/usage/fzf-overrides/README.md b/docs/usage/fzf-overrides/README.md index ea508ff..eecac45 100644 --- a/docs/usage/fzf-overrides/README.md +++ b/docs/usage/fzf-overrides/README.md @@ -1,10 +1,30 @@ +# The FZF Overrides of Navi + +Navi allows you to override certain parts of FZF in multiple ways. + + +* [The FZF Overrides of Navi](#the-fzf-overrides-of-navi) + * [Command line arguments](#command-line-arguments) + * [Environment variables](#environment-variables) + + +## Command line arguments + +Navi allows you to use command line arguments in order to override fzf values: + ```sh # if you want to override only when selecting snippets navi --fzf-overrides '--height 3' # if you want to override only when selecting argument values navi --fzf-overrides-var '--height 3' +``` +## Environment variables + +Navi allows you to use environment variables in order to override fzf values. + +```bash # if you want to override for all cases FZF_DEFAULT_OPTS="--height 3" navi -``` \ No newline at end of file +``` diff --git a/docs/usage/shell-scripting/README.md b/docs/usage/shell-scripting/README.md index 9334f55..3eb8036 100644 --- a/docs/usage/shell-scripting/README.md +++ b/docs/usage/shell-scripting/README.md @@ -2,7 +2,17 @@ You can use Navi with shell scripting. -The following blog post gives you an example of a real world scenario: [denisidoro.github.io/posts/cli-templates/](https://denisidoro.github.io/posts/cli-templates/) + +* [Navi and shell scripting](#navi-and-shell-scripting) + * [Simply calling a cheat](#simply-calling-a-cheat) + * [Defining variables while calling](#defining-variables-while-calling) + * [Filtering results for a variable](#filtering-results-for-a-variable) + * [Selecting the best match for a variable](#selecting-the-best-match-for-a-variable) + + +> [NOTE!] +> The following blog post gives you an example of a real world scenario: [denisidoro.github.io/posts/cli-templates/](https://denisidoro.github.io/posts/cli-templates/) + ## Simply calling a cheat From df8c0ff7b3a176b4463c058feda4ff5d25a089d1 Mon Sep 17 00:00:00 2001 From: alexis-opolka <53085471+alexis-opolka@users.noreply.github.com> Date: Wed, 30 Apr 2025 22:14:03 +0200 Subject: [PATCH 61/63] Update docs on widgets Signed-off-by: alexis-opolka <53085471+alexis-opolka@users.noreply.github.com> --- docs/widgets/howto/TMUX.md | 20 ++++++++++++++++---- docs/widgets/howto/VIM.md | 18 ++++++++++++++---- 2 files changed, 30 insertions(+), 8 deletions(-) diff --git a/docs/widgets/howto/TMUX.md b/docs/widgets/howto/TMUX.md index a9d2fb0..332c4db 100644 --- a/docs/widgets/howto/TMUX.md +++ b/docs/widgets/howto/TMUX.md @@ -1,15 +1,27 @@ -## Tmux +# Tmux widget -You can use **navi** as a [Tmux](https://github.com/tmux/tmux/wiki) widget to reach your Vim commands, often used SQL queries, etc. in any command-line app even in SSH sessions. +You can use **navi** as a [Tmux](https://github.com/tmux/tmux/wiki) widget to reach your Vim commands, +often used SQL queries, etc. in any command-line app even in SSH sessions. -Add these lines to your Tmux config file to access **navi** by pressing `prefix + C-g`. + +* [Tmux widget](#tmux-widget) + * [Keybinding navi](#keybinding-navi) + * [Example cheatsheet](#example-cheatsheet) + + +## Keybinding navi + +To be able to open navi via prefix + C-g , you need to add the following lines +to your Tmux configuration file. ```sh bind-key -N "Open Navi (cheat sheets)" -T prefix C-g split-window \ "$SHELL --login -i -c 'navi --print | head -n 1 | tmux load-buffer -b tmp - ; tmux paste-buffer -p -t {last} -b tmp -d'" ``` -Example cheatsheet: +## Example cheatsheet + +Here is an example cheatsheet to use inside Tmux: ```sh % vim diff --git a/docs/widgets/howto/VIM.md b/docs/widgets/howto/VIM.md index 70af1c9..fcfcc2c 100644 --- a/docs/widgets/howto/VIM.md +++ b/docs/widgets/howto/VIM.md @@ -1,8 +1,18 @@ -## vim +# Vim widget -If you want syntax highlighting support for Navi in Vim, add those syntax rules -to your syntax files such as at `$VIMRUNTIME/syntax/navi.vim`. -The rules are defined based on the [Cheatsheet syntax](cheatsheet_syntax.md). + +* [Vim widget](#vim-widget) + * [Syntax Highlighting](#syntax-highlighting) + + +## Syntax Highlighting + +If you want syntax highlighting support for Navi in Vim, you need to +add those syntax rules to your syntax files such as at `$VIMRUNTIME/syntax/navi.vim`. + +The rules are defined based on the [Cheatsheet syntax](/docs/cheatsheet/syntax/README.md). + +Here is an example: ```vim syntax match Comment "\v^;.*$" From c409a0f149fedc79311c1963e7f30868800caece Mon Sep 17 00:00:00 2001 From: alexis-opolka <53085471+alexis-opolka@users.noreply.github.com> Date: Wed, 30 Apr 2025 22:15:00 +0200 Subject: [PATCH 62/63] Small update Signed-off-by: alexis-opolka <53085471+alexis-opolka@users.noreply.github.com> --- docs/widgets/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/widgets/README.md b/docs/widgets/README.md index 35c7c57..fe58a2a 100644 --- a/docs/widgets/README.md +++ b/docs/widgets/README.md @@ -12,8 +12,8 @@ Widgets are 3rd-party contributions and integrates Navi with 3rd-party software | Bash | :white_check_mark: | | Fish | | | Zsh | | -| NuShell | | -| PowerShell | | +| NuShell | :white_check_mark: | +| PowerShell | :white_check_mark: | ## PowerShell Widget From 48fd4db08db61598d4f877efe95c5a9344173cdb Mon Sep 17 00:00:00 2001 From: alexis-opolka <53085471+alexis-opolka@users.noreply.github.com> Date: Sun, 4 May 2025 11:00:43 +0200 Subject: [PATCH 63/63] Did a bit of refactoring - Deleted the png file inside the repository Signed-off-by: alexis-opolka <53085471+alexis-opolka@users.noreply.github.com> --- docs/configuration/README.md | 2 +- docs/contributions/README.md | 38 +++++++++++++++++- docs/developers/README.md | 30 -------------- docs/src/configuration/navi-custom-colors.png | Bin 59184 -> 0 bytes 4 files changed, 38 insertions(+), 32 deletions(-) delete mode 100644 docs/developers/README.md delete mode 100644 docs/src/configuration/navi-custom-colors.png diff --git a/docs/configuration/README.md b/docs/configuration/README.md index 0e1647c..5e2560a 100644 --- a/docs/configuration/README.md +++ b/docs/configuration/README.md @@ -132,7 +132,7 @@ Below is an example of what to do if you'd like navi to look like the French fla - The result: - ![img.png](/docs/src/configuration/navi-custom-colors.png) + ![navi-custom-colors](https://github.com/user-attachments/assets/d80352c5-d888-43e6-927d-805a8de1a7e2) ### Resizing columns diff --git a/docs/contributions/README.md b/docs/contributions/README.md index 1dbf420..6d14d7e 100644 --- a/docs/contributions/README.md +++ b/docs/contributions/README.md @@ -1,7 +1,16 @@ -# How to contribute to Navi +# Navi contributors This section is about the ways you can contribute to Navi and its ecosystem. + +* [Navi contributors](#navi-contributors) + * [How to contribute to Navi](#how-to-contribute-to-navi) + * [Versioning Scheme](#versioning-scheme) + * [Deprecation of features](#deprecation-of-features) + + +## How to contribute to Navi + You have multiple ways to contribute to navi, here are the documented ones: - [Write code for Navi](code/README.md) @@ -9,3 +18,30 @@ You have multiple ways to contribute to navi, here are the documented ones: - [Open Bug tickets](bugs/README.md) Please see each section for more details. + + +## Versioning Scheme + +| Type | Description | +|-------|--------------------------------------------------------------------------------------------------| +| Major | Anything which introduces a major breaking change. The bash to rust rewrite was such an example. | +| Minor | Almost everything. | +| Fix | A fix, just like its name. It should be micro releases with minimal changes. | + +## Deprecation of features + +Once you introduce a feature, you need to have a clear view of when we're +going to remove its support within navi. + +In order to offer stability to the users, we prefer having 10 minor versions +between the deprecation notice and the removal of its support. + +````txt +Version where the feature is being deprecated: 0.10.0 +Version where the support is dropped: 0.20.0 +```` + +> [!NOTE] +> This rule is not absolute and each feature deprecation needs to be handled +> carefully given its own circumstances, but try to stick as close as possible +> to this rule. diff --git a/docs/developers/README.md b/docs/developers/README.md deleted file mode 100644 index 92de8e9..0000000 --- a/docs/developers/README.md +++ /dev/null @@ -1,30 +0,0 @@ -# Developers documentation - -This documentation entry is destined to contributors of the navi project -and open-source repository. - -## Versioning Scheme - -| Type | Description | -|-------|--------------------------------------------------------------------------------------------------| -| Major | Anything which introduces a major breaking change. The bash to rust rewrite was such an example. | -| Minor | Almost everything. | -| Fix | A fix, just like its name. It should be micro releases with minimal changes. | - -## Deprecation of features - -Once you introduce a feature, you need to have a clear view of when we're -going to remove its support within navi. - -In order to offer stability to the users, we prefer having 10 minor versions -between the deprecation notice and the removal of its support. - -````txt -Version where the feature is being deprecated: 0.10.0 -Version where the support is dropped: 0.20.0 -```` - -> [!NOTE] -> This rule is not absolute and each feature deprecation needs to be handled -> carefully given its own circumstances, but try to stick as close as possible -> to this rule. diff --git a/docs/src/configuration/navi-custom-colors.png b/docs/src/configuration/navi-custom-colors.png deleted file mode 100644 index 2b3831b4ed469b87342b172b41a53b91f640359a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 59184 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∾hV%=6pQBNISrv%lK_E07YT>lBDaJ~ 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