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

Complete package name for "uv remove" (#1072)

![image](https://github.com/user-attachments/assets/7653d26b-665f-4caa-a764-0f83b41f5519)

Drawback:

The flags of "uv remove" command are no longer completed after I add
competer like this:

```nu
  export extern "uv remove" [
    --no-config
    --help(-h)
    --version(-V)
    ...packages: string@"nu-complete uv packages"
  ]
```

I have no solution yet.
This commit is contained in:
Nguyễn Hồng Quân 2025-04-07 19:23:53 +07:00 committed by GitHub
parent a19339cdaa
commit 548b6bbe95
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -5,6 +5,64 @@
module completions {
const PYPRJ = 'pyproject.toml'
# Split a string to list of args, taking quotes into account.
# Code is copied and modified from https://github.com/nushell/nushell/issues/14582#issuecomment-2542596272
def args-split []: string -> list<string> {
# Define our states
const STATE_NORMAL = 0
const STATE_IN_SINGLE_QUOTE = 1
const STATE_IN_DOUBLE_QUOTE = 2
const STATE_ESCAPE = 3
const WHITESPACES = [" " "\t" "\n" "\r"]
# Initialize variables
mut state = $STATE_NORMAL
mut current_token = ""
mut result: list<string> = []
mut prev_state = $STATE_NORMAL
# Process each character
for char in ($in | split chars) {
if $state == $STATE_ESCAPE {
# Handle escaped character
$current_token = $current_token + $char
$state = $prev_state
} else if $char == '\' {
# Enter escape state
$prev_state = $state
$state = $STATE_ESCAPE
} else if $state == $STATE_NORMAL {
if $char == "'" {
$state = $STATE_IN_SINGLE_QUOTE
} else if $char == '"' {
$state = $STATE_IN_DOUBLE_QUOTE
} else if ($char in $WHITESPACES) {
# Whitespace in normal state means token boundary
$result = $result | append $current_token
$current_token = ""
} else {
$current_token = $current_token + $char
}
} else if $state == $STATE_IN_SINGLE_QUOTE {
if $char == "'" {
$state = $STATE_NORMAL
} else {
$current_token = $current_token + $char
}
} else if $state == $STATE_IN_DOUBLE_QUOTE {
if $char == '"' {
$state = $STATE_NORMAL
} else {
$current_token = $current_token + $char
}
}
}
# Handle the last token
$result = $result | append $current_token
# Return the result
$result
}
def "nu-complete uv python_preference" [] {
[ "only-managed" "managed" "system" "only-system" ]
}
@ -32,9 +90,70 @@ module completions {
}
}
def "nu-complete uv groups" [] {
def get-groups []: nothing -> list<string> {
let file = (find-pyproject-file)
open $file | get -i dependency-groups | columns
try { open $file | get -i dependency-groups | columns } catch { [] }
}
# Groups completer for subcommands
def "nu-complete uv groups" [] {
get-groups
}
# Groups completer for "uv add".
# When there is no groups, we suggest a common name "dev".
def "nu-complete uv groups for add" [] {
get-groups | default ['dev']
}
# From a list of packages and their version strings, get only package names.
# Ref: https://packaging.python.org/en/latest/specifications/dependency-specifiers/#dependency-specifiers
def parse-package-names []: list<string> -> list<string> {
$in | split column -n 2 -r '[\s\[@>=<;~!]' p v | get p
}
# Get packages from "project.dependencies"
def get-main-packages [] {
let file = (find-pyproject-file)
try { open $file | get -i project.dependencies | parse-package-names } catch { [] }
}
# Get packages from "project.optional-dependencies"
def get-optional-packages [] {
let file = (find-pyproject-file)
try { open $file | get -i project.optional-dependencies | parse-package-names } catch { [] }
}
# Get packages from "dependency-groups".
# Ref: https://packaging.python.org/en/latest/specifications/dependency-groups/#dependency-groups
def get-dependency-group-packages [only_group?: string] {
let file = (find-pyproject-file)
let dg = try { open $file | get -i dependency-groups } catch { [] }
# One group can include other groups, like:
# dev = ['click', { include-group = "docs" }, { include-group = "linting" }, { include-group = "test" }]
let handle_line = {|p| if (($p | describe) == 'string') { $p } else { $dg | get ($p.include-group) } }
if ($only_group | is-not-empty) {
$dg | get $only_group | each $handle_line | flatten | parse-package-names
} else {
$dg | items { |gn, pk| $pk | each $handle_line | flatten } | flatten | parse-package-names
}
}
def get-all-dependencies [] {
get-main-packages | append (get-optional-packages) | append (get-dependency-group-packages)
}
export def "nu-complete uv packages" [context: string, position?:int] {
let preceding = $context | str substring ..$position
let prev_tokens = $preceding | str trim | args-split
# Check if "--group" is specified
let go = $prev_tokens | enumerate | find '--group' | get -i index.0
let group = if ($go | is-not-empty) { $prev_tokens | get -i ($go + 1)}
if ($group | is-empty ) {
get-all-dependencies
} else {
get-dependency-group-packages $group
}
}
# An extremely fast Python package manager.
@ -428,7 +547,6 @@ def "nu-complete uv remove index_strategy" [] {
# Remove dependencies from the project
export extern "uv remove" [
...packages: string # The names of the dependencies to remove (e.g., `ruff`)
--dev # Remove the packages from the development dependency group
--optional: string # Remove the packages from the project's optional dependencies for the specified extra
--group: string@"nu-complete uv groups" # Remove the packages from the specified dependency group
@ -501,6 +619,7 @@ def "nu-complete uv remove index_strategy" [] {
--no-config # Avoid discovering configuration files (`pyproject.toml`, `uv.toml`)
--help(-h) # Display the concise help for this command
--version(-V) # Display the uv version
...packages: string@"nu-complete uv packages" # The names of the dependencies to remove (e.g., `ruff`)
]
def "nu-complete uv sync index_strategy" [] {