Exemplo n.º 1
0
class PythonChecker:
    options = LinePicker()
    path = 'pyflakes'

    def __init__(self, area):
        self.area = area
        area.install('snakerr', ('PYTHON', '<Control-h>', self.check_module),
                     ('PYTHON', '<Key-h>', self.display_errors),
                     ('PYTHON', '<Key-H>', self.check_all))

    @classmethod
    def c_path(cls, path):
        printd('Snakerr - Setting Pyflakes path = ', cls.path)
        cls.path = path

    def display_errors(self, event=None):
        root.status.set_msg('Pyflakes previous errors!')
        self.options.display()
        self.area.chmode('NORMAL')

    def check_all(self, event=None):
        path = get_project_root(self.area.filename)
        child = Popen([self.path, path],
                      stdout=PIPE,
                      stderr=STDOUT,
                      encoding=self.area.charset)
        output = child.communicate()[0]

        # Pyflakes omit the column attribute when there are
        # syntax errors thus the (.+?) in the beggining of the
        # regex is necessary.
        regex = '(.+?):([0-9]+):?[0-9]*:(.+)'
        ranges = findall(regex, output)

        sys.stdout.write('Pyflakes found global errors:\n%s\n' % output)
        self.area.chmode('NORMAL')
        root.status.set_msg('Pyflakes errors: %s' % len(ranges))

        if ranges:
            self.options(ranges)

    def check_module(self, event=None):
        path = get_project_root(self.area.filename)
        child = Popen([self.path, path],
                      stdout=PIPE,
                      stderr=STDOUT,
                      encoding=self.area.charset)
        output = child.communicate()[0]

        regex = '(%s):([0-9]+):?[0-9]*:(.+)' % relpath(self.area.filename)
        ranges = findall(regex, output)
        sys.stdout.write('Errors:\n%s\n' % output)
        self.area.chmode('NORMAL')
        root.status.set_msg('Pyflakes errors: %s' % len(ranges))

        if ranges:
            self.options(ranges)
Exemplo n.º 2
0
class Fstmt:
    options = LinePicker()
    path = 'ag'

    def __init__(self, area):
        self.area = area

        area.install(
            'fstmt',
            ('NORMAL', '<Key-z>', lambda event: self.options.display()),
            ('NORMAL', '<Control-z>', lambda event: self.picker('-i')),
            ('NORMAL', '<Key-Z>', lambda event: self.picker('-s')))

    @classmethod
    def c_path(cls, path='ag'):
        cls.path = path
        printd('Fstmt - Setting ag path = ', path)

    def catch_pattern(self):
        pattern = self.area.join_ranges('sel')
        pattern = pattern if pattern else self.area.get(
            *self.area.get_word_range())

        pattern = escape(pattern)
        return pattern

    def make_cmd(self, pattern, dir, *args):
        cmd = [
            Fstmt.path, '--nocolor', '--nogroup', '--vimgrep', '--noheading'
        ]
        cmd.extend(args)
        cmd.extend([pattern, dir])
        return cmd

    def run_cmd(self, pattern, *args):
        dir = self.area.project
        dir = dir if dir else AreaVi.HOME
        dir = dir if dir else self.area.filename
        child = Popen(self.make_cmd(pattern, dir, *args),
                      stdout=PIPE,
                      stderr=STDOUT,
                      encoding=self.area.charset)
        regex = '(.+):([0-9]+):[0-9]+:(.+)'
        ranges = findall(regex, child.communicate()[0])

        if ranges:
            self.options(ranges)
        else:
            root.status.set_msg('No pattern found!')

    def picker(self, *args):
        pattern = self.catch_pattern()
        if not pattern:
            root.status.set_msg('No pattern set!')
        else:
            self.run_cmd(pattern, *args)
Exemplo n.º 3
0
    def __init__(self, area):
        self.area = area
        self.err_picker = LinePicker()
        completions = lambda event: YcmdWindow(event.widget, self.server)
        wrapper = lambda event: area.after(1000, self.on_ready)

        # Used to keep the server alive.
        def keep():
            self.server.is_alive()
            area.after(250000, keep)

        area.after(250000, keep)

        # area.master.bind('<Destroy>', self.on_unload)
        area.install('ycmd', ('INSERT', '<Control-Key-period>', completions),
                     (-1, '<<LoadData>>', wrapper),
                     (-1, '<<SaveData>>', wrapper),
                     ('NORMAL', '<Control-greater>',
                      lambda event: self.err_picker.display()))
Exemplo n.º 4
0
class WordSearch:
    options = LinePicker()

    def __init__(self, area):
        self.area = area

        area.install('word-search', ('NORMAL', '<Key-M>', self.match),
                     ('NORMAL', '<Key-V>', self.display_matches))

    def display_matches(self, event):
        self.options.display()
        root.status.set_msg('Word Search matches!')

    def match(self, event):
        """

        """

        ask = Ask()
        data = ask.data.split(' ')
        find = lambda ind: self.area.find(
            escape(ind).lower(), '1.0', step='+1l linestart')

        seq = self.match_regions(find, data)
        matches = ((self.area.filename, line,
                    self.area.get_line('%s.0' % line)) for count, line in seq)

        if not seq:
            root.status.set_msg('No pattern found!')
        else:
            self.options(matches)

    def match_regions(self, find, data):
        regions = []

        for ind in data:
            for ch, index0, index1 in find(ind):
                regions.append((int(index0.split('.')[0]), ch))

        regions.sort()
        seq = groupby(regions, lambda ind: ind[0])
        matches = self.sort_matches(seq, data)
        return matches

    def sort_matches(self, seq, data):
        matches = []

        for line, group in seq:
            count = 0
            for line, word in group:
                if word in data:
                    count = count + 1
            matches.append((count, line))
        matches.sort(reverse=True)
        return matches
Exemplo n.º 5
0
class StaticChecker(object):
    options = LinePicker()
    path = 'mypy'

    def __init__(self, area):
        self.area = area
        area.install(
            'mypy', ('PYTHON', '<Control-t>', self.check_module),
            ('PYTHON', '<Key-t>', lambda event: self.options.display()),
            ('PYTHON', '<Key-T>', self.check_all))

    @classmethod
    def c_path(cls, path):
        printd('Snakerr - Setting Mypy path = ', cls.path)
        cls.path = path

    def check_all(self, event=None):
        path = get_project_root(self.area.filename)
        child = Popen([self.path, path],
                      stdout=PIPE,
                      stderr=STDOUT,
                      encoding=self.area.charset)
        output = child.communicate()[0]

        regex = '(.+?):([0-9]+):(.+)'
        ranges = findall(regex, output)

        sys.stdout.write('Mypy errors: \n%s\n' % output)
        self.area.chmode('NORMAL')

        root.status.set_msg('Mypy errors: %s' % len(ranges))
        if ranges:
            self.options(ranges)

    def check_module(self, event=None):
        path = get_project_root(self.area.filename)
        child = Popen([self.path, path],
                      stdout=PIPE,
                      stderr=STDOUT,
                      encoding=self.area.charset)
        output = child.communicate()[0]

        regex = '(%s):([0-9]+):(.+)' % relpath(self.area.filename)
        ranges = findall(regex, output)
        sys.stdout.write('Mypy errors: \n%s\n' % output)
        self.area.chmode('NORMAL')

        root.status.set_msg('Mypy errors: %s' % len(ranges))
        if ranges:
            self.options(ranges)
Exemplo n.º 6
0
class PythonAnalysis:
    options = LinePicker()
    path = 'vulture'

    def __init__(self, area):
        self.area = area
        area.install(
            'deadcode', ('PYTHON', '<Control-o>', self.check_module),
            ('PYTHON', '<Key-o>', lambda event: self.options.display()),
            ('PYTHON', '<Key-O>', self.check_all))

    @classmethod
    def c_path(cls, path):
        printd('Deadcode - Setting Vulture path = ', cls.path)
        cls.path = path

    def check_all(self, event=None):
        path = get_project_root(self.area.filename)
        child = Popen([self.path, path],
                      stdout=PIPE,
                      stderr=STDOUT,
                      encoding=self.area.charset)
        output = child.communicate()[0]

        regex = '(.+):([0-9]+):?[0-9]*:(.+)'
        ranges = findall(regex, output)
        sys.stdout.write('Vulture found global errors:\n%s\n' % output)
        self.area.chmode('NORMAL')

        root.status.set_msg('Vulture errors: %s' % len(ranges))
        if ranges:
            self.options(ranges)

    def check_module(self, event=None):
        path = get_project_root(self.area.filename)
        child = Popen([self.path, path],
                      stdout=PIPE,
                      stderr=STDOUT,
                      encoding=self.area.charset)
        output = child.communicate()[0]

        regex = '(%s):([0-9]+):?[0-9]*:(.+)' % relpath(self.area.filename)
        ranges = findall(regex, output)

        sys.stdout.write('%s errors:\n%s\n' % (self.area.filename, output))
        self.area.chmode('NORMAL')

        root.status.set_msg('Vulture errors: %s' % len(ranges))
        if ranges:
            self.options(ranges)
Exemplo n.º 7
0
class YcmdCompletion:
    server = None

    def __init__(self, area):
        self.area = area
        self.err_picker = LinePicker()
        completions = lambda event: YcmdWindow(event.widget, self.server)
        wrapper = lambda event: area.after(1000, self.on_ready)

        # Used to keep the server alive.
        def keep():
            self.server.is_alive()
            area.after(250000, keep)

        area.after(250000, keep)

        # area.master.bind('<Destroy>', self.on_unload)
        area.install('ycmd', ('INSERT', '<Control-Key-period>', completions),
                     (-1, '<<LoadData>>', wrapper),
                     (-1, '<<SaveData>>', wrapper),
                     ('NORMAL', '<Control-greater>',
                      lambda event: self.err_picker.display()))

    def on_unload(self, event):
        """
        """
        data = {
            self.area.filename: {
                'filetypes': [FILETYPES[self.area.extension]],
                'contents': self.area.get('1.0', 'end')
            }
        }

        req = self.server.buffer_unload(1, 1, self.area.filename, data)
        printd('Ycmd - BufferUnload status', req.status_code)
        printd('Ycmd - BufferUnload JSON response', req.json())

    def on_ready(self):
        """
        This method sends the ReadyToParseEvent to ycmd whenever a file is
        opened or saved. It is necessary to start some 
        ycmd language completers.

        When there is a global .ycm_extra_conf.py in the home dir
        then it is loaded automatically otherwise a message is
        displayed to the user to load it using lycm.
        """

        data = {
            self.area.filename: {
                'filetypes': [FILETYPES[self.area.extension]],
                'contents': self.area.get('1.0', 'end')
            }
        }

        req = self.server.ready(1, 1, self.area.filename, data)
        rsp = req.json()

        if req.status_code == 500:
            self.on_exc(rsp)
        elif req.status_code == 200 and rsp:
            self.on_diagnostics(rsp)

    def on_diagnostics(self, rsp):
        """
        """

        ranges = [(ind['location']['filepath'], ind['location']['line_num'],
                   ind['text']) for ind in rsp]

        self.err_picker(ranges, display=False)
        root.status.set_msg('Ycmd found errors. Displaying diagnostics!')

    def on_exc(self, rsp):
        exc = rsp.get('exception')
        if exc and exc.get('TYPE') == 'UnknownExtraConf':
            self.is_gxconf(exc['extra_conf_file'])

    @classmethod
    def is_gxconf(cls, xconf):
        gxconf = expanduser('~')
        gxconf = join(gxconf, '.ycm_extra_conf.py')

        if xconf == gxconf:
            cls.server.load_conf(gxconf)
        else:
            root.status.set_msg((('Found %s!' ' lycm(path) to load.') % xconf))

    @classmethod
    def setup(cls, path, xconf=expanduser('~')):
        """ 
        Create the default_settings.json file in case it doesn't exist.
        The file is located in the home dir. It also starts ycmd server.

        It also creates a global ycm_extra_conf.py file in your home dir.
        This file is used for giving completion for c-family languages and
        specifying some specific settings.

        Check ycmd docs for details.
        """
        settings_file = join(expanduser('~'), '.default_settings.json')
        if not exists(settings_file):
            copyfile(join(dirname(__file__), 'default_settings.json'),
                     settings_file)

        xconf = join(xconf, '.ycm_extra_conf.py')
        if not exists(xconf):
            copyfile(join(dirname(__file__), 'ycm_extra_conf.py'), xconf)

        port = random.randint(1000, 9999)
        cls.server = YcmdServer(path, port, settings_file)
        ENV['lycm'] = cls.lycm
        ENV['dycm'] = cls.dycm

    @classmethod
    def dycm(cls):
        """
        """
        data = {
            Command.area.filename: {
                'filetypes': [FILETYPES[Command.area.extension]],
                'contents': Command.area.get('1.0', 'end')
            }
        }

        cls.server.debug_info(1, 1, Command.area.filename, data)

    @classmethod
    def lycm(cls, path=None):
        """
        """

        home = expanduser('~')
        path = path if path else join(home, '.ycm_extra_conf.py')

        cls.server.load_conf(path)
        root.status.set_msg('Loaded %s' % path)
Exemplo n.º 8
0
class FSniffer(object):
    options = LinePicker()
    wide    = True

    def __init__(self, area):
        self.area = area
        area.install('fsniffer', 
        ('NORMAL', '<Alt-t>', lambda e: self.options.display()), 
        ('NORMAL', '<Alt-y>', 
        lambda event: Get(events={'<Return>' : self.find,
        '<Control-w>':self.set_wide, '<<Idle>>': self.update_pattern,
        '<Escape>': lambda wid: True})))
    
    @classmethod
    def set_wide(cls, event):
        FSniffer.wide = False if FSniffer.wide else True
        root.status.set_msg('Set wide search: %s' % FSniffer.wide)

    def update_pattern(self, wid):
        pattern = build_regex(wid.get(), '.*')
        root.status.set_msg('File pattern: %s' % pattern)

    def make_cmd(self, pattern):
        # When FSniffer.wide is False it searches in the current 
        # Areavi instance project.
        cmd   = ['locate', '--limit', '200']
        regex = build_regex(pattern, '.*')

        if self.wide or not self.area.project:
            cmd.extend(['--regexp', regex])
        else:
            cmd.extend(['--regexp', '%s.*%s' % (
                self.area.project, regex)])

        # Used to filter only files because locate doesn't support 
        # searching only for files.
        cmd = '%s | %s' % (' '.join(cmd), '''while read -r file; do
          [ -d "$file" ] || printf '%s\n' "$file"; done''')
        return cmd

    def run_cmd(self, pattern):
        cmd   = self.make_cmd(pattern)
        child = Popen(cmd, stdout=PIPE, stderr=STDOUT, 
        encoding=self.area.charset, shell=True)

        output = child.communicate()[0]
        return output

    def find(self, wid):
        pattern = wid.get()
        output = self.run_cmd(pattern)
        if output:
            self.fmt_output(output)
        else:
            root.status.set_msg('No results:%s!' % pattern)
        return True

    def fmt_output(self, output):
        output = output.strip('\n').rstrip('\n')
        ranges = output.split('\n')
        ranges = [ind for ind in ranges
            if ranges]

        ranges = [(ind, '0', basename(ind)) for ind in ranges]

        self.options(ranges)
Exemplo n.º 9
0
 def display(self, ranges):
     root.status.set_msg('Errors were found!')
     options = LinePicker()
     options(ranges)
Exemplo n.º 10
0
class Sniper:
    options = LinePicker()
    # Path to ag program.
    path = 'ag'

    # Dirs where ag will search when in 
    # wide mode.
    dirs = ()

    # Sniper search options.
    file_regex = ''
    ignore     = ''
    multiline  = True

    # Either lax(1), literal(0), regex(2).
    type   = 1
    nocase = False
    wide   = True

    def  __init__(self, area):
        self.area = area

        area.install('sniper', 
        ('NORMAL', '<Key-b>', lambda event: self.options.display()),
        ('NORMAL', '<Key-B>', lambda event: Get(events = {
        '<Return>':self.find, 
        '<Control-i>':self.set_ignore_regex, 
        '<Control-x>':self.set_type_lax, 
        '<Control-r>':self.set_type_regex, 
        '<Control-l>':self.set_type_literal, 
        '<Control-g>':self.set_file_regex, 
        '<Control-s>':self.set_nocase, 
        '<Control-w>':self.set_wide, 
        '<Control-m>':self.set_multiline, 
        '<Escape>':  lambda wid: True})))

        if not self.dirs:
            printd('Sniper - Sniper.dirs is not set.')

    @classmethod
    def c_path(cls, path='ag'):
        """
        Set the ag path. If ag is known to your environment then
        there is no need to set it.
        """
        pass
        cls.path = path
        printd('Sniper - Setting ag path = ', path)

    @classmethod
    def c_dirs(cls, *dirs):
        """
        Folders where ag will be searching for data.
        """
        cls.dirs = dirs
        printd('Sniper - Setting dirs =', *dirs)

    def set_wide(self, wid):
        Sniper.wide = False if Sniper.wide else True
        root.status.set_msg('Set wide search: %s' % Sniper.wide)

    def set_multiline(self, wid):
        Sniper.multiline = False if Sniper.multiline else True
        root.status.set_msg('Set multiline search: %s' % Sniper.multiline)

    def set_nocase(self, wid):
        Sniper.nocase = False if Sniper.nocase else True
        root.status.set_msg('Set nocase search: %s' % Sniper.nocase)

    def set_ignore_regex(self, wid):
        Sniper.ignore = wid.get()
        root.status.set_msg('Set ignore file regex:%s' % Sniper.ignore)
        wid.delete(0, 'end')

    def set_type_literal(self, wid):
        root.status.set_msg('Set search type: LITERAL')
        Sniper.type = 0

    def set_type_lax(self, wid):
        root.status.set_msg('Set search type: LAX')
        Sniper.type = 1

    def set_type_regex(self, wid):
        root.status.set_msg('Set search type: REGEX')
        Sniper.type = 2

    def set_file_regex(self, wid):
        self.file_regex = wid.get()
        root.status.set_msg('Set file regex:%s' % self.file_regex)
        wid.delete(0, 'end')

    def make_cmd(self, pattern):
        cmd = [self.path, '--nocolor', '--nogroup',
        '--vimgrep', '--noheading']

        if self.ignore:
            cmd.extend(['--ignore', self.ignore])
        if self.file_regex:
            cmd.extend(['-G', self.file_regex])
        if self.nocase:
            cmd.append('-s')
        if not self.multiline:
            cmd.append('--nomultiline')
        else:
            cmd.append('--multiline')

        if self.type == 1:
            cmd.append(build_regex(pattern))
        elif self.type == 2:
            cmd.append(pattern)
        else:
            cmd.extend(['-Q', pattern])

        if not Sniper.wide:
            cmd.extend([self.area.project, AreaVi.HOME])
        else:
            cmd.extend(Sniper.dirs)
        return cmd

    def run_cmd(self, pattern):
        cmd = self.make_cmd(pattern)
        child = Popen(cmd, stdout=PIPE, stderr=STDOUT, 
        encoding=self.area.charset)
        return child.communicate()[0]

    @error
    def find(self, wid):
        """
        """

        pattern = wid.get()
        root.status.set_msg('Set pattern:%s!' % pattern)

        output = self.run_cmd(pattern)
        regex  = '(.+):([0-9]+):[0-9]+:(.+)' 
        ranges = findall(regex, output)

        if ranges:
            self.options(ranges)
        else:
            root.status.set_msg('No results:%s!' % pattern)
        return True