Metadata-Version: 2.4
Name: daps-testing
Version: 1.1.9
Summary: DAPS - Definitely a Python Shell
Author: arizona
Classifier: Operating System :: POSIX :: Linux
Classifier: Programming Language :: Python :: 3
Classifier: Topic :: Terminals
Requires-Python: >=3.10
Requires-Dist: prompt-toolkit>=3.0.52
Requires-Dist: pygments>=2.20.0
Requires-Dist: python-pam>=2.0.2
Description-Content-Type: text/markdown

# DAPS
**D**efinitely **A** **P**ython **S**hell. A shell written in pure Python.

[![PyPI](https://img.shields.io/pypi/v/daps-pip?style=for-the-badge)](https://pypi.org/project/daps-pip/)

---

DAPS is available on PyPI!
```bash
pip install daps-pip
```

## Usage

Basic shell commands work as expected, e.g. `cd`, `ls`, pipes (`|`), redirection (`>`, `>>`, `<`, `2>`, `&>`), and background jobs (`&`).

Built-in commands include:

- `cd <dir>` – Change directory. Runs any registered `on_cd` hooks and checks for `.dapsrc`.
- `clear` – Clears the screen (and re-runs the greeter if `cleargreet` is enabled).
- `clearhist` – Clears shell history. After running this, history won't be recorded again until the shell is restarted.
- `exit` – Exits the shell. Prompts for confirmation first if `confirm_exit` is enabled.
- `jobs` – Lists background jobs.
- `fg [job_id]` – Brings a background job to the foreground.
- `bg [job_id]` – Resumes a stopped job in the background.
- `source <file>` / `. <file>` – Runs a `.daps` script inline, so any variables it sets persist in your current shell (unlike a subshell).
- `set` / `export` / `unset` / `readonly` / `declare` – Standard POSIX-style variable builtins. Bare `VAR=value` assignment is also supported.
- `secretpython` – Drops into a live Python REPL inside the running shell process.

### Inline interpreters

- `p!<code>` – Runs `<code>` as Python, directly in the shell's own process (e.g. `p!2 + 2`).
- `n!<code>` – Runs `<code>` as JavaScript via Node.js (`node` must be installed).

### Scripting

DAPS understands three kinds of scripts:

- **`.daps` files** – Run natively (not shelled out) via `source`/`.` or by executing the file directly. Supports `if` / `elif` / `else` / `end`, `for <var> in <items>` / `end`, `while <cond>` / `end`, and `break` / `continue`. Conditions are shell commands; exit code `0` is truthy.
- **`.sh` / `.bash` / `.fish` / `.zsh` / `.ksh` files** – Shelled out to the matching interpreter.
- **Shebang scripts** – The shebang line decides the interpreter, same as normal Unix behavior.

### Modules

Drop a `.py` file into `~/.config/daps/modules/` and its top-level functions become callable as `modulename.function args...` from the shell.

### Plugins

Drop a `.py` file into `~/.config/daps/plugins/` defining `main(bg, daps)` (or the older `main(bg)`), and it's loaded automatically at startup. Plugins get a `daps` registry handle to extend the shell:

- `daps.add_prefix(prefix, handler)` – e.g. a custom `r!` for Ruby.
- `daps.add_builtin(name, handler)` – register a new flat command.
- `daps.add_alias(name, expansion)` – ship a default alias (only applies if the user hasn't already set one).
- `daps.add_completer(fn)` – contribute extra tab-completion candidates.
- `daps.on_precmd(fn)` / `daps.on_postcmd(fn)` – hooks that run before/after every command.
- `daps.on_cd(fn)` – hook that runs whenever the shell changes directory.
- `daps.on_exit(fn)` – hook that runs right before the shell exits.
- `daps.set_prompt_hook(fn)` – fully override the prompt text.
- `daps.on(event, fn)` / `daps.emit(event, **data)` – simple pub/sub between plugins.

Plugins can never override core builtins or the `p!`/`n!` prefixes.

### Per-directory `.dapsrc`

If a directory contains a `.dapsrc` file, DAPS will offer to run it (as plain Python, exec'd against the shell's own namespace) whenever you `cd` into that directory. You must explicitly trust a directory first:

- `dapsrc.allow [path]` – Trust `.dapsrc` in the given (or current) directory.
- `dapsrc.deny [path]` – Revoke trust for a directory.

---

## Configuration

DAPS is configured via `~/.config/daps/config.py`, a real Python file — not JSON. It's created automatically on first run with every option commented out. To configure the shell, edit the `daps` object it defines:

```python
daps = Config()

daps.lock = False               # Require PAM password auth on shell start
daps.motd = True                # Show the message of the day on startup
daps.aliases = {}                # Command aliases, e.g. {"ll": "ls -la"}
daps.devicename = False         # Show product name instead of hostname in the prompt
daps.cleargreet = False         # Re-run the greeter every time `clear` is run
daps.greeter = None             # 'daps' for the built-in sysfetch, or a shell command string, or None
daps.language = None             # Force a UI language: en, es, fr, de, ru, ja, pt, zh, it
daps.env = {}                    # Environment variables set at startup
daps.path = []                   # Extra directories prepended to PATH at startup
daps.startup_commands = []       # Commands run once at startup, after the greeter
daps.history_size = 1000         # Max lines kept in ~/.daps.history
daps.prompt_symbols = {"root": "#", "user": "$"}
daps.confirm_exit = False        # Ask for confirmation before `exit` closes the shell
daps.show_exec_time = False      # Show how long each command took
daps.exec_time_threshold = 1.0   # Only show the timer if the command took at least this long
daps.starship = False            # Use Starship for the prompt instead of the built-in one
```

**Note:** Built-in commands can't be overridden by aliases or plugin builtins.

---

### `greeter`

Runs on shell startup. Set to `"daps"` to use the built-in `sysfetch`-style system info greeter, a shell command string to run something else (e.g. `fastfetch`), or `None` to disable it.

```python
daps.greeter = "daps"
```

### `aliases`

Simple command aliases:

```python
daps.aliases = {
    "ll": "ls -l",
}
```

### `cleargreet`

Whether the greeter re-runs every time you use `clear`:

```python
daps.cleargreet = True
```

### `devicename`

Show the device's product name (e.g. `ASUS E410MA`) in the prompt instead of the hostname (e.g. `fedora`):

```python
daps.devicename = True
```

### `starship`

If you'd rather use [Starship](https://starship.rs) for prompt rendering instead of DAPS's built-in prompt (or a plugin's `set_prompt_hook`):

```python
daps.starship = True
```

### `lock`

Requires a password (checked via PAM against your system account) before the shell will start:

```python
daps.lock = True
```

### `motd`

Whether the "message of the day" banner (version, tips) is shown on startup:

```python
daps.motd = False
```

### `language`

Forces the UI language instead of auto-detecting it from your system locale. Affects things like error messages and `sysfetch` labels. One of `en`, `es`, `fr`, `de`, `ru`, `ja`, `pt`, `zh`, `it`:

```python
daps.language = "fr"
```

### `env`

A dict of environment variables to set every time the shell starts, before anything else runs:

```python
daps.env = {
    "EDITOR": "nvim",
    "PROJECT_ENV": "dev",
}
```

### `path`

Extra directories to prepend to `PATH` at startup:

```python
daps.path = ["~/.local/bin", "~/scripts"]
```

### `startup_commands`

A list of commands run once, in order, right after the greeter finishes. Supports `cd` (which actually changes the shell's working directory) and otherwise runs each command through the system shell:

```python
daps.startup_commands = [
    "cd ~/projects",
    "echo Ready to work",
]
```

### `history_size`

The maximum number of lines kept in `~/.daps.history`. Older entries are trimmed on startup:

```python
daps.history_size = 5000
```

### `prompt_symbols`

The character shown after the username/host in the prompt, depending on whether you're root or a normal user:

```python
daps.prompt_symbols = {"root": "#", "user": "$"}
```

### `confirm_exit`

If enabled, running `exit` asks `Exit shell? [y/N]` before actually closing the shell:

```python
daps.confirm_exit = True
```

### `show_exec_time`

Prints how long each command took to run, right after it finishes:

```python
daps.show_exec_time = True
```

### `exec_time_threshold`

Only used when `show_exec_time` is enabled — the timer is only printed if the command took at least this many seconds:

```python
daps.exec_time_threshold = 0.5
```

### Example of a full config

```python
daps = Config()

daps.lock = False
daps.motd = True
daps.aliases = {"ll": "ls -l"}
daps.devicename = True
daps.cleargreet = True
daps.greeter = "daps"
daps.language = None
daps.env = {"EDITOR": "nvim"}
daps.path = ["~/.local/bin"]
daps.startup_commands = ["cd ~/projects"]
daps.history_size = 5000
daps.prompt_symbols = {"root": "#", "user": "$"}
daps.confirm_exit = True
daps.show_exec_time = True
daps.exec_time_threshold = 0.5
daps.starship = False
```

---

## More Information

- More features are coming soon!
- DAPS is protected by the **GNU license**, meaning any contributions or derivatives of the program **must be fully open source**.

---

**© 2026, Nytrix Labs**
