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); }
int text_search_range_forward(Text *txt, size_t pos, size_t len, Regex *r, size_t nmatch, RegexMatch pmatch[], int eflags) { char *buf = text_bytes_alloc0(txt, pos, len); if (!buf) return REG_NOMATCH; regmatch_t match[nmatch]; int ret = regexec(&r->regex, buf, nmatch, match, eflags); if (!ret) { for (size_t i = 0; i < nmatch; i++) { pmatch[i].start = match[i].rm_so == -1 ? EPOS : pos + match[i].rm_so; pmatch[i].end = match[i].rm_eo == -1 ? EPOS : pos + match[i].rm_eo; } } free(buf); return ret; }
Filerange text_object_number(Text *txt, size_t pos) { char *buf, *err = NULL; Filerange r = text_object_range(txt, pos, is_number); if (!text_range_valid(&r)) return r; if (!(buf = text_bytes_alloc0(txt, r.start, text_range_size(&r)))) return text_range_empty(); errno = 0; strtoll(buf, &err, 0); if (errno || err == buf) r = text_range_empty(); else r.end = r.start + (err - buf); free(buf); return r; }
int text_search_range_backward(Text *txt, size_t pos, size_t len, Regex *r, size_t nmatch, RegexMatch pmatch[], int eflags) { char *buf = text_bytes_alloc0(txt, pos, len); if (!buf) return REG_NOMATCH; regmatch_t match[nmatch]; char *cur = buf; int ret = REG_NOMATCH; while (!regexec(&r->regex, cur, nmatch, match, eflags)) { ret = 0; for (size_t i = 0; i < nmatch; i++) { pmatch[i].start = match[i].rm_so == -1 ? EPOS : pos + (size_t)(cur - buf) + match[i].rm_so; pmatch[i].end = match[i].rm_eo == -1 ? EPOS : pos + (size_t)(cur - buf) + match[i].rm_eo; } cur += match[0].rm_eo; } free(buf); return ret; }
static const char *prompt_enter(Vis *vis, const char *keys, const Arg *arg) { Win *prompt = vis->win; View *view = prompt->view; Text *txt = prompt->file->text; Win *win = prompt->parent; char *cmd = NULL; Filerange range = view_selection_get(view); if (!text_range_valid(&range)) range = text_object_line(txt, view_cursor_get(view)); if (text_range_valid(&range)) cmd = text_bytes_alloc0(txt, range.start, text_range_size(&range)); if (!win || !cmd) { vis_info_show(vis, "Prompt window invalid\n"); prompt_restore(prompt); prompt_hide(prompt); free(cmd); return keys; } size_t len = strlen(cmd); if (len > 0 && cmd[len-1] == '\n') cmd[len-1] = '\0'; bool lastline = (range.end == text_size(txt)); prompt_restore(prompt); if (vis_prompt_cmd(vis, cmd)) { prompt_hide(prompt); if (!lastline) { text_delete(txt, range.start, text_range_size(&range)); text_appendf(txt, "%s\n", cmd); } } else { vis->win = prompt; vis->mode = &vis_modes[VIS_MODE_INSERT]; } free(cmd); vis_draw(vis); return keys; }