linthis 0.17.1

A fast, cross-platform multi-language linter and formatter
Documentation
# linthis init 支持 pre-commit hooks 集成设计

## 需求

在执行 `linthis init` 时,可以同时创建 pre-commit hooks 配置文件,简化项目初始化流程。

## 设计方案对比

### 方案 1: 添加 --hook 标志(推荐)

```bash
# 只创建配置文件(当前行为,向后兼容)
linthis init
linthis init -g

# 创建配置文件 + hooks 配置
linthis init --hook prek
linthis init --hook pre-commit
linthis init --hook git
linthis init -g --hook prek
```

**优点**:
- 简单直观
- 支持多种 hook 管理器
- 向后兼容(不指定 --hook 时行为不变)
- 灵活,可以明确选择工具

**缺点**:
- 需要记住三种工具名称

**CLI 定义**:
```rust
Init {
    /// Create global configuration (~/.linthis/config.toml)
    #[arg(short, long)]
    global: bool,

    /// Initialize pre-commit hooks configuration
    #[arg(long, value_name = "TOOL")]
    hook: Option<HookTool>,
}

#[derive(Clone, Debug, ValueEnum)]
enum HookTool {
    /// Create .pre-commit-config.yaml for prek (recommended, faster)
    Prek,
    /// Create .pre-commit-config.yaml for pre-commit
    PreCommit,
    /// Create .git/hooks/pre-commit script
    Git,
}
```

---

### 方案 2: 添加 --with-hooks 布尔标志

```bash
# 创建配置文件 + hooks(默认 prek)
linthis init --with-hooks
linthis init --hooks  # 简写

# 不创建 hooks(默认)
linthis init
```

**优点**:
- 最简单,推荐默认工具(prek)
- 降低选择成本

**缺点**:
- 不够灵活,无法选择工具
- 如果用户想用 pre-commit 或 git hook 就需要额外参数

**扩展方案 2A**:
```bash
linthis init --with-hooks       # 默认 prek
linthis init --with-hooks=prek
linthis init --with-hooks=pre-commit
linthis init --with-hooks=git
```

---

### 方案 3: 添加 hooks 子命令

```bash
# 只创建配置文件
linthis init

# 只创建 hooks
linthis init hooks
linthis init hooks --tool prek
linthis init hooks --tool pre-commit

# 不支持一条命令同时创建
```

**优点**:
- 职责分离,语义清晰
- 可以单独初始化 hooks

**缺点**:
- 命令层级深
- 不够便捷,需要两条命令

---

### 方案 4: 交互式提示

```bash
linthis init
# Output:
# ✓ Created .linthis.toml
#
# Would you like to set up pre-commit hooks? (y/n)
# > y
#
# Choose a hook manager:
#   1. prek (recommended, faster)
#   2. pre-commit (standard)
#   3. git hook (simple)
# > 1
#
# ✓ Created .pre-commit-config.yaml
```

**优点**:
- 用户友好,引导式
- 降低学习成本

**缺点**:
- 不适合脚本化/CI 环境
- 需要处理非交互模式

**改进**:支持 `--non-interactive` 或通过环境变量禁用

---

## 推荐方案:方案 1 + 交互式提示

### 命令行接口

```bash
# 非交互模式(明确指定)
linthis init --hook prek          # 创建 .linthis.toml + .pre-commit-config.yaml
linthis init --hook pre-commit    # 创建 .linthis.toml + .pre-commit-config.yaml
linthis init --hook git           # 创建 .linthis.toml + .git/hooks/pre-commit
linthis init                      # 只创建 .linthis.toml(向后兼容)

# 全局配置
linthis init -g --hook prek       # 创建全局配置,hooks 仅在项目级别

# 交互模式(推荐新用户)
linthis init --interactive        # 或 -i
# 提示用户选择是否创建 hooks 及工具类型
```

### 实现细节

#### 1. CLI 参数定义

```rust
/// Initialize configuration file
Init {
    /// Create global configuration (~/.linthis/config.toml)
    #[arg(short, long)]
    global: bool,

    /// Initialize pre-commit hooks (prek, pre-commit, or git)
    #[arg(long, value_name = "TOOL")]
    hook: Option<HookTool>,

    /// Interactive mode - prompt for hooks setup
    #[arg(short, long)]
    interactive: bool,
}

#[derive(Clone, Debug, ValueEnum)]
#[value(rename_all = "kebab-case")]
enum HookTool {
    /// Prek (Rust-based, faster)
    Prek,
    /// Pre-commit (Python-based, standard)
    PreCommit,
    /// Traditional git hook
    Git,
}
```

#### 2. 创建的文件

**prek / pre-commit**:
```yaml
# .pre-commit-config.yaml
repos:
  - repo: local
    hooks:
      - id: linthis
        name: linthis
        entry: linthis --staged --check-only
        language: system
        pass_filenames: false
```

**git**:
```bash
#!/bin/sh
# .git/hooks/pre-commit
linthis --staged --check-only
```

#### 3. 执行流程

```
linthis init [--global] [--hook TOOL] [--interactive]
  |
  ├─> 创建配置文件 (.linthis.toml 或 ~/.linthis/config.toml)
  |
  ├─> if --hook specified:
  |     └─> 创建对应的 hooks 配置文件
  |
  ├─> else if --interactive:
  |     ├─> 询问: "Set up pre-commit hooks? (y/n)"
  |     └─> if yes:
  |           ├─> 显示选项 (prek/pre-commit/git)
  |           └─> 创建对应的 hooks 配置文件
  |
  └─> 输出成功信息
```

#### 4. 输出示例

```bash
$ linthis init --hook prek
✓ Created .linthis.toml
✓ Created .pre-commit-config.yaml (prek/pre-commit compatible)

Next steps:
  1. Install prek: cargo install prek
  2. Set up hooks: prek install

Or use pre-commit:
  1. Install pre-commit: pip install pre-commit
  2. Set up hooks: pre-commit install
```

```bash
$ linthis init --hook git
✓ Created .linthis.toml
✓ Created .git/hooks/pre-commit

Next steps:
  Make sure the hook is executable:
    chmod +x .git/hooks/pre-commit
```

#### 5. 特殊情况处理

- **全局配置 + hooks**: hooks 只在项目级别有意义,如果 `--global --hook` 同时指定,给出警告并忽略 hooks
  ```bash
  $ linthis init -g --hook prek
  Warning: Hooks can only be configured at project level, ignoring --hook flag
   Created /Users/user/.linthis/config.toml
  ```

- **文件已存在**:
  ```bash
  $ linthis init --hook prek
   Created .linthis.toml
  Warning: .pre-commit-config.yaml already exists, skipping
  ```

- **不在 git 仓库中使用 --hook git**:
  ```bash
  $ linthis init --hook git
   Created .linthis.toml
  Error: Not in a git repository, cannot create .git/hooks/pre-commit
  ```

---

## 实现计划

### 阶段 1: 基础功能(MVP)

1. ✅ 定义 CLI 参数(`--hook` 标志)
2. ✅ 实现 `HookTool` 枚举
3. ✅ 实现创建 `.pre-commit-config.yaml` 的逻辑
4. ✅ 实现创建 `.git/hooks/pre-commit` 的逻辑
5. ✅ 添加相应的输出和提示信息
6. ✅ 测试各种场景

### 阶段 2: 增强功能

1. ⬜ 添加 `--interactive` 模式
2. ⬜ 改进错误处理和用户提示
3. ⬜ 添加单元测试

### 阶段 3: 文档

1. ⬜ 更新 README.md
2. ⬜ 更新命令行帮助文本
3. ⬜ 添加示例和最佳实践

---

## 用户故事

### 故事 1: Rust 开发者(推荐路径)

```bash
# 初始化项目配置和 prek hooks
linthis init --hook prek

# 安装 prek
cargo install prek

# 设置 hooks
prek install

# 完成!
```

### 故事 2: Python 开发者

```bash
# 初始化项目配置和 pre-commit hooks
linthis init --hook pre-commit

# 安装 pre-commit
pip install pre-commit

# 设置 hooks
pre-commit install
```

### 故事 3: 简单项目

```bash
# 只用传统 git hook,不需要额外工具
linthis init --hook git

# 完成!hook 已设置
```

### 故事 4: 新手用户

```bash
# 交互式引导
linthis init --interactive

# 系统会询问并引导设置
```

---

## 优势

1. **便捷**: 一条命令完成配置文件和 hooks 的初始化
2. **灵活**: 支持三种主流 hook 管理方式
3. **向后兼容**: 不指定 --hook 时行为不变
4. **推荐最佳实践**: 默认推荐 prek(性能最好)
5. **新手友好**: 提供交互式模式
6. **CI 友好**: 支持非交互模式

---

## 待讨论问题

1. 是否需要支持同时安装多个 hook 管理器?(可能不需要)
2. 是否需要 `linthis init --hook auto` 自动检测已安装的工具?
3. 交互模式是否应该是默认行为?(可能会影响脚本化使用)
4. 是否需要 `linthis hooks` 子命令用于后续管理?