Esempio n. 1
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);
}
Esempio n. 2
0
static size_t op_put(Vis *vis, Text *txt, OperatorContext *c) {
	size_t pos = c->pos;
	bool sel = text_range_size(&c->range) > 0;
	bool sel_linewise = sel && text_range_is_linewise(txt, &c->range);
	if (sel) {
		text_delete_range(txt, &c->range);
		pos = c->pos = c->range.start;
	}
	switch (c->arg->i) {
	case VIS_OP_PUT_AFTER:
	case VIS_OP_PUT_AFTER_END:
		if (c->reg->linewise && !sel_linewise)
			pos = text_line_next(txt, pos);
		else if (!sel)
			pos = text_char_next(txt, pos);
		break;
	case VIS_OP_PUT_BEFORE:
	case VIS_OP_PUT_BEFORE_END:
		if (c->reg->linewise)
			pos = text_line_begin(txt, pos);
		break;
	}

	size_t len;
	const char *data = register_get(vis, c->reg, &len);

	for (int i = 0; i < c->count; i++) {
		text_insert(txt, pos, data, len);
		pos += len;
	}

	if (c->reg->linewise) {
		switch (c->arg->i) {
		case VIS_OP_PUT_BEFORE_END:
		case VIS_OP_PUT_AFTER_END:
			pos = text_line_start(txt, pos);
			break;
		case VIS_OP_PUT_AFTER:
			pos = text_line_start(txt, text_line_next(txt, c->pos));
			break;
		case VIS_OP_PUT_BEFORE:
			pos = text_line_start(txt, c->pos);
			break;
		}
	} else {
		switch (c->arg->i) {
		case VIS_OP_PUT_AFTER:
		case VIS_OP_PUT_BEFORE:
			pos = text_char_prev(txt, pos);
			break;
		}
	}

	return pos;
}
Esempio n. 3
0
Filerange text_range_linewise(Text *txt, Filerange *rin) {
	Filerange rout = *rin;
	rout.start = text_line_begin(txt, rin->start);
	if (rin->end != text_line_begin(txt, rin->end))
		rout.end = text_line_next(txt, rin->end);
	return rout;
}
Esempio n. 4
0
File: sam.c Progetto: ewqasd200g/vis
static bool cmd_select(Vis *vis, Win *win, Command *cmd, const char *argv[], Cursor *cur, Filerange *range) {
	Filerange sel = text_range_empty();
	if (!win)
		return sam_execute(vis, NULL, cmd->cmd, NULL, &sel);
	bool ret = true;
	View *view = win->view;
	Text *txt = win->file->text;
	bool multiple_cursors = view_cursors_multiple(view);
	Cursor *primary = view_cursors_primary_get(view);

	for (Cursor *c = view_cursors(view), *next; c && ret; c = next) {
		next = view_cursors_next(c);
		size_t pos = view_cursors_pos(c);
		if (vis->mode->visual) {
			sel = view_cursors_selection_get(c);
		} else if (cmd->cmd->address) {
			/* convert a single line range to a goto line motion */
			if (!multiple_cursors && cmd->cmd->cmddef->func == cmd_print) {
				Address *addr = cmd->cmd->address;
				switch (addr->type) {
				case '+':
				case '-':
					addr = addr->right;
					/* fall through */
				case 'l':
					if (addr && addr->type == 'l' && !addr->right)
						addr->type = 'g';
					break;
				}
			}
			sel = text_range_new(pos, pos);
		} else if (cmd->cmd->cmddef->flags & CMD_ADDRESS_POS) {
			sel = text_range_new(pos, pos);
		} else if (cmd->cmd->cmddef->flags & CMD_ADDRESS_LINE) {
			sel = text_object_line(txt, pos);
		} else if (cmd->cmd->cmddef->flags & CMD_ADDRESS_AFTER) {
			size_t next_line = text_line_next(txt, pos);
			sel = text_range_new(next_line, next_line);
		} else if (multiple_cursors) {
			sel = text_object_line(txt, pos);
		} else {
			sel = text_range_new(0, text_size(txt));
		}
		if (text_range_valid(&sel))
			ret &= sam_execute(vis, win, cmd->cmd, c, &sel);
		if (cmd->cmd->cmddef->flags & CMD_ONCE)
			break;
	}

	if (vis->win && vis->win->view == view && primary != view_cursors_primary_get(view))
		view_cursors_primary_set(view_cursors(view));
	return ret;
}
Esempio n. 5
0
size_t text_function_start_prev(Text *txt, size_t pos) {
	char c;
	size_t apos = text_byte_get(txt, pos, &c) && c == '}' && pos > 0 ? pos - 1 : pos;
	size_t a = text_function_end_next(txt, apos);
	size_t b = text_function_end_prev(txt, pos);
	if (a != apos) {
		size_t match = text_bracket_match(txt, a);
		a = match != a ? text_line_next(txt, text_line_empty_prev(txt, match)) : pos;
	}
	if (b != pos) {
		size_t match = text_bracket_match(txt, b);
		b = match != b ? text_line_next(txt, text_line_empty_prev(txt, match)) : pos;
	}
	if (a >= pos && b >= pos)
		return pos;
	else if (a >= pos)
		return b;
	else if (b >= pos)
		return a;
	else
		return MAX(a, b);
}
Esempio n. 6
0
size_t text_function_start_next(Text *txt, size_t pos) {
	size_t a = text_function_end_next(txt, pos);
	size_t b = a;
	char c;
	if (a != pos) {
		Iterator it = text_iterator_get(txt, a);
		while (text_iterator_byte_next(&it, &c) && (c == '\r' || c == '\n'));
		a = it.pos;
	}
	if (b != pos) {
		size_t match = text_bracket_match(txt, b);
		b = match != b ? text_line_next(txt, text_line_empty_prev(txt, match)) : pos;
	}
	if (a <= pos && b <= pos)
		return pos;
	else if (a <= pos)
		return b;
	else if (b <= pos)
		return a;
	else
		return MIN(a, b);
}
Esempio n. 7
0
File: sam.c Progetto: ewqasd200g/vis
static Filerange address_line_evaluate(Address *addr, File *file, Filerange *range, int sign) {
	Text *txt = file->text;
	size_t offset = addr->number != 0 ? addr->number : 1;
	size_t start = range->start, end = range->end, line;
	if (sign > 0) {
		char c;
		if (end > 0 && text_byte_get(txt, end-1, &c) && c == '\n')
			end--;
		line = text_lineno_by_pos(txt, end);
		line = text_pos_by_lineno(txt, line + offset);
	} else if (sign < 0) {
		line = text_lineno_by_pos(txt, start);
		line = offset < line ? text_pos_by_lineno(txt, line - offset) : 0;
	} else {
		line = text_pos_by_lineno(txt, addr->number);
	}

	if (addr->type == 'g')
		return text_range_new(line, line);
	else
		return text_range_new(line, text_line_next(txt, line));
}
Esempio n. 8
0
Filerange text_object_line(Text *txt, size_t pos) {
	Filerange r;
	r.start = text_line_begin(txt, pos);
	r.end = text_line_next(txt, pos);
	return r;
}
Esempio n. 9
0
size_t text_range_line_next(Text *txt, Filerange *r, size_t pos) {
	if (!text_range_contains(r, pos))
		return EPOS;
	size_t newpos = text_line_next(txt, pos);
	return newpos != pos && newpos < r->end ? newpos : EPOS;
}
Esempio n. 10
0
size_t text_line_down(Text *txt, size_t pos) {
	int width = text_line_width_get(txt, pos);
	size_t next = text_line_next(txt, pos);
	return text_line_width_set(txt, next, width);
}
Esempio n. 11
0
File: sam.c Progetto: ewqasd200g/vis
static bool cmd_extract(Vis *vis, Win *win, Command *cmd, const char *argv[], Cursor *cur, Filerange *range) {
	if (!win)
		return false;
	bool ret = true;
	Text *txt = win->file->text;

	if (cmd->regex) {
		size_t start = range->start, end = range->end, last_start = EPOS;
		RegexMatch match[1];
		while (start < end) {
			bool found = text_search_range_forward(txt, start,
				end - start, cmd->regex, 1, match,
				start > range->start ? REG_NOTBOL : 0) == 0;
			Filerange r = text_range_empty();
			if (found) {
				if (argv[0][0] == 'x')
					r = text_range_new(match[0].start, match[0].end);
				else
					r = text_range_new(start, match[0].start);
				if (match[0].start == match[0].end) {
					if (last_start == match[0].start) {
						start++;
						continue;
					}
					/* in Plan 9's regexp library ^ matches the beginning
					 * of a line, however in POSIX with REG_NEWLINE ^
					 * matches the zero-length string immediately after a
					 * newline. Try filtering out the last such match at EOF.
					 */
					if (end == match[0].start && start > range->start)
						break;
				}
				start = match[0].end;
			} else {
				if (argv[0][0] == 'y')
					r = text_range_new(start, end);
				start = end;
			}

			if (text_range_valid(&r)) {
				Mark mark_start = text_mark_set(txt, start);
				Mark mark_end = text_mark_set(txt, end);
				ret &= sam_execute(vis, win, cmd->cmd, NULL, &r);
				last_start = start = text_mark_get(txt, mark_start);
				if (start == EPOS && last_start != r.end)
					last_start = start = r.end;
				end = text_mark_get(txt, mark_end);
				if (start == EPOS || end == EPOS) {
					ret = false;
					break;
				}
			}
		}
	} else {
		size_t start = range->start, end = range->end;
		while (start < end) {
			size_t next = text_line_next(txt, start);
			if (next > end)
				next = end;
			Filerange r = text_range_new(start, next);
			if (start == next || !text_range_valid(&r))
				break;
			start = next;
			Mark mark_start = text_mark_set(txt, start);
			Mark mark_end = text_mark_set(txt, end);
			ret &= sam_execute(vis, win, cmd->cmd, NULL, &r);
			start = text_mark_get(txt, mark_start);
			if (start == EPOS)
				start = r.end;
			end = text_mark_get(txt, mark_end);
			if (end == EPOS) {
				ret = false;
				break;
			}
		}
	}

	view_cursors_dispose(cur);
	return ret;
}