Beispiel #1
0
    def _tag_count(self, tag):
        """To pick the best tag candidate for a given tag name.

        The number retruned is meant to be used in conjunction with the :tag
        vim command (see :h :tag)
        """
        enc = v.encoding()
        candidates = v.call(u'taglist("{}")'.format(tag["name"]))
        if len(candidates) == 1:
            return 1, candidates[0]["filename"].decode(enc)

        #  group tags by file name
        groups = []
        for fname, g in groupby(candidates, key=itemgetter("filename")):
            groups.append((fname, list(g)))
        groups.sort(key=itemgetter(0))

        # sort tags by the `line` field (XXX: or `cmd`?); tags from of the
        # current buffer are put first. This is ensures that the `:[count]tag
        # [name]` command will work as expected (see :h tag-priority)
        ordered_candidates = []
        for fname, tags in groups:
            sorted_tags = sorted(tags, key=itemgetter("line"))
            if fname.decode(enc) == v.bufname():
                ordered_candidates = sorted_tags + ordered_candidates
            else:
                ordered_candidates.extend(sorted_tags)

        files = [c["filename"].decode(enc) for c in ordered_candidates]
        scores = [0]*len(ordered_candidates)
        for i, candidate in enumerate(ordered_candidates):
            if candidate["cmd"].decode(enc) == tag["cmd"]:
                scores[i] += 1
            if candidate["name"].decode(enc) == tag["name"]:
                scores[i] += 1
            if candidate["filename"].decode(enc) == tag["file"]:
                scores[i] += 1
            if candidate["line"].decode(enc) == tag["exts"].get("line"):
                scores[i] += 1
            if candidate["kind"].decode(enc) == tag["exts"].get("kind"):
                scores[i] += 1
            if candidate["language"].decode(enc) == tag["exts"].get("language"):
                scores[i] += 1

        idx = scores.index(max(scores))
        return idx + 1, files[idx]
Beispiel #2
0
    def open(self):
        """To open the Surfer user interface."""
        # The Fugitive plugin seems to interfere with Surfer since it adds
        # some filenames to the vim option `tags`. Surfer does this too,
        # but if Fugitive is installed and the user is editing a file in a git
        # repository, it seems that Surfer cannot append anything to the
        # `tag` option. I haven't still figured out why this happens but this
        # seems to fix the issue.
        v.exe("exe 'set tags='.&tags")

        self.user_buf = self.BufInfo(v.bufname(), v.bufnr(), v.winnr())
        pmod = settings.get("project_search_modifier")
        bmod = settings.get("buffer_search_modifier")

        prompt = u"echohl SurferPrompt | echon \"{}\" | echohl None".format(
            settings.get("prompt"))

        self._open_window()
        self.renderer.render(self.winnr, -1, "", [], "")
        v.redraw()

        # Start the input loop
        key = input.Input()
        while True:

            self.perform_new_search = True

            # Display the prompt and the current query
            v.exe(prompt)
            query = self.query.replace("\\", "\\\\").replace('"', '\\"')
            v.exe(u"echon \"{}\"".format(query))

            # Wait for the next pressed key
            key.get()

            # Go to the tag on the current line
            if (key.RETURN or key.CTRL and key.CHAR in ('g', 'o', 'p', 's')):
                mode = key.CHAR if key.CHAR in ('s', 'p') else ''
                tag = self.mapper.get(self.cursor_pos)
                if tag:
                    self._jump_to(tag, mode)
                    break

            # Close the Surfer window
            elif key.ESC or key.INTERRUPT:
                self._close()
                break

            # Delete a character backward
            elif key.BS:
                query = self.query.strip()
                if query and query in (bmod, pmod):
                    self.plug.generator.rebuild_tags = True
                self.query = u"{}".format(self.query)[:-1]
                self.cursor_pos = -1  # move the cursor to the bottom

            # Move the cursor up
            elif key.UP or key.TAB or key.CTRL and key.CHAR == 'k':
                self.perform_new_search = False
                if self.cursor_pos == 0:
                    self.cursor_pos = len(v.buffer()) - 1
                else:
                    self.cursor_pos -= 1

            # Move the cursor down
            elif key.DOWN or key.CTRL and key.CHAR == 'j':
                self.perform_new_search = False
                if self.cursor_pos == len(v.buffer()) - 1:
                    self.cursor_pos = 0
                else:
                    self.cursor_pos += 1

            # Clear the current search
            elif key.CTRL and key.CHAR == 'u':
                query = self.query.lstrip()
                if query and query[0] in (bmod, pmod):
                        self.query = query[0]
                else:
                    self.query = u""
                self.cursor_pos = -1  # move the cursor to the bottom

            # A character has been pressed.
            elif key.CHAR:
                self.query += key.CHAR
                self.cursor_pos = -1  # move the cursor to the bottom
                if key.CHAR in (pmod, bmod) and len(self.query.strip()) == 1:
                    self.plug.generator.rebuild_tags = True

            else:
                v.redraw()
                continue

            self._update()
            v.redraw()
Beispiel #3
0
 def update_root(self):
     """To keep updated the project root whenever the user edits a buffer."""
     bufname = v.bufname()
     if bufname is None or not bufname.startswith(self.root_cache):
         self.files_cache = []
         self.root_cache = u""