Skip to content

Commit

Permalink
A first pass at a much smarter block toggling command. It's now able …
Browse files Browse the repository at this point in the history
…to cope with scenarios like braces inside a String literal and it properly handles some nesting. This restores the command to working order after it broke due to an Oniguruma update in the last TextMate update.
  • Loading branch information
JEG2 committed Nov 29, 2009
1 parent 52e21e9 commit ba45106
Show file tree
Hide file tree
Showing 4 changed files with 153 additions and 159 deletions.
150 changes: 150 additions & 0 deletions Commands/Toggle ‘do … end’ : ‘{ … }’.tmCommand
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>beforeRunningCommand</key>
<string>nop</string>
<key>command</key>
<string>#!/usr/bin/env ruby -wKU
# encoding: UTF-8
require "rexml/text"
require "#{ENV["TM_SUPPORT_PATH"]}/lib/escape"
# transform XML into normal and sanitized Ruby
ruby, safe_ruby, scope = "", "", []
STDIN.read.scan(/&lt;(.*?)&gt;|([^&lt;]+)/) do
if $1
if $1[0] == ?/
scope.pop
else
scope.push($1)
end
else
unescaped = REXML::Text.unnormalize($2)
ruby &lt;&lt; unescaped
# strip strings, regexes, and comments from safe_ruby but leave byte count
if scope.any? { |s| s =~ /\A(?:string|comment)\b/ }
safe_ruby &lt;&lt; " " * unescaped.length
else
safe_ruby &lt;&lt; unescaped
end
end
end
# find and mark the cursor
line_number = ENV["TM_LINE_NUMBER"].to_i
input_start_line = ENV["TM_INPUT_START_LINE"].to_i
row = line_number - input_start_line
col = ENV["TM_LINE_INDEX"].to_i
if line_number == input_start_line
col -= ENV["TM_INPUT_START_LINE_INDEX"].to_i
end
cursor = ruby[/\A(?:.*\n){#{row - 1}}.{#{col}}/].size
CURSOR = [0xFFFC].pack("U")
B = "(?:\\b|#{CURSOR})" # Note: /\w/u includes CURSOR
ruby[cursor, 0] = CURSOR
safe_ruby[cursor, 0] = CURSOR
# find the block nearest to the cursor
block_start, block_length = nil, nil
loop do
block_start = safe_ruby.rindex( /(\{|#{B}do#{B})/,
block_start.nil? ? cursor : block_start - 1 )
if block_start.nil? # block not found: give up and don't change the document
print e_sn(ruby).sub(CURSOR, "$0")
exit
end
block_length, nesting = 0, []
if $1 == "{"
re, starts, stop = /\{|\}|[^{}]+/, ["{"], "}"
else
re, starts, stop = /#{B}do#{B}|#{B}end#{B}|./m, ["do"], "end"
end
safe_ruby[block_start..-1].scan(re) do |token|
block_length += token.length
token.sub!(/\A#{CURSOR}/, "")
token.sub!(/#{CURSOR}\z/, "")
case token
when *starts
nesting &lt;&lt; token
when stop
if nesting.last.nil?
nesting &lt;&lt; nil
break
else
nesting.pop
break if nesting.empty?
end
end
end
break if nesting.empty? and ruby[block_start, block_length].include? CURSOR
end
block = ruby[block_start, block_length]
# toggle the block
if block[0] == ?{
block = block[1..-2]
if block.include? "\n"
block[0, 0] = " " if block =~ /\A#{CURSOR}?[A-Za-z0-9_]/
block &lt;&lt; " " if block =~ /[A-Za-z0-9_]#{CURSOR}?\z/
block = "do#{block}end"
else # expand the block
block.strip!
lines = %w[do]
if block.sub!(/\A(#{CURSOR}?(\s*)\|[^|]*\|)/, "")
lines.first &lt;&lt; "#{' ' if $2.empty?}#{$1}"
end
indent = ruby[0...block_start][/^([ \t]*).*\Z/, 1]
tab = ( ENV["TM_SOFT_TABS"] == "YES" ? " " * ENV["TM_TAB_SIZE"].to_i :
"\t" )
lines &lt;&lt; "#{indent}#{tab}#{block.strip}"
lines &lt;&lt; "#{indent}end"
block = lines.join("\n")
end
else
block = block[2..-4]
if block.include? "\n" # collapse the block
lines = block.send(block.respond_to?(:lines) ? :lines : :to_s).to_a
lines.first.send(
"#{'r' if lines.first =~ /\A\s*#{CURSOR}?\s*\|[^|]*\|/}strip!"
)
lines[1..-1].each do |line|
line.strip!
end
lines.first &lt;&lt; "; " unless lines.first =~
/\A\s*#{CURSOR}?\s*(?:\|[^|]*\|)?\s*#{CURSOR}?\z/
lines.first &lt;&lt; " " unless lines.first =~ /\s\z/
lines[1..-2].each do |line|
line &lt;&lt; "; "
end
lines[-2].sub!(/; \z/, "") if lines.size &gt; 2 and lines.last.empty?
cursor_by_end = lines.size &gt; 2 &amp;&amp; lines.last == CURSOR
lines[-2].sub!(/; \z/, " ") if cursor_by_end
block = "{#{lines.join}#{' ' unless cursor_by_end}}"
else
block = "{#{block}}"
end
end
# replace document
print e_sn(ruby[0...block_start])
print e_sn(block).sub(CURSOR, "$0")
print e_sn(ruby[(block_start + block_length)..-1])
</string>
<key>input</key>
<string>selection</string>
<key>inputFormat</key>
<string>xml</string>
<key>keyEquivalent</key>
<string>^{</string>
<key>name</key>
<string>Toggle ‘do … end’ / ‘{ … }’</string>
<key>output</key>
<string>insertAsSnippet</string>
<key>scope</key>
<string>source.ruby</string>
<key>uuid</key>
<string>59E811FF-E722-46BE-8938-04713612FABB</string>
</dict>
</plist>
63 changes: 0 additions & 63 deletions Macros/Toggle Single : Multi Line Block.plist

This file was deleted.

94 changes: 0 additions & 94 deletions Support/bin/toggle_block.rb

This file was deleted.

5 changes: 3 additions & 2 deletions info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
<string>66708259-62C3-11D9-B8CF-000D93589AF6</string>
<string>66708052-62C3-11D9-B8CF-000D93589AF6</string>
<string>6670881E-62C3-11D9-B8CF-000D93589AF6</string>
<string>7990EE60-C850-4779-A8C0-7FD2C853B99B</string>
</array>
<key>description</key>
<string>Support for the &lt;a href="http://www.ruby-lang.org/"&gt;Ruby&lt;/a&gt; programming language.</string>
Expand Down Expand Up @@ -290,7 +291,7 @@
<dict>
<key>items</key>
<array>
<string>7990EE60-C850-4779-A8C0-7FD2C853B99B</string>
<string>59E811FF-E722-46BE-8938-04713612FABB</string>
<string>------------------------------------</string>
<string>855FC4EF-7B1E-48EE-AD4E-5ECB8ED79D1C</string>
<string>4B72C5C3-6CA7-41AC-B2F9-51DEA25D469E</string>
Expand Down Expand Up @@ -442,12 +443,12 @@
<string>B297E4B8-A8FF-49CE-B9C4-6D4911724D43</string>
<string>835FAAC6-5431-436C-998B-241F7226B99B</string>
<string>0275EF39-9357-408F-AF20-79E415CA9504</string>
<string>59E811FF-E722-46BE-8938-04713612FABB</string>
<string>97054C4D-E4A3-45B1-9C00-B82DBCB30CAD</string>
<string>569C9822-8C41-4907-94C7-1A8A0031B66D</string>
<string>6519CB08-8326-4B77-A251-54722FFBFC1F</string>
<string>47D203ED-EB9B-4653-A07B-A897800CEB76</string>
<string>C122CD92-DDBE-4869-9C7A-CC2B254C9411</string>
<string>7990EE60-C850-4779-A8C0-7FD2C853B99B</string>
<string>121B334B-2AA6-4E9A-A8B8-BF93B627982B</string>
<string>58FDEA60-10AF-4C49-AA09-29B77030DB25</string>
<string>33969819-62C5-4E03-B824-C2337205F364</string>
Expand Down

0 comments on commit ba45106

Please sign in to comment.