[TxMt] Re: Range of selection string / environment variable TM_SELECTION

Kai Wood lists at kwood.eu
Thu Jan 16 16:31:00 UTC 2014


On 16.01.2014, at 17:07, Kai Wood <lists at kwood.eu> wrote:

> On 16.01.2014, at 16:38, Allan Odgaard <mailinglist at textmate.org> wrote:
> 
>> On 16 Jan 2014, at 21:42, Kai Wood wrote:
>> 
>>> I need the first and last line number in a range of lines where either a blinking cursor or a selection appears in the document. Only visible selections count.
>> 
>> Here is a ruby function that parses the selection string syntax and maps it to a “first, last” line that is rendered selected:
>> 
>>    def parse_selection_string(str)
>>      str.split('&').map do |range|
>>        if range =~ /(\d+)(?::(\d+))?(?:\+\d+)?(?:([-x])(\d+)(?::(\d+))?(?:\+\d+)?)?/
>>          l1, l2, c1, c2 = $1.to_i, ($4 ? $4.to_i : nil), ($2 || 1).to_i, ($5 || 1).to_i
>>          l1, l2, c1, c2 = l2, l1, c2, c1 if l2 && (l1 > l2 || l1 == l2 && c2 > c1)
>> 
>>          case $3
>>            when 'x'
>>              [ l1, l2 ]
>>            when '-'
>>              l2 -= 1 if c2 == 1
>>              [ l1, l2 ]
>>            else
>>              [ l1, l1 ]
>>          end
>>        else
>>          abort "unsupported selection string syntax: ‘#{range}’"
>>        end
>>      end
>>    end
>> 
>> You may want to post-process the result to merge overlapping ranges.
> 
> I hope this will not cost you a sleepless night, because…
> 
> <Screen Shot 2014-01-16 at 16.58.53.png>
> 
> Result: [[18, 22], [4, 3], [11, 11]] (Lowest value: 3, one less on the minimum side)
> 
> But a very nice try anyway, thanks!

The solution i came up with, would be this:

def parse_selection_for_visible_lines(selection_string)
  selected_lines = selection_string.split(/[&x-]/).map { |e| e.split(/[:+]/).first.to_i }
  selected_range = [selected_lines.min, selected_lines.max]
  
  if (selection_string.split("&").map { |e| (e.match(/.*-(\d*)$/) ? $1 : nil ) } - [nil]).max.to_i == selected_range.last
    selected_range[1] -= 1
  end

  selected_range
end

It’s ugly and it doesn’t even try to parse the selection string as a whole, like yours. It somehow works, because the only case where there is 1 additional line at the end of the document occurs, if a block of cursors separated by “&” with normal_range separator “-" WITHOUT position “:” at the end is found (Something like "23:3-24”) - but only if this block is at the end of the range. (I’m not even sure I can explain this correctly :) )





More information about the textmate mailing list