Release v2.0
π Release v2.0
π New Features
-
π§ Sidebar added to the main UI
- Fully customizable fields
- Can be detached into a separate window
-
ποΈ Trello-style task board
-
β Task scanner for code comments using
# TODO:and# BUG:patterns, displayed in the sidebar -
ποΈ Set a default editor from settings
-
π GitHub integration has been separated into a standalone app (downloadable from the UI)
-
π Project summary viewer for quick insights
-
π³ Tree viewer added to explore the selected project, with:
- File preview
- File search
- Expandable view in the main table (still experimental)
-
π Notes system to write project-specific notes
-
πΎ Backup & restore feature to save project snapshots without using Git/GitHub
-
π§ͺ Sandbox mode for testing small Python scripts (basic but useful)
-
π§© Plugin system added to easily extend the app using Python
-
πͺ Plugin marketplace Adds a small Marketplace where you can search and install plugins(Not Functional yet)
-
π Search in Files Add VSCode-style in file search with the Control + f shortcut.
-
π Fuzzy Finder Added fuzzy finder function with the Control + p shortcut.
-
π Command Palete Add the Command Palette with the Control + Shift + p shortcut (Still in development).
-
</> CLI Commands Added some CLI commands (Still in testing)
π¦ Organizer CLI Usage
Organizer includes a command-line interface to manage and interact with your projects directly from the terminal β ideal for scripting, automation, or power users.
π₯οΈ Available in both the Python script version and the compiled
.exeversion (In the.exeversion you have to add it to the PATH)
β Basic Usage
organizer [COMMAND] [SUBCOMMAND] [OPTIONS]π Available Commands
π list-projects
List all registered projects.
organizer list-projectsβ add-project
Add new project.
organizer add-project <NAME> <PATH> [--desc TEXT] [--lang LANG] [--repo URL]Example:
organizer add-project MyApp "c:/Users/Me/Projects/MyApp" --desc "Internal Tool" --lang Python --repo https://github.com/me/myappπ open-project
Open a project by its name.
organizer open-project <NAME>ποΈ version
Show the current version of Organizer.
organizer versionβ
task (Task Management)
organizer task [list|add|complete] <PROJECT> [ARGS...]
PROJECTcan be the full path or the project name stored in organizer
- List task
organizer task list <PROJECT>- Add task
organizer task add <PROJECT> "<TASK TEXT>"- Complete task
organizer task complete <PROJECT> <TASK_INDEX>π get-language
Analyzer programing lenguages used in a project
organizer get-language <PROJECT>π list-versions
List all saved version of a project.
organizer list-versions <PROJECT>π Notes
- Any argument marked as
<PROJECT>can be either:- The full path to a project directory, or
- The name of a registered project.
- If a project name is ambiguous or not found, you'll get a helpful error.
π‘ Examples
organizer list-projects
organizer add-project BlogApp "C:/Users/User/BlogApp" --desc "Blog CMS"
organizer open-project BlogApp
organizer task add BlogApp "Fix authentication bug"
organizer task complete BlogApp 0
organizer get-language BlogApp
organizer list-versions BlogAppπ§© Plugin System β Create and manage custom plugins
The application includes a modular plugin system, allowing users to enhance its functionality by writing simple Python scripts. Plugins are managed visually and use the built-in PluginAPI.
π Folder Structure
Organizer/
|-- plugins/
| |-- my_plugin.py
| |-- my_plugin_meta.json
|-- plugin_config.json- All plugins go in the
plugins/folder. - Each plugin must implement a
register(api)function. - Optionally, it can have an
unregister(api)function to clean up resources (π‘ Recommended when disabling the plugin).
β Create a Basic Plugin
# plugins/my_plugin.py
def register(api):
def hello():
print("π Hello from the plugin!")
api.add_menu_command("Say Hello", hello)
def unregister(api):
api.remove_menu_command("Say Hello")π Add metadata (optional)
Create a metadata file named <plugin_name>_meta.json to display details in the visual manager:
// plugins/my_plugin_meta.json
{
"description": "Adds a greeting to the main menu.",
"version": "1.0",
"author": "Juan Dev"
}π Plugin lifecycle
| MΓ©todo | DescripciΓ³n |
|---|---|
register(api) |
Called when the plugin loads. Here you register buttons, commands, widgets, etc. |
unregister(api) |
(Optional) Clean up resources, remove menus, widgets, etc. |
π§ PluginAPI Reference
Available methods in the api object passed to your plugin:
# Project access
api.get_selected_project_path() # Returns the selected project's path
api.get_selected_node() # Returns the selected tree node
# UI manipulation
api.add_menu_command("Label", function)
api.remove_menu_command("Label")
api.add_sidebar_widget(widget_tk)
api.add_main_button("Text", function)
# Settings integration
api.register_settings_section("Name", frame_builder)
api.unregister_settings_section("Name")
# Custom commands
api.register_command("name", function)
api.run_command("name")βοΈ Tips for Plugin Development
-
Always use
try/exceptto avoid crashing the app -
Hot reload supported: disable and re-enable plugins to apply changes
-
No app restart needed to test new or updated plugins
π‘ Full Plugin Example
# plugins/plugin_demo.py
PLUGIN_NAME = "Plugin Development Guide"
PLUGIN_DESCRIPTION = "Explains how to create plugins for Organizer with full examples."
plugin_config = {
"enabled": True
}
_widgets = {
"main_button": None,
"sidebar_label": None,
"settings_section": None,
"doc_window": None
}
def register(api):
from tkinter import Toplevel
from tkinter import ttk
from tkinterweb import HtmlFrame
import markdown2
from pygments.formatters import HtmlFormatter
from pygments import highlight
from pygments.lexers import PythonLexer
import re
def highlight_code_blocks(md_text):
code_block_pattern = r"```python(.*?)```"
matches = re.finditer(code_block_pattern, md_text, re.DOTALL)
for match in matches:
code = match.group(1).strip()
highlighted = highlight(code, PythonLexer(), HtmlFormatter(nowrap=True))
md_text = md_text.replace(match.group(0), f"<pre><code>{highlighted}</code></pre>")
return md_text
def open_documentation():
if _widgets["doc_window"] and _widgets["doc_window"].winfo_exists():
_widgets["doc_window"].lift()
return
top = Toplevel(api.main_window)
top.title("How to Create a Plugin")
top.geometry("800x600")
_widgets["doc_window"] = top
top.grid_rowconfigure(0, weight=1)
top.grid_columnconfigure(0, weight=1)
frame = HtmlFrame(top, messages_enabled = False)
frame.grid(row=0, column=0, sticky="nsew")
frame.grid_rowconfigure(0, weight=1)
frame.grid_columnconfigure(0, weight=1)
def unregister(api):
if _widgets["sidebar_label"]:
_widgets["sidebar_label"].destroy()
_widgets["sidebar_label"] = None
if _widgets["main_button"]:
_widgets["main_button"].destroy()
_widgets["main_button"] = None
if _widgets["doc_window"] and _widgets["doc_window"].winfo_exists():
_widgets["doc_window"].destroy()
_widgets["doc_window"] = None
if _widgets["settings_section"]:
api.unregister_settings_section(_widgets["settings_section"])
_widgets["settings_section"] = Noneπ§© Available PluginAPI Functions
api.get_selected_project_path()
# β Get the path of the selected project in the tree.api.get_selected_node()
# β Get all data of the selected tree node.api.add_menu_command(label, callback)
# β Add a new command to the menu.api.remove_menu_command(label)
# β Remove a command added previously to the menu.api.add_sidebar_widget(widget)
# β Add a widget to the left sidebar.api.add_main_button(text, callback, row=20, column=0)
# β Add a button to the main frame.api.register_settings_section(name, builder_fn)
# β Add a new section to the appβs settings window.api.unregister_settings_section(name)
# β Remove a section from the settings window.β Best Practices
β’ Use grid() instead of pack() to avoid layout conflicts.
β’ Always implement unregister(api) to remove all added widgets or commands.
β’ Keep your plugin self-contained and stable.
html = markdown2.markdown(content, extras=["fenced-code-blocks", "code-friendly"])
highlighted_html = highlight_code_blocks(html)
full_html = f"<html><head>{github_css}</head><body>{highlighted_html}</body></html>"
frame.load_html(full_html)
sidebar_label = ttk.Label(text="π§ͺ Plugin Guide Active", padding=5)
api.add_sidebar_widget(sidebar_label)
_widgets["sidebar_label"] = sidebar_label
btn = api.add_main_button("π How to Create Plugins", open_documentation, row=22, column=0)
_widgets["main_button"] = btn
def build_settings(parent):
ttk.Label(parent, text="π Plugin Creation Guide", font=("Segoe UI", 10, "bold")).grid(row=0, column=0, sticky="w", pady=5)
ttk.Label(
parent,
text="This section explains how to create and manage plugins for Organizer.",
wraplength=380,
justify="left"
).grid(row=1, column=0, sticky="w", pady=5)
ttk.Button(parent, text="π Open Full Guide", command=open_documentation).grid(row=2, column=0, pady=10, sticky="w")
api.register_settings_section("Plugin Development", build_settings)
_widgets["settings_section"] = "Plugin Development"
def unregister(api):
if _widgets["sidebar_label"]:
_widgets["sidebar_label"].destroy()
_widgets["sidebar_label"] = None
if _widgets["main_button"]:
_widgets["main_button"].destroy()
_widgets["main_button"] = None
if _widgets["doc_window"] and _widgets["doc_window"].winfo_exists():
_widgets["doc_window"].destroy()
_widgets["doc_window"] = None
if _widgets["settings_section"]:
api.unregister_settings_section(_widgets["settings_section"])
_widgets["settings_section"] = None// plugins/plugin_demo_meta.json
{
"description": "This plugin shows a complete integration example.",
"version": "1.0",
"author": "Nooch98"
}π§ Changes & Improvements
-
Revamped Settings screen (Editor Configuration & Theme sections)
-
Updated Main Project Table:
- Now expandable to reveal files and directories
-
Now in the editor settings you can set a default editor so you don't have to choose it every time you open a project.
-
Now the theme selection is saved and the next time you open the app it will appear with the theme selected.