1
Fork 0
mirror of https://github.com/RGBCube/nu_scripts synced 2025-08-01 22:57:46 +00:00

Async git prompt (#288)

This commit is contained in:
Dan Davison 2022-09-05 18:08:40 -04:00 committed by GitHub
parent 203727b291
commit 97b9c1202a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 135 additions and 0 deletions

View file

@ -0,0 +1,28 @@
This module exports commands for creating a nushell prompt that computes git status (staged and
unstaged changes) asynchronously. This can be useful in large git repos when it is slow to obtain
this information synchronously.
To use this module:
0. Place the file `async-git-prompt.nu` in the `$nu.config-path` directory (this is the directory
containing `init.nu` and `env.nu`).
1. Use the command `async-git-prompt-string` in your own `PROMPT_COMMAND` (the file prompt.nu
contains an example of doing this.)
At this point, your prompt will be computing the information synchronously, because the cache
file does not yet exist.
2. In a repo where git is slow, run the command `async-git-prompt-refresh-cache`.
Now, your prompt will be fast, but it also won't update automatically. You could investigate a good
way to invalidate the cache automatically, but the manual alternative is:
3. Whenever you think your prompt might be stale, re-run the command `async-git-prompt-refresh-cache`.
Your prompt will update on one of the next times that you hit <enter>.
4. It will probably be convenient to alias this, e.g.
```nu
alias r = async-git-prompt-refresh-cache
```
5. To go back to synchronous mode, run `async-git-prompt-delete-cache`.

View file

@ -0,0 +1,77 @@
# This module exports commands for creating a nushell prompt that computes git status (staged and
# unstaged changes) asynchronously. This can be useful in large git repos when it is slow to obtain
# this information synchronously.
# See README.md for usage.
def unstaged-symbol [] { 'અ' }
def staged-symbol [] { 'જ' }
def in-progress-symbol [] { '…' }
def cached-result-symbol [] { $"·" } #〈
def cache-file [] { '.nu-async-git-prompt-cache'}
def do-async [commands: string] {
bash -c $"nu -c '($commands)' &"
}
export def async-git-prompt-string [] {
let cache_path = (cache-path)
if ($cache_path | empty?) {
""
} else if ($cache_path | path exists) {
$"(cached-result-symbol)(open $cache_path | str trim)"
} else {
async-git-prompt-compute-sync
}
}
export def async-git-prompt-compute-sync [] {
let unstaged = {
let symbol = if ((git diff --quiet | complete).exit_code == 1) {
(unstaged-symbol)
} else {
''
}
{ unstaged: $symbol}
}
let staged = {
let symbol = if ((git diff --cached --quiet | complete).exit_code == 1) {
(staged-symbol)
} else {
''
}
{ staged: $symbol}
}
# Execute the two slow git commands in parallel and merge the results into a single record
let symbols = ([ $unstaged $staged ] | par-each { |it| do $it } | reduce {|a b| $a | merge {$b}})
$"($symbols | get 'unstaged') ($symbols | get 'staged')" | str trim
}
export def async-git-prompt-refresh-cache [] {
let cache_path = (cache-path)
if ($cache_path != null) {
echo (in-progress-symbol) | save $cache_path
do-async $"use ($nu.config-path | path expand | path dirname)/async-git-prompt.nu *; async-git-prompt-compute-sync | save ($cache_path)"
}
}
export def async-git-prompt-delete-cache [] {
let cache_path = (cache-path)
if ($cache_path != null) {
rm -f $cache_path
}
}
def cache-path [] {
let dir = if ('.git' | path exists) {
'.'
} else {
do -i { git rev-parse --show-toplevel | str trim -r }
}
if ($dir | empty?) {
null
} else {
$dir | path join (cache-file)
}
}

View file

@ -0,0 +1,30 @@
# This file contains an example nushell prompt, making use of the async-git-prompt module.
use async-git-prompt.nu *
def prompt-concat [parts: table] {
$parts
| where (not ($it.text | empty?))
| each { |it| $"($it.color)($it.text)" }
| str collect ' '
}
def prompt-git-branch [] {
do -i { git rev-parse --abbrev-ref HEAD | str trim -r}
}
def prompt-create-left-prompt [] {
let pwd = ($env.PWD | str replace $env.HOME '~')
prompt-concat [
{text: $pwd, color: (ansi green_bold)}
{text: (prompt-git-branch), color: (ansi blue_bold)}
{text: (async-git-prompt-string), color: (ansi green_bold)}
]
}
def prompt-create-right-prompt [] {
$nothing
}
let-env PROMPT_COMMAND = { prompt-create-left-prompt }
let-env PROMPT_COMMAND_RIGHT = { prompt-create-right-prompt }
let-env PROMPT_INDICATOR = { $" (ansi green_bold)〉" }