[TxMt] improvement suggestion for "comment line/selection"

James Edward Gray II james at grayproductions.net
Tue Dec 5 02:54:47 UTC 2006


On Dec 4, 2006, at 4:55 PM, Thomas Krajacic wrote:

> mmhmm, could you tell me how to fix it manually maybe. I don't want  
> to mess with subversion.

Navigate to the command in the bundle editor, switch output to Insert  
as Snippet, and change the command content to the code below.

I agree with Jacob though, it's probably time to have a checkout if  
you don't want to wait 10 weeks for a new update.

James Edward Gray II

#!/usr/bin/env ruby

require "#{ENV["TM_SUPPORT_PATH"]}/lib/escape"

def out(*args)
   print( *args.map do |arg|
     escaped = e_sn(arg)
     $selected ? escaped.gsub("}", "\\}") : escaped
   end )
end

# by James Edward Gray II <james (at) grayproductions.net>

# find all available comment variables
var_suffixes = [""]
2.upto(1.0/0.0) do |n|
   if ENV.include? "TM_COMMENT_START_#{n}"
     var_suffixes << "_#{n}"
   else
     break
   end
end

text    = STDIN.read
default = nil  # the comment we will insert, if none are removed

# maintain selection
if text == ENV["TM_SELECTED_TEXT"]
   $selected = true
   print "${0:"
   at_exit { print "}" }
else
   $selected = false
end

# try a removal for each comment...
var_suffixes.each do |suffix|
   # build comment
   com = { :start     => ENV["TM_COMMENT_START#{suffix}"] || "# ",
           :end       => ENV["TM_COMMENT_END#{suffix}"]   || "",
           :mode      => ENV["TM_COMMENT_MODE#{suffix}"]  || (ENV 
["TM_COMMENT_END#{suffix}"] ? "block" : "line"),
           :no_indent => ENV["TM_COMMENT_DISABLE_INDENT#{suffix}"] }

   com[:esc_start], com[:esc_end] = [com[:start], com[:end]].map do | 
str|
     str.gsub(/[\\|()\[\].?*+{}^$]/, '\\\\\&').
         gsub(/\A\s+|\s+\z/, '(?:\&)?')
   end

   # save the first one as our insertion default
   default = com if default.nil?

   # try a removal
   case com[:mode]
   when "line"  # line by line comment
     if text != "" && text.map { |l| !!(l =~ /\A\s*(#{com 
[:esc_start]}|$)/) }.
                           uniq == [true]
       out text.gsub( /^(\s*)#{com[:esc_start]}(.*)#{com[:esc_end]} 
(\s*)$/,
                      '\1\2\3' )
       exit
     end
   when "block" # block comment
     regex = /\A(\s*)#{com[:esc_start]}(.*?)#{com[:esc_end]}(\s*)\z/m
     if text =~ regex
       out text.sub(regex, '\1\2\3')
       exit
     end
   end
end

# none of our removals worked, so preform an insert (minding indent  
setting)
case default[:mode]
when "line"  # apply comment line by line
   if default[:no_indent] || text.empty?
     out text.gsub(/^.*$/, "#{default[:start]}\\&#{default[:end]}")
   else
     indent = text.scan(/^[\t ]*(?=\S)/).min { |lhs, rhs| lhs.length  
<=> rhs.length } || ""
     text.map do |line|
       if line =~ /^(#{indent})(.*)$(\n?)/ then
         out $1 + default[:start] + $2 + default[:end] + $3
       elsif line =~ /^(.*)$(\n?)/ then
         out indent + default[:start] + $1 + default[:end] + $2
       end
     end
   end
when "block" # apply comment around selection
   if text =~ /\A[ \t]*\z/
     out default[:start], text
     print "${0}"
     out default[:end]
   elsif default[:no_indent]
     out default[:start], text, default[:end]
   else
     lines = text.to_a
     if lines.empty?
       out default[:start], default[:end]
     else
       lines[-1].sub!(/^(.*)$/, "\\1#{default[:end]}")
       out lines.shift.sub(/^(\s*)(.*)$/, "\\1#{default[:start]}\\2")
       out *lines unless lines.empty?
     end
   end
end




More information about the textmate mailing list