Пример #1
0
    def on_suggest(self, user_input, items_chain):
        if (not items_chain
                or items_chain[0].category() != kp.ItemCategory.KEYWORD
                or items_chain[0].target() != "jumpfile"):
            return

        with self.wa_mutex:
            playlist = self.wa.get_tracks_titles()
        if not playlist:
            return

        suggestions = []
        desc_fmt = "Requests Winamp to jump to track #{:0" + str(
            len(str(len(playlist)))) + "}"
        for idx in range(len(playlist)):
            title = playlist[idx]
            if title is None:
                continue

            # if user_input is empty, just match everything we get
            include_track = 1
            if len(user_input) > 0:
                #include_track = True if user_input.lower() in title.lower() else False
                include_track = kpu.fuzzy_score(user_input, title) > 0
            if include_track:
                clone = items_chain[0].clone()
                clone.set_args(str(idx), title)
                clone.set_short_desc(desc_fmt.format(idx + 1))
                suggestions.append(clone)

        if len(suggestions) > 0:
            self.set_suggestions(suggestions)
Пример #2
0
    def on_suggest(self, user_input, items_chain):
        if not items_chain or items_chain[0].category(
        ) != kp.ItemCategory.KEYWORD:
            return

        suggestions = []

        data_bag = kpu.kwargs_decode(items_chain[0].data_bag())
        sessions = self._distros[data_bag['distro_name']]['sessions']
        for session in sessions:
            session_name = str(session).replace('\\', '/')
            if not user_input or kpu.fuzzy_score(user_input, session_name) > 0:
                suggestions.append(
                    self.create_item(
                        category=kp.ItemCategory.REFERENCE,
                        label=session_name,
                        short_desc='Open "{}" with HeidiSQL'.format(
                            session_name),
                        target=kpu.kwargs_encode(
                            distro_name=data_bag['distro_name'],
                            session=session),
                        args_hint=kp.ItemArgsHint.FORBIDDEN,
                        hit_hint=kp.ItemHitHint.IGNORE))

        self.set_suggestions(suggestions, kp.Match.ANY, kp.Sort.NONE)
Пример #3
0
    def _home_suggestions(self, search_terms):
        # suggest only existing home dirs
        existing_home_dirs = []
        for home_dir in self.home:
            if os.path.isdir(home_dir):
                existing_home_dirs.append(home_dir)

        # If only one home dir remains, directly browse its content and filter
        # the results using search_terms, if any.
        if len(existing_home_dirs) == 1:
            suggestions, match_method, sort_method = self._browse_dir(
                existing_home_dirs[0],
                check_base_dir=False,
                search_terms=search_terms,
                store_score=True)
            if len(search_terms) > 0:
                # Because of the self.home_trigger prefix, the user_input cannot
                # be matched against files names. So we have to sort the
                # suggestions by ourselves.
                self._sort_matched_suggestions(suggestions)
                return suggestions, kp.Match.ANY, kp.Sort.NONE
            else:
                return suggestions, match_method, sort_method

        # Otherwise, we must first offer the list of available "home"
        # directories. Here again, we filter them by using search_terms if
        # needed.
        else:
            suggestions = []
            for home_dir in existing_home_dirs:
                match_score = None
                if len(search_terms) > 0:
                    match_score = kpu.fuzzy_score(search_terms,
                                                  os.path.basename(home_dir))
                    if not match_score:
                        continue
                    match_score = str(match_score)
                suggestions.append(
                    self.create_item(category=kp.ItemCategory.FILE,
                                     label=os.path.basename(home_dir),
                                     short_desc="",
                                     target=home_dir,
                                     args_hint=kp.ItemArgsHint.ACCEPTED,
                                     hit_hint=kp.ItemHitHint.KEEPALL,
                                     loop_on_suggest=True,
                                     data_bag=match_score))

            if len(search_terms) > 0:
                # Because of the self.home_trigger prefix, the user_input cannot be
                # matched against files names. So we have to sort the suggestions by
                # ourselves.
                self._sort_matched_suggestions(suggestions)

            return suggestions, kp.Match.ANY, kp.Sort.NONE
Пример #4
0
    def on_suggest(self, user_input, items_chain):
        if not items_chain or items_chain[0].category(
        ) != kp.ItemCategory.FILE:
            return

        suggestions = []

        data_bag = kpu.kwargs_decode(items_chain[0].data_bag())
        current_distro = self._distros[data_bag['distro_name']]
        current_distro_path = os.path.dirname(
            os.path.abspath(current_distro['exe_file']))
        sessions = current_distro['sessions']

        for session_name in sessions:
            displayed_session_name = session_name.replace(
                os.path.join(current_distro_path, 'Sessions') + os.sep, '')
            if not user_input or kpu.fuzzy_score(user_input,
                                                 displayed_session_name) > 0:
                suggestions.append(
                    self.create_item(category=kp.ItemCategory.REFERENCE,
                                     label="{}".format(displayed_session_name),
                                     short_desc='Launch "{}" session'.format(
                                         displayed_session_name),
                                     target=kpu.kwargs_encode(
                                         dist=data_bag['distro_name'],
                                         session=session_name),
                                     args_hint=kp.ItemArgsHint.FORBIDDEN,
                                     hit_hint=kp.ItemHitHint.IGNORE))

        if user_input:
            suggestions.append(
                self.create_item(
                    category=kp.ItemCategory.REFERENCE,
                    label="{}".format(user_input),
                    short_desc='Launch "{}" directly'.format(user_input),
                    target=kpu.kwargs_encode(dist=data_bag['distro_name'],
                                             host_name=user_input),
                    args_hint=kp.ItemArgsHint.FORBIDDEN,
                    hit_hint=kp.ItemHitHint.IGNORE))

        self.set_suggestions(suggestions, kp.Match.ANY, kp.Sort.NONE)
Пример #5
0
    def on_suggest(self, user_input, items_chain):
        if not items_chain and (not self.always_suggest or len(user_input) == 0):
            return
        if items_chain and (
                items_chain[0].category() != kp.ItemCategory.KEYWORD or
                items_chain[0].target() != self.KEYWORD):
            return

        try:
            handles = AltTab.list_alttab_windows()
        except OSError as exc:
            self.err("Failed to list Alt+Tab windows.", str(exc))
            return

        suggestions = []
        procs = {}
        for hwnd in handles:
            # get window's title and the id of its parent process
            try:
                wnd_title = AltTab.get_window_text(hwnd)
                (_, proc_id) = AltTab.get_window_thread_process_id(hwnd)
                if proc_id == kp.pid():
                    continue # skip any window from main keypirinha's process
            except OSError:
                continue

            # Get the name of its parent process.
            # We have to OpenProcess to do that. Unfortunately, Vista and beyond
            # won't allow us to do so if the remote process has higher
            # privileges than us.
            if proc_id in procs:
                proc_image = procs[proc_id]
            else:
                try:
                    proc_image = AltTab.get_process_image_path(proc_id)
                except OSError:
                    proc_image = None
                procs[proc_id] = proc_image

            # build the final label of the suggestion item
            item_label = wnd_title
            item_short_desc = "{}: {}".format(self.item_label, wnd_title)
            if proc_image is not None:
                proc_name = os.path.splitext(os.path.basename(proc_image))[0]
                if self.proc_name_first:
                    item_label = proc_name + ": " + item_label
                    #item_short_desc = proc_name + ": " + item_short_desc
                else:
                    item_label += " (" + proc_name + ")"
                item_short_desc += " (" + proc_name + ")"

            # if user_input is empty, just match everything we get
            match_score = 1
            if len(user_input) > 0:
                if items_chain and items_chain[0]:
                    against = item_label
                else:
                    against = self.item_label + " " + item_label
                match_score = kpu.fuzzy_score(user_input, against)
            if match_score:
                suggestion = self._create_keyword_item(self.item_label, item_short_desc, target=proc_image)
                suggestion.set_args(str(hwnd), item_label)
                suggestions.append(suggestion)

        if len(suggestions) > 0:
            self.set_suggestions(suggestions)
Пример #6
0
    def _enum_key(self,
                  keypath,
                  user_input="",
                  show_error=True,
                  loop_on_current=True):
        def _sort_names(sequence, do_natsort):
            if do_natsort:
                yield from natsort.natsorted(sequence,
                                             alg=natsort.ns.GROUPLETTERS
                                             | natsort.ns.LOCALE
                                             | natsort.ns.IGNORECASE)
            else:
                yield from sequence

        def _sort_items(sequence):
            # sort items using the score that is stored in the data_bag member,
            # then clear it to avoid polluting the Catalog and the History
            def _sortkey(item):
                score = item.data_bag()
                item.set_data_bag("")
                return score

            sequence.sort(key=_sortkey, reverse=True)

        user_input = user_input.strip()
        if not len(user_input):
            user_input = None
        items = []

        # open registry key
        try:
            hkey = winreg.OpenKey(keypath.root_hkey, keypath.subkey)
        except OSError as exc:
            if show_error:
                items.append(
                    self.create_error_item(
                        label=keypath.path,
                        short_desc="Registry key not found: " + keypath.path))
            return items

        # enumerate keys and values
        subkeys = {}
        values = {}
        try:
            idx = 0
            while True:
                try:
                    name = winreg.EnumKey(hkey, idx)
                    idx += 1
                    if len(name):
                        if user_input is None:
                            score = None
                        else:
                            score = kpu.fuzzy_score(user_input, name)
                        if score is None or score > 0:
                            subkeys[name] = score
                except OSError:
                    break

            # enum values
            idx = 0
            while True:
                try:
                    val = _KeyValue(*winreg.EnumValue(hkey, idx))
                    idx += 1
                    if user_input is None:
                        score = None
                    elif not len(val.name):
                        score = 1  # name may be empty for the "(Default)" value
                    else:
                        score = kpu.fuzzy_score(user_input, val.name)
                    if score is None or score > 0:
                        values[val.name] = (val, score)
                except OSError:
                    break
        finally:
            hkey.Close()

        for subkey_name in _sort_names(subkeys.keys(), user_input is None):
            full_path = keypath.path + "\\" + subkey_name
            data_bag = None if subkeys[subkey_name] is None else str(
                subkeys[subkey_name])
            items.append(
                self.create_item(category=self.ITEMCAT_REGKEY,
                                 label=subkey_name,
                                 short_desc=full_path,
                                 target=full_path,
                                 args_hint=kp.ItemArgsHint.ACCEPTED,
                                 hit_hint=kp.ItemHitHint.IGNORE,
                                 loop_on_suggest=True,
                                 data_bag=data_bag))

        for value_name in _sort_names(values.keys(), user_input is None):
            full_path = keypath.path + "\\" + value_name
            data_bag = None if values[value_name][1] is None else str(
                values[value_name][1])
            if values[value_name][0].data_type in (
                    winreg.REG_SZ, winreg.REG_MULTI_SZ, winreg.REG_EXPAND_SZ,
                    winreg.REG_LINK, winreg.REG_RESOURCE_LIST,
                    winreg.REG_FULL_RESOURCE_DESCRIPTOR,
                    winreg.REG_RESOURCE_REQUIREMENTS_LIST):
                icon = self.icon_strvalue
            else:
                icon = self.icon_binvalue
            items.append(
                self.create_item(
                    category=self.ITEMCAT_REGVALUE,
                    label="(Default)" if not len(value_name) else value_name,
                    short_desc=full_path,
                    target=full_path,
                    args_hint=kp.ItemArgsHint.FORBIDDEN,
                    hit_hint=kp.ItemHitHint.IGNORE,
                    loop_on_suggest=False,
                    icon_handle=icon,
                    data_bag=data_bag))

        if user_input is None:
            items.insert(
                0,
                self.create_item(category=self.ITEMCAT_REGKEY,
                                 label="\\",
                                 short_desc=keypath.path,
                                 target=keypath.path,
                                 args_hint=kp.ItemArgsHint.ACCEPTED,
                                 hit_hint=kp.ItemHitHint.IGNORE,
                                 loop_on_suggest=loop_on_current))
        else:
            _sort_items(items)

        return items
Пример #7
0
    def _insert_recents(self,
                        suggestions,
                        match_method=kp.Match.ANY,
                        sort_method=kp.Sort.NONE,
                        search_terms=""):
        recents = []
        if search_terms:
            search_terms = os.path.normcase(os.path.normpath(search_terms))

        try:
            with winreg.OpenKey(
                    winreg.HKEY_CURRENT_USER,
                    "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\TypedPaths"
            ) as hkey:
                url_idx = 0
                while True:
                    (name, value, typ) = winreg.EnumValue(hkey, url_idx)
                    url_idx += 1
                    if typ == winreg.REG_SZ and name.lower().startswith("url"):
                        # we must check that value is a path since value can
                        # also be the name of a known folder like "Computer"
                        value = os.path.normpath(value)
                        if not (os.path.isabs(value)
                                or os.path.ismount(value)):
                            continue

                        if search_terms and not os.path.normcase(
                                value).startswith(search_terms):
                            continue

                        if match_method == kp.Match.FUZZY:
                            score = str(kpu.fuzzy_score(search_terms, value))
                        else:
                            score = None

                        recents.append(
                            self.create_item(
                                category=kp.ItemCategory.FILE,
                                label=value,
                                short_desc="",
                                target=value,
                                args_hint=kp.ItemArgsHint.ACCEPTED,
                                hit_hint=kp.ItemHitHint.KEEPALL,
                                loop_on_suggest=True,
                                data_bag=score))
        except OSError as exc:
            pass

        if sort_method == kp.Sort.NONE:

            def _find_same_item(target, lst):
                target = os.path.normpath(target)
                for idx in range(len(lst)):
                    if target == os.path.normpath(lst[idx].target()):
                        return idx
                return None

            # remove duplicates by ourselves so Keypirinha does not try to merge
            # them, which may alter the desired positioning of items
            for recent_item in recents:
                match_idx = _find_same_item(recent_item.target(), suggestions)
                if match_idx is not None:
                    suggestions.pop(match_idx)

            recents = natsort.natsorted(recents,
                                        key=lambda x: x.label(),
                                        alg=natsort.ns.PATH | natsort.ns.LOCALE
                                        | natsort.ns.IGNORECASE)

            # prepend the recents list to the suggestions
            # but always keep the "." item at the top
            if len(suggestions) > 0 and suggestions[0].label() == ".":
                suggestions[1:0] = recents
            else:
                suggestions[:0] = recents

        else:
            # note: Keypirinha will take care of removing duplicates
            suggestions += recents