Python Line Continuations

Using TextMate, it is very easy to get snippets and commands to do things that you often do. However, the python bundle is a bit lacking, and this is a great opportunity to improve that.

I’ve created a Command that will enter a newline, and if not inside a list, function call, dictionary or multi-line string, automatically add a trailing .

I’ve hooked it in to the Enter key, and the other settings can be seen in the screenshot below:

The actual code follows:

 1#!/usr/bin/env ruby
 3scope = ENV['TM_SCOPE'].split
 5no_trail = ['punctuation.definition.arguments.end.python',
 6            'meta.structure.list.python',
 7            'meta.structure.dictionary.python',
 8            'string.quoted.single.block.python',
 9            'string.quoted.double.block.python']
11print (scope & no_trail) == [] ? "\\n" : "\n"

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.


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#! /usr/bin/ruby
 3# A ruby class for sending notifications to Prowl.
 5require 'uri'
 6require 'net/http'
 7require 'net/https'
 9class String
10  def urlencode
11    gsub( /[^a-zA-Z0-9\-_\.!~*'()]/n ) {|x| sprintf('%%%02x', x[0]) }
12  end
15class Hash
16  def urlencode
17    collect { |k,v| "#{k.to_s.urlencode}=#{v.to_s.urlencode}" }.join('&')
18  end
21class Prowler
22  def initialize user, pass
23    @url = URI.parse('')
24    @username = user
25    @password = pass
27    @http =, @url.port)
28    @http.use_ssl = true
29  end
31  def send_notification app, evt, desc
34    options = {
35      'application' => app,
36      'event' => evt,
37      'description' => desc
38    }
40    req ="#{@url.path}?#{options.urlencode}")
41    req.basic_auth @username, @password
42    @http.request(req)
43  end
47# How to use?
48# p ='username', 'password')
49# p.send_notification('App','Event','Desc')

Scheme line "values"

Years ago, when I first saw TextMate demonstrated, one of the ways it was used as a teaching tool, when teaching Ruby, was to have the current line executed, and the value it returned appended to the current line:

(2 + 3) * 4 / 5 # => 4

That is, pressing Cmd-Shift-Ctrl-E would execute the line, and update the marker.

Today, while playing around with Scheme, I came up with a neat way to do the same type of thing.

Initially, I made it so that it executed the current line, and added/updated the marker. Then, I realised I could load the file, and then execute the current line.

You can create a new bundle command, and bind it to whatever key you want, with a scope selector of source.scheme, Input of Line, Output of Replace Input.

#!/usr/bin/env bash

[[ -f "${TM_SUPPORT_PATH}/lib/" ]] && . "${TM_SUPPORT_PATH}/lib/"

# Evaluate the current line in our Scheme interpreter
# The interpreter you use should be set in the environment
# variable TM_SCHEME

# The whole file will be loaded, and the current line's value executed,
# and added to the line as a comment.

CMD=$(basename "$INTERPRET")

LINE=`cat /dev/stdin | sed 's/; =>.*//'`
VALUE=`echo $LINE | $INTERPRET --load $TM_FILEPATH | grep ';Value: ' | sed 's/;Value: //'`

echo -n $LINE "; =>" $VALUE

Unfortunately, trailing comments are handled as a seperate line, so getting the ruby-like behaviour of updating all of the ; => comments will have to wait for another day.