Sublime Forum

Code cleanup help request

#1

I’ve created a basic plugin for a specific use and was hoping someone could lend an expert eye to comment or help clean up my noob python code?

The plugin’s use is to generate a completions file on a per project basis for Drupal PHP projects. It scans up from the current file location on save and looks for the *.sublime-project file in which case it recursively walks through the project looking for php files which it uses to create a Drupal.sublime-projectcompletions file in the project’s root directory (alongside the sublime-project file). The plugin then uses this to populate the autocomplete suggestions through the API.

In basic testing this seems to be working ok but I’d like to know if there is a more efficient way of doing this? Can I store the completions file in memory to speed things up? Maybe call it from disk only when the file has changed? Should I be using shelve to store the data, or mmap to map it to memory?

Note that I’ve never programmed in Python before (its very nice!) so please forgive my sloppy code. Any advice or direction is greatly appreciated.

The plugin code looks like this:

[code]import os, glob, fnmatch, re, threading, sublime, sublime_plugin

class ProjectCompletionsScan(threading.Thread):

def __init__(self, rootPath, timeout):
    threading.Thread.__init__(self)
    self.rootPath = rootPath
    self.timeout = timeout
    self.result = None

def run(self):
    try:
        patterns = '.inc', '.php', '.module']
        search = re.compile(r'^function\s(.+?)\((?:(.+?))?\)\s{$', re.MULTILINE)
        compPath = os.path.dirname(self.rootPath) + '/Drupal.sublime-projectcompletions'
        cfp = open(compPath, 'w')
        cfp.close()
        cfp = open(compPath, 'a')

        for root, dirs, files in os.walk(os.path.dirname(self.rootPath)):
            for p in patterns:
                for f in files:
                    if f.endswith(p):
                        # Open the file.
                        fp = open(os.path.join(root, f), 'r')
                        content = fp.read()
                        # Retrieve functions from file.
                        funcs = search.findall(content)
                        if funcs:
                            # Write the functions to file
                            for row in funcs:
                                args = ''
                                arglist = row[1].replace(', ', ',').split(',')
                                i = 0
                                if arglist:
                                    for i, val in enumerate(arglist):
                                        arglist* = '${' + str(i) + ':' + arglist*.replace('$', '') + '}'
                                line = row[0] + "\t" + row[0] + "(" + ', '.join(arglist) + ")"
                                # Append to file
                                cfp.write(line + "\n")
                        fp.close()
        cfp.close()
        return
    except OSError, e:
        sublime.error_message("An unknown issue occured.")

class ProjectCompletions(sublime_plugin.EventListener):

def find_file(self, start_at, look_for):
    start_at = os.path.abspath(start_at)
    if not os.path.isdir(start_at):
        start_at = os.path.dirname(start_at)
    while True:
        for filename in os.listdir(start_at):
            if fnmatch.fnmatch(filename, look_for):
                return os.path.join(start_at, filename) 
        continue_at = os.path.abspath(os.path.join(start_at, '..'))
        if continue_at == start_at:
            return None
        start_at = continue_at

def on_post_save(self, view):
    path = view.file_name()
    rootPath = None

    if path:
        # Try to find the myproject.sublime-project file
        for filename in '*.sublime-project']:
            rootPath = self.find_file(path, filename)
    if rootPath:
        threads = ]
        thread = ProjectCompletionsScan(rootPath, 5)
        threads.append(thread)
        thread.start()

def on_query_completions(self, view, prefix, locations):
    path = view.file_name()
    completions_location = None
    if path:
        # Try to find the Drupal.sublime-completions file
        for filename in '*.sublime-projectcompletions']:
            completions_location = self.find_file(path, filename)
    if completions_location:
        fp = open(completions_location, 'r')

        t = ()
        data = ]
        line = fp.readline()

        while len(line) != 0:
           e1, e2 = line.split("\t")
           t = e1, e2.rstrip()
           data.append(t)
           line = fp.readline()
           
        fp.close()
        return data
    else:
        return None[/code]**
0 Likes

#2

try: .... except OSError, e: sublime.error_message("An unknown issue occured.")
Is sublime crushed if error? I usually don`t change stack trace and current error to uninformative string.

I use with (effbot.org/zone/python-with-statement.htm) to open files

String formating via % or string.format

#arglist* = '${' + str(i) + ':' + arglist*.replace('$', '') + '}' arglist* = '${%s':%s'}' % (i, arglist*.replace('$', ''))

I prefer to create list of strings and then:

with open('file', w) as f: f.write('\n'.join(list_of_strings))

funcs = search.findall(content) if funcs: # Write the functions to file for row in funcs:funcs is all ways list. If it is empty iteration will do nothing. Remove condition and save one indent level.****

0 Likes

#3

Thank you Cjkjvfnby! Really appreciate the tips.

0 Likes