Skip to content

Commit 7a36b26

Browse files
feat: help, utf8 supports
1 parent 1589461 commit 7a36b26

46 files changed

Lines changed: 1777 additions & 99 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

CMakeLists.txt

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,22 @@ include(cmake/third_party/CPM.cmake)
1515
# ── Compiler flags ────────────────────────────────────────────
1616
include(cmake/compile/CompilerFlag.cmake)
1717

18-
# ── Applet sources (shared between main exe and tests) ────────
19-
file(GLOB_RECURSE CFBOX_APPLET_SOURCES CONFIGURE_DEPENDS src/applets/*.cpp)
18+
# ── Applet configuration ─────────────────────────────────────
19+
include(cmake/Config.cmake)
20+
21+
# ── Applet sources (conditional on config) ───────────────────
22+
set(CFBOX_APPLET_SOURCES)
23+
foreach(applet IN LISTS CFBOX_APPLETS)
24+
string(TOUPPER "${applet}" APPLET_UPPER)
25+
if(CFBOX_ENABLE_${APPLET_UPPER})
26+
list(APPEND CFBOX_APPLET_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src/applets/${applet}.cpp)
27+
endif()
28+
endforeach()
2029

2130
# ── Main executable ───────────────────────────────────────────
2231
add_executable(cfbox src/main.cpp ${CFBOX_APPLET_SOURCES})
2332
target_include_directories(cfbox PUBLIC include)
33+
target_include_directories(cfbox PUBLIC ${CMAKE_CURRENT_BINARY_DIR}/include)
2434
target_link_libraries(cfbox PRIVATE cfbox_compiler_flags)
2535

2636
# ── GTest via CPM (FetchContent) ──────────────────────────────
@@ -39,6 +49,7 @@ if(GTest_ADDED)
3949
if(CFBOX_TEST_SOURCES)
4050
add_executable(cfbox_tests ${CFBOX_TEST_SOURCES} ${CFBOX_APPLET_SOURCES})
4151
target_include_directories(cfbox_tests PUBLIC include)
52+
target_include_directories(cfbox_tests PUBLIC ${CMAKE_CURRENT_BINARY_DIR}/include)
4253
target_link_libraries(cfbox_tests PRIVATE
4354
cfbox_compiler_flags
4455
GTest::gtest_main

CONTRIBUTING.md

Lines changed: 31 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -31,10 +31,10 @@ Release builds use `-O2` by default and enable LTO. For size-optimized builds, a
3131
## Running Tests
3232

3333
```bash
34-
# Unit tests (108 GTest cases)
34+
# Unit tests (149 GTest cases)
3535
ctest --test-dir build --output-on-failure
3636

37-
# Integration tests (16 shell scripts comparing against GNU coreutils)
37+
# Integration tests (17 shell scripts comparing against GNU coreutils)
3838
bash tests/integration/run_all.sh
3939
```
4040

@@ -138,12 +138,36 @@ The CI pipeline ([ci.yml](.github/workflows/ci.yml)) runs on every push/PR to `m
138138

139139
1. Create `src/applets/<name>.cpp` with signature `auto <name>_main(int argc, char* argv[]) -> int`.
140140
- Add a comment header listing supported flags and known differences from GNU.
141-
2. Declare the function in [applets.hpp](include/cfbox/applets.hpp).
142-
3. Add one entry to `APPLET_REGISTRY` in [applets.hpp](include/cfbox/applets.hpp).
143-
4. Add GTest unit tests in `tests/unit/test_<name>.cpp` (see [test_capture.hpp](tests/unit/test_capture.hpp) for stdout capture and `TempDir` utilities).
144-
5. Add shell integration tests in `tests/integration/test_<name>.sh` following the pattern in existing scripts.
141+
- Add a `constexpr cfbox::help::HelpEntry HELP` constant in the anonymous namespace.
142+
- Handle `--help` / `--version` right after `args::parse()`:
143+
```cpp
144+
if (parsed.has_long("help")) { cfbox::help::print_help(HELP); return 0; }
145+
if (parsed.has_long("version")) { cfbox::help::print_version(HELP); return 0; }
146+
```
147+
2. Declare the function in [applets.hpp](include/cfbox/applets.hpp), guarded by `#if CFBOX_ENABLE_<UPPER>`.
148+
3. Add one entry to `APPLET_REGISTRY` in [applets.hpp](include/cfbox/applets.hpp), also guarded by `#if CFBOX_ENABLE_<UPPER>`.
149+
4. Add the applet name to the `CFBOX_APPLETS` list in [cmake/Config.cmake](cmake/Config.cmake).
150+
5. Add a `#cmakedefine01 CFBOX_ENABLE_<UPPER>` line to [include/cfbox/applet_config.hpp.in](include/cfbox/applet_config.hpp.in).
151+
6. Add GTest unit tests in `tests/unit/test_<name>.cpp` (see [test_capture.hpp](tests/unit/test_capture.hpp) for stdout capture and `TempDir` utilities). Guard the test file with `#if CFBOX_ENABLE_<UPPER>`.
152+
7. Add shell integration tests in `tests/integration/test_<name>.sh` following the pattern in existing scripts.
145153

146-
> **Note:** The `init` applet is special — it runs as PID 1 in QEMU system-mode tests. Regular applets should not need special PID 1 handling.
154+
> **Note:** The `init` applet is special — it runs as PID 1 in QEMU system-mode tests and uses manual `argv` scanning instead of `args::parse()`. Regular applets should not need special PID 1 handling.
155+
156+
## Build Configuration
157+
158+
CFBox supports per-applet configuration via CMake options:
159+
160+
```bash
161+
# Disable individual applets
162+
cmake -DCFBOX_ENABLE_GREP=OFF -DCFBOX_ENABLE_SED=OFF ..
163+
164+
# Use preset profiles
165+
cmake -DCFBOX_PROFILE=minimal .. # Only core file operations
166+
cmake -DCFBOX_PROFILE=embedded .. # Everything except optional text processing
167+
cmake -DCFBOX_PROFILE=desktop .. # All applets enabled (default)
168+
```
169+
170+
Available profiles: `minimal` (echo, cat, ls, cp, mv, rm, mkdir, grep), `embedded` (all except sort/uniq/sed), `desktop`/`full` (all enabled).
147171

148172
## Submitting Changes
149173

README.en.md

Lines changed: 30 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,12 @@ A minimalist BusyBox alternative written in modern C++23.
88
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
99
[![C++23](https://img.shields.io/badge/C++23-00599C?logo=cplusplus)](https://en.cppreference.com/w/cpp/23)
1010
[![CMake](https://img.shields.io/badge/CMake-3.26+-064F8C?logo=cmake)](https://cmake.org/)
11-
[![Tests](https://img.shields.io/badge/Tests-124_passing-brightgreen)](tests/)
11+
[![Tests](https://img.shields.io/badge/Tests-149_passing-brightgreen)](tests/)
1212
[![Applets](https://img.shields.io/badge/Applets-17-brightgreen)](src/applets/)
1313

1414
## Overview
1515

16-
CFBox is a single-executable Unix utility collection distributed via symbolic links. All development is complete — 17 applets implemented and tested, with a CI pipeline covering native builds, cross-compilation, and QEMU user/system-mode testing across 5 stages.
16+
CFBox is a single-executable Unix utility collection distributed via symbolic links. 17 applets implemented and tested, with a CI pipeline covering native builds, cross-compilation, and QEMU user/system-mode testing across 5 stages. Features configurable CMake builds (per-applet toggles), GNU-style long options, and colored help output.
1717

1818
**Design philosophy:** Simplicity first — Modern C++ (`std::expected`) — Embedded-friendly (cross-compilation, static linking)
1919

@@ -25,8 +25,8 @@ cmake -B build
2525
cmake --build build
2626

2727
# Test
28-
ctest --test-dir build --output-on-failure # 108 GTest unit tests
29-
bash tests/integration/run_all.sh # 16 integration test scripts
28+
ctest --test-dir build --output-on-failure # 149 GTest unit tests
29+
bash tests/integration/run_all.sh # 17 integration test scripts
3030

3131
# Run via subcommand
3232
./build/cfbox echo "Hello, World!"
@@ -42,7 +42,7 @@ echo "Hello, World!" # now calls cfbox via symlink
4242

4343
| Applet | Supported Flags / Features |
4444
|--------|----------------------------|
45-
| `echo` | `-n` (no trailing newline), `-e` (interpret escape sequences) |
45+
| `echo` | `-n` (no trailing newline), `-e` (interpret escape sequences), all applets support `--help` / `--version` |
4646
| `printf` | Format strings (`%s` `%d` `%f` `%c` `%%`), format reuse |
4747
| `cat` | `-n` (number lines), `-b` (number non-blank), `-A` (show non-printing), stdin passthrough |
4848
| `head` | `-n N` (first N lines), `-c N` (first N bytes), multi-file headers |
@@ -57,16 +57,16 @@ echo "Hello, World!" # now calls cfbox via symlink
5757

5858
| Applet | Supported Flags / Features |
5959
|--------|----------------------------|
60-
| `mkdir` | `-p` (create parents), `-m MODE` (permissions) |
61-
| `rm` | `-r` (recursive), `-f` (force), `-i` (interactive), `/` safety check |
62-
| `cp` | `-r` (recursive), `-p` (preserve permissions), multi-file to directory |
60+
| `mkdir` | `-p`/`--parents` (create parents), `-m`/`--mode MODE` (permissions) |
61+
| `rm` | `-r`/`--recursive` (recursive), `-f`/`--force` (force), `-i` (interactive), `/` safety check |
62+
| `cp` | `-r`/`--recursive` (recursive), `-p`/`--preserve` (preserve permissions), multi-file to directory |
6363
| `mv` | `-f` (force overwrite), cross-filesystem fallback (copy + remove) |
6464

6565
### Directory & Search
6666

6767
| Applet | Supported Flags / Features |
6868
|--------|----------------------------|
69-
| `ls` | `-a` (show hidden), `-l` (long format), `-h` (human-readable sizes) |
69+
| `ls` | `-a`/`--all` (show hidden), `-l`/`--long` (long format), `-h`/`--human-readable` (human-readable sizes) |
7070
| `find` | `-name PATTERN` (glob), `-type [f\|d\|l]`, `-maxdepth N`, `-exec CMD {} ;` |
7171

7272
### System
@@ -97,22 +97,30 @@ echo "Hello, World!" # now calls cfbox via symlink
9797
cfbox/
9898
├── CMakeLists.txt
9999
├── cmake/
100-
│ ├── compile/CompilerFlag.cmake # Compiler warnings & optimization flags
101-
│ ├── third_party/CPM.cmake # CPM dependency manager
102-
│ └── toolchain/ # Cross-compilation toolchains
100+
│ ├── Config.cmake # Per-applet configuration (CFBOX_ENABLE_xxx options)
101+
│ ├── compile/CompilerFlag.cmake # Compiler warnings & optimization flags
102+
│ ├── third_party/CPM.cmake # CPM dependency manager
103+
│ └── toolchain/ # Cross-compilation toolchains
103104
├── configs/
104-
│ └── qemu-virt-aarch64.config # Minimal QEMU aarch64 kernel config
105-
├── document/ # Detailed documentation
106-
├── include/cfbox/ # Public headers
105+
│ └── qemu-virt-aarch64.config # Minimal QEMU aarch64 kernel config
106+
├── document/ # Detailed documentation
107+
├── include/cfbox/
108+
│ ├── applet_config.hpp.in # CMake-generated config (version + enable flags)
109+
│ ├── applet.hpp / applets.hpp # Registry & dispatch
110+
│ ├── args.hpp # Short + long option argument parser
111+
│ ├── help.hpp # --help / --version help system
112+
│ ├── term.hpp # ANSI colored output (NO_COLOR support)
113+
│ ├── utf8.hpp # Unicode-aware width/count utilities
114+
│ └── ... # error.hpp, io.hpp, fs_util.hpp, escape.hpp
107115
├── src/
108-
│ ├── main.cpp # Dispatch entry
109-
│ └── applets/ # 17 command implementations
116+
│ ├── main.cpp # Dispatch entry
117+
│ └── applets/ # 17 command implementations
110118
├── tests/
111-
│ ├── unit/ # GTest unit tests (108 cases)
112-
│ └── integration/ # Shell integration tests (16 scripts)
113-
├── scripts/ # Build, test, install scripts
114-
├── .github/workflows/ci.yml # CI pipeline
115-
└── CONTRIBUTING.md # Contributing guide
119+
│ ├── unit/ # GTest unit tests (149 cases)
120+
│ └── integration/ # Shell integration tests (17 scripts)
121+
├── scripts/ # Build, test, install scripts
122+
├── .github/workflows/ci.yml # CI pipeline
123+
└── CONTRIBUTING.md # Contributing guide
116124
```
117125

118126
## Contributing

README.md

Lines changed: 30 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,12 @@
88
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
99
[![C++23](https://img.shields.io/badge/C++23-00599C?logo=cplusplus)](https://en.cppreference.com/w/cpp/23)
1010
[![CMake](https://img.shields.io/badge/CMake-3.26+-064F8C?logo=cmake)](https://cmake.org/)
11-
[![Tests](https://img.shields.io/badge/Tests-124_passing-brightgreen)](tests/)
11+
[![Tests](https://img.shields.io/badge/Tests-149_passing-brightgreen)](tests/)
1212
[![Applets](https://img.shields.io/badge/Applets-17-brightgreen)](src/applets/)
1313

1414
## 概述
1515

16-
CFBox 是一个单一可执行文件的 Unix 工具集,通过符号链接分发。全部开发已完成,17 个 applet 已实现并通过测试,CI 流水线覆盖原生构建、交叉编译、QEMU 用户/系统模式 5 种测试场景。
16+
CFBox 是一个单一可执行文件的 Unix 工具集,通过符号链接分发。17 个 applet 已实现并通过测试,CI 流水线覆盖原生构建、交叉编译、QEMU 用户/系统模式 5 种测试场景。支持 CMake 配置化构建(per-applet 开关)、GNU 风格长选项、彩色帮助输出
1717

1818
**设计理念:** 简洁优先 — 现代C++(`std::expected`) — 嵌入式友好(交叉编译、静态链接)
1919

@@ -25,8 +25,8 @@ cmake -B build
2525
cmake --build build
2626

2727
# 测试
28-
ctest --test-dir build --output-on-failure # 108 个 GTest 单元测试
29-
bash tests/integration/run_all.sh # 16 套集成测试脚本
28+
ctest --test-dir build --output-on-failure # 149 个 GTest 单元测试
29+
bash tests/integration/run_all.sh # 17 套集成测试脚本
3030

3131
# 通过子命令运行
3232
./build/cfbox echo "Hello, World!"
@@ -42,7 +42,7 @@ echo "Hello, World!" # 通过符号链接调用 cfbox
4242

4343
| 命令 | 支持的标志 / 功能 |
4444
|------|-------------------|
45-
| `echo` | `-n`(不换行),`-e`(解释转义序列) |
45+
| `echo` | `-n`(不换行),`-e`(解释转义序列),所有 applet 支持 `--help` / `--version` |
4646
| `printf` | 格式字符串(`%s` `%d` `%f` `%c` `%%`),格式重用 |
4747
| `cat` | `-n`(显示行号),`-b`(非空行编号),`-A`(显示不可打印字符),stdin 透传 |
4848
| `head` | `-n N`(前 N 行),`-c N`(前 N 字节),多文件头部 |
@@ -57,16 +57,16 @@ echo "Hello, World!" # 通过符号链接调用 cfbox
5757

5858
| 命令 | 支持的标志 / 功能 |
5959
|------|-------------------|
60-
| `mkdir` | `-p`(递归创建父目录),`-m MODE`(设置权限) |
61-
| `rm` | `-r`(递归删除),`-f`(强制),`-i`(交互确认),`/` 安全检查 |
62-
| `cp` | `-r`(递归复制),`-p`(保留权限),多文件到目录 |
60+
| `mkdir` | `-p`/`--parents`(递归创建父目录),`-m`/`--mode MODE`(设置权限) |
61+
| `rm` | `-r`/`--recursive`(递归删除),`-f`/`--force`(强制),`-i`(交互确认),`/` 安全检查 |
62+
| `cp` | `-r`/`--recursive`(递归复制),`-p`/`--preserve`(保留权限),多文件到目录 |
6363
| `mv` | `-f`(强制覆盖),跨文件系统回退(复制 + 删除) |
6464

6565
### 目录与搜索
6666

6767
| 命令 | 支持的标志 / 功能 |
6868
|------|-------------------|
69-
| `ls` | `-a`(显示隐藏文件),`-l`(长格式),`-h`(人类可读大小) |
69+
| `ls` | `-a`/`--all`(显示隐藏文件),`-l`/`--long`(长格式),`-h`/`--human-readable`(人类可读大小) |
7070
| `find` | `-name 模式`(glob 匹配),`-type [f\|d\|l]``-maxdepth N``-exec 命令 {} ;` |
7171

7272
### 系统
@@ -97,22 +97,30 @@ echo "Hello, World!" # 通过符号链接调用 cfbox
9797
cfbox/
9898
├── CMakeLists.txt
9999
├── cmake/
100-
│ ├── compile/CompilerFlag.cmake # 编译器警告与优化标志
101-
│ ├── third_party/CPM.cmake # CPM 依赖管理
102-
│ └── toolchain/ # 交叉编译工具链
100+
│ ├── Config.cmake # Per-applet 配置(CFBOX_ENABLE_xxx 选项)
101+
│ ├── compile/CompilerFlag.cmake # 编译器警告与优化标志
102+
│ ├── third_party/CPM.cmake # CPM 依赖管理
103+
│ └── toolchain/ # 交叉编译工具链
103104
├── configs/
104-
│ └── qemu-virt-aarch64.config # QEMU aarch64 最小内核配置
105-
├── document/ # 详细文档
106-
├── include/cfbox/ # 公共头文件
105+
│ └── qemu-virt-aarch64.config # QEMU aarch64 最小内核配置
106+
├── document/ # 详细文档
107+
├── include/cfbox/
108+
│ ├── applet_config.hpp.in # CMake 生成的配置(版本号 + 启用开关)
109+
│ ├── applet.hpp / applets.hpp # 注册表与分发
110+
│ ├── args.hpp # 短选项 + 长选项参数解析器
111+
│ ├── help.hpp # --help / --version 帮助系统
112+
│ ├── term.hpp # ANSI 彩色输出(NO_COLOR 支持)
113+
│ ├── utf8.hpp # Unicode 感知的宽度/计数工具
114+
│ └── ... # error.hpp, io.hpp, fs_util.hpp, escape.hpp
107115
├── src/
108-
│ ├── main.cpp # 分发入口
109-
│ └── applets/ # 17 个命令实现
116+
│ ├── main.cpp # 分发入口
117+
│ └── applets/ # 17 个命令实现
110118
├── tests/
111-
│ ├── unit/ # GTest 单元测试(108 个用例)
112-
│ └── integration/ # Shell 集成测试(16 个脚本)
113-
├── scripts/ # 构建、测试、安装脚本
114-
├── .github/workflows/ci.yml # CI 流水线
115-
└── CONTRIBUTING.md # 贡献指南
119+
│ ├── unit/ # GTest 单元测试(149 个用例)
120+
│ └── integration/ # Shell 集成测试(17 个脚本)
121+
├── scripts/ # 构建、测试、安装脚本
122+
├── .github/workflows/ci.yml # CI 流水线
123+
└── CONTRIBUTING.md # 贡献指南
116124
```
117125

118126
## 贡献

0 commit comments

Comments
 (0)