# cxr

`cxr` は、YAML テンプレートからディレクトリ構成やファイルを生成する Rust 製 CLI です。

[English](./README.md)

## できること

- 利用可能なテンプレートを一覧表示する
- テンプレートのひな形を作成する
- テンプレート内の変数を置き換えてファイル群を生成する

## ビルド

```bash
cargo build
```

## 使い方

```bash
cargo run -- list
cargo run -- list --tag web
cargo run -- list --search starter
cargo run -- new <name>
cargo run -- remove <name>
cargo run -- fzf
cargo run -- lint <template> [--all]
cargo run -- <template> [-v VAR=VALUE ...] [-o OUTPUT] [--dry-run] [--force|--backup|--skip]
```

インストール済みなら `cargo run --` の代わりに `cxr` を使えます。

### コマンド

- `list` : 利用可能なテンプレートを表示（`--tag` / `--search` 対応）
- `new <name>` : `~/.config/cxr/` または `$XDG_CONFIG_HOME/cxr/` に `<name>.yaml` を作成
- `remove <name>`（`delete <name>`）: 既存のテンプレートを削除
- `fzf` : fzf でテンプレートを選択して生成
- `lint <template>`（`--all`）: 生成せずにテンプレートを検証（または全テンプレートを検証）
- `<template>` : 指定したテンプレートからファイルを生成

## テンプレートの置き場所

テンプレートは次のいずれかに保存されます。

- `$XDG_CONFIG_HOME/cxr/`
- `~/.config/cxr/`

ファイル名は `<template>.yaml` です。

## テンプレート形式

テンプレートは YAML で定義します。

```yaml
name: "default template"
description: "A default template generated by cxr"
tags:
  - starter
variables:
  - project_name
  - author: "John Doe"
pre_hook: "echo pre {{ project_name }}"
post_hook: "echo post {{ project_name }}"
items:
  - type: "directory"
    name: "src"
    when: "project_name"
    items:
      - type: "file"
        name: "main.py"
        content: |
          def main():
              print("Hello, {{ project_name }}!")
```

### 変数

- `- project_name` のように値なしで定義すると、生成時に入力を求められます
- `- author: "John Doe"` のように書くと、デフォルト値付きで入力できます
- `{{ project_name }}` のようなプレースホルダは、ファイル名・ディレクトリ名・ファイル内容で置換されます
- `when` を付けると条件が false の場合にアイテムをスキップできます。対応形式: `flag`, `!flag`, `name == value`, `name != value`
- `extends` を使うと、別テンプレートの変数・タグ・フック・アイテムを継承できます
- `tags` は `cxr list --tag <tag>` での絞り込みに使えます

### アイテム

- `type: directory` : ディレクトリを作成
- `type: file` : ファイルを作成

## 既存ファイルの扱い

同名のディレクトリやファイルがある場合は、上書きするかどうかを確認します。

## 上書き戦略

- `--force`: 既存ファイルを確認なしで上書き
- `--backup`: 既存ファイルを `.bak` に退避してから書き込み（既存の `.bak` は上書き）
- `--skip`: 既存ファイルを確認なしでスキップ

ディレクトリは再利用され、上書き戦略はファイルにのみ適用されます。`--backup` の場合は既存ディレクトリを `.bak` に退避してから新しく作成します。

## ドライラン

`--dry-run`（`-n`）を付けると、実際には書き込まずに生成結果だけを表示します。既存チェックは行い、上書き対象は「Would overwrite」と表示します。

## フック

テンプレート YAML に `pre_hook` / `post_hook` を設定すると、生成の前後でコマンドを実行できます。実行時のカレントは出力先ディレクトリで、`{{ var }}` 置換に対応します。フックが失敗した場合はエラーで中断します。

```yaml
pre_hook: "echo pre {{ project_name }}"
post_hook: "echo post {{ project_name }}"
```

実行方法は `/bin/sh -c` です。ドライラン時はフックを実行しません。
フックには `CX_OUTPUT_DIR`、`CX_TEMPLATE_NAME`、`CX_TEMPLATE_DESCRIPTION`、および解決済みの変数が環境変数として渡されます。

## 非対話式変数（--vars-file）

`--vars-file` に YAML または JSON 形式の変数マップを指定して、非対話で値を提供できます。ファイルは変数名をキー、文字列を値とするマッピングにしてください。例:

```yaml
project_name: myproject
author: Jane
```

優先順位: コマンドラインの `-v VAR=VALUE` > `--vars-file` > 対話プロンプト > テンプレートのデフォルト。`--vars-file` に含まれる変数は対話プロンプトでは尋ねられません。使用例:

```bash
cargo run -- mytemplate --vars-file vars.yaml --dry-run
```


## fzf 選択

`cxr fzf` は [fzf](https://github.com/junegunn/fzf) を使ってテンプレートを選択し、そのまま生成します。fzf が無い場合やキャンセル時はエラーで終了します。

`cxr list --search <query>` はテンプレート名・説明・タグを対象に検索します。
