mirror of
https://github.com/nushell/nu_scripts.git
synced 2024-08-17 17:30:24 +03:00
170 lines
4.0 KiB
Plaintext
170 lines
4.0 KiB
Plaintext
# You must set $env.CDPATH, try:
|
|
#
|
|
# $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
|
|
} else {
|
|
$env.HOME
|
|
}
|
|
|
|
let target_dir = if $dir == "" {
|
|
$default
|
|
} else if $dir == "-" {
|
|
if "OLDPWD" in $env {
|
|
$env.OLDPWD
|
|
} else {
|
|
$default
|
|
}
|
|
} else {
|
|
cdpath
|
|
| reduce -f "" { |$it, $acc|
|
|
if $acc == "" {
|
|
let new_path = ([$it $dir] | path join)
|
|
if ($new_path | path exists) {
|
|
$new_path
|
|
} else {
|
|
""
|
|
}
|
|
} else {
|
|
$acc
|
|
}
|
|
}
|
|
}
|
|
|
|
let target_dir = if $target_dir == "" {
|
|
let cdpath = $env.CDPATH | str join ", "
|
|
|
|
error make {
|
|
msg: $"No such child under: ($cdpath)",
|
|
label: {
|
|
text: "Child directory",
|
|
start: $span.start,
|
|
end: $span.end,
|
|
}
|
|
}
|
|
} else {
|
|
$target_dir
|
|
}
|
|
|
|
cd $target_dir
|
|
}
|
|
}
|
|
|
|
use cdpath c
|