Source

aurum / python / aurum / powerline.py

Full commit
from importlib import import_module
from collections import namedtuple
import aurum.rcdriverfuncs as rcdfuncs
import aurum.repeatedcmd as rc
import vim
from os.path import dirname, isdir, join, relpath

Funcs = namedtuple('Funcs', 'branch status')
dummy_func = lambda *args : None
dummy_funcs = Funcs(dummy_func, dummy_func)
vcss = {}

def generate_status_func(g_repo, status_func):
    def status(path, fname):
        try:
            status = status_func(path, files=(relpath(fname, path),), ignored=True)
        except:
            return None
        for k, v in status.iteritems():
            if v:
                return k
        return None
    return status

def generate_branch_func(g_repo, branch_func):
    def branch(path):
        return branch_func(g_repo(path))
    return branch

func_generators = {
    'status': generate_status_func,
    'branch': generate_branch_func,
}

def specialize(funcs, path):
    def status(fname):
        return funcs.status(path, fname)
    def branch():
        return funcs.branch(path)
    return Funcs(status=status, branch=branch)

def generate_directories(path):
    yield path
    while True:
        old_path = path
        path = dirname(path)
        if path == old_path:
            break
        yield path

def guess(path):
    for directory in generate_directories(path):
        for vcs, vcs_dir in (('git', '.git'),
                             ('mercurial', '.hg'),
                             ('bazaar', '.bzr'),
                             ('subversion', '.svn')):
            if isdir(join(directory, vcs_dir)):
                try:
                    if vcs not in vcss:
                        try:
                            module = import_module('aurum.au'+vcs)
                        except:
                            module = None

                        try:
                            status_func = func_generators['status'](module.g_repo, getattr(module, '_get_status'))
                        except AttributeError:
                            try:
                                status_func = getattr(rcdfuncs, vcs+'_status')
                            except AttributeError:
                                status_func = dummy_func

                        try:
                            branch_func = func_generators['branch'](module.g_repo,
                                                                    getattr(module, 'repo_props')['branch'])
                        except AttributeError, KeyError:
                            try:
                                branch_func = getattr(rcdfuncs, vcs+'_branch')
                            except AttributeError:
                                branch_func = dummy_func

                        vcss[vcs] = Funcs(status=status_func, branch=branch_func)
                    return specialize(vcss[vcs], directory)
                except:
                    pass
    return None

buffers = {}
started = False

def wipe_buffer(bufnr):
    if bufnr in buffers:
        for value in buffers[bufnr].itervalues():
            rc.remove(value)
        buffers.pop(bufnr)

def wipe_key(key):
    for bdict in buffers.itervalues():
        if key in bdict:
            rc.get(bdict[key], now=True)

def wipe_buffer_key(bufnr, key):
    if bufnr in buffers and key in buffers[bufnr]:
        rc.get(buffers[bufnr][key], now=True)

def setup_buffer(bufnr, func_name, *args):
    if not started:
        vim.eval('FraworLoad(@%aurum/powerline)')

    if bufnr not in buffers:
        vim.command('autocmd! AuRemovePowerlineRC BufWipeOut,BufFilePost <buffer='+str(bufnr)+'> '+
                ':python aurum.powerline.wipe_buffer('+str(bufnr)+')')
        bdict = {}
        buffers[bufnr] = bdict

        funcs = guess(vim.buffers[bufnr-1].name)

        bdict['funcs'] = funcs
    else:
        bdict = buffers[bufnr]
        funcs = bdict['funcs']

    if not funcs:
        return None

    if func_name not in bdict:
        bdict[func_name] = rc.new(float(vim.eval('<SNR>'+sid+'_Eval("s:_r.cache.getinterval(\''+func_name+'\')")')),
                                  getattr(funcs, func_name), *args)
        if func_name == 'status':
            vim.command('autocmd! AuRemovePowerlineRC BufWritePost <buffer='+str(bufnr)+'> '+
                    ':python aurum.powerline.wipe_buffer_key('+str(bufnr)+', '+repr(func_name)+')')

    return bdict[func_name]

def branch():
    return rc.get(setup_buffer(vim.current.buffer.number, 'branch'))

def file_vcs_status():
    if not vim.current.buffer.name or vim.eval('&buftype'):
        return None
    bsetup = setup_buffer(vim.current.buffer.number, 'status', vim.current.buffer.name)
    if bsetup is None:
        return None

    status = rc.get(bsetup)

    if not status or status == 'clean':
        return None

    statchar = status[0].upper()
    return {
            'contents': statchar,
            'highlight': ['file_vcs_status_'+statchar, 'file_vcs_status']
           }

# vim: ft=python ts=4 sw=4 sts=4 et tw=120