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
10 changes: 10 additions & 0 deletions .github/workflows/ci-linux.yml
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,16 @@ jobs:
run: |
"$MCPP_FRESH" test

- name: Shell completion in bash, zsh, PowerShell and fish
env:
MCPP_REQUIRE_SHELLS: "1"
run: |
set -euo pipefail
sudo apt-get update
sudo apt-get install -y zsh fish
command -v pwsh
MCPP="$MCPP_FRESH" bash tests/e2e/894_shell_completion.sh

# Each package under `modules/` carries its own tests, and they are built
# as that package ALONE -- a configuration the root suite never produces,
# since there every module is linked together. A subsystem that has
Expand Down
6 changes: 6 additions & 0 deletions .github/workflows/ci-windows.yml
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,12 @@ jobs:
export MCPP_VENDORED_XLINGS=$(cygpath -w "$USERPROFILE/.xlings/subos/default/bin/xlings.exe")
"$MCPP_SELF" test

- name: Native PowerShell completion
shell: pwsh
run: |
$env:MCPP = $env:MCPP_FRESH
python tests/scripts/test_shell_completion.py ShellCompletionTests.test_powershell ShellCompletionTests.test_query_is_read_only_and_does_not_execute_partial_commands

# WS8: this row has Visual Studio, so its answer is the "Windows with
# usable MSVC" row of docs/01 and docs/20.
- name: The documented default toolchain is this host's answer
Expand Down
43 changes: 42 additions & 1 deletion docs/01-getting-started.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,48 @@ mcpp --version
> rather than using `source`, and verify the active command with
> `Get-Command mcpp.exe`.

### Shell completion

mcpp provides Tab completion for bash, zsh, PowerShell (`pwsh`) and fish.
Generate all four scripts, or select one shell:

```bash
mcpp self completion
mcpp self completion bash
```

Scripts are written to `<mcpp-home>/config/shell/`. This command does not
initialize a toolchain or access the network. Normal sandbox initialization
also creates the scripts. Repeating the command updates generated scripts;
keep local customizations in the shell's own configuration file.

For the default `~/.mcpp` home, add the corresponding line to the configuration
file below and start a new shell, or execute the line in the current session:

| Shell | Configuration file | Loading command |
|---|---|---|
| bash | `~/.bashrc` | `source ~/.mcpp/config/shell/mcpp.bash` |
| zsh | `${ZDOTDIR:-$HOME}/.zshrc` | `source ~/.mcpp/config/shell/mcpp.zsh` |
| fish | `$XDG_CONFIG_HOME/fish/config.fish`, or `~/.config/fish/config.fish` | `source ~/.mcpp/config/shell/mcpp.fish` |
| PowerShell | `$PROFILE.CurrentUserAllHosts` | `. "$HOME/.mcpp/config/shell/mcpp.ps1"` |

Use the actual mcpp home for a standalone custom prefix or an explicit
`MCPP_HOME`. zsh initializes its completion system if it is not already active;
when the configuration calls `compinit`, load the mcpp script after that call.
In PowerShell, create the profile's parent directory and file if absent.

The standalone installer generates the scripts and appends a loading command
for the shell identified by `SHELL`. Reinstallation does not append the same
command twice. `MCPP_NO_COMPLETION=1` disables this profile change;
`MCPP_NO_PATH=1` independently disables its PATH change. Unknown shells receive
manual loading instructions.

Completion covers commands, nested subcommands, long and short options, and
built-in values such as cache modes, profiles and mirrors. File arguments use
the shell's filename completion. Completion queries do not run project scripts,
install dependencies or access registries. Package names, custom profiles,
target names and registry versions are not dynamically queried.

## Creating a Project

```bash
Expand Down Expand Up @@ -267,4 +309,3 @@ For the differences between the four modes and their artifact layouts, see [10
- Explaining default decisions: `mcpp why [toolchain|runtime|deps]`; host capability checkup: `mcpp self doctor`;
machine-readable resolution manifest: the build artifact `target/<triple>/<fp>/resolution.json`.
- Offline operation: `mcpp --offline` or `MCPP_OFFLINE=1` prevents index refreshes, downloads, and toolchain installation. In a home that has never been used it also skips the first-use sandbox bootstrap (index clone, ninja, patchelf), announces the skip once, and leaves the home un-bootstrapped; commands that need those tools report it.

37 changes: 37 additions & 0 deletions docs/zh/01-getting-started.md
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,43 @@ mcpp --version
> 命令安装,重启 PowerShell 而不是执行 `source`,并用
> `Get-Command mcpp.exe` 确认当前生效的命令。

### Shell 补全

mcpp 为 bash、zsh、PowerShell(`pwsh`)和 fish 提供 Tab 补全。
以下命令生成全部四种脚本,或仅生成指定 shell 的脚本:

```bash
mcpp self completion
mcpp self completion bash
```

脚本写入 `<mcpp-home>/config/shell/`。该命令不初始化工具链,也不访问网络。
正常的沙箱初始化也会生成这些脚本。重复执行会更新生成的脚本;本地自定义配置
放在 shell 自身的配置文件中。

使用默认 `~/.mcpp` home 时,将对应加载语句加入下表中的配置文件并启动新 shell,
或在当前会话直接执行该语句:

| Shell | 配置文件 | 加载语句 |
|---|---|---|
| bash | `~/.bashrc` | `source ~/.mcpp/config/shell/mcpp.bash` |
| zsh | `${ZDOTDIR:-$HOME}/.zshrc` | `source ~/.mcpp/config/shell/mcpp.zsh` |
| fish | `$XDG_CONFIG_HOME/fish/config.fish`,未设置时为 `~/.config/fish/config.fish` | `source ~/.mcpp/config/shell/mcpp.fish` |
| PowerShell | `$PROFILE.CurrentUserAllHosts` | `. "$HOME/.mcpp/config/shell/mcpp.ps1"` |

独立安装的自定义前缀或显式设置的 `MCPP_HOME` 使用实际的 mcpp home 路径。
zsh 的补全系统尚未启用时,脚本会初始化它;配置中已有 `compinit` 调用时,
在该调用之后加载 mcpp 脚本。PowerShell 的 profile 文件及其父目录不存在时,
先创建它们。

独立安装器会生成脚本,并为 `SHELL` 标识的 shell 追加加载语句。重复安装不会
重复追加同一条语句。`MCPP_NO_COMPLETION=1` 关闭这一配置文件修改;
`MCPP_NO_PATH=1` 独立控制 PATH 修改。未识别的 shell 会收到手动加载提示。

补全覆盖命令、嵌套子命令、长短选项,以及缓存模式、构建 profile、镜像等内置值。
文件参数使用 shell 原生文件名补全。补全查询不执行项目脚本、不安装依赖,也不访问
索引。包名、自定义 profile、目标名称和索引中的版本不进行动态查询。

## 创建项目

```bash
Expand Down
82 changes: 68 additions & 14 deletions install.sh
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,11 @@
# MCPP_VERSION — pin a specific version (default: latest)
# MCPP_PREFIX — install root (default: $HOME/.mcpp)
# MCPP_NO_PATH — set to skip shell-rc PATH editing
# MCPP_NO_COMPLETION — set to skip shell-rc completion editing
#
# Layout afterwards (PREFIX = $HOME/.mcpp by default):
# $PREFIX/bin/{mcpp,xlings} ← binary + pinned bundled xlings
# $PREFIX/config/shell/ ← sourceable shell completion scripts
# $PREFIX/registry/ ← seeded on first `mcpp` invocation
# $PREFIX/... ← mcpp's full self-contained tree
#
Expand All @@ -21,6 +23,8 @@ set -euo pipefail
REPO="mcpp-community/mcpp"
VERSION="${MCPP_VERSION:-latest}"
PREFIX="${MCPP_PREFIX:-$HOME/.mcpp}"
shell_name="${SHELL:-}"
shell_name="${shell_name##*/}"

# ---- platform detection ---------------------------------------------------
# OS+arch → release asset platform tag. Linux reports the arch as aarch64;
Expand Down Expand Up @@ -126,22 +130,46 @@ mkdir -p "$PREFIX"
echo ":: Extracting to $PREFIX"
tar -xzf "$WORK/mcpp.tar.gz" -C "$PREFIX" --strip-components=1

# Older pinned releases predate completion. Probe help without initialization.
completion_available=0
if "$PREFIX/bin/mcpp" self --help 2>/dev/null | grep 'completion' >/dev/null; then
MCPP_HOME="$PREFIX" "$PREFIX/bin/mcpp" self completion
completion_available=1
fi

# ---- PATH integration -----------------------------------------------------
if [[ -z "${MCPP_NO_PATH:-}" ]]; then
rc=""
case "${SHELL##*/}" in
bash) rc="$HOME/.bashrc" ;;
zsh) rc="${ZDOTDIR:-$HOME}/.zshrc" ;;
fish) rc="$HOME/.config/fish/config.fish" ;;
rc=""
case "$shell_name" in
bash) rc="$HOME/.bashrc" ;;
zsh) rc="${ZDOTDIR:-$HOME}/.zshrc" ;;
fish) rc="${XDG_CONFIG_HOME:-$HOME/.config}/fish/config.fish" ;;
pwsh)
if command -v pwsh >/dev/null 2>&1; then
rc=$(pwsh -NoProfile -Command '$PROFILE.CurrentUserAllHosts')
fi ;;
esac
shell_quote() {
local value="$1"
case "$shell_name" in
pwsh) value="${value//\'/\'\'}" ;;
fish)
value="${value//\\/\\\\}"
value="${value//\'/\\\'}" ;;
*) value="${value//\'/\'\\\'\'}" ;;
esac
printf "'%s'" "$value"
}
if [[ -z "${MCPP_NO_PATH:-}" ]]; then
if [[ -n "$rc" ]]; then
if [[ "${SHELL##*/}" == "fish" ]]; then
line="set -gx PATH \"$PREFIX/bin\" \$PATH"
else
line="export PATH=\"$PREFIX/bin:\$PATH\""
fi
quoted_bin=$(shell_quote "$PREFIX/bin")
case "$shell_name" in
fish) line="set -gx PATH $quoted_bin \$PATH" ;;
pwsh) line="\$env:PATH = $quoted_bin + [IO.Path]::PathSeparator + \$env:PATH" ;;
*) line="export PATH=$quoted_bin:\"\$PATH\"" ;;
esac
mkdir -p "$(dirname "$rc")"
if ! grep -Fqs "$PREFIX/bin" "$rc" 2>/dev/null; then
if ! grep -Fqx "$line" "$rc" 2>/dev/null \
&& ! grep -Fqs "$PREFIX/bin" "$rc" 2>/dev/null; then
printf '\n# mcpp\n%s\n' "$line" >> "$rc"
echo ":: Added $PREFIX/bin to PATH via $rc"
else
Expand All @@ -153,13 +181,39 @@ if [[ -z "${MCPP_NO_PATH:-}" ]]; then
fi
fi

# ---- completion integration ----------------------------------------------
if [[ -z "${MCPP_NO_COMPLETION:-}" && "$completion_available" == 1 ]]; then
if [[ -n "$rc" ]]; then
extension="$shell_name"
[[ "$shell_name" == pwsh ]] && extension=ps1
script="$PREFIX/config/shell/mcpp.$extension"
quoted_script=$(shell_quote "$script")
if [[ "$shell_name" == pwsh ]]; then
line="if (Test-Path -LiteralPath $quoted_script) { . $quoted_script }"
elif [[ "$shell_name" == fish ]]; then
line="test -f $quoted_script; and source $quoted_script"
else
line="[ ! -f $quoted_script ] || source $quoted_script"
fi
mkdir -p "$(dirname "$rc")"
if ! grep -Fqx "$line" "$rc" 2>/dev/null; then
printf '\n# mcpp completion\n%s\n' "$line" >> "$rc"
echo ":: Enabled completion via $rc"
fi
else
echo ":: Completion scripts: $PREFIX/config/shell/ (source the script for your shell)"
fi
fi

# ---- verify install -------------------------------------------------------
echo
"$PREFIX/bin/mcpp" --version
echo
echo "✓ mcpp installed at $PREFIX"
if [[ -n "${rc:-}" ]]; then
echo " Open a new shell (or 'source $rc') and run: mcpp --help"
if [[ -n "${rc:-}" && -f "$rc" ]]; then
load_command="source $(shell_quote "$rc")"
[[ "$shell_name" == pwsh ]] && load_command=". $(shell_quote "$rc")"
echo " Open a new shell (or $load_command) and run: mcpp --help"
else
echo " Add $PREFIX/bin to your PATH, then run: mcpp --help"
fi
Loading
Loading