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/bash_init.sh" ]] && . "${TM_SUPPORT_PATH}/lib/bash_init.sh"

# 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.

INTERPRET=${TM_SCHEME}
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.

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

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.

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
 2 
 3 scope = ENV['TM_SCOPE'].split
 4 
 5 no_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']
10 
11 print (scope & no_trail) == [] ? "\\n" : "\n"