mirror of
https://github.com/RGBCube/nu_scripts
synced 2025-08-02 15:17:47 +00:00
Improved CDPATH (#644)
This updated `c` command supports: * Changing to the previous directory with `c -` * Changing to absolute directories * Completion of CDPATH entries * Completion of absolute paths * Completion of children When completing CDPATH entries the parent directory is shown to provide context in case multiple CDPATH entries have the same child directory names. Fixes #244
This commit is contained in:
parent
c39a41ad2d
commit
c93ce14fc9
1 changed files with 157 additions and 24 deletions
|
@ -1,36 +1,169 @@
|
||||||
def-env c [dir = ""] {
|
# You must set $env.CDPATH, try:
|
||||||
let default = if $nu.os-info.name == "windows" {
|
#
|
||||||
|
# $env.CDPATH = [
|
||||||
|
# ".",
|
||||||
|
# "~",
|
||||||
|
# "~/path/to/repositories",
|
||||||
|
# ]
|
||||||
|
#
|
||||||
|
# The above $env.CDPATH will complete:
|
||||||
|
# * Entries under the current directory ($env.PWD)
|
||||||
|
# * Entries in your home directory ($env.HOME)
|
||||||
|
# * Entries where you check out repositories
|
||||||
|
# * Children of those entries
|
||||||
|
#
|
||||||
|
# This CDPATH implementation also completes absolute paths to help you use `c`
|
||||||
|
# instead of `cd`
|
||||||
|
#
|
||||||
|
# Bugs:
|
||||||
|
# * `c` does not complete paths that start with "~". This should support both
|
||||||
|
# directories ("~/.config/nu"), users ("~notme"), and both combined
|
||||||
|
# ("~notme/.config/nu")
|
||||||
|
module cdpath {
|
||||||
|
# $env.CDPATH with unique, expanded, existing paths
|
||||||
|
def cdpath [] {
|
||||||
|
$env.CDPATH
|
||||||
|
| path expand
|
||||||
|
| uniq
|
||||||
|
| filter {|| $in | path exists }
|
||||||
|
}
|
||||||
|
|
||||||
|
# Children of a path
|
||||||
|
def children [path: string] {
|
||||||
|
ls -a $path
|
||||||
|
| where type == "dir"
|
||||||
|
| get name
|
||||||
|
}
|
||||||
|
|
||||||
|
# Completion for `c`
|
||||||
|
#
|
||||||
|
# `contains` is used instead of `starts-with` to behave similar to fuzzy
|
||||||
|
# completion behavior.
|
||||||
|
#
|
||||||
|
# During completion of a CDPATH entry the description contains the parent
|
||||||
|
# directory you will complete under. This allows you to tell which entry in
|
||||||
|
# your CDPATH your are completing to if you have the same directory under
|
||||||
|
# multiple entries.
|
||||||
|
def complete [context: string] {
|
||||||
|
let context_dir = $context | parse "c {context_dir}" | get context_dir | first
|
||||||
|
let path = $context_dir | path split
|
||||||
|
let no_trailing_slash = not ($context_dir | str ends-with "/")
|
||||||
|
|
||||||
|
# completion with no context
|
||||||
|
if ( $path | is-empty ) {
|
||||||
|
complete_from_cdpath
|
||||||
|
# Complete an entry in CDPATH
|
||||||
|
#
|
||||||
|
# This appends a / to allow continuation to the last step
|
||||||
|
} else if $no_trailing_slash and (1 == ( $path | length )) {
|
||||||
|
let first = $path | first
|
||||||
|
|
||||||
|
complete_from_cdpath
|
||||||
|
| filter {|| $in.value | str contains $first }
|
||||||
|
| upsert value {|| $"($in.value)/" }
|
||||||
|
# Complete a child of a CDPATH entry
|
||||||
|
} else {
|
||||||
|
let prefix = if 1 == ($path | length) {
|
||||||
|
$path | first
|
||||||
|
} else {
|
||||||
|
$path | first (($path | length) - 1) | path join
|
||||||
|
}
|
||||||
|
|
||||||
|
let last = if 1 == ($path | length) {
|
||||||
|
""
|
||||||
|
} else {
|
||||||
|
$path | last
|
||||||
|
}
|
||||||
|
|
||||||
|
let chosen_path = if ( $path | first) == "/" {
|
||||||
|
if $no_trailing_slash {
|
||||||
|
$prefix
|
||||||
|
} else {
|
||||||
|
$context_dir
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
cdpath
|
||||||
|
| each {||
|
||||||
|
$in | path join $prefix
|
||||||
|
}
|
||||||
|
| filter {||
|
||||||
|
$in | path exists
|
||||||
|
}
|
||||||
|
| first
|
||||||
|
}
|
||||||
|
|
||||||
|
children $chosen_path
|
||||||
|
| filter {||
|
||||||
|
$in | str contains $last
|
||||||
|
}
|
||||||
|
| each {|child|
|
||||||
|
$"($chosen_path | path join $child)/"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
def complete_from_cdpath [] {
|
||||||
|
cdpath
|
||||||
|
| each { |path|
|
||||||
|
children $path
|
||||||
|
| path basename
|
||||||
|
| sort
|
||||||
|
| each { |child| { value: $child, description: $path } }
|
||||||
|
}
|
||||||
|
| flatten
|
||||||
|
| uniq-by value
|
||||||
|
}
|
||||||
|
|
||||||
|
# Change directory with $env.CDPATH
|
||||||
|
export def-env c [dir = "": string@complete] {
|
||||||
|
let span = (metadata $dir).span
|
||||||
|
let default = if $nu.os-info.name == "windows" {
|
||||||
$env.USERPROFILE
|
$env.USERPROFILE
|
||||||
} else {
|
} else {
|
||||||
$env.HOME
|
$env.HOME
|
||||||
}
|
}
|
||||||
|
|
||||||
let complete_dir = if $dir == "" {
|
let target_dir = if $dir == "" {
|
||||||
|
$default
|
||||||
|
} else if $dir == "-" {
|
||||||
|
if "OLDPWD" in $env {
|
||||||
|
$env.OLDPWD
|
||||||
|
} else {
|
||||||
$default
|
$default
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
$env.CDPATH
|
cdpath
|
||||||
| reduce -f "" { |$it, $acc| if $acc == "" {
|
| reduce -f "" { |$it, $acc|
|
||||||
let new_path = ([$it $dir] | path join)
|
if $acc == "" {
|
||||||
|
let new_path = ([$it $dir] | path join)
|
||||||
if ($new_path | path exists) {
|
if ($new_path | path exists) {
|
||||||
$new_path
|
$new_path
|
||||||
} else {
|
} else {
|
||||||
""
|
""
|
||||||
}
|
}
|
||||||
} else { $acc }}
|
} else {
|
||||||
|
$acc
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let complete_dir = if $complete_dir == "" {
|
let target_dir = if $target_dir == "" {
|
||||||
error make --unspanned {msg: "No such path"}
|
let cdpath = $env.CDPATH | str join ", "
|
||||||
} else if (($complete_dir | path expand | path type) != "dir") {
|
|
||||||
error make --unspanned {msg: "Not a directory"}
|
error make {
|
||||||
|
msg: $"No such child under: ($cdpath)",
|
||||||
|
label: {
|
||||||
|
text: "Child directory",
|
||||||
|
start: $span.start,
|
||||||
|
end: $span.end,
|
||||||
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
($complete_dir | path expand)
|
$target_dir
|
||||||
}
|
}
|
||||||
|
|
||||||
cd $complete_dir
|
cd $target_dir
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
# You need to have $env.CDPATH variable declared, my suggestion from config.nu:
|
use cdpath c
|
||||||
# $env.CDPATH = [".", $env.HOME, "/", ([$env.HOME, ".config"] | path join)]
|
|
||||||
# WINDOWS:
|
|
||||||
# $env.CDPATH = ["", $env.USERPROFILE, ([$env.USERPROFILE, "AppData\\Roaming\\"] | path join)]
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue