6. 5. 2013

Editor gedit a plugin GDP Format

Mým nejoblíbenějším editorem na programování je editor gVim, ale po instalaci nového Linuxu je potřeba ho vždycky složitě konfigurovat a tak mám tendenci zkoušet něco jiného, především gedit. To je jednoduchý textový editor, který lze pluginy rozšířit o různé zajímavé funkce. Jedním z takových zajímavých pluginů je GDP Format.


Tento plugin je potřeba doinstalovat a spolu s jinými se nalézá v balíčku gedit-developers-plugin.

Plugin GDP Format kontroluje formát zdrojových kódů, mimo jiné i pro můj oblíbený Python, a upozorňuje na různé vážné chyby (program se na nich zhroutí) i drobné formátovací nedostatky. To je vcelku užitečná věc, protože odhaluje problematická místa a pomáhá udržovat štábní kulturu zdrojových kódů. Drobný problém je, že to jaksi není konfigurovatelné, takže buď se podvolíte nastaveným pravidlům, jak má zdrojový kód vypadat a nebo máte problém, protože budete zavaleni fůrou zbytečných chybových hlášení, které sice můžete ignorovat, ale snadno v nich přehlédnete ty důležité.

Některá pravidla se mi přijímají snadno i když jsem je zatím nedodržoval. Např. že mezi funkcemi mají být volné alespoň dva řádky nebo že mezi textem a následujícím komentářem mají být alespoň dvě mezery. Některé ale přijmout nemohu, například že kolem operátoru má být právě jedna mezera. To totiž vede ke kódu, který se mi zdá být nepřehledný:
hrf = open('kdesi/cosi', 'r')
xmlData = minidom.parse(hrf)
root = xmlData.getRoot()
A proto radši preferuji tento styl, který mi přijde lepší a na který jsem zvyklý.
hrf     = open('kdesi/cosi', 'r')
xmlData = minidom.parse(hrf)
root    = xmlData.getRoot()
Jenže z tohoto důvodu se pak na mě vyhrnou desítky chybových hlášení a celý plugin pak postrádá smysl. Nechápu, proč k tomu nikdo nedodělal filtr na hlášení, které chce uživatel ignorovat. A tak jsem se rozhodl si ho dodělat sám.

Nejprve jsem si myslel, že si upravím ten plugin (je naprogramován v Pythonu), ale zkoumáním zdrojových kódů jsem zjistil, že to tak jednoduché nebude. A že ten plugin kontrolu provádí za pomoci systémového nástroje pocketlint, který je rovněž naprogramovaný v Pythonu. A je to tak vlastně lepší, protože taková úprava se projeví u všech programů, které ho používají ke kontrole zdrojových kódů.

Úprava je jednoduchá. Stačilo upravit medody __init__ a __call__ třídy Reporter v souboru /usr/lib/python2.7/dist-packages/pocketlint/formatcheck.py (platné pro Ubuntu 12.04, ale případný zájemce si určitě snadno dohledá správné umístění ve svém systému). Pro zájemce nabízím příslušnou čás kódu s úpravami. Mé změny začínají řádkem wraith ... ch.Ignores a končí řádkem wraith end.

Úprava spočívá v tom, že při inicializaci třídy Reporter se načte obsah souboru ~/.pocketlints_ignore v kterém jsou uvedeny texty chybových hlášení, které se mají ignorovat, každé chybové hlášení na jednom řádku. Stačí aby bylo uvedeno id chybového hlášení, ale je dobré tam ponechat i texty, aby bylo i v budoucnu zřejmé co je co. Příklad konfiguračního souboru rovněž připojuji.

class Reporter:
    """Common rules for checkers."""
    CONSOLE = object()
    FILE_LINES = object()
    COLLECTOR = object()

    def __init__(self, report_type, treeview=None):
        self.report_type = report_type
        self.file_lines_view = treeview
        if self.file_lines_view is not None:
            self.treestore = self.file_lines_view.get_model()
        self.piter = None
        self._last_file_name = None
        self.call_count = 0
        self.error_only = False
        self.messages = []
        # wraith 2013.05.06 ch.Ignores
        self.ignore_list = {}
        try:
            from os.path import expanduser
            home  = expanduser("~")
            fHand = open(home + '/.pocketlints_ignore.rc', 'r')
            fData = fHand.readlines()
            fHand.close()

            for row in fData:
                row = row.strip()
                if  row[0] == '#':
                    continue  # coment line
                idErr = row.split(' ', 1)[0]
                if  idErr == ['']:
                    continue  # empty line
                self.ignore_list[idErr] = 0
        except:
            pass
        print self.ignore_list
        # wraith end


    def __call__(self, line_no, message, icon=None,
                 base_dir=None, file_name=None):
        """Report a message."""
        if self.error_only and icon != 'error':
            return
        # wraith 2013.05.06 - ch.Ignores
        idErr = message.split(' ', 1)[0]
        if  idErr in self.ignore_list:
            if  self.ignore_list[idErr] == 0:
                self.ignore_list[idErr] =  1
                message = idErr + ' ~/.pocketlints_ignore.rc'
            else:
                return
        # wraith end
        self.call_count += 1
        args = (line_no, message, icon, base_dir, file_name)
        if self.report_type == self.FILE_LINES:
            self._message_file_lines(*args)
        elif self.report_type == self.COLLECTOR:
            self._message_collector(*args)
        else:
            self._message_console(*args)

příklad ~/.pocketlints_ignore.rc

# List ignored errors in pocketlints
# Hack in: /usr/lib/python2.7/dist-packages/pocketlint/formatcheck.py
E221 multiple spaces before operator
E222 multiple spaces after operator

Žádné komentáře:

Okomentovat