コード例 #1
0
ファイル: ui.py プロジェクト: vim-scripts/surfer.vim
    def _fmt_file(self, tag, dups_fnames):
        """Format tag file."""
        pmod = settings.get("project_search_modifier")
        bmod = settings.get("buffer_search_modifier")

        file = tag["file"]
        root = self.plug.project.get_root()

        # The user always wants the tag file displayed relative to the
        # current project root if it exists. Replacing the home with
        # '~' may be needed for files outside the current project that
        # are printed with the absolute path.
        if settings.get("tag_file_relative_to_project_root", bool):
            if root:
                f = file.replace(root, u"").replace(os.path.expanduser("~"), u"~")
                return f[1:] if f.startswith(os.path.sep) else f

        # If the `g:surfer_tag_file_custom_depth` is set,
        # cut the path according its value
        depth = settings.get("tag_file_custom_depth", int)
        if depth > 0:
            return os.path.join(*file.split(os.path.sep)[-depth:])

        # If th file name is duplicate in among search results
        # then display also the container directory
        if file in dups_fnames and len(file.split(os.path.sep)) > 1:
            return os.path.join(*file.split(os.path.sep)[-2:])

        # By default display only the file name
        return os.path.basename(file)
コード例 #2
0
ファイル: ui.py プロジェクト: vim-scripts/surfer.vim
    def _highlight_tags(self, tags, curr_line):
        """To highlight search results."""
        vk_colors = settings.get("visual_kinds_colors")
        vk_shape = settings.get("visual_kinds_shape")
        indicator = settings.get("current_line_indicator")

        for i, tag in enumerate(tags):

            if i == curr_line:
                offset = len(indicator.encode(v.encoding()))
            else:
                offset = len(indicator)

            if settings.get("visual_kinds", bool):
                offset += len(vk_shape.encode(v.encoding()))
                kind = tag["exts"].get("kind")
                if kind in vk_colors:
                    patt = u"\c\%{}l{}".format(i+1, vk_shape.replace(u"u",u"%u"))
                    v.highlight("SurferVisualKind_" + kind, patt)

            patt = u"\c\%{}l\%{}c.*".format(i+1, offset+len(tag["name"])+1)
            v.highlight("SurferShade", patt)

            for pos in misc.as_byte_indexes(tag["match_positions"], tag["name"]):

                patt = u"\c\%{}l\%{}c.".format(i+1, offset+pos+1)
                v.highlight("SurferMatches", patt)
コード例 #3
0
ファイル: finder.py プロジェクト: vim-scripts/surfer.vim
 def _split_query(self, query):
     """To extract the search modifier from the query. The clean query is
     also returned."""
     bmod = settings.get("buffer_search_modifier")
     pmod = settings.get("project_search_modifier")
     if query and query[0] in (pmod, bmod):
         return query[0], query[1:]
     return u"", query
コード例 #4
0
ファイル: generator.py プロジェクト: vim-scripts/surfer.vim
 def _files(self, modifier, curr_bufname):
     """To return all files for which tags need to be generated."""
     if curr_bufname and modifier == settings.get("buffer_search_modifier"):
         files = [curr_bufname]
     elif modifier == settings.get("project_search_modifier"):
         files = self.plug.project.get_files()
     else:
         files = v.buffers()
     exclude = settings.get("exclude")
     fn = lambda path: not any(fnmatch(path, patt) for patt in exclude)
     return filter(fn, files)
コード例 #5
0
ファイル: ui.py プロジェクト: vim-scripts/surfer.vim
 def _render_line(self, tag, query, dups_fnames):
     """To format a single line with the tag information."""
     visual_kind = u""
     if settings.get("visual_kinds", bool):
         visual_kind = settings.get("visual_kinds_shape")
     debug = settings.get("debug", int)
     line_format = settings.get("line_format")
     return u"{}{}{}{}{}".format(
         u" "*len(settings.get("current_line_indicator")),
         visual_kind, tag["name"],
         u"".join(self.formatter.fmt(fmtstr, tag, dups_fnames) for fmtstr in line_format),
         u" [{}]".format(tag["similarity"]) if debug else "")
コード例 #6
0
ファイル: generator.py プロジェクト: vim-scripts/surfer.vim
    def _filetype_data(self, filetype):
        """To return filetype-specific data."""
        if filetype == "*":
            prg = settings.get("ctags_prg")
            args = settings.get("ctags_args")
            kinds_map = {}
            exclude_kinds = settings.get("exclude_kinds")
        else:
            user_langs = settings.get("custom_languages")
            prg = user_langs[filetype].get("ctags_prg", "")
            args = user_langs[filetype].get("ctags_args", "")
            kinds_map = user_langs[filetype].get("kinds_map", {})
            exclude_kinds = user_langs[filetype].get("exclude_kinds", [])

        return prg, args, kinds_map, exclude_kinds
コード例 #7
0
ファイル: ui.py プロジェクト: vim-scripts/surfer.vim
    def _setup_buffer(self):
        """To set sane options for the search results buffer."""
        last_search = ""
        if v.eval("@/"):
            last_search = v.eval("@/").decode(v.encoding()).replace(u'"', u'\\"')
        self.exit_cmds.extend([
            u"let @/=\"{}\"".format(last_search),
            u"set laststatus={}".format(v.opt("ls")),
            u"set guicursor={}".format(v.opt("gcr")),
        ])

        commands = [
            "let @/ = ''",
            "call clearmatches()"
        ]

        options = [
            "buftype=nofile", "bufhidden=wipe", "nobuflisted", "noundofile",
            "nobackup", "noswapfile", "nowrap", "nonumber", "nolist",
            "textwidth=0", "colorcolumn=0", "laststatus=0", "norelativenumber",
            "nocursorcolumn", "nospell", "foldcolumn=0", "foldcolumn=0",
            "guicursor=a:hor5-Cursor-blinkwait100",
        ]

        if settings.get("cursorline", bool):
            options.append("cursorline")
        else:
            options.append("nocursorline")

        for opt in options:
            v.exe("try|setl {}|catch|endtry".format(opt))

        for cmd in commands:
            v.exe(cmd)
コード例 #8
0
ファイル: ui.py プロジェクト: vim-scripts/surfer.vim
    def _render_curr_line(self, cursor_pos):
        """To add an indicator in front of the current line."""
        if cursor_pos < 0:
            cursor_pos = len(v.buffer()) - 1

        line = v.getline(cursor_pos)
        indicator = settings.get("current_line_indicator")
        v.setline(cursor_pos, indicator + line[len(indicator):])

        return cursor_pos
コード例 #9
0
ファイル: ui.py プロジェクト: vim-scripts/surfer.vim
    def setup_colors(self):
        """To setup Surfer highlight groups."""
        postfix = "" if v.opt("bg") == "light" else "_darkbg"
        colors = {
            "SurferShade": settings.get("shade_color{}".format(postfix)),
            "SurferMatches": settings.get("matches_color{}".format(postfix)),
            "SurferPrompt": settings.get("prompt_color{}".format(postfix)),
            "SurferError": "WarningMsg"
        }
        for group, color in colors.items():
            if color:
                link = "" if "=" in color else "link"
                v.exe(u"hi {} {} {}".format(link, group, color))

        colors = settings.get("visual_kinds_colors{}".format(postfix))
        for kind, color in colors.items():
            if color:
                link = "" if "=" in color else "link"
                v.exe(u"hi {} SurferVisualKind_{} {}".format(link, kind, color))
コード例 #10
0
ファイル: ui.py プロジェクト: vim-scripts/surfer.vim
    def _update(self):
        """To update search results."""
        tags = []
        error = ""
        if self.perform_new_search:
            try:
                max_results = settings.get('max_results', int)
                tags = self.plug.finder.find_tags(
                    self.query, max_results, self.user_buf.name)
                self.search_results_cache = tags
            except ex.SurferException as e:
                error = e.message
        else:
            tags = self.search_results_cache

        self.mapper, self.cursor_pos = self.renderer.render(
                self.winnr, self.cursor_pos, self.query, tags,
                msg=error, iserror=bool(error))
コード例 #11
0
ファイル: generator.py プロジェクト: vim-scripts/surfer.vim
    def _group_files_by_filetype(self, files):
        """To group files by filetype.

        The filetype "*" groups all files that will be parsed with
        `surfer_ctags_prg`.
        """
        user_langs = settings.get("custom_languages")
        extensions_map = {}
        for filetype, values in user_langs.items():
            for extension in values.get("extensions", []):
                extensions_map[extension] = filetype

        groups = defaultdict(list)
        for f in files:
            extension = splitext(f)[1]
            groups[extensions_map.get(extension, "*")].append(f)

        return groups
コード例 #12
0
ファイル: ui.py プロジェクト: vim-scripts/surfer.vim
    def render(self, target_win, cursor_pos, query, tags, msg="", iserror=False):
        """To render all search results."""
        v.exe('syntax clear')
        v.focus_win(target_win)
        mapper = {}

        if not tags and not msg:
            msg = settings.get("no_results_msg")

        if msg:

            v.setbuffer(msg)
            v.setwinh(len(msg.split("\n")))
            (len(msg.split("\n")))
            cursor_pos = 0
            if iserror:
                self._highlight_err()

        else:

            # Find duplicates file names
            dups = {}
            for _, g in groupby(tags, key=lambda t: os.path.basename(t["file"])):
                # s is a set of unique paths but with the same basename
                s = set(t["file"] for t in g)
                if len(s) > 1:
                    dups.update((file, True) for file in s)

            tags = tags[::-1]
            mapper = dict(enumerate(t for t in tags))
            v.setbuffer([self._render_line(t, query, dups) for t in tags])
            cursor_pos = self._render_curr_line(cursor_pos)
            self._highlight_tags(tags, cursor_pos)
            v.setwinh(len(tags))

        v.cursor((cursor_pos + 1, 0))
        v.exe("normal! 0")

        return mapper, cursor_pos
コード例 #13
0
ファイル: finder.py プロジェクト: vim-scripts/surfer.vim
    def _find(self, query, tags, max_results):
        """To find all matching tags for the given `query`."""
        matches = []
        smart_case = settings.get("smart_case", int)

        for tag in tags:
            similarity, positions = match(query, tag["name"], smart_case)
            if positions:
                matches.append({
                    "match_positions": positions,
                    "similarity": similarity,
                    "name": tag["name"],
                    "file": tag["file"],
                    "cmd": tag["cmd"],
                    "exts": tag["exts"]
                })

        l = len(matches)
        if max_results < 0 or max_results > l:
            max_results = l

        return sorted(matches, key=itemgetter("similarity"))[:max_results]
コード例 #14
0
ファイル: ui.py プロジェクト: vim-scripts/surfer.vim
    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()
コード例 #15
0
ファイル: project.py プロジェクト: vim-scripts/surfer.vim
 def get_root(self):
     """To return the current project root."""
     if not self.root_cache:
         self.root_cache = self._find_root(v.cwd(), settings.get("root_markers"))
     return self.root_cache