developer-assistant 0.3.0__tar.gz → 0.3.5__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 (27) hide show
  1. {developer_assistant-0.3.0/developer_assistant.egg-info → developer_assistant-0.3.5}/PKG-INFO +29 -7
  2. {developer_assistant-0.3.0 → developer_assistant-0.3.5}/PYPI.md +28 -3
  3. {developer_assistant-0.3.0 → developer_assistant-0.3.5}/README.md +44 -11
  4. {developer_assistant-0.3.0 → developer_assistant-0.3.5}/da/default/test-project.ini +3 -1
  5. {developer_assistant-0.3.0 → developer_assistant-0.3.5}/da/interface.py +19 -12
  6. {developer_assistant-0.3.0 → developer_assistant-0.3.5}/da/intro.md +22 -3
  7. {developer_assistant-0.3.0 → developer_assistant-0.3.5}/da/modules/config_manager.py +1 -2
  8. {developer_assistant-0.3.0 → developer_assistant-0.3.5}/da/modules/opener.py +0 -2
  9. {developer_assistant-0.3.0 → developer_assistant-0.3.5}/da/modules/projects_manager.py +28 -25
  10. {developer_assistant-0.3.0 → developer_assistant-0.3.5}/da/modules/version_logic.py +95 -85
  11. developer_assistant-0.3.5/da/templates/changelog_template.txt +5 -0
  12. {developer_assistant-0.3.0 → developer_assistant-0.3.5/developer_assistant.egg-info}/PKG-INFO +29 -7
  13. {developer_assistant-0.3.0 → developer_assistant-0.3.5}/pyproject.toml +1 -4
  14. developer_assistant-0.3.0/da/templates/changelog_template.txt +0 -6
  15. {developer_assistant-0.3.0 → developer_assistant-0.3.5}/LICENSE +0 -0
  16. {developer_assistant-0.3.0 → developer_assistant-0.3.5}/da/__init__.py +0 -0
  17. {developer_assistant-0.3.0 → developer_assistant-0.3.5}/da/default/default-changelog.md +0 -0
  18. {developer_assistant-0.3.0 → developer_assistant-0.3.5}/da/default/default-memory.ini +0 -0
  19. {developer_assistant-0.3.0 → developer_assistant-0.3.5}/da/modules/__init__.py +0 -0
  20. {developer_assistant-0.3.0 → developer_assistant-0.3.5}/da/templates/entry_template.txt +0 -0
  21. {developer_assistant-0.3.0 → developer_assistant-0.3.5}/da/templates/header_template.txt +0 -0
  22. {developer_assistant-0.3.0 → developer_assistant-0.3.5}/developer_assistant.egg-info/SOURCES.txt +0 -0
  23. {developer_assistant-0.3.0 → developer_assistant-0.3.5}/developer_assistant.egg-info/dependency_links.txt +0 -0
  24. {developer_assistant-0.3.0 → developer_assistant-0.3.5}/developer_assistant.egg-info/entry_points.txt +0 -0
  25. {developer_assistant-0.3.0 → developer_assistant-0.3.5}/developer_assistant.egg-info/requires.txt +0 -0
  26. {developer_assistant-0.3.0 → developer_assistant-0.3.5}/developer_assistant.egg-info/top_level.txt +0 -0
  27. {developer_assistant-0.3.0 → developer_assistant-0.3.5}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: developer-assistant
3
- Version: 0.3.0
3
+ Version: 0.3.5
4
4
  Summary: A lightweight TUI app for managing and simplifying your Markdown changelogs.
5
5
  License: The MIT License (MIT)
6
6
 
@@ -12,11 +12,8 @@ License: The MIT License (MIT)
12
12
 
13
13
  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
14
14
  Project-URL: Homepage, https://github.com/Ivory-Hubert/Developer-Assistant
15
- Project-URL: Repository, https://github.com/Ivory-Hubert/Developer-Assistant.git
16
- Project-URL: Issues, https://github.com/Ivory-Hubert/Developer-Assistant/issues
17
15
  Project-URL: Changelog, https://github.com/Ivory-Hubert/Developer-Assistant/blob/main/CHANGELOG.md
18
16
  Classifier: Programming Language :: Python :: 3
19
- Classifier: License :: OSI Approved :: MIT License
20
17
  Classifier: Operating System :: OS Independent
21
18
  Classifier: Environment :: Console
22
19
  Classifier: Topic :: Software Development :: Libraries :: Python Modules
@@ -32,6 +29,9 @@ Dynamic: license-file
32
29
  # Developer Assistant
33
30
 
34
31
  ## Installing from PyPI
32
+
33
+ The program is designed for minimal friction and simple setup. Only installation is required, on first run DA will create local user data automatically. The same process is used for new profiles.
34
+
35
35
  **Using uv:**
36
36
  `uv tool install developer-assistant`
37
37
 
@@ -53,17 +53,18 @@ A. **Using uv:** `uv tool upgrade developer-assistant`
53
53
 
54
54
  B. **Using pip:** `python -m pip install -U developer-assistant`
55
55
 
56
+
56
57
  ## Introduction
57
58
 
58
59
  ### What does this tool do?
59
- Developer Assistant is a lightweight TUI app for simplifying and managing your changelogs. You can customize the templates for each profile to match your existing format, and use DA as a central hub to access every changelog and project folder you maintain.
60
+ Developer Assistant is a lightweight TUI for simplifying and managing your changelogs. You can customize the templates for **each profile** to match your existing format, and use DA as a central hub to access every changelog and project folder you maintain.
60
61
 
61
- You can create as many profiles as you need. Each profile gets its own **project specific** `.ini` files, created automatically through the menu based on the information you provide. These act as links that tell DA where your changelogs are and what's the last version number.
62
+ You can create as many profiles as you need. Each profile gets its own **project specific** `.ini` files, created automatically through the menu based on the information you provide. These act as links that tell DA where your changelogs are, which profile owns them and what's the last version number.
62
63
 
63
64
  Your files are kept safe at all times. Before adding new changes, your existing `CHANGELOG.md` is automatically backed up. While editing, all changes are written to a temporary file first and only prepended to & replaced with your real changelog once you confirm them.
64
65
 
65
66
 
66
- ## Using the program.
67
+ ### Using the program.
67
68
  1. **What *not* to do**
68
69
 
69
70
  Don't change the folder structure or modify variable names inside `.ini` files.
@@ -88,14 +89,33 @@ The program comes with the "Default" profile, you can choose to either stick wit
88
89
 
89
90
  Migrating a project or template from one profile to another is currently manual, **make sure to also change the "*owner*" value in `.ini` files accordingly**.
90
91
 
92
+ ---
93
+
91
94
  **Customizable templates**
92
95
 
93
96
  In the **local** `Templates/` folder you can modify the template contents to your liking - **just avoid changing the `{{placeholder}}` names**.
94
97
 
98
+ Templates come in three flavours:
99
+
100
+ * changelog_template.txt - *Changelog title*
101
+
102
+ * header_template.txt - *Version and date*
103
+
104
+ * entry_template.txt - *Change entry and comments*
105
+
106
+
95
107
  **Linked projects all in one place**
96
108
 
97
109
  The `Projects/` folder holds the `.ini` files you create when starting a new project with DA.
98
110
 
111
+ [Project.ini example](./documents/project-example.ini)
112
+
113
+ The `command` variable is a custom command that DA will run in your project folder once you choose "Format & commit" in `Main menu / Projects / Project menu / Changelog`. Even when provided, it is **not** run without your confirmation, first it's printed with the folder name and you can choose to skip it.
114
+
115
+ `owner` & `edited` are filled out automatically when a new project is created and `edited` updates with every changelog update.
116
+
117
+ ---
118
+
99
119
  **Safe changelog updates**
100
120
 
101
121
  Before applying any changes, your previous `CHANGELOG.md` is automatically backed up into your project folder.
@@ -104,10 +124,12 @@ New changes are first written to a temporary file and only prepended to & replac
104
124
  This ensures your existing changelog is never overwritten or corrupted, and you always have a fallback copy.
105
125
  If the temporary changelog is present on startup you are prompted to remove or keep it.
106
126
 
127
+
107
128
  **Ease of navigation**
108
129
 
109
130
  You can access files/folders and configuration straight from the menus, so you shouldn't find yourself searching through the program's directory or even your local user data very often.
110
131
 
132
+
111
133
  **Configuration**
112
134
 
113
135
  The `memory.ini` file does exactly what you'd expect, it features:
@@ -1,6 +1,9 @@
1
1
  # Developer Assistant
2
2
 
3
3
  ## Installing from PyPI
4
+
5
+ The program is designed for minimal friction and simple setup. Only installation is required, on first run DA will create local user data automatically. The same process is used for new profiles.
6
+
4
7
  **Using uv:**
5
8
  `uv tool install developer-assistant`
6
9
 
@@ -22,17 +25,18 @@ A. **Using uv:** `uv tool upgrade developer-assistant`
22
25
 
23
26
  B. **Using pip:** `python -m pip install -U developer-assistant`
24
27
 
28
+
25
29
  ## Introduction
26
30
 
27
31
  ### What does this tool do?
28
- Developer Assistant is a lightweight TUI app for simplifying and managing your changelogs. You can customize the templates for each profile to match your existing format, and use DA as a central hub to access every changelog and project folder you maintain.
32
+ Developer Assistant is a lightweight TUI for simplifying and managing your changelogs. You can customize the templates for **each profile** to match your existing format, and use DA as a central hub to access every changelog and project folder you maintain.
29
33
 
30
- You can create as many profiles as you need. Each profile gets its own **project specific** `.ini` files, created automatically through the menu based on the information you provide. These act as links that tell DA where your changelogs are and what's the last version number.
34
+ You can create as many profiles as you need. Each profile gets its own **project specific** `.ini` files, created automatically through the menu based on the information you provide. These act as links that tell DA where your changelogs are, which profile owns them and what's the last version number.
31
35
 
32
36
  Your files are kept safe at all times. Before adding new changes, your existing `CHANGELOG.md` is automatically backed up. While editing, all changes are written to a temporary file first and only prepended to & replaced with your real changelog once you confirm them.
33
37
 
34
38
 
35
- ## Using the program.
39
+ ### Using the program.
36
40
  1. **What *not* to do**
37
41
 
38
42
  Don't change the folder structure or modify variable names inside `.ini` files.
@@ -57,14 +61,33 @@ The program comes with the "Default" profile, you can choose to either stick wit
57
61
 
58
62
  Migrating a project or template from one profile to another is currently manual, **make sure to also change the "*owner*" value in `.ini` files accordingly**.
59
63
 
64
+ ---
65
+
60
66
  **Customizable templates**
61
67
 
62
68
  In the **local** `Templates/` folder you can modify the template contents to your liking - **just avoid changing the `{{placeholder}}` names**.
63
69
 
70
+ Templates come in three flavours:
71
+
72
+ * changelog_template.txt - *Changelog title*
73
+
74
+ * header_template.txt - *Version and date*
75
+
76
+ * entry_template.txt - *Change entry and comments*
77
+
78
+
64
79
  **Linked projects all in one place**
65
80
 
66
81
  The `Projects/` folder holds the `.ini` files you create when starting a new project with DA.
67
82
 
83
+ [Project.ini example](./documents/project-example.ini)
84
+
85
+ The `command` variable is a custom command that DA will run in your project folder once you choose "Format & commit" in `Main menu / Projects / Project menu / Changelog`. Even when provided, it is **not** run without your confirmation, first it's printed with the folder name and you can choose to skip it.
86
+
87
+ `owner` & `edited` are filled out automatically when a new project is created and `edited` updates with every changelog update.
88
+
89
+ ---
90
+
68
91
  **Safe changelog updates**
69
92
 
70
93
  Before applying any changes, your previous `CHANGELOG.md` is automatically backed up into your project folder.
@@ -73,10 +96,12 @@ New changes are first written to a temporary file and only prepended to & replac
73
96
  This ensures your existing changelog is never overwritten or corrupted, and you always have a fallback copy.
74
97
  If the temporary changelog is present on startup you are prompted to remove or keep it.
75
98
 
99
+
76
100
  **Ease of navigation**
77
101
 
78
102
  You can access files/folders and configuration straight from the menus, so you shouldn't find yourself searching through the program's directory or even your local user data very often.
79
103
 
104
+
80
105
  **Configuration**
81
106
 
82
107
  The `memory.ini` file does exactly what you'd expect, it features:
@@ -3,9 +3,11 @@
3
3
 
4
4
  > **A lightweight TUI app for managing and simplifying your Markdown changelogs.**
5
5
 
6
- * **Setup:** Start with [SETUP](./SETUP.md) to get started.
6
+ > `pip install developer-assistant`
7
7
 
8
- * **Changes:** Yes, I keep a [CHANGELOG](./CHANGELOG.md)
8
+ * **Installation:** detailed instructions in [SETUP](./SETUP.md)
9
+
10
+ * **Changes:** yes, I keep a [CHANGELOG](./CHANGELOG.md)
9
11
 
10
12
  ---
11
13
 
@@ -19,6 +21,8 @@
19
21
  ## Appearance
20
22
 
21
23
  ### Coloured, easy-to-use menus
24
+ A comfortable interface with a modern polish, built the good old way:
25
+
22
26
  ![Changelog Menu](documents/images/changelog-menu.png)
23
27
 
24
28
  ### Beautiful changelog previews
@@ -30,9 +34,9 @@ Preview your Markdown changelogs directly in the terminal with Rich rendering:
30
34
  ## Introduction
31
35
 
32
36
  ### What does this tool do?
33
- Developer Assistant is a lightweight TUI for simplifying and managing your changelogs. You can customize the templates for each profile to match your existing format, and use DA as a central hub to access every changelog and project folder you maintain.
37
+ Developer Assistant is a lightweight TUI for simplifying and managing your changelogs. You can customize the templates for **each profile** to match your existing format, and use DA as a central hub to access every changelog and project folder you maintain.
34
38
 
35
- You can create as many profiles as you need. Each profile gets its own **project specific** `.ini` files, created automatically through the menu based on the information you provide. These act as links that tell DA where your changelogs are and what's the last version number.
39
+ You can create as many profiles as you need. Each profile gets its own **project specific** `.ini` files, created automatically through the menu based on the information you provide. These act as links that tell DA where your changelogs are, which profile owns them and what's the last version number.
36
40
 
37
41
  Your files are kept safe at all times. Before adding new changes, your existing `CHANGELOG.md` is automatically backed up. While editing, all changes are written to a temporary file first and only prepended to & replaced with your real changelog once you confirm them.
38
42
 
@@ -55,22 +59,43 @@ Don't change the folder structure or modify variable names inside `.ini` files.
55
59
 
56
60
  The `da-ui/` folder and subfolders will be created automatically.
57
61
 
58
- You can access its content quickly when going to: `Main menu / Settings`
62
+ > [!TIP]
63
+ > You can access its content quickly when going to: `Main menu / Settings`
59
64
 
60
65
  **Profiles for seperate projects and templates**
61
66
 
62
67
  The program comes with the "Default" profile, you can choose to either stick with this one or create your own profiles in `Main menu / Profiles`. Each profile has seperate projects and they can't be accessed by other profiles. You can choose to customize the templates seperately too.
63
68
 
64
- Migrating a project or template from one profile to another is currently manual, **make sure to also change the "*owner*" value in `.ini` files accordingly**.
69
+ > [!NOTE]
70
+ > Migrating a project or template from one profile to another is currently manual, **make sure to also change the "*owner*" value in `.ini` files accordingly**.
71
+
72
+ ---
65
73
 
66
74
  **Customizable templates**
67
75
 
68
76
  In the **local** `Templates/` folder you can modify the template contents to your liking - **just avoid changing the `{{placeholder}}` names**.
69
77
 
78
+ Templates come in three flavours:
79
+
80
+ * changelog_template.txt - *Changelog title*
81
+
82
+ * header_template.txt - *Version and date*
83
+
84
+ * entry_template.txt - *Change entry and comments*
85
+
86
+
70
87
  **Linked projects all in one place**
71
88
 
72
89
  The `Projects/` folder holds the `.ini` files you create when starting a new project with DA.
73
90
 
91
+ [Project.ini example](./documents/project-example.ini)
92
+
93
+ The `command` variable is a custom command that DA will run in your project folder once you choose "Format & commit" in `Main menu / Projects / Project menu / Changelog`. Even when provided, it is **not** run without your confirmation, first it's printed with the folder name and you can choose to skip it.
94
+
95
+ `owner` & `edited` are filled out automatically when a new project is created and `edited` updates with every changelog update.
96
+
97
+ ---
98
+
74
99
  **Safe changelog updates**
75
100
 
76
101
  Before applying any changes, your previous `CHANGELOG.md` is automatically backed up into your project folder.
@@ -79,10 +104,12 @@ New changes are first written to a temporary file and only prepended to & replac
79
104
  This ensures your existing changelog is never overwritten or corrupted, and you always have a fallback copy.
80
105
  If the temporary changelog is present on startup you are prompted to remove or keep it.
81
106
 
107
+
82
108
  **Ease of navigation**
83
109
 
84
110
  You can access files/folders and configuration straight from the menus, so you shouldn't find yourself searching through the program's directory or even your local user data very often.
85
111
 
112
+
86
113
  **Configuration**
87
114
 
88
115
  The `memory.ini` file does exactly what you'd expect, it features:
@@ -97,7 +124,8 @@ The `memory.ini` file does exactly what you'd expect, it features:
97
124
 
98
125
  Last project & active profile get updated automatically, the rest are up to you.
99
126
 
100
- **`Ctrl+C` works everywhere to quickly exit DA.**
127
+ > [!TIP]
128
+ > **`Ctrl+C` works everywhere to quickly exit DA.**
101
129
 
102
130
  ---
103
131
 
@@ -113,10 +141,15 @@ Once configured, you can create as many changelog entries as you want by picking
113
141
  Two possibilities, depending on how you installed.
114
142
 
115
143
  ### 1. Installed from PyPI
116
- A. **Using uv:** `uv tool upgrade developer-assistant`
117
-
118
- B. **Using pip:** `python -m pip install -U developer-assistant`
119
-
144
+ A. **Using uv:**
145
+ ```bash
146
+ uv tool upgrade developer-assistant
147
+ ```
148
+
149
+ B. **Using pip:**
150
+ ```bash
151
+ python -m pip install -U developer-assistant
152
+ ```
120
153
 
121
154
  ### 2. Installed from a local clone
122
155
  *Run all terminal commands in the repo folder*
@@ -3,5 +3,7 @@ edited =
3
3
  owner = Default
4
4
  path = C:\Users\...\Developer-Assistant\test-project
5
5
  changelog = C:\Users\...\Developer-Assistant\test-project\CHANGELOG.md
6
- version = 1.0.0
6
+ version = 1.0.0
7
+ command = git add CHANGELOG.md
8
+ ;; the command could be anything, DA will run it in your project folder if you add it (runs in "Format & commit")
7
9
  cloud =
@@ -17,7 +17,7 @@ from importlib import resources
17
17
 
18
18
  class Interface:
19
19
  def __init__(self):
20
- self.version = "0.3.0"
20
+ self.version = "0.3.5"
21
21
  self.clear = 'cls' if platform.system() == 'Windows' else 'clear'
22
22
 
23
23
  title = f"DA - {self.version}"
@@ -104,7 +104,7 @@ class Interface:
104
104
  while True:
105
105
  os.system(self.clear)
106
106
  print(colored(f"{self.active_profile}", f"{self.color}") + " / Main menu")
107
- print(self.header.center(127, "="))
107
+ print(self.header)
108
108
  print("E. Exit\n")
109
109
  print("Last project:")
110
110
  print(colored(last_project, f"{self.color}"))
@@ -116,7 +116,7 @@ class Interface:
116
116
 
117
117
  if choice.lower() == "e":
118
118
  os.system(self.clear)
119
- print(self.header.center(127, "="))
119
+ print(self.header)
120
120
  print("Bye!")
121
121
  time.sleep(1)
122
122
  return "exit"
@@ -131,14 +131,14 @@ class Interface:
131
131
  return "settings"
132
132
  else:
133
133
  print("")
134
- print(colored("Unknown option...", "light_red", attrs=["blink"]))
134
+ print(colored("Unknown option...", "light_red", attrs=["bold"]))
135
135
  time.sleep(1)
136
136
 
137
137
  def settings(self):
138
138
  while True:
139
139
  os.system(self.clear)
140
140
  print(colored(f"{self.active_profile}", f"{self.color}") + " / Main menu / Settings")
141
- print(self.header.center(127, "="))
141
+ print(self.header)
142
142
  print("E. Back\n")
143
143
 
144
144
  print(colored("Configuration options", attrs=["underline"]))
@@ -166,14 +166,14 @@ class Interface:
166
166
  Opener.open(self.config.templates_folder)
167
167
  else:
168
168
  print("")
169
- print(colored("Unknown option...", "light_red", attrs=["blink"]))
169
+ print(colored("Unknown option...", "light_red", attrs=["bold"]))
170
170
  time.sleep(1)
171
171
 
172
172
  def profiles(self):
173
173
  while True:
174
174
  os.system(self.clear)
175
175
  print(colored(f"{self.active_profile}", f"{self.color}") + " / Main menu / Profiles")
176
- print(self.header.center(127, "="))
176
+ print(self.header)
177
177
  print("E. Back\n")
178
178
 
179
179
  print("1. Create a new profile")
@@ -189,7 +189,7 @@ class Interface:
189
189
  self.switch_profile()
190
190
  else:
191
191
  print("")
192
- print(colored("Unknown option...", "light_red", attrs=["blink"]))
192
+ print(colored("Unknown option...", "light_red", attrs=["bold"]))
193
193
  time.sleep(1)
194
194
 
195
195
  def switch_profile(self):
@@ -256,9 +256,17 @@ class Interface:
256
256
  self.memory = self.config.load_memory()
257
257
 
258
258
  self.color = self.memory.get('color') or "light_blue"
259
- self.header = (colored(" Developer Assistant ", f"{self.color}"))
260
259
  self.user_path = os.environ.get('USERPROFILE') or os.environ.get('HOME', 'User')
261
260
 
261
+ brand = (colored(" Developer Assistant ", f"{self.color}"))
262
+ text = " Developer Assistant "
263
+
264
+ columns, _ = shutil.get_terminal_size()
265
+ pad_size = (columns - len(text)) // 2
266
+ bars = "=" * max(0, pad_size)
267
+
268
+ self.header = f"{bars}{brand}{bars}"
269
+
262
270
  def local_init(self):
263
271
  default_files = resources.files("da.default")
264
272
  dest = self.config.memory_ini
@@ -268,7 +276,7 @@ class Interface:
268
276
  shutil.copy(item, dest)
269
277
 
270
278
  self.config.projects_folder.mkdir(parents=True, exist_ok=True)
271
- # Add Test-Project
279
+
272
280
  dest = self.config.projects_folder
273
281
  for item in default_files.iterdir():
274
282
  if item.name == "test-project.ini":
@@ -283,9 +291,8 @@ class Interface:
283
291
 
284
292
  readme_content = resources.files("da").joinpath("intro.md").read_text()
285
293
 
286
- MARKDOWN = readme_content
287
294
  console = Console()
288
- md = Markdown(MARKDOWN)
295
+ md = Markdown(readme_content)
289
296
  console.print(md)
290
297
 
291
298
  input("\nContinue..." + colored("[Enter]", f"{self.color}"))
@@ -31,13 +31,15 @@ Don't change the folder structure or modify variable names inside `.ini` files.
31
31
 
32
32
  The `da-ui/` folder and subfolders will be created automatically.
33
33
 
34
- You can access its content quickly when going to: `Main menu / Settings`
34
+ > Tip:
35
+ > You can access its content quickly when going to: `Main menu / Settings`
35
36
 
36
37
  **Profiles for seperate projects and templates**
37
38
 
38
39
  The program comes with the "Default" profile, you can choose to either stick with this one or create your own profiles in `Main menu / Profiles`. Each profile has seperate projects and they can't be accessed by other profiles. You can choose to customize the templates seperately too.
39
40
 
40
- Migrating a project or template from one profile to another is currently manual, **make sure to also change the "*owner*" value in `.ini` files accordingly**.
41
+ > Note:
42
+ > Migrating a project or template from one profile to another is currently manual, **make sure to also change the "*owner*" value in `.ini` files accordingly**.
41
43
 
42
44
  ---
43
45
 
@@ -45,10 +47,25 @@ Migrating a project or template from one profile to another is currently manual,
45
47
 
46
48
  In the **local** `Templates/` folder you can modify the template contents to your liking - **just avoid changing the `{{placeholder}}` names**.
47
49
 
50
+ Templates come in three flavours:
51
+
52
+ * changelog_template.txt - *Changelog title*
53
+
54
+ * header_template.txt - *Version and date*
55
+
56
+ * entry_template.txt - *Change entry and comments*
57
+
58
+
48
59
  **Linked projects all in one place**
49
60
 
50
61
  The `Projects/` folder holds the `.ini` files you create when starting a new project with DA.
51
62
 
63
+ The `command` variable is a custom command that DA will run in your project folder once you choose "Format & commit" in `Main menu / Projects / Project menu / Changelog`. Even when provided, it is **not** run without your confirmation, first it's printed with the folder name and you can choose to skip it.
64
+
65
+ `owner` & `edited` are filled out automatically when a new project is created and `edited` updates with every changelog update.
66
+
67
+ ---
68
+
52
69
  **Safe changelog updates**
53
70
 
54
71
  Before applying any changes, your previous `CHANGELOG.md` is automatically backed up into your project folder.
@@ -57,10 +74,12 @@ New changes are first written to a temporary file and only prepended to & replac
57
74
  This ensures your existing changelog is never overwritten or corrupted, and you always have a fallback copy.
58
75
  If the temporary changelog is present on startup you are prompted to remove or keep it.
59
76
 
77
+
60
78
  **Ease of navigation**
61
79
 
62
80
  You can access files/folders and configuration straight from the menus, so you shouldn't find yourself searching through the program's directory or even your local user data very often.
63
81
 
82
+
64
83
  **Configuration**
65
84
 
66
85
  The `memory.ini` file does exactly what you'd expect, it features:
@@ -75,4 +94,4 @@ The `memory.ini` file does exactly what you'd expect, it features:
75
94
 
76
95
  Last project & active profile get updated automatically, the rest are up to you.
77
96
 
78
- **`Ctrl+C` works everywhere to quickly exit DA.**
97
+ > **`Ctrl+C` works everywhere to quickly exit DA.**
@@ -65,7 +65,6 @@ class ConfigManager:
65
65
  return
66
66
 
67
67
  def project_ini(self):
68
- #==Create new project ini==
69
68
  project_parser = configparser.ConfigParser()
70
69
  project_parser["SETTINGS"] = self.data
71
70
 
@@ -77,7 +76,6 @@ class ConfigManager:
77
76
  return
78
77
 
79
78
  def load_project(self):
80
- #==Return project ini variables==
81
79
  project_parser = configparser.ConfigParser()
82
80
  project_parser.read(self.new_project_ini)
83
81
 
@@ -88,6 +86,7 @@ class ConfigManager:
88
86
  'path': prj.get('path'),
89
87
  'changelog': prj.get('changelog'),
90
88
  'version': prj.get('version'),
89
+ 'command': prj.get('command'),
91
90
  'cloud': prj.get('cloud')
92
91
  }
93
92
 
@@ -7,12 +7,10 @@ from termcolor import colored
7
7
  class Opener:
8
8
  @staticmethod
9
9
  def open(path):
10
- #==Check if path exists==
11
10
  if not os.path.exists(path):
12
11
  print(colored("\nThis path does not exist.", "light_red"))
13
12
  time.sleep(1)
14
13
  return
15
- #==Open if exists==
16
14
  else:
17
15
  system = platform.system()
18
16
  if system == "Windows":
@@ -5,6 +5,7 @@ import platform
5
5
  from pathlib import Path
6
6
  from datetime import datetime
7
7
 
8
+ from prompt_toolkit import prompt
8
9
  from termcolor import colored
9
10
 
10
11
  from da.modules.config_manager import ConfigManager
@@ -25,7 +26,7 @@ class ProjectsManager:
25
26
  self.memory = self.config.load_memory()
26
27
  os.system(self.clear)
27
28
  print(colored(f"{self.active_profile}", f"{self.color}") + " / Main menu / Projects")
28
- print(self.header.center(127, "="))
29
+ print(self.header)
29
30
  print("E. Back\n")
30
31
  print(colored("1. Last project:", attrs=["underline"]))
31
32
  print(colored(self.memory.get('last_project'), f"{self.color}"))
@@ -48,7 +49,7 @@ class ProjectsManager:
48
49
  elif choice == "1":
49
50
  project = self.memory.get('last_project')
50
51
  if not project:
51
- print(colored("\nLast project has not been defined...", "light_red", attrs=["blink"]))
52
+ print(colored("\nLast project has not been defined...", "light_red", attrs=["bold"]))
52
53
  time.sleep(1)
53
54
  else:
54
55
  self.load_project(f"{project}")
@@ -57,7 +58,6 @@ class ProjectsManager:
57
58
  self.new_project()
58
59
 
59
60
  elif choice.lower() in ("a", "b", "c"):
60
- #==If the pinned project is empty, return an error message==
61
61
  options_map = {
62
62
  'a': 'pinned_project',
63
63
  'b': 'pinned_project1',
@@ -67,7 +67,7 @@ class ProjectsManager:
67
67
  project_name = self.memory.get(key)
68
68
  if project_name == "":
69
69
  print("")
70
- print(colored(f"Project '{choice}' has not been defined...", "light_red", attrs=["blink"]))
70
+ print(colored(f"Project '{choice}' has not been defined...", "light_red", attrs=["bold"]))
71
71
  time.sleep(1)
72
72
  else:
73
73
  project = self.memory.get(key)
@@ -77,7 +77,7 @@ class ProjectsManager:
77
77
  self.prf_projects()
78
78
  else:
79
79
  print("")
80
- print(colored("Unknown option...", "light_red", attrs=["blink"]))
80
+ print(colored("Unknown option...", "light_red", attrs=["bold"]))
81
81
  time.sleep(1)
82
82
 
83
83
  def new_project(self):
@@ -86,21 +86,23 @@ class ProjectsManager:
86
86
  now = datetime.now()
87
87
  today = now.strftime("%Y-%m-%d")
88
88
 
89
- print(self.header.center(127, "="))
89
+ print(self.header)
90
90
  print("E. Abort/back\n")
91
91
 
92
- name = input("Enter new project name > ")
92
+ name = prompt("Enter new project name > ")
93
93
  if name.lower() == "e":
94
94
  return
95
- path = input("\nEnter project path > ")
95
+ path = prompt("\nEnter project path > ")
96
96
 
97
- changelog = input("\nProject changelog path > ")
97
+ changelog = prompt("\nProject changelog path > ")
98
98
 
99
- version = input("\nCurrent project version > ")
99
+ version = prompt("\nCurrent project version > ")
100
100
 
101
- #cloud = input("\nCloud service (not required) > ")
101
+ command = prompt("\nCustom commit command > ")
102
102
 
103
- confirm = input("\nConfirm(Y) or abort(E) > ")
103
+ #cloud = prompt("\nCloud service (not required) > ")
104
+
105
+ confirm = input("\nConfirm(Y) or abort(E) > ").strip()
104
106
  if confirm.lower() == "e":
105
107
  return
106
108
 
@@ -112,6 +114,7 @@ class ProjectsManager:
112
114
  "path": path,
113
115
  "changelog": changelog,
114
116
  "version": version,
117
+ "command": command,
115
118
  "cloud": ""
116
119
  }
117
120
  new_manager.project_ini()
@@ -119,15 +122,15 @@ class ProjectsManager:
119
122
 
120
123
  else:
121
124
  print("")
122
- print(colored("Unknown option, try again...", "light_red", attrs=["blink"]))
123
- time.sleep(2)
125
+ print(colored("Unknown option, try again...", "light_red", attrs=["bold"]))
126
+ time.sleep(1)
124
127
  return
125
128
 
126
129
  def prf_projects(self):
127
130
  while True:
128
131
  os.system(self.clear)
129
132
  print(colored(f"{self.active_profile}", f"{self.color}") + " / Main menu / Projects / Profile projects")
130
- print(self.header.center(127, "="))
133
+ print(self.header)
131
134
  print("E. Back\n")
132
135
  prof_prj = self.config.projects_folder
133
136
  contents = os.listdir(prof_prj)
@@ -150,7 +153,7 @@ class ProjectsManager:
150
153
  self.load_project(project)
151
154
  else:
152
155
  print("")
153
- print(colored("Unknown option...", "light_red", attrs=["blink"]))
156
+ print(colored("Unknown option...", "light_red", attrs=["bold"]))
154
157
  time.sleep(1)
155
158
 
156
159
  def load_project(self, project):
@@ -190,7 +193,7 @@ class ProjectsManager:
190
193
 
191
194
  os.system(self.clear)
192
195
  print(colored(f"{self.active_profile}", f"{self.color}") + " / Main menu / Projects / Project menu")
193
- print(self.header.center(127, "="))
196
+ print(self.header)
194
197
  print("E. Back\n")
195
198
  print(colored("Chosen project:", attrs=["underline"]))
196
199
  print(colored(project, f"{self.color}"))
@@ -208,8 +211,7 @@ class ProjectsManager:
208
211
  return
209
212
 
210
213
  elif choice == "1":
211
- path = setting.get('path')
212
- folder = Path(path)
214
+ folder = Path(setting.get('path'))
213
215
  Opener.open(folder)
214
216
 
215
217
  elif choice == "2":
@@ -223,27 +225,28 @@ class ProjectsManager:
223
225
  if os.path.exists(changelog):
224
226
  print(colored("\nThis action will overwrite your existing changelog!\n", "yellow"))
225
227
  input("Acknowledge..." + colored("[Enter]", f"{self.color}"))
226
- self.rest_bak(setting, project)
228
+
229
+ self.rest_bak(setting, changelog, project)
227
230
 
228
231
  #elif choice == "5":
229
232
 
230
233
  else:
231
234
  print("")
232
- print(colored("Unknown option...", "light_red", attrs=["blink"]))
235
+ print(colored("Unknown option...", "light_red", attrs=["bold"]))
233
236
  time.sleep(1)
234
237
 
235
- def rest_bak(self, setting, project):
238
+ def rest_bak(self, setting, changelog, project):
236
239
  prj_path = Path(setting.get('path'))
237
240
  has_bak = list(prj_path.glob("*.bak"))
238
241
 
239
242
  if not has_bak:
240
243
  print(colored(f"\nCan't find any .bak files for {project}", "yellow"))
241
- time.sleep(2)
244
+ time.sleep(1)
242
245
  return
243
246
 
244
247
  bak = has_bak[0]
245
- bak.rename(prj_path / "CHANGELOG.md")
246
- print(f"\nRenamed {bak.name} to CHANGELOG.md")
248
+ os.replace(bak, changelog)
249
+ print(f"\nReplaced {bak.name} with CHANGELOG.md")
247
250
  time.sleep(1)
248
251
  return
249
252
 
@@ -24,6 +24,7 @@ class VersionLogic:
24
24
  self.user_path = user_path
25
25
 
26
26
  self.memory = self.config.load_memory()
27
+ self.console = Console()
27
28
 
28
29
  def project_menu(self, project, profile):
29
30
  self.active_project = project
@@ -43,16 +44,16 @@ class VersionLogic:
43
44
  self.setting = load_manager.load_project()
44
45
  self.changelog_path = Path(self.setting.get('changelog'))
45
46
  self.prj_ver = self.setting.get('version')
46
- prj_path = Path(self.setting.get('path'))
47
+ self.prj_path = Path(self.setting.get('path'))
47
48
 
48
49
  os.system(self.clear)
49
50
  print(colored(f"{self.active_profile}", f"{self.color}") + " / Main menu / Projects / Project menu / Changelog")
50
- print(self.header.center(127, "="))
51
+ print(self.header)
51
52
  print("E. Back\n")
52
53
  print(colored("Chosen project:", attrs=["underline"]))
53
54
  print(colored(self.active_project, f"{self.color}"))
54
55
  print("Version: " + colored(self.prj_ver, f"{self.color}"))
55
- print("\n1. Create a new changelog")
56
+ print("\n1. Format & commit")
56
57
  print("2. Add new changes")
57
58
  print("\n3. Open the changelog")
58
59
  print("4. Preview .md changelog\n")
@@ -63,26 +64,27 @@ class VersionLogic:
63
64
  return
64
65
 
65
66
  elif choice == "1":
66
- if not os.path.exists(prj_path):
67
- print(colored("\nSystem cannot find the path to this project.", "light_red"))
68
- time.sleep(1.5)
67
+ if not os.path.exists(self.changelog_path):
68
+ print(no_path)
69
+ time.sleep(1)
69
70
  else:
70
- self.create_changelog()
71
+ self.finalise()
71
72
 
72
73
  elif choice == "2":
73
- if not os.path.exists(self.changelog_path):
74
- print(no_path)
75
- time.sleep(1.5)
74
+ if not os.path.exists(self.prj_path):
75
+ print(colored("\nSystem cannot find the path to this project.", "light_red"))
76
+ time.sleep(1)
76
77
  else:
77
78
  self.update_changelog()
78
79
 
79
80
  elif choice == "3":
80
81
  if not os.path.exists(self.changelog_path):
81
82
  print(no_path)
82
- time.sleep(1.5)
83
+ time.sleep(1)
83
84
  continue
84
85
  else:
85
- if self.check_size():
86
+ method = self.check_size()
87
+ if method == "reject":
86
88
  continue
87
89
  else:
88
90
  Opener.open(self.changelog_path)
@@ -90,55 +92,56 @@ class VersionLogic:
90
92
  elif choice == "4":
91
93
  if not os.path.exists(self.changelog_path):
92
94
  print(no_path)
93
- time.sleep(1.5)
95
+ time.sleep(1)
94
96
  else:
95
- self.view_md(self.changelog_path)
97
+ log_content = ""
98
+ with open(self.changelog_path, "r", encoding="utf-8") as f:
99
+ log_content = f.read()
100
+ self.view_md(log_content)
96
101
 
97
102
  else:
98
103
  print("")
99
- print(colored("Unknown option...", "light_red", attrs=["blink"]))
104
+ print(colored("Unknown option...", "light_red", attrs=["bold"]))
100
105
  time.sleep(1)
101
106
 
102
- def create_changelog(self):
103
- os.system(self.clear)
104
- print(self.header.center(127, "="))
105
- print("E. Back/abort\n")
106
-
107
- if os.path.exists(self.changelog_path):
108
- print(colored("This action will overwrite your existing changelog!\n", "yellow"))
109
- input("Acknowledge..." + colored("[Enter]\n", f"{self.color}"))
107
+ def finalise(self):
108
+ with open(self.changelog_path, "r", encoding="utf-8") as f:
109
+ existing = f.read()
110
110
 
111
- version = input("Version > ")
112
- if version.lower() == "e":
113
- return
114
- change_type = input("\nChange type > ")
111
+ template = self.template_loader("changelog_template.txt")
115
112
 
116
- entry = prompt("\nFirst entry > ")
113
+ combined = template + "\n" + existing
117
114
 
118
- comment = prompt("\nOptional comment > ")
115
+ prj_dir = self.changelog_path.parent
116
+ fd, temp_path = tempfile.mkstemp(dir=prj_dir, text=True)
119
117
 
120
- choice = input("\nSave (Enter) Cancel (E).\nAdd further entries with 'Add new changes' in the menu! > ")
121
- if choice.lower() == "e":
122
- return
118
+ try:
119
+ with os.fdopen(fd, "w", encoding="utf-8") as f:
120
+ f.write(combined)
121
+ f.flush()
123
122
 
124
- data = {
125
- "date": self.today,
126
- "version": version,
127
- "type": change_type,
128
- "changes": entry,
129
- "comments": comment
130
- }
123
+ os.replace(temp_path, self.changelog_path)
131
124
 
132
- template = self.template_loader("changelog_template.txt")
125
+ except Exception as e:
126
+ if os.path.exists(temp_path):
127
+ os.remove(temp_path)
128
+ raise e
133
129
 
134
- rendered = self.template_renderer(template, data)
130
+ cmd = self.setting.get('command')
135
131
 
136
- with open(self.changelog_path, "w", encoding="utf-8") as f:
137
- f.write(rendered + "\n")
132
+ if cmd.strip():
133
+ print("\nwill run: " + colored(f"{cmd}", f"{self.color}"))
134
+ print("in folder: " + colored(f"{self.prj_path}", f"{self.color}"))
135
+ confirm = input("\nConfirm[Enter] or abort[E] > ").strip()
136
+ print("")
138
137
 
139
- new_config = ConfigManager(f"{self.active_project}.ini", profile=self.active_profile)
140
- new_config.update_project("version", version)
141
- new_config.update_project("edited", self.today)
138
+ if confirm.lower() == "e":
139
+ return
140
+ try:
141
+ subprocess.run(cmd, cwd=self.prj_path, shell=True, check=True)
142
+ except Exception as e:
143
+ print(colored("\nfailed: ", "light_red") + f"{e}")
144
+ input("\nReturn...[Enter]")
142
145
 
143
146
  last_project = self.memory.get('last_project')
144
147
  if last_project != self.active_project:
@@ -147,8 +150,10 @@ class VersionLogic:
147
150
  return
148
151
 
149
152
  def update_changelog(self):
150
- if self.check_size():
151
- return
153
+ if os.path.exists(self.changelog_path):
154
+ method = self.check_size()
155
+ if method == "reject":
156
+ return
152
157
 
153
158
  self.change_type = None
154
159
  self.change = None
@@ -156,7 +161,7 @@ class VersionLogic:
156
161
  while True:
157
162
  os.system(self.clear)
158
163
  print(colored(f"{self.active_profile}", f"{self.color}") + " / Main menu / Projects / Project menu / Changelog / Add changes")
159
- print(self.header.center(127, "="))
164
+ print(self.header)
160
165
  print("E. Back/abort")
161
166
  print("O. Open templog for fixes")
162
167
  print("S. Review changes & save\n")
@@ -183,7 +188,6 @@ class VersionLogic:
183
188
 
184
189
  type_choice = input(f"{self.user_path}> ").strip()
185
190
 
186
- #==Assign change types to keys==
187
191
  type_map = {
188
192
  "1": "Added",
189
193
  "2": "Removed",
@@ -207,7 +211,7 @@ class VersionLogic:
207
211
  self.save_changes()
208
212
  else:
209
213
  print("")
210
- print(colored("Unknown option...", "light_red", attrs=["blink"]))
214
+ print(colored("Unknown option...", "light_red", attrs=["bold"]))
211
215
  time.sleep(1)
212
216
 
213
217
  def prepend_changes(self):
@@ -218,21 +222,20 @@ class VersionLogic:
218
222
  with open(self.templog_path, "r", encoding="utf-8") as f:
219
223
  existing = f.read()
220
224
 
221
- #==Add the change type header if needed==
222
225
  if header not in existing:
223
226
  with open(self.templog_path, "a", encoding="utf-8") as f:
224
227
  f.write(header + "\n")
225
228
 
226
229
  while True:
227
230
  os.system(self.clear)
228
- print(self.header.center(127, "="))
231
+ print(self.header)
229
232
 
230
233
  print("Chosen change type:")
231
234
  print(colored(self.change_type, f"{self.color}"))
232
235
 
233
- self.change = prompt("\nChange entry: ")
236
+ self.change = prompt("\nChange entry > ")
234
237
 
235
- self.comment = prompt("\nOptional comment: ")
238
+ self.comment = prompt("\nOptional comment > ")
236
239
 
237
240
  data = {
238
241
  "changes": self.change,
@@ -246,13 +249,13 @@ class VersionLogic:
246
249
  with open(self.templog_path, "a", encoding="utf-8") as f:
247
250
  f.write(rendered + "\n")
248
251
 
249
- choice = input("\nSave & exit [E] or add more [Enter]? ")
252
+ choice = input("\nNew type [E] or add more [Enter] > ")
250
253
  if choice.lower() == "e":
251
254
  return
252
255
 
253
256
  def save_changes(self):
254
257
  os.system(self.clear)
255
- print(self.header.center(127, "="))
258
+ print(self.header)
256
259
  print(colored("Please check the output file:", f"{self.color}", attrs=["underline"]))
257
260
 
258
261
  templog_content = ""
@@ -260,18 +263,15 @@ class VersionLogic:
260
263
  with open(self.templog_path, "r", encoding="utf-8") as f:
261
264
  templog_content = f.read()
262
265
 
263
- print(colored(f"[New version] - {self.today}\n", "magenta", attrs=["underline"]))
266
+ message = colored(f"[New version] - {self.today}\n", "magenta", attrs=["underline"])
264
267
 
265
- MARKDOWN = templog_content
266
- console = Console()
267
- md = Markdown(MARKDOWN)
268
- console.print(md)
268
+ self.view_md(templog_content, message)
269
269
  else:
270
270
  print(colored("No changes added.", "light_red"))
271
271
  time.sleep(1)
272
272
  return
273
273
 
274
- choice = input("\nContinue" + colored("[Enter]", f"{self.color}") + " or go back" + colored("[E] ", f"{self.color}"))
274
+ choice = input("\nContinue" + colored("[Enter]", f"{self.color}") + " or add more" + colored("[E] ", f"{self.color}"))
275
275
 
276
276
  if choice.lower() == "e":
277
277
  return
@@ -291,10 +291,8 @@ class VersionLogic:
291
291
 
292
292
  old_content = ""
293
293
  if os.path.exists(self.changelog_path):
294
- #==Make a duplicate of the old changelog==
295
- log_name = f"Changelog-{self.today}.bak"
296
- project_folder = Path(self.setting.get('path'))
297
- duplicate_path = project_folder / log_name
294
+ log_name = "changelog.bak"
295
+ duplicate_path = self.prj_path / log_name
298
296
 
299
297
  src = self.changelog_path
300
298
  dest = duplicate_path
@@ -336,35 +334,47 @@ class VersionLogic:
336
334
  time.sleep(2)
337
335
  return
338
336
 
339
- def view_md(self, log_path):
340
- if self.check_size():
341
- return
342
-
343
- os.system(self.clear)
344
- print(self.header.center(127, "="))
345
- print("")
337
+ def view_md(self, log_content, message=None):
338
+ flag = 0
339
+ if not message:
340
+ method = self.check_size()
341
+ if method == "reject":
342
+ return
343
+ elif method == "print":
344
+ flag = 1
346
345
 
347
- log_content = ""
348
- with open(log_path, "r", encoding="utf-8") as f:
349
- log_content = f.read()
346
+ if message:
347
+ print(message)
348
+ else:
349
+ os.system(self.clear)
350
+ print(self.header)
351
+ print("")
350
352
 
351
- MARKDOWN = log_content
352
- console = Console()
353
- md = Markdown(MARKDOWN)
354
- console.print(md)
353
+ if flag:
354
+ print(log_content)
355
+ print(colored("\nThis log is too large to render in Markdown! (Max 10MB)", "yellow"))
356
+ else:
357
+ md = Markdown(log_content)
358
+ self.console.print(md)
355
359
 
356
- input("\nReturn..." + colored("[Enter]", f"{self.color}"))
360
+ if not message:
361
+ input("\nReturn..." + colored("[Enter]", f"{self.color}"))
357
362
  return
358
363
 
359
364
  def check_size(self):
360
- MAX_SIZE = 100 * 1024 * 1024
365
+ print_size = 10 * 1024 * 1024
366
+ max_size = 20 * 1024 * 1024
361
367
 
362
368
  size = self.changelog_path.stat().st_size
363
369
  size_mb = size / (1024 * 1024)
364
- if size > MAX_SIZE:
370
+
371
+ if size > max_size:
365
372
  print(colored(f"\nChangelog too large to load safely: {size_mb:.2f} MB", "light_red"))
366
373
  time.sleep(2)
367
- return True
374
+ return "reject"
375
+
376
+ elif size > print_size:
377
+ return "print"
368
378
 
369
379
  def template_loader(self, template_file):
370
380
  template_path = self.config.templates_folder / template_file
@@ -0,0 +1,5 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: developer-assistant
3
- Version: 0.3.0
3
+ Version: 0.3.5
4
4
  Summary: A lightweight TUI app for managing and simplifying your Markdown changelogs.
5
5
  License: The MIT License (MIT)
6
6
 
@@ -12,11 +12,8 @@ License: The MIT License (MIT)
12
12
 
13
13
  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
14
14
  Project-URL: Homepage, https://github.com/Ivory-Hubert/Developer-Assistant
15
- Project-URL: Repository, https://github.com/Ivory-Hubert/Developer-Assistant.git
16
- Project-URL: Issues, https://github.com/Ivory-Hubert/Developer-Assistant/issues
17
15
  Project-URL: Changelog, https://github.com/Ivory-Hubert/Developer-Assistant/blob/main/CHANGELOG.md
18
16
  Classifier: Programming Language :: Python :: 3
19
- Classifier: License :: OSI Approved :: MIT License
20
17
  Classifier: Operating System :: OS Independent
21
18
  Classifier: Environment :: Console
22
19
  Classifier: Topic :: Software Development :: Libraries :: Python Modules
@@ -32,6 +29,9 @@ Dynamic: license-file
32
29
  # Developer Assistant
33
30
 
34
31
  ## Installing from PyPI
32
+
33
+ The program is designed for minimal friction and simple setup. Only installation is required, on first run DA will create local user data automatically. The same process is used for new profiles.
34
+
35
35
  **Using uv:**
36
36
  `uv tool install developer-assistant`
37
37
 
@@ -53,17 +53,18 @@ A. **Using uv:** `uv tool upgrade developer-assistant`
53
53
 
54
54
  B. **Using pip:** `python -m pip install -U developer-assistant`
55
55
 
56
+
56
57
  ## Introduction
57
58
 
58
59
  ### What does this tool do?
59
- Developer Assistant is a lightweight TUI app for simplifying and managing your changelogs. You can customize the templates for each profile to match your existing format, and use DA as a central hub to access every changelog and project folder you maintain.
60
+ Developer Assistant is a lightweight TUI for simplifying and managing your changelogs. You can customize the templates for **each profile** to match your existing format, and use DA as a central hub to access every changelog and project folder you maintain.
60
61
 
61
- You can create as many profiles as you need. Each profile gets its own **project specific** `.ini` files, created automatically through the menu based on the information you provide. These act as links that tell DA where your changelogs are and what's the last version number.
62
+ You can create as many profiles as you need. Each profile gets its own **project specific** `.ini` files, created automatically through the menu based on the information you provide. These act as links that tell DA where your changelogs are, which profile owns them and what's the last version number.
62
63
 
63
64
  Your files are kept safe at all times. Before adding new changes, your existing `CHANGELOG.md` is automatically backed up. While editing, all changes are written to a temporary file first and only prepended to & replaced with your real changelog once you confirm them.
64
65
 
65
66
 
66
- ## Using the program.
67
+ ### Using the program.
67
68
  1. **What *not* to do**
68
69
 
69
70
  Don't change the folder structure or modify variable names inside `.ini` files.
@@ -88,14 +89,33 @@ The program comes with the "Default" profile, you can choose to either stick wit
88
89
 
89
90
  Migrating a project or template from one profile to another is currently manual, **make sure to also change the "*owner*" value in `.ini` files accordingly**.
90
91
 
92
+ ---
93
+
91
94
  **Customizable templates**
92
95
 
93
96
  In the **local** `Templates/` folder you can modify the template contents to your liking - **just avoid changing the `{{placeholder}}` names**.
94
97
 
98
+ Templates come in three flavours:
99
+
100
+ * changelog_template.txt - *Changelog title*
101
+
102
+ * header_template.txt - *Version and date*
103
+
104
+ * entry_template.txt - *Change entry and comments*
105
+
106
+
95
107
  **Linked projects all in one place**
96
108
 
97
109
  The `Projects/` folder holds the `.ini` files you create when starting a new project with DA.
98
110
 
111
+ [Project.ini example](./documents/project-example.ini)
112
+
113
+ The `command` variable is a custom command that DA will run in your project folder once you choose "Format & commit" in `Main menu / Projects / Project menu / Changelog`. Even when provided, it is **not** run without your confirmation, first it's printed with the folder name and you can choose to skip it.
114
+
115
+ `owner` & `edited` are filled out automatically when a new project is created and `edited` updates with every changelog update.
116
+
117
+ ---
118
+
99
119
  **Safe changelog updates**
100
120
 
101
121
  Before applying any changes, your previous `CHANGELOG.md` is automatically backed up into your project folder.
@@ -104,10 +124,12 @@ New changes are first written to a temporary file and only prepended to & replac
104
124
  This ensures your existing changelog is never overwritten or corrupted, and you always have a fallback copy.
105
125
  If the temporary changelog is present on startup you are prompted to remove or keep it.
106
126
 
127
+
107
128
  **Ease of navigation**
108
129
 
109
130
  You can access files/folders and configuration straight from the menus, so you shouldn't find yourself searching through the program's directory or even your local user data very often.
110
131
 
132
+
111
133
  **Configuration**
112
134
 
113
135
  The `memory.ini` file does exactly what you'd expect, it features:
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "developer-assistant"
3
- version = "0.3.0"
3
+ version = "0.3.5"
4
4
  description = "A lightweight TUI app for managing and simplifying your Markdown changelogs."
5
5
  readme = "PYPI.md"
6
6
  requires-python = ">=3.10"
@@ -13,7 +13,6 @@ dependencies = [
13
13
  ]
14
14
  classifiers = [
15
15
  "Programming Language :: Python :: 3",
16
- "License :: OSI Approved :: MIT License",
17
16
  "Operating System :: OS Independent",
18
17
  "Environment :: Console",
19
18
  "Topic :: Software Development :: Libraries :: Python Modules",
@@ -21,8 +20,6 @@ classifiers = [
21
20
 
22
21
  [project.urls]
23
22
  Homepage = "https://github.com/Ivory-Hubert/Developer-Assistant"
24
- Repository = "https://github.com/Ivory-Hubert/Developer-Assistant.git"
25
- Issues = "https://github.com/Ivory-Hubert/Developer-Assistant/issues"
26
23
  Changelog = "https://github.com/Ivory-Hubert/Developer-Assistant/blob/main/CHANGELOG.md"
27
24
 
28
25
  [project.scripts]
@@ -1,6 +0,0 @@
1
- ## [{{version}}] - {{date}}
2
-
3
- ### {{type}}
4
- - **{{changes}}**
5
-
6
- {{comments}}