"""Define interfaces."""
import json
import os.path
import time
import vim # noqa
class VimPymodeEnviroment(object):
"""Vim User interface."""
prefix = '[Pymode]'
def __init__(self):
"""Init VIM environment."""
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:
"""
return self.curbuf
@staticmethod
def var(name, to_bool=False, silence=False, default=None):
"""Get vim variable.
:return vimobj:
"""
try:
value = vim.eval(name)
except vim.error:
if silence:
return default
raise
if to_bool:
try:
value = bool(int(value))
except ValueError:
value = value
return value
@staticmethod
def message(msg, history=False):
"""Show message to user.
:return: :None
"""
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:
"""
prompt = []
prompt.append(str(self.prefix.strip()))
prompt.append(str(msg).strip())
if default != '':
prompt.append('[%s]' % default)
prompt.append('> ')
prompt = ' '.join([s for s in prompt if s])
vim.command('echohl Debug')
try:
input_str = vim.eval('input(%r)' % (prompt,))
except KeyboardInterrupt:
input_str = ''
vim.command('echohl none')
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)
@staticmethod
def error(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 is not None:
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, dumps=True):
"""Decode bstr to vim encoding.
:return unicode string:
"""
if dumps:
value = json.dumps(value)
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
@staticmethod
def goto_line(line):
"""Go to line."""
vim.command('normal %sggzz' % line)
def goto_file(self, path, cmd='e', force=False):
"""Open file by path."""
if force or os.path.abspath(path) != self.curbuf.name:
self.debug('read', path)
if ' ' in path and os.name == 'posix':
path = path.replace(' ', '\\ ')
vim.command("%s %s" % (cmd, path))
@staticmethod
def goto_buffer(bufnr):
"""Open buffer."""
if str(bufnr) != '-1':
vim.command('buffer %s' % bufnr)
def select_line(self, start, end):
vim.command('normal %sggV%sgg' % (start, end))
env = VimPymodeEnviroment()