Metadata-Version: 2.4
Name: bytecraft
Version: 0.3.0
Summary: A lightweight DSL for scaffolding files and folders
Author: Sourasish Das
License: SOCL-1.0
Classifier: Programming Language :: Python :: 3
Classifier: Operating System :: OS Independent
Classifier: Topic :: Software Development :: Build Tools
Classifier: Topic :: Utilities
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Dynamic: author
Dynamic: classifier
Dynamic: description
Dynamic: description-content-type
Dynamic: license
Dynamic: license-file
Dynamic: requires-python
Dynamic: summary

# 🧱 Bytecraft

> A human-readable DSL for scaffolding files and folders.

```
pip install bytecraft
```

---

Bytecraft lets you describe a project structure in plain, readable instructions and execute it with a single command — no Bash, no Python boilerplate, no mental overhead.

```
# bootstrap.bc

load-vars "project.ebv"

set-working-folder "{{project}}"

make-folder "src"
make-folder "src/utils"
make-folder "assets"

make-file "README.md" with "# {{project}}"
make-file "src/main.py" with "print('Hello, World!')"
make-file "src/utils/helper.py"
```

```bash
py -m bytecraft bootstrap.bc
```

```
[Bytecraft] Loaded 3 variable(s) from: project.ebv
[Bytecraft] Working folder set: my-app
[Bytecraft] Created folder: my-app/src
[Bytecraft] Created folder: my-app/src/utils
[Bytecraft] Created folder: my-app/assets
[Bytecraft] Created file: my-app/README.md
[Bytecraft] Created file: my-app/src/main.py
[Bytecraft] Created file: my-app/src/utils/helper.py
```

---

## Installation

Requires Python 3.10+

```bash
pip install bytecraft
```

---

## Commands

### `set-working-folder`

Sets the base directory for all subsequent relative paths. Created automatically if it doesn't exist.

```
set-working-folder "my-project"
```

---

### `make-folder`

Creates a directory and any missing parent directories. Does nothing if the folder already exists.

```
make-folder "src/utils"
```

---

### `make-file`

Creates a file. Parent directories are created automatically. Overwrites if the file already exists.

```
# Empty file
make-file "src/__init__.py"

# Inline content
make-file "VERSION" with "1.0.0"

# Multi-line content block
make-file "README.md" with ---
# My Project

Some description here.
---
```

---

### `append-file`

Appends content to an existing file. Creates the file if it doesn't exist. A newline is automatically inserted before the new content if the file is non-empty.

```
make-file "log.txt" with "First entry"
append-file "log.txt" with "Second entry"

# Multi-line append
append-file "README.md" with ---

## New Section

Added after the fact.
---
```

---

### `copy-file`

Copies a file or folder to a new location. Parent directories are created automatically. If copying a folder that already exists at the destination, it is replaced.

```
copy-file "src/app.py" to "backup/app.py"
copy-file "src" to "src_backup"
```

---

### `move-file`

Moves a file or folder to a new location. Parent directories are created automatically.

```
move-file "build/output.js" to "dist/app.js"
move-file "temp" to "archive/temp"
```

---

### `make-zip`

Creates a zip archive from a file or folder. Folder structure is preserved inside the zip.

```
make-zip "releases/v1.0.zip" from "dist"
make-zip "releases/app.zip" from "dist/app.py"
```

---

### `set`

Defines a variable. Variables are referenced anywhere using `{{name}}` syntax — in paths, content, template calls, and loop bodies.

```
set project "my-app"
set version "1.0.0"

make-file "VERSION" with "{{version}}"
make-file "src/main.py" with "# {{project}} v{{version}}"
```

---

### `load-vars`

Loads variables from an `.ebv` (External Bytecraft Variables) file. Useful for sharing config across multiple scripts.

```
load-vars "config.ebv"
```

**`config.ebv`:**
```
# Project config
project = my-app
version = 1.0.0
author = Sourasish Das
env = prod
```

Lines starting with `#` are ignored. Values do not need quotes.

---

### `for`

Loops over a list of values or an integer range. The loop variable is available inside the body via `{{name}}`. Loops can be nested.

```
# Value list
for name in "auth" "api" "db"
  make-folder "src/{{name}}"
  make-file "src/{{name}}/__init__.py" with "# {{name}} module"
end-for

# Integer range
for i in 1 to 5
  make-file "logs/day_{{i}}.log"
end-for
```

---

### `if`

Conditionally executes a block. Supports file existence checks and variable comparisons. Can be nested inside loops and other `if` blocks.

```
# File existence
if exists "src/main.py"
  make-file "src/backup.py" with "# backup"
end-if

if not exists "dist"
  make-folder "dist"
end-if

# Variable comparison
if "{{env}}" is "prod"
  include "hardening.bc"
end-if

if "{{env}}" is not "dev"
  make-file "prod-only.txt" with "production config"
end-if
```

---

### `define-template` / `use-template`

Templates let you define reusable scaffolding blocks and stamp them out with different values. Variables passed to `use-template` are local to that call and do not leak back into the outer script.

```
define-template "module"
  make-folder "src/{{name}}"
  make-file "src/{{name}}/__init__.py"
  make-file "src/{{name}}/main.py" with "# {{name}} module — {{project}}"
end-template

use-template "module" name "auth"
use-template "module" name "api"
use-template "module" name "db"
```

---

### `include`

Runs another `.bc` file inline with fully shared state. Variables, templates, the working folder, and strict mode all carry across in both directions. Paths are resolved relative to the calling script's directory.

```
include "base.bc"
include "templates/python.bc"
```

---

### `strict on` / `strict off`

In strict mode, warnings become fatal errors — undefined variables, unknown commands, and missing source files all halt execution immediately. Can be toggled on and off within the same script.

```
strict on

make-file "VERSION" with "{{version}}"   # fine if version is set
make-file "bad.txt" with "{{typo}}"      # ERROR: halts execution

strict off
```

---

### Comments

Lines starting with `#` are ignored.

```
# This is a comment
```

---

## Forgiving Syntax

Bytecraft is intentionally forgiving. Quotes are optional — if they're missing, Bytecraft will recover and interpret your intent:

```
make-file hello.txt with Hello World
```

is treated the same as:

```
make-file "hello.txt" with "Hello World"
```

Unknown commands print a warning and are skipped rather than crashing the script. Use `strict on` if you want the opposite behaviour.

---

## Full Example

```
# Full project scaffold

strict on

load-vars "project.ebv"

set-working-folder "{{project}}"

# Stamp out feature modules
define-template "module"
  make-folder "src/{{name}}"
  make-file "src/{{name}}/__init__.py"
  make-file "src/{{name}}/main.py" with "# {{name}} — {{project}}"
end-template

for name in "auth" "api" "db" "admin"
  use-template "module" name "{{name}}"
end-for

# Generate per-environment configs
for env in "dev" "staging" "prod"
  if "{{env}}" is "prod"
    make-file "config/{{env}}.json" with "{ \"strict\": true }"
  end-if
  if "{{env}}" is not "prod"
    make-file "config/{{env}}.json" with "{ \"strict\": false }"
  end-if
end-for

# Static files
make-file "VERSION" with "{{version}}"

make-file "README.md" with ---
# {{project}}

Version: {{version}}
Author: {{author}}
---

# Build log
make-file "build.log" with "Build started"
append-file "build.log" with "Modules scaffolded"
append-file "build.log" with "Configs generated"

# Only package if we're in prod
if "{{env}}" is "prod"
  copy-file "src" to "dist/src"
  make-zip "releases/{{project}}-{{version}}.zip" from "dist"
  append-file "build.log" with "Release zipped"
end-if
```

**`project.ebv`:**
```
project = my-app
version = 1.0.0
author = Sourasish Das
env = prod
```

---

## Limitations (v0.3.0)

- No arithmetic or string operations in expressions
- No `else` / `else-if` blocks
- No nested variable references (e.g. `{{{{key}}}}`)

---

## Roadmap

- [x] Variables and interpolation
- [x] Multi-line file content blocks
- [x] `copy-file` and `move-file`
- [x] `make-zip`
- [x] `append-file`
- [x] Templates (`define-template` / `use-template`)
- [x] `include`
- [x] Strict mode
- [x] `for` loops (value lists and ranges)
- [x] `if` conditionals (exists checks and variable comparisons)
- [x] `.ebv` external variable files
- [ ] `else` / `else-if`
- [ ] Delete commands (`delete-file`, `delete-folder`)
- [ ] Arithmetic in ranges and variables

---

## License

[Server-Lab Open-Control License (SOCL) 1.0](./LICENSE)  
Copyright (c) 2025 Sourasish Das
