def act(controller, bundle, options):
    context = tea.get_context(controller)
    
    snippet = tea.get_option(options, 'snippet', '')
    maintain_selection = tea.get_option(options, 'maintain_selection', False)
    
    text, range = tea.selection_and_range(context)
    
    snippet = tea.indent_snippet(context, snippet, range)
    snippet = tea.clean_line_endings(context, snippet)
    
    # Set up target selection
    sel_loc = snippet.find('$SELECTED_TEXT')
    cursor_loc = snippet.find('$0')
    if maintain_selection:
        select_range = tea.new_range(sel_loc + range.location, range.length)
    elif cursor_loc != -1:
        select_range = tea.new_range(snippet.find('$0') + range.location, 0)
    else:
        select_range = None
    
    snippet = snippet.replace('$SELECTED_TEXT', text)
    snippet = snippet.replace('$0', '')
    if select_range is not None:
        tea.insert_text_and_select(context, snippet, range, select_range)
    else:
        tea.insert_text(context, snippet, range)
def act(context, default=None, fallback_url='', undo_name=None, **syntaxes):
    '''
    Required action method
    
    A flexible link generator which uses the clipboard text (if there's
    a recognizable link there) and formats the snippet based on the
    active syntax of the context
    '''
    if default is None:
        return False
    # Get the text and range
    text, range = tea.get_single_selection(context, True)
    if text == None:
        return False
    
    # Get the clipboard contents, parse for a URL
    process = subprocess.Popen(['pbpaste'], stdout=subprocess.PIPE)
    clipboard, error = process.communicate(None)
    # Construct the default link
    url = format_hyperlink(clipboard, fallback_url)
    # Get the snippet based on the root zone
    snippet = tea.select_from_zones(context, range, default, **syntaxes)
    # Indent the snippet
    snippet = tea.indent_snippet(context, snippet, range)
    snippet = tea.construct_snippet(text, snippet)
    snippet = snippet.replace('$URL', tea.sanitize_for_snippet(url))
    return tea.insert_snippet_over_range(context, snippet, range, undo_name)
def act(context, first_snippet='', following_snippet='',
        final_append='', undo_name=None):
    '''
    Required action method
    
    This only allows a single selection (enforced through the utility
    functions) then parses over the lines and inserts a snippet
    
    Theoretically we could allow discontiguous selections; have to consider
    it if recipes get snippet capabilities
    '''
    text, range = tea.get_single_selection(context, True)
    if text == None:
        return False
    # Split the text into lines, maintaining the linebreaks
    lines = text.splitlines(True)
    # Compile the regex for quicker action on lots of lines
    parser = re.compile(r'(\s*)(.*?)(\s*(\r?\n)|$)')
    # Indent the snippets
    first = tea.indent_snippet(context, first_snippet, range)
    following = tea.indent_snippet(context, following_snippet, range)
    # Loop over lines and construct the snippet
    snippet = ''
    # This is the number of snippets processed, not lines
    count = 1
    for line in lines:
        content = parser.search(line)
        # Only wrap the line if there's some content
        if content.group(2) != '':
            if count == 1:
                segment = tea.construct_snippet(content.group(2), first)
            else:
                segment = tea.construct_snippet(content.group(2), following)
            snippet += content.group(1) + segment + content.group(3)
            count += 1
        else:
            snippet += line
    snippet += final_append
    return tea.insert_snippet_over_range(context, snippet, range, undo_name)
def act(context, first_snippet='', following_snippet='',
        final_append='', undo_name=None):
    '''
    Required action method
    
    Wraps the selected text in a snippet
    
    Support for discontiguous selections will be implemented when recipes
    can support snippets; until then only first_snippet will be used
    '''
    # TODO: change to a loop once snippets in recipes are supported
    # This function will handle the logic of when to use open vs. multi
    text, range = tea.get_single_selection(context)
    if text == None:
        text = ''
    # Indent the snippet
    snippet = tea.indent_snippet(context, first_snippet + final_append, range)
    snippet = tea.construct_snippet(text, snippet)
    return tea.insert_snippet_over_range(context, snippet, range, undo_name)
def act(context, default=None, undo_name=None, **syntaxes):
    '''
    Required action method
    
    Inserts an arbitrary text snippet after the cursor with provisions for
    syntax-specific alternatives
    
    Accepts $SELECTED_TEXT placeholder
    
    This method requires at least the snippet default to be defined in the XML
    '''
    if default is None:
        return False
    # Get the cursor position
    text, range = tea.get_single_selection(context)
    # Check for root-zone specific override
    snippet = tea.select_from_zones(context, range, default, **syntaxes)
    # Indent the snippet
    snippet = tea.indent_snippet(context, snippet, range)
    # Construct the snippet
    snippet = tea.construct_snippet(text, snippet)
    # Insert that snippet!
    return tea.insert_snippet_over_range(context, snippet, range, undo_name)
def act(controller, bundle, options):
    context = tea.get_context(controller)
    
    # Get the options
    alpha_numeric = tea.get_option(options, 'alpha_numeric', True)
    extra_characters = tea.get_option(options, 'extra_characters', '_-')
    bidirectional = tea.get_option(options, 'bidirectional', True)
    snippet = tea.get_option(options, 'snippet', '<$SELECTED_TEXT>$0</$WORD>')
    mode = tea.get_option(options, 'mode', '')
    
    # Fetch the word
    range = context.selectedRange()
    word, new_range = tea.get_word_or_selection(context, range, alpha_numeric,
                                                extra_characters, bidirectional)
    if word == '':
        # No word, so nothing further to do
        return False
    # If we're using $WORD, make sure the word is just a word
    if snippet.find('$WORD') >= 0:
        fullword = word
        word = tea.parse_word(word)
        if word is None:
            word = ''
    else:
        fullword = word
    
    # Process that sucker!
    if mode == 'zen' and fullword.find(' ') < 0:
        # Explicitly load zen settings
        zen_settings = settings_loader.load_settings()
        zen_core.update_settings(zen_settings)
        
        # Set up the config variables
        zen_core.newline = tea.get_line_ending(context)
        zen_settings['variables']['indentation'] = tea.get_indentation_string(context)
        
        # This allows us to use smart incrementing tab stops in zen snippets
        point_ix = [0]
        def place_ins_point(text):
            if not point_ix[0]:
                point_ix[0] += 1
                return '$0'
            else:
                return ''
            
        zen_core.insertion_point = place_ins_point
        
        # Determine doctype as best we can based on file extension
        doc_type = tea.get_zen_doctype(context)
        
        # Prepare the snippet
        snippet = zen_core.expand_abbreviation(fullword, doc_type, 'xhtml')
    elif mode == 'zen' and tea.is_selfclosing(word):
        # Self-closing, so construct the snippet from scratch
        snippet = '<' + fullword
        if fullword == word and not fullword in ['br', 'hr']:
            snippet += ' $0 />'
        else:
            snippet += ' />$0'
    # Indent the snippet
    snippet = tea.indent_snippet(context, snippet, new_range)
    snippet = tea.clean_line_endings(context, snippet)
    # Special replacement in case we're using $WORD
    snippet = snippet.replace('$WORD', word)
    snippet = snippet.replace('$SELECTED_TEXT', fullword)
    cursor_loc = snippet.find('$0')
    if cursor_loc != -1:
        select_range = tea.new_range(cursor_loc + new_range.location, 0)
        snippet = snippet.replace('$0', '')
        tea.insert_text_and_select(context, snippet, new_range, select_range)
    else:
        tea.insert_text(context, snippet, new_range)
 def wrap(self, context, abbr, profile_name='xhtml'):
     # Set up the config variables
     zen_settings = settings_loader.load_settings()
     zen.update_settings(zen_settings)
     zen.newline = self.safe_str(tea.get_line_ending(context))
     zen_settings['variables']['indentation'] = self.safe_str(tea.get_indentation_string(context))
     
     # This allows us to use smart incrementing tab stops in zen snippets
     point_ix = [0]
     def place_ins_point(text):
         if not point_ix[0]:
             point_ix[0] += 1
             return '$0'
         else:
             return ''
     zen.insertion_point = place_ins_point
     
     text, rng = tea.selection_and_range(context)
     if not text:
         # no selection, find matching tag
         content = context.string()
         start, end = html_matcher.match(content, rng.location)
         if start is None:
             # nothing to wrap
             return False
         
         def is_space(char):
             return char.isspace() or char in r'\n\r'
         
         # narrow down selection until first non-space character
         while start < end:
             if not is_space(content[start]):
                 break
             start += 1
         
         while end > start:
             end -= 1
             if not is_space(content[end]):
                 end += 1
                 break
         
         rng = tea.new_range(start, end - start)
         text = tea.get_selection(context, rng)
         
     # Fetch the doctype based on file extension
     doc_type = tea.get_zen_doctype(context)
     
     text = self.unindent(context, text)
     
     # Damn Python's encodings! Have to convert string to ascii before wrapping 
     # and then back to utf-8
     result = zen.wrap_with_abbreviation(self.safe_str(abbr), self.safe_str(text), doc_type, profile_name)
     result = unicode(result, 'utf-8')
     
     result = tea.indent_snippet(context, result, rng)
     result = tea.clean_line_endings(context, result)
     
     cursor_loc = result.find('$0')
     if cursor_loc != -1:
         select_range = tea.new_range(cursor_loc + rng.location, 0)
         result = result.replace('$0', '')
         tea.insert_text_and_select(context, result, rng, select_range)
     else:
         tea.insert_text(context, result, rng)
def act(
    context,
    default=None,
    alpha_numeric=True,
    extra_characters="",
    bidirectional=True,
    mode=None,
    close_string="",
    undo_name=None,
    **syntaxes
):
    """
    Required action method
    
    Transforms the word under the cursor (or the word immediately previous
    to the cursor) into a snippet (or processes it using zen-coding)
    
    The snippet offers two placeholders:
    $SELECTED_TEXT: replaced with the word, or any selected text
    $WORD: if text is selected, replaced just with the first word
    """

    if default is None:
        return False
    range = tea.get_single_range(context, True)
    if range == None:
        return False
    # Check for specific zone override
    snippet = tea.select_from_zones(context, range, default, **syntaxes)
    # Fetch the word
    word, new_range = tea.get_word_or_selection(context, range, alpha_numeric, extra_characters, bidirectional)
    if word == "":
        # No word, so nothing further to do
        return False
    # If we're using $WORD, make sure the word is just a word
    if snippet.find("$WORD") >= 0:
        fullword = word
        word = tea.parse_word(word)
        if word is None:
            word = ""
    else:
        fullword = word

    # We've got some extra work if the mode is HTML or zen
    # This is a really hacky solution, but I can't think of a concise way to
    # represent this functionality via XML
    if mode == "zen" and fullword.find(" ") < 0:
        # Set up the config variables
        zen_core.newline = tea.get_line_ending(context)
        # This allows us to use smart incrementing tab stops in zen snippets
        global point_ix
        point_ix = 0

        def place_ins_point(text):
            globals()["point_ix"] += 1
            return "$%s" % point_ix

        zen_core.insertion_point = place_ins_point
        zen_core.sub_insertion_point = place_ins_point
        zen_core.selfclosing_string = tea.get_tag_closestring(context)
        zen_settings["indentation"] = tea.get_indentation_string(context)
        # Detect the type of document we're working with
        zones = {"css, css *": "css", "xsl, xsl *": "xsl", "xml, xml *": "xml"}
        doc_type = tea.select_from_zones(context, range, "html", **zones)

        # Prepare the snippet
        snippet = zen_core.expand_abbr(fullword, doc_type)
    elif (mode == "zen" or mode == "html") and tea.is_selfclosing(word):
        # Self-closing, so construct the snippet from scratch
        snippet = "<" + fullword
        if fullword == word and not fullword in ["br", "hr"]:
            snippet += " $1"
        snippet += "$E_XHTML>$0"
    # Indent the snippet
    snippet = tea.indent_snippet(context, snippet, new_range)
    # Special replacement in case we're using $WORD
    snippet = snippet.replace("$WORD", word)
    # Construct the snippet
    snippet = tea.construct_snippet(fullword, snippet)
    return tea.insert_snippet_over_range(context, snippet, new_range, undo_name)