JSLint and git blame for fun and profit

For some unknown reason, we have a problem with superfluous trailing commas at work in our JavaScript. It's probably because we have a bunch of Perl developers writing JavaScript. Unfortunately, this doesn't play well in a world with Internet Explorer.

JSLint makes this easy enough to track down. But I wanted something more. I wanted to know who the culprits were. Thus, I whipped up this little script that'll take a list of files and tell you who committed a file with a trailing comma in it. Besides, JSLint, You'll need Rhino and a script to execute commands (named runtime.js). I'll try and post that later.

// blame_comma.js -- loop through the files passed in and see who has
// commas in them

// find ../htdocs/js/ECM -type f -name "*.js" -print | \
// xargs java -classpath \
//   /usr/share/yuicompressor-2.4.2/lib/rhino-1.6R7.jar \
//   org.mozilla.javascript.tools.shell.Main blame_comma.js

load('fulljslint.js');
load('runtime.js');

(function(args) {
    var bad_files = {};
    for (var i = 0; i < args.length; i++) {
        var file = args[i],
            js = readFile(file);
        var success = JSLINT(js, {
            browser : true,
            undef   : true,
            newcap  : false,
            indent  : 4,
            predef: ["Ext","ECM","ActiveXObject","window",
                     "TestCase","document","assertTrue","sinon","gt"]
        });
        if (!success) {
            var errors = JSLINT.errors;
            for (var j=0;j<errors.length;j++) {
                var e = errors[j];
                if (e && e.reason && e.reason.match(/Extra comma/)) {
                    var cmd = 'git blame -L' + e.line + ', ' +
                              e.line + ' -- ' + file;
                    var output = runtime.exec( cmd );
                    if (!bad_files[file]) {
                        bad_files[file] = [];
                    }
                    bad_files[file].push(output);
                }
            }
        }
    }
    for (var key in bad_files) {
        if (bad_files.hasOwnProperty(key)) {
            print("\n" + key);
            var errors = bad_files[key];
            for (var i = 0; i<errors.length;i++) {
                print(errors[i]);
            }
        }
    }
})(arguments)

Like most of the stuff I seem to do lately, this is available as a gist on GitHub. Let me know if you see anything you like.

Add a comment
Category: programming Tags:

Beautify your JavaScript in Emacs

I know you'll find this hard to believe dear reader but I'm a big fan of using Emacs to write JavaScript. One thing that irked me in the past is that none of the libraries got the indentation and other formatting how I wanted. Luckily, I recently stumbled onto js-beautify (via the most excellent jsFiddle.

Lo and behold, there is a command line interface to beautifying JavaScript! Good thing Emacs can call shell commands on text so easily. Thus, we have:

;;; js-beautify.el -- beautify some js code

(defgroup js-beautify nil
  "Use jsbeautify to beautify some js"
  :group 'editing)

(defcustom js-beautify-args "--jslint-happy --brace-style=end-expand
--keep-array-indentation"
  "Arguments to pass to jsbeautify script"
  :type '(string)
  :group 'js-beautify)

(defcustom js-beautify-path "~/projects/js-beautify/python/jsbeautifier.py"
  "Path to jsbeautifier python file"
  :type '(string)
  :group 'js-beautify)

(defun js-beautify ()
  "Beautify a region of javascript using the code from jsbeautify.org"
  (interactive)
  (let ((orig-point (point)))
    (unless (mark)
      (mark-defun))
    (shell-command-on-region (point)
                             (mark)
                             (concat "python "
                                     js-beautify-path
                                     " --stdin "
                                     js-beautify-args)
                             nil t)
    (goto-char orig-point)))

(provide 'js-beautify)
;;; js-beautify.el ends here

I like it so much I have bound to M-t (for tidy) in a mode hook:

(local-set-key "\M-t" 'js-beautify)

If you want to follow any updates, I've put this snippet up as a Gist on GitHub so feel free to clone and send me any pull requests.

Add a comment
Category: editor Tags:

Toggler in Ext JS

Since it has been awhile since I last posted and we started using Ext JS at work, I thought I'd post a little snippet JavaScript for setting up a link that toggles something.

// create a toggler link...is there a better way?
var toggler = new Ext.BoxComponent({
    autoEl: {
        tag: 'a',
        href: '#',
        html: 'All'
    },
    listeners: {
        'render': function(comp) {
            var el = comp.getEl();
            el.on({
                'click': {
                    scope: comp,
                    fn: function(event, element) {
                        event.stopEvent();
                        var text = this.getEl().dom.innerHTML;
                        text = text.toggle('All', 'None');
                        this.update(text);
                        // do your toggling here
                    }
                }
            });
        }
    }
});

Because it's an instance of Ext.Component it can easily be added to a Ext.Container so it's a tad more reusable than a straight up select. At least I think so.

Questions and comments welcome.

Add a comment
Category: programming Tags:

Books I Read in 2010

I was messing around with the Goodreads API and generated a list of books I read in 2010. Here they are in reverse order:

Only 32 books in a year! That's kind of low for me, even with my Kindle by my side. Such is life I suppose. I really enjoyed How to Live Safely in a Science Fictional Universe by Charles Yu, the Hunger Games series and Pragmatic Thinking and Learning: Refactor Your Wetware by Andy Hunt if anyone is looking for a "Best of."

Full disclosure: These are Amazon affiliate links so if you happen to buy one through a link, I'll get some shekels.

Add a comment
Category: reading Tags:

Git script to update Bugzilla

At my work we use git and Bugzilla for source code control and bug tracking respectively. We have a process where bugfixes are commited to a branch off of master with the name of bugfix/bz1234 where 1234 is the id of the issue in our bugzilla system.

After a fix is completed, a merge request is filed in our bugzilla system to merge this branch back into master (developers don't have write privileges to master). We are in the process of writing up a hook to parse commit messages to automate all of this but it's taking some time.

So, in the interest of making my life a bit easier until then, I took advantage of Bugzilla's excellent email_in.pl to parse incoming emails to edit tickets and wrote up a command to file fix and merge tickets for me.

I simply put git-bz on my $PATH and call it thusly:

> git bz fix
> git fix 1.2.3 hotfix | sendmail -t

Note: Our merge tickets require a milestone and a version for the merge ticket, thus the extra arguments for the merge.

Your system is probably radically different than ours but I thought it'd be interesting to post something here showing how powerful git is. Let me know what you think.

#!/usr/bin/env perl
# git-bz -- given a version and target, print out a merge
#           email for sending to bz

use warnings;
use strict;

use Carp;
use Git;

#============================================================================
# map a shorthand version to the one bz expects for merges
#============================================================================
my %versions = (
    'mne'    => 'Merge (M&E/Patch)',
    'rc'     => 'Merge (RC/Major)',
    'hotfix' => 'Merge (Hotfix)'
);

#============================================================================
# get the action and config info
#============================================================================
my $action   = shift || '';
my $bz_email = Git::config('bz.email');

if (! $bz_email) {
    croak 'No bugzilla email found';
}

#============================================================================
# start doing the work
#============================================================================
if ( $action eq 'fix' ) {
    my $user_email = get_user_email();
    my $bz_info = get_bz_info();

    print <<"MAIL";
To: $bz_email
From: $user_email
Subject: Issue $bz_info->{bug} fixed

\@bug_id = $bz_info->{bug}
\@bug_status = RESOLVED
\@resolution = FIXED

Fixed in $bz_info->{branch} pending merge.

MAIL

} elsif ( $action eq 'merge' ) {
    my $target_milestone = shift || '---';
    my $merge_to = shift;
    my $version  = ( $merge_to && $versions{$merge_to} ) ||
                   'unspecified';
    my $bz_info  = get_bz_info();

    my $user_email = get_user_email();

    if ( !defined $bz_info->{bug} ) {
        croak "No bug id found in branch name";
    }

    my $bug_id = $bz_info->{bug};
    my $bz_branch = $bz_info->{branch};

 #============================================================================
 # get the remote branch, url and name
 #============================================================================
    my @remote_info
        = Git::command( 'config', '--get-regexp', '^branch\.'
                        . $bz_branch );
    my ( $remote, $remote_branch );
    for my $line (@remote_info) {
        if ( $line =~ /\.remote\s+(.+)/x ) {
            $remote = $1;
        } elsif ( $line =~ /merge\s+((refs\/)?heads\/)?(.+)/x ) {
            $remote_branch = $3;
        }
    }

    my $remote_url = Git::command_oneline( 'config', '--get-regexp',
        'remote.' . $remote . '.url' );
    if ( $remote_url =~ m/url\s+(.+)/x ) {
        $remote_url = $1;
    }

 #============================================================================
 # get the commits to show
 #============================================================================
    my $commits = Git::command(
        'log',            "$remote/$remote_branch..",
        '--pretty=short', '--name-status'
    );

 #============================================================================
 # finally print out the email message
 #============================================================================
    print <<"MAIL";
To: $bz_email
From: $user_email
Subject: Please merge $bz_branch to $remote_branch

\@blocked = $bug_id
\@product = Application Defects
\@component = Merge Request
\@version = $version
\@target_milestone = $target_milestone

Please merge $bz_branch to the remote branch $remote_branch

Merge: $bz_branch
To: $remote_branch
Repository: $remote_url

$commits
MAIL

} else {
    croak <<"USAGE";
error: Unknon subcommand: $action
usage: git bz fix <target>
   or: git bz merge <merge_to> <target>

USAGE
}

#============================================================================
# get current branch and bug ID
#============================================================================
sub get_bz_info {
    my $bz_branch = Git::command_oneline( 'symbolic-ref', 'HEAD' );
    $bz_branch =~ s{^refs\/heads/}{}x;
    my ($bug_id) = $bz_branch =~ m/bz(\d+)/x;
    return { branch => $bz_branch, bug => $bug_id };
}

sub get_user_email {
    my $email = Git::command_oneline( 'config', '--get', 'user.email' );
    return $email;
}

If you want to use it, you'll need to set up a config to point to your own bz email.

> git config bz.email mybz@somedomain.com

This script is available as a gist on github.

Add a comment
Category: programming Tags:

Emacs and Remember The Milk all jumbled up

I'm a huge fan of Remember The Milk and GNU Emacs. So much so, that I've given them both money over the years. And now I've (kind of) combined them. I just pushed slack-rtm to GitHub.

I've kind of avoided Emacs Lisp, the 1984 Subaru of Lisp. While I've done some minor hacking of my .emacs in the two years I've been using Emacs, I have not really done any serious programming in it. But with this, I'm hoping to remedy that a bit. It's been fine so far, even though the learning curve has been steep. I don't think I'll be writing a JavaScript interpreter anytime soon.

Right now, it's pretty simple. It just creates a buffer and shoves your tasks into it. I've only tested it on GNU Emacs 23.1.50.1. Ultimately, I'd like it to sync between an orgmode file and RTM, kind of like what Sacha Chua did with org-toodledo.

So, have at it. Feel free to fork it and send me pull requests. I'm hoping to release early (DONE!) and often.

Add a comment
Category: editor Tags:

Sheena Is A C++ Hacker

Not really. And my name's not Sheena. But I did make a contribution to the awesome console based newsreader Newsbeuter. If you want to see my patch, it's available on Github. I fixed a problem with the way that it authenticated against Google Reader API.

As for Newsbeuter, if you like doing everything from the commandline, this is the newsreader for you. Lots of features like keyboard shortcuts that can be reconfigured easily and query feeds so you can create your own pipe.

Check it out

Add a comment
Category: personal Tags:

Google Apps Script For Fun and Profit

OK, so I have to admit that I have a mancrush on Google Apps Script. It's a nice little tool that allows you to do a whole variety of things on a bunch of Google Products. For instance:

With scripts, you can:
* Create your own custom spreadsheet functions
* Automate repetitive tasks (e.g. process responses to Google Docs forms)
* Link multiple Google products together (e.g. send emails or schedule
* Calendar events from a list of addresses in a Spreadsheet)
* Customize existing Google products (e.g. add custom buttons or menus to run * your own scripts)

Not only is the tool itself very nice (a slick in-browser editor with syntax highlighting and context sensitive prompts), the tutorials are as well. In a little under 15 minutes while reading the tutorial I was able to write a script that emails you the next 10 days events from any calendar. It uses JavaScript so if you are familiar with that, then you could probably even do it quicker than me and my old brain.

A pet peeve that I have is that the daily email I get from Google Calendar doesn't include my contact's birthdays. Even if it did, it'd only be for that day which would be too late for me to drop a card in the mail. And even if did that, it wouldn't send the email to my wife. Thus, the following script was born.

// how many days in advance
var INTERVAL = 10;

// the calendar to grab
var CALENDAR = "Contacts' birthdays and events";

// who to send it to
var EMAIL_TO = "email1@somewhere.com,email2@somewhere.com";

//  the subject to use
var SUBJECT = "Birthdays for Seth next " + INTERVAL + " days "

function onOpen() {
  var submenu = [{ name:"Send Birthday List",
                   functionName:"sendBirthdayList"
                 }];
  SpreadsheetApp.getActiveSpreadsheet().addMenu('Birthdays', submenu);
}

function sendBirthdayList() {
  // Get the event template string from the spreadsheet
  var emailTemplate = SpreadsheetApp
        .getActiveSheet().getRange("b2").getValue();
  var eventTemplate = SpreadsheetApp
        .getActiveSheet().getRange("b3").getValue();
  // Get the next INTERVAL days
  var start = new Date();
  var end = new Date(start.getTime() + 1000*60*60*24*10);

  var cal = CalendarApp.openByName(CALENDAR);
  var events = cal.getEvents(start, end);

  // Add each event to the email
  var eventLines = "";

  for (var e in events) {
    var event = events[e];
    eventLines += eventTemplate
      .replace("<TITLE>", event.getTitle())
      .replace("<DAY>", event.getEndTime().toLocaleDateString())
      .replace("'s birthday","");

  }
  var email = emailTemplate.replace("<EVENTS>", eventLines);
  MailApp.sendEmail(EMAIL_TO,
                    SUBJECT + now.toLocaleDateString(), email);
}

Lo! Better living through technology.

Right now, I have the template for the email stored in two cells in a spreadsheet and other configuration info at the top of the script. Those could probably go in cell data too, just so it'd be easier to share this script. But it should give you an idea of lovely it is touse Google Apps Script.

Using the triggers that are built-in (Triggers < Current script triggers...), I have it scheduled to email us every 3 days at midnight. So, hopefully, I won't be missing any birthdays.

Add a comment
Category: personal Tags:

97 Things Every Programmer Should Know

I recently picked up O'Reilly's book 97 Things Every Programmer Should Know: Collective Wisdom from the Experts as it was an eBook Deal of the Day. Overall, I thought it a great book for a programmer just starting out in the field. It had quite a few things that I wish I'd known earlier. Probably because I took an unconventional route to programming.

One thing I found interesting was that many of the essays made reference to the suggestion from The Pragmatic Programmer: From Journeyman to Master to learn one new langauage every year. The suggestion by itself wasn't interesting. I think many people have heard it. The thing that intrigued me about it was that "The Pragmatic Programmer" is published by Addison-Wesley. I don't think I've seen such overt references to other publishers' books in a programming book before.

Kudos to you O'Reilly.

Add a comment
Category: reading Tags:

A Better Bugzilla2

For a variety of reasons, I'm still using version 2 of Bugzilla at work even though it's considered "dead" by Bugzilla. And the interface looks like it's been dead awhile.

But, thanks to Greasemonkey, I'm not stuck with the interface. Inspired by Jesse Ruderman's TidyBug, I made my own Greasemonkey script which I'm calling TidyBz2.

Here's the before shot:

A Better Bugzilla Before

Here's the after shot:

A Better Bugzilla After

It hides the huge header, makes the title of the issue much more prominent and fixes some other formatting nits I disliked. Information that I think is more important is moved up to the top as well. But there are also perks you can't see. You can use the keyboard to do pretty much anything you need to: comment, resolve, browse the URL, search, navigate between comments a la gmail, etc. Once you have it installed, just press ? to see all the keyboard shortcuts.

It's up on GitHub so feel free to fork it and make any modifications you'd like to see.

Add a comment
Category: tools Tags:

PragPub

This is probably way late but The Pragmatic Bookshelf, publishers of fine programming books, have launched a free monthly magazine called PragPub that covers a variety of topics. For instance, this month has a nice overview of how to use Sass. Past topics have included articles about Clojure, automating screencasts and managing life projects.

Granted, they are ultimately pushing their books (which I think are excellent) but they are releasing the magazine in PDF, epub and mobi. How cool is that?

PragPub

Add a comment
Category: reading Tags:

Visit your local library via Amazon.com

xISBN

I love reading. It's how I get most my knowledge (or lack thereof). And I also really like bookmarklets. They make browsing the web much easier.

And I found this great bookmarklet that let's you find a book that you are viewing on Amazon.com at your local library. It's called xISBN Bookmarklet. I just call it 'library lookup v2.' It was inspired by Jon Udell's LibraryLookup which I used to use so I just updated the version.

It's really easy to set up and use. Set up is covered on its page under "Try xISBN Bookmarkets." One thing you'll need in advance is to know the base URL of your library's catalog. Mine is http://catalog.colapl.org for example.

Using it is even eaiser. You just look at a page on Amazon or Barnes and Noble and click the bookmarklet. Or if there's a ISBN on a page, you can just select it and click the bookmarklet. It'll take you to a page like this.

Depending on your library, you could place a hold on it and then pick it up. Remember, support your local library!

Add a comment
Category: tools Tags:

And I'm back

OK, so it's been over a year since my last post (of which I completed all except two). But here I am now with a wonderful new design, thanks to Sprout Creative and a new outlook on blogging.

I've taken a bit of a different approach to blogging this time. Instead of using a content management system like Wordpress or Movable Type, I'm opting for static html. The pages are generated by Jekyll after being written in GNU Emacs. I'm hoping that this tool set makes it easier for me to get posts up. Let me know if you have any questions about the process or if you have any comments about the design.

We'll see if it sticks. If you don't hear from me for another year, then you'll know that this little experiment failed.

Add a comment
Category: personal Tags:

Resolutions

I have been mulling these over for the past couple of days but I thought I'd post them to the internets in hopes of injecting some accountability into the whole morass.

  • Get knee fixed
  • Go on vacation somewhere besides San Francisco/Oakland or Rhode Island with wife and child
  • Take better photos
  • Bake cake for wife's birthday
  • Lay off the sugar and don't lay around as much (uhm, after I bake the cake)
  • Learn Clojure
  • Fix what ails desktop computer
  • Clean out top drawer of bureau
  • Rebalance 401K
  • Turn 40 (yeah, I'm old)

If you are reading this and want a health check, feel free to ping me.

Add a comment
Category: personal Tags:

Dojo snippets for Emacs

I've been using Dojo for a couple of months now and I really like it as it makes writing cross-browser JavaScript a breeze.

Emacs 4EVA!!

I've also been using Emacs with YASnippet for a bit now too. YASnippet is a plugin for Emacs that allows you to define a snippet that'll get transformed into something much bigger in your file. It saves you a lot of typing as you can define areas in your snippet where you get prompted to enter text and it'll autofill with your entries. Very handy, let me tell you. There's a screencast on YouTube showing how powerful it is.

Which brings me to the point of this post. I've created a package of snippets aimed at people writing Dojo based JavaScript. It's hosted up on GitHub if you would like to use it. Currently, it only includes (what I feel to be) the major functions but feel free to contact me if you'd like to add more.

Add a comment
Category: editor Tags:

svn log made easy

svn log is a great command to see what's going on in your subversion repository. Unfortunately, at my job we are using a really old version (1.1.4!), a version so old that it doesn't support the --limit argument. This makes the svn log painful to use as it outputs EVERYTHING.

Luckily, svn log is so awesome that it overcomes this weakness and allows you to use a date based criteria for listing log statements. Unfortunately, the syntax is hard for me to remember. Thus, I wrote this little shell script function that'll list activity for the given days in the past. You can put it in your .bashrc and run it like svnlog 14. That'll output logs from the last 14 days.

svnlog() {
    OFFSET=$1
    shift
    svn log -r HEAD:{"`date -d "$OFFSET days ago" +%Y-%m-%d`"} $*
}
Add a comment
Category: programming Tags:

Commandline Fun

Insprired by an article on ibm.com about using twitter from the command line, I wrote up a simple little script to get your friends updates.

Here it is:

$ curl -s -u username:password \
http://twitter.com/statuses/friends_timeline.xml |
awk '/<text/ {
  gsub(/<\/*text>/,"");
  text = $0;
}
/screen_name/ {
  gsub(/ *<\/*screen_name>/,"");
  print $0;
  print text;
}'

All it does it is use cURL to grab the timeline from twitter. Then it passes it through awk to extract the name and text from your buddies. Simple and silly, yes?

Add a comment
Category: shell Tags:

More Keyboard Fun

Continuing along on the keyboard theme, most Google apps have keyboard shortcuts. I've started using Google calendar and found the keyboard shortcuts for it as well. Very handy.

Google Calendar keyboard shortcuts

Add a comment
Category: tools Tags:

Speaking of keyboard navigation....

Did you know that you can navigate Google search results with your keyboard?

It's a Google Labs experiment so you'll have to enable it on any machine you want to try it.

To experience the glory of navigating search results with your keyboard, head on over to Google Experimental Search and click "Join" for the Keyboard Shortcuts experiment. Then it's simply a matter of pressing "J" to navigate down the search results and "K" to move up your search results on Google. Pressing "O" will then open up the link for you. There are a few others that you might like as well so give this experiment a whirl.

The keyboard shortcuts key will also show up on your search results page so that'll help you remember them. (Experienced vi users will of course recognize these keyboard shortcuts.)

Add a comment
Category: tools Tags:

Throw away that mouse

Mouseless browsing screenshot

I'm not a big fan of using the mouse. It pains me to reach for it to accomplish something. That's why I was really excited to find the Mouseless Browsing add-on for Firefox.

From the add-on's homepage:

Mouseless Browsing (MLB) is a Firefox-Extension which enables you to browse the internet with the keyboard. The basic principle is to add small boxes with unique ids behind every link and/or form element. You just have to type in the id and press enter (there is also an automatice mode available) to trigger the corresponding action i.e. following a link, pressing a button or selecting a textfield.

I could never get w3m working how I liked it so Mouseless Browsing really scratches an itch I have.

Add a comment
Category: tools Tags:

© Seth Mason

Themed using aboutwilson

Powered by Pelican