mirror of
https://github.com/RubyMetric/chsrc
synced 2026-10-26 01:54:44 +08:00
203 lines
5.7 KiB
Bash
203 lines
5.7 KiB
Bash
# ---------------------------------------------------------------
|
|
# SPDX-License-Identifier: GPL-3.0-or-later
|
|
# ---------------------------------------------------------------
|
|
# Shell File : completion.sh
|
|
# File Authors : 郭恒 <2085471348@qq.com>
|
|
# Contributors : Nil Null <nil@null.org>
|
|
# |
|
|
# Created On : <2026-03-19>
|
|
# Last Modified : <2026-03-21>
|
|
#
|
|
# ----------
|
|
# chsrc 的 Shell 自动补全脚本(当前仅在 Ubuntu 中测试过)
|
|
# 1. Bash 已测试
|
|
# 2. Zsh 暂未测试
|
|
#
|
|
# @issue https://github.com/RubyMetric/chsrc/issues/204
|
|
# source completion.sh # 当前终端立即生效
|
|
# ---------------------------------------------------------------
|
|
|
|
_chsrc() {
|
|
|
|
# 初始化部分
|
|
|
|
## 手动划分字符串
|
|
local line="${COMP_LINE:0:$COMP_POINT}" # COMP_LINE的从0到光标的所有输入,作为一个字符串
|
|
read -ra words <<< "$line" # 按IFS重新分词,默认分隔符是" \t\n"
|
|
cword=$(( ${#words[@]} - 1 )) # 下表从0开始,当前词下标
|
|
|
|
### 如果行末是空格,说明需要补充新的词
|
|
if [[ "${line: -1}" == " " ]]; then
|
|
words+=("")
|
|
cword=$(( ${#words[@]} - 1 ))
|
|
fi
|
|
|
|
cur="${words[$cword]}"
|
|
|
|
## 定义具体dish
|
|
local dishes_lang="gem ruby rb rubygem rubygems bundler
|
|
python pypi py
|
|
pip
|
|
poetry
|
|
pdm
|
|
rye
|
|
uv
|
|
js javascript node nodejs
|
|
bun
|
|
npm
|
|
yarn
|
|
pnpm
|
|
nvm
|
|
perl cpan
|
|
php composer
|
|
lua luarocks
|
|
go golang goproxy
|
|
rust cargo crate crates
|
|
rustup
|
|
java maven mvn maven-daemon mvnd gradle
|
|
clojure clojars cloj lein
|
|
dart pub
|
|
flutter
|
|
nuget net .net dotnet
|
|
haskell cabal stack hackage
|
|
ocaml opam
|
|
r cran
|
|
julia"
|
|
|
|
local dishes_os="ubuntu zorinos
|
|
linuxmint
|
|
debian
|
|
fedora
|
|
opensuse opensuse-leap opensuse-tumbleweed
|
|
kali
|
|
msys2 msys
|
|
arch archlinux
|
|
archlinuxcn archcn
|
|
manjaro
|
|
gentoo
|
|
rocky rockylinux
|
|
alma almalinux
|
|
alpine
|
|
voidlinux
|
|
solus
|
|
trisquel
|
|
linuxlite
|
|
ros ros2
|
|
raspi raspberrypi
|
|
armbian
|
|
openwrt opkg LEDE
|
|
termux
|
|
openkylin
|
|
openeuler
|
|
anolis openanolis
|
|
deepin
|
|
freebsd
|
|
netbsd
|
|
openbsd"
|
|
|
|
local dishes_ware="winget
|
|
brew homebrew
|
|
cocoa cocoapods cocoapod
|
|
docker dockerhub
|
|
flatpak flathub
|
|
nix
|
|
guix
|
|
emacs elpa
|
|
latex ctan tex texlive miktex tlmgr mpm
|
|
conda anaconda"
|
|
|
|
local all_dishes="$dishes_lang $dishes_os $dishes_ware"
|
|
local options="-dry -scope= -ipv6 -english -en -no-color -h --help"
|
|
local scope_options="project user system"
|
|
local commands="help issue list ls measure cesu get set reset"
|
|
|
|
# 逻辑部分
|
|
|
|
# 扫描已输入词,跳过选项,依次填入 cmd / second_arg,并计数
|
|
# 找到第一个非选项词作为子命令
|
|
local non_opts=()
|
|
for w in "${words[@]:1:cword-1}"; do
|
|
[[ $w != -* ]] && non_opts+=("$w")
|
|
done
|
|
# 若有non_opts[0]
|
|
local cmd=${non_opts[0]}
|
|
|
|
if [[ -z "$cmd" ]]; then
|
|
COMPREPLY=( $(compgen -W "$commands $options" -- "$cur") )
|
|
return 0
|
|
fi
|
|
|
|
local second_arg="${non_opts[1]:-}"
|
|
local args_after=${#non_opts[@]}
|
|
|
|
|
|
# 补全-scope=project这样的选项时,需要手动控制,先补全-scope=再补全后面的
|
|
# 作为一个函数来实现
|
|
_complete_options() {
|
|
if [[ $cur == -scope=* ]]; then
|
|
# cur="-scope=",匹配
|
|
COMPREPLY=( $(compgen -W "$scope_options" -- "${cur#-scope=}") )
|
|
elif [[ $cur == -* ]]; then
|
|
COMPREPLY=( $(compgen -W "$options" -- "$cur") )
|
|
# 补全 -scope 本身时不加尾部空格,让用户可以继续输入=
|
|
if [[ ${COMPREPLY[0]} == "-scope=" ]]; then
|
|
# 对已经补全的候选项做出调整,补全出-scope=后不跟空格,才能匹配scope_options
|
|
compopt -o nospace
|
|
fi
|
|
fi
|
|
}
|
|
|
|
# 主要的补全逻辑
|
|
case "$cmd" in
|
|
help|h|issue|i)
|
|
COMPREPLY=( $(compgen -W "help issue" -- $cur))
|
|
;;
|
|
list|ls|l)
|
|
if [[ $args_after -eq 1 ]]; then
|
|
COMPREPLY=( $(compgen -W "mirror dish os lang ware $all_dishes " -- $cur) )
|
|
else
|
|
_complete_options
|
|
fi
|
|
;;
|
|
measure|m|cesu)
|
|
if [[ $args_after -eq 1 && $cur != -* ]]; then
|
|
COMPREPLY=( $(compgen -W "$all_dishes" -- "$cur") )
|
|
else
|
|
_complete_options
|
|
fi
|
|
;;
|
|
get|g)
|
|
if [[ $args_after -eq 1 && $cur != -* ]]; then
|
|
COMPREPLY=( $(compgen -W "$all_dishes" -- "$cur") )
|
|
else
|
|
COMPREPLY=( $(compgen -W "$options" -- $cur) )
|
|
fi
|
|
;;
|
|
reset)
|
|
if [[ $args_after -eq 1 ]]; then
|
|
COMPREPLY=( $(compgen -W "$all_dishes" -- $cur) )
|
|
else
|
|
COMPREPLY=( $(compgen -W "$options" -- $cur) )
|
|
fi
|
|
;;
|
|
set|s)
|
|
if [[ $args_after -eq 1 && $cur != -* ]]; then
|
|
COMPREPLY=( $(compgen -W "$all_dishes" -- "$cur") )
|
|
elif [[ $args_after -eq 2 ]]; then
|
|
COMPREPLY=( $(compgen -W "first" -- $cur) )
|
|
else
|
|
_complete_options
|
|
fi
|
|
;;
|
|
*)
|
|
_complete_options
|
|
;;
|
|
|
|
esac
|
|
return 0
|
|
}
|
|
|
|
|
|
# 注册, 作用于当前终端
|
|
complete -F _chsrc chsrc
|