Пример #1
0
static void window_selection_changed(void *win, Filerange *sel) {
	File *file = ((Win*)win)->file;
	if (text_range_valid(sel)) {
		file->marks[MARK_SELECTION_START] = text_mark_set(file->text, sel->start);
		file->marks[MARK_SELECTION_END] = text_mark_set(file->text, sel->end);
	}
}
Пример #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 bool sam_execute(Vis *vis, Win *win, Command *cmd, Cursor *cur, Filerange *range) {
	bool ret = true;
	if (cmd->address && win)
		*range = address_evaluate(cmd->address, win->file, range, 0);

	switch (cmd->argv[0][0]) {
	case '{':
	{
		if (!win) {
			ret = false;
			break;
		}
		Text *txt = win->file->text;
		Mark start, end;
		Filerange group = *range;

		for (Command *c = cmd->cmd; c && ret; c = c->next) {
			if (!text_range_valid(&group))
				return false;

			start = text_mark_set(txt, group.start);
			end = text_mark_set(txt, group.end);

			ret &= sam_execute(vis, win, c, NULL, &group);

			size_t s = text_mark_get(txt, start);
			/* hack to make delete work, only update if still valid */
			if (s != EPOS)
				group.start = s;
			group.end = text_mark_get(txt, end);
		}
		break;
	}
	default:
		ret = cmd->cmddef->func(vis, win, cmd, cmd->argv, cur, range);
		break;
	}
	return ret;
}
Пример #5
0
static void window_jumplist_add(Win *win, size_t pos) {
	Mark mark = text_mark_set(win->file->text, pos);
	if (mark && win->jumplist)
		ringbuf_add(win->jumplist, mark);
}
Пример #6
0
void window_selection_save(Win *win) {
	File *file = win->file;
	Filerange sel = view_cursors_selection_get(view_cursors(win->view));
	file->marks[VIS_MARK_SELECTION_START] = text_mark_set(file->text, sel.start);
	file->marks[VIS_MARK_SELECTION_END] = text_mark_set(file->text, sel.end);
}
Пример #7
0
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;
}