Tuesday, November 25, 2008

Syntac Checking for PHP in Emacs

Syntax checking for PHP in Emacs

When programming PHP I often find it useful to see parse errors that are created as I type. A missing semicolon at the end of the line, a missing quotation mark, a dot in the wrong place, stuff like that that triggers PHP Fatal or Parse Errors. On-the-fly syntax checking is a common feature of good programming IDE’s and editors. Emacs is no exception – there’s flymake minor mode that is meant to help you discover errors at the time of writing code. Flymake is currently a part of Emacs distribution and it covers on-the-fly syntax checks for a lot of popular programming languages like C, C++, Java, Perl and others. Unfortunately PHP syntax checks are not included in that package. I have been looking around trying to find an extension for flymake to make it work with PHP

but couldn’t find any so I decided to write my own.

Flymake-php.el is a bit os Lisp code that plays nicely with flymake and PHP on-the-fly syntax checking. Below you can see this extension in action:

!Flymake and PHP in action

How to install ?

1. Copy the following code to your Emacs library path (for example ~/.emacs.d/flymake-php.el)
    ;; Flymake PHP Extension

(require 'flymake)

(defconst flymake-allowed-php-file-name-masks '(
(".php3'" flymake-php-init)
(".inc'" flymake-php-init)
(".php'" flymake-php-init))
"Filename extensions that switch on flymake-php mode syntax checks")

(defconst flymake-php-err-line-pattern-re '("(Parse|Fatal) error: (.*) in (.*) on line ([0-9]+)" 3 4 nil 2)
"Regexp matching PHP error messages")

(defun flymake-php-init ()
(let* ((temp-file (flymake-init-create-temp-buffer-copy
(local-file (file-relative-name
(file-name-directory buffer-file-name))))
(list "php" (list "-f" local-file "-l"))))

(defun flymake-php-load ()
(setq flymake-allowed-file-name-masks (append flymake-allowed-file-name-masks flymake-allowed-php-file-name-masks))
(setq flymake-err-line-patterns (cons flymake-php-err-line-pattern-re flymake-err-line-patterns))
(flymake-mode t)
(local-set-key "C-cd" 'flymake-display-err-menu-for-current-line))

(provide 'flymake-php)
2. Make sure the library path is present in your .emacs, for example:
    (add-to-list 'load-path "~/.emacs.d/")
3. Require the flymake-php extension
    (require 'flymake-php)
4. If you’re using php-mode (I bet you are if you program in PHP) you can add a hook to this extension, so that every time a php-mode is switched on you’ll have flymake minor mode running. 5.
(add-hook 'php-mode-user-hook 'flymake-php-load)


Now every time you open a php file that has an extension specified in flymake-allowed-php-file-name-masks a flymake minor mode will be switched on with on-the-fly syntax checking. If you see a highlighted line you can position the cursor on the line and press C-c d to see a popup window with an error message (similar to the screenshot above).

M-x flymake-goto-next-error and M-x flymake-goto-prev-error functions allow for easy navigation to the next/previous erroneous line, respectively. You can also bind these functions to the keys of your choice (local-set-key function).

How does this work ?

Quote from flymake-info manual:

Flymake runs the pre-configured syntax check tool (compiler for C++ files, `perl’ for perl files, etc.) in the background, passing it a temporary copy of the current buffer, and parses the output for known error/warning message patterns. Flymake then highlights erroneous lines (i.e. lines for which at least one error or warning has been reported by the syntax check tool), and displays an overall buffer status in the mode line. Status information displayed by Flymake contains total number of errors and warnings reported for the buffer during the last syntax check.
Syntax check is done ‘on-the-fly’. It is started whenever

- buffer is loaded - a newline character is added to the buffer - some changes were made to the buffer more than `0.5’ seconds ago (the delay is configurable).

Customise your flymake

You can further customise your flymake-mode. For example to disable a syntax check every time a newline is added to a buffer you can set flymake-start-syntax-check-on-newline variable to nil, eg.:

(setq flymake-start-syntax-check-on-newline nil) 

You can also customise the look of the error line “face” (font, size and color of the error line) by setting flymake-errline-face. Please refer to flymake info manual for all the available options.

php.ini settings Because flymake will call php -l temp-buffer every time a request is trigger it’s a good idea to disable error logging in php.ini (cli version)

; Log errors into a log file (server-specific log, stderr, or error_log (below)) ; As stated above, you’re strongly advised to use error logging in place of ; error displaying on production web sites. log_errors = Off

What about warnings ?

If you’re an adventurous soul (by this I mean “hacking Lisp code” type of adventure :) ), you may extend this a little bit and add support for PHP warning messages.

No comments: