From 611c9b4f512e83eb05a4744a4b414682bbba7055 Mon Sep 17 00:00:00 2001 From: Vladimir Petrzhikovskii Date: Tue, 6 Feb 2024 00:18:49 +0100 Subject: [PATCH] feat(module): add jj module to display repository status --- .github/config-schema.json | 72 ++++ docs/config/README.md | 746 +++++++++++++++++++++++++---------- src/configs/jj.rs | 41 ++ src/configs/mod.rs | 3 + src/configs/starship_root.rs | 1 + src/formatter/model.rs | 6 +- src/module.rs | 1 + src/modules/jj.rs | 290 ++++++++++++++ src/modules/mod.rs | 3 + 9 files changed, 949 insertions(+), 214 deletions(-) create mode 100644 src/configs/jj.rs create mode 100644 src/modules/jj.rs diff --git a/.github/config-schema.json b/.github/config-schema.json index e2bade18a1f3f..d6b892747c1e2 100644 --- a/.github/config-schema.json +++ b/.github/config-schema.json @@ -868,6 +868,26 @@ } ] }, + "jj_status": { + "default": { + "branch_style": "purple", + "change_id_prefix_style": "purple", + "change_id_suffix_style": "bright-black", + "commit_id_prefix_style": "blue", + "commit_id_suffix_style": "bright-black", + "disabled": false, + "divergent_symbol": " 💥", + "format": "\\[$symbol[$change_id_prefix]($change_id_prefix_style)[$change_id_suffix]($change_id_suffix_style) [$commit_id_prefix]($commit_id_prefix_style)[$commit_id_suffix]($commit_id_suffix_style) on [$branch]($branch_style)$no_description_symbol$divergent_symbol\\]", + "no_description_symbol": " 📝", + "symbol": "🍐 ", + "truncation_length": 8 + }, + "allOf": [ + { + "$ref": "#/definitions/JJConfig" + } + ] + }, "jobs": { "default": { "disabled": false, @@ -3939,6 +3959,58 @@ }, "additionalProperties": false }, + "JJConfig": { + "type": "object", + "properties": { + "symbol": { + "default": "🍐 ", + "type": "string" + }, + "format": { + "default": "\\[$symbol[$change_id_prefix]($change_id_prefix_style)[$change_id_suffix]($change_id_suffix_style) [$commit_id_prefix]($commit_id_prefix_style)[$commit_id_suffix]($commit_id_suffix_style) on [$branch]($branch_style)$no_description_symbol$divergent_symbol\\]", + "type": "string" + }, + "disabled": { + "default": false, + "type": "boolean" + }, + "change_id_prefix_style": { + "default": "purple", + "type": "string" + }, + "change_id_suffix_style": { + "default": "bright-black", + "type": "string" + }, + "commit_id_prefix_style": { + "default": "blue", + "type": "string" + }, + "commit_id_suffix_style": { + "default": "bright-black", + "type": "string" + }, + "truncation_length": { + "default": 8, + "type": "integer", + "format": "uint8", + "minimum": 0.0 + }, + "no_description_symbol": { + "default": " 📝", + "type": "string" + }, + "divergent_symbol": { + "default": " 💥", + "type": "string" + }, + "branch_style": { + "default": "purple", + "type": "string" + } + }, + "additionalProperties": false + }, "JobsConfig": { "type": "object", "properties": { diff --git a/docs/config/README.md b/docs/config/README.md index 469e0797d7c5d..e374c7102662c 100644 --- a/docs/config/README.md +++ b/docs/config/README.md @@ -1,12 +1,14 @@ # Configuration -To get started configuring starship, create the following file: `~/.config/starship.toml`. +To get started configuring starship, create the following +file: `~/.config/starship.toml`. ```sh mkdir -p ~/.config && touch ~/.config/starship.toml ``` -All configuration for starship is done in this [TOML](https://github.com/toml-lang/toml) file: +All configuration for starship is done in +this [TOML](https://github.com/toml-lang/toml) file: ```toml # Get editor completions based on the config schema @@ -26,13 +28,15 @@ disabled = true ### Config File Location -You can change default configuration file location with `STARSHIP_CONFIG` environment variable: +You can change default configuration file location with `STARSHIP_CONFIG` +environment variable: ```sh export STARSHIP_CONFIG=~/example/non/default/path/starship.toml ``` -Equivalently in PowerShell (Windows) would be adding this line to your `$PROFILE`: +Equivalently in PowerShell (Windows) would be adding this line to +your `$PROFILE`: ```powershell $ENV:STARSHIP_CONFIG = "$HOME\example\non\default\path\starship.toml" @@ -46,14 +50,17 @@ os.setenv('STARSHIP_CONFIG', 'C:\\Users\\user\\example\\non\\default\\path\\star ### Logging -By default starship logs warnings and errors into a file named `~/.cache/starship/session_${STARSHIP_SESSION_KEY}.log`, where the session key is corresponding to an instance of your terminal. +By default starship logs warnings and errors into a file +named `~/.cache/starship/session_${STARSHIP_SESSION_KEY}.log`, where the session +key is corresponding to an instance of your terminal. This, however can be changed using the `STARSHIP_CACHE` environment variable: ```sh export STARSHIP_CACHE=~/.starship/cache ``` -Equivalently in PowerShell (Windows) would be adding this line to your `$PROFILE`: +Equivalently in PowerShell (Windows) would be adding this line to +your `$PROFILE`: ```powershell $ENV:STARSHIP_CACHE = "$HOME\AppData\Local\Temp" @@ -67,17 +74,25 @@ os.setenv('STARSHIP_CACHE', 'C:\\Users\\user\\AppData\\Local\\Temp') ### Terminology -**Module**: A component in the prompt giving information based on contextual information from your OS. For example, the "nodejs" module shows the version of Node.js that is currently installed on your computer, if your current directory is a Node.js project. +**Module**: A component in the prompt giving information based on contextual +information from your OS. For example, the "nodejs" module shows the version of +Node.js that is currently installed on your computer, if your current directory +is a Node.js project. -**Variable**: Smaller sub-components that contain information provided by the module. For example, the "version" variable in the "nodejs" module contains the current version of Node.js. +**Variable**: Smaller sub-components that contain information provided by the +module. For example, the "version" variable in the "nodejs" module contains the +current version of Node.js. -By convention, most modules have a prefix of default terminal color (e.g. `via` in "nodejs") and an empty space as a suffix. +By convention, most modules have a prefix of default terminal color (e.g. `via` +in "nodejs") and an empty space as a suffix. ### Strings -In TOML syntax, [text values](https://toml.io/en/v1.0.0#string) are declared with `'`, `"`, `'''`, or `"""`. +In TOML syntax, [text values](https://toml.io/en/v1.0.0#string) are declared +with `'`, `"`, `'''`, or `"""`. -The following Starship syntax symbols have special usage in a format string and must be escaped to display as that character: `$ [ ] ( )`. +The following Starship syntax symbols have special usage in a format string and +must be escaped to display as that character: `$ [ ] ( )`. | Symbol | Type | Notes | | ------ | ------------------------- | ------------------------------------------------------ | @@ -100,7 +115,8 @@ format = '\[\$\] ' ``` When using line breaks, multi-line declarations can be used. -For example, if you want to print a `$` symbol on a new line, the following values for `format` are equivalent: +For example, if you want to print a `$` symbol on a new line, the following +values for `format` are equivalent: ```toml # with literal string @@ -117,7 +133,8 @@ format = """ format = "\n\\$" ``` -In multiline basic strings, newlines can be used for formatting without being present in the value by escaping them. +In multiline basic strings, newlines can be used for formatting without being +present in the value by escaping them. ```toml format = """ @@ -133,7 +150,8 @@ line2 ### Format Strings Format strings are the format that a module prints all its variables with. -Most modules have an entry called `format` that configures the display format of the module. +Most modules have an entry called `format` that configures the display format of +the module. You can use texts, variables and text groups in a format string. #### Variable @@ -144,61 +162,85 @@ The name of a variable can only contain letters, numbers and `_`. For example: - `'$version'` is a format string with a variable named `version`. -- `'$git_branch$git_commit'` is a format string with two variables named `git_branch` and `git_commit`. +- `'$git_branch$git_commit'` is a format string with two variables + named `git_branch` and `git_commit`. - `'$git_branch $git_commit'` has the two variables separated with a space. #### Text Group A text group is made up of two different parts. -The first part, which is enclosed in a `[]`, is a [format string](#format-strings). +The first part, which is enclosed in a `[]`, is +a [format string](#format-strings). You can add texts, variables, or even nested text groups in it. -In the second part, which is enclosed in a `()`, is a [style string](#style-strings). This can be used to style the first part. +In the second part, which is enclosed in a `()`, is +a [style string](#style-strings). This can be used to style the first part. For example: - `'[on](red bold)'` will print a string `on` with bold text colored red. -- `'[⌘ $version](bold green)'` will print a symbol `⌘` followed by the content of variable `version`, with bold text colored green. -- `'[a [b](red) c](green)'` will print `a b c` with `b` red, and `a` and `c` green. +- `'[⌘ $version](bold green)'` will print a symbol `⌘` followed by the content + of variable `version`, with bold text colored green. +- `'[a [b](red) c](green)'` will print `a b c` with `b` red, and `a` and `c` + green. #### Style Strings -Most modules in starship allow you to configure their display styles. This is done with an entry (usually called `style`) which is a string specifying the configuration. Here are some examples of style strings along with what they do. For details on the full syntax, consult the [advanced config guide](../advanced-config/). +Most modules in starship allow you to configure their display styles. This is +done with an entry (usually called `style`) which is a string specifying the +configuration. Here are some examples of style strings along with what they do. +For details on the full syntax, consult +the [advanced config guide](../advanced-config/). - `'fg:green bg:blue'` sets green text on a blue background - `'bg:blue fg:bright-green'` sets bright green text on a blue background -- `'bold fg:27'` sets bold text with [ANSI color](https://i.stack.imgur.com/KTSQa.png) 27 +- `'bold fg:27'` sets bold text + with [ANSI color](https://i.stack.imgur.com/KTSQa.png) 27 - `'underline bg:#bf5700'` sets underlined text on a burnt orange background - `'bold italic fg:purple'` sets bold italic purple text - `''` explicitly disables all styling -Note that what styling looks like will be controlled by your terminal emulator. For example, some terminal emulators will brighten the colors instead of bolding text, and some color themes use the same values for the normal and bright colors. Also, to get italic text, your terminal must support italics. +Note that what styling looks like will be controlled by your terminal emulator. +For example, some terminal emulators will brighten the colors instead of bolding +text, and some color themes use the same values for the normal and bright +colors. Also, to get italic text, your terminal must support italics. #### Conditional Format Strings -A conditional format string wrapped in `(` and `)` will not render if all variables inside are empty. +A conditional format string wrapped in `(` and `)` will not render if all +variables inside are empty. For example: -- `'(@$region)'` will show nothing if the variable `region` is `None` or empty string, otherwise `@` followed by the value of region. -- `'(some text)'` will always show nothing since there are no variables wrapped in the braces. -- When `$combined` is a shortcut for `\[$a$b\]`, `'($combined)'` will show nothing only if `$a` and `$b` are both `None`. +- `'(@$region)'` will show nothing if the variable `region` is `None` or empty + string, otherwise `@` followed by the value of region. +- `'(some text)'` will always show nothing since there are no variables wrapped + in the braces. +- When `$combined` is a shortcut for `\[$a$b\]`, `'($combined)'` will show + nothing only if `$a` and `$b` are both `None`. This works the same as `'(\[$a$b\] )'`. ### Negative matching -Many modules have `detect_extensions`, `detect_files`, and `detect_folders` variables. These take -lists of strings to match or not match. "Negative" options, those which should not be matched, are -indicated with a leading '!' character. The presence of _any_ negative indicator in the directory +Many modules have `detect_extensions`, `detect_files`, and `detect_folders` +variables. These take +lists of strings to match or not match. "Negative" options, those which should +not be matched, are +indicated with a leading '!' character. The presence of _any_ negative indicator +in the directory will result in the module not being matched. -Extensions are matched against both the characters after the last dot in a filename, and the -characters after the first dot in a filename. For example, `foo.bar.tar.gz` will be matched -against `bar.tar.gz` and `gz` in the `detect_extensions` variable. Files whose name begins with a +Extensions are matched against both the characters after the last dot in a +filename, and the +characters after the first dot in a filename. For example, `foo.bar.tar.gz` will +be matched +against `bar.tar.gz` and `gz` in the `detect_extensions` variable. Files whose +name begins with a dot are not considered to have extensions at all. -To see how this works in practice, you could match TypeScript but not MPEG Transport Stream files thus: +To see how this works in practice, you could match TypeScript but not MPEG +Transport Stream files thus: ```toml detect_extensions = ['ts', '!video.ts', '!audio.ts'] @@ -258,7 +300,8 @@ mustard = '#af8700' ### Default Prompt Format -The default `format` is used to define the format of the prompt, if empty or no `format` is provided. The default is as shown: +The default `format` is used to define the format of the prompt, if empty or +no `format` is provided. The default is as shown: ```toml format = '$all' @@ -275,6 +318,7 @@ $directory\ $vcsh\ $fossil_branch\ $fossil_metrics\ +$jj_status\ $git_branch\ $git_commit\ $git_state\ @@ -364,11 +408,19 @@ format = '$all$directory$character' ## AWS -The `aws` module shows the current AWS region and profile and an expiration timer when using temporary credentials. -The output of the module uses the `AWS_REGION`, `AWS_DEFAULT_REGION`, and `AWS_PROFILE` env vars and the `~/.aws/config` and `~/.aws/credentials` files as required. +The `aws` module shows the current AWS region and profile and an expiration +timer when using temporary credentials. +The output of the module uses the `AWS_REGION`, `AWS_DEFAULT_REGION`, +and `AWS_PROFILE` env vars and the `~/.aws/config` and `~/.aws/credentials` +files as required. -The module will display a profile only if its credentials are present in `~/.aws/credentials` or if a `credential_process`, `sso_start_url`, or `sso_session` are defined in `~/.aws/config`. Alternatively, having any of the `AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY`, or `AWS_SESSION_TOKEN` env vars defined will also suffice. -If the option `force_display` is set to `true`, all available information will be displayed even if no credentials per the conditions above are detected. +The module will display a profile only if its credentials are present +in `~/.aws/credentials` or if a `credential_process`, `sso_start_url`, +or `sso_session` are defined in `~/.aws/config`. Alternatively, having any of +the `AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY`, or `AWS_SESSION_TOKEN` env +vars defined will also suffice. +If the option `force_display` is set to `true`, all available information will +be displayed even if no credentials per the conditions above are detected. When using [aws-vault](https://github.com/99designs/aws-vault) the profile is read from the `AWS_VAULT` env var and the credentials expiration date @@ -381,7 +433,8 @@ When using [AWSume](https://awsu.me) the profile is read from the `AWSUME_PROFILE` env var and the credentials expiration date is read from the `AWSUME_EXPIRATION` env var. -When using [saml2aws](https://github.com/Versent/saml2aws) the expiration information obtained from `~/.aws/credentials` +When using [saml2aws](https://github.com/Versent/saml2aws) the expiration +information obtained from `~/.aws/credentials` falls back to the `x_security_token_expires` key. When using [aws-sso-cli](https://github.com/synfinatic/aws-sso-cli) the profile @@ -459,7 +512,9 @@ Enterprise_Naming_Scheme-voidstars = 'void**' ## Azure -The `azure` module shows the current Azure Subscription. This is based on showing the name of the default subscription or the username, as defined in the `~/.azure/azureProfile.json` file. +The `azure` module shows the current Azure Subscription. This is based on +showing the name of the default subscription or the username, as defined in +the `~/.azure/azureProfile.json` file. ### Options @@ -508,7 +563,8 @@ very-long-subscription-name = 'vlsn' ## Battery -The `battery` module shows how charged the device's battery is and its current charging status. +The `battery` module shows how charged the device's battery is and its current +charging status. The module is only visible when the device's battery is below 10%. ### Options @@ -537,7 +593,9 @@ discharging_symbol = '💀 ' ### Battery Display -The `display` configuration option is used to define when the battery indicator should be shown (threshold), which symbol would be used (symbol), and what it would like (style). +The `display` configuration option is used to define when the battery indicator +should be shown (threshold), which symbol would be used (symbol), and what it +would like (style). If no `display` is provided. The default is as shown: ```toml @@ -546,7 +604,9 @@ threshold = 10 style = 'bold red' ``` -The default value for the `charging_symbol` and `discharging_symbol` option is respectively the value of `battery`'s `charging_symbol` and `discharging_symbol` option. +The default value for the `charging_symbol` and `discharging_symbol` option is +respectively the value of `battery`'s `charging_symbol` and `discharging_symbol` +option. #### Options @@ -576,10 +636,15 @@ discharging_symbol = '💦 ' ## Buf -The `buf` module shows the currently installed version of [Buf](https://buf.build). By default, the module is shown if all of the following conditions are met: +The `buf` module shows the currently installed version +of [Buf](https://buf.build). By default, the module is shown if all of the +following conditions are met: - The [`buf`](https://github.com/bufbuild/buf) CLI is installed. -- The current directory contains a [`buf.yaml`](https://docs.buf.build/configuration/v1/buf-yaml), [`buf.gen.yaml`](https://docs.buf.build/configuration/v1/buf-gen-yaml), or [`buf.work.yaml`](https://docs.buf.build/configuration/v1/buf-work-yaml) configuration file. +- The current directory contains + a [`buf.yaml`](https://docs.buf.build/configuration/v1/buf-yaml), [`buf.gen.yaml`](https://docs.buf.build/configuration/v1/buf-gen-yaml), + or [`buf.work.yaml`](https://docs.buf.build/configuration/v1/buf-work-yaml) + configuration file. ### Options @@ -615,7 +680,8 @@ symbol = '🦬 ' ## Bun -The `bun` module shows the currently installed version of the [bun](https://bun.sh) JavaScript runtime. +The `bun` module shows the currently installed version of +the [bun](https://bun.sh) JavaScript runtime. By default the module will be shown if any of the following conditions are met: - The current directory contains a `bun.lockb` file @@ -686,11 +752,15 @@ NB that `version` is not in the default format. ### Commands -The `commands` option accepts a list of commands to determine the compiler version and name. +The `commands` option accepts a list of commands to determine the compiler +version and name. -Each command is represented as a list of the executable name, followed by its arguments, usually something like `['mycc', '--version']`. Starship will try executing each command until it gets a result on STDOUT. +Each command is represented as a list of the executable name, followed by its +arguments, usually something like `['mycc', '--version']`. Starship will try +executing each command until it gets a result on STDOUT. -If a C compiler is not supported by this module, you can request it by [raising an issue on GitHub](https://github.com/starship/starship/). +If a C compiler is not supported by this module, you can request it +by [raising an issue on GitHub](https://github.com/starship/starship/). ### Example @@ -703,7 +773,8 @@ format = 'via [$name $version]($style)' ## Character -The `character` module shows a character (usually an arrow) beside where the text +The `character` module shows a character (usually an arrow) beside where the +text is entered in your terminal. The character will tell you whether the last command was successful or not. It @@ -719,7 +790,8 @@ look at [this example](#with-custom-error-shape). `vimcmd_symbol` is only supported in cmd, fish and zsh. `vimcmd_replace_one_symbol`, `vimcmd_replace_symbol`, and `vimcmd_visual_symbol` -are only supported in fish due to [upstream issues with mode detection in zsh](https://github.com/starship/starship/issues/625#issuecomment-732454148). +are only supported in fish due +to [upstream issues with mode detection in zsh](https://github.com/starship/starship/issues/625#issuecomment-732454148). ::: @@ -775,7 +847,8 @@ vimcmd_symbol = '[V](bold green) ' ## CMake -The `cmake` module shows the currently installed version of [CMake](https://cmake.org/). By default +The `cmake` module shows the currently installed version +of [CMake](https://cmake.org/). By default the module will be activated if any of the following conditions are met: - The current directory contains a `CMakeLists.txt` file @@ -843,7 +916,8 @@ the `min_time` config value, if it exists. ::: warning Do not hook the DEBUG trap in Bash -If you are running Starship in `bash`, do not hook the `DEBUG` trap after running +If you are running Starship in `bash`, do not hook the `DEBUG` trap after +running `eval $(starship init $0)`, or this module **will** break. ::: @@ -887,11 +961,13 @@ format = 'underwent [$duration](bold yellow)' ## Conda -The `conda` module shows the current [Conda](https://docs.conda.io/en/latest/) environment, if `$CONDA_DEFAULT_ENV` is set. +The `conda` module shows the current [Conda](https://docs.conda.io/en/latest/) +environment, if `$CONDA_DEFAULT_ENV` is set. ::: tip -This does not suppress conda's own prompt modifier, you may want to run `conda config --set changeps1 False`. +This does not suppress conda's own prompt modifier, you may want to +run `conda config --set changeps1 False`. ::: @@ -927,7 +1003,8 @@ format = '[$symbol$environment](dimmed green) ' ## Container -The `container` module displays a symbol and container name, if inside a container. +The `container` module displays a symbol and container name, if inside a +container. ### Options @@ -959,7 +1036,8 @@ format = '[$symbol \[$name\]]($style) ' ## Crystal -The `crystal` module shows the currently installed version of [Crystal](https://crystal-lang.org/). +The `crystal` module shows the currently installed version +of [Crystal](https://crystal-lang.org/). By default the module will be shown if any of the following conditions are met: - The current directory contains a `shard.yml` file @@ -999,9 +1077,12 @@ format = 'via [✨ $version](bold blue) ' ## Daml -The `daml` module shows the currently used [Daml](https://www.digitalasset.com/developers) -SDK version when you are in the root directory of your Daml project. The `sdk-version` in -the `daml.yaml` file will be used, unless it's overridden by the `DAML_SDK_VERSION` +The `daml` module shows the currently +used [Daml](https://www.digitalasset.com/developers) +SDK version when you are in the root directory of your Daml project. +The `sdk-version` in +the `daml.yaml` file will be used, unless it's overridden by +the `DAML_SDK_VERSION` environment variable. By default the module will be shown if any of the following conditions are met: @@ -1041,12 +1122,14 @@ format = 'via [D $version](bold bright-green) ' ## Dart -The `dart` module shows the currently installed version of [Dart](https://dart.dev/). +The `dart` module shows the currently installed version +of [Dart](https://dart.dev/). By default the module will be shown if any of the following conditions are met: - The current directory contains a file with `.dart` extension - The current directory contains a `.dart_tool` directory -- The current directory contains a `pubspec.yaml`, `pubspec.yml` or `pubspec.lock` file +- The current directory contains a `pubspec.yaml`, `pubspec.yml` + or `pubspec.lock` file ### Options @@ -1082,10 +1165,12 @@ format = 'via [🔰 $version](bold red) ' ## Deno -The `deno` module shows you your currently installed version of [Deno](https://deno.land/). +The `deno` module shows you your currently installed version +of [Deno](https://deno.land/). By default the module will be shown if any of the following conditions are met: -- The current directory contains a `deno.json`, `deno.jsonc`, `mod.ts`, `mod.js`, `deps.ts` or `deps.js` file +- The current directory contains + a `deno.json`, `deno.jsonc`, `mod.ts`, `mod.js`, `deps.ts` or `deps.js` file ### Options @@ -1123,7 +1208,8 @@ The `directory` module shows the path to your current directory, truncated to three parent folders. Your directory will also be truncated to the root of the git repo that you're currently in. -When using the `fish_style_pwd_dir_length` option, instead of hiding the path that is +When using the `fish_style_pwd_dir_length` option, instead of hiding the path +that is truncated, you will see a shortened name of each directory based on the number you enable for the option. @@ -1158,8 +1244,10 @@ it would have been `nixpkgs/pkgs`. | `fish_style_pwd_dir_length` | `0` | The number of characters to use when applying fish shell pwd path logic. | | `use_logical_path` | `true` | If `true` render the logical path sourced from the shell via `PWD` or `--logical-path`. If `false` instead render the physical filesystem path with symlinks resolved. | -`substitutions` allows you to define arbitrary replacements for literal strings that occur in the path, for example long network -prefixes or development directories (i.e. Java). Note that this will disable the fish style PWD. +`substitutions` allows you to define arbitrary replacements for literal strings +that occur in the path, for example long network +prefixes or development directories (i.e. Java). Note that this will disable the +fish style PWD. ```toml [directory.substitutions] @@ -1167,11 +1255,16 @@ prefixes or development directories (i.e. Java). Note that this will disable the 'src/com/long/java/path' = 'mypath' ``` -`fish_style_pwd_dir_length` interacts with the standard truncation options in a way that can be surprising at first: if it's non-zero, -the components of the path that would normally be truncated are instead displayed with that many characters. For example, the path -`/built/this/city/on/rock/and/roll`, which would normally be displayed as `rock/and/roll`, would be displayed as -`/b/t/c/o/rock/and/roll` with `fish_style_pwd_dir_length = 1`--the path components that would normally be removed are displayed with -a single character. For `fish_style_pwd_dir_length = 2`, it would be `/bu/th/ci/on/rock/and/roll`. +`fish_style_pwd_dir_length` interacts with the standard truncation options in a +way that can be surprising at first: if it's non-zero, +the components of the path that would normally be truncated are instead +displayed with that many characters. For example, the path +`/built/this/city/on/rock/and/roll`, which would normally be displayed +as `rock/and/roll`, would be displayed as +`/b/t/c/o/rock/and/roll` with `fish_style_pwd_dir_length = 1`--the path +components that would normally be removed are displayed with +a single character. For `fish_style_pwd_dir_length = 2`, it would +be `/bu/th/ci/on/rock/and/roll`. @@ -1211,7 +1304,9 @@ truncation_symbol = '…/' ## Direnv -The `direnv` module shows the status of the current rc file if one is present. The status includes the path to the rc file, whether it is loaded, and whether it has been allowed by `direnv`. +The `direnv` module shows the status of the current rc file if one is present. +The status includes the path to the rc file, whether it is loaded, and whether +it has been allowed by `direnv`. ### Options @@ -1293,8 +1388,10 @@ format = 'via [🐋 $context](blue bold)' ## Dotnet -The `dotnet` module shows the relevant version of the [.NET Core SDK](https://dotnet.microsoft.com/) for the current directory. If -the SDK has been pinned in the current directory, the pinned version is shown. Otherwise the module +The `dotnet` module shows the relevant version of +the [.NET Core SDK](https://dotnet.microsoft.com/) for the current directory. If +the SDK has been pinned in the current directory, the pinned version is shown. +Otherwise the module shows the latest installed version of the SDK. By default this module will only be shown in your prompt when one or more of @@ -1311,9 +1408,12 @@ the following files are present in the current directory: You'll also need the .NET Core SDK installed in order to use it correctly. -Internally, this module uses its own mechanism for version detection. Typically it is twice as fast -as running `dotnet --version`, but it may show an incorrect version if your .NET project has an -unusual directory layout. If accuracy is more important than speed, you can disable the mechanism by +Internally, this module uses its own mechanism for version detection. Typically +it is twice as fast +as running `dotnet --version`, but it may show an incorrect version if your .NET +project has an +unusual directory layout. If accuracy is more important than speed, you can +disable the mechanism by setting `heuristic = false` in the module options. The module will also show the Target Framework Moniker @@ -1358,7 +1458,8 @@ heuristic = false ## Elixir -The `elixir` module shows the currently installed version of [Elixir](https://elixir-lang.org/) and [Erlang/OTP](https://erlang.org/doc/). +The `elixir` module shows the currently installed version +of [Elixir](https://elixir-lang.org/) and [Erlang/OTP](https://erlang.org/doc/). By default the module will be shown if any of the following conditions are met: - The current directory contains a `mix.exs` file. @@ -1398,7 +1499,8 @@ symbol = '🔮 ' ## Elm -The `elm` module shows the currently installed version of [Elm](https://elm-lang.org/). +The `elm` module shows the currently installed version +of [Elm](https://elm-lang.org/). By default the module will be shown if any of the following conditions are met: - The current directory contains a `elm.json` file @@ -1441,24 +1543,30 @@ format = 'via [ $version](cyan bold) ' ## Environment Variable -The `env_var` module displays the current value of a selected environment variables. +The `env_var` module displays the current value of a selected environment +variables. The module will be shown only if any of the following conditions are met: - The `variable` configuration option matches an existing environment variable -- The `variable` configuration option is not defined, but the `default` configuration option is +- The `variable` configuration option is not defined, but the `default` + configuration option is ::: tip -The order in which env_var modules are shown can be individually set by including -`${env_var.foo}` in the top level `format` (as it includes a dot, you need to use `${...}`). -By default, the `env_var` module will simply show all env_var modules in the order they were defined. +The order in which env_var modules are shown can be individually set by +including +`${env_var.foo}` in the top level `format` (as it includes a dot, you need to +use `${...}`). +By default, the `env_var` module will simply show all env_var modules in the +order they were defined. ::: ::: tip Multiple environmental variables can be displayed by using a `.`. (see example) -If the `variable` configuration option is not set, the module will display value of variable under the name of text after the `.` character. +If the `variable` configuration option is not set, the module will display value +of variable under the name of text after the `.` character. Example: following configuration will display value of USER environment variable @@ -1516,7 +1624,8 @@ default = 'unknown user' ## Erlang -The `erlang` module shows the currently installed version of [Erlang/OTP](https://erlang.org/doc/). +The `erlang` module shows the currently installed version +of [Erlang/OTP](https://erlang.org/doc/). By default the module will be shown if any of the following conditions are met: - The current directory contains a `rebar.config` file. @@ -1556,7 +1665,8 @@ format = 'via [e $version](bold red) ' ## Fennel -The `fennel` module shows the currently installed version of [Fennel](https://fennel-lang.org). +The `fennel` module shows the currently installed version +of [Fennel](https://fennel-lang.org). By default the module will be shown if any of the following conditions are met: - The current directory contains a file with the `.fnl` extension @@ -1595,8 +1705,10 @@ symbol = '⫰ ' ## Fill -The `fill` module fills any extra space on the line with a symbol. If multiple `fill` modules are -present in a line they will split the space evenly between them. This is useful for aligning +The `fill` module fills any extra space on the line with a symbol. If +multiple `fill` modules are +present in a line they will split the space evenly between them. This is useful +for aligning other modules. ### Options @@ -1626,7 +1738,8 @@ AA -------------------------------------------- BB ----------------------------- ## Fossil Branch -The `fossil_branch` module shows the name of the active branch of the check-out in your current directory. +The `fossil_branch` module shows the name of the active branch of the check-out +in your current directory. ### Options @@ -1662,7 +1775,9 @@ truncation_symbol = '' ## Fossil Metrics -The `fossil_metrics` module will show the number of added and deleted lines in the check-out in your current directory. At least v2.14 (2021-01-20) of Fossil is required. +The `fossil_metrics` module will show the number of added and deleted lines in +the check-out in your current directory. At least v2.14 (2021-01-20) of Fossil +is required. ### Options @@ -1697,10 +1812,14 @@ format = '[+$added]($added_style)/[-$deleted]($deleted_style) ' ## Google Cloud (`gcloud`) -The `gcloud` module shows the current configuration for [`gcloud`](https://cloud.google.com/sdk/gcloud) CLI. -This is based on the `~/.config/gcloud/active_config` file and the `~/.config/gcloud/configurations/config_{CONFIG NAME}` file and the `CLOUDSDK_CONFIG` env var. +The `gcloud` module shows the current configuration +for [`gcloud`](https://cloud.google.com/sdk/gcloud) CLI. +This is based on the `~/.config/gcloud/active_config` file and +the `~/.config/gcloud/configurations/config_{CONFIG NAME}` file and +the `CLOUDSDK_CONFIG` env var. -When the module is enabled it will always be active, unless `detect_env_vars` has +When the module is enabled it will always be active, unless `detect_env_vars` +has been set in which case the module will only be active when one of the environment variables has been set. @@ -1776,7 +1895,8 @@ very-long-project-name = 'vlpn' ## Git Branch -The `git_branch` module shows the active branch of the repo in your current directory. +The `git_branch` module shows the active branch of the repo in your current +directory. ### Options @@ -1818,7 +1938,8 @@ ignore_branches = ['master', 'main'] ## Git Commit -The `git_commit` module shows the current commit hash and also the tag (if any) of the repo in your current directory. +The `git_commit` module shows the current commit hash and also the tag (if any) +of the repo in your current directory. ### Options @@ -1947,8 +2068,10 @@ current directory. ::: tip -The Git Status module is very slow in Windows directories (for example under `/mnt/c/`) when in a WSL environment. -You can disable the module or use the `windows_starship` option to use a Windows-native Starship executable to compute `git_status` for those paths. +The Git Status module is very slow in Windows directories (for example +under `/mnt/c/`) when in a WSL environment. +You can disable the module or use the `windows_starship` option to use a +Windows-native Starship executable to compute `git_status` for those paths. ::: @@ -2001,7 +2124,9 @@ The following variables can be used in `diverged`: | `ahead_count` | Number of commits ahead of the tracking branch | | `behind_count` | Number of commits behind the tracking branch | -The following variables can be used in `conflicted`, `ahead`, `behind`, `untracked`, `stashed`, `modified`, `staged`, `renamed` and `deleted`: +The following variables can be used +in `conflicted`, `ahead`, `behind`, `untracked`, `stashed`, `modified`, `staged`, `renamed` +and `deleted`: | Variable | Description | | -------- | ------------------------ | @@ -2048,7 +2173,8 @@ windows_starship = '/mnt/c/Users/username/scoop/apps/starship/current/starship.e ## Go -The `golang` module shows the currently installed version of [Go](https://golang.org/). +The `golang` module shows the currently installed version +of [Go](https://golang.org/). By default the module will be shown if any of the following conditions are met: - The current directory contains a `go.mod` file @@ -2106,7 +2232,9 @@ format = 'via [$symbol($version )($mod_version )]($style)' ## Guix-shell -The `guix_shell` module shows the [guix-shell](https://guix.gnu.org/manual/devel/en/html_node/Invoking-guix-shell.html) environment. +The `guix_shell` module shows +the [guix-shell](https://guix.gnu.org/manual/devel/en/html_node/Invoking-guix-shell.html) +environment. The module will be shown when inside a guix-shell environment. ### Options @@ -2139,15 +2267,18 @@ format = 'via [🐂](yellow bold) ' ## Gradle -The `gradle` module shows the version of the [Gradle Wrapper](https://docs.gradle.org/current/userguide/gradle_wrapper.html) +The `gradle` module shows the version of +the [Gradle Wrapper](https://docs.gradle.org/current/userguide/gradle_wrapper.html) currently used in the project directory. By default the module will be shown if any of the following conditions are met: -- The current directory contains a `gradle/wrapper/gradle-wrapper.properties` directory. +- The current directory contains a `gradle/wrapper/gradle-wrapper.properties` + directory. - The current directory contains a file ending with `.gradle` or `.gradle.kts`. -The `gradle` module is only able to read your Gradle Wrapper version from your config file, we don't execute your wrapper, because of the security concerns. +The `gradle` module is only able to read your Gradle Wrapper version from your +config file, we don't execute your wrapper, because of the security concerns. ### Options @@ -2175,7 +2306,8 @@ The `gradle` module is only able to read your Gradle Wrapper version from your c ## Haskell -The `haskell` module finds the current selected GHC version and/or the selected Stack snapshot. +The `haskell` module finds the current selected GHC version and/or the selected +Stack snapshot. By default the module will be shown if any of the following conditions are met: @@ -2208,10 +2340,13 @@ By default the module will be shown if any of the following conditions are met: ## Haxe -The `haxe` module shows the currently installed version of [Haxe](https://haxe.org/). +The `haxe` module shows the currently installed version +of [Haxe](https://haxe.org/). By default the module will be shown if any of the following conditions are met: -- The current directory contains a `project.xml`, `Project.xml`, `application.xml`, `haxelib.json`, `hxformat.json` or `.haxerc` file +- The current directory contains + a `project.xml`, `Project.xml`, `application.xml`, `haxelib.json`, `hxformat.json` + or `.haxerc` file - The current directory contains a `.haxelib` or a `haxe_libraries` directory - The current directory contains a file with the `.hx` or `.hxml` extension @@ -2249,7 +2384,8 @@ format = "via [⌘ $version](bold fg:202) " ## Helm -The `helm` module shows the currently installed version of [Helm](https://helm.sh/). +The `helm` module shows the currently installed version +of [Helm](https://helm.sh/). By default the module will be shown if any of the following conditions are met: - The current directory contains a `helmfile.yaml` file @@ -2340,11 +2476,15 @@ disabled = false ## Java -The `java` module shows the currently installed version of [Java](https://www.oracle.com/java/). +The `java` module shows the currently installed version +of [Java](https://www.oracle.com/java/). By default the module will be shown if any of the following conditions are met: -- The current directory contains a `pom.xml`, `build.gradle.kts`, `build.sbt`, `.java-version`, `deps.edn`, `project.clj`, `build.boot`, or `.sdkmanrc` file -- The current directory contains a file with the `.java`, `.class`, `.gradle`, `.jar`, `.clj`, or `.cljc` extension +- The current directory contains + a `pom.xml`, `build.gradle.kts`, `build.sbt`, `.java-version`, `deps.edn`, `project.clj`, `build.boot`, + or `.sdkmanrc` file +- The current directory contains a file with + the `.java`, `.class`, `.gradle`, `.jar`, `.clj`, or `.cljc` extension ### Options @@ -2378,6 +2518,78 @@ By default the module will be shown if any of the following conditions are met: symbol = '🌟 ' ``` +## JJ + +The `jj` module reflects the current status of your Jujutsu repository. It shows +different symbols and formats depending on the state of your work in progress, +including changes, commits, branch, and more. + +The `jj` module is only shown when you're in a directory that is part of a +Jujutsu repository. + +The default functionality includes displaying: + +- current change id +- current commit id + +::: warning + +This module requires the Jujutsu command line tool to be installed and +accessible in your system's PATH for it to function correctly. + +::: + +### Options + +| Option | Default | Description | +| ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------- | +| `symbol` | `'🍐 '` | The string used before displaying the repository status. | +| `no_description_symbol` | `' 📝'` | Is displayed when change description is empty. | +| `divergent_symbol` | `' 💥'` | Is displayed when commit is in divergent state. | +| `format` | `'\[$symbol[$change_id_prefix]($change_id_prefix_style)[$change_id_suffix]($change_id_suffix_style) [$commit_id_prefix]($commit_id_prefix_style)[$commit_id_suffix]($commit_id_suffix_style) on [$branch]($branch_style)$no_description_symbol$divergent_symbol\]'` | The format for rendering the module. `symbol`, `style`, and other variables can be included. | +| `disabled` | `false` | Disables the `jj` module. | +| `change_id_prefix_style` | `'purple'` | The style for uniq part of change id. | +| `change_id_suffix_style` | `'bright-black'` | The style for the rest of change id. | +| `commit_id_prefix_style` | `'blue'` | The style for unique part of commit hash. | +| `commit_id_suffix_style` | `'bright-black'` | The style for the rest of commit hash. | +| `truncation_length` | `8` | Truncates the commit and change id to `truncation_length` characters. | +| `branch_style` | `'purple'` | The style for the branch name. | + +### Variables + +``` +[🍐 rnyynlop 811ca1a4 on push-rnyynlopprno*] +``` + +| Variable | Example | Description | +| ------------------ | --------- | ----------------------------------------------------------------- | +| `symbol` | `🍐` | Mirrors the value of option `symbol`. | +| `change_id_prefix` | `r` | Unique part of the change id, styled by `change_id_prefix_style`. | +| `change_id_suffix` | `nyynlop` | The rest of the change id, styled by `change_id_suffix_style`. | +| `commit_id_prefix` | `811` | Unique part of the commit id, styled by `commit_id_prefix_style`. | +| `commit_id_suffix` | `ca1a4` | The rest of the commit id, styled by `commit_id_suffix_style`. | +| `branch` | `master` | The current branch name. | + +### Example + +```toml +# ~/.config/starship.toml + +[jj] +symbol = "🍐 " +style = "purple" +format = "\\[$symbol[$change_id_prefix]($change_id_prefix_style)[$change_id_suffix]($change_id_suffix_style) [$commit_id_prefix]($commit_id_prefix_style)[$commit_id_suffix]($commit_id_suffix_style) on [$branch]($branch_style)$no_description_symbol$divergent_symbol\\]" +disabled = false +change_id_prefix_style = "purple" +change_id_suffix_style = "bright-black" +commit_id_prefix_style = "blue" +commit_id_suffix_style = "bright-black" +truncation_length = 8 +no_description_symbol = "📝" +divergent_symbol = "💥" +branch_style = "purple" +``` + ## Jobs The `jobs` module shows the current number of jobs running. @@ -2405,7 +2617,8 @@ This module is not supported on tcsh and nu. The `threshold` option is deprecated, but if you want to use it, the module will show the number of jobs running if there is more than 1 job, or -more than the `threshold` config value, if it exists. If `threshold` is set to 0, +more than the `threshold` config value, if it exists. If `threshold` is set to +0, then the module will also show when there are 0 jobs running. ::: @@ -2422,7 +2635,8 @@ then the module will also show when there are 0 jobs running. | `style` | `'bold blue'` | The style for the module. | | `disabled` | `false` | Disables the `jobs` module. | -*: This option is deprecated, please use the `number_threshold` and `symbol_threshold` options instead. +*: This option is deprecated, please use the `number_threshold` +and `symbol_threshold` options instead. ### Variables @@ -2447,7 +2661,8 @@ symbol_threshold = 0 ## Julia -The `julia` module shows the currently installed version of [Julia](https://julialang.org/). +The `julia` module shows the currently installed version +of [Julia](https://julialang.org/). By default the module will be shown if any of the following conditions are met: - The current directory contains a `Project.toml` file @@ -2488,7 +2703,8 @@ symbol = '∴ ' ## Kotlin -The `kotlin` module shows the currently installed version of [Kotlin](https://kotlinlang.org/). +The `kotlin` module shows the currently installed version +of [Kotlin](https://kotlinlang.org/). By default the module will be shown if any of the following conditions are met: - The current directory contains a `.kt` or a `.kts` file @@ -2536,12 +2752,16 @@ kotlin_binary = 'kotlinc' ## Kubernetes -Displays the current [Kubernetes context](https://kubernetes.io/docs/concepts/configuration/organize-cluster-access-kubeconfig/#context) name and, if set, the namespace, user and cluster from the kubeconfig file. +Displays the +current [Kubernetes context](https://kubernetes.io/docs/concepts/configuration/organize-cluster-access-kubeconfig/#context) +name and, if set, the namespace, user and cluster from the kubeconfig file. The namespace needs to be set in the kubeconfig file, this can be done via `kubectl config set-context starship-context --namespace astronaut`. -Similarly, the user and cluster can be set with `kubectl config set-context starship-context --user starship-user` +Similarly, the user and cluster can be set +with `kubectl config set-context starship-context --user starship-user` and `kubectl config set-context starship-context --cluster starship-cluster`. -If the `$KUBECONFIG` env var is set the module will use that if not it will use the `~/.kube/config`. +If the `$KUBECONFIG` env var is set the module will use that if not it will use +the `~/.kube/config`. ::: tip @@ -2558,7 +2778,8 @@ case the module will only be active in directories that match those conditions. ::: warning -The `context_aliases` and `user_aliases` options are deprecated. Use `contexts` and the corresponding `context_alias` +The `context_aliases` and `user_aliases` options are deprecated. Use `contexts` +and the corresponding `context_alias` and `user_alias` options instead. ::: @@ -2576,9 +2797,11 @@ and `user_alias` options instead. | `contexts` | `[]` | Customized styles and symbols for specific contexts. | | `disabled` | `true` | Disables the `kubernetes` module. | -*: This option is deprecated, please add `contexts` with the corresponding `context_alias` and `user_alias` options instead. +*: This option is deprecated, please add `contexts` with the +corresponding `context_alias` and `user_alias` options instead. -To customize the style of the module for specific environments, use the following configuration as +To customize the style of the module for specific environments, use the +following configuration as part of the `contexts` list: | Variable | Description | @@ -2590,8 +2813,10 @@ part of the `contexts` list: | `style` | The style for the module when using this context. If not set, will use module's style. | | `symbol` | The symbol for the module when using this context. If not set, will use module's symbol. | -Note that all regular expression are anchored with `^$` and so must match the whole string. The `*_pattern` -regular expressions may contain capture groups, which can be referenced in the corresponding alias via `$name` and `$N` +Note that all regular expression are anchored with `^$` and so must +match the whole string. The `*_pattern` +regular expressions may contain capture groups, which can be referenced in the +corresponding alias via `$name` and `$N` (see example below and the [rust Regex::replace() documentation](https://docs.rs/regex/latest/regex/struct.Regex.html#method.replace)). @@ -2633,7 +2858,8 @@ detect_files = ['k8s'] #### Kubernetes Context specific config -The `contexts` configuration option is used to customise what the current Kubernetes context name looks +The `contexts` configuration option is used to customise what the current +Kubernetes context name looks like (style and symbol) if the name matches the defined regular expression. ```toml @@ -2718,7 +2944,8 @@ disabled = false ## Lua -The `lua` module shows the currently installed version of [Lua](http://www.lua.org/). +The `lua` module shows the currently installed version +of [Lua](http://www.lua.org/). By default the module will be shown if any of the following conditions are met: - The current directory contains a `.lua-version` file @@ -2793,7 +3020,8 @@ To enable it, set `disabled` to `false` in your configuration file. | style\* | | Mirrors the value of option `style` | *: This variable can only be used as a part of a style string -*\*: The SWAP file information is only displayed if detected on the current system +*\*: The SWAP file information is only displayed if detected on the current +system ### Example @@ -2848,7 +3076,8 @@ style = 'bold dimmed green' ## Mercurial Branch -The `hg_branch` module shows the active branch and topic of the repo in your current directory. +The `hg_branch` module shows the active branch and topic of the repo in your +current directory. ### Options @@ -2885,7 +3114,8 @@ truncation_symbol = '' ## Nim -The `nim` module shows the currently installed version of [Nim](https://nim-lang.org/). +The `nim` module shows the currently installed version +of [Nim](https://nim-lang.org/). By default the module will be shown if any of the following conditions are met: - The current directory contains a `nim.cfg` file @@ -2928,7 +3158,9 @@ symbol = '🎣 ' ## Nix-shell -The `nix_shell` module shows the [nix-shell](https://nixos.org/guides/nix-pills/developing-with-nix-shell.html) environment. +The `nix_shell` module shows +the [nix-shell](https://nixos.org/guides/nix-pills/developing-with-nix-shell.html) +environment. The module will be shown when inside a nix-shell environment. ### Options @@ -2970,15 +3202,18 @@ format = 'via [☃️ $state( \($name\))](bold blue) ' ## Node.js -The `nodejs` module shows the currently installed version of [Node.js](https://nodejs.org/). +The `nodejs` module shows the currently installed version +of [Node.js](https://nodejs.org/). By default the module will be shown if any of the following conditions are met: - The current directory contains a `package.json` file - The current directory contains a `.node-version` file - The current directory contains a `.nvmrc` file - The current directory contains a `node_modules` directory -- The current directory contains a file with the `.js`, `.mjs` or `.cjs` extension -- The current directory contains a file with the `.ts`, `.mts` or `.cts` extension +- The current directory contains a file with the `.js`, `.mjs` or `.cjs` + extension +- The current directory contains a file with the `.ts`, `.mts` or `.cts` + extension ### Options @@ -3016,15 +3251,18 @@ format = 'via [🤖 $version](bold green) ' ## OCaml -The `ocaml` module shows the currently installed version of [OCaml](https://ocaml.org/). +The `ocaml` module shows the currently installed version +of [OCaml](https://ocaml.org/). By default the module will be shown if any of the following conditions are met: -- The current directory contains a file with `.opam` extension or `_opam` directory +- The current directory contains a file with `.opam` extension or `_opam` + directory - The current directory contains a `esy.lock` directory - The current directory contains a `dune` or `dune-project` file - The current directory contains a `jbuild` or `jbuild-ignore` file - The current directory contains a `.merlin` file -- The current directory contains a file with `.ml`, `.mli`, `.re` or `.rei` extension +- The current directory contains a file with `.ml`, `.mli`, `.re` or `.rei` + extension ### Options @@ -3065,7 +3303,8 @@ format = 'via [🐪 $version]($style) ' ## Open Policy Agent The `opa` module shows the currently installed version of the OPA tool. -By default the module will be shown if the current directory contains a `.rego` file. +By default the module will be shown if the current directory contains a `.rego` +file. ### Options @@ -3103,7 +3342,8 @@ format = 'via [⛑️ $version](bold red) ' The `openstack` module shows the current OpenStack cloud and project. The module only active when the `OS_CLOUD` env var is set, in which case it will read -`clouds.yaml` file from any of the [default locations](https://docs.openstack.org/python-openstackclient/latest/configuration/index.html#configuration-files). +`clouds.yaml` file from any of +the [default locations](https://docs.openstack.org/python-openstackclient/latest/configuration/index.html#configuration-files). to fetch the current project in use. ### Options @@ -3140,11 +3380,13 @@ symbol = '☁️ ' ## OS The `os` module shows the current operating system. -OS information is detected via the [os_info](https://lib.rs/crates/os_info) crate. +OS information is detected via the [os_info](https://lib.rs/crates/os_info) +crate. ::: warning -The [os_info](https://lib.rs/crates/os_info) crate used by this module is known to be inaccurate on some systems. +The [os_info](https://lib.rs/crates/os_info) crate used by this module is known +to be inaccurate on some systems. ::: @@ -3164,10 +3406,13 @@ To enable it, set `disabled` to `false` in your configuration file. | `disabled` | `true` | Disables the `os` module. | | `symbols` | | A table that maps each operating system to its symbol. | -`symbols` allows you to define arbitrary symbols to display for each operating system type. -Operating system types not defined by your configuration use the default symbols table below. +`symbols` allows you to define arbitrary symbols to display for each operating +system type. +Operating system types not defined by your configuration use the default symbols +table below. All operating systems currently supported by the module are listed below. -If you would like an operating system to be added, feel free to open a [feature request](https://github.com/starship/starship/issues/new/choose). +If you would like an operating system to be added, feel free to open +a [feature request](https://github.com/starship/starship/issues/new/choose). ```toml # This is the default symbols table. @@ -3247,29 +3492,51 @@ Arch = "Arch is the best! " ## Package Version The `package` module is shown when the current directory is the repository for a -package, and shows its current version. The module currently supports `npm`, `nimble`, `cargo`, -`poetry`, `python`, `composer`, `gradle`, `julia`, `mix`, `helm`, `shards`, `daml` and `dart` packages. +package, and shows its current version. The module currently +supports `npm`, `nimble`, `cargo`, +`poetry`, `python`, `composer`, `gradle`, `julia`, `mix`, `helm`, `shards`, `daml` +and `dart` packages. -- [**npm**](https://docs.npmjs.com/cli/commands/npm) – The `npm` package version is extracted from the `package.json` present +- [**npm**](https://docs.npmjs.com/cli/commands/npm) – The `npm` package version + is extracted from the `package.json` present in the current directory -- [**Cargo**](https://doc.rust-lang.org/cargo/) – The `cargo` package version is extracted from the `Cargo.toml` present in the current directory -- [**Nimble**](https://github.com/nim-lang/nimble) - The `nimble` package version is extracted from the `*.nimble` file present in the current directory with the `nimble dump` command -- [**Poetry**](https://python-poetry.org/) – The `poetry` package version is extracted from the `pyproject.toml` present +- [**Cargo**](https://doc.rust-lang.org/cargo/) – The `cargo` package version is + extracted from the `Cargo.toml` present in the current directory +- [**Nimble**](https://github.com/nim-lang/nimble) - The `nimble` package + version is extracted from the `*.nimble` file present in the current directory + with the `nimble dump` command +- [**Poetry**](https://python-poetry.org/) – The `poetry` package version is + extracted from the `pyproject.toml` present in the current directory -- [**Python**](https://www.python.org) - The `python` package version is extracted from a [PEP 621](https://peps.python.org/pep-0621/) compliant `pyproject.toml` or a `setup.cfg` present in the current directory -- [**Composer**](https://getcomposer.org/) – The `composer` package version is extracted from the `composer.json` present +- [**Python**](https://www.python.org) - The `python` package version is + extracted from a [PEP 621](https://peps.python.org/pep-0621/) + compliant `pyproject.toml` or a `setup.cfg` present in the current directory +- [**Composer**](https://getcomposer.org/) – The `composer` package version is + extracted from the `composer.json` present in the current directory -- [**Gradle**](https://gradle.org/) – The `gradle` package version is extracted from the `build.gradle` present in the current directory -- [**Julia**](https://docs.julialang.org/en/v1/stdlib/Pkg/) - The package version is extracted from the `Project.toml` present in the current directory -- [**Mix**](https://hexdocs.pm/mix/) - The `mix` package version is extracted from the `mix.exs` present in the current directory -- [**Helm**](https://helm.sh/docs/helm/helm_package/) - The `helm` chart version is extracted from the `Chart.yaml` present in the current directory -- [**Maven**](https://maven.apache.org/) - The `maven` package version is extracted from the `pom.xml` present in the current directory -- [**Meson**](https://mesonbuild.com/) - The `meson` package version is extracted from the `meson.build` present in the current directory -- [**Shards**](https://crystal-lang.org/reference/the_shards_command/index.html) - The `shards` package version is extracted from the `shard.yml` present in the current directory -- [**V**](https://vlang.io) - The `vlang` package version is extracted from the `v.mod` present in the current directory -- [**SBT**](https://scala-sbt.org) - The `sbt` package version is extracted from the `build.sbt` present in the current directory -- [**Daml**](https://www.digitalasset.com/developers) - The `daml` package version is extracted from the `daml.yaml` present in the current directory -- [**Dart**](https://pub.dev/) - The `dart` package version is extracted from the `pubspec.yaml` present in the current directory +- [**Gradle**](https://gradle.org/) – The `gradle` package version is extracted + from the `build.gradle` present in the current directory +- [**Julia**](https://docs.julialang.org/en/v1/stdlib/Pkg/) - The package + version is extracted from the `Project.toml` present in the current directory +- [**Mix**](https://hexdocs.pm/mix/) - The `mix` package version is extracted + from the `mix.exs` present in the current directory +- [**Helm**](https://helm.sh/docs/helm/helm_package/) - The `helm` chart version + is extracted from the `Chart.yaml` present in the current directory +- [**Maven**](https://maven.apache.org/) - The `maven` package version is + extracted from the `pom.xml` present in the current directory +- [**Meson**](https://mesonbuild.com/) - The `meson` package version is + extracted from the `meson.build` present in the current directory +- [**Shards **](https://crystal-lang.org/reference/the_shards_command/index.html) - + The `shards` package version is extracted from the `shard.yml` present in the + current directory +- [**V**](https://vlang.io) - The `vlang` package version is extracted from + the `v.mod` present in the current directory +- [**SBT**](https://scala-sbt.org) - The `sbt` package version is extracted from + the `build.sbt` present in the current directory +- [**Daml**](https://www.digitalasset.com/developers) - The `daml` package + version is extracted from the `daml.yaml` present in the current directory +- [**Dart**](https://pub.dev/) - The `dart` package version is extracted from + the `pubspec.yaml` present in the current directory > ⚠️ The version being shown is that of the package whose source code is in your > current directory, not your package manager. @@ -3306,7 +3573,8 @@ format = 'via [🎁 $version](208 bold) ' ## Perl -The `perl` module shows the currently installed version of [Perl](https://www.perl.org/). +The `perl` module shows the currently installed version +of [Perl](https://www.perl.org/). By default the module will be shown if any of the following conditions are met: - The current directory contains a `Makefile.PL` or `Build.PL` file @@ -3347,7 +3615,8 @@ format = 'via [🦪 $version]($style) ' ## PHP -The `php` module shows the currently installed version of [PHP](https://www.php.net/). +The `php` module shows the currently installed version +of [PHP](https://www.php.net/). By default the module will be shown if any of the following conditions are met: - The current directory contains a `composer.json` file @@ -3388,7 +3657,8 @@ format = 'via [🔹 $version](147 bold) ' ## Pijul Channel -The `pijul_channel` module shows the active channel of the repo in your current directory. +The `pijul_channel` module shows the active channel of the repo in your current +directory. ### Options @@ -3403,19 +3673,24 @@ The `pijul_channel` module shows the active channel of the repo in your current ## Pulumi -The `pulumi` module shows the current username, selected [Pulumi Stack](https://www.pulumi.com/docs/intro/concepts/stack/), and version. +The `pulumi` module shows the current username, +selected [Pulumi Stack](https://www.pulumi.com/docs/intro/concepts/stack/), and +version. ::: tip -By default the Pulumi version is not shown, since it takes an order of magnitude longer to load then most plugins (~70ms). -If you still want to enable it, [follow the example shown below](#with-pulumi-version). +By default the Pulumi version is not shown, since it takes an order of magnitude +longer to load then most plugins (~70ms). +If you still want to enable +it, [follow the example shown below](#with-pulumi-version). ::: By default the module will be shown if any of the following conditions are met: - The current directory contains either `Pulumi.yaml` or `Pulumi.yml` -- A parent directory contains either `Pulumi.yaml` or `Pulumi.yml` unless `search_upwards` is set to `false` +- A parent directory contains either `Pulumi.yaml` or `Pulumi.yml` + unless `search_upwards` is set to `false` ### Options @@ -3462,7 +3737,8 @@ format = '[$symbol$stack]($style) ' ## PureScript -The `purescript` module shows the currently installed version of [PureScript](https://www.purescript.org/) version. +The `purescript` module shows the currently installed version +of [PureScript](https://www.purescript.org/) version. By default the module will be shown if any of the following conditions are met: - The current directory contains a `spago.dhall` file @@ -3502,8 +3778,10 @@ format = 'via [$symbol$version](bold white)' ## Python -The `python` module shows the currently installed version of [Python](https://www.python.org/) and the -current [Python virtual environment](https://docs.python.org/tutorial/venv.html) if one is activated. +The `python` module shows the currently installed version +of [Python](https://www.python.org/) and the +current [Python virtual environment](https://docs.python.org/tutorial/venv.html) +if one is activated. If `pyenv_version_name` is set to `true`, it will display the pyenv version name. Otherwise, it will display the version number from `python --version`. @@ -3603,7 +3881,8 @@ python_binary = ['./venv/bin/python', 'python', 'python3', 'python2'] ## R -The `rlang` module shows the currently installed version of [R](https://www.r-project.org/). The module will be shown if +The `rlang` module shows the currently installed version +of [R](https://www.r-project.org/). The module will be shown if any of the following conditions are met: - The current directory contains a file with the `.R` extension. @@ -3646,7 +3925,8 @@ format = 'with [📐 $version](blue bold) ' ## Raku -The `raku` module shows the currently installed version of [Raku](https://www.raku.org/). +The `raku` module shows the currently installed version +of [Raku](https://www.raku.org/). By default the module will be shown if any of the following conditions are met: - The current directory contains a `META6.json` file @@ -3685,7 +3965,8 @@ format = 'via [🦪 $version]($style) ' ## Red -By default the `red` module shows the currently installed version of [Red](https://www.red-lang.org/). +By default the `red` module shows the currently installed version +of [Red](https://www.red-lang.org/). The module will be shown if any of the following conditions are met: - The current directory contains a file with `.red` or `.reds` extension @@ -3724,7 +4005,8 @@ symbol = '🔴 ' ## Ruby -By default the `ruby` module shows the currently installed version of [Ruby](https://www.ruby-lang.org/). +By default the `ruby` module shows the currently installed version +of [Ruby](https://www.ruby-lang.org/). The module will be shown if any of the following conditions are met: - The current directory contains a `Gemfile` file @@ -3769,7 +4051,8 @@ symbol = '🔺 ' ## Rust -By default the `rust` module shows the currently installed version of [Rust](https://www.rust-lang.org/). +By default the `rust` module shows the currently installed version +of [Rust](https://www.rust-lang.org/). The module will be shown if any of the following conditions are met: - The current directory contains a `Cargo.toml` file @@ -3811,7 +4094,8 @@ format = 'via [⚙️ $version](red bold)' ## Scala -The `scala` module shows the currently installed version of [Scala](https://www.scala-lang.org/). +The `scala` module shows the currently installed version +of [Scala](https://www.scala-lang.org/). By default the module will be shown if any of the following conditions are met: - The current directory contains a `build.sbt`, `.scalaenv` or `.sbtenv` file @@ -3905,7 +4189,9 @@ disabled = false ## SHLVL -The `shlvl` module shows the current [`SHLVL`](https://tldp.org/LDP/abs/html/internalvariables.html#SHLVLREF) ('shell level') environment variable, if it is +The `shlvl` module shows the +current [`SHLVL`](https://tldp.org/LDP/abs/html/internalvariables.html#SHLVLREF) (' +shell level') environment variable, if it is set to a number and meets or exceeds the specified threshold. ### Options @@ -3959,7 +4245,9 @@ threshold = 0 ## Singularity -The `singularity` module shows the current [Singularity](https://sylabs.io/singularity/) image, if inside a container +The `singularity` module shows the +current [Singularity](https://sylabs.io/singularity/) image, if inside a +container and `$SINGULARITY_NAME` is set. ### Options @@ -3992,7 +4280,8 @@ format = '[📦 \[$env\]]($style) ' ## Solidity -The `solidity` module shows the currently installed version of [Solidity](https://soliditylang.org/) +The `solidity` module shows the currently installed version +of [Solidity](https://soliditylang.org/) The module will be shown if any of the following conditions are met: - The current directory contains a file with the `.sol` extension @@ -4031,7 +4320,9 @@ format = "via [S $version](blue bold)" ## Spack -The `spack` module shows the current [Spack](https://spack.readthedocs.io/en/latest/) environment, if `$SPACK_ENV` is set. +The `spack` module shows the +current [Spack](https://spack.readthedocs.io/en/latest/) environment, +if `$SPACK_ENV` is set. ### Options @@ -4065,7 +4356,8 @@ format = '[$symbol$environment](dimmed blue) ' ## Status The `status` module displays the exit code of the previous command. -If $success_symbol is empty (default), the module will be shown only if the exit code is not `0`. +If $success_symbol is empty (default), the module will be shown only if the exit +code is not `0`. The status code will cast to a signed 32-bit integer. ::: tip @@ -4179,7 +4471,8 @@ disabled = false ## Swift -By default the `swift` module shows the currently installed version of [Swift](https://swift.org/). +By default the `swift` module shows the currently installed version +of [Swift](https://swift.org/). The module will be shown if any of the following conditions are met: - The current directory contains a `Package.swift` file @@ -4219,19 +4512,24 @@ format = 'via [🏎 $version](red bold)' ## Terraform -The `terraform` module shows the currently selected [Terraform workspace](https://www.terraform.io/docs/language/state/workspaces.html) and version. +The `terraform` module shows the currently +selected [Terraform workspace](https://www.terraform.io/docs/language/state/workspaces.html) +and version. ::: tip -By default the Terraform version is not shown, since this is slow for current versions of Terraform when a lot of plugins are in use. -If you still want to enable it, [follow the example shown below](#with-terraform-version). +By default the Terraform version is not shown, since this is slow for current +versions of Terraform when a lot of plugins are in use. +If you still want to enable +it, [follow the example shown below](#with-terraform-version). ::: By default the module will be shown if any of the following conditions are met: - The current directory contains a `.terraform` folder -- Current directory contains a file with the `.tf`, `.tfplan` or `.tfstate` extensions +- Current directory contains a file with the `.tf`, `.tfplan` or `.tfstate` + extensions ### Options @@ -4280,7 +4578,11 @@ format = '[🏎💨 $workspace]($style) ' ## Time The `time` module shows the current **local** time. -The `format` configuration value is used by the [`chrono`](https://crates.io/crates/chrono) crate to control how the time is displayed. Take a look [at the chrono strftime docs](https://docs.rs/chrono/0.4.7/chrono/format/strftime/index.html) to see what options are available. +The `format` configuration value is used by +the [`chrono`](https://crates.io/crates/chrono) crate to control how the time is +displayed. Take a +look [at the chrono strftime docs](https://docs.rs/chrono/0.4.7/chrono/format/strftime/index.html) +to see what options are available. ::: tip @@ -4301,7 +4603,8 @@ To enable it, set `disabled` to `false` in your configuration file. | `disabled` | `true` | Disables the `time` module. | | `time_range` | `'-'` | Sets the time range during which the module will be shown. Times must be specified in 24-hours format | -If `use_12hr` is `true`, then `time_format` defaults to `'%r'`. Otherwise, it defaults to `'%T'`. +If `use_12hr` is `true`, then `time_format` defaults to `'%r'`. Otherwise, it +defaults to `'%T'`. Manually setting `time_format` will override the `use_12hr` setting. ### Variables @@ -4328,7 +4631,8 @@ time_range = '10:00:00-14:00:00' ## Typst -The `typst` module shows the current installed version of Typst used in a project. +The `typst` module shows the current installed version of Typst used in a +project. By default, the module will be shown if any of the following conditions are met: @@ -4409,7 +4713,8 @@ show_always = true ## Vagrant -The `vagrant` module shows the currently installed version of [Vagrant](https://www.vagrantup.com/). +The `vagrant` module shows the currently installed version +of [Vagrant](https://www.vagrantup.com/). By default the module will be shown if any of the following conditions are met: - The current directory contains a `Vagrantfile` file @@ -4448,11 +4753,13 @@ format = 'via [⍱ $version](bold white) ' ## V -The `vlang` module shows you your currently installed version of [V](https://vlang.io/). +The `vlang` module shows you your currently installed version +of [V](https://vlang.io/). By default the module will be shown if any of the following conditions are met: - The current directory contains a file with `.v` extension -- The current directory contains a `v.mod`, `vpkg.json` or `.vpkg-lock.json` file +- The current directory contains a `v.mod`, `vpkg.json` or `.vpkg-lock.json` + file ### Options @@ -4485,7 +4792,8 @@ format = 'via [V $version](blue bold) ' ## VCSH -The `vcsh` module displays the current active [VCSH](https://github.com/RichiH/vcsh) repository. +The `vcsh` module displays the current +active [VCSH](https://github.com/RichiH/vcsh) repository. The module will be shown only if a repository is currently in use. ### Options @@ -4518,7 +4826,8 @@ format = '[🆅 $repo](bold blue) ' ## Zig -By default the `zig` module shows the currently installed version of [Zig](https://ziglang.org/). +By default the `zig` module shows the currently installed version +of [Zig](https://ziglang.org/). The module will be shown if any of the following conditions are met: - The current directory contains a `.zig` file @@ -4563,9 +4872,11 @@ These modules will be shown if any of the following conditions are met: - The current directory contains a file whose name is in `detect_files` - The current directory contains a directory whose name is in `detect_folders` -- The current directory contains a file whose extension is in `detect_extensions` +- The current directory contains a file whose extension is + in `detect_extensions` - The `when` command returns 0 -- The current Operating System (std::env::consts::OS) matches with `os` field if defined. +- The current Operating System (std::env::consts::OS) matches with `os` field if + defined. ::: tip @@ -4576,23 +4887,30 @@ Multiple custom modules can be defined by using a `.`. ::: tip The order in which custom modules are shown can be individually set by including -`${custom.foo}` in the top level `format` (as it includes a dot, you need to use `${...}`). -By default, the `custom` module will simply show all custom modules in the order they were defined. +`${custom.foo}` in the top level `format` (as it includes a dot, you need to +use `${...}`). +By default, the `custom` module will simply show all custom modules in the order +they were defined. ::: ::: tip -[Issue #1252](https://github.com/starship/starship/discussions/1252) contains examples of custom modules. -If you have an interesting example not covered there, feel free to share it there! +[Issue #1252](https://github.com/starship/starship/discussions/1252) contains +examples of custom modules. +If you have an interesting example not covered there, feel free to share it +there! ::: ::: warning Command output is printed unescaped to the prompt -Whatever output the command generates is printed unmodified in the prompt. This means if the output -contains special sequences that are interpreted by your shell they will be expanded when displayed. -These special sequences are shell specific, e.g. you can write a command module that writes bash sequences, +Whatever output the command generates is printed unmodified in the prompt. This +means if the output +contains special sequences that are interpreted by your shell they will be +expanded when displayed. +These special sequences are shell specific, e.g. you can write a command module +that writes bash sequences, e.g. `\h`, but this module will not work in a fish or zsh shell. Format strings can also contain shell specific prompt sequences, e.g. @@ -4638,16 +4956,22 @@ Format strings can also contain shell specific prompt sequences, e.g. - The first string is the path to the shell to use to execute the command. - Other following arguments are passed to the shell. -If unset, it will fallback to STARSHIP_SHELL and then to 'sh' on Linux, and 'cmd /C' on Windows. +If unset, it will fallback to STARSHIP_SHELL and then to 'sh' on Linux, and 'cmd +/C' on Windows. The `command` will be passed in on stdin. -If `shell` is not given or only contains one element and Starship detects PowerShell will be used, +If `shell` is not given or only contains one element and Starship detects +PowerShell will be used, the following arguments will automatically be added: `-NoProfile -Command -`. -If `shell` is not given or only contains one element and Starship detects Cmd will be used, -the following argument will automatically be added: `/C` and `stdin` will be set to `false`. -If `shell` is not given or only contains one element and Starship detects Nushell will be used, -the following arguments will automatically be added: `-c` and `stdin` will be set to `false`. +If `shell` is not given or only contains one element and Starship detects Cmd +will be used, +the following argument will automatically be added: `/C` and `stdin` will be set +to `false`. +If `shell` is not given or only contains one element and Starship detects +Nushell will be used, +the following arguments will automatically be added: `-c` and `stdin` will be +set to `false`. This behavior can be avoided by explicitly passing arguments to the shell, e.g. ```toml diff --git a/src/configs/jj.rs b/src/configs/jj.rs new file mode 100644 index 0000000000000..c346e1c162984 --- /dev/null +++ b/src/configs/jj.rs @@ -0,0 +1,41 @@ +use serde::{Deserialize, Serialize}; + +#[derive(Clone, Deserialize, Serialize, Debug)] +#[cfg_attr( + feature = "config-schema", + derive(schemars::JsonSchema), + schemars(deny_unknown_fields) +)] +#[serde(default)] +pub struct JJConfig<'a> { + pub symbol: &'a str, + pub format: &'a str, + pub disabled: bool, + pub change_id_prefix_style: &'a str, + pub change_id_suffix_style: &'a str, + pub commit_id_prefix_style: &'a str, + pub commit_id_suffix_style: &'a str, + pub truncation_length: u8, + pub no_description_symbol: &'a str, + pub divergent_symbol: &'a str, + pub branch_style: &'a str, +} + +impl<'a> Default for JJConfig<'a> { + fn default() -> Self { + JJConfig { + symbol: "🍐 ", + // format: "[[$change_id_prefix]($change_id_prefix_style)[$change_id_suffix]($change_id_suffix_style) [$commit_id_prefix]($commit_id_prefix_style)[$commit_id_suffix]($commit_id_suffix_style)$branch]($style)", + format: "\\[$symbol[$change_id_prefix]($change_id_prefix_style)[$change_id_suffix]($change_id_suffix_style) [$commit_id_prefix]($commit_id_prefix_style)[$commit_id_suffix]($commit_id_suffix_style) on [$branch]($branch_style)$no_description_symbol$divergent_symbol\\]", + disabled: false, + change_id_prefix_style: "purple", // magenta + change_id_suffix_style: "bright-black", + commit_id_prefix_style: "blue", + commit_id_suffix_style: "bright-black", + truncation_length: 8, + no_description_symbol: " 📝", + divergent_symbol: " 💥", + branch_style: "purple", + } + } +} diff --git a/src/configs/mod.rs b/src/configs/mod.rs index c2cf0a8d93354..152ac8d26f886 100644 --- a/src/configs/mod.rs +++ b/src/configs/mod.rs @@ -45,6 +45,7 @@ pub mod helm; pub mod hg_branch; pub mod hostname; pub mod java; +pub mod jj; pub mod jobs; pub mod julia; pub mod kotlin; @@ -196,6 +197,8 @@ pub struct FullConfig<'a> { #[serde(borrow)] java: java::JavaConfig<'a>, #[serde(borrow)] + jj_status: jj::JJConfig<'a>, + #[serde(borrow)] jobs: jobs::JobsConfig<'a>, #[serde(borrow)] julia: julia::JuliaConfig<'a>, diff --git a/src/configs/starship_root.rs b/src/configs/starship_root.rs index 86fe7e7547db6..106a83ba07c16 100644 --- a/src/configs/starship_root.rs +++ b/src/configs/starship_root.rs @@ -41,6 +41,7 @@ pub const PROMPT_ORDER: &[&str] = &[ "vcsh", "fossil_branch", "fossil_metrics", + "jj_status", "git_branch", "git_commit", "git_state", diff --git a/src/formatter/model.rs b/src/formatter/model.rs index 2db30775065b7..17e5912ce5b94 100644 --- a/src/formatter/model.rs +++ b/src/formatter/model.rs @@ -11,13 +11,13 @@ pub trait StyleVariableHolder { fn get_style_variables(&self) -> BTreeSet; } -#[derive(Clone)] +#[derive(Clone, Debug)] pub struct TextGroup<'a> { pub format: Vec>, pub style: Vec>, } -#[derive(Clone)] +#[derive(Clone, Debug)] pub enum FormatElement<'a> { Text(Cow<'a, str>), Variable(Cow<'a, str>), @@ -25,7 +25,7 @@ pub enum FormatElement<'a> { Conditional(Vec>), } -#[derive(Clone)] +#[derive(Clone, Debug)] pub enum StyleElement<'a> { Text(Cow<'a, str>), Variable(Cow<'a, str>), diff --git a/src/module.rs b/src/module.rs index 0dcc0aad4d3ad..791a4386aa418 100644 --- a/src/module.rs +++ b/src/module.rs @@ -52,6 +52,7 @@ pub const ALL_MODULES: &[&str] = &[ "hg_branch", "hostname", "java", + "jj_status", "jobs", "julia", "kotlin", diff --git a/src/modules/jj.rs b/src/modules/jj.rs new file mode 100644 index 0000000000000..c041a5ffa5c06 --- /dev/null +++ b/src/modules/jj.rs @@ -0,0 +1,290 @@ +use super::{Context, Module, ModuleConfig}; +use crate::configs::jj::JJConfig; +use crate::formatter::string_formatter::StringFormatterError; +use crate::formatter::StringFormatter; +use std::borrow::Cow; + +/// Creates a module with the jj status in the current directory +/// +/// Will display the current branch, commit and change id of the jj repository in the current directory +pub fn module<'a>(context: &'a Context) -> Option> { + let mut module = context.new_module("jj_status"); + let config = JJConfig::try_load(module.config); + // check if the current directory is a jj repo + let repo_root = context + .exec_cmd("jj", &["root", "--ignore-working-copy"])? + .stdout; + + let template = jj_template(config.truncation_length); + let output = context.exec_cmd( + "jj", + &[ + "log", + "-r", + "@", + "-T", + template.as_str(), + "--no-graph", + "--ignore-working-copy", + "--no-pager", + "--color", + "never", + "-R", + repo_root.trim(), + ], + )?; + let parsed = JJStatus::new(&output.stdout)?; + let formatter = match StringFormatter::new(config.format) { + Ok(formatter) => formatter, + Err(e) => { + log::error!("Error in parsing format string for jj module {}", e); + return None; + } + }; + let formatted = formatter + .map_meta(|s, _| match s { + "symbol" => Some(config.symbol), + "divergent_symbol" => { + if parsed.divergent == "true" { + Some(config.divergent_symbol) + } else { + None + } + } + "no_description_symbol" => parsed + .description + .is_empty() + .then_some(config.no_description_symbol), + _ => None, + }) + .map_style(|s| { + Some(Ok(match s { + "change_id_prefix_style" => config.change_id_prefix_style, + "change_id_suffix_style" => config.change_id_suffix_style, + "commit_id_prefix_style" => config.commit_id_prefix_style, + "commit_id_suffix_style" => config.commit_id_suffix_style, + "branch_style" => config.branch_style, + _ => return None, + })) + }) + .map(|v| parsed.format(v)) + .parse(None, Some(context)); + let formatted = match formatted { + Ok(formatted) => formatted, + Err(e) => { + log::error!("Error in parsing format string for jj module {}", e); + return None; + } + }; + module.set_segments(formatted); + + Some(module) +} + +fn jj_template(len: u8) -> String { + format!( + r##"change_id.shortest({len}).prefix() ++ "#," ++ change_id.shortest({len}).rest() ++ "#," ++ commit_id.shortest({len}).prefix() ++ "#," ++ commit_id.shortest({len}).rest() ++ "#," ++ divergent ++ "#," ++ description ++ "#," ++ branches.join(",")"##, + ) +} + +#[derive(Clone, Copy, Debug, Eq, PartialEq)] +struct JJStatus<'s> { + change_id_prefix: &'s str, + change_id_suffix: &'s str, + commit_id_prefix: &'s str, + commit_id_suffix: &'s str, + divergent: &'s str, + description: &'s str, + branches: &'s str, +} + +impl<'s> JJStatus<'s> { + fn new(input: &'s str) -> Option> { + let expected_parts = jj_template(8).matches("#,").count() + 1; + let parsed: Vec<&str> = input.split("#,").collect(); + if parsed.len() != expected_parts { + log::error!( + "expected at least {expected_parts} parts, got {}", + parsed.len() + ); + return None; + } + let [change_id_prefix, change_id_suffix, commit_id_prefix, commit_id_suffix, divergent, description, branches] = + parsed[..] + else { + return None; + }; + Some(Self { + change_id_prefix, + change_id_suffix, + commit_id_prefix, + commit_id_suffix, + divergent, + description, + branches, + }) + } + + fn format(&self, var: &str) -> Option, StringFormatterError>> { + let Self { + change_id_prefix, + change_id_suffix, + commit_id_prefix, + commit_id_suffix, + branches, + description, + .. + } = self; + let branch = if branches.is_empty() { + "" + } else { + branches + }; + + match var { + "change_id_prefix" => Some(Ok(Cow::Borrowed(change_id_prefix))), + "change_id_suffix" => Some(Ok(Cow::Borrowed(change_id_suffix))), + "commit_id_prefix" => Some(Ok(Cow::Borrowed(commit_id_prefix))), + "commit_id_suffix" => Some(Ok(Cow::Borrowed(commit_id_suffix))), + "branch" => Some(Ok(Cow::Borrowed(branch))), + "description" => Some(Ok(Cow::Borrowed(description))), + _ => None, + } + } +} + +#[cfg(test)] +mod test { + static PATH_TO_REPO: &'static str = "/path/to/repo"; + use crate::modules::jj::JJStatus; + use crate::test::ModuleRenderer; + use crate::utils::CommandOutput; + + fn jj_log(output: &str) -> (String, Option) { + ( + format!( + "jj log -r @ -T {} --no-graph --ignore-working-copy --no-pager --color never -R {PATH_TO_REPO}", + crate::modules::jj::jj_template(8) + ), + Some(CommandOutput { + stdout: output.to_string(), + stderr: "".to_string(), + }), + ) + } + + fn is_jj_repo() -> &'static str { + "jj root --ignore-working-copy" + } + + #[test] + fn not_a_jj_repo() { + let actual = ModuleRenderer::new("jj_status") + .cmd(is_jj_repo(), None) + .collect(); + let expected = None; + assert_eq!(expected, actual); + } + + #[test] + fn test_actual_jj_repo() { + let (mocked_jj_log_command, mocked_jj_log_output) = + jj_log("kxx#,zlovo#,be9#,d1825#,false#,#,br1,br2"); + let repo_root = Some(CommandOutput { + stdout: PATH_TO_REPO.to_string(), + stderr: "".to_string(), + }); + let actual = ModuleRenderer::new("jj_status") + .cmd(is_jj_repo(), repo_root.clone()) + .cmd(mocked_jj_log_command.as_str(), mocked_jj_log_output) + .collect() + .unwrap(); + assert_eq!("[🍐 \u{1b}[35mkxx\u{1b}[90mzlovo\u{1b}[0m \u{1b}[34mbe9\u{1b}[90md1825\u{1b}[0m on \u{1b}[35mbr1,br2\u{1b}[0m 📝]", actual); + } + + #[test] + fn test_actual_jj_repo_with_divergence() { + // Mock input to represent a JJ repository status with divergence + let (mocked_jj_log_command, mocked_jj_log_output) = + jj_log("kxx#,zlovo#,be9#,d1825#,true#,#,br1,br2"); + + let repo_root = Some(CommandOutput { + stdout: PATH_TO_REPO.to_string(), + stderr: "".to_string(), + }); + + let actual = ModuleRenderer::new("jj_status") + .cmd(is_jj_repo(), repo_root) + .cmd(mocked_jj_log_command.as_str(), mocked_jj_log_output) + .collect() + .unwrap(); + assert_eq!("[🍐 \u{1b}[35mkxx\u{1b}[90mzlovo\u{1b}[0m \u{1b}[34mbe9\u{1b}[90md1825\u{1b}[0m on \u{1b}[35mbr1,br2\u{1b}[0m 📝 💥]", actual); + } + + #[test] + fn test_parser() { + let input = "kxx#,zlovo#,be9#,d1825#,false#,#,br1,br2"; + let expected = JJStatus { + change_id_prefix: "kxx", + change_id_suffix: "zlovo", + commit_id_prefix: "be9", + commit_id_suffix: "d1825", + divergent: "false", + description: "", + branches: "br1,br2", + }; + let actual = JJStatus::new(input).unwrap(); + assert_eq!(expected, actual); + + let input = "kxx#,zlovo#,be9#,d1825#,false#,#,"; + let expected = JJStatus { + change_id_prefix: "kxx", + change_id_suffix: "zlovo", + commit_id_prefix: "be9", + commit_id_suffix: "d1825", + divergent: "false", + branches: "", + description: "", + }; + let actual = JJStatus::new(input).unwrap(); + assert_eq!(expected, actual); + } + + #[test] + fn test_minimal_input() { + let jj_status = JJStatus::new("a#,b#,c#,d#,true#,e#,f").unwrap(); + assert_eq!(jj_status.change_id_prefix, "a"); + assert_eq!(jj_status.change_id_suffix, "b"); + assert_eq!(jj_status.commit_id_prefix, "c"); + assert_eq!(jj_status.commit_id_suffix, "d"); + assert_eq!(jj_status.divergent, "true"); + assert_eq!(jj_status.description, "e"); + assert_eq!(jj_status.branches, "f"); + } + + #[test] + fn test_no_branches() { + let jj_status = JJStatus::new("a#,b#,c#,d#,false#,e#,").unwrap(); + let formatted_branch = jj_status.format("branch").unwrap().unwrap(); + assert_eq!(formatted_branch, ""); + } + + #[test] + fn test_incorrect_input_format() { + let jj_status = JJStatus::new("a,b,c"); + assert!(jj_status.is_none()); + } + + #[test] + fn test_multiple_branches() { + let jj_status = JJStatus::new("1#,2#,3#,4#,false#,desc#,branch1,branch2").unwrap(); + let formatted_branch = jj_status.format("branch").unwrap().unwrap(); + assert_eq!(formatted_branch, "branch1,branch2"); + } + + #[test] + fn test_divergent_true() { + let jj_status = JJStatus::new("1#,2#,3#,4#,true#,desc#,branch").unwrap(); + assert_eq!(jj_status.divergent, "true"); + } +} diff --git a/src/modules/mod.rs b/src/modules/mod.rs index 57983cd1e6fb4..8823804caeb95 100644 --- a/src/modules/mod.rs +++ b/src/modules/mod.rs @@ -90,6 +90,7 @@ mod zig; #[cfg(feature = "battery")] mod battery; +mod jj; mod typst; #[cfg(feature = "battery")] @@ -149,6 +150,7 @@ pub fn handle<'a>(module: &str, context: &'a Context) -> Option> { "hg_branch" => hg_branch::module(context), "hostname" => hostname::module(context), "java" => java::module(context), + "jj_status" => jj::module(context), "jobs" => jobs::module(context), "julia" => julia::module(context), "kotlin" => kotlin::module(context), @@ -267,6 +269,7 @@ pub fn description(module: &str) -> &'static str { "hg_branch" => "The active branch and topic of the repo in your current directory", "hostname" => "The system hostname", "java" => "The currently installed version of Java", + "jj_status" => "The status of the current jj repo", "jobs" => "The current number of jobs running", "julia" => "The currently installed version of Julia", "kotlin" => "The currently installed version of Kotlin",