Trending
Zamfara moves to contain diphtheria, other preventable diseases is trending now Strain flips Hall signal in altermagnetic manganese telluride, suggesting a path to pract… is trending now Japan aims for the moons of Mars is trending now Mimas looks like one of Saturn's deadest moons: a frozen, heavily cratered ball with no o… is trending now Radio telescopes help scientists map molecules in space and uncover where and how stars f… is trending now Catalan party: Barcelona flex their muscles with a thrashing of Basel is trending now Rodri transfer news: Spain captain agrees deal to join Barcelona from Man City is trending now Gary Neville: "Manchester United massacred by an AC Milan side without many first-choice … is trending now A striking appearance from Zidane: the new coach's eyes watching from afar is trending now Davido Announces ‘Tell Everybody’ Video With Leon Thomas is trending now 2Baba takes ‘The Baba Experience’ to UK, Ireland is trending now “CHIDERA” will mark a new chapter in my career – Olamide Oladapo is trending now Zamfara moves to contain diphtheria, other preventable diseases is trending now Strain flips Hall signal in altermagnetic manganese telluride, suggesting a path to pract… is trending now Japan aims for the moons of Mars is trending now Mimas looks like one of Saturn's deadest moons: a frozen, heavily cratered ball with no o… is trending now Radio telescopes help scientists map molecules in space and uncover where and how stars f… is trending now Catalan party: Barcelona flex their muscles with a thrashing of Basel is trending now Rodri transfer news: Spain captain agrees deal to join Barcelona from Man City is trending now Gary Neville: "Manchester United massacred by an AC Milan side without many first-choice … is trending now A striking appearance from Zidane: the new coach's eyes watching from afar is trending now Davido Announces ‘Tell Everybody’ Video With Leon Thomas is trending now 2Baba takes ‘The Baba Experience’ to UK, Ireland is trending now “CHIDERA” will mark a new chapter in my career – Olamide Oladapo is trending now
Payroll

Command Palette Launcher (VS Code Style)

 """Command Palette Launcher (VS Code style)Tech: tkinter, os, keyboard, difflibFeatures:- Ctrl+P to open palette (global using 'keyboard', and also inside Tk window)- Index files from a folder for quick search- Fuzzy search using difflib- Open files (os.startfile on Windows / xdg-open on Linux / open on macOS)- Add custom commands (open app, shell command)- Demo includes uploaded file path: /mnt/data/image.png"""import osimport sysimport threadingimport platformimport subprocessfrom pathlib import Pathimport tkinter as tkfrom tkinter import ttk, filedialog, messageboxfrom difflib import get_close_matches# Optional global hotkey packagetry:    import keyboard  # pip install keyboard    KEYBOARD_AVAILABLE = Trueexcept Exception:    KEYBOARD_AVAILABLE = False# Demo uploaded file path (from your session)DEMO_FILE = "/mnt/data/image.png"# ------------------------------# Utility functions# ------------------------------def open_path(path):    """Open a file or folder using the OS default application."""    p = str(path)    if platform.system() == "Windows":        os.startfile(p)    elif platform.system() == "Darwin":  # macOS        subprocess.Popen(["open", p])    else:  # Linux and others        subprocess.Popen(["xdg-open", p])def is_executable_file(path):    try:        return os.access(path, os.X_OK) and Path(path).is_file()    except Exception:        return False# ------------------------------# Indexer# ------------------------------class FileIndexer:    def __init__(self):        self.items = []  # list of {"title": ..., "path": ..., "type": "file"|"cmd"}        # preload demo item if exists        if Path(DEMO_FILE).exists():            self.add_item(title=Path(DEMO_FILE).name, path=str(DEMO_FILE), typ="file")    def add_item(self, title, path, typ="file"):        rec = {"title": title, "path": path, "type": typ}        self.items.append(rec)    def index_folder(self, folder, max_files=5000):        """Recursively index a folder (stop at max_files)."""        folder = Path(folder)        count = 0        for root, dirs, files in os.walk(folder):            for f in files:                try:                    fp = Path(root) / f                    self.add_item(title=f, path=str(fp), typ="file")                    count += 1                    if count >= max_files:                        return count                except Exception:                    continue        return count    def add_common_apps(self):        """Add some common app commands (platform-specific)."""        sysplat = platform.system()        apps = []        if sysplat == "Windows":            # common Windows apps (paths may vary)            apps = [                ("Notepad", "notepad.exe"),                ("Calculator", "calc.exe"),                ("Paint", "mspaint.exe"),            ]        elif sysplat == "Darwin":            apps = [                ("TextEdit", "open -a TextEdit"),                ("Calculator", "open -a Calculator"),            ]        else:  # Linux            apps = [                ("Gedit", "gedit"),                ("Calculator", "gnome-calculator"),            ]        for name, cmd in apps:            self.add_item(title=name, path=cmd, typ="cmd")    def search(self, query, limit=15):        """Simple fuzzy search: look for substrings first, then difflib matches."""        q = query.strip().lower()        if not q:            # return top items            return self.items[:limit]        # substring matches (higher priority)        substr_matches = [it for it in self.items if q in it["title"].lower() or q in it["path"].lower()]        if len(substr_matches) >= limit:            return substr_matches[:limit]        # prepare list of titles for difflib        titles = [it["title"] for it in self.items]        close = get_close_matches(q, titles, n=limit, cutoff=0.4)        # map back to records preserving order (titles may repeat)        close_records = []        for t in close:            for it in self.items:                if it["title"] == t and it not in close_records:                    close_records.append(it)                    break        # combine substring + close matches, ensure uniqueness        results = []        seen = set()        for it in substr_matches + close_records:            key = (it["title"], it["path"])            if key not in seen:                results.append(it)                seen.add(key)            if len(results) >= limit:                break        return results# ------------------------------# GUI# ------------------------------class CommandPalette(tk.Toplevel):    def __init__(self, master, indexer: FileIndexer):        super().__init__(master)        self.indexer = indexer        self.title("Command Palette")        self.geometry("700x380")        self.transient(master)        self.grab_set()  # modal        self.resizable(False, False)        # Styling        self.configure(bg="#2b2b2b")        # Search box        self.search_var = tk.StringVar()        search_entry = ttk.Entry(self, textvariable=self.search_var, font=("Consolas", 14), width=60)        search_entry.pack(padx=12, pady=(12,6))        search_entry.focus_set()        search_entry.bind("<KeyRelease>", self.on_search_key)        search_entry.bind("<Escape>", lambda e: self.close())        search_entry.bind("<Return>", lambda e: self.open_selected())        # Results list        self.tree = ttk.Treeview(self, columns=("title","path","type"), show="headings", height=12)        self.tree.heading("title", text="Title")        self.tree.heading("path", text="Path / Command")        self.tree.heading("type", text="Type")        self.tree.column("title", width=250)        self.tree.column("path", width=350)        self.tree.column("type", width=80, anchor="center")        self.tree.pack(padx=12, pady=6, fill="both", expand=True)        self.tree.bind("<Double-1>", lambda e: self.open_selected())        self.tree.bind("<Return>", lambda e: self.open_selected())        # Bottom buttons        btn_frame = ttk.Frame(self)        btn_frame.pack(fill="x", padx=12, pady=(0,12))        ttk.Button(btn_frame, text="Open Folder to Index", command=self.browse_and_index).pack(side="left")        ttk.Button(btn_frame, text="Add Command", command=self.add_command_dialog).pack(side="left", padx=6)        ttk.Button(btn_frame, text="Close (Esc)", command=self.close).pack(side="right")        # initial populate        self.update_results(self.indexer.items[:50])    def on_search_key(self, event=None):        q = self.search_var.get()        results = self.indexer.search(q, limit=50)        self.update_results(results)        # keep the first row selected        children = self.tree.get_children()        if children:            self.tree.selection_set(children[0])            self.tree.focus(children[0])    def update_results(self, records):        # clear        for r in self.tree.get_children():            self.tree.delete(r)        for rec in records:            self.tree.insert("", "end", values=(rec["title"], rec["path"], rec["type"]))    def open_selected(self):        sel = self.tree.selection()        if not sel:            return        vals = self.tree.item(sel[0])["values"]        title, path, typ = vals        try:            if typ == "file":                open_path(path)            elif typ == "cmd":                # if it's a shell command, run it                # Allow both simple exe names and complex shell commands                if platform.system() == "Windows":                    subprocess.Popen(path, shell=True)                else:                    subprocess.Popen(path.split(), stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)            else:                # fallback attempt                open_path(path)        except Exception as e:            messagebox.showerror("Open failed", f"Could not open {path}\n\n{e}")        finally:            self.close()    def browse_and_index(self):        folder = filedialog.askdirectory()        if not folder:            return        count = self.indexer.index_folder(folder)        messagebox.showinfo("Indexed", f"Indexed approx {count} files from {folder}")        # refresh results        self.on_search_key()    def add_command_dialog(self):        dlg = tk.Toplevel(self)        dlg.title("Add Command / App")        dlg.geometry("500x150")        tk.Label(dlg, text="Title:").pack(anchor="w", padx=8, pady=(8,0))        title_e = ttk.Entry(dlg, width=60)        title_e.pack(padx=8)        tk.Label(dlg, text="Command or Path:").pack(anchor="w", padx=8, pady=(8,0))        path_e = ttk.Entry(dlg, width=60)        path_e.pack(padx=8)        def add():            t = title_e.get().strip() or Path(path_e.get()).name            p = path_e.get().strip()            if not p:                messagebox.showwarning("Input", "Please provide a command or path")                return            typ = "cmd" if (" " in p or os.sep not in p and not Path(p).exists()) else "file"            self.indexer.add_item(title=t, path=p, typ=typ)            dlg.destroy()            self.on_search_key()        ttk.Button(dlg, text="Add", command=add).pack(pady=8)    def close(self):        try:            self.grab_release()        except:            pass        self.destroy()# ------------------------------# Main App Window# ------------------------------class PaletteApp:    def __init__(self, root):        self.root = root        root.title("Command Palette Launcher")        root.geometry("700x120")        self.indexer = FileIndexer()        self.indexer.add_common_apps()        # Add a few demo entries (including uploaded file path)        if Path(DEMO_FILE).exists():            self.indexer.add_item(title=Path(DEMO_FILE).name, path=str(DEMO_FILE), typ="file")        # Top UI        frame = ttk.Frame(root, padding=12)        frame.pack(fill="both", expand=True)        ttk.Label(frame, text="Press Ctrl+P to open command palette", font=("Arial", 12)).pack(anchor="w")        ttk.Button(frame, text="Open Palette (Ctrl+P)", command=self.open_palette).pack(pady=10, anchor="w")        ttk.Button(frame, text="Index Folder", command=self.index_folder).pack(side="left")        ttk.Button(frame, text="Exit", command=root.quit).pack(side="right")        # register global hotkey in a background thread (if available)        if KEYBOARD_AVAILABLE:            t = threading.Thread(target=self.register_global_hotkey, daemon=True)            t.start()        else:            print("keyboard package not available — global hotkey disabled. Use app's Ctrl+P instead.")        # bind Ctrl+P inside the Tk window too        root.bind_all("<Control-p>", lambda e: self.open_palette())    def open_palette(self):        # open modal CommandPalette        cp = CommandPalette(self.root, self.indexer)    def index_folder(self):        folder = filedialog.askdirectory()        if not folder:            return        count = self.indexer.index_folder(folder)        messagebox.showinfo("Indexed", f"Indexed approx {count} files")    def register_global_hotkey(self):        """        Register Ctrl+P as a global hotkey using keyboard module.        When pressed, we must bring the Tk window to front and open palette.        """        try:            # On some systems, keyboard requires admin privileges. If it fails, we catch and disable.            keyboard.add_hotkey("ctrl+p", lambda: self.trigger_from_global())            keyboard.wait()  # keep the listener alive        except Exception as e:            print("Global hotkey registration failed:", e)    def trigger_from_global(self):        # Because keyboard runs in another thread, schedule UI work in Tk mainloop        try:            self.root.after(0, self.open_palette)            # Try to bring window to front            try:                self.root.lift()                self.root.attributes("-topmost", True)                self.root.after(500, lambda: self.root.attributes("-topmost", False))            except Exception:                pass        except Exception as e:            print("Error triggering palette:", e)# ------------------------------# Run# ------------------------------def main():    root = tk.Tk()    app = PaletteApp(root)    root.mainloop()if __name__ == "__main__":    main()

View original source →

Related