Sublime Forum

Status update onPostSave

#1

I’m trying to run php -l (lint) on every file that I save, to check for syntax errors.

I would like to update the status bar with the result, if there is an error, but somehow I can’t manage to do that onPostSave.

First I had this which doesn’t work at all because I guess the sublime “File Saved blabla” message overwrites it.

[code]import sublime, sublimeplugin, subprocess

class phpLint(sublimeplugin.Plugin):
def onPostSave(self, view):
if view.fileName()-4:] == ‘.php’:
file = subprocess.Popen('php -l '+view.fileName(), stdout=subprocess.PIPE).stdout
if file.readline()[0:2] == ‘No’:
print ‘Syntax OK’;
else:
sublime.setStatus(‘phpLint’, file.readline());
[/code]

Then I tried this with the timeout as seen in the IdleWatcher example:

[code]import sublime, sublimeplugin, subprocess, functools

class phpLint(sublimeplugin.Plugin):
def onPostSave(self, view):
if view.fileName()-4:] == ‘.php’:
file = subprocess.Popen('php -l '+view.fileName(), stdout=subprocess.PIPE).stdout
if file.readline()[0:2] == ‘No’:
print ‘Syntax OK’;
else:
sublime.setTimeout(functools.partial(self.updateStatus, view, file.readline()), 500)

def updateStatus(self, view, text):
    sublime.setStatus('phpLint', text);

[/code]

This fails with AttributeError: ‘module’ object has no attribute ‘setStatus’, which I’m not sure I understand.

Alternatively I could do it onPreSave and prevent the saving if the file has syntax error, but I’m not sure if that’s possible.

Also I have the problem that Popen() pops up a console window while php -l runs, which really sucks even though it just flashes… Any idea how to prevent that ?

Cheers.

0 Likes

#2

Ok this works, without console flash, except that I have to wait until the “Saved %file% (%encoding%)” message goes away after a few seconds to see if I had a parse error or not. I’d also still like to prevent file saving if possible.

[code]import sublime, sublimeplugin
from subprocess import STARTUPINFO, PIPE, Popen

class phpLint(sublimeplugin.Plugin):
def onPostSave(self, view):
if view.fileName()-4:] == ‘.php’:
startupinfo = STARTUPINFO()
startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW
file = Popen(‘php -l "’+view.fileName()+’"’, stdout=PIPE, startupinfo=startupinfo).stdout

        if file.readline()[0:2] == 'No':
            view.setStatus('phpLint', '');
            print 'Syntax OK';
        else:
            view.setStatus('phpLint', '<!> '+file.readline().strip());

[/code]

0 Likes

#3

view.setStatus associates a persistent bit of information with the view, that’s shown in the status bar when the view is focussed. It sounds like you want to use sublime.statusMessage, which shows a temporary status message, irrespective of the current view. This will also appear immediately, unless another call to sublime.statusMessage occurs and overwrites the last one.

By default, statusMessage is called internally after each save, notifying the user of a successful save, so you’ll want to use the setTimeout based approach that you used above to call it after this - the only difference from the first code snippet is calling sublime.statusMessage rather than (the non-existent) sublime.setStatus.

0 Likes

#4

Ok thanks jon. Would be cool to have a new onSave event, associated with some kind of sublime.preventDefault() (à la javascript) to cancel the default behavior that sublime would have when that even fires. This could allow me to stop it from saving a file that has syntax errors.

Here is the final version of the php lint check if anyone is interested:

[code]import sublime, sublimeplugin, functools
from subprocess import STARTUPINFO, PIPE, Popen

class phpLint(sublimeplugin.Plugin):
def onPostSave(self, view):
if view.fileName()-4:] == ‘.php’:
startupinfo = STARTUPINFO()
startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW
file = Popen(‘php -l "’+view.fileName()+’"’, stdout=PIPE, startupinfo=startupinfo).stdout

        if file.readline()[0:2] != 'No':
            sublime.setTimeout(functools.partial(self.updateStatus, view, file.readline().strip()), 100)

def updateStatus(self, view, text):
    sublime.statusMessage('<!> '+text);

[/code]

When I got time I’ll try to add a command to move the cursor to the point where the error occured later on, but this will have to do for now.

0 Likes