Fork me on GitHub

Drew's World

Rants, News, Etc on my Life and Projects

SublimeText2 Guard Plugin Debut

by Andrew De Ponte (@cyphactor)

Hi all. I know it has been a while. Please forgive me. My life has been a little crazy. I am still in the process of buliding my house. I also recently became engaged so I am trying to deal with wedding planning. Beyond that I am still trying to get all my development work done for RealPractice, my side company, and all of my open source projects.

Anyways, I needed a break from serious projects and decided it was time for a small fun project that would potentially help me develop the more serious projects more efficiently. A while back I started using a new text editor called Sublime Text 2. Basically it is what TextMate 2 promised (and failed) to be and more.

So, since I have been using this for a while and I have been developing Ruby and Rails apps lately using BDD and TDD I decided it was time to remove the annoyance of having to switch to the terminal after each little development iteration to check Guard’s output to see why my tests are failing. Wow that was a run on sentence. Oh, well it is 2 am and I just finished the plugin so bare with me. Anyways. Therefore, I decided it was the perfect opportunity to build a Sublime Text 2 plugin that integrates Guard into it.

It is available with its documentation on GitHub at http://github.com/cyphactor/sublime_guard. Please don’t hesitate to go grab it, use it, extend it, contribute back, report bugs, or throw me new feature requests.

Archaic - Archived Chats and Dev Helper

by Andrew De Ponte (@cyphactor)

So for those of that don’t know, I lead of team of software developers. For a long time now I have noticed a number of gaps in the industry with respect to software development and team collaboration. One area that I always felt was missing some love was group chat.

Sure, there are a large number of different chat protocols and applications that implement them all. However, they generally miss an archived history that has full text searching. Beyond the group chat is prime location to distribute push notifications when Git repositories that the team is working with have changes pushed to them. Because of these two issues and number of other that I really don’t want to get into at this point I have started a new open source project called “Archaic”.

Archaic is a Rails application that provides archiving of IRC channel chats with a full text search interface as well as general developer helpers. It is composed of two pieces, an IRC Bot and the Rails application. Technically they both share the rails environment as the IRC Bot should be run with rails runner. You can checkout the project at the following: http://github.com/cyphactor/archaic.

I plan to keep the master branch functional so feel free to use the master branch. It currently has the following features.

  • IRC Chat Archiving
  • Full Text Chat Archive Searching with Context (to expand context simply click on resulting match)
  • Week number helper (when anyone in IRC channel types “weeknum” it replies with current week number)
  • Ticket number helper (when anyone in IRC channel types “#\d+” it replies with link to that ticket)

This is the initial introduction to this project and I am sure it has numerous directions that it can and will grow into. I very much welcome your thoughts, suggestions, feature requests, bug reports, testing, etc.

I believe that having a good central place of communication for a team even if they are working in the same office helps at least as a mechanism for keeping your devs notified about repo pushes close to real time.

Anyways, enjoy!

A Quick Multi-Source Ticket Dashboard

by Andrew De Ponte (@cyphactor)

Today was one of those days where I woke up and something was just off with respect to my workflow for some reason. I was frustrated with the fact that I had to load a browser and go to a website to see what my tickets were for the day. Instinctively I just wanted my tickets to magically be in my head so I didn’t have to go through all those steps. So, I started thinking about this problem more and more as the day went by and I came to the conclusion that I really have two problems.

  1. I have tickets dispersed through multiple ticketing system.
  2. I hate having to go through so many steps to see my tickets.

When I started thinking about my two problems I realized that I have my tickets in roughly four different applications/services. These applications/services are as follows:

  • Trac - Web based project management/task management tool
  • Lighthouse - Web based project management/task management tool
  • GitHub - Web based Git repository management system and issue tracking tool
  • Things - Desktop task management system

Beyond having multiple ticket sources, most of them have multiple accounts for various reasons (contract jobs I have done, etc.). Being in a specific environment while working within that scope/environment is fine. For example if I am working on Project X it makes sense that I be in project X’s environment. However, the situation that I am frustrated with is the initialization and transition periods which exist before you start working on a project and when you are switching from one project to the next project.

Based on my issues and the situation I am frustrated with I have come up with a small set of requirements for a solution. These requirements are listed below.

  1. Tickets from all ticket sources must exist in a dashboard
  2. This dashboard must require zero effort/steps to view it
  3. This dashboard must automatically update with zero effort/steps

As many of you know despite the fact that I write software for various platforms and in various languages my platform for development is generally Mac OS X. Given that Mac OS X was my environment, I started thinking about this requirement set and thinking about how I could make something that required zero effort/steps to view it. The closest thing I could come up with was having my tickets displayed on my desktop. After a few minutes of googling based on that idea I found an awesome tool for Mac OS X called GeekTool. Among other things, GeekTool will run shell scripts/console applications for you on a set frequency and display their output to a defined section of your desktop. This was perfect in my opinion so I played with it for a few minutes and decide that I was going to use GeekTool.

Given the functionality of GeekTool all that was really left was to write shell scripts/console applications that output all of my tickets from the various ticket sources and I would have a very quick and functional solution to my issue. Hence, I got to writing and pumped out the following short little Ruby scripts, and one AppleScript script to provide output of all my tickets from the various sources.

The following is a ruby script that pulls all my tickets in from all of my various Lighthouse accounts and projects.

#!/usr/bin/env ruby
require 'rubygems'
require 'lighthouse-api'

include Lighthouse

accounts = ['domain one', 'domain two', 'domain three']
Lighthouse.token = 'your lighthouse All Accounts token'

accounts.each { |a|
  Lighthouse.account = a
  Project.find(:all).each { |p|
    if (!p.archived)
      ticks = p.tickets({:q => "responsible:me sort:priority state:open"})
      if (ticks.length > 0)
        puts p.name
        puts "-------------------------"
        puts "    id | pri | title"
        puts "-------------------------"
        ticks.each { |t|
          puts t.id.to_s.rjust(6) + " | " + t.priority.to_s.center(3) + " | " + t.title
        }
        puts "\n"
      end
    end
  }
}

The following is a ruby script that pulls all my tickets in from all of my various GitHub accounts and projects.

#!/usr/bin/env ruby

require 'rubygems'
require 'octopi'

include Octopi

creds = [
  { :login => "login one", :token => "API token tied to login one" },
  { :login => "login two", :token => "API token tied to login two" },
  { :login => "login three", :token => "API token tied to login three"}
]

creds.each { |cred|
  authenticated_with :login => cred[:login], :token => cred[:token] do
    user = User.find(cred[:login])
    repos = user.repositories
    repos.each { |r|
      ticks = Issue.find_all(:repository => r, :state => "open")
      if (ticks.length > 0)
        puts r.name
        puts "-------------------------"
        puts "    id | pri | title"
        puts "-------------------------"
        ticks.each { |t|
          puts "n/a".rjust(6) + " | " + t.votes.to_s.center(3) + " | " + t.title
        }
        puts "\n"
      end
    }
  end
}

The following is a AppleScript script that pulls all my tickets in from Things.

tell application "Things"
  set nl to "\n"
  set output to "Things Tasks in Today\n--------------------------\n"
  repeat with todayToDo in to dos of list "Today"
    set curTaskName to name of todayToDo
    set output to output & " - " & curTaskName & nl
  end repeat
end tell
output

The following is a Python script that pulls all my tickets in from Trac when your Trac environment has the Trac XML RPC plugin installed.

#!/usr/bin/env python

import xmlrpclib

username = "loginname"
password = "password"
port = None # if need to specify a port set this to the port number
host = "domain-name-where-trac-hosted" # trac.rippletv.com at my work
path = "/path-to-the-environment"

url = "https://%s:%s@%s" % (username, password, host) 
if (port):
    url += ":%s" % (str(port))
url += path + "/login/xmlrpc"

svr = xmlrpclib.ServerProxy(url)

print "-------------------------"
print "    id | pri | title"
print "-------------------------"

ticket_ids = svr.ticket.query("owner=" + username + "&status!=closed&order=priority")
for ti in ticket_ids:
  cur_tick = svr.ticket.get(ti)
  cur_tick_hash = cur_tick[3]
  cur_id = ti
  cur_summary = cur_tick_hash['summary']
  cur_priority = cur_tick_hash['priority']
  pri_num = 0
  if (cur_priority == "trivial"):
    pri_num = 0
  elif (cur_priority == "minor"):
    pri_num = 1
  elif (cur_priority == "major"):
    pri_num = 2
  elif (cur_priority == "critical"):
    pri_num = 3
  elif (cur_priority == "blocker"):
    pri_num = 4
  print str(cur_id).rjust(6) +  " | " + str(pri_num).center(3) + " | " + str(cur_summary)

After coding the above scripts I simply set them up through the GeekTool UI and like magic within 15 mins or so I had a working solution to my issue, thanks to the power of REST based Web Services, Ruby, the Ruby Community, and Things AppleScript integration. Checkout a screenshot here.

jQuery Comparative Histogram Plugin

by Andrew De Ponte (@cyphactor)

I recently wrote a jQuery Plugin that I am calling jquery_comphist. It is a jQuery Plugin that draws a Comparative Histogram of a provided population divided into two major groups with any number of shared sub-groups. One of the most common uses for such a feature is when you are trying to display demographics data on some population. Anyways, as usual the code is available at my GitHub page here and you can see a demo of it below.

 

With the jQuery Comparative Histogram (CompHist) Plugin you can easily represent populations and information about them. A prime usage exampe of this is demographics. All the styling is done via CSS. Hence the style is easily modified. It does the calculations for you and it allows for non listed group counts via a non_demo_count data option.

The above demo was produced by defining a few code snippets. The first snippet is a snippet of HTML that includes the jQuery Comparative Histogram javascript source file and CSS style sheet. Note: The jQuery Comparative Histogram javascript source file needs to come after the standard jQuery javascript source file. An example of this snippet is as follows:

<script type="text/javascript" src="../jquery.comphist.js"></script>
<link rel="stylesheet" type="text/css" href="../stylesheets/jquery.comphist.css">

Note: In the above snippet the href values are likely to be different in your case. The second code snippet is simply a single line of HTML where the div that is to be the Comparative Histogram. It is key that this div has an id that is easily referenced and a set height and width. An example of this snippet is as follows:

<div id="compplaceholder" style="width: 375px; height: 200px;"></div>

The third code snippet needed is the javascript that defines the data, creates the Comparative Histogram in the specified div, and handles the hover functionality. An example of this is seen below.

<script type="text/javascript">
$(function () {
  function showCompHistTooltip(x, y, contents) {
    console.log("called my shit");
    $('<div id="comphist1tooltip">' + contents + '</div>').css({
      position: 'absolute',
      display: 'none',
      top: y - 20,
      left: x - 30,
      border: '1px solid #fdd',
      padding: '2px',
      'background-color': '#fee',
      opacity: 1
    }).appendTo("body").fadeIn(200);
  }

  var comphist_data = {
    population_label: 'Active Fans This Week',
    group_1_label: 'Male', group_2_label: 'Female',
    subgroups: [
    { label: '13-17', group_1_count: 3, group_2_count: 16 },
    { label: '18-24', group_1_count: 7, group_2_count: 27 },
    { label: '25-34', group_1_count: 3, group_2_count: 29 },
    { label: '35-44', group_1_count: 2, group_2_count: 9 },
    { label: '45-54', group_1_count: 0, group_2_count: 4 },
    { label: '55+', group_1_count: 0, group_2_count: 0 }
    ],
    non_demo_count: 0
  };
  $("#compplaceholder").comphist({}, comphist_data);

  $("#compplaceholder").bind("barover", function (e, perc, pos) {
    $("#comphist1tooltip").remove();
    showCompHistTooltip(pos.left, pos.top, perc);
  });

  $("#compplaceholder").bind("barout", function (e, perc, pos) {
    $("#comphist1tooltip").remove();
  });
});
</script>

Hopefully, the demo and quick code example helps get you up and running quickly.

Flot Multi-series Bar Graph Support

by Andrew De Ponte (@cyphactor)

Hey boys and girls. I just got finished coding support for Multi-series bar graphs into Flot (a jQuery based JavaScript graphing library). Hence, I figured I would share not only the code but a little preview of it below. The code for it can be found at my GitHub account here. Please enjoy the little demo below.

 

Mouse hovers at (0, 0).

With the multi-series bar graph support, you can have Flot display the series side by side. This is useful when you are interested in visually comparing series and grouping segments you want to columns in series that you are specifically interested in comparing.

The above demo was produced by defining a few code snippets. The first snippet is a snippet of HTML that includes the customized Flot javascript source file. Note: The Flot javascript source file needs to come after the standard jQuery javascript source file. An example of this snippet is as follows:

<!--[if IE]><script language="javascript" type="text/javascript" src="../excanvas.min.js"></script><![endif]-->
<script language="javascript" type="text/javascript" src="../jquery.js"></script>
<script language="javascript" type="text/javascript" src="../jquery.flot.js"></script>

Note: In the above snippet the href values are likely to be different in your case. The second code snippet is simply a single line of HTML that is the div that is to be the Multi-series Bar Graph. It is key that this div has an id that is easily referenced and a set height and width. An example of this snippet is as follows:

<div id="placeholder" style="width: 375px; height: 200px;"></div>

The third code snippet needed is the javascript that defines the data, creates the Multi-series Bar Graph in the specified div, and handles the hover functionality. An example of this is seen below.

<script id="source">
$(function () {
  var ms_data = [{"label":"FOO","data":[[0,80],[1,70],[2,100],[3,60],[4,102]]},
                 {"label":"BAR","data":[[0,10],[1,20],[2,30],[3,40],[4,80]]},
                 {"label":"CAR","data":[[0,5],[1,10],[2,15],[3,20],[4,25]]}]
  var ms_ticks = [[0,"1/28"],[1,"1/29"],[2,"1/30"],[3,"1/31"],[4,"1/32"]];

    function plotWithOptions() {
      $.plot($("#placeholder"), ms_data, {
        bars: { show: true, barWidth: 0.6, series_spread: true, align: "center" },
        xaxis: { ticks: ms_ticks, autoscaleMargin: .10 },
        grid: { hoverable: true, clickable: true }
      });
    }

    function showTooltip(x, y, contents) {
        $('').css( {
            position: 'absolute',
            display: 'none',
            top: y + 5,
            left: x + 5,
            border: '1px solid #fdd',
            padding: '2px',
            'background-color': '#fee',
            opacity: 0.80
        }).appendTo("body").show();
    }

    plotWithOptions();

    $("#placeholder").bind("plothover", function (event, pos, item) {
      $("#x").text(pos.x.toFixed(2));
      $("#y").text(pos.y.toFixed(2));
        if (item) {
            if (previousPoint != item.datapoint) {
                previousPoint = item.datapoint;

                $("#tooltip").remove();
                var x = item.datapoint[0].toFixed(2),
                    y = item.datapoint[1].toFixed(2);

                showTooltip(item.pageX, item.pageY,
                            item.series.label + " Group id: " + Math.floor(x) + ", y = " + y + ", seriesIndex: " + item.seriesIndex);
            }
        }
        else {
            $("#tooltip").remove();
            previousPoint = null;            
        }
    });

    $("#placeholder").bind("plotclick", function (event, pos, item) {
        if (item) {
            $("#clickdata").text("You clicked bar " + item.dataIndex + " in " + item.series.label + ".");
        }
    });
});
</script>

Hopefully, the demo and quick code example helps get you up and running.