Skip to content

Release v2.0

Choose a tag to compare

@Nooch98 Nooch98 released this 28 Jul 19:39
· 7 commits to main since this release
9c64764

πŸš€ Release v2.0

🌟 New Features

  • 🧭 Sidebar added to the main UI

    1. Fully customizable fields
    2. 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 .exe version (In the .exe version 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...]

PROJECT can 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/except to 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.