Source

vimpire / vimpire.py

Full commit
#!/usr/bin/env python3

import os
import re

from os.path import exists, expanduser, join, splitext, isdir
from subprocess import check_call
from urllib.request import urlretrieve, urlopen
from zipfile import ZipFile

HOME = expanduser('~')

VIMRC = join(HOME, '.vimrc')
VIMRUNTIME = join(HOME, '.vim')
AUTOLOAD = join(VIMRUNTIME, 'autoload')
BUNDLE_DIR = join(VIMRUNTIME, 'bundle')

PATHOGEN_DIR = join(AUTOLOAD, 'pathogen.vim')
PATHOGEN_URL = ('https://raw.github.com/tpope/vim-pathogen'
                '/HEAD/autoload/pathogen.vim')

PLUGIN_RE = re.compile(r'" plugin: (\S+) (ht|git|svn|vim|zip) (\S+)')


def sh(cmd, *args, **kwargs):
    if isinstance(cmd, str):
        print('Executing: %s' % cmd)
    else:
        print('Executing: %s' % ' '.join(cmd))
    check_call(cmd, *args, **kwargs)


def check_env():
    if not os.path.exists(PATHOGEN_DIR):
        if not os.path.exists(AUTOLOAD):
            os.makedirs(AUTOLOAD)
        print('Installing pathogen.vim...')
        urlretrieve(PATHOGEN_URL, PATHOGEN_DIR)

    if not os.path.exists(BUNDLE_DIR):
        os.makedirs(BUNDLE_DIR)


class Plugin(object):
    def __init__(self, name, handler, path):
        self.name = name
        self.handler = handler
        self.path = path
        self.run = []

    def handle_hg(self):
        sh(['hg', 'clone', self.path, self.name])

    def handle_git(self):
        sh(['git', 'clone', self.path, self.name])

    def handle_vim(self):
        with urlopen(self.path) as f:
            content = f.read().decode('ISO-8859-1')
        m = re.search(r'download_script\.php\?src_id=\d+', content)
        if m is None:
            raise Exception("Can't find vim script to download.")
        filename, headers = urlretrieve('http://www.vim.org/scripts/' + m.group(0))
        ext = splitext(headers.get_filename())[1].replace('.', '')
        with ZipFile(filename) as f:
            f.extractall(self.name)

    def get_handler(self):
        return getattr(self, 'handle_%s' % self.handler)

    def install(self):
        if exists(join(BUNDLE_DIR, self.name)):
            print('plugin: %s (alreading installed)' % self.name)
        else:
            print('plugin: %s installing...' % self.name)
            handler = self.get_handler()
            handler()

            if self.run:
                cwd = os.getcwd()
                os.chdir(self.name)
                for cmd in self.run:
                    sh(cmd, shell=True)
                os.chdir(cwd)

            print('  ... installed.\n')


def get_plugins():
    plugins = []
    pathogen_not_found = True
    with open(VIMRC) as f:
        for line in f:
            if line.startswith('" plugin: '):
                m = PLUGIN_RE.match(line)
                if m:
                    name, handler, path = m.groups()
                    plugin = Plugin(name, handler, path)
                    plugins.append(plugin)

            elif line.startswith('" run: ') and plugin is not None:
                cmd = line[len('" run: '):]
                plugin.run.append(cmd)

            elif line.startswith('call pathogen#infect'):
                pathogen_not_found = False
                plugin = None

            else:
                plugin = None

    if pathogen_not_found:
        raise Exception('It seems, that pathogen is not configured.\n'
                        'Make sure, that you have\n'
                        '\n'
                        '    call pathogen#infect()\n'
                        '\n'
                        'line at the top of your ~/.vimrc file.\n')

    return plugins


def main():
    plugins = get_plugins()
    check_env()
    os.chdir(BUNDLE_DIR)

    update_help_tags = False
    installed_plugins = []

    # Install/update plugins
    for plugin in plugins:
        installed_plugins.append(plugin.name)
        if plugin.install():
            update_help_tags = True

    # Uninstall removed plugins
    for name in os.listdir(BUNDLE_DIR):
        path = join(BUNDLE_DIR, name)
        if isdir(path) and name not in installed_plugins:
            print('plugin: %s uninstalling...' % name)
            sh(['rm', '-rf', path])
            print('  ... uninstalled.\n')
            update_help_tags = True

    # Update help tags
    if update_help_tags:
        sh(['vim', '-c', 'Helptags', '-c', 'q'])


if __name__ == '__main__':
    main()