samhuri.net/posts/2006/02/textmate-insert-text-into-self-down.md
Sami Samhuri 007b1058b6
Migrate from Swift to Ruby (#33)
Replace the Swift site generator with a Ruby and Phlex implementation.
Loads site and projects from TOML, derive site metadata from posts.

Migrate from make to bake and add standardrb and code coverage tasks.

Update CI and docs to match the new workflow, and remove unused
assets/dependencies plus obsolete tooling.
2026-02-07 21:19:03 -08:00

2.7 KiB

Title Author Date Timestamp Tags
TextMate: Insert text into self.down Sami Samhuri 21st February, 2006 2006-02-21T14:55:00-08:00 textmate, rails, hacking, commands, macro, rails, snippets, textmate

UPDATE: I got everything working and it's all packaged up here. There's an installation script this time as well.

Thanks to a helpful thread on the TextMate mailing list I have the beginning of a solution to insert text at 2 (or more) locations in a file.

I implemented this for a new snippet I was working on for migrations, rename_column. Since the command is the same in self.up and self.down simply doing a reverse search for rename_column in my hackish macro didn't return the cursor the desired location.

That's enough introduction, here's the program to do the insertion:

#!/usr/bin/env ruby
def indent(s)
  s =~ /^(\s*)/
  ' ' * $1.length
end

up_line = 'rename_column "${1:table}", "${2:column}", "${3:new_name}"$0'
down_line = "rename_column \"$$1\", \"$$3\", \"$$2\"\n"

# find the end of self.down and insert 2nd line
lines = STDIN.read.to_a.reverse
ends_seen = 0
lines.each_with_index do |line, i|
  ends_seen += 1    if line =~ /^\s*end\b/
  if ends_seen == 2
    lines[i..i] = [lines[i], indent(lines[i]) * 2 + down_line]
    break
  end
end

# return the new text, escaping special chars
print up_line + lines.reverse.to_s.gsub(/([$`\\])/, '\\\\\1').gsub(/\$\$/, '$')

Save this as a command in your Rails, or syncPeople on Rails, bundle. The command options should be as follows:

  • Save: Nothing
  • Input: Selected Text or Nothing
  • Output: Insert as Snippet
  • Activation: Whatever you want, I'm going to use a macro described below and leave this empty
  • Scope Selector: source.ruby.rails

The first modification it needs is to get the lines to insert as command line arguments so we can use it for other snippets. Secondly, regardless of the Re-indent pasted text setting the text returned is indented incorrectly.

The macro I'm thinking of to invoke this is tab-triggered and will simply:

  • Select word (⌃W)
  • Delete ()
  • Select to end of file (⇧⌘↓)
  • Run command "Put in self.down"