fillmyfile 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.
Files changed (167) hide show
  1. fillmyfile-0.1.0/LICENSE +22 -0
  2. fillmyfile-0.1.0/PKG-INFO +116 -0
  3. fillmyfile-0.1.0/README.md +86 -0
  4. fillmyfile-0.1.0/fillmyfile/__init__.py +8 -0
  5. fillmyfile-0.1.0/fillmyfile/cli/__init__.py +0 -0
  6. fillmyfile-0.1.0/fillmyfile/cli/main.py +429 -0
  7. fillmyfile-0.1.0/fillmyfile/engine/__init__.py +0 -0
  8. fillmyfile-0.1.0/fillmyfile/engine/auto_indexer.py +9 -0
  9. fillmyfile-0.1.0/fillmyfile/engine/category_engine.py +28 -0
  10. fillmyfile-0.1.0/fillmyfile/engine/database_engine.py +92 -0
  11. fillmyfile-0.1.0/fillmyfile/engine/db_search_engine.py +63 -0
  12. fillmyfile-0.1.0/fillmyfile/engine/favorites_engine.py +77 -0
  13. fillmyfile-0.1.0/fillmyfile/engine/file_picker.py +32 -0
  14. fillmyfile-0.1.0/fillmyfile/engine/indexer_engine.py +141 -0
  15. fillmyfile-0.1.0/fillmyfile/engine/installer.py +18 -0
  16. fillmyfile-0.1.0/fillmyfile/engine/metadata_engine.py +41 -0
  17. fillmyfile-0.1.0/fillmyfile/engine/pack_manager.py +89 -0
  18. fillmyfile-0.1.0/fillmyfile/engine/paths.py +178 -0
  19. fillmyfile-0.1.0/fillmyfile/engine/preview_engine.py +48 -0
  20. fillmyfile-0.1.0/fillmyfile/engine/project_engine.py +86 -0
  21. fillmyfile-0.1.0/fillmyfile/engine/recents_engine.py +51 -0
  22. fillmyfile-0.1.0/fillmyfile/engine/search_engine.py +36 -0
  23. fillmyfile-0.1.0/fillmyfile/engine/snippet_engine.py +133 -0
  24. fillmyfile-0.1.0/fillmyfile/engine/statistics_engine.py +44 -0
  25. fillmyfile-0.1.0/fillmyfile/engine/template_creator.py +99 -0
  26. fillmyfile-0.1.0/fillmyfile/engine/template_deleter.py +61 -0
  27. fillmyfile-0.1.0/fillmyfile/engine/template_editor.py +27 -0
  28. fillmyfile-0.1.0/fillmyfile/engine/template_exporter.py +47 -0
  29. fillmyfile-0.1.0/fillmyfile/engine/template_importer.py +19 -0
  30. fillmyfile-0.1.0/fillmyfile/engine/variable_engine.py +6 -0
  31. fillmyfile-0.1.0/fillmyfile/engine/variable_prompt_engine.py +26 -0
  32. fillmyfile-0.1.0/fillmyfile/templates/projects/click-cli-app/meta.json +7 -0
  33. fillmyfile-0.1.0/fillmyfile/templates/projects/click-cli-app/template/README.md +3 -0
  34. fillmyfile-0.1.0/fillmyfile/templates/projects/click-cli-app/template/pyproject.toml +7 -0
  35. fillmyfile-0.1.0/fillmyfile/templates/projects/click-cli-app/template/src/{{package_name}}/__init__.py +1 -0
  36. fillmyfile-0.1.0/fillmyfile/templates/projects/click-cli-app/template/src/{{package_name}}/main.py +15 -0
  37. fillmyfile-0.1.0/fillmyfile/templates/projects/fastapi-service/meta.json +7 -0
  38. fillmyfile-0.1.0/fillmyfile/templates/projects/fastapi-service/template/README.md +7 -0
  39. fillmyfile-0.1.0/fillmyfile/templates/projects/fastapi-service/template/app/__init__.py +1 -0
  40. fillmyfile-0.1.0/fillmyfile/templates/projects/fastapi-service/template/app/main.py +8 -0
  41. fillmyfile-0.1.0/fillmyfile/templates/projects/fastapi-service/template/requirements.txt +2 -0
  42. fillmyfile-0.1.0/fillmyfile/templates/projects/pytest-project/meta.json +7 -0
  43. fillmyfile-0.1.0/fillmyfile/templates/projects/pytest-project/template/pyproject.toml +10 -0
  44. fillmyfile-0.1.0/fillmyfile/templates/projects/pytest-project/template/tests/test_smoke.py +2 -0
  45. fillmyfile-0.1.0/fillmyfile/templates/projects/python-module/meta.json +7 -0
  46. fillmyfile-0.1.0/fillmyfile/templates/projects/python-module/template/README.md +63 -0
  47. fillmyfile-0.1.0/fillmyfile/templates/projects/python-module/template/pyproject.toml +17 -0
  48. fillmyfile-0.1.0/fillmyfile/templates/projects/python-module/template/src/{{package_name}}/__init__.py +5 -0
  49. fillmyfile-0.1.0/fillmyfile/templates/projects/python-module/template/tests/test_hello.py +19 -0
  50. fillmyfile-0.1.0/fillmyfile/templates/projects/python-package/meta.json +7 -0
  51. fillmyfile-0.1.0/fillmyfile/templates/projects/python-package/template/README.md +3 -0
  52. fillmyfile-0.1.0/fillmyfile/templates/projects/python-package/template/pyproject.toml +10 -0
  53. fillmyfile-0.1.0/fillmyfile/templates/projects/python-package/template/src/{{package_name}}/__init__.py +1 -0
  54. fillmyfile-0.1.0/fillmyfile/templates/projects/sqlite-cli-tool/meta.json +7 -0
  55. fillmyfile-0.1.0/fillmyfile/templates/projects/sqlite-cli-tool/template/main.py +40 -0
  56. fillmyfile-0.1.0/fillmyfile/templates/projects/sqlite-cli-tool/template/requirements.txt +1 -0
  57. fillmyfile-0.1.0/fillmyfile/templates/projects/textual-tui/meta.json +7 -0
  58. fillmyfile-0.1.0/fillmyfile/templates/projects/textual-tui/template/app.py +15 -0
  59. fillmyfile-0.1.0/fillmyfile/templates/projects/textual-tui/template/requirements.txt +1 -0
  60. fillmyfile-0.1.0/fillmyfile/templates/snippets/ambulance-distance-time-fuel/meta.json +12 -0
  61. fillmyfile-0.1.0/fillmyfile/templates/snippets/ambulance-distance-time-fuel/template.py +54 -0
  62. fillmyfile-0.1.0/fillmyfile/templates/snippets/anime-file-menu/meta.json +12 -0
  63. fillmyfile-0.1.0/fillmyfile/templates/snippets/anime-file-menu/template.py +101 -0
  64. fillmyfile-0.1.0/fillmyfile/templates/snippets/argparse-cli/meta.json +7 -0
  65. fillmyfile-0.1.0/fillmyfile/templates/snippets/argparse-cli/template.py +17 -0
  66. fillmyfile-0.1.0/fillmyfile/templates/snippets/bfs-graph/meta.json +7 -0
  67. fillmyfile-0.1.0/fillmyfile/templates/snippets/bfs-graph/template.py +18 -0
  68. fillmyfile-0.1.0/fillmyfile/templates/snippets/binary-file-stack/meta.json +13 -0
  69. fillmyfile-0.1.0/fillmyfile/templates/snippets/binary-file-stack/template.py +263 -0
  70. fillmyfile-0.1.0/fillmyfile/templates/snippets/binary-search/meta.json +7 -0
  71. fillmyfile-0.1.0/fillmyfile/templates/snippets/binary-search/template.py +16 -0
  72. fillmyfile-0.1.0/fillmyfile/templates/snippets/book-stack-manager/meta.json +13 -0
  73. fillmyfile-0.1.0/fillmyfile/templates/snippets/book-stack-manager/template.py +182 -0
  74. fillmyfile-0.1.0/fillmyfile/templates/snippets/bubble-sort/meta.json +1 -0
  75. fillmyfile-0.1.0/fillmyfile/templates/snippets/bubble-sort/template.py +15 -0
  76. fillmyfile-0.1.0/fillmyfile/templates/snippets/bucket-sort/meta.json +1 -0
  77. fillmyfile-0.1.0/fillmyfile/templates/snippets/bucket-sort/template.py +22 -0
  78. fillmyfile-0.1.0/fillmyfile/templates/snippets/chudnovsky-pi/meta.json +1 -0
  79. fillmyfile-0.1.0/fillmyfile/templates/snippets/chudnovsky-pi/template.py +28 -0
  80. fillmyfile-0.1.0/fillmyfile/templates/snippets/click-command/meta.json +7 -0
  81. fillmyfile-0.1.0/fillmyfile/templates/snippets/click-command/template.py +16 -0
  82. fillmyfile-0.1.0/fillmyfile/templates/snippets/counting-sort/meta.json +1 -0
  83. fillmyfile-0.1.0/fillmyfile/templates/snippets/counting-sort/template.py +17 -0
  84. fillmyfile-0.1.0/fillmyfile/templates/snippets/decimal-to-binary-stack/meta.json +13 -0
  85. fillmyfile-0.1.0/fillmyfile/templates/snippets/decimal-to-binary-stack/tenplate.py +126 -0
  86. fillmyfile-0.1.0/fillmyfile/templates/snippets/dfs-graph/meta.json +7 -0
  87. fillmyfile-0.1.0/fillmyfile/templates/snippets/dfs-graph/template.py +16 -0
  88. fillmyfile-0.1.0/fillmyfile/templates/snippets/dijkstra/meta.json +7 -0
  89. fillmyfile-0.1.0/fillmyfile/templates/snippets/dijkstra/template.py +21 -0
  90. fillmyfile-0.1.0/fillmyfile/templates/snippets/edit-distance/meta.json +1 -0
  91. fillmyfile-0.1.0/fillmyfile/templates/snippets/edit-distance/template.py +21 -0
  92. fillmyfile-0.1.0/fillmyfile/templates/snippets/euclid-gcd/meta.json +1 -0
  93. fillmyfile-0.1.0/fillmyfile/templates/snippets/euclid-gcd/template.py +12 -0
  94. fillmyfile-0.1.0/fillmyfile/templates/snippets/fastapi-route/meta.json +7 -0
  95. fillmyfile-0.1.0/fillmyfile/templates/snippets/fastapi-route/template.py +13 -0
  96. fillmyfile-0.1.0/fillmyfile/templates/snippets/gamer-management-system/meta.json +13 -0
  97. fillmyfile-0.1.0/fillmyfile/templates/snippets/gamer-management-system/template.py +516 -0
  98. fillmyfile-0.1.0/fillmyfile/templates/snippets/heap-sort/meta.json +1 -0
  99. fillmyfile-0.1.0/fillmyfile/templates/snippets/heap-sort/template.py +8 -0
  100. fillmyfile-0.1.0/fillmyfile/templates/snippets/insertion-sort/meta.json +1 -0
  101. fillmyfile-0.1.0/fillmyfile/templates/snippets/insertion-sort/template.py +14 -0
  102. fillmyfile-0.1.0/fillmyfile/templates/snippets/kadane/meta.json +1 -0
  103. fillmyfile-0.1.0/fillmyfile/templates/snippets/kadane/template.py +12 -0
  104. fillmyfile-0.1.0/fillmyfile/templates/snippets/kmp-search/meta.json +1 -0
  105. fillmyfile-0.1.0/fillmyfile/templates/snippets/kmp-search/template.py +39 -0
  106. fillmyfile-0.1.0/fillmyfile/templates/snippets/lcs/meta.json +1 -0
  107. fillmyfile-0.1.0/fillmyfile/templates/snippets/lcs/template.py +13 -0
  108. fillmyfile-0.1.0/fillmyfile/templates/snippets/logger/meta.json +7 -0
  109. fillmyfile-0.1.0/fillmyfile/templates/snippets/logger/template.py +8 -0
  110. fillmyfile-0.1.0/fillmyfile/templates/snippets/lru-cache/meta.json +7 -0
  111. fillmyfile-0.1.0/fillmyfile/templates/snippets/lru-cache/template.py +9 -0
  112. fillmyfile-0.1.0/fillmyfile/templates/snippets/merge-sort/meta.json +1 -0
  113. fillmyfile-0.1.0/fillmyfile/templates/snippets/merge-sort/template.py +25 -0
  114. fillmyfile-0.1.0/fillmyfile/templates/snippets/pathlib-json/meta.json +7 -0
  115. fillmyfile-0.1.0/fillmyfile/templates/snippets/pathlib-json/template.py +13 -0
  116. fillmyfile-0.1.0/fillmyfile/templates/snippets/pydantic-model/meta.json +7 -0
  117. fillmyfile-0.1.0/fillmyfile/templates/snippets/pydantic-model/template.py +9 -0
  118. fillmyfile-0.1.0/fillmyfile/templates/snippets/pytest-test/meta.json +7 -0
  119. fillmyfile-0.1.0/fillmyfile/templates/snippets/pytest-test/template.py +7 -0
  120. fillmyfile-0.1.0/fillmyfile/templates/snippets/quick-sort/meta.json +1 -0
  121. fillmyfile-0.1.0/fillmyfile/templates/snippets/quick-sort/template.py +12 -0
  122. fillmyfile-0.1.0/fillmyfile/templates/snippets/radix-sort/meta.json +1 -0
  123. fillmyfile-0.1.0/fillmyfile/templates/snippets/radix-sort/template.py +21 -0
  124. fillmyfile-0.1.0/fillmyfile/templates/snippets/remove-position-character/meta.json +11 -0
  125. fillmyfile-0.1.0/fillmyfile/templates/snippets/remove-position-character/template.py +18 -0
  126. fillmyfile-0.1.0/fillmyfile/templates/snippets/requests-call/meta.json +7 -0
  127. fillmyfile-0.1.0/fillmyfile/templates/snippets/requests-call/template.py +9 -0
  128. fillmyfile-0.1.0/fillmyfile/templates/snippets/rich-table/meta.json +7 -0
  129. fillmyfile-0.1.0/fillmyfile/templates/snippets/rich-table/template.py +18 -0
  130. fillmyfile-0.1.0/fillmyfile/templates/snippets/selection-sort/meta.json +1 -0
  131. fillmyfile-0.1.0/fillmyfile/templates/snippets/selection-sort/template.py +13 -0
  132. fillmyfile-0.1.0/fillmyfile/templates/snippets/shell-sort/meta.json +1 -0
  133. fillmyfile-0.1.0/fillmyfile/templates/snippets/shell-sort/template.py +18 -0
  134. fillmyfile-0.1.0/fillmyfile/templates/snippets/sieve-primes/meta.json +1 -0
  135. fillmyfile-0.1.0/fillmyfile/templates/snippets/sieve-primes/template.py +14 -0
  136. fillmyfile-0.1.0/fillmyfile/templates/snippets/sliding-window/meta.json +7 -0
  137. fillmyfile-0.1.0/fillmyfile/templates/snippets/sliding-window/template.py +13 -0
  138. fillmyfile-0.1.0/fillmyfile/templates/snippets/smallest-digit-number/meta.json +11 -0
  139. fillmyfile-0.1.0/fillmyfile/templates/snippets/smallest-digit-number/template.py +22 -0
  140. fillmyfile-0.1.0/fillmyfile/templates/snippets/techfest-pass-manager/meta.json +13 -0
  141. fillmyfile-0.1.0/fillmyfile/templates/snippets/techfest-pass-manager/template.py +616 -0
  142. fillmyfile-0.1.0/fillmyfile/templates/snippets/textual-app/meta.json +7 -0
  143. fillmyfile-0.1.0/fillmyfile/templates/snippets/textual-app/template.py +17 -0
  144. fillmyfile-0.1.0/fillmyfile/templates/snippets/top-k-heap/meta.json +7 -0
  145. fillmyfile-0.1.0/fillmyfile/templates/snippets/top-k-heap/template.py +8 -0
  146. fillmyfile-0.1.0/fillmyfile/templates/snippets/topological-sort/meta.json +1 -0
  147. fillmyfile-0.1.0/fillmyfile/templates/snippets/topological-sort/template.py +27 -0
  148. fillmyfile-0.1.0/fillmyfile/templates/snippets/trie/meta.json +7 -0
  149. fillmyfile-0.1.0/fillmyfile/templates/snippets/trie/template.py +39 -0
  150. fillmyfile-0.1.0/fillmyfile/templates/snippets/two-pointers/meta.json +7 -0
  151. fillmyfile-0.1.0/fillmyfile/templates/snippets/two-pointers/template.py +16 -0
  152. fillmyfile-0.1.0/fillmyfile/templates/snippets/union-find/meta.json +7 -0
  153. fillmyfile-0.1.0/fillmyfile/templates/snippets/union-find/template.py +27 -0
  154. fillmyfile-0.1.0/fillmyfile/tui/__init__.py +0 -0
  155. fillmyfile-0.1.0/fillmyfile/tui/app.py +358 -0
  156. fillmyfile-0.1.0/fillmyfile/tui/preview_panel.py +21 -0
  157. fillmyfile-0.1.0/fillmyfile/tui/sidebar.py +38 -0
  158. fillmyfile-0.1.0/fillmyfile/tui/status_bar.py +8 -0
  159. fillmyfile-0.1.0/fillmyfile/tui/theme.py +46 -0
  160. fillmyfile-0.1.0/fillmyfile.egg-info/PKG-INFO +116 -0
  161. fillmyfile-0.1.0/fillmyfile.egg-info/SOURCES.txt +165 -0
  162. fillmyfile-0.1.0/fillmyfile.egg-info/dependency_links.txt +1 -0
  163. fillmyfile-0.1.0/fillmyfile.egg-info/entry_points.txt +2 -0
  164. fillmyfile-0.1.0/fillmyfile.egg-info/requires.txt +7 -0
  165. fillmyfile-0.1.0/fillmyfile.egg-info/top_level.txt +1 -0
  166. fillmyfile-0.1.0/pyproject.toml +51 -0
  167. fillmyfile-0.1.0/setup.cfg +4 -0
@@ -0,0 +1,22 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Vishnu. Made with Python.
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
22
+
@@ -0,0 +1,116 @@
1
+ Metadata-Version: 2.4
2
+ Name: fillmyfile
3
+ Version: 0.1.0
4
+ Summary: Offline developer snippet and project engine
5
+ Author: Vishnu
6
+ License: MIT
7
+ Keywords: snippets,templates,cli,tui,developer-tools
8
+ Classifier: Development Status :: 3 - Alpha
9
+ Classifier: Environment :: Console
10
+ Classifier: Intended Audience :: Developers
11
+ Classifier: License :: OSI Approved :: MIT License
12
+ Classifier: Programming Language :: Python :: 3
13
+ Classifier: Programming Language :: Python :: 3.10
14
+ Classifier: Programming Language :: Python :: 3.11
15
+ Classifier: Programming Language :: Python :: 3.12
16
+ Classifier: Programming Language :: Python :: 3.13
17
+ Classifier: Topic :: Software Development :: Code Generators
18
+ Classifier: Topic :: Utilities
19
+ Requires-Python: >=3.10
20
+ Description-Content-Type: text/markdown
21
+ License-File: LICENSE
22
+ Requires-Dist: click
23
+ Requires-Dist: rich
24
+ Requires-Dist: jinja2
25
+ Requires-Dist: rapidfuzz
26
+ Requires-Dist: pyperclip
27
+ Requires-Dist: textual
28
+ Requires-Dist: platformdirs
29
+ Dynamic: license-file
30
+
31
+ # FillMyFile
32
+
33
+ FillMyFile is an offline snippet and project-template manager for developers.
34
+ It lets you save reusable code snippets, create projects from local templates,
35
+ search them from the CLI or TUI, and share libraries as zip packs.
36
+
37
+ ## Install
38
+
39
+ ```bash
40
+ pip install fillmyfile
41
+ ```
42
+
43
+ For local development:
44
+
45
+ ```bash
46
+ pip install -e .
47
+ ```
48
+
49
+ ## Quick Start
50
+
51
+ ```bash
52
+ fillmyfile init
53
+ fillmyfile list
54
+ fillmyfile search logger
55
+ fillmyfile use logger ./scratch.py
56
+ ```
57
+
58
+ ## Add Your Own Snippets
59
+
60
+ ```bash
61
+ fillmyfile add snippet click-command ./command.py \
62
+ --description "Click command skeleton" \
63
+ --category python \
64
+ --tags cli,click
65
+ ```
66
+
67
+ Project templates work the same way:
68
+
69
+ ```bash
70
+ fillmyfile add project fastapi-service ./my-fastapi-folder \
71
+ --description "FastAPI service starter" \
72
+ --category web \
73
+ --tags fastapi,api
74
+ ```
75
+
76
+ ## Share Packs
77
+
78
+ Install a pack folder:
79
+
80
+ ```bash
81
+ fillmyfile pack install ./my-pack
82
+ ```
83
+
84
+ Export your local library:
85
+
86
+ ```bash
87
+ fillmyfile pack export my-team-pack
88
+ ```
89
+
90
+ ## Useful Commands
91
+
92
+ ```bash
93
+ fillmyfile init
94
+ fillmyfile list --type snippet
95
+ fillmyfile list --type project
96
+ fillmyfile search auth
97
+ fillmyfile dbsearch api
98
+ fillmyfile info logger
99
+ fillmyfile use logger ./app.py
100
+ fillmyfile create click-cli-app my-tool
101
+ fillmyfile export logger
102
+ fillmyfile import ./logger.zip
103
+ fillmyfile tui ./app.py
104
+ ```
105
+
106
+ ## Where Data Lives
107
+
108
+ FillMyFile keeps user snippets, projects, packs, and its SQLite index in the
109
+ operating system's user data directory. The installed Python package stays
110
+ read-only and safe to upgrade.
111
+
112
+ ## License & Credits
113
+
114
+ © 2026 Vishnu. Made with Python.
115
+ Licensed under the [MIT License](LICENSE).
116
+
@@ -0,0 +1,86 @@
1
+ # FillMyFile
2
+
3
+ FillMyFile is an offline snippet and project-template manager for developers.
4
+ It lets you save reusable code snippets, create projects from local templates,
5
+ search them from the CLI or TUI, and share libraries as zip packs.
6
+
7
+ ## Install
8
+
9
+ ```bash
10
+ pip install fillmyfile
11
+ ```
12
+
13
+ For local development:
14
+
15
+ ```bash
16
+ pip install -e .
17
+ ```
18
+
19
+ ## Quick Start
20
+
21
+ ```bash
22
+ fillmyfile init
23
+ fillmyfile list
24
+ fillmyfile search logger
25
+ fillmyfile use logger ./scratch.py
26
+ ```
27
+
28
+ ## Add Your Own Snippets
29
+
30
+ ```bash
31
+ fillmyfile add snippet click-command ./command.py \
32
+ --description "Click command skeleton" \
33
+ --category python \
34
+ --tags cli,click
35
+ ```
36
+
37
+ Project templates work the same way:
38
+
39
+ ```bash
40
+ fillmyfile add project fastapi-service ./my-fastapi-folder \
41
+ --description "FastAPI service starter" \
42
+ --category web \
43
+ --tags fastapi,api
44
+ ```
45
+
46
+ ## Share Packs
47
+
48
+ Install a pack folder:
49
+
50
+ ```bash
51
+ fillmyfile pack install ./my-pack
52
+ ```
53
+
54
+ Export your local library:
55
+
56
+ ```bash
57
+ fillmyfile pack export my-team-pack
58
+ ```
59
+
60
+ ## Useful Commands
61
+
62
+ ```bash
63
+ fillmyfile init
64
+ fillmyfile list --type snippet
65
+ fillmyfile list --type project
66
+ fillmyfile search auth
67
+ fillmyfile dbsearch api
68
+ fillmyfile info logger
69
+ fillmyfile use logger ./app.py
70
+ fillmyfile create click-cli-app my-tool
71
+ fillmyfile export logger
72
+ fillmyfile import ./logger.zip
73
+ fillmyfile tui ./app.py
74
+ ```
75
+
76
+ ## Where Data Lives
77
+
78
+ FillMyFile keeps user snippets, projects, packs, and its SQLite index in the
79
+ operating system's user data directory. The installed Python package stays
80
+ read-only and safe to upgrade.
81
+
82
+ ## License & Credits
83
+
84
+ © 2026 Vishnu. Made with Python.
85
+ Licensed under the [MIT License](LICENSE).
86
+
@@ -0,0 +1,8 @@
1
+ """FillMyFile - Offline developer snippet and project engine.
2
+
3
+ © 2026 Vishnu. Made with Python.
4
+ """
5
+
6
+ __version__ = "0.1.0"
7
+ __author__ = "Vishnu"
8
+ __copyright__ = "© 2026 Vishnu. Made with Python."
File without changes
@@ -0,0 +1,429 @@
1
+ import click
2
+ from rich import print
3
+
4
+ from fillmyfile.engine.database_engine import DatabaseEngine
5
+ from fillmyfile.engine.db_search_engine import DBSearchEngine
6
+ from fillmyfile.engine.favorites_engine import FavoritesEngine
7
+ from fillmyfile.engine.file_picker import FilePicker
8
+ from fillmyfile.engine.indexer_engine import IndexerEngine
9
+ from fillmyfile.engine.installer import Installer
10
+ from fillmyfile.engine.metadata_engine import MetadataEngine
11
+ from fillmyfile.engine.pack_manager import PackManager
12
+ from fillmyfile.engine.paths import (
13
+ DATA_DIR,
14
+ PROJECTS_DIR,
15
+ SNIPPETS_DIR,
16
+ copy_starter_templates,
17
+ ensure_app_dirs,
18
+ )
19
+ from fillmyfile.engine.project_engine import ProjectEngine
20
+ from fillmyfile.engine.recents_engine import RecentsEngine
21
+ from fillmyfile.engine.search_engine import SearchEngine
22
+ from fillmyfile.engine.snippet_engine import SnippetEngine
23
+ from fillmyfile.engine.statistics_engine import StatisticsEngine
24
+ from fillmyfile.engine.template_creator import TemplateCreator
25
+ from fillmyfile.engine.template_deleter import TemplateDeleter
26
+ from fillmyfile.engine.template_editor import TemplateEditor
27
+ from fillmyfile.engine.template_exporter import TemplateExporter
28
+ from fillmyfile.engine.template_importer import TemplateImporter
29
+
30
+
31
+ def bootstrap(seed=False, force_seed=False):
32
+ ensure_app_dirs()
33
+ DatabaseEngine.initialize()
34
+
35
+ library_is_empty = not any(SNIPPETS_DIR.iterdir()) and not any(
36
+ PROJECTS_DIR.iterdir()
37
+ )
38
+
39
+ if seed or library_is_empty:
40
+ copy_starter_templates(force_seed)
41
+ else:
42
+ copy_starter_templates(False)
43
+
44
+ IndexerEngine.rebuild_index()
45
+
46
+
47
+ def parse_tags(tags):
48
+ return [
49
+ tag.strip()
50
+ for tag in tags.split(",")
51
+ if tag.strip()
52
+ ]
53
+
54
+
55
+ @click.group()
56
+ def cli():
57
+ """Offline snippet and project template manager."""
58
+
59
+
60
+ @cli.command()
61
+ @click.option("--force", is_flag=True, help="Overwrite bundled starter templates.")
62
+ def init(force):
63
+ """Create the FillMyFile library and seed starter templates."""
64
+
65
+ bootstrap(seed=True, force_seed=force)
66
+ print(f"[green]FillMyFile is ready at {DATA_DIR}[/green]")
67
+
68
+
69
+ @cli.command("list")
70
+ @click.option(
71
+ "--type",
72
+ "template_type",
73
+ type=click.Choice(["snippet", "project"]),
74
+ default="snippet",
75
+ )
76
+ def list_templates(template_type):
77
+ """List templates in the local library."""
78
+
79
+ bootstrap()
80
+
81
+ if template_type == "snippet":
82
+ items = SnippetEngine.list_snippets()
83
+ else:
84
+ items = [
85
+ item["name"]
86
+ for item in MetadataEngine.load_all_metadata("project")
87
+ ]
88
+
89
+ print(f"\n[bold white]Available {template_type.title()}s[/bold white]\n")
90
+
91
+ for item in items:
92
+ print(f"- {item}")
93
+
94
+
95
+ @cli.command()
96
+ @click.argument("name")
97
+ @click.argument("target")
98
+ def use(name, target):
99
+ """Render a snippet into a target file."""
100
+
101
+ bootstrap()
102
+
103
+ try:
104
+ SnippetEngine.insert_snippet(name, target)
105
+ print(f"[green]Inserted '{name}' into {target}[/green]")
106
+ except Exception as error:
107
+ print(f"[red]{error}[/red]")
108
+
109
+
110
+ @cli.command()
111
+ @click.argument("template")
112
+ @click.argument("project_name")
113
+ @click.option(
114
+ "--install/--no-install",
115
+ default=False,
116
+ help="Install requirements.txt after creating the project.",
117
+ )
118
+ def create(template, project_name, install):
119
+ """Create a project from a saved project template."""
120
+
121
+ bootstrap()
122
+
123
+ try:
124
+ project_path = ProjectEngine.create_project(template, project_name)
125
+
126
+ if install:
127
+ Installer.install_requirements(project_path)
128
+
129
+ print(f"[green]Project '{project_name}' created at {project_path}[/green]")
130
+ except Exception as error:
131
+ print(f"[red]{error}[/red]")
132
+
133
+
134
+ @cli.command()
135
+ @click.argument("query")
136
+ @click.option(
137
+ "--type",
138
+ "template_type",
139
+ type=click.Choice(["snippet", "project"]),
140
+ default=None,
141
+ )
142
+ def search(query, template_type):
143
+ """Search templates from metadata files."""
144
+
145
+ bootstrap()
146
+ results = SearchEngine.search(query, template_type)
147
+
148
+ print(f"\n[bold white]Results for '{query}'[/bold white]\n")
149
+
150
+ if not results:
151
+ print("[red]No results found[/red]")
152
+ return
153
+
154
+ for result in results:
155
+ print(f"- {result['name']} [white]({result['category']})[/white]")
156
+
157
+
158
+ @cli.command()
159
+ @click.argument("query")
160
+ @click.option(
161
+ "--type",
162
+ "template_type",
163
+ type=click.Choice(["snippet", "project"]),
164
+ default=None,
165
+ )
166
+ def dbsearch(query, template_type):
167
+ """Search templates from the local SQLite index."""
168
+
169
+ bootstrap()
170
+ results = DBSearchEngine.search(query, template_type)
171
+
172
+ print(f"\n[bold white]Database Results for '{query}'[/bold white]\n")
173
+
174
+ if not results:
175
+ print("[red]No results found[/red]")
176
+ return
177
+
178
+ for result in results:
179
+ print(f"- {result['name']} [white]({result['category']})[/white]")
180
+
181
+
182
+ @cli.command()
183
+ @click.argument("name")
184
+ def info(name):
185
+ """Show metadata for one template."""
186
+
187
+ bootstrap()
188
+ templates = MetadataEngine.load_all_metadata()
189
+
190
+ for template in templates:
191
+ if template["name"] == name:
192
+ print()
193
+ print(f"[bold white]{template['name']}[/bold white]")
194
+ print(f"[white]Type:[/white] {template.get('type', '')}")
195
+ print(f"[white]Category:[/white] {template.get('category', '')}")
196
+ print(f"[white]Description:[/white] {template.get('description', '')}")
197
+ print(f"[white]Tags:[/white] {', '.join(template.get('tags', []))}")
198
+ print()
199
+ return
200
+
201
+ print(f"[red]Template '{name}' not found[/red]")
202
+
203
+
204
+ @cli.command()
205
+ def index():
206
+ """Rebuild the SQLite template index."""
207
+
208
+ try:
209
+ bootstrap()
210
+ print("[green]Template index rebuilt successfully[/green]")
211
+ except Exception as error:
212
+ print(f"[red]{error}[/red]")
213
+
214
+
215
+ @cli.group()
216
+ def add():
217
+ """Add snippets or project templates to your library."""
218
+
219
+
220
+ @add.command("snippet")
221
+ @click.argument("name")
222
+ @click.argument("source_file", required=False)
223
+ @click.option("--description", prompt=True)
224
+ @click.option("--category", prompt=True)
225
+ @click.option("--tags", prompt="Tags (comma separated)", default="")
226
+ def add_snippet(name, source_file, description, category, tags):
227
+ """Add a snippet from a source file."""
228
+
229
+ bootstrap()
230
+
231
+ if not source_file:
232
+ print("Choose snippet file...")
233
+ source_file = FilePicker.pick_file()
234
+
235
+ try:
236
+ TemplateCreator.create_snippet(
237
+ name,
238
+ source_file,
239
+ description,
240
+ category,
241
+ parse_tags(tags),
242
+ )
243
+ print(f"[green]Snippet '{name}' added[/green]")
244
+ except Exception as error:
245
+ print(f"[red]{error}[/red]")
246
+
247
+
248
+ @add.command("project")
249
+ @click.argument("name")
250
+ @click.argument("source_folder", required=False)
251
+ @click.option("--description", prompt=True)
252
+ @click.option("--category", prompt=True)
253
+ @click.option("--tags", prompt="Tags (comma separated)", default="")
254
+ def add_project(name, source_folder, description, category, tags):
255
+ """Add a project template from a folder."""
256
+
257
+ bootstrap()
258
+
259
+ if not source_folder:
260
+ print("Choose project folder...")
261
+ source_folder = FilePicker.pick_folder()
262
+
263
+ try:
264
+ TemplateCreator.create_project(
265
+ name,
266
+ source_folder,
267
+ description,
268
+ category,
269
+ parse_tags(tags),
270
+ )
271
+ print(f"[green]Project template '{name}' added[/green]")
272
+ except Exception as error:
273
+ print(f"[red]{error}[/red]")
274
+
275
+
276
+ @cli.group()
277
+ def new():
278
+ """Backward-compatible alias for add."""
279
+
280
+
281
+ new.add_command(add_snippet, "snippet")
282
+ new.add_command(add_project, "project")
283
+
284
+
285
+ @cli.command()
286
+ @click.argument("name")
287
+ def remove(name):
288
+ """Remove a template from the local library."""
289
+
290
+ bootstrap()
291
+
292
+ try:
293
+ if TemplateDeleter.delete(name):
294
+ print(f"[green]Removed '{name}'[/green]")
295
+ else:
296
+ print(f"[red]Template '{name}' not found[/red]")
297
+ except Exception as error:
298
+ print(f"[red]{error}[/red]")
299
+
300
+
301
+ @cli.command()
302
+ @click.argument("name")
303
+ def edit(name):
304
+ """Open a template folder in the OS file browser."""
305
+
306
+ bootstrap()
307
+
308
+ if not TemplateEditor.edit(name):
309
+ print(f"[red]Template '{name}' not found[/red]")
310
+
311
+
312
+ @cli.command("export")
313
+ @click.argument("name")
314
+ @click.option("--destination", default=None, help="Folder for the exported zip.")
315
+ def export_template(name, destination):
316
+ """Export one template as a zip file."""
317
+
318
+ bootstrap()
319
+
320
+ try:
321
+ archive = TemplateExporter.export(name, destination)
322
+ if archive:
323
+ print(f"[green]Exported to {archive}[/green]")
324
+ else:
325
+ print(f"[red]Template '{name}' not found[/red]")
326
+ except Exception as error:
327
+ print(f"[red]{error}[/red]")
328
+
329
+
330
+ @cli.command("import")
331
+ @click.argument("zip_path")
332
+ def import_template(zip_path):
333
+ """Import a template or pack zip."""
334
+
335
+ bootstrap()
336
+
337
+ try:
338
+ TemplateImporter.import_zip(zip_path)
339
+ print("[green]Import complete[/green]")
340
+ except Exception as error:
341
+ print(f"[red]{error}[/red]")
342
+
343
+
344
+ @cli.group()
345
+ def pack():
346
+ """Install or export snippet packs."""
347
+
348
+
349
+ @pack.command("install")
350
+ @click.argument("folder_path")
351
+ def pack_install(folder_path):
352
+ """Install a pack folder containing snippets/ and/or projects/."""
353
+
354
+ bootstrap()
355
+
356
+ try:
357
+ PackManager.install_pack(folder_path)
358
+ print("[green]Pack installed[/green]")
359
+ except Exception as error:
360
+ print(f"[red]{error}[/red]")
361
+
362
+
363
+ @pack.command("export")
364
+ @click.argument("name", default="fillmyfile-pack")
365
+ @click.option("--destination", default=None, help="Folder for the exported pack zip.")
366
+ def pack_export(name, destination):
367
+ """Export the whole local library as a pack zip."""
368
+
369
+ bootstrap()
370
+
371
+ try:
372
+ archive = PackManager.export_pack(name, destination)
373
+ print(f"[green]Exported pack to {archive}[/green]")
374
+ except Exception as error:
375
+ print(f"[red]{error}[/red]")
376
+
377
+
378
+ @cli.command()
379
+ @click.argument("name")
380
+ def favorite(name):
381
+ """Mark a template as a favorite."""
382
+
383
+ bootstrap()
384
+ FavoritesEngine.add(name)
385
+ FavoritesEngine.mark(name, True)
386
+ print(f"[green]'{name}' added to favorites[/green]")
387
+
388
+
389
+ @cli.command()
390
+ def recent():
391
+ """Show recently used snippets."""
392
+
393
+ bootstrap()
394
+ items = RecentsEngine.get_recent()
395
+
396
+ print("\n[bold white]Recent Templates[/bold white]\n")
397
+
398
+ for item in items:
399
+ print(f"- {item}")
400
+
401
+
402
+ @cli.command()
403
+ def top():
404
+ """Show most-used snippets."""
405
+
406
+ bootstrap()
407
+ rows = StatisticsEngine.get_top_used()
408
+
409
+ print("\n[bold white]Top Used Templates[/bold white]\n")
410
+
411
+ for row in rows:
412
+ print(f"- {row[0]} ({row[1]} uses)")
413
+
414
+
415
+ @cli.command()
416
+ @click.argument("target_file", required=False)
417
+ def tui(target_file):
418
+ """Launch the terminal UI."""
419
+
420
+ bootstrap()
421
+
422
+ from fillmyfile.tui.app import FillMyFileApp
423
+
424
+ app = FillMyFileApp(target_file)
425
+ app.run()
426
+
427
+
428
+ if __name__ == "__main__":
429
+ cli()
File without changes
@@ -0,0 +1,9 @@
1
+ from fillmyfile.engine.indexer_engine import IndexerEngine
2
+
3
+
4
+ class AutoIndexer:
5
+
6
+ @staticmethod
7
+ def rebuild():
8
+
9
+ IndexerEngine.rebuild_index()
@@ -0,0 +1,28 @@
1
+ from fillmyfile.engine.database_engine import DatabaseEngine
2
+
3
+
4
+ class CategoryEngine:
5
+
6
+ @staticmethod
7
+ def get_categories(template_type=None):
8
+
9
+ conn = DatabaseEngine.connect()
10
+ cursor = conn.cursor()
11
+
12
+ cursor.execute(
13
+ """
14
+ SELECT DISTINCT category
15
+ FROM templates
16
+ WHERE (? IS NULL OR type = ?)
17
+ """
18
+ ,
19
+ (template_type, template_type)
20
+ )
21
+
22
+ rows = cursor.fetchall()
23
+
24
+ conn.close()
25
+
26
+ return sorted(
27
+ [row[0] for row in rows if row[0]]
28
+ )