abitree 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- abitree-0.1.0/PKG-INFO +87 -0
- abitree-0.1.0/README.md +73 -0
- abitree-0.1.0/abitree/__init__.py +1 -0
- abitree-0.1.0/abitree/cli.py +98 -0
- abitree-0.1.0/abitree/icons.py +272 -0
- abitree-0.1.0/abitree/tree.py +82 -0
- abitree-0.1.0/abitree.egg-info/PKG-INFO +87 -0
- abitree-0.1.0/abitree.egg-info/SOURCES.txt +11 -0
- abitree-0.1.0/abitree.egg-info/dependency_links.txt +1 -0
- abitree-0.1.0/abitree.egg-info/entry_points.txt +2 -0
- abitree-0.1.0/abitree.egg-info/top_level.txt +1 -0
- abitree-0.1.0/pyproject.toml +26 -0
- abitree-0.1.0/setup.cfg +4 -0
abitree-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: abitree
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Generate beautiful file trees for your README
|
|
5
|
+
Author: Abidit Shrestha
|
|
6
|
+
License: MIT
|
|
7
|
+
Keywords: cli,tree,readme,file-tree,developer-tools
|
|
8
|
+
Classifier: Programming Language :: Python :: 3
|
|
9
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
10
|
+
Classifier: Operating System :: OS Independent
|
|
11
|
+
Classifier: Environment :: Console
|
|
12
|
+
Requires-Python: >=3.9
|
|
13
|
+
Description-Content-Type: text/markdown
|
|
14
|
+
|
|
15
|
+
# 🌳 abitree
|
|
16
|
+
|
|
17
|
+
Generate beautiful, icon-rich file trees for your README — instantly.
|
|
18
|
+
|
|
19
|
+
```
|
|
20
|
+
📁 my-project/
|
|
21
|
+
├── 📁 src/
|
|
22
|
+
│ ├── 🐍 main.py
|
|
23
|
+
│ ├── ⚛️ App.tsx
|
|
24
|
+
│ └── 🎨 styles.css
|
|
25
|
+
├── 📦 package.json
|
|
26
|
+
├── 🐳 Dockerfile
|
|
27
|
+
└── 📝 README.md
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## Installation
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
pip install abitree
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
## Usage
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
# Current directory
|
|
40
|
+
abitree
|
|
41
|
+
|
|
42
|
+
# Specific path
|
|
43
|
+
abitree ./my-project
|
|
44
|
+
|
|
45
|
+
# Limit depth
|
|
46
|
+
abitree -L 2
|
|
47
|
+
|
|
48
|
+
# Output to file
|
|
49
|
+
abitree -o structure.md
|
|
50
|
+
|
|
51
|
+
# Wrap in markdown code block
|
|
52
|
+
abitree --md
|
|
53
|
+
|
|
54
|
+
# Directories only
|
|
55
|
+
abitree --dirs-only
|
|
56
|
+
|
|
57
|
+
# Ignore extra folders
|
|
58
|
+
abitree -i dist,build,.cache
|
|
59
|
+
|
|
60
|
+
# No icons (plain text)
|
|
61
|
+
abitree --no-icons
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
## Options
|
|
65
|
+
|
|
66
|
+
| Flag | Description |
|
|
67
|
+
|------|-------------|
|
|
68
|
+
| `path` | Directory to scan (default: `.`) |
|
|
69
|
+
| `-L, --level` | Max depth |
|
|
70
|
+
| `-o, --output` | Write output to file |
|
|
71
|
+
| `-i, --ignore` | Comma-separated ignore list |
|
|
72
|
+
| `--dirs-only` | Show directories only |
|
|
73
|
+
| `--no-icons` | Disable icons |
|
|
74
|
+
| `--no-default-ignore` | Don't ignore `.git`, `node_modules`, etc. |
|
|
75
|
+
| `--md` | Wrap output in markdown code block |
|
|
76
|
+
|
|
77
|
+
## Default ignored
|
|
78
|
+
|
|
79
|
+
`.git`, `__pycache__`, `.DS_Store`, `.idea`, `.vscode`, `node_modules`
|
|
80
|
+
|
|
81
|
+
## Author
|
|
82
|
+
|
|
83
|
+
Built by [Abidit Shrestha](https://github.com/abiditshrestha)
|
|
84
|
+
|
|
85
|
+
## License
|
|
86
|
+
|
|
87
|
+
MIT
|
abitree-0.1.0/README.md
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
# 🌳 abitree
|
|
2
|
+
|
|
3
|
+
Generate beautiful, icon-rich file trees for your README — instantly.
|
|
4
|
+
|
|
5
|
+
```
|
|
6
|
+
📁 my-project/
|
|
7
|
+
├── 📁 src/
|
|
8
|
+
│ ├── 🐍 main.py
|
|
9
|
+
│ ├── ⚛️ App.tsx
|
|
10
|
+
│ └── 🎨 styles.css
|
|
11
|
+
├── 📦 package.json
|
|
12
|
+
├── 🐳 Dockerfile
|
|
13
|
+
└── 📝 README.md
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
## Installation
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
pip install abitree
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## Usage
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
# Current directory
|
|
26
|
+
abitree
|
|
27
|
+
|
|
28
|
+
# Specific path
|
|
29
|
+
abitree ./my-project
|
|
30
|
+
|
|
31
|
+
# Limit depth
|
|
32
|
+
abitree -L 2
|
|
33
|
+
|
|
34
|
+
# Output to file
|
|
35
|
+
abitree -o structure.md
|
|
36
|
+
|
|
37
|
+
# Wrap in markdown code block
|
|
38
|
+
abitree --md
|
|
39
|
+
|
|
40
|
+
# Directories only
|
|
41
|
+
abitree --dirs-only
|
|
42
|
+
|
|
43
|
+
# Ignore extra folders
|
|
44
|
+
abitree -i dist,build,.cache
|
|
45
|
+
|
|
46
|
+
# No icons (plain text)
|
|
47
|
+
abitree --no-icons
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
## Options
|
|
51
|
+
|
|
52
|
+
| Flag | Description |
|
|
53
|
+
|------|-------------|
|
|
54
|
+
| `path` | Directory to scan (default: `.`) |
|
|
55
|
+
| `-L, --level` | Max depth |
|
|
56
|
+
| `-o, --output` | Write output to file |
|
|
57
|
+
| `-i, --ignore` | Comma-separated ignore list |
|
|
58
|
+
| `--dirs-only` | Show directories only |
|
|
59
|
+
| `--no-icons` | Disable icons |
|
|
60
|
+
| `--no-default-ignore` | Don't ignore `.git`, `node_modules`, etc. |
|
|
61
|
+
| `--md` | Wrap output in markdown code block |
|
|
62
|
+
|
|
63
|
+
## Default ignored
|
|
64
|
+
|
|
65
|
+
`.git`, `__pycache__`, `.DS_Store`, `.idea`, `.vscode`, `node_modules`
|
|
66
|
+
|
|
67
|
+
## Author
|
|
68
|
+
|
|
69
|
+
Built by [Abidit Shrestha](https://github.com/abiditshrestha)
|
|
70
|
+
|
|
71
|
+
## License
|
|
72
|
+
|
|
73
|
+
MIT
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = '0.1.0'
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import argparse
|
|
2
|
+
import sys
|
|
3
|
+
from .tree import generate_tree
|
|
4
|
+
|
|
5
|
+
DEFAULT_IGNORE = [".git", "__pycache__", ".DS_Store", ".idea", ".vscode", "node_modules"]
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def main():
|
|
9
|
+
parser = argparse.ArgumentParser(
|
|
10
|
+
prog="abitree",
|
|
11
|
+
description="🌳 abitree — generate beautiful file trees for your README",
|
|
12
|
+
)
|
|
13
|
+
|
|
14
|
+
parser.add_argument(
|
|
15
|
+
"path",
|
|
16
|
+
nargs="?",
|
|
17
|
+
default=".",
|
|
18
|
+
help="Path to directory (default: current directory)",
|
|
19
|
+
)
|
|
20
|
+
|
|
21
|
+
parser.add_argument(
|
|
22
|
+
"-L", "--level",
|
|
23
|
+
type=int,
|
|
24
|
+
default=None,
|
|
25
|
+
metavar="DEPTH",
|
|
26
|
+
help="Max depth of the tree",
|
|
27
|
+
)
|
|
28
|
+
|
|
29
|
+
parser.add_argument(
|
|
30
|
+
"-o", "--output",
|
|
31
|
+
type=str,
|
|
32
|
+
default=None,
|
|
33
|
+
metavar="FILE",
|
|
34
|
+
help="Output to a file (e.g. README.md)",
|
|
35
|
+
)
|
|
36
|
+
|
|
37
|
+
parser.add_argument(
|
|
38
|
+
"-i", "--ignore",
|
|
39
|
+
type=str,
|
|
40
|
+
default=None,
|
|
41
|
+
metavar="PATTERNS",
|
|
42
|
+
help="Comma-separated list of names to ignore (e.g. node_modules,.git)",
|
|
43
|
+
)
|
|
44
|
+
|
|
45
|
+
parser.add_argument(
|
|
46
|
+
"--dirs-only",
|
|
47
|
+
action="store_true",
|
|
48
|
+
help="Show directories only",
|
|
49
|
+
)
|
|
50
|
+
|
|
51
|
+
parser.add_argument(
|
|
52
|
+
"--no-icons",
|
|
53
|
+
action="store_true",
|
|
54
|
+
help="Disable icons (plain text output)",
|
|
55
|
+
)
|
|
56
|
+
|
|
57
|
+
parser.add_argument(
|
|
58
|
+
"--no-default-ignore",
|
|
59
|
+
action="store_true",
|
|
60
|
+
help="Disable default ignored folders (.git, node_modules, etc.)",
|
|
61
|
+
)
|
|
62
|
+
|
|
63
|
+
parser.add_argument(
|
|
64
|
+
"--md",
|
|
65
|
+
action="store_true",
|
|
66
|
+
help="Wrap output in a markdown code block",
|
|
67
|
+
)
|
|
68
|
+
|
|
69
|
+
args = parser.parse_args()
|
|
70
|
+
|
|
71
|
+
# Build ignore list
|
|
72
|
+
ignore = [] if args.no_default_ignore else list(DEFAULT_IGNORE)
|
|
73
|
+
if args.ignore:
|
|
74
|
+
ignore += [i.strip() for i in args.ignore.split(",")]
|
|
75
|
+
|
|
76
|
+
tree = generate_tree(
|
|
77
|
+
path=args.path,
|
|
78
|
+
max_depth=args.level,
|
|
79
|
+
ignore=ignore,
|
|
80
|
+
dirs_only=args.dirs_only,
|
|
81
|
+
use_icons=not args.no_icons,
|
|
82
|
+
)
|
|
83
|
+
|
|
84
|
+
if args.md:
|
|
85
|
+
output = f"```\n{tree}\n```"
|
|
86
|
+
else:
|
|
87
|
+
output = tree
|
|
88
|
+
|
|
89
|
+
if args.output:
|
|
90
|
+
with open(args.output, "w") as f:
|
|
91
|
+
f.write(output + "\n")
|
|
92
|
+
print(f"✅ Tree written to {args.output}")
|
|
93
|
+
else:
|
|
94
|
+
print(output)
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
if __name__ == "__main__":
|
|
98
|
+
main()
|
|
@@ -0,0 +1,272 @@
|
|
|
1
|
+
ICONS = {
|
|
2
|
+
# Folders
|
|
3
|
+
"__folder__": "📁",
|
|
4
|
+
|
|
5
|
+
# Python
|
|
6
|
+
".py": "🐍",
|
|
7
|
+
".pyw": "🐍",
|
|
8
|
+
".ipynb": "📓",
|
|
9
|
+
".pyi": "🐍",
|
|
10
|
+
".pyc": "🐍",
|
|
11
|
+
|
|
12
|
+
# JavaScript / TypeScript
|
|
13
|
+
".js": "🟨",
|
|
14
|
+
".mjs": "🟨",
|
|
15
|
+
".cjs": "🟨",
|
|
16
|
+
".ts": "🔷",
|
|
17
|
+
".mts": "🔷",
|
|
18
|
+
".cts": "🔷",
|
|
19
|
+
".jsx": "⚛️",
|
|
20
|
+
".tsx": "⚛️",
|
|
21
|
+
|
|
22
|
+
# Web
|
|
23
|
+
".html": "🌐",
|
|
24
|
+
".htm": "🌐",
|
|
25
|
+
".css": "🎨",
|
|
26
|
+
".scss": "🎨",
|
|
27
|
+
".sass": "🎨",
|
|
28
|
+
".less": "🎨",
|
|
29
|
+
".styl": "🎨",
|
|
30
|
+
|
|
31
|
+
# Frameworks / Components
|
|
32
|
+
".vue": "💚",
|
|
33
|
+
".svelte": "🔥",
|
|
34
|
+
".astro": "🚀",
|
|
35
|
+
|
|
36
|
+
# Rust
|
|
37
|
+
".rs": "🦀",
|
|
38
|
+
".toml": "⚙️",
|
|
39
|
+
|
|
40
|
+
# Go
|
|
41
|
+
".go": "🐹",
|
|
42
|
+
|
|
43
|
+
# C / C++
|
|
44
|
+
".c": "🔵",
|
|
45
|
+
".h": "🔵",
|
|
46
|
+
".cpp": "🔵",
|
|
47
|
+
".cc": "🔵",
|
|
48
|
+
".cxx": "🔵",
|
|
49
|
+
".hpp": "🔵",
|
|
50
|
+
".hxx": "🔵",
|
|
51
|
+
|
|
52
|
+
# Java / JVM
|
|
53
|
+
".java": "☕",
|
|
54
|
+
".class": "☕",
|
|
55
|
+
".jar": "☕",
|
|
56
|
+
".kt": "🟣",
|
|
57
|
+
".kts": "🟣",
|
|
58
|
+
".scala": "🔴",
|
|
59
|
+
".groovy": "🟢",
|
|
60
|
+
".gradle": "🟢",
|
|
61
|
+
|
|
62
|
+
# C# / .NET
|
|
63
|
+
".cs": "🟦",
|
|
64
|
+
".csx": "🟦",
|
|
65
|
+
".vb": "🟦",
|
|
66
|
+
".fs": "🟦",
|
|
67
|
+
".fsx": "🟦",
|
|
68
|
+
|
|
69
|
+
# Ruby
|
|
70
|
+
".rb": "💎",
|
|
71
|
+
".erb": "💎",
|
|
72
|
+
".gemspec": "💎",
|
|
73
|
+
|
|
74
|
+
# PHP
|
|
75
|
+
".php": "🐘",
|
|
76
|
+
".phtml": "🐘",
|
|
77
|
+
|
|
78
|
+
# Swift
|
|
79
|
+
".swift": "🍎",
|
|
80
|
+
|
|
81
|
+
# Dart / Flutter
|
|
82
|
+
".dart": "🎯",
|
|
83
|
+
|
|
84
|
+
# Lua
|
|
85
|
+
".lua": "🌙",
|
|
86
|
+
|
|
87
|
+
# Shell / Bash
|
|
88
|
+
".sh": "🐚",
|
|
89
|
+
".bash": "🐚",
|
|
90
|
+
".zsh": "🐚",
|
|
91
|
+
".fish": "🐚",
|
|
92
|
+
".ps1": "🪟",
|
|
93
|
+
".psm1": "🪟",
|
|
94
|
+
".bat": "🪟",
|
|
95
|
+
".cmd": "🪟",
|
|
96
|
+
|
|
97
|
+
# R
|
|
98
|
+
".r": "📊",
|
|
99
|
+
".R": "📊",
|
|
100
|
+
".rmd": "📊",
|
|
101
|
+
".Rmd": "📊",
|
|
102
|
+
|
|
103
|
+
# Julia
|
|
104
|
+
".jl": "🔵",
|
|
105
|
+
|
|
106
|
+
# Elixir / Erlang
|
|
107
|
+
".ex": "💜",
|
|
108
|
+
".exs": "💜",
|
|
109
|
+
".erl": "💜",
|
|
110
|
+
".hrl": "💜",
|
|
111
|
+
|
|
112
|
+
# Haskell
|
|
113
|
+
".hs": "🟣",
|
|
114
|
+
".lhs": "🟣",
|
|
115
|
+
|
|
116
|
+
# Clojure
|
|
117
|
+
".clj": "🟢",
|
|
118
|
+
".cljs": "🟢",
|
|
119
|
+
".cljc": "🟢",
|
|
120
|
+
|
|
121
|
+
# Nim
|
|
122
|
+
".nim": "🟡",
|
|
123
|
+
|
|
124
|
+
# Zig
|
|
125
|
+
".zig": "🟠",
|
|
126
|
+
|
|
127
|
+
# Config / Infra
|
|
128
|
+
".json": "📦",
|
|
129
|
+
".jsonc": "📦",
|
|
130
|
+
".json5": "📦",
|
|
131
|
+
".yaml": "🔧",
|
|
132
|
+
".yml": "🔧",
|
|
133
|
+
".xml": "📄",
|
|
134
|
+
".toml": "⚙️",
|
|
135
|
+
".ini": "⚙️",
|
|
136
|
+
".cfg": "⚙️",
|
|
137
|
+
".conf": "⚙️",
|
|
138
|
+
".config": "⚙️",
|
|
139
|
+
".env": "🔒",
|
|
140
|
+
".env.local": "🔒",
|
|
141
|
+
".env.example": "🔒",
|
|
142
|
+
|
|
143
|
+
# Docker
|
|
144
|
+
"Dockerfile": "🐳",
|
|
145
|
+
".dockerignore": "🐳",
|
|
146
|
+
"docker-compose.yml": "🐳",
|
|
147
|
+
"docker-compose.yaml": "🐳",
|
|
148
|
+
|
|
149
|
+
# Kubernetes
|
|
150
|
+
"k8s": "☸️",
|
|
151
|
+
|
|
152
|
+
# CI/CD
|
|
153
|
+
".github": "🐙",
|
|
154
|
+
".gitlab-ci.yml": "🦊",
|
|
155
|
+
"Jenkinsfile": "🔵",
|
|
156
|
+
".circleci": "⭕",
|
|
157
|
+
".travis.yml": "🔨",
|
|
158
|
+
|
|
159
|
+
# Package managers
|
|
160
|
+
"package.json": "📦",
|
|
161
|
+
"package-lock.json": "🔒",
|
|
162
|
+
"yarn.lock": "🔒",
|
|
163
|
+
"pnpm-lock.yaml": "🔒",
|
|
164
|
+
"Cargo.toml": "⚙️",
|
|
165
|
+
"Cargo.lock": "🔒",
|
|
166
|
+
"go.mod": "🐹",
|
|
167
|
+
"go.sum": "🔒",
|
|
168
|
+
"Gemfile": "💎",
|
|
169
|
+
"Gemfile.lock": "🔒",
|
|
170
|
+
"requirements.txt": "🐍",
|
|
171
|
+
"pyproject.toml": "🐍",
|
|
172
|
+
"setup.py": "🐍",
|
|
173
|
+
"setup.cfg": "🐍",
|
|
174
|
+
"Pipfile": "🐍",
|
|
175
|
+
"Pipfile.lock": "🔒",
|
|
176
|
+
"poetry.lock": "🔒",
|
|
177
|
+
"composer.json": "🐘",
|
|
178
|
+
"composer.lock": "🔒",
|
|
179
|
+
"pubspec.yaml": "🎯",
|
|
180
|
+
"pubspec.lock": "🔒",
|
|
181
|
+
|
|
182
|
+
# Docs
|
|
183
|
+
".md": "📝",
|
|
184
|
+
".mdx": "📝",
|
|
185
|
+
".rst": "📝",
|
|
186
|
+
".txt": "📄",
|
|
187
|
+
".pdf": "📕",
|
|
188
|
+
".doc": "📘",
|
|
189
|
+
".docx": "📘",
|
|
190
|
+
|
|
191
|
+
# Data
|
|
192
|
+
".csv": "📊",
|
|
193
|
+
".tsv": "📊",
|
|
194
|
+
".sql": "🗄️",
|
|
195
|
+
".db": "🗄️",
|
|
196
|
+
".sqlite": "🗄️",
|
|
197
|
+
".sqlite3": "🗄️",
|
|
198
|
+
".graphql": "🔺",
|
|
199
|
+
".gql": "🔺",
|
|
200
|
+
".proto": "📡",
|
|
201
|
+
|
|
202
|
+
# Media
|
|
203
|
+
".png": "🖼️",
|
|
204
|
+
".jpg": "🖼️",
|
|
205
|
+
".jpeg": "🖼️",
|
|
206
|
+
".gif": "🖼️",
|
|
207
|
+
".svg": "🎨",
|
|
208
|
+
".ico": "🖼️",
|
|
209
|
+
".webp": "🖼️",
|
|
210
|
+
".mp4": "🎥",
|
|
211
|
+
".mp3": "🎵",
|
|
212
|
+
".wav": "🎵",
|
|
213
|
+
".woff": "🔤",
|
|
214
|
+
".woff2": "🔤",
|
|
215
|
+
".ttf": "🔤",
|
|
216
|
+
".otf": "🔤",
|
|
217
|
+
|
|
218
|
+
# Git
|
|
219
|
+
".gitignore": "🙈",
|
|
220
|
+
".gitattributes": "🙈",
|
|
221
|
+
".gitmodules": "🙈",
|
|
222
|
+
|
|
223
|
+
# Editor configs
|
|
224
|
+
".editorconfig": "✏️",
|
|
225
|
+
".eslintrc": "🔍",
|
|
226
|
+
".eslintignore": "🔍",
|
|
227
|
+
".prettierrc": "💅",
|
|
228
|
+
".prettierignore": "💅",
|
|
229
|
+
".stylelintrc": "💅",
|
|
230
|
+
".babelrc": "🔄",
|
|
231
|
+
"babel.config.js": "🔄",
|
|
232
|
+
"webpack.config.js": "📦",
|
|
233
|
+
"vite.config.js": "⚡",
|
|
234
|
+
"vite.config.ts": "⚡",
|
|
235
|
+
"tailwind.config.js": "🌊",
|
|
236
|
+
"tailwind.config.ts": "🌊",
|
|
237
|
+
"tsconfig.json": "🔷",
|
|
238
|
+
"jsconfig.json": "🟨",
|
|
239
|
+
|
|
240
|
+
# Makefile / Build
|
|
241
|
+
"Makefile": "🔨",
|
|
242
|
+
"makefile": "🔨",
|
|
243
|
+
"CMakeLists.txt": "🔨",
|
|
244
|
+
"Taskfile.yml": "🔨",
|
|
245
|
+
|
|
246
|
+
# Notebooks / misc
|
|
247
|
+
".ipynb": "📓",
|
|
248
|
+
".http": "🌐",
|
|
249
|
+
".rest": "🌐",
|
|
250
|
+
".log": "📋",
|
|
251
|
+
".lock": "🔒",
|
|
252
|
+
".zip": "🗜️",
|
|
253
|
+
".tar": "🗜️",
|
|
254
|
+
".gz": "🗜️",
|
|
255
|
+
".rar": "🗜️",
|
|
256
|
+
|
|
257
|
+
# Default
|
|
258
|
+
"__default__": "📄",
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
|
|
262
|
+
def get_icon(name: str, is_dir: bool = False) -> str:
|
|
263
|
+
if is_dir:
|
|
264
|
+
return ICONS["__folder__"]
|
|
265
|
+
|
|
266
|
+
# Check full filename first (e.g. Dockerfile, Makefile)
|
|
267
|
+
if name in ICONS:
|
|
268
|
+
return ICONS[name]
|
|
269
|
+
|
|
270
|
+
# Check extension
|
|
271
|
+
ext = "." + name.rsplit(".", 1)[-1] if "." in name else ""
|
|
272
|
+
return ICONS.get(ext, ICONS["__default__"])
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import os
|
|
2
|
+
from .icons import get_icon
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
def build_tree(
|
|
6
|
+
root: str,
|
|
7
|
+
prefix: str = "",
|
|
8
|
+
max_depth: int = None,
|
|
9
|
+
current_depth: int = 0,
|
|
10
|
+
ignore: list = None,
|
|
11
|
+
dirs_only: bool = False,
|
|
12
|
+
use_icons: bool = True,
|
|
13
|
+
) -> list:
|
|
14
|
+
if ignore is None:
|
|
15
|
+
ignore = []
|
|
16
|
+
|
|
17
|
+
if max_depth is not None and current_depth >= max_depth:
|
|
18
|
+
return []
|
|
19
|
+
|
|
20
|
+
try:
|
|
21
|
+
entries = sorted(os.scandir(root), key=lambda e: (not e.is_dir(), e.name.lower()))
|
|
22
|
+
except (PermissionError, OSError):
|
|
23
|
+
return []
|
|
24
|
+
|
|
25
|
+
# Skip symlinks that point to directories to avoid infinite loops
|
|
26
|
+
entries = [e for e in entries if not (e.is_symlink() and e.is_dir())]
|
|
27
|
+
|
|
28
|
+
# Filter ignored
|
|
29
|
+
entries = [e for e in entries if e.name not in ignore]
|
|
30
|
+
|
|
31
|
+
# Filter files if dirs only
|
|
32
|
+
if dirs_only:
|
|
33
|
+
entries = [e for e in entries if e.is_dir()]
|
|
34
|
+
|
|
35
|
+
lines = []
|
|
36
|
+
for i, entry in enumerate(entries):
|
|
37
|
+
is_last = i == len(entries) - 1
|
|
38
|
+
connector = "└── " if is_last else "├── "
|
|
39
|
+
extension = " " if is_last else "│ "
|
|
40
|
+
|
|
41
|
+
icon = get_icon(entry.name, entry.is_dir()) + " " if use_icons else ""
|
|
42
|
+
trail = "/" if entry.is_dir() else ""
|
|
43
|
+
|
|
44
|
+
lines.append(f"{prefix}{connector}{icon}{entry.name}{trail}")
|
|
45
|
+
|
|
46
|
+
if entry.is_dir():
|
|
47
|
+
lines.extend(
|
|
48
|
+
build_tree(
|
|
49
|
+
root=entry.path,
|
|
50
|
+
prefix=prefix + extension,
|
|
51
|
+
max_depth=max_depth,
|
|
52
|
+
current_depth=current_depth + 1,
|
|
53
|
+
ignore=ignore,
|
|
54
|
+
dirs_only=dirs_only,
|
|
55
|
+
use_icons=use_icons,
|
|
56
|
+
)
|
|
57
|
+
)
|
|
58
|
+
|
|
59
|
+
return lines
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
def generate_tree(
|
|
63
|
+
path: str = ".",
|
|
64
|
+
max_depth: int = None,
|
|
65
|
+
ignore: list = None,
|
|
66
|
+
dirs_only: bool = False,
|
|
67
|
+
use_icons: bool = True,
|
|
68
|
+
) -> str:
|
|
69
|
+
path = os.path.abspath(path)
|
|
70
|
+
root_name = os.path.basename(path)
|
|
71
|
+
icon = get_icon(root_name, is_dir=True) + " " if use_icons else ""
|
|
72
|
+
|
|
73
|
+
lines = [f"{icon}{root_name}/"]
|
|
74
|
+
lines += build_tree(
|
|
75
|
+
root=path,
|
|
76
|
+
max_depth=max_depth,
|
|
77
|
+
ignore=ignore or [],
|
|
78
|
+
dirs_only=dirs_only,
|
|
79
|
+
use_icons=use_icons,
|
|
80
|
+
)
|
|
81
|
+
|
|
82
|
+
return "\n".join(lines)
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: abitree
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Generate beautiful file trees for your README
|
|
5
|
+
Author: Abidit Shrestha
|
|
6
|
+
License: MIT
|
|
7
|
+
Keywords: cli,tree,readme,file-tree,developer-tools
|
|
8
|
+
Classifier: Programming Language :: Python :: 3
|
|
9
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
10
|
+
Classifier: Operating System :: OS Independent
|
|
11
|
+
Classifier: Environment :: Console
|
|
12
|
+
Requires-Python: >=3.9
|
|
13
|
+
Description-Content-Type: text/markdown
|
|
14
|
+
|
|
15
|
+
# 🌳 abitree
|
|
16
|
+
|
|
17
|
+
Generate beautiful, icon-rich file trees for your README — instantly.
|
|
18
|
+
|
|
19
|
+
```
|
|
20
|
+
📁 my-project/
|
|
21
|
+
├── 📁 src/
|
|
22
|
+
│ ├── 🐍 main.py
|
|
23
|
+
│ ├── ⚛️ App.tsx
|
|
24
|
+
│ └── 🎨 styles.css
|
|
25
|
+
├── 📦 package.json
|
|
26
|
+
├── 🐳 Dockerfile
|
|
27
|
+
└── 📝 README.md
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## Installation
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
pip install abitree
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
## Usage
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
# Current directory
|
|
40
|
+
abitree
|
|
41
|
+
|
|
42
|
+
# Specific path
|
|
43
|
+
abitree ./my-project
|
|
44
|
+
|
|
45
|
+
# Limit depth
|
|
46
|
+
abitree -L 2
|
|
47
|
+
|
|
48
|
+
# Output to file
|
|
49
|
+
abitree -o structure.md
|
|
50
|
+
|
|
51
|
+
# Wrap in markdown code block
|
|
52
|
+
abitree --md
|
|
53
|
+
|
|
54
|
+
# Directories only
|
|
55
|
+
abitree --dirs-only
|
|
56
|
+
|
|
57
|
+
# Ignore extra folders
|
|
58
|
+
abitree -i dist,build,.cache
|
|
59
|
+
|
|
60
|
+
# No icons (plain text)
|
|
61
|
+
abitree --no-icons
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
## Options
|
|
65
|
+
|
|
66
|
+
| Flag | Description |
|
|
67
|
+
|------|-------------|
|
|
68
|
+
| `path` | Directory to scan (default: `.`) |
|
|
69
|
+
| `-L, --level` | Max depth |
|
|
70
|
+
| `-o, --output` | Write output to file |
|
|
71
|
+
| `-i, --ignore` | Comma-separated ignore list |
|
|
72
|
+
| `--dirs-only` | Show directories only |
|
|
73
|
+
| `--no-icons` | Disable icons |
|
|
74
|
+
| `--no-default-ignore` | Don't ignore `.git`, `node_modules`, etc. |
|
|
75
|
+
| `--md` | Wrap output in markdown code block |
|
|
76
|
+
|
|
77
|
+
## Default ignored
|
|
78
|
+
|
|
79
|
+
`.git`, `__pycache__`, `.DS_Store`, `.idea`, `.vscode`, `node_modules`
|
|
80
|
+
|
|
81
|
+
## Author
|
|
82
|
+
|
|
83
|
+
Built by [Abidit Shrestha](https://github.com/abiditshrestha)
|
|
84
|
+
|
|
85
|
+
## License
|
|
86
|
+
|
|
87
|
+
MIT
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
README.md
|
|
2
|
+
pyproject.toml
|
|
3
|
+
abitree/__init__.py
|
|
4
|
+
abitree/cli.py
|
|
5
|
+
abitree/icons.py
|
|
6
|
+
abitree/tree.py
|
|
7
|
+
abitree.egg-info/PKG-INFO
|
|
8
|
+
abitree.egg-info/SOURCES.txt
|
|
9
|
+
abitree.egg-info/dependency_links.txt
|
|
10
|
+
abitree.egg-info/entry_points.txt
|
|
11
|
+
abitree.egg-info/top_level.txt
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
abitree
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=68", "wheel"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "abitree"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
description = "Generate beautiful file trees for your README"
|
|
9
|
+
authors = [{ name = "Abidit Shrestha" }]
|
|
10
|
+
readme = "README.md"
|
|
11
|
+
license = { text = "MIT" }
|
|
12
|
+
requires-python = ">=3.9"
|
|
13
|
+
keywords = ["cli", "tree", "readme", "file-tree", "developer-tools"]
|
|
14
|
+
classifiers = [
|
|
15
|
+
"Programming Language :: Python :: 3",
|
|
16
|
+
"License :: OSI Approved :: MIT License",
|
|
17
|
+
"Operating System :: OS Independent",
|
|
18
|
+
"Environment :: Console",
|
|
19
|
+
]
|
|
20
|
+
|
|
21
|
+
[project.scripts]
|
|
22
|
+
abitree = "abitree.cli:main"
|
|
23
|
+
|
|
24
|
+
[tool.setuptools.packages.find]
|
|
25
|
+
where = ["."]
|
|
26
|
+
include = ["abitree*"]
|
abitree-0.1.0/setup.cfg
ADDED