PHP Code Compliance In Emacs

July 01, 2011 at 09:00 AM | categories: php, emacs | View Comments

My job has me working on a project in PHP right now -- it sure isn't Python, but PHP has grown up considerably since the last time I used it, which has been awhile. Consequently, I have no Emacs config for PHP setup, other than vanilla php-mode, so I went in search of one. Of course, I knew Sacha Chua would have a great one, so that's where I've started.

My code is required to conform to the PEAR coding standards which is a bit pedantic in places, but it's generally a good reference to make clean and readable code. The only real pain in conforming to a coding standard is if your editor doesn't pick up on your mistakes right away, you get no automatic feedback and you're left with the task of cleaning up your code later at an inconvenient time. In my case, a subversion pre-commit hook checks for compliance and prevents me from checking in non-conforming code just when I thought I was ready to go home!

Sacha's configuration only checks for general syntax errors, it doesn't check for code compliance. For that, I'm using PHP_CodeSniffer which performs a static analysis of a PHP file and notes any deviations for a given standard. They even support Emacs compile mode out of the box. Compile mode still doesn't give me automatic feedback though, for that I still wanted to use flymake like Sacha has.

So here's my elisp for configuring Emacs to automatically highlight both syntax errors and coding standard deviations for PHP:

(require 'php-mode)
(require 'flymake)

;; Pear coding standards : http://pear.php.net/manual/en/standards.indenting.php
(defun pear/php-mode-init ()
  "Set some buffer-local variables."
  (setq case-fold-search t)
  (setq indent-tabs-mode nil)
  (setq fill-column 78)
  (setq c-basic-offset 4)
  (c-set-offset 'arglist-cont 0)
  (c-set-offset 'arglist-intro '+)
  (c-set-offset 'case-label 2)
  (c-set-offset 'arglist-close 0))
(add-hook 'php-mode-hook 'pear/php-mode-init)

(defun my-php-hook-function ()
  (set (make-local-variable 'compile-command) (format "php_lint %s" (buffer-file-name))))
(add-hook 'php-mode-hook 'my-php-hook-function)

(defun flymake-php-init ()
  "Use php and phpcs to check the syntax and code compliance of the current file."
  (let* ((temp (flymake-init-create-temp-buffer-copy 'flymake-create-temp-inplace))
     (local (file-relative-name temp (file-name-directory buffer-file-name))))
    (list "php_lint" (list local))))

;;This is the error format for : php -f somefile.php -l 
(add-to-list 'flymake-err-line-patterns
  '("\\(Parse\\|Fatal\\) error: +\\(.*?\\) in \\(.*?\\) on line \\([0-9]+\\)$" 3 4 nil 2))

(add-to-list 'flymake-allowed-file-name-masks '("\\.php$" flymake-php-init))
(add-hook 'php-mode-hook (lambda () (flymake-mode 1)))

This depends on a small BASH helper script which I have stored in my $HOME/bin directory (which is on my PATH by default):

!/bin/bash
#This does standard PHP syntax checking
php -f $1 -l
#This does coding standard checking
phpcs --standard=PEAR --report=emacs $1
#Always exit with status code 0 otherwise flymake complains
exit 0

Now I get nice red highlighting for when I forget a doc tag or to put a space between parens and brackets. Isn't pedantry great? :/

Read and Post Comments

Searching GameFAQs within Steam games

September 22, 2010 at 08:30 PM | categories: python, games | View Comments

To take the edge off work, I've been playing Fallout 3 this week. Let me just say this: post apocalyptic Washington DC is huge! Thankfully, there's GameFAQs, because I don't have 40 hours a week to devote to playing games the hard way.

The problem is, 3D games are notoriously bad at recovering after you Alt-Tab out of the game to use your web browser. Luckily, Steam has a built in web browser, so that you don't need to leave the game in order to check GameFAQs, which is great... except for the fact that the Steam browser is totally lame.

See, GameFAQs are plain text files. I think that's cool; plain text is an age old geek tradition, plus it's the ultimate portable file format. However, that also makes things difficult when you're talking about a guide that is over 1MB and broken into hundreds of sections with no hyperlinks to help navigate. GameFAQ authors are a smart bunch though, they have the habit of creating unique codes for each section, essentially creating ad-hoc hyperlinks. You just use your browser's search feature to search for the code and you go right to the section you want.

And what browser doesn't have a search feature?

Oh... right, the Steam browser.

Seriously?

Seriously!?

Alright fine, I'm a hacker, I can get around this. My solution was to write a GameFAQs proxy that downloads FAQs and injects them into a page that uses the jQuery highlight plugin. Slapping on a header to every page for easy navigation, gives us our very own search-in-the-browser add-on for the feature-gimped Steam browser.

Download a standalone executable and try it yourself. Yea, I probably could have made a public server, but I didn't want to get into a copyright hassle, so for now you'll just need to run it yourself on your own computer. I've tried to make it as easy as possible. If you're a Python geek and want to check out the source (or just paranoid about running a pre-compiled exe), it's over on github. If you're interested in how I compiled the Pylons application into a standalone executable with bbfreeze, checkout make.py (although it's pretty cludgy).

One more thing, this proxy is essentially scraping the GameFAQs.com website, so it's possible things could break if they change their site too much. Let me know in the comments if this thing doesn't work anymore.

Instructions for the standalone executable:

  • Download the exe (Tested on Windows 7, 32 & 64 bit)
  • Run the application. It's a self extracting archive, extract it wherever you want. The desktop is fine (it's just one .bat file and a directory.)
  • Run start_steam_gamefaqs.bat and wait for the window to pop up.
  • Leaving that window open, start your steam game.
  • In the game, press Shift-Tab to bring up the Steam community page.
  • Click on the web browser.
  • Enter the URL : http://localhost:5000
  • Search for your desired game and FAQ.
  • Search the page by pressing Ctrl-F and typing in the "Search This Page" box. Pressing Enter multiple times in that box will find the next match for that search term.

Read and Post Comments

My Model M Keyboard Dyed

July 17, 2010 at 07:13 PM | categories: cool stuff | View Comments

I've been using the same IBM Model M keyboard for about 6 years now. I never thought I would see the day when it would quit working. I love this keyboard -- the buckling springs deliberately and assuredly clicking and clacking beneath my fingers blow the pants off any cheap-ass keyboard you get for "free" with your factory Dell PC. It's amazing that the best keyboard ever made was actually one of the very first. Created in 1985, the Model M set the standard to beat, but the quality of PC keyboards over the years has only gone downhill. Thank goodness Unicomp still makes these things. Otherwise, I'm not sure what I would ever replace this keyboard with... maybe a Das or a Deck.

Luckily, I don't have to replace it. It hasn't died yet, and probably never will.

Chris McDonough recently wrote an excellent article on the 25 years of the Model M. Since reading it, I've been thinking quite a bit about my trusty Model M and I decided to give it an early 25th birthday present: some new colors!






I followed a guide from Overclock.net describing the process of applying rit dye to the keys. I've used other keyboards that had paint jobs on them before, but the rit dye process is soo much nicer. With paint, you always get a sticky paint feel on the keys and of course it also covers up the letters on the keys permanently. The rit dye, on the other hand, permeates the plastic and leaves no residue on the surface at all. In fact, you can still see the letters quite well.

I liked the red and brown combination used in the Overclock.net guide, although I left the original color differentiation of the model M intact: letters and numbers red, and the meta keys and some of the F keys brown. The red keys turned out fantastic, the letters on them are very distinctive. However, the brown turned out a bit differently; being much darker, almost black, it all but obscures the markings on the keys. No big deal though, I guess my new Model M is half-way to a Das Ultimate after all. :)

Read and Post Comments

Audacious Dynamic Playlist powered by inotify

July 13, 2010 at 12:22 AM | categories: python, linux | View Comments

I was playing around with StreamRipper today to record a shoutcast stream I enjoy, and I thought to myself: wouldn't it be nice to be able to continuously play all the files I've downloaded without having to manually queue the new files in Audacious?

So, I scratched an itch. With a little DBUS, pyinotify, and an optparse wrapper, I now have a tool to automatically add the tracks to my Audacious playlist. You can grab the latest version on github.

Streamripper does have a relay option (-r) to allow you to listen to the same stream as you're ripping it, and if that's what you want, the following script is superfluous. However, what I wanted was something slightly different: I didn't necessarily want to just listen to the stream live, instead, I wanted the ability to jump around between the tracks already downloaded, exploring different songs, but with the list of tracks ever expanding. That's what this script allows.

You'll need python-dbus and setuptools installed, then just install with:

easy_install http://github.com/EnigmaCurry/audacious-plugins/zipball/master

Startup StreamRipper with your favorite audio stream and point the tool at your target directory:

python -m ec_audacious.dynamic_filesystem_playlist /path/to/your/streamripper_location

Now when StreamRipper creates a new file, it will get automatically (instantaeneously actually, thanks to inotify!) to your Audacious playlist.

Alternatively, you can use the streamripper wrapper script that I've included to start both the filesystem monitor as well as streamripper in one go:

Put the following in your .bashrc file or somewhere equivalent:

alias streamripper="python -m ec_audacious.streamripper"

Then whenever you run streamripper, you'll actually be running the wrapper script instead:

streamripper http://your-cool-stream.com:8000 --audacious

By aliasing streamripper to point to the ec_audacious.streamripper wrapper script, we're effectively adding a new option to streamripper called --audacious which spawns our filesystem monitor.

Read and Post Comments

Bill of Responsibilities

April 18, 2010 at 11:55 AM | categories: liberty rants | View Comments

George Donnelly recently blogged about his personal Bill of Responsibilites. I think his approach to crafting a message of liberty, through the lens of personal responsibility, is a creatively powerful one. It is his post that has inspired this one.

I've tried in the past to formulate a consistent approach to describing to people what true liberty is, but I think quite often that message resorts to telling people that they are doing something wrong and/or immoral. While I might be correct, focusing on someone else's faults is often not very constructive. Instead, why not focus on how I choose to live my life and my justification for doing so?

This Bill of Responsibilities is essentially a contract with myself. These are things that I believe are central to my being a good and productive person. However, if I fail to do these things, I not only fail myself but also the rest of mankind. My hope is that by living up to my own expectations, I can provide a framework for others to emulate and improve upon.

So here goes, my own personal Bill of Responsibilities:

Preamble

I have the ultimate responsibility for my own survival. The division of labor that has evolved within mutual societies is wondrously beneficial to the progress of mankind and it should be taken advantage of in order to increase one's quality of life. However, the existence of such developed societies does not relieve my own personal responsibility to provide for my own needs and desires. In addition, every action I take in life will have some impact upon others. A free and prosperous society requires that I take responsibility to never use unjustified force or fraud against my fellow man.

Responsibilities

  1. I have the responsibility to take care of myself. I cannot rely on anyone else to provide for my shelter, sustenance, education, livelihood, security, health care, entertainment, retirement, or any other thing.

  2. I have the responsibility, as a civil member of a society, to only engage others in a voluntary and mutually-agreeable fashion. I have the responsibility to never force an individual to do what they do not want to do, unless that force is a justifiable reaction to their own aggression.

  3. I have the responsibility to keep my word in my dealings with others. If I fail to honor my agreements, I have the responsibility to make full restitution in as timely a fashion as possible. To do otherwise is fraudulent and manipulative.

  4. I have the responsibility for my mistakes. If my actions unjustifiably harm or endanger another person, I am responsible for making full restitution in as timely a fashion as possible. To do otherwise is reckless and violent.

  5. I have the responsibility to defend myself and my family from those that would hurt us. I cannot rely on any other individual to risk their own life or livelihood to protect me.

  6. I have the responsibility to educate myself. Schooling is insufficient, and in many cases, destructive of the cognitive abilities of the mind. Information, derived from any source, must be processed by an engaged, observant, and critical mind.

  7. I have the responsibility to resist cooperating with people that choose to conduct themselves in violent ways. To cooperate with such evil, would immediately endanger myself and my family. To be idle and complicit in any crime against myself, strengthens the aggressor and provides the potential of harming my fellow man.

  8. I have the responsibility to question authority. Does an authority conduct themselves in a responsible manner? Do their claims of authority stem from actual property rights, or do they stem from fraud or force to acquire your compliance for their own gain? To leave these questions unanswered, or worse, unquestioned, is to allow one's mind to degenerate into a state of Stockholm syndrome.

  9. I have the responsibility to speak out against injustice and to support others that do as well. In order to live in a free and prosperous society, justice must be served.

  10. I have the responsibility to continuously exercise my liberties, for they are precariously positioned to be lost if I am not practiced in defending them. I have the responsibility to continuously work to assert my retention of lost liberties, for the longer I wait and do nothing, the more unrecoverable they become.

Read and Post Comments

Next Page »