Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion MANIFEST.in
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
include LICENSE
include README.md
include LICENSE
186 changes: 153 additions & 33 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,62 +1,182 @@
# RP Tree

RP Tree is a command-line tool to generate directory tree diagrams.
![Python](https://img.shields.io/badge/python-3.8%2B-blue)
![License](https://img.shields.io/badge/license-MIT-green)
![Version](https://img.shields.io/badge/version-0.2.0-orange)

## Installation
RP Tree is a simple and fast CLI tool to generate directory tree diagrams.

To install **RP Tree**, just run the following command:
## Installation

```sh
$ pip install rptree
```bash
pip install rptree
```

## Usage

```sh
$ rptree /path/to/directory/
```bash
rptree [ROOT_DIR]
```

If no directory is provided, the current directory is used:

```bash
rptree
```

Show help:

```bash
rptree -h
```

## Options

### General

- `-h`, `--help` Show help message
- `-v`, `--version` Show version

### Modes

- `-d`, `--dir-only` Show directories only
- `-f`, `--files-only` Show files only

### Ordering

- `-df`, `--dirs-first` List directories before files
- `-ff`, `--files-first` List files before directories

> Alphabetical order is always applied as base sorting.

### Display

- `-n`, `--no-pipes` Remove vertical pipes between branches

### Ignoring

- `-i`, `--ignore PATTERN [PATTERN ...]` Ignore files/directories
- `-gi`, `--gitignore` Respect `.gitignore` rules

### Depth

- `-dl`, `--depth-level N` Limit depth

### Output

- `-o`, `--output-file FILE` Save output to file (Markdown format)

## Examples

Basic:

```bash
rptree
```

**Note:** The `-h` or `--help` option provides help on using RP Tree.
Directories first:

```bash
rptree . -df
```

Files only:

```bash
rptree . -f
```

Limit depth:

```bash
rptree . -dl 2
```

Ignore entries:

```bash
rptree . -i node_modules dist .git
```

Use `.gitignore`:

```bash
rptree . -gi
```

No pipes mode:

```bash
rptree . -n
```

Save to file:

```bash
rptree . -o tree.md
```

## Sample Output

```sh
$ rptree hello/
./hello/
### Default

```text
project/
├── hello/
│ ├── __init__.py
│ └── hello.py
├── src/
│ ├── main.py
│ └── utils.py
├── tests/
│ └── test_hello.py
│ └── test_main.py
├── LICENSE
├── README.md
├── requirements.txt
└── setup.py
└── README.md
```

That's it! You've generated a nice directory tree diagram.
### No pipes (`-n`)

```text
project/
├── src/
│ ├── main.py
│ └── utils.py
├── tests/
│ └── test_main.py
└── README.md
```

## Features

If you run RP Tree with a directory path as an argument, then you get a full directory tree diagram printed on your screen. The default input directory is your current directory.
- Clean and readable tree output
- `.gitignore` support
- Custom ignore patterns
- Depth limiting
- Flexible sorting
- Optional compact mode (`--no-pipes`)

RP Tree also provides the following options:
## Release History

- `-v`, `--version` shows the application version and exits
- `-h`, `--help` show a usage message
- `-d`, `--dir-only` generates a directory-only tree diagram
- `-o`, `--output-file` generates a full directory tree diagram and save it to a file in markdown format
### 0.3.0

## Release History
- Fixed `--no-pipes` behavior
- Fixed `.gitignore` directory handling
- Improved tree formatting (matches classic `tree`)
- Added modern packaging (`pyproject.toml`)

### 0.2.0

- Added filtering and ordering options
- Added `.gitignore` support
- Added depth control

### 0.1.0

- Initial release

## Author

- 0.1.1
- Display the entries in alphabetical order
- 0.1.0
- A work in progress
Leodanis Pozo Ramos

## About the Author
## License

Leodanis Pozo Ramos - Email: leodanis@realpython.com
^RP Tree^ is distributed under the MIT license. See [LICENSE](LICENSE) for more information.
23 changes: 23 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
[build-system]
requires = ["setuptools>=61.0"]
build-backend = "setuptools.build_meta"

[project]
name = "rptree"
version = "0.3.0"
description = "Generate directory tree diagrams from the command line"
readme = "README.md"
license = { file = "LICENSE" }
authors = [
{ name = "Leodanis Pozo Ramos" }
]
requires-python = ">=3.8"
dependencies = [
"pathspec"
]

[project.scripts]
rptree = "rptree.__main__:main"

[project.urls]
Homepage = "https://github.com/realpython/rptree"
4 changes: 3 additions & 1 deletion rptree/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
"""Top-level package for RP Tree."""

__version__ = "0.1.1"
__all__ = ["__version__"]

__version__ = "0.2.0"
45 changes: 35 additions & 10 deletions rptree/__main__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
"""This module provides the RP Tree CLI."""
"""Entry point for RP Tree CLI."""

import pathlib
import sys
Expand All @@ -7,17 +7,42 @@
from .rptree import DirectoryTree


def main():
def main() -> None:
args = parse_cmd_line_arguments()
root_dir = pathlib.Path(args.root_dir)
root_dir = pathlib.Path(args.root_dir).resolve()

if not root_dir.exists():
print(f"Error: directory not found: {root_dir}", file=sys.stderr)
sys.exit(1)

if not root_dir.is_dir():
print("The specified root directory doesn't exist")
sys.exit()
tree = DirectoryTree(
root_dir, dir_only=args.dir_only, output_file=args.output_file
)
tree.generate()
print(f"Error: path is not a directory: {root_dir}", file=sys.stderr)
sys.exit(1)

try:
tree = DirectoryTree(
root_dir=root_dir,
dir_only=args.dir_only,
files_only=args.files_only,
dirs_first=args.dirs_first,
files_first=args.files_first,
no_pipes=args.no_pipes,
ignore=args.ignore,
use_gitignore=args.gitignore,
depth_level=args.depth_level,
output_file=args.output_file,
)

tree.generate()

except KeyboardInterrupt:
print("\nOperation cancelled.", file=sys.stderr)
sys.exit(130)

except Exception as e:
print(f"Error: {e}", file=sys.stderr)
sys.exit(1)


if __name__ == "__main__":
main()
main()
Loading