""" Define interfaces. """ from __future__ import print_function import vim import json import time import os.path from .utils import PY2 class VimPymodeEnviroment(object): """ Vim User interface. """ prefix = '[Pymode]' def __init__(self): self.current = vim.current self.options = dict(encoding=vim.eval('&enc')) self.options['debug'] = self.var('g:pymode_debug', True) @property def curdir(self): """ Return current working directory. """ return self.var('getcwd()') @property def curbuf(self): """ Return current buffer. """ return self.current.buffer @property def cursor(self): """ Return current window position. :return tuple: (row, col) """ return self.current.window.cursor @property def source(self): """ Return source of current buffer. """ return "\n".join(self.lines) @property def lines(self): """ Iterate by lines in current file. :return list: """ if not PY2: return self.curbuf return [l.decode(self.options.get('encoding')) for l in self.curbuf] def var(self, name, to_bool=False): """ Get vim variable. :return vimobj: """ value = vim.eval(name) if to_bool: try: value = bool(int(value)) except ValueError: value = value return value def message(self, msg, history=False): """ Show message to user. """ if history: return vim.command('echom "%s"' % str(msg)) return vim.command('call pymode#wide_message("%s")' % str(msg)) def user_input(self, msg, default=''): """ Return user input or default. :return str: """ msg = '%s %s ' % (self.prefix, msg) if default != '': msg += '[%s] ' % default try: vim.command('echohl Debug') input_str = vim.eval('input("%s> ")' % msg) vim.command('echohl none') except KeyboardInterrupt: input_str = '' return input_str or default def user_confirm(self, msg, yes=False): """ Get user confirmation. :return bool: """ default = 'yes' if yes else 'no' action = self.user_input(msg, default) return action and 'yes'.startswith(action) def user_input_choices(self, msg, *options): """ Get one of many options. :return str: A choosen option """ choices = ['%s %s' % (self.prefix, msg)] choices += [ "%s. %s" % (num, opt) for num, opt in enumerate(options, 1)] try: input_str = int( vim.eval('inputlist(%s)' % self.prepare_value(choices))) except (KeyboardInterrupt, ValueError): input_str = 0 if not input_str: self.message('Cancelled!') return False try: return options[input_str - 1] except (IndexError, ValueError): self.error('Invalid option: %s' % input_str) return self.user_input_choices(msg, *options) def error(self, msg): """ Show error to user. """ vim.command('call pymode#error("%s")' % str(msg)) def debug(self, msg, *args): """ Print debug information. """ if self.options.get('debug'): print("%s %s [%s]" % ( int(time.time()), msg, ', '.join([str(a) for a in args]))) def stop(self, value=None): """ Break Vim function. """ cmd = 'return' if value: cmd += ' ' + self.prepare_value(value) vim.command(cmd) def catch_exceptions(self, func): """ Decorator. Make execution more silence. :return func: """ def _wrapper(*args, **kwargs): try: return func(*args, **kwargs) except (Exception, vim.error) as e: # noqa if self.options.get('debug'): raise self.error(e) return None return _wrapper def run(self, name, *args): """ Run vim function. """ vim.command('call %s(%s)' % (name, ", ".join([ self.prepare_value(a) for a in args ]))) def let(self, name, value): """ Set variable. """ cmd = 'let %s = %s' % (name, self.prepare_value(value)) self.debug(cmd) vim.command(cmd) def prepare_value(self, value): """ Decode bstr to vim encoding. :return unicode string: """ value = json.dumps(value) if PY2: value = value.decode('utf-8').encode(self.options.get('encoding')) return value def get_offset_params(self, cursor=None, base=""): """ Calculate current offset. :return tuple: (source, offset) """ row, col = cursor or env.cursor source = "" offset = 0 for i, line in enumerate(self.lines, 1): if i == row: source += line[:col] + base offset = len(source) source += line[col:] else: source += line source += '\n' env.debug('Get offset', base or None, row, col, offset) return source, offset def goto_line(self, line): """ Go to line. """ vim.command('normal %sggzz' % line) def goto_file(self, path, cmd='e', force=False): """ Function description. """ if force or os.path.abspath(path) != self.curbuf.name: self.debug('read', path) vim.command("%s %s" % (cmd, path)) def goto_buffer(self, bufnr): """ Open buffer. """ if str(bufnr) != '-1': vim.command('buffer %s' % bufnr) env = VimPymodeEnviroment()