Esempio n. 1
0
def get_line_after_and_range(context, range=None):
    '''Get the full line immediately after the current (or supplied) range'''
    line_ending = tea.get_line_ending(context)
    len_line_ending = len(line_ending)
    if range is None: range = tea.get_range(context)
    content = context.string()

    start = range.location + range.length

    if not is_line_ending(content, start - len_line_ending, line_ending):
        start = content.find(line_ending, start)
        if start == -1:
            return None
        else:
            start += len_line_ending

    end = content.find(line_ending, start)
    if end == -1:
        end = len(content)
    else:
        end += len_line_ending

    start = max(0, start)
    end = min(end, len(content))
    line_range = tea.new_range(start, end - start)

    return tea.get_selection(context, line_range), line_range
Esempio n. 2
0
def get_line_after_and_range(context, range = None):
    '''Get the full line immediately after the current (or supplied) range'''
    line_ending = tea.get_line_ending(context)
    len_line_ending = len(line_ending)
    if range is None: range = tea.get_range(context)
    content = context.string()
    
    start = range.location + range.length
    
    if not is_line_ending(content, start - len_line_ending, line_ending):
        start = content.find(line_ending, start)
        if start == -1:
            return None
        else:
            start += len_line_ending
    
    end = content.find(line_ending, start)
    if end == -1:
        end = len(content)
    else:
        end += len_line_ending
    
    start = max(0, start)
    end = min(end, len(content))
    line_range = tea.new_range(start, end - start)
    
    return tea.get_selection(context, line_range), line_range
def act(context, actionObject, operation='entab'):
    def replacements(match):
        '''Utility function for replacing items'''
        return match.group(0).replace(search, replace)
    
    spaces = int(actionObject.userInput().stringValue())
    if operation == 'entab':
        target = re.compile(r'^(\t* +\t*)+', re.MULTILINE)
        search = ' ' * spaces
        replace = '\t'
    else:
        target = re.compile(r'^( *\t+ *)+', re.MULTILINE)
        search = '\t'
        replace = ' ' * spaces
    insertions = tea.new_recipe()
    ranges = tea.get_ranges(context)
    if len(ranges) == 1 and ranges[0].length == 0:
        # No selection, use the document
        ranges[0] = tea.new_range(0, context.string().length())
    for range in ranges:
        text = tea.get_selection(context, range)
        # Non-Unix line endings will bork things; convert them
        text = tea.unix_line_endings(text)
        text = re.sub(target, replacements, text)
        if tea.get_line_ending(context) != '\n':
            text = tea.clean_line_endings(context, text)
        insertions.addReplacementString_forRange_(text, range)
    insertions.setUndoActionName_(operation.title())
    context.applyTextRecipe_(insertions)
    
    return True
Esempio n. 4
0
    def set_context(self, context):
        """
		Setup underlying editor context. You should call this method
		<code>before</code> using any Zen Coding action.
		@param context: context object
		"""
        self._context = context
        zen.newline = self.safe_str(tea.get_line_ending(context))
        self.zen_settings["variables"]["indentation"] = self.safe_str(tea.get_indentation_string(context))
Esempio n. 5
0
	def set_context(self, context):
		"""
		Setup underlying editor context. You should call this method
		<code>before</code> using any Zen Coding action.
		@param context: context object
		"""
		self._context = context
		zen_coding.set_newline(tea.get_line_ending(context))
		zen_coding.zen_settings['variables']['indentation'] = tea.get_indentation_string(context)
def act(context, direction=None, remove_duplicates=False, undo_name=None):
	'''
	Required action method
	
	This only allows a single selection (enforced through the utility
	functions) then sorts the lines, either ascending or descending.
	
	Theoretically we could allow discontiguous selections; might be useful?
	'''
	# Check if there is a selection, otherwise take all lines
	ranges = tea.get_ranges(context)
	if len(ranges) == 1 and ranges[0].length == 0:
		range = tea.new_range(0, context.string().length())
		text = tea.get_selection(context, range)
	else:
		text, range = tea.get_single_selection(context, True)
	
	if text == None:
		return False

	# Split the text into lines, not maintaining the linebreaks
	lines = text.splitlines(False)
	
	# Remove duplicates if set
	if remove_duplicates:
		if direction is None:
			seen = {}
			result = []
			for x in lines:
				if x in seen: continue
				seen[x] = 1
				result.append(x)
			lines = result
		else:
			lines = list(set(lines))
	
	# Sort lines ascending or descending
	if direction == 'asc' or direction == 'desc':
		lines.sort()
		if direction == 'desc':
			lines.reverse()
	
	# If direction is random, shuffle lines
	if direction == 'random':
		random.shuffle(lines)

	# Join lines to one string
	linebreak = tea.get_line_ending(context)
	sortedText = unicode.join(linebreak, lines)
	
	# Add final linebreak if selected text has one
	if text.endswith(linebreak):
		sortedText += linebreak

	# Paste the text
	return tea.insert_text_over_range(context, sortedText, range, undo_name)
Esempio n. 7
0
	def set_context(self, context, bundle):
		"""
		Setup underlying editor context. You should call this method
		<code>before</code> using any Zen Coding action.
		@param context: context object
		"""
		self._context = context
		self._bundle = bundle
		zencoding.utils.set_newline(tea.get_line_ending(context))
		zencoding.utils.set_variable('indentation', tea.get_indentation_string(context))
Esempio n. 8
0
def lines_and_range(context, range=None):
    '''Get the range of the full lines containing the current (or supplied) range'''
    line_ending = tea.get_line_ending(context)
    len_line_ending = len(line_ending)
    if range is None: range = tea.get_range(context)
    content = context.string()

    start, end = range.location, range.location + range.length

    if not is_line_ending(content, start - len_line_ending, line_ending):
        start = content.rfind(line_ending, 0, start)
        if start == -1:
            start = 0
        else:
            start += len_line_ending

    # select to the end of the line (if it's not already selected)
    if not is_line_ending(content, end, line_ending):
        # edge case: cursor is at start of line and more than one line selected:
        if not is_line_ending(content, end - len_line_ending,
                              line_ending) or len(
                                  content[start:end].split(line_ending)) <= 1:
            end = content.find(line_ending, end)
            if end == -1:
                end = len(content)
            else:
                end += len_line_ending
    # edge case: empty line, not selected
    elif is_line_ending(content, end - len_line_ending, line_ending):
        if len(content[start:end].split(line_ending)) <= 1:
            end = content.find(line_ending, end)
            if end == -1:
                end = len(content)
            else:
                end += len_line_ending
    else:
        end += len_line_ending

    start = max(0, start)
    end = min(end, len(content))

    line_range = tea.new_range(start, end - start)

    return tea.get_selection(context, line_range), line_range
Esempio n. 9
0
def lines_and_range(context, range = None):
    '''Get the range of the full lines containing the current (or supplied) range'''
    line_ending = tea.get_line_ending(context)
    len_line_ending = len(line_ending)
    if range is None: range = tea.get_range(context)
    content = context.string()
    
    start, end = range.location, range.location + range.length
    
    if not is_line_ending(content, start - len_line_ending, line_ending):
        start = content.rfind(line_ending, 0, start)
        if start == -1:
            start = 0
        else:
            start += len_line_ending
    
    # select to the end of the line (if it's not already selected)
    if not is_line_ending(content, end, line_ending):
        # edge case: cursor is at start of line and more than one line selected:
        if not is_line_ending(content, end - len_line_ending, line_ending) or len(content[start:end].split(line_ending)) <= 1:
            end = content.find(line_ending, end)
            if end == -1:
                end = len(content)
            else:
                end += len_line_ending
    # edge case: empty line, not selected
    elif is_line_ending(content, end - len_line_ending, line_ending):
        if len(content[start:end].split(line_ending)) <= 1:
            end = content.find(line_ending, end)
            if end == -1:
                end = len(content)
            else:
                end += len_line_ending
    else:
        end += len_line_ending
    
    start = max(0, start)
    end = min(end, len(content))
    
    line_range = tea.new_range(start, end - start)
    
    return tea.get_selection(context, line_range), line_range
Esempio n. 10
0
def get_line_before_and_range(context, range=None):
    '''Get the full line immediately before the current (or supplied) range'''
    line_ending = tea.get_line_ending(context)
    if range is None: range = tea.get_range(context)
    content = context.string()

    end = content.rfind(line_ending, 0, range.location)
    if end == -1:
        return None
    else:
        end = end + len(line_ending)

    start = content.rfind(line_ending, 0, end - len(line_ending))
    if start == -1:
        start = 0
    else:
        start += len(line_ending)

    start = max(0, start)
    end = min(end, len(content))
    line_range = tea.new_range(start, end - start)

    return tea.get_selection(context, line_range), line_range
Esempio n. 11
0
def get_line_before_and_range(context, range = None):
    '''Get the full line immediately before the current (or supplied) range'''
    line_ending = tea.get_line_ending(context)
    if range is None: range = tea.get_range(context)
    content = context.string()

    end = content.rfind(line_ending, 0, range.location)
    if end == -1:
        return None
    else:
        end = end + len(line_ending)
    
    start = content.rfind(line_ending, 0, end - len(line_ending))
    if start == -1:
        start = 0
    else:
        start += len(line_ending)
    
    start = max(0, start)
    end = min(end, len(content))
    line_range = tea.new_range(start, end - start)
    
    return tea.get_selection(context, line_range), line_range
 def didEndSheet_returnCode_contextInfo_(self, sheet, code, info):
     def replacements(match):
         '''Utility function for replacing items'''
         return match.group(0).replace(self.search, self.replace)
     
     if code == 1:
         # Leave sheet open with "processing" spinner
         self.spinner.startAnimation_(self)
         
         spaces = int(self.numSpaces.stringValue())
         if self.action == 'entab':
             target = re.compile(r'^(\t* +\t*)+', re.MULTILINE)
             self.search = ' ' * spaces
             self.replace = '\t'
         else:
             target = re.compile(r'^( *\t+ *)+', re.MULTILINE)
             self.search = '\t'
             self.replace = ' ' * spaces
         insertions = tea.new_recipe()
         ranges = tea.get_ranges(self.context)
         if len(ranges) == 1 and ranges[0].length == 0:
             # No selection, use the document
             ranges[0] = tea.new_range(0, self.context.string().length())
         for range in ranges:
             text = tea.get_selection(self.context, range)
             # Non-Unix line endings will bork things; convert them
             text = tea.unix_line_endings(text)
             text = re.sub(target, replacements, text)
             if tea.get_line_ending(self.context) != '\n':
                 text = tea.clean_line_endings(self.context, text)
             insertions.addReplacementString_forRange_(text, range)
         insertions.setUndoActionName_(self.action.title())
         self.context.applyTextRecipe_(insertions)
         self.spinner.stopAnimation_(self)
     
     sheet.orderOut_(self)
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)
Esempio n. 14
0
def act(context, direction=None, remove_duplicates=False, undo_name=None):
    """
    Required action method
    
    This sorts the selected lines (or document, if no selection)
    either ascending, descending, or randomly.
    """
    # Check if there is a selection, otherwise take all lines
    ranges = tea.get_ranges(context)
    if len(ranges) == 1 and ranges[0].length == 0:
        ranges = [tea.new_range(0, context.string().length())]

    # Setup the text recipe
    recipe = tea.new_recipe()

    for range in ranges:
        text = tea.get_selection(context, range)

        # A blank range means we have only one range and it's empty
        # so we can't do any sorting
        if text == "":
            return False

        # Split the text into lines, not maintaining the linebreaks
        lines = text.splitlines(False)

        # Remove duplicates if set
        if remove_duplicates:
            if direction is None:
                seen = {}
                result = []
                for x in lines:
                    if x in seen:
                        continue
                    seen[x] = 1
                    result.append(x)
                lines = result
            else:
                lines = list(set(lines))

        # Sort lines ascending or descending
        if direction == "asc" or direction == "desc":
            lines.sort()
            if direction == "desc":
                lines.reverse()

        # If direction is random, shuffle lines
        if direction == "random":
            random.shuffle(lines)

        # Join lines to one string
        linebreak = tea.get_line_ending(context)
        sortedText = unicode.join(linebreak, lines)

        # Add final linebreak if selected text has one
        if text.endswith(linebreak):
            sortedText += linebreak

        # Insert the text
        recipe.addReplacementString_forRange_(sortedText, range)

    if undo_name is not None:
        recipe.setUndoActionName_(undo_name)
    # Apply the recipe
    return context.applyTextRecipe_(recipe)
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)
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:
    $EDITOR_SELECTION: 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
    # TODO remove it
    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):
            point_ix[0] += 1
            return '$%s' % point_ix[0]
        zen_core.insertion_point = place_ins_point
    
        # 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)
        
        # Setup the zen profile based on doc_type and XHTML status
        profile = {}
        if doc_type == 'html':
            close_string = tea.get_tag_closestring(context)
            if close_string == '/':
                profile['self_closing_tag'] = True
            elif close_string != ' /':
                profile['self_closing_tag'] = False
        elif doc_type == 'xml':
            profile = {'self_closing_tag': True, 'tag_nl': True}
        
        zen_core.setup_profile('tea_profile', profile)
        
        # Prepare the snippet
        snippet = zen_core.expand_abbreviation(fullword, doc_type, 'tea_profile')
    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'
    # 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)
 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)