示例#1
0
static size_t op_shift_left(Vis *vis, Text *txt, OperatorContext *c) {
	size_t pos = text_line_begin(txt, c->range.end), prev_pos;
	size_t tabwidth = vis->tabwidth, tablen;
	size_t deleted = 0;

	/* if range ends at the begin of a line, skip line break */
	if (pos == c->range.end)
		pos = text_line_prev(txt, pos);

	do {
		char c;
		size_t len = 0;
		prev_pos = pos = text_line_begin(txt, pos);
		Iterator it = text_iterator_get(txt, pos);
		if (text_iterator_byte_get(&it, &c) && c == '\t') {
			len = 1;
		} else {
			for (len = 0; text_iterator_byte_get(&it, &c) && c == ' '; len++)
				text_iterator_byte_next(&it, NULL);
		}
		tablen = MIN(len, tabwidth);
		text_delete(txt, pos, tablen);
		pos = text_line_prev(txt, pos);
		deleted += tablen;
	}  while (pos >= c->range.start && pos != prev_pos);

	return c->pos - deleted;
}
示例#2
0
static size_t op_join(Vis *vis, Text *txt, OperatorContext *c) {
	size_t pos = text_line_begin(txt, c->range.end), prev_pos;
	Mark mark = NULL;

	/* if operator and range are both linewise, skip last line break */
	if (c->linewise && text_range_is_linewise(txt, &c->range)) {
		size_t line_prev = text_line_prev(txt, pos);
		size_t line_prev_prev = text_line_prev(txt, line_prev);
		if (line_prev_prev >= c->range.start)
			pos = line_prev;
	}

	do {
		prev_pos = pos;
		size_t end = text_line_start(txt, pos);
		pos = text_char_next(txt, text_line_finish(txt, text_line_prev(txt, end)));
		if (pos >= c->range.start && end > pos) {
			text_delete(txt, pos, end - pos);
			text_insert(txt, pos, " ", 1);
			if (!mark)
				mark = text_mark_set(txt, pos);
		} else {
			break;
		}
	} while (pos != prev_pos);

	size_t newpos = text_mark_get(txt, mark);
	return newpos != EPOS ? newpos : c->range.start;
}
示例#3
0
static size_t op_join(Vis *vis, Text *txt, OperatorContext *c) {
	size_t pos = text_line_begin(txt, c->range.end), prev_pos;
	Mark mark = NULL;

	/* if operator and range are both linewise, skip last line break */
	if (c->linewise && text_range_is_linewise(txt, &c->range)) {
		size_t line_prev = text_line_prev(txt, pos);
		size_t line_prev_prev = text_line_prev(txt, line_prev);
		if (line_prev_prev >= c->range.start)
			pos = line_prev;
	}

	size_t len = c->arg->s ? strlen(c->arg->s) : 0;

	do {
		prev_pos = pos;
		size_t end = text_line_start(txt, pos);
		pos = text_line_prev(txt, end);
		if (pos < c->range.start || end <= pos)
			break;
		text_delete(txt, pos, end - pos);
		char prev, next;
		if (text_byte_get(txt, pos-1, &prev) && !isspace((unsigned char)prev) &&
		    text_byte_get(txt, pos, &next) && next != '\r' && next != '\n')
			text_insert(txt, pos, c->arg->s, len);
		if (!mark)
			mark = text_mark_set(txt, pos);
	} while (pos != prev_pos);

	size_t newpos = text_mark_get(txt, mark);
	return newpos != EPOS ? newpos : c->range.start;
}
示例#4
0
static size_t op_delete(Vis *vis, Text *txt, OperatorContext *c) {
	c->reg->linewise = c->linewise;
	register_put_range(vis, c->reg, txt, &c->range);
	text_delete_range(txt, &c->range);
	size_t pos = c->range.start;
	if (c->linewise && pos == text_size(txt))
		pos = text_line_begin(txt, text_line_prev(txt, pos));
	return pos;
}
示例#5
0
Filerange text_object_indentation(Text *txt, size_t pos) {
    char c;
    size_t bol = text_line_begin(txt, pos);
    size_t sol = text_line_start(txt, bol);
    size_t start = bol;
    size_t end = text_line_next(txt, bol);
    size_t line_indent = sol - bol;
    bool line_empty = text_byte_get(txt, bol, &c) && (c == '\r' || c == '\n');

    char *buf = text_bytes_alloc0(txt, bol, line_indent);
    char *tmp = malloc(line_indent);

    if (!buf || !tmp) {
        free(buf);
        free(tmp);
        return text_range_empty();
    }

    while ((bol = text_line_begin(txt, text_line_prev(txt, start))) != start) {
        sol = text_line_start(txt, bol);
        size_t indent = sol - bol;
        if (indent < line_indent)
            break;
        bool empty = text_byte_get(txt, bol, &c) && (c == '\r' || c == '\n');
        if (line_empty && !empty)
            break;
        if (line_indent == 0 && empty)
            break;
        text_bytes_get(txt, bol, line_indent, tmp);
        if (memcmp(buf, tmp, line_indent))
            break;
        start = bol;
    }

    do {
        bol = end;
        sol = text_line_start(txt, bol);
        size_t indent = sol - bol;
        if (indent < line_indent)
            break;
        bool empty = text_byte_get(txt, bol, &c) && (c == '\r' || c == '\n');
        if (line_empty && !empty)
            break;
        if (line_indent == 0 && empty)
            break;
        text_bytes_get(txt, bol, line_indent, tmp);
        if (memcmp(buf, tmp, line_indent))
            break;
        end = text_line_next(txt, bol);
    } while (bol != end);

    free(buf);
    free(tmp);
    return text_range_new(start, end);
}
示例#6
0
size_t text_range_line_last(Text *txt, Filerange *r) {
	if (!text_range_valid(r))
		return EPOS;
	size_t pos = text_line_begin(txt, r->end);
	if (pos == r->end) {
		/* range ends at a begin of a line, skip last line ending */
		pos = text_line_prev(txt, pos);
		pos = text_line_begin(txt, pos);
	}
	return r->start <= pos ? pos : r->start;
}
示例#7
0
static size_t op_shift_right(Vis *vis, Text *txt, OperatorContext *c) {
	char spaces[9] = "         ";
	spaces[MIN(vis->tabwidth, LENGTH(spaces) - 1)] = '\0';
	const char *tab = vis->expandtab ? spaces : "\t";
	size_t tablen = strlen(tab);
	size_t pos = text_line_begin(txt, c->range.end), prev_pos;
	size_t inserted = 0;

	/* if range ends at the begin of a line, skip line break */
	if (pos == c->range.end)
		pos = text_line_prev(txt, pos);

	do {
		prev_pos = pos = text_line_begin(txt, pos);
		text_insert(txt, pos, tab, tablen);
		pos = text_line_prev(txt, pos);
		inserted += tablen;
	}  while (pos >= c->range.start && pos != prev_pos);

	return c->pos + inserted;
}
示例#8
0
size_t text_range_line_prev(Text *txt, Filerange *r, size_t pos) {
	if (!text_range_contains(r, pos))
		return EPOS;
	size_t newpos = text_line_begin(txt, text_line_prev(txt, pos));
	return newpos != pos && r->start <= newpos ? newpos : EPOS;
}
示例#9
0
size_t text_line_up(Text *txt, size_t pos) {
	int width = text_line_width_get(txt, pos);
	size_t prev = text_line_prev(txt, pos);
	return text_line_width_set(txt, prev, width);
}