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:
parent
203727b291
commit
97b9c1202a
3 changed files with 135 additions and 0 deletions
28
prompt/async_git_prompt/README.md
Normal file
28
prompt/async_git_prompt/README.md
Normal 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`.
|
77
prompt/async_git_prompt/async-git-prompt.nu
Normal file
77
prompt/async_git_prompt/async-git-prompt.nu
Normal 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)
|
||||
}
|
||||
}
|
30
prompt/async_git_prompt/prompt.nu
Normal file
30
prompt/async_git_prompt/prompt.nu
Normal 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)〉" }
|
Loading…
Add table
Add a link
Reference in a new issue