def make_stop_menu(self, stop: Stop, back: str) -> BaseAction: items = [ ExtensionResultItem( icon="images/icon.png", name="Departures", highlightable=False, on_enter=SetUserQueryAction(f"{self.kw} departures {stop.id}")) ] if self.fav_has(stop.id): items.append( ExtensionResultItem( icon="images/icon.png", name="Remove from favorites", highlightable=False, on_enter=ExtensionCustomAction(f"remove {stop.id}"))) else: items.append( ExtensionResultItem( icon="images/icon.png", name="Add to favorites", highlightable=False, on_enter=ExtensionCustomAction(f"add {stop.id}"))) items.append( ExtensionResultItem(icon="images/icon.png", name="Back", highlightable=False, on_enter=SetUserQueryAction(back + "`"))) return RenderResultListAction(items)
def show_menu(self): """ Shoe available extension options """ return RenderResultListAction([ ExtensionResultItem( icon=ICON_DEFAULT, name='Recent Builds', description='Lists the latest builds on Circle CI', on_enter=SetUserQueryAction(KEYWORD_RECENT_BUILDS + ' ')), ExtensionResultItem(icon=ICON_DEFAULT, name='Projects', description='Projects', on_enter=SetUserQueryAction(KEYWORD_PROJECTS + ' ')), ExtensionResultItem( icon=ICON_DEFAULT, name='Dashboard', description='Open the Circle CI dashboard page', on_enter=OpenUrlAction("https://circleci.com/dashboard")), ExtensionResultItem( icon=ICON_DEFAULT, name='Account Settings', description='Open the Circle CI account settings page', on_enter=OpenUrlAction("https://circleci.com/dashboard")), ExtensionResultItem( icon=ICON_DEFAULT, name='Status', description='Open the Circle CI status page', on_enter=OpenUrlAction("https://status.circleci.com/account")), ])
def on_event(self, event, extension): data = event.get_data() type = data.get("type") if type == "select": extension.snippet = data.get("snippet") extension.state = "var" elif type == "cancel": extension.reset() return SetUserQueryAction("") next_variable = extension.snippet.next_variable() if extension.state == "var" and next_variable: keyword = extension.preferences["snippets_keyword"] extension.variable = next_variable return ActionList([ SetUserQueryAction(keyword + " "), RenderResultListAction( show_var_input(extension.snippet, next_variable, next_variable.get("default", ""))) ]) try: copy_mode = extension.preferences["snippets_copy_mode"] if extension.snippet.file_path_template: try: file_path = extension.snippet.render_to_file_path( copy_mode=copy_mode) self._notify(extension, file_path, title="Snippet written to file") except FileExistsError as e: self._notify(extension, e.args[0], title="File already exists") return HideWindowAction() else: (mimetype, snippet) = extension.snippet.render(copy_mode=copy_mode) action = None if copy_mode == "xsel": copy_to_clipboard_xsel(snippet, mimetype) action = HideWindowAction() elif copy_mode == "wl": copy_to_clipboard_wl(snippet, mimetype) action = HideWindowAction() else: action = CopyToClipboardAction(snippet) self._notify(extension, snippet, mimetype) return action except Exception as e: logger.exception(e) return RenderResultListAction( [ExtensionResultItem(name=str(e), on_enter=DoNothingAction())]) finally: extension.reset()
def show_menu(self): """ Show the main extension menu when the user types the extension keyword without arguments """ keyword = self.preferences["kw"] menu = [ ExtensionResultItem( icon='images/icon.png', name="My", description= "Your personal menu with shortcuts for your Issues, Merge Requests and more", highlightable=False, on_enter=SetUserQueryAction("%s my" % keyword)), ExtensionResultItem( icon='images/icon.png', name="Project Search", description= "Search public projects in the entire GitLab platform", highlightable=False, on_enter=SetUserQueryAction("%s search " % keyword)), ExtensionResultItem( icon='images/icon.png', name="My Projects", description="List the projects you are a member of", highlightable=False, on_enter=SetUserQueryAction("%s projects " % keyword)), ExtensionResultItem(icon='images/icon.png', name="My Projects (Starred)", description="List your starred projects", highlightable=False, on_enter=SetUserQueryAction("%s starred " % keyword)), ExtensionResultItem(icon='images/icon.png', name="My Groups", description="List the groups you belong", highlightable=False, on_enter=SetUserQueryAction("%s groups " % keyword)), ExtensionResultItem(icon='images/icon.png', name="GitLab Website", description="Opens the GitLab website", highlightable=False, on_enter=OpenUrlAction(self.gitlab.url)), ExtensionResultItem( icon='images/icon.png', name="GitLab Status", description="Opens the GitLab status page", highlightable=False, on_enter=OpenUrlAction("https://status.gitlab.com")) ] return RenderResultListAction(menu)
def build_tag_items(self, tags, user_keyword): items = [] for tag in tags: data = {'type': 'pinboard', 'tags': [tag], 'browser': self.browser} items.append(ExtensionResultItem(icon='images/tag.png', name=tag, on_enter=SetUserQueryAction('%s %s' % (user_keyword, tag)), on_alt_enter=ExtensionCustomAction(data))) if items: data = {'type': 'pinboard', 'tags': tags, 'browser': self.browser} items.append(ExtensionResultItem(icon='images/tag.png', name='#all', on_enter=SetUserQueryAction('%s %s' % (user_keyword, '/'.join(tags))), on_alt_enter=ExtensionCustomAction(data))) return items
def process_keyword_query(self, event, extension) -> BaseAction: """ Handle a search query entered by user """ query_keyword = event.get_keyword() query_arg = event.get_argument() if not query_arg: if extension.recent_active_entries: return render.search_results( query_keyword, "", extension.recent_active_entries, extension.get_max_result_items(), ) return render.ask_to_enter_query() if extension.check_and_reset_active_entry(query_keyword, query_arg): details = self.keepassxc_db.get_entry_details(query_arg) return render.active_entry(details) prev_query_arg = extension.check_and_reset_search_restore(query_arg) if prev_query_arg: return SetUserQueryAction("{} {}".format(query_keyword, prev_query_arg)) entries = self.keepassxc_db.search(query_arg) return render.search_results(query_keyword, query_arg, entries, extension.get_max_result_items())
def list_available_docs(self, keyword, query): """ Renders a list of available Documentation, optionally filtered by the query argument :param str keyword: The search keyword :param str query: The search query. """ docs = self.devdocs_svc.get_docs(query) if not docs: return RenderResultListAction([ ExtensionResultItem( icon='images/icon.png', name='No documentation found matching your criteria', highlightable=False, on_enter=HideWindowAction()) ]) items = [] for doc in docs[:10]: items.append( ExtensionResultItem(icon=self.get_icon(doc['slug']), name=doc['name'], description=doc.get('release', ""), on_enter=SetUserQueryAction( "%s %s:" % (keyword, doc['slug'])), on_alt_enter=self.open_in_devdocs( doc['slug']))) return RenderResultListAction(items)
def _generate_result_item_from_exact_match(self, extension, dbang: DBang, search_terms: list): """ Generates the result item for an exact dbang match case 1) the query is already in the correct format: If the user clicks on the item, the url should be opened example: "! w Ulauncher" -> opens a Wikipedia search for Ulauncher in the browser case 2) otherwise the query is set to the right format, with the Dbang term in front example: ! wikipedia search" -> sets the query to "! w ", and in the next query event case 1 will apply """ if len(search_terms) > 1: search_text = " ".join(search_terms[1:]) title = "{0} | {1}: Search for \"{2}\"".format( dbang.t, self.make_site_title(dbang), self.escape_html(search_text)) # The url is not generated right away, as the search term still change # The ExtensionCustomAction below will be received by OpenNewestUrlActionListener, # which takes the newest query that the user has typed for url generation action = ExtensionCustomAction(dbang, keep_app_open=True) else: title = "{0} | {1}: Enter search term".format( dbang.t, self.make_site_title(dbang)) new_query = self._make_query(extension, dbang) action = SetUserQueryAction(new_query) return ExtensionResultItem(name=title, icon=extension.icons.get_icon_path( dbang), description=self.make_bang_description( dbang), on_enter=action)
def render_results(self, path, files, dirs, keyword): """ Prepares the results for the UI """ items = [] limit = int(self.extension.preferences['max-results']) if limit < len(dirs) + len(files): items.append(MORE_ELEMENTS_ITEM) for _dir in dirs: limit -= 1 if limit < 0: break action = SetUserQueryAction("{0} {1}/".format( keyword, os_path.join(path, _dir))) items.append( ExtensionResultItem(icon=FOLDER_ICON, name="{0}".format(_dir), description=FOLDER_DESCRIPTION, on_enter=action)) for _file in files: limit -= 1 if limit < 0: break action = RunScriptAction("pass -c {0}/{1}".format(path, _file), None) items.append( ExtensionResultItem(icon=PASSWORD_ICON, name="{0}".format(_file), description=PASSWORD_DESCRIPTION, on_enter=action)) return items
def make_stop(self, stop: Stop, back: str) -> ExtensionResultItem: return ExtensionResultItem( icon="images/icon.png", name=f"#{stop.id} {stop.name}", description=f"{stop.lat}, {stop.lon}", on_enter=SetUserQueryAction(f"{self.kw} departures {stop.id}"), on_alt_enter=self.make_stop_menu(stop, back))
def show_menu(self): keyword = self.keyword items = [] items.append( ExtensionResultItem(name="Create Task", description="Create a new task", icon="images/create.png", on_enter=SetUserQueryAction("%s create " % keyword)) ) items.append( ExtensionResultItem(name="Today Tasks", description="Today task list", icon="images/today.png", on_enter=ExtensionCustomAction({"action": "today"}, keep_app_open=True)) ) items.append( ExtensionResultItem(name="Projects", description="Project list", icon="images/projects.png", on_enter=ExtensionCustomAction({"action": "projects"}, keep_app_open=True)) ) return RenderResultListAction(items)
def on_event(self, event, extension) -> BaseAction: try: data = event.get_data() action = data.get("action", None) if action == "read_passphrase": self.read_verify_passphrase() return DoNothingAction() if action == "activate_entry": keyword = data.get("keyword", None) entry = data.get("entry", None) extension.set_active_entry(keyword, entry) prev_query_arg = data.get("prev_query_arg", None) extension.set_active_entry_search_restore( entry, prev_query_arg) extension.add_recent_active_entry(entry) return SetUserQueryAction("{} {}".format(keyword, entry)) if action == "show_notification": Notify.Notification.new(data.get("summary")).show() except KeepassxcCliNotFoundError: return render.cli_not_found_error() except KeepassxcFileNotFoundError: return render.db_file_not_found_error() except KeepassxcCliError as exc: return render.keepassxc_cli_error(exc.message) return DoNothingAction()
def on_enter(self, query): action_list = ActionList() if query.get_keyword() == self.keyword and query.get_argument(): argument = query.get_argument() elif self.is_default_search: argument = query else: argument = None if self.run_without_argument: if self._is_url(): action = OpenUrlAction(self.cmd.strip()) else: action = RunScriptAction(self.cmd) action_list.append(action) elif argument: if self._is_url(): command = self.cmd.strip().replace('%s', argument) action = OpenUrlAction(command) else: action = RunScriptAction(self.cmd, argument) action_list.append(action) else: action_list.append(SetUserQueryAction('%s ' % self.keyword)) self._query_history.save_query(query, self.get_name()) return action_list
def on_enter(self, query): self._file_queries.save_query(self.path.get_abs_path()) if self.path.is_dir(): return SetUserQueryAction( os.path.join(self.path.get_user_path(), '')) return OpenAction(self.path.get_abs_path())
def execute(self, event, query, only_running=True): """ Lists the Containers """ filters = {} if query: filters["name"] = query.lstrip('-a ') if only_running: filters["status"] = "running" containers = self.extension.docker_client.containers.list( filters=filters, limit=8) items = [] for container in containers: items.append( ExtensionResultItem( icon='images/icon.png', name=container.name, description=container.status, on_enter=SetUserQueryAction( "%s -c %s" % (event.get_keyword(), container.short_id)))) return RenderResultListAction(items)
def on_event(self, event, extension): import gi gi.require_version('Gtk', '3.0') gi.require_version('Notify', '0.7') from gi.repository import Notify Notify.init('Ulauncher-OpenSubtitles') data = event.get_data() # If it's a 'download' type try: import srt url = data['download']['url'] download_id = data['download']['download_id'] try: srt.download(url, download_id) Notify.Notification.new("OpenSubtitles", 'Subtitles downloaded!', 'images/opensubtitles.png').show() except: Notify.Notification.new("OpenSubtitles", 'Error downloading subtitles!', 'images/not_found.png').show() except: # Check for video hash search try: from video import hash_video from preferences import PREF_KEYWORD file_path = data['video_hash'] file_hash = hash_video(file_path) return SetUserQueryAction(PREF_KEYWORD + ' -hash' + file_hash) except: # Do other feature pass
def handle_query(self, query: str) -> BaseAction: if query == '~': return SetUserQueryAction('~/') path = Path(query) # type: Path result_items = [] # type: Union[List, SortedList] try: existing_dir = path.get_existing_dir() if existing_dir == path.get_abs_path(): file_names = self.list_files(path.get_abs_path(), sort_by_usage=True) for name in self.filter_dot_files(file_names)[:self.RESULT_LIMIT]: file = os.path.join(existing_dir, name) result_items.append(self.create_result_item(file)) else: file_names = self.list_files(existing_dir) search_for = path.get_search_part() if not search_for.startswith('.'): file_names = self.filter_dot_files(file_names) files = [os.path.join(existing_dir, name) for name in file_names] result_items = SortedList(search_for, min_score=40, limit=self.RESULT_LIMIT) result_items.extend([self.create_result_item(name) for name in reversed(files)]) except (InvalidPathError, OSError): result_items = [] return RenderResultListAction(result_items)
def list_repos(self, query): """ Lists the Repositories from the user """ try: repos = self.travis_client.get_repos(query) except Exception as e: return self.handle_errors(e) if not repos: return RenderResultListAction([ ExtensionResultItem(icon='images/icon.png', name='No Repositories found', on_enter=HideWindowAction()) ]) items = [] for repo in repos[:8]: desc = '' if repo['description']: desc = repo['description'] items.append( ExtensionResultItem( icon='images/icon.png', name=repo['name'], description=desc, on_enter=SetUserQueryAction( "%s %s builds" % (self.preferences["kw"], repo['id'])), on_alt_enter=OpenUrlAction(repo['url']))) return RenderResultListAction(items)
def update_ui_query_string(self, event, query): """Changes Ui query string""" # pylint: disable=(protected-access) self._client.send( Response(event, SetUserQueryAction(self.variables.keyword + " " + query)))
def show_docsets_list(self, event, query): """ Displays a list of available docs """ docs = self.searcher.get_available_docs(query) items = [] if not docs: return RenderResultListAction([ ExtensionResultItem( icon='images/icon.png', name='No docsets found matching your criteria', on_enter=HideWindowAction()) ]) for doc in docs[:8]: items.append( ExtensionResultItem( icon=doc['icon'], name=doc['name'], description=doc['description'], on_alt_enter=OpenUrlAction(doc['url']), on_enter=SetUserQueryAction( "%s %s " % (event.get_keyword(), doc['key'])))) return RenderResultListAction(items)
def make_departures_stop(self, stop: Stop, back: str) -> ExtensionResultItem: return ExtensionResultItem( icon="images/icon.png", name=f"{stop.name}", description=f"Last updated {datetime.now().strftime('%H:%M:%S')}", highlightable=False, on_enter=SetUserQueryAction(f"{self.kw} departures {stop.id}`"), on_alt_enter=self.make_stop_menu(stop, back))
def show_menu(self, keyword): """ Show the main extension menu, when the user types the extension keyword without arguments """ return RenderResultListAction([ ExtensionResultItem(icon='images/icon.png', name="Upcoming events", description="Access your profile page", on_enter=SetUserQueryAction("%s events " % keyword)), ExtensionResultItem(icon='images/icon.png', name="courses", description="Courses", on_enter=SetUserQueryAction("%s courses " % keyword)) ])
def no_generator_items(keyword): return [ ExtensionResultItem(icon=generate_icon(gen_name), name=gen_data['name'], description=gen_data['description'], on_enter=SetUserQueryAction(keyword + ' ' + gen_name)) for (gen_name, gen_data) in GENERATORS.items() ]
def on_event(self, event, extension): vault = extension.preferences["obsidian_vault"] data = event.get_data() type = data.get("type") if type == "cancel": extension.reset() return SetUserQueryAction("") elif type == "create-note" and extension.state == "quick-capture-to-note": path = create_note_in_vault(vault, data.get("name")) append_to_note_in_vault(vault, path, extension.content) extension.reset() return HideWindowAction() elif type == "create-note": path = create_note_in_vault(vault, data.get("name")) url = generate_url(vault, path) return OpenAction(url) elif type == "quick-capture": quick_capute_note = extension.preferences[ "obsidian_quick_capture_note"] append_to_note_in_vault(vault, quick_capute_note, data.get("content")) return HideWindowAction() elif type == "quick-capture-to-note": keyword_quick_capture = extension.preferences[ "obsidian_quick_capture"] extension.state = "quick-capture-to-note" extension.content = data.get("content") return SetUserQueryAction(keyword_quick_capture + " ") elif extension.state == "quick-capture-to-note" and type == "select-note": quick_capute_note = data.get("note").path append_to_note_in_vault(vault, quick_capute_note, extension.content) extension.reset() return HideWindowAction() return DoNothingAction()
def on_event(self, event, extension): keyword = event.get_keyword() argument = event.get_argument() if not isinstance(event.get_argument(), str): return RenderResultListAction([ ExtensionResultItem(icon='images/jira.svg', name='Search for an issue summary', highlightable=False, on_enter=SetUserQueryAction( "%s %s " % (keyword, 'sm'))), ExtensionResultItem( icon='images/jira.svg', name='Try to search for a specific issue. Ex: PROJECT-123', highlightable=False, on_enter=HideWindowAction()) ]) try: summary_query = argument.startswith("sm ") summary_query_arg_length = len(argument.split('sm ')) if summary_query and summary_query_arg_length > 1: issues = extension.jira.search_issues( 'summary~"' + argument.split('sm ')[1] + '"') return self.render_results(issues) elif summary_query: return RenderResultListAction([ ExtensionResultItem(icon='images/jira.svg', name='No input', highlightable=False, on_enter=HideWindowAction()) ]) project_and_key = event.get_argument().split('-') if len(project_and_key) <= 1: return RenderResultListAction([ ExtensionResultItem(icon='images/jira.svg', name='Input not complete', highlightable=False, on_enter=HideWindowAction()) ]) return self.render_results( [extension.jira.issue(event.get_argument())]) except JIRAError as e: return RenderResultListAction([ ExtensionResultItem(icon='images/error.svg', description='', highlightable=False, name=e.text) ])
def on_event(self, event, extension): """ Handles the event """ data = event.get_data() if data["action"] == RESULT_ITEM_ENTER: extension.brotab_client.activate_tab(data["tab"]) if data["action"] == REFRESH_TABS: extension.brotab_client.index() kw = extension.preferences["kw"] extension.notify("Index Finished") return SetUserQueryAction("%s " % kw)
def handle_online_approx_results( self, soup: BeautifulSoup) -> List[ExtensionResultItem]: """All elements to be displayed by the extension when an approximate result is found (i.e.: no exact match for given word is found). Args: soup (BeautifulSoup): Whole page soup. Returns: List[ExtensionResultItem]: All elements to be shown by the extension. """ # approx_results = soup.find_all("a", {"data-acc": "LISTA APROX"}) # Example result: # <div class="n1"><a data-acc="LISTA APROX" data-cat="FETCH" data-eti="ad" href="/ad" title="Ir a la entrada">ad</a> (ad)</div> max_suggested_items = int(self.preferences["max_suggested_items"]) logger.info(f"max_suggested_items={max_suggested_items}") approx_results = soup.find_all("div", {"class": "n1"}) if len(approx_results) == 0: raise RuntimeError( "Attempted to handle the approx result case, but the soup doesn't have any <a> tags with 'data-acc'=='LISTA APROX'." ) seen = set() items = [] for i in approx_results[:max_suggested_items]: # Done this weird way because i.text would leave the <sup> tag as plaintext. # The structure of these <a> tags is, for example: # <a data-acc="LISTA APROX" data-cat="FETCH" data-eti="saber" href="/saber" title="Ir a la entrada">saber<sup>1</sup></a> # So children is always [word_of_interest, sup tag] or just [word_of_interest]. # Of note, the children is a NavigatableString which ulauncher doesn't like. a, infinitive = i.children display_name = str(next(a.children)) # Guarantee list of approx suggestions shows unique results. # On the web, the results are duplicated cause they link to different sections of the webpage, but the webpage is the same. # Ergo, it doesn't add information to show the entries more than once. if display_name in seen: continue else: seen.add(display_name) # https://github.com/Ulauncher/Ulauncher/blob/dev/ulauncher/api/shared/action/SetUserQueryAction.py new_query = f"{self.preferences['kw']} {display_name}" items.append( ExtensionResultItem( icon="images/icon.png", name=f"{display_name} ꞏ {infinitive.strip()}", description="Sugerencia RAE", on_enter=SetUserQueryAction(new_query), )) return items
def __help(self): all_opt = opts.get_all() items = [] for i in range(len(all_opt)): hint_str = 'locate ' + all_opt[i] query_str = 's r ' + all_opt[i] + ' ' items.append( ExtensionSmallResultItem( icon='images/info.png', name=hint_str, on_enter=SetUserQueryAction(query_str))) return items
def on_event(self, event, extension): if len(items) == 0: for ext in self.get_extensions(): items.append( ExtensionResultItem( icon=ext.icon, name='%s (%s)' % (ext.name, ext.def_value.rstrip().upper()), description='%s' % ext.description, on_enter=SetUserQueryAction(ext.def_value))) term = (event.get_argument() or "").lower() sorted = self.sort(term) return RenderResultListAction(sorted)
def handle_key_press_event(self, widget, event, query): keyval = event.get_keyval() keyname = Gdk.keyval_name(keyval[1]) ctrl = event.state & Gdk.ModifierType.CONTROL_MASK if keyname == 'BackSpace' and not ctrl and '/' in query and len(query.strip().rstrip('/')) > 1 and \ widget.get_position() == len(query) and not widget.get_selection_bounds(): # stop key press event if: # it's a BackSpace key and # Ctrl modifier is not pressed and # cursor is at the last position and # path exists and it's a directory and # input text is not selected widget.emit_stop_by_name('key-press-event') return SetUserQueryAction(os.path.join(Path(query).parent, '')) return DoNothingAction()