'Parse out the leading Ruby expression and return a CITDL
expression for it.
We parse out the Ruby expression preceding the given position
(typically a calltip/autocomplete trigger position), simplify the
expression (by removing whitespace, etc.) and translate that to an
appropriate CITDL (*) expression. Returns None if there is no
appropriate such expression.
Optimization Notes:
- We can throw out Ruby expressions with function calls
because CodeIntel does not currently handle return values.
- Abort at hash and list indexing: the types of elements in these
objects are not tracked by CodeIntel.
- Currently we don\'t really make use of the styling info because we
abort at indexing, function call arguments, etc. where recognizing
string/number/regex boundaries would be useful. This info might be
useful later if this algorithm is beefed up.
Examples:
GIVEN                                   CITDL EXPR
send(<|>                                send
foo.instance_of?(<|>                    foo.instance_of?
File.open(<|>                           File.open
Zlib::Deflate.deflate(<|>               Zlib::Deflate.deflate
@assigned.<|>                           @assigned
@@foo.<|>                               @foo
$blah.<|>                               @blah
YAML::PRIVATE_TYPES[r].call(<|>         <punt because of []>
[$2].pack(<|>                           <punt>
@db_class::<|>WidgetClassName           <punt: looks to be rare>
0.<|>                                   Fixnum
\'...\'.<|>  "...".<|>                    String
[].step(<|>                             Array.step
{}.step(<|>                             Hash.step
* http://specs.tl.activestate.com/kd/kd-0100.html#citdl'

def citdl_expr_from_trg(self, buf, trg):

    DEBUG = False
    pos = trg.pos
    styleClassifier = ((isinstance(buf, UDLBuffer) and _UDLStyleClassifier) or _RubyStyleClassifier)(buf)
    accessor = buf.accessor
    last_pos = (pos - 1)
    buflen = accessor.length()
    end_pos = pos
    if (trg.form == TRG_FORM_DEFN):
        trg_length = 0
        curr_style = accessor.style_at_pos(last_pos)
        if (not styleClassifier.is_identifier_or_definition_style(curr_style)):
            return None
        idx = pos
        while (idx < buflen):
            new_style = accessor.style_at_pos(idx)
            if (new_style != curr_style):
                end_pos = idx
                break
            idx += 1
    else:
        trg_length = trg.length
        end_pos = (pos - trg_length)
    wrk_text = buf.accessor.text_range(max(0, (pos - 100)), end_pos)
    if DEBUG:
        print banner('Ruby    citdl_expr_from_trg')
        if (pos > 100):
            print '...',
        print (wrk_text + '<+>')
        print banner(None, '-')
    match = self._leading_citdl_expr_pat.search(wrk_text)
    if (not match):
        if ((trg.type == 'names') and (not trg.implicit)):
            citdl_expr = ''
            if DEBUG:
                print 'trigger-type    of    current-names:    match    anything'
        else:
            citdl_expr = None
            if DEBUG:
                print 'could    not    match    a    trailing    Ruby    var'
    elif match.group('literal'):
        literal = match.group('literal')
        literal_tail = match.group('literal_tail')
        ruby_type_from_literal = {']': 'Array', '}': 'Hash', '"': 'String', "'": 'String'}
        if DEBUG:
            print ('leading    literal    (part):    %r    (tail=%r)' % (literal, literal_tail))
        try:
            ruby_type = ruby_type_from_literal[match.group('literal')]
        except KeyError:
            if (('.' in literal) or ('e' in literal) or ('E' in literal)):
                ruby_type = 'Float'
            else:
                ruby_type = 'Fixnum'
        citdl_expr = (ruby_type + literal_tail)
    else:
        citdl_expr = match.group(0)
        if DEBUG:
            print ('parsed    out    leading    Ruby    citdl_expr:    %r' % citdl_expr)
    if DEBUG:
        print ('returning:    %r' % citdl_expr)
        print banner(None, '-')
    return citdl_expr
