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; }
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; }
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; }