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)
def _generate_tagfile(self): """To generate a new temporary tagfile and update the vim `tags` option.""" tagfile = tempfile.NamedTemporaryFile(delete=False) v.exe(u"set tags+={}".format(tagfile.name)) self.old_tagfiles.append(tagfile.name) return tagfile
def _open_window(self): """To open the Surfer window if not already visible.""" if not self.winnr: self.exit_cmds.append(u"set ei={}".format(v.opt("ei"))) v.exe(u"set eventignore=all") v.exe(u'sil! keepa botright 1new {}'.format(self.name)) self._setup_buffer() self.winnr = v.bufwinnr(self.name)
def _remove_tagfiles(self): """To delete all previously created tagfiles.""" for tagfile in self.old_tagfiles: v.exe(u"set tags-={}".format(tagfile)) try: os.remove(tagfile) except OSError: pass
def _close(self): """To close the Surfer user interface.""" v.exe('q') for cmd in self.exit_cmds: v.exe(cmd) if self.user_buf.winnr: v.focus_win(self.user_buf.winnr) self._reset() v.redraw()
def _jump_to(self, tag, mode=""): """To jump to the tag on the current line.""" hidden = v.opt("hidden") autowriteall = v.opt("autowriteall") modified = v.call(u"getbufvar({},'&mod')".format(self.user_buf.nr)) bufname = self.user_buf.name self._close() count, tagfile = self._tag_count(tag) if (not hidden and not autowriteall) and modified and tagfile != bufname: v.echohl(u"write the buffer first. (:h hidden)", "WarningMsg") else: v.exe(u"sil! {}{}tag {}".format(count, mode, tag["name"])) v.exe("normal! zvzzg^")
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))
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
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()