mirror of
https://github.com/RGBCube/nu_scripts
synced 2025-07-30 13:47:46 +00:00
Add completions for lftp (#1113)
[lftp](https://lftp.yar.ru/) is the program which I use when I need to copy many files at once via SSH. Though having `FTP` in the name, it supports more protocols than just FTP. This PR provides auto-completion for the "site" argument. Source of sites are: - SSH aliases (for SFTP and FISH protocols). - LFTP's bookmarks. 
This commit is contained in:
parent
c0e88c5756
commit
e82487722b
2 changed files with 129 additions and 0 deletions
31
custom-completions/lftp/README.md
Normal file
31
custom-completions/lftp/README.md
Normal file
|
@ -0,0 +1,31 @@
|
|||
# LFTP completions
|
||||
|
||||
[`LFTP`](https://lftp.yar.ru/) is a file transfer program supporting many protocols (FTP, HTTP, SFTP, FISH, TORRENT). It is shell-like, reliable and can transfer several files in parallel.
|
||||
|
||||
## Install completion script
|
||||
|
||||
### Method 1: Use from Git repo
|
||||
|
||||
- `git clone https://github.com/nushell/nu_scripts.git`
|
||||
|
||||
- Add this to `$nu.config-path` file.
|
||||
|
||||
```nu
|
||||
source repo/custom-completions/lftp/lftp-completions.nu
|
||||
```
|
||||
|
||||
### Method 2: Selectively copy
|
||||
|
||||
|
||||
- Copy the _lftp-completions.nu_ to Nu standard place.
|
||||
|
||||
```nu
|
||||
cp custom-completions/lftp/lftp-completions.nu ($nu.data-dir | path join 'completions')
|
||||
```
|
||||
|
||||
- Open `$nu.config-path` file and add this:
|
||||
|
||||
```nu
|
||||
source lftp-completions.nu
|
||||
```
|
||||
|
98
custom-completions/lftp/lftp-completions.nu
Normal file
98
custom-completions/lftp/lftp-completions.nu
Normal file
|
@ -0,0 +1,98 @@
|
|||
# nu-version: 0.102.0
|
||||
|
||||
module lftp-completion-utils {
|
||||
def extract-host []: list<string> -> record<name: string, addr: string> {
|
||||
# Host is a list of lines, like:
|
||||
# ╭───┬──────────────────────────────╮
|
||||
# │ 0 │ Host quanweb │
|
||||
# │ 1 │ User quan │
|
||||
# │ 2 │ Hostname quan.hoabinh.vn │
|
||||
# │ 3 │ # ProxyJump farmb-omz │
|
||||
# │ 4 │ │
|
||||
# ╰───┴──────────────────────────────╯
|
||||
let host = $in
|
||||
let $first_line = try { $host | first | str trim } catch { null }
|
||||
# Don't accept blocks like "Host *"
|
||||
if ($first_line | is-empty) or '*' in $first_line {
|
||||
null
|
||||
} else {
|
||||
let name = $first_line | split row -r '\s+' | get 1
|
||||
# May not contain hostname
|
||||
match ($host | slice 1.. | find -ir '^\s*Hostname\s') {
|
||||
[] => null,
|
||||
$addr => { name: $name, addr: ($addr | str trim | split row -n 2 -r '\s+' | get 1) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Process a SSH config file
|
||||
export def process []: string -> record<hosts: list<record<name: string, addr: string>>, includes: list<string>> {
|
||||
let lines = $in | lines
|
||||
# Get 'Include' lines
|
||||
let include_lines = $lines | find -n -ir '^Include\s' | str trim | each { $in | split row -n 2 -r '\s+' | get 1 | str trim -c '"'}
|
||||
# Find "Host" blocks
|
||||
let marks = $lines | enumerate | find -n -ir '^Host\s'
|
||||
let mark_indices = $marks | get index | append ($lines | length)
|
||||
let hosts = $mark_indices | window 2 | each {|w| $lines | slice $w.0..<($w.1) }
|
||||
{
|
||||
hosts: ($hosts | each { $in | extract-host }),
|
||||
includes: $include_lines
|
||||
}
|
||||
}
|
||||
|
||||
export def get-ssh-sites []: nothing -> table<value: string, description: string> {
|
||||
let files = [
|
||||
'/etc/ssh/ssh_config',
|
||||
'~/.ssh/config'
|
||||
] | filter {|file| $file | path exists }
|
||||
|
||||
|
||||
let first_result: record<hosts: list<record<name: string, addr: string>>, includes: list<string>> = $files | par-each {|file|
|
||||
let folder = $file | path expand | path dirname
|
||||
let r = $file | open --raw | process
|
||||
$r | update includes { each {|f| $folder | path join $f } }
|
||||
} | reduce {|it| merge deep $it --strategy=append }
|
||||
|
||||
let $includes: list<string> = $first_result.includes | each {|f|
|
||||
if '*' in $f {
|
||||
glob $f
|
||||
} else if ($f | path exists) {
|
||||
[$f]
|
||||
} else []
|
||||
} | flatten
|
||||
|
||||
# Process include files
|
||||
let included_hosts: list<record<name: string, addr: string>> = (if ($includes | is-empty) { [] } else {
|
||||
let second_result = $includes | par-each {|p| $p | open --raw | process } | reduce {|it| merge deep $it --strategy=append }
|
||||
$second_result.hosts
|
||||
})
|
||||
|
||||
let hosts = $first_result.hosts ++ $included_hosts
|
||||
$hosts | each {|h| [$"sftp://($h.name)" $"fish://($h.name)"] | wrap value | insert description $h.addr } | flatten
|
||||
}
|
||||
|
||||
export def get-bookmark-sites []: nothing -> table<value: string, description: string> {
|
||||
const FILE_PATH = '~/.local/share/lftp/bookmarks' | path expand
|
||||
let sites = open --raw $FILE_PATH | lines | split column -n 2 -r \s+ value description
|
||||
$sites | update value { $"bm:($in)" }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
def "nu-complete lftp-site" [] {
|
||||
use lftp-completion-utils get-ssh-sites
|
||||
use lftp-completion-utils get-bookmark-sites
|
||||
get-ssh-sites | append (get-bookmark-sites)
|
||||
}
|
||||
|
||||
export extern 'lftp' [
|
||||
-c: string # Execute the commands and exit
|
||||
-d # Switch on debugging mode
|
||||
-e: string # Execute the command just after selecting
|
||||
-p: int # Use the port for connection
|
||||
-u: string # Use the user/password for authentication
|
||||
--norc # Don't execute rc files from the home directory
|
||||
--help # Print the help and exit
|
||||
--version # Print lftp version and exit
|
||||
site?: string@"nu-complete lftp-site" # Host name, URL or bookmark name
|
||||
]
|
Loading…
Add table
Add a link
Reference in a new issue