def match_pair(editor, direction='out'):
	"""
	Find and select HTML tag pair
	@param editor: Editor instance
	@type editor: ZenEditor
	@param direction: Direction of pair matching: 'in' or 'out'. 
	@type direction: str 
	"""
	direction = direction.lower()
	
	range_start, range_end = editor.get_selection_range()
	cursor = range_end
	content = editor.get_content()
	range = None
	
	
	old_open_tag = html_matcher.last_match['opening_tag']
	old_close_tag = html_matcher.last_match['closing_tag']
	
	if direction == 'in' and old_open_tag and range_start != range_end:
#		user has previously selected tag and wants to move inward
		if not old_close_tag:
#			unary tag was selected, can't move inward
			return False
		elif old_open_tag['start'] == range_start:
			raise Exception, 'search inward'
			if content[old_open_tag['end']] == '<':
#				test if the first inward tag matches the entire parent tag's content
				_r = html_matcher.find(content, old_open_tag['end'] + 1)
				if _r[0] == old_open_tag['end'] and _r[1] == old_close_tag['start']:
					range = html_matcher.match(content, old_open_tag['end'] + 1)
				else:
					range = (old_open_tag['end'], old_close_tag['start'])
			else:
				range = (old_open_tag['end'], old_close_tag['start'])
		else:
			new_cursor = content[0, old_close_tag['start']].find('<', old_open_tag['end'])
			search_pos = new_cursor + 1 if new_cursor != -1 else old_open_tag['end']
			range = html_matcher.match(content, search_pos)
	else:
		range = html_matcher.match(content, cursor)
	
	
	if range[0] is not None:
		editor.create_selection(range[0], range[1])
		return True
	else:
		return False
def go_to_matching_pair(editor):
	"""
	Moves caret to matching opening or closing tag
	@param editor: Editor instance
	@type editor: ZenEditor
	"""
	content = editor.get_content()
	caret_pos = editor.get_caret_pos()
	
	if content[caret_pos] == '<': 
		# looks like caret is outside of tag pair  
		caret_pos += 1
		
	range = html_matcher.match(content, caret_pos)
		
	if range[0] is not None:
		# match found
		open_tag = html_matcher.last_match['opening_tag']
		close_tag = html_matcher.last_match['closing_tag']
			
		if close_tag: # exclude unary tags
			if open_tag['start'] <= caret_pos and open_tag['end'] >= caret_pos:
				editor.set_caret_pos(close_tag['start'])
			elif close_tag['start'] <= caret_pos and close_tag['end'] >= caret_pos:
				editor.set_caret_pos(open_tag['start'])
Exemple #3
0
    def core_wrap_with_abbreviation(self, abbr):

        if not abbr:
            return None

        syntax = self.get_syntax()
        profile_name = self.get_profile_name()

        start_offset, end_offset = self.get_selection_range()
        content = self.get_content()

        if start_offset == end_offset:
            rng = html_matcher.match(content, start_offset, profile_name)
            if rng[0] is None:
                return None
            else:
                start_offset, end_offset = rng

        start_offset, end_offset = zen_actions.narrow_to_non_space(
            content, start_offset, end_offset)
        line_bounds = zen_actions.get_line_bounds(content, start_offset)
        padding = zen_actions.get_line_padding(
            content[line_bounds[0]:line_bounds[1]])

        new_content = content[start_offset:end_offset]
        return zen_core.wrap_with_abbreviation(
            abbr, zen_actions.unindent_text(new_content, padding), syntax,
            profile_name)
def wrap_with_abbreviation(editor, abbr, syntax, profile_name='xhtml'):
	"""
	Wraps content with abbreviation
	@param editor: Editor instance
	@type editor: ZenEditor
	@param syntax: Syntax type (html, css, etc.)
	@type syntax: str
	@param profile_name: Output profile name (html, xml, xhtml)
	@type profile_name: str
	"""
	start_offset, end_offset = editor.get_selection_range()
	content = editor.get_content()
	
	if not abbr: return None 
	
	if start_offset == end_offset:
		# no selection, find tag pair
		range = html_matcher.match(content, start_offset)
		
		if range[0] is None: # nothing to wrap
			return None
			
		start_offset = range[0]
		end_offset = range[1]
			
		# narrow down selection until first non-space character
		while start_offset < end_offset:
			if not content[start_offset].isspace(): break
			start_offset += 1
		
		while end_offset > start_offset:
			end_offset -= 1
			if not content[end_offset].isspace():
				end_offset += 1
				break
	
	new_content = content[start_offset:end_offset]
	result = zen.wrap_with_abbreviation(abbr, unindent(editor, new_content), syntax, profile_name)
	
	if result:
		editor.replace_content(result, start_offset, end_offset)
def merge_lines(editor):
	"""
	Merge lines spanned by user selection. If there's no selection, tries to find
	matching tags and use them as selection
	@param editor: Editor instance
	@type editor: ZenEditor
	"""
	start, end = editor.get_selection_range()
	if start == end:
		# find matching tag
		pair = html_matcher.match(editor.get_content(), editor.get_caret_pos())
		if pair and pair[0] is not None:
			start, end = pair
	
	if start != end:
		# got range, merge lines
		text = editor.get_content()[start, end]
		lines = map(lambda s: re.sub(r'^\s+', '', s), zen.split_by_lines(text))
		text = re.sub(r'\s{2,}', ' ', ''.join(lines))
		editor.replace_content(text, start, end)
		editor.create_selection(start, start + len(text))
	def core_wrap_with_abbreviation(self, abbr):
	
		if not abbr:
			return None

		syntax = self.get_syntax()
		profile_name = self.get_profile_name()

		start_offset, end_offset = self.get_selection_range()
		content = self.get_content()

		if start_offset == end_offset:
			rng = html_matcher.match(content, start_offset, profile_name)
			if rng[0] is None:
				return None
			else:
				start_offset, end_offset = rng

		start_offset, end_offset = zen_actions.narrow_to_non_space(content, start_offset, end_offset)
		line_bounds = zen_actions.get_line_bounds(content, start_offset)
		padding = zen_actions.get_line_padding(content[line_bounds[0]:line_bounds[1]])

		new_content = content[start_offset:end_offset]
		return zen_core.wrap_with_abbreviation(abbr, zen_actions.unindent_text(new_content, padding), syntax, profile_name)