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
150 changes: 114 additions & 36 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,59 +4,137 @@ RP Tree is a command-line tool to generate directory tree diagrams.

## Installation

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

```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 application version

### Modes

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

### Ordering

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

> Note: Alphabetical order is always used as the base ordering.

### Ignoring

- `-i`, `--ignore NAME [NAME ...]` Ignore specific files or directories
- `-gi`, `--gitignore` Respect `.gitignore` rules

### Depth

- `-dl`, `--depth-level N` Limit the tree depth to N levels

### Output

- `-o`, `--output-file FILE` Save the generated tree to a file

## Examples

Generate tree for current directory:

```bash
rptree
```

Directories first:

```bash
rptree . -df
```

Files only:

```bash
rptree . -f
```

Limit depth:

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

Ignore specific entries:

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

**Note:** The `-h` or `--help` option provides help on using RP Tree.
Use `.gitignore` rules:

```bash
rptree . -gi
```

Save output to file:

```bash
rptree . -o tree.txt
```

## Sample Output

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

That's it! You've generated a nice directory tree diagram.
## Release History

## Features
### 0.2.0

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.
- Added `--files-only` (`-f`)
- Added `--dirs-first` (`-df`)
- Added `--files-first` (`-ff`)
- Added `--ignore` (`-i`)
- Added `.gitignore` support (`-gi`)
- Added `--depth-level` (`-dl`)
- Improved tree formatting
- Added type hints

RP Tree also provides the following options:
### 0.1.1

- `-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
- Display entries in alphabetical order

## Release History
### 0.1.0

- 0.1.1
- Display the entries in alphabetical order
- 0.1.0
- A work in progress
- Initial release

## About the Author
## Author

Leodanis Pozo Ramos - Email: leodanis@realpython.com
Leodanis Pozo Ramos
2 changes: 1 addition & 1 deletion rptree/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
"""Top-level package for RP Tree."""

__version__ = "0.1.1"
__version__ = "0.2.0"
29 changes: 22 additions & 7 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,32 @@
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"Directory not found: {root_dir}")
sys.exit(1)

if not root_dir.is_dir():
print("The specified root directory doesn't exist")
sys.exit()
print(f"Path is not a directory: {root_dir}")
sys.exit(1)

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

tree.generate()


if __name__ == "__main__":
main()
main()
81 changes: 73 additions & 8 deletions rptree/cli.py
Original file line number Diff line number Diff line change
@@ -1,38 +1,103 @@
"""This module provides the RP Tree CLI."""

import argparse
import sys

from . import __version__


def parse_cmd_line_arguments():
def parse_cmd_line_arguments() -> argparse.Namespace:
parser = argparse.ArgumentParser(
prog="tree",
description="RP Tree, a directory tree generator",
prog="rptree",
description="Generate a directory tree",
epilog="Thanks for using RP Tree!",
)

parser.version = f"RP Tree v{__version__}"
parser.add_argument("-v", "--version", action="version")

parser.add_argument(
"root_dir",
metavar="ROOT_DIR",
nargs="?",
default=".",
help="generate a full directory tree starting at ROOT_DIR",
)

parser.add_argument(
"-d",
"--dir-only",
action="store_true",
help="generate a directory-only tree",
)

parser.add_argument(
"-f",
"--files-only",
action="store_true",
help="generate a file-only tree",
)

ordering = parser.add_mutually_exclusive_group()

ordering.add_argument(
"-df",
"--dirs-first",
action="store_true",
help="list directories before files",
)

ordering.add_argument(
"-ff",
"--files-first",
action="store_true",
help="list files before directories",
)

parser.add_argument(
"-i",
"--ignore",
metavar="PATTERN",
nargs="*",
default=None,
help="ignore files or directories (supports patterns, e.g. *.py)",
)

parser.add_argument(
"-gi",
"--gitignore",
action="store_true",
help="respect .gitignore rules",
)

parser.add_argument(
"-dl",
"--depth-level",
metavar="N",
type=int,
default=None,
help="limit tree depth to N levels",
)

parser.add_argument(
"-o",
"--output-file",
metavar="OUTPUT_FILE",
nargs="?",
default=sys.stdout,
help="generate a full directory tree and save it to a file",
default=None,
help="save the generated tree to a file",
)
return parser.parse_args()

args = parser.parse_args()

if args.dir_only and args.files_only:
parser.error("cannot use --dir-only and --files-only together")

if args.dir_only and (args.dirs_first or args.files_first):
parser.error("ordering options are not valid with --dir-only")

if args.files_only and (args.dirs_first or args.files_first):
parser.error("ordering options are not valid with --files-only")

if args.depth_level is not None and args.depth_level < 0:
parser.error("--depth-level must be >= 0")

return args
Loading