예제 #1
0
def do_css_reflection(editor):
    content = editor.get_content()
    caret_pos = editor.get_caret_pos()
    css = parser_utils.extract_css_rule(content, caret_pos)

    if not css or caret_pos < css[0] or caret_pos > css[1]:
        # no matching CSS rule or caret outside rule bounds
        return False

    tokens = parser_utils.parse_css(content[css[0]:css[1]], css[0])
    token_ix = find_token_from_position(tokens, caret_pos, 'identifier')

    if token_ix != -1:
        cur_prop = tokens[token_ix]['content']
        value_token = find_value_token(tokens, token_ix + 1)
        base_name = get_base_css_name(cur_prop)
        re_name = re.compile('^(?:\\-\\w+\\-)?' + base_name + '$')
        re_name = get_reflected_css_name(base_name)
        values = []

        if not value_token:
            return False

        # search for all vendor-prefixed properties
        for i, token in enumerate(tokens):
            if token['type'] == 'identifier' and re.search(
                    re_name,
                    token['content']) and token['content'] != cur_prop:
                v = find_value_token(tokens, i + 1)
                if v:
                    values.append({'name': token, 'value': v})

        # some editors do not provide easy way to replace multiple code
        # fragments so we have to squash all replace operations into one
        if values:
            data = content[
                values[0]['value']['start']:values[-1]['value']['end']]
            offset = values[0]['value']['start']
            value = value_token['content']

            values.reverse()
            for v in values:
                rv = get_reflected_value(cur_prop, value, v['name']['content'],
                                         v['value']['content'])
                data = replace_substring(data, v['value']['start'] - offset,
                                         v['value']['end'] - offset, rv)

                # also calculate new caret position
                if v['value']['start'] < caret_pos:
                    caret_pos += len(rv) - len(v['value']['content'])

            return {
                'data': data,
                'start': offset,
                'end': values[0]['value']['end'],
                'caret': caret_pos
            }

    return None
예제 #2
0
def do_css_reflection(editor):
	content = editor.get_content()
	caret_pos = editor.get_caret_pos()
	css = parser_utils.extract_css_rule(content, caret_pos)
		
	if not css or caret_pos < css[0] or caret_pos > css[1]:
		# no matching CSS rule or caret outside rule bounds
		return False
		
	tokens = parser_utils.parse_css(content[css[0]:css[1]], css[0])
	token_ix = find_token_from_position(tokens, caret_pos, 'identifier')
	
	if token_ix != -1:
		cur_prop = tokens[token_ix]['content']
		value_token = find_value_token(tokens, token_ix + 1)
		base_name = get_base_css_name(cur_prop)
		re_name = re.compile('^(?:\\-\\w+\\-)?' + base_name + '$')
		re_name = get_reflected_css_name(base_name)
		values = []
			
		if not value_token:
			return False
			
		# search for all vendor-prefixed properties
		for i, token in enumerate(tokens):
			if token['type'] == 'identifier' and re.search(re_name, token['content']) and token['content'] != cur_prop:
				v = find_value_token(tokens, i + 1)
				if v:
					values.append({'name': token, 'value': v})
		
		# some editors do not provide easy way to replace multiple code 
		# fragments so we have to squash all replace operations into one
		if values:
			data = content[values[0]['value']['start']:values[-1]['value']['end']]
			offset = values[0]['value']['start']
			value = value_token['content']
				
			values.reverse()
			for v in values:
				rv = get_reflected_value(cur_prop, value, v['name']['content'], v['value']['content'])
				data = replace_substring(data, v['value']['start'] - offset, v['value']['end'] - offset, rv)
					
				# also calculate new caret position
				if v['value']['start'] < caret_pos:
					caret_pos += len(rv) - len(v['value']['content'])
				
			return {
				'data': data,
				'start': offset,
				'end': values[0]['value']['end'],
				'caret': caret_pos
			}
	
	return None
예제 #3
0
파일: token.py 프로젝트: jecelyin/sublime
def do_css_reflection(editor):
    content = editor.get_content()
    caret_pos = editor.get_caret_pos()
    css = parser_utils.extract_css_rule(content, caret_pos)

    if not css or caret_pos < css[0] or caret_pos > css[1]:
        # no matching CSS rule or caret outside rule bounds
        return False

    tokens = parser_utils.parse_css(content[css[0] : css[1]], css[0])
    token_ix = find_token_from_position(tokens, caret_pos, "identifier")

    if token_ix != -1:
        cur_prop = tokens[token_ix]["content"]
        value_token = find_value_token(tokens, token_ix + 1)
        base_name = get_base_css_name(cur_prop)
        re_name = re.compile("^(?:\\-\\w+\\-)?" + base_name + "$")
        re_name = get_reflected_css_name(base_name)
        values = []

        if not value_token:
            return False

            # search for all vendor-prefixed properties
        for i, token in enumerate(tokens):
            if token["type"] == "identifier" and re.search(re_name, token["content"]) and token["content"] != cur_prop:
                v = find_value_token(tokens, i + 1)
                if v:
                    values.append({"name": token, "value": v})

                    # some editors do not provide easy way to replace multiple code
                    # fragments so we have to squash all replace operations into one
        if values:
            data = content[values[0]["value"]["start"] : values[-1]["value"]["end"]]
            offset = values[0]["value"]["start"]
            value = value_token["content"]

            values.reverse()
            for v in values:
                rv = get_reflected_value(cur_prop, value, v["name"]["content"], v["value"]["content"])
                data = replace_substring(data, v["value"]["start"] - offset, v["value"]["end"] - offset, rv)

                # also calculate new caret position
                if v["value"]["start"] < caret_pos:
                    caret_pos += len(rv) - len(v["value"]["content"])

            return {"data": data, "start": offset, "end": values[0]["value"]["end"], "caret": caret_pos}

    return None
예제 #4
0
def update_image_size_css(editor):
    """
	Updates image size of CSS rule
 	@type editor: ZenEditor
	"""
    caret_pos = editor.get_caret_pos()
    content = editor.get_content()
    rule = parser_utils.extract_css_rule(content, caret_pos, True)

    if rule:
        css = parser_utils.parse_css(content[rule[0]:rule[1]], rule[0])
        cur_token = find_token_from_position(css, caret_pos, 'identifier')
        value = find_value_token(css, cur_token + 1)

        if not value: return False

        # find insertion point
        ins_point = find_css_insertion_point(css, cur_token)

        m = re.match(r'url\((["\']?)(.+?)\1\)', value['content'], re.I)
        if m:
            size = get_image_size_for_source(editor, m.group(2))
            if size:
                wh = {'width': None, 'height': None}
                updates = []
                styler = learn_css_style(css, cur_token)

                for i, item in enumerate(css):
                    if item['type'] == 'identifier' and item['content'] in wh:
                        wh[item['content']] = i

                def update(name, val):
                    v = None
                    if wh[name] is not None:
                        v = find_value_token(css, wh[name] + 1)

                    if v:
                        updates.append([v['start'], v['end'], '%spx' % val])
                    else:
                        updates.append([
                            ins_point['token']['end'],
                            ins_point['token']['end'],
                            styler(name, '%spx' % val)
                        ])

                update('width', size['width'])
                update('height', size['height'])

                if updates:
                    updates.sort(lambda a, b: a[0] - b[0])
                    #					updates = sorted(updates, key=lambda a: a[0])

                    # some editors do not provide easy way to replace multiple code
                    # fragments so we have to squash all replace operations into one
                    offset = updates[0][0]
                    offset_end = updates[-1][1]
                    data = content[offset:offset_end]

                    updates.reverse()
                    for u in updates:
                        data = replace_substring(data, u[0] - offset,
                                                 u[1] - offset, u[2])

                        # also calculate new caret position
                        if u[0] < caret_pos:
                            caret_pos += len(u[2]) - u[1] + u[0]

                    if ins_point['need_col']:
                        data = replace_substring(
                            data, ins_point['token']['end'] - offset,
                            ins_point['token']['end'] - offset, ';')

                    return {
                        'data': data,
                        'start': offset,
                        'end': offset_end,
                        'caret': caret_pos
                    }

    return None
예제 #5
0
파일: token.py 프로젝트: CaIIIKiH/ZenCoding
def update_image_size_css(editor):
    """
    Updates image size of CSS rule
    @type editor: ZenEditor
    """
    caret_pos = editor.get_caret_pos()
    content = editor.get_content()
    rule = parser_utils.extract_css_rule(content, caret_pos, True)
    
    if rule:
        css = parser_utils.parse_css(content[rule[0]:rule[1]], rule[0])
        cur_token = find_token_from_position(css, caret_pos, 'identifier')
        value = find_value_token(css, cur_token + 1)
            
        if not value: return False
        
        # find insertion point
        ins_point = find_css_insertion_point(css, cur_token)
        
        m = re.match(r'url\((["\']?)(.+?)\1\)', value['content'], re.I)
        if m:
            size = get_image_size_for_source(editor, m.group(2))
            if size:
                wh = {'width': None, 'height': None}
                updates = []
                styler = learn_css_style(css, cur_token)
                
                for i, item in enumerate(css):
                    if item['type'] == 'identifier' and item['content'] in wh:
                        wh[item['content']] = i
                    
                def update(name, val):
                    v = None
                    if wh[name] is not None:
                        v = find_value_token(css, wh[name] + 1)
                        
                    if v:
                        updates.append([v['start'], v['end'], '%spx' % val])
                    else:
                        updates.append([ins_point['token']['end'], ins_point['token']['end'], styler(name, '%spx' % val)])
                        
                
                update('width', size['width'])
                update('height', size['height'])
                
                if updates:
                    updates.sort(lambda a,b: a[0] - b[0])
#                   updates = sorted(updates, key=lambda a: a[0]) 
                    
                    # some editors do not provide easy way to replace multiple code 
                    # fragments so we have to squash all replace operations into one
                    offset = updates[0][0]
                    offset_end = updates[-1][1]
                    data = content[offset:offset_end]
                    
                    updates.reverse()
                    for u in updates:
                        data = replace_substring(data, u[0] - offset, u[1] - offset, u[2])
                            
                        # also calculate new caret position
                        if u[0] < caret_pos:
                            caret_pos += len(u[2]) - u[1] + u[0]
                        
                    
                    if ins_point['need_col']:
                        data = replace_substring(data, ins_point['token']['end'] - offset, ins_point['token']['end'] - offset, ';')
                    
                    return {
                        'data': data,
                        'start': offset,
                        'end': offset_end,
                        'caret': caret_pos
                    };
                    
    return None
예제 #6
0
def get_range_for_prev_item_in_css(rule, offset, sel_start, sel_end):
    """
	Returns range for item to be selected in CSS rule before current caret position
	
	@param rule: CSS rule declaration
    @type rule: str
    
    @param offset: Rule's position index inside content
    @type offset: int
    
    @param sel_start: Start index of user selection
    @type sel_start: int
    
    @param sel_end: End index of user selection
    @type sel_end: int
    
    @return: List with two indexes if next item was found, None otherwise
	"""
    tokens = parser_utils.parse_css(rule, offset)
    next = []

    def check_same_range(r):
        "Same range is used inside complex value processor"
        return r[0] == sel_start and r[1] == sel_end

    # search for token that is left to the selection
    for i in range(len(tokens) - 1, -1, -1):
        token = tokens[i]
        if token['type'] in known_css_types:
            # check token position
            pos_test = token['start'] < sel_start
            if token['type'] == 'value' and token['ref_start_ix'] != token[
                    'ref_end_ix']:  # respect complex values
                pos_test = token['start'] <= sel_start

            if not pos_test: continue

            # found token that should be selected
            if token['type'] == 'identifier':
                rule_sel = handle_full_rule_css(tokens, i, token['start'])
                if rule_sel:
                    return rule_sel
            elif token['type'] == 'value' and token['ref_start_ix'] != token[
                    'ref_end_ix']:
                # looks like a complex value
                children = token['children']
                for child in children:
                    if child[0] < sel_start:
                        # create array copy
                        next = [child[0], child[1]]

                        rule_sel = handle_css_special_case(
                            rule, next[0], next[1], offset)
                        return not check_same_range(
                            rule_sel) and rule_sel or next

                # if we are here than we already traversed trough all
                # child tokens, select full value
                next = [token['start'], token['end']]
                if not check_same_range(next):
                    return next
            else:
                return [token['start'], token['end']]

    return None
예제 #7
0
def get_range_for_next_item_in_css(rule, offset, sel_start, sel_end):
    """
    Returns range for item to be selected in tag after current caret position
    
    @param rule: CSS rule declaration
    @type rule: str
    
    @param offset: Rule's position index inside content
    @type offset: int
    
    @param sel_start: Start index of user selection
    @type sel_start: int
    
    @param sel_end: End index of user selection
    @type sel_end: int
    
    @return: List with two indexes if next item was found, None otherwise
	"""
    tokens = parser_utils.parse_css(rule, offset)
    next = []

    def check_same_range(r):
        "Same range is used inside complex value processor"
        return r[0] == sel_start and r[1] == sel_end

    # search for token that is right to selection
    for i, token in enumerate(tokens):
        if token['type'] in known_css_types:
            # check token position
            if sel_start == sel_end:
                pos_test = token['end'] > sel_start
            else:
                pos_test = token['start'] >= sel_start
                if token['type'] == 'value':  # respect complex values
                    pos_test = pos_test or sel_start >= token[
                        'start'] and token['end'] >= sel_end

            if not pos_test: continue

            # found token that should be selected
            if token['type'] == 'identifier':
                rule_sel = handle_full_rule_css(
                    tokens, i, sel_end <= token['end'] and token['start']
                    or -1)
                if rule_sel:
                    return rule_sel

            elif token['type'] == 'value' and sel_end > token[
                    'start'] and token['children']:
                # looks like a complex value
                children = token['children']
                for child in children:
                    if child[0] >= sel_start or (sel_start == sel_end
                                                 and child[1] > sel_start):
                        next = [child[0], child[1]]
                        if check_same_range(next):
                            rule_sel = handle_css_special_case(
                                rule, next[0], next[1], offset)
                            if not check_same_range(rule_sel):
                                return rule_sel
                            else:
                                continue

                        return next
            elif token['end'] > sel_end:
                return [token['start'], token['end']]

    return None
예제 #8
0
def get_range_for_prev_item_in_css(rule, offset, sel_start, sel_end):
	"""
	Returns range for item to be selected in CSS rule before current caret position
	
	@param rule: CSS rule declaration
    @type rule: str
    
    @param offset: Rule's position index inside content
    @type offset: int
    
    @param sel_start: Start index of user selection
    @type sel_start: int
    
    @param sel_end: End index of user selection
    @type sel_end: int
    
    @return: List with two indexes if next item was found, None otherwise
	"""
	tokens = parser_utils.parse_css(rule, offset)
	next = []
			
	def check_same_range(r):
		"Same range is used inside complex value processor"
		return r[0] == sel_start and r[1] == sel_end
		
	# search for token that is left to the selection
	for i in range(len(tokens) - 1, -1, -1):
		token = tokens[i]
		if token['type'] in known_css_types:
			# check token position
			pos_test = token['start'] < sel_start
			if token['type'] == 'value' and token['ref_start_ix'] != token['ref_end_ix']: # respect complex values
				pos_test = token['start'] <= sel_start
			
			if not pos_test: continue
			
			# found token that should be selected
			if token['type'] == 'identifier':
				rule_sel = handle_full_rule_css(tokens, i, token['start'])
				if rule_sel:
					return rule_sel
			elif token['type'] == 'value' and token['ref_start_ix'] != token['ref_end_ix']:
				# looks like a complex value
				children = token['children']
				for child in children:
					if child[0] < sel_start:
						# create array copy
						next = [child[0], child[1]] 
						
						rule_sel = handle_css_special_case(rule, next[0], next[1], offset)
						return not check_same_range(rule_sel) and rule_sel or next
					
				# if we are here than we already traversed trough all
				# child tokens, select full value
				next = [token['start'], token['end']]
				if not check_same_range(next): 
					return next
			else:
				return [token['start'], token['end']]
	
	return None
예제 #9
0
def get_range_for_next_item_in_css(rule, offset, sel_start, sel_end):
	"""
    Returns range for item to be selected in tag after current caret position
    
    @param rule: CSS rule declaration
    @type rule: str
    
    @param offset: Rule's position index inside content
    @type offset: int
    
    @param sel_start: Start index of user selection
    @type sel_start: int
    
    @param sel_end: End index of user selection
    @type sel_end: int
    
    @return: List with two indexes if next item was found, None otherwise
	"""
	tokens = parser_utils.parse_css(rule, offset)
	next = []
		
	def check_same_range(r):
		"Same range is used inside complex value processor"
		return r[0] == sel_start and r[1] == sel_end
	
			
	# search for token that is right to selection
	for i, token in enumerate(tokens):
		if token['type'] in known_css_types:
			# check token position
			if sel_start == sel_end:
				pos_test = token['end'] > sel_start
			else:
				pos_test = token['start'] >= sel_start
				if token['type'] == 'value': # respect complex values
					pos_test = pos_test or sel_start >= token['start'] and token['end'] >= sel_end
			
			if not pos_test: continue
			
			# found token that should be selected
			if token['type'] == 'identifier':
				rule_sel = handle_full_rule_css(tokens, i, sel_end <= token['end'] and token['start'] or -1)
				if rule_sel:
					return rule_sel
				
			elif token['type'] == 'value' and sel_end > token['start'] and token['children']:
				# looks like a complex value
				children = token['children']
				for child in children:
					if child[0] >= sel_start or (sel_start == sel_end and child[1] > sel_start):
						next = [child[0], child[1]]
						if check_same_range(next):
							rule_sel = handle_css_special_case(rule, next[0], next[1], offset)
							if not check_same_range(rule_sel):
								return rule_sel
							else:
								continue
						
						return next
			elif token['end'] > sel_end:
				return [token['start'], token['end']]
	
	return None