Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 12 additions & 2 deletions .github/workflows/PR-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,10 @@
# Workflow File : PR-test.yml
# File Authors : 曾奥然 <ccmywish@qq.com>
# Contributors : Mikachu2333 <linkchou@yandex.com>
# | @swim233
# |
# Created On : <2025-06-19>
# Last Modified : <2025-08-17>
# Last Modified : <2026-09-09>
#
# Test PR
# ---------------------------------------------------------------
Expand All @@ -25,6 +26,10 @@ on:
paths:
- "src/**"
- "lib/**"
- "Makefile"
- "tool/completion/**"
- "test/*zsh-completion*"
- "pkg/deb/**"

jobs:
test-on-ubuntu:
Expand All @@ -36,13 +41,18 @@ jobs:
- name: 检出代码
uses: actions/checkout@v7

- name: 安装Zsh补全测试依赖
run: |
sudo apt-get update
sudo apt-get install -y zsh

- name: 测试构建情况
run: |
make

- name: 测试test情况
run: |
make test
make test REQUIRE_ZSH=1

test-on-windows:
name: 在Windows上测试
Expand Down
28 changes: 25 additions & 3 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,10 @@
# | @G_I_Y
# | @NewbieXvwu
# | @Mikachu2333
# | @swim233
# |
# Created On : <2023-08-28>
# Last Modified : <2026-08-14>
# Last Modified : <2026-09-09>
#
# 请阅读 ./doc/01-开发与构建.md 来使用
# --------------------------------------------------------------
Expand Down Expand Up @@ -202,6 +203,9 @@ build-in-release-mode:
@$(call Build-Command-For-Release, $(ReleaseMode-Target-Name))
@$(call Finished-Echo-Info, RELEASE)

# 确保从干净源码树执行 install 时已构建 RELEASE mode 二进制
$(ReleaseMode-Target-Name): build-in-release-mode

build-in-ci-release-mode:
@$(call Starting-Echo-Info, CI-RELEASE, $(CIReleaseMode-Target-Name))
@$(call Build-Command-For-Release, $(CIReleaseMode-Target-Name))
Expand All @@ -215,7 +219,7 @@ debug: build-in-debug-mode



test: test-make-var test-xy test-fw
test: test-make-var test-xy test-fw test-zsh-completion

test-make-var:
@echo "On-Linux: $(On-Linux)"
Expand Down Expand Up @@ -245,6 +249,19 @@ test-fw:
@$(CC) test/fw.c $(CFLAGS) -o fw
@./fw

test-zsh-completion:
@perl ./test/verify-sync-state-of-zsh-completion
@if command -v zsh >/dev/null 2>&1; then \
zsh -n ./tool/completion/_chsrc ./test/simulate-zsh-completion.zsh ./test/zsh-completion-integration.zsh && \
zsh -f ./test/simulate-zsh-completion.zsh && \
zsh -f ./test/zsh-completion-integration.zsh; \
elif [ "$(REQUIRE_ZSH)" = "1" ]; then \
echo "zsh is required for Zsh completion tests" >&2; \
exit 1; \
else \
echo "zsh not found; skipped Zsh completion runtime tests"; \
fi

check: test

# AUR package 安装时将执行此 target
Expand Down Expand Up @@ -276,10 +293,15 @@ build-deb:
clean-deb:
@$(MAKE) -C pkg/deb deb-clean

# 源码安装使用 Zsh 通用的 site-functions 目录;Debian 打包时会将其
# 覆盖为 /usr/share/zsh/vendor-completions,以符合 Debian 的目录约定
ZSH_COMPLETION_DIR ?= /usr/share/zsh/site-functions

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CI的时候用的是另一个目录覆盖了这个变量,可以注释一下二者的区别


install: $(ReleaseMode-Target-Name)
install -D -m 755 $(ReleaseMode-Target-Name) $(DESTDIR)/usr/bin/chsrc
install -D -m 644 doc/chsrc.1 $(DESTDIR)/usr/share/man/man1/chsrc.1
install -D -m 644 tool/completion/bash_completion.sh $(DESTDIR)/usr/share/bash-completion/completions/chsrc
install -D -m 644 tool/completion/_chsrc $(DESTDIR)$(ZSH_COMPLETION_DIR)/_chsrc



Expand All @@ -291,4 +313,4 @@ install: $(ReleaseMode-Target-Name)

.PHONY: all b build bd br bcir d t check c \
build-in-dev-mode build-in-debug-mode build-in-release-mode build-in-ci-release-mode \
debug test test-make-var test-xy test-fw fastcheck test-cli clean install build-deb clean-deb rawstr4c
debug test test-make-var test-xy test-fw test-zsh-completion fastcheck test-cli clean install build-deb clean-deb rawstr4c
15 changes: 14 additions & 1 deletion pkg/deb/deb-installation-test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,20 @@ else
echo "✓ chsrc man page exists"
fi

# Test 3: Test basic functionality
# Test 3: Check if shell completion files exist
if [ ! -f "/usr/share/bash-completion/completions/chsrc" ]; then
echo "ERROR: Bash completion not found at /usr/share/bash-completion/completions/chsrc"
exit 1
fi

if [ ! -f "/usr/share/zsh/vendor-completions/_chsrc" ]; then
echo "ERROR: Zsh completion not found at /usr/share/zsh/vendor-completions/_chsrc"
exit 1
fi

echo "✓ Bash and Zsh completion files exist"

# Test 4: Test basic functionality
echo "Testing basic chsrc functionality..."
if /usr/bin/chsrc help >/dev/null 2>&1; then
echo "✓ command 'chsrc help' works"
Expand Down
4 changes: 3 additions & 1 deletion pkg/deb/debian/rules
Original file line number Diff line number Diff line change
Expand Up @@ -46,4 +46,6 @@ override_dh_auto_build:
@$(MAKE) -C $(Chsrc-Root-Dir) build-in-release-mode

override_dh_auto_install:
@$(MAKE) -C $(Chsrc-Root-Dir) install DESTDIR=$(CURDIR)/debian/chsrc
@$(MAKE) -C $(Chsrc-Root-Dir) install \
DESTDIR=$(CURDIR)/debian/chsrc \
ZSH_COMPLETION_DIR=/usr/share/zsh/vendor-completions
1 change: 1 addition & 0 deletions src/chsrc-main.c
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ chsrc_register_chefs_and_sauciers ()
chef_register_contributor ("@techoc", "Rui Yang", "techoc@foxmail.com", NULL);
chef_register_contributor ("@BingChunMoLi", "BingChunMoLi", "bingchunmoli@bingchunmoli.com", NULL);
chef_register_contributor ("@wcbing", "wcbing", "i@wcbing.top", NULL);
chef_register_contributor ("@swim233", "TheSw1m", "swim853279614@163.com", NULL);
// 该注释下一行的用户 ID 为 Gitee ID
chef_register_contributor ("@hezonglun", "HeZongLun", "hezonglun123456@outlook.com", NULL);
chef_register_contributor ("@Young-Lord", "LY", "ly-niko@qq.com", NULL);
Expand Down
236 changes: 236 additions & 0 deletions test/simulate-zsh-completion.zsh
Original file line number Diff line number Diff line change
@@ -0,0 +1,236 @@
#!/usr/bin/env zsh
# ---------------------------------------------------------------
# SPDX-License-Identifier: GPL-3.0-or-later
# ---------------------------------------------------------------
# Test File : simulate-zsh-completion.zsh
# Test Authors : @swim233
# Contributors : TheSw1m <swim853279614@163.com>
# |
# Created On : <2026-09-08>
# Last Modified : <2026-09-09>
#
# 使用同名函数覆盖 Zsh 补全组件,模拟并测试 _chsrc 的状态机。
# 测试不会读取或修改用户的 Zsh 配置。
#
# $ zsh -f test/simulate-zsh-completion.zsh
# ---------------------------------------------------------------

emulate -L zsh
setopt errexit nounset pipefail extendedglob

typeset test_dir=${0:A:h}
fpath=("${test_dir}/../tool/completion" ${fpath})
autoload -Uz _chsrc

typeset -ga captured

# 模拟 _describe,将符合 PREFIX 的候选项记录到 captured
_describe() {
local array_name=${argv[-1]}
local -a specs
specs=("${(@P)array_name}")
local spec candidate
for spec in ${specs}; do
candidate=${spec%%:*}
if [[ -z ${PREFIX} || ${candidate[1,${#PREFIX}]} == ${PREFIX} ]]; then
captured+=("${candidate}")
fi
done
}

# 模拟 compadd,仅记录 -- 分隔符之后且符合 PREFIX 的候选项
compadd() {
local after_separator=0 arg
for arg in ${argv}; do
if (( after_separator )); then
if [[ -z ${PREFIX} || ${arg[1,${#PREFIX}]} == ${PREFIX} ]]; then
captured+=("${arg}")
fi
elif [[ ${arg} == -- ]]; then
after_separator=1
fi
done
}

# 模拟 compset -P,从 PREFIX 中移除已经输入的固定前缀
compset() {
if [[ $1 == -P ]]; then
PREFIX=${PREFIX#$2}
fi
}

# 测试无需展示补全提示信息
_message() { return 0 }

# 构造 Zsh 补全上下文并执行 _chsrc
capture() {
captured=()
words=("${(@)argv}")
CURRENT=${#words}
PREFIX=${words[CURRENT]}
_chsrc
}

assert_has() {
local expected=$1
# (I) 返回最后一个匹配元素的下标,未匹配时返回 0;
# (e) 使用字符串精确匹配,避免将候选项当作模式解析。
if (( ! ${captured[(Ie)${expected}]} )); then

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这里的 Ie 建议给一下注释是什么意思

print -u2 -- "Expected completion '$expected' in: ${captured[*]}"
return 1
fi
}

assert_lacks() {
local unexpected=$1
# 与 assert_has 相同,使用 (Ie) 取得精确匹配元素的下标。
if (( ${captured[(Ie)${unexpected}]} )); then
print -u2 -- "Unexpected completion '$unexpected' in: ${captured[*]}"
return 1
fi
}

capture chsrc ''
assert_has version
assert_has measure
assert_has reset
assert_has -scope=
assert_lacks mea
assert_lacks rest
assert_lacks -local
assert_lacks -scope
assert_lacks -english
assert_lacks -no-colour
assert_lacks -h
assert_lacks -help
assert_lacks --help
assert_lacks -v
assert_lacks -version
assert_lacks --version

capture chsrc -scope=p
assert_has project
assert_lacks default

typeset -A dispatch_expect=(
help -dry
h -dry
-h -dry
-help -dry
--help -dry
issue -dry
issues -dry
isue -dry
i -dry
version -dry
ver -dry
-v -dry
-version -dry
--version -dry
list mirror
ls mirror
l mirror
measure ruby
mea ruby
m ruby
cesu ruby
ce ruby
c ruby
get ruby
g ruby
set ruby
s ruby
reset ruby
rest ruby
r ruby
)

typeset command expected
for command expected in "${(@kv)dispatch_expect}"; do
capture chsrc "${command}" ''
assert_has "${expected}"
done

capture chsrc set ''
assert_has omarchy
assert_has uv-pypi-index
assert_has uv-python-build
assert_has -scope=
assert_lacks pypi
assert_lacks nodejs-binary

capture chsrc s -dry ''
assert_has ruby

capture chsrc set -local ''
assert_has ruby

capture chsrc set -english ''
assert_has ruby

capture chsrc set -no-colour ''
assert_has ruby

capture chsrc set -scope project ''
assert_has ruby

capture chsrc set -scope ''
assert_has default
assert_has project
assert_has user
assert_has system
assert_lacks ruby

capture chsrc set -scope=
assert_has default
assert_has project
assert_has user
assert_has system

capture chsrc set -scope=p
assert_has project
assert_lacks default
assert_lacks system

capture chsrc set -scope=x
assert_lacks default
assert_lacks project

capture chsrc set -lo
assert_lacks -local

capture chsrc -en -he
assert_lacks -help
assert_lacks help

capture chsrc list ''
assert_has mirror
assert_has dish
assert_has lang
assert_has ware
assert_lacks mirrors
assert_lacks dishes
assert_lacks language
assert_lacks software
assert_has ruby

capture chsrc set ruby ''
assert_has first
assert_has upstream
assert_lacks -dry

capture chsrc set ruby f
assert_has first
assert_lacks upstream

capture chsrc set ruby first ''
assert_lacks first
assert_lacks upstream

capture chsrc set ruby first u
assert_lacks upstream

capture chsrc set ruby -scope=
assert_lacks default

print 'Zsh completion state-machine tests passed.'
Loading