From 6bd3b1328411dda4e50a400173e17721e28757ca Mon Sep 17 00:00:00 2001 From: Storm Dragon Date: Sun, 27 Sep 2026 16:55:56 -0400 Subject: [PATCH] Fix unreliable run dialogue history entries --- scripts/run_dialog.py | 56 ++++++++++++++++++++++++++++++++++++------- 1 file changed, 48 insertions(+), 8 deletions(-) diff --git a/scripts/run_dialog.py b/scripts/run_dialog.py index 5c11cb7..50763fc 100755 --- a/scripts/run_dialog.py +++ b/scripts/run_dialog.py @@ -87,16 +87,17 @@ def read_history(): def write_history(entry, items): entry = entry.strip() if not entry: - return + return items[:MAX_HISTORY_ENTRIES] updated_items = [entry] updated_items.extend(item for item in items if item != entry) + return updated_items[:MAX_HISTORY_ENTRIES] + + +def save_history(items): path = history_path() path.parent.mkdir(parents=True, exist_ok=True) - path.write_text( - "\n".join(updated_items[:MAX_HISTORY_ENTRIES]) + "\n", - encoding="utf-8", - ) + path.write_text("\n".join(items[:MAX_HISTORY_ENTRIES]) + "\n", encoding="utf-8") def path_commands(): @@ -167,9 +168,11 @@ def application_results(query, applications): for app in applications: name = app.get_display_name() or app.get_name() executable = app.get_executable() or "" + if not executable: + continue if not matches(query, name) and not matches(query, executable): continue - results.append(Result("application", name, f"Application: {executable}", name, app.get_id() or "")) + results.append(Result("application", name, f"Application: {executable}", executable, app.get_id() or "")) return sorted(results, key=lambda item: item.label.casefold()) @@ -390,8 +393,23 @@ class RunDialog(Gtk.Window): self.entry.set_text(result.value) self.entry.set_position(-1) + def remember_history(self, entry): + entry = entry.strip() + if not entry: + return + self.history = write_history(entry, self.history) + save_history(self.history) + + def forget_history(self, entry): + entry = entry.strip() + if entry not in self.history: + return + self.history.remove(entry) + save_history(self.history) + def activate(self, result=None): if result is not None and result.kind == "directory": + self.remember_history(result.value) self.entry.set_text(result.value) self.entry.set_position(-1) return @@ -400,7 +418,6 @@ class RunDialog(Gtk.Window): if not text: return - write_history(text, self.history) if result is not None and result.kind == "application": self.launch_application(result) return @@ -412,10 +429,16 @@ class RunDialog(Gtk.Window): self.show_error(f"Application is no longer available: {result.label}") return try: - app.launch([], None) + launched = app.launch([], None) except GLib.Error as error: + self.forget_history(result.value) self.show_error(f"Could not open {result.label}.\n\n{error.message}") return + if not launched: + self.forget_history(result.value) + self.show_error(f"Could not open {result.label}.") + return + self.remember_history(result.value) self.close() def launch_raw(self, text): @@ -467,12 +490,15 @@ class RunDialog(Gtk.Window): def check_process(self, process, description): status = process.poll() if status is None: + self.remember_history(description) Gtk.main_quit() return False if status == 0: + self.remember_history(description) Gtk.main_quit() return False + self.forget_history(description) self.show_all() self.entry.grab_focus() self.show_error( @@ -547,6 +573,19 @@ class RunDialog(Gtk.Window): def run_self_test(): + class FakeApplication: + def get_display_name(self): + return "Mozilla Firefox" + + def get_name(self): + return "Mozilla Firefox" + + def get_executable(self): + return "/usr/lib/firefox/firefox" + + def get_id(self): + return "firefox.desktop" + test_dir = Path(os.environ["I38_RUN_DIALOG_TEST_DIR"]) (test_dir / "folder").mkdir(parents=True) (test_dir / "tool").write_text("#!/bin/sh\n", encoding="utf-8") @@ -560,6 +599,7 @@ def run_self_test(): assert raw_target_kind("man://bash") == "manual" assert raw_target_kind(str(test_dir / "note.txt")) == "path" assert raw_target_kind('python3 "/tmp/file with spaces.py"') == "command" + assert application_results("firef", [FakeApplication()])[0].value == "/usr/lib/firefox/firefox" assert merge_results( [Result("history", "firefox", "History", "firefox")], [Result("command", "firefox", "Command", "firefox")],