Prowl

Prowl is awesome. Growl notifications can be forwarded to your iPhone.

But you can get notifications from anywhere. A Perl script is included, but that didn’t work on my server. So I wrote one in Ruby:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
#! /usr/bin/ruby

# A ruby class for sending notifications to Prowl.

require 'uri'
require 'net/http'
require 'net/https'

class String
  def urlencode
    gsub( /[^a-zA-Z0-9\-_\.!~*'()]/n ) {|x| sprintf('%%%02x', x[0]) }
  end
end

class Hash
  def urlencode
    collect { |k,v| "#{k.to_s.urlencode}=#{v.to_s.urlencode}" }.join('&')
  end
end

class Prowler
  def initialize user, pass
    @url = URI.parse('https://prowl.weks.net/api/add_notification.php')
    @username = user
    @password = pass
    
    @http = Net::HTTP.new(@url.host, @url.port)
    @http.use_ssl = true
  end

  def send_notification app, evt, desc
    

    options = {
      'application' => app,
      'event' => evt,
      'description' => desc
    }
    
    req = Net::HTTP::Get.new("#{@url.path}?#{options.urlencode}")
    req.basic_auth @username, @password
    @http.request(req)
  end

end

# How to use?
# p = Prowler.new('username', 'password')
# p.send_notification('App','Event','Desc')

Logos

Started up a new iPhone app today. The logo at the bottom of the screen looked a bit familiar:

Here is the logo from the Adelaide City Council (which has been in use for about 7 years):

Wonder which came first…

If I overlay one one the other, we see they are not identical:

]

Fix Redmine not showing repository data

For some time, the git repository I am using to track changes for my Django-Management TextMate bundle was not working correctly in Redmine. I was able to connect it up using the settings, but was getting errors about the files not being found.

It turns out that git was not in my path. Putting a link from /usr/local/bin/git to /usr/bin/git fixed that all up.

TextMate return codes

From the TextMate manual:

These functions only work when the initial output option is not set as “Show as HTML”. The list of functions is as follows:

  • exit_discard
  • exit_replace_text
  • exit_replace_document
  • exit_insert_text
  • exit_insert_snippet
  • exit_show_html
  • exit_show_tool_tip
  • exit_create_new_document  

This is all well and good, but what about when you are in another language?

Simple. Just ensure your exit code matches. The values start at 200, for exit_discard, and 205 is exit_show_html.

This is probably not the best way to do it, as these may change in the future. But, I couldn’t think of another way, at least not offline.

Reasons PHP sucks #753

Another good example of a PHP “quirk” is the way PHP handles constants. It was one of the major factors affecting performance. Just removing all the constants allowed us to improve the performance by almost 2x (we left one constant to be precise).

From The Need for Speed.

That’s right - PHP is up to 2X faster if you don’t use constants. You know, that means hardcode values in…

Patch for Mercurial.tmbundle

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
diff -r 5e13047a2284 Support/hg_commit.rb
    --- a/Support/hg_commit.rb	Mon Apr 27 11:38:15 2009 +0930
    +++ b/Support/hg_commit.rb	Mon Apr 27 11:39:00 2009 +0930
    @@ -79,7 +79,7 @@
       commit_paths_array = matches_to_paths(commit_matches)
       commit_status = matches_to_status(commit_matches).join(":")
       commit_path_text = commit_paths_array.collect{|path| path.quote_filename_for_shell }.join(" ")
    -  commit_args = %x{"#{commit_tool}" --status #{commit_status} #{commit_path_text} }
    +  commit_args = %x{"#{commit_tool}" --diff-cmd hg,diff --status #{commit_status} #{commit_path_text} }
     
       status = $CHILD_STATUS
       if status != 0
    

SWI-Prolog Bundle

I’ve cloned and updated the included Prolog bundle to use my Run script.

This can be found at GitHub: SWI-Prolog.tmbundle.

Run Prolog Program

In the continuing effort to do ‘productive’ tasks, but not actually the project I am supposed to be working on, I present a TextMate command to run the current prolog file, with nice HTML output, and input via a dialog box.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
    #! /usr/bin/env ruby
    
    require ENV["TM_SUPPORT_PATH"] + "/lib/tm/executor"
    
    command = [ENV["TM_PROLOG"] || "swipl", "-s", ENV["TM_FILEPATH"]]
    two_line = false
    
    welcome = /^(Welcome to SWI-Prolog)|(Copyright )|(SWI-Prolog comes with)|(and you are welcome)|(Please visit)|(For help, use)/
    
    TextMate::Executor.run(command) do |str, type|
      if type == :err
        if two_line
          two_line = false
          # this line is part of the previous message
          "#{str}</div>"
        # Is this a warning line?
        elsif str =~ /(Warning):\s(.*):(\d+):/
          warn, file, line = $1, $2, $3
          filename = file.split('/')[-1]
          two_line = true
          file_link = "<a class=\"near\" href=\"txmt://open?line=#{line}&url=file://#{file}\">#{filename}</a>"
          "<div class=\"#{warn}\">#{warn}: #{file_link}, line #{line}:"
        elsif str =~ /(ERROR):\s(.*):(\d+):(\d+):\s(.*)/
          file, line, char, message = $2, $3, $4, $5
          filename = file.split('/')[-1]
          file_link = "<a class=\"near\" href=\"txmt://open?line=#{line}&column=#{char}&url=file://#{file}\">#{filename}</a>"
          "<div class=\"err\">ERROR: #{file_link}, line #{line}, col #{char}: #{message}</div>"
        elsif str =~ /ERROR:\s(.*)/
          message = $1
          "<div class=\"test fail\">ERROR: #{message}</div>"
        elsif str =~ /%\s(.*)\scompiled\s(.*)\ssec,\s(.*)\sbytes/
          file, time, length = $1, $2, $3
          filename = file.split('/')[-1]
          file_link = "<a class=\"near\" href=\"txmt://open?url=file://#{file}\">#{filename}</a>"
          "<div class=\"test ok\"> #{file_link} (#{length} bytes) compiled in #{time} sec.</div>"
        elsif str =~ welcome
          "<span class=\"copyright\" style=\"font-size:xx-small;\">#{str}</span> "
        else
          "<div class=\"output\">#{str}</div>"
        end
      else
        "<div class=\"output\">#{str}</div>"
      end
    end

Run Django Tests from TextMate

It would be cool to be able to run my Django tests from within TextMate.

Update: this version will run just the tests from the active file, if there are any. Otherwise, it runs all of the tests in the whole project.

Here is a Command to do just that:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
    #! /usr/bin/env ruby
    
    command = [ENV["TM_PYTHON"] || "python", "-u", "#{ENV['TM_PROJECT_DIRECTORY']}/manage.py", "test", "--noinput"]
    
    File.open(ENV['TM_FILEPATH']) do |f|
      f.readlines.each do |line|
        if line =~ /class (.*)\(.*TestCase\):/
          test_case = $1
          app_name = ENV['TM_FILEPATH'].split(ENV['TM_PROJECT_DIRECTORY'])[1].split('/')[1]
          test_name = "#{app_name}.#{test_case}"
          command << test_name
        end
      end
    end
    
    require ENV["TM_SUPPORT_PATH"] + "/lib/tm/executor"
    
    ENV["PYTHONPATH"] = ENV["TM_BUNDLE_SUPPORT"] + (ENV.has_key?("PYTHONPATH") ? ":" + ENV["PYTHONPATH"] : "")
    
    TextMate::Executor.run(command) do |str, type|
      if type == :err
        if str =~ /\A[\.EF]*\Z/
          str.gsub!(/(\.)/, "<span class=\"test ok\">\\1</span>")
          str.gsub!(/(E|F)/, "<span class=\"test fail\">\\1</span>")
          str + "<br/>\n"
        elsif str =~ /\A(FAILED.*)\Z/
          "<div class=\"test fail\">#{htmlize $1}</div>\n"
        elsif str =~ /\A(OK.*)\Z/
          "<div class=\"test ok\">#{htmlize $1}</div>\n"
        elsif str =~ /^(\s+)File "(.+)", line (\d+), in (.*)/
          indent = $1
          file   = $2
          line   = $3
          method = $4
          indent += " " if file.sub!(/^\"(.*)\"/,"\1")
          url = "&url=file://" + e_url(file)
          display_name = file.split('/').last 
          "#{htmlize(indent)}<a class=\"near\" href=\"txmt://open?line=#{line + url}\">" +
            (method ? "method #{method}" : "<em>at top level</em>") +
            "</a> in <strong>#{display_name}</strong> at line #{line}<br/>\n"
        end
      end
    end

Flaky Internet at 8:21pm

I seem to recall my internet going down, and then coming back up, at around the same time every night.

Tonight it flaked at 8:21pm.