astr astr_prepend_char(astr as, int c) { return astr_insert_char(as, 0, c); }
int main(void) { astr as1, as2, as3; int i; as1 = astr_new(); astr_assign_cstr(as1, " world"); astr_prepend_cstr(as1, "hello"); astr_append_char(as1, '!'); assert_eq(as1, "hello world!"); as3 = astr_substr(as1, 6, 5); assert_eq(as3, "world"); as2 = astr_new(); astr_assign_cstr(as2, " "); astr_prepend_cstr(as2, "The"); astr_append(as2, as3); astr_append_char(as2, '.'); assert_eq(as2, "The world."); astr_delete(as3); as3 = astr_substr(as1, -6, 5); assert_eq(as3, "world"); astr_assign_cstr(as1, "12345"); astr_delete(as2); as2 = astr_left(as1, 10); assert_eq(as2, "12345"); astr_delete(as2); as2 = astr_left(as1, 3); assert_eq(as2, "123"); astr_delete(as2); as2 = astr_right(as1, 10); assert_eq(as2, "12345"); astr_delete(as2); as2 = astr_right(as1, 3); assert_eq(as2, "345"); astr_assign_cstr(as1, "12345"); astr_insert_cstr(as1, 3, "mid"); astr_insert_cstr(as1, 0, "begin"); astr_insert_cstr(as1, 100, "end"); assert_eq(as1, "begin123mid45end"); astr_assign_cstr(as1, "12345"); astr_insert_char(as1, -2, 'x'); astr_insert_char(as1, -10, 'y'); astr_insert_char(as1, 10, 'z'); assert_eq(as1, "y123x45z"); astr_assign_cstr(as1, "12345"); astr_delete(as2); as2 = astr_substr(as1, -2, 5); assert_eq(as2, "45"); astr_assign_cstr(as1, "12345"); astr_delete(as2); as2 = astr_substr(as1, -10, 5); assert_eq(as2, "12345"); astr_assign_cstr(as1, "1234567"); astr_replace_cstr(as1, -4, 2, "foo"); assert_eq(as1, "123foo67"); astr_assign_cstr(as1, "1234567"); astr_replace_cstr(as1, 1, 3, "foo"); assert_eq(as1, "1foo567"); astr_assign_cstr(as1, "1234567"); astr_replace_cstr(as1, -1, 5, "foo"); assert_eq(as1, "123456foo"); astr_assign_cstr(as1, "1234567"); astr_remove(as1, 4, 10); assert_eq(as1, "1234"); astr_assign_cstr(as1, "abc def de ab cd ab de fg"); while ((i = astr_find_cstr(as1, "de")) >= 0) astr_replace_cstr(as1, i, 2, "xxx"); assert_eq(as1, "abc xxxf xxx ab cd ab xxx fg"); while ((i = astr_find_cstr(as1, "ab")) >= 0) astr_remove(as1, i, 2); assert_eq(as1, "c xxxf xxx cd xxx fg"); while ((i = astr_find_cstr(as1, " ")) >= 0) astr_replace_char(as1, i, 2, ' '); assert_eq(as1, "c xxxf xxx cd xxx fg"); astr_fill(as1, 'x', 3); assert_eq(as1, "xxx"); astr_fmt(as1, "%s * %d = ", "5", 3); astr_afmt(as1, "%d", 15); assert_eq(as1, "5 * 3 = 15"); printf("Input one string: "); fflush(stdout); astr_fgets(as1, stdin); printf("You wrote: \"%s\"\n", astr_cstr(as1)); astr_delete(as1); astr_delete(as2); astr_delete(as3); printf("astr test successful.\n"); return 0; }
static astr do_minibuf_read (const char *prompt, const char *value, size_t pos, Completion * cp, History * hp) { static int overwrite_mode = 0; int c, thistab, lasttab = -1; size_t prompt_len; char *s; astr as = astr_new_cstr (value), saved = NULL; prompt_len = strlen (prompt); if (pos == SIZE_MAX) pos = astr_len (as); for (;;) { switch (lasttab) { case COMPLETION_MATCHEDNONUNIQUE: s = " [Complete, but not unique]"; break; case COMPLETION_NOTMATCHED: s = " [No match]"; break; case COMPLETION_MATCHED: s = " [Sole completion]"; break; default: s = ""; } draw_minibuf_read (prompt, astr_cstr (as), prompt_len, s, pos); thistab = -1; switch (c = getkey ()) { case KBD_NOKEY: break; case KBD_CTRL | 'z': FUNCALL (suspend_emacs); break; case KBD_RET: term_move (term_height () - 1, 0); term_clrtoeol (); if (saved) astr_delete (saved); return as; case KBD_CANCEL: term_move (term_height () - 1, 0); term_clrtoeol (); if (saved) astr_delete (saved); astr_delete (as); return NULL; case KBD_CTRL | 'a': case KBD_HOME: pos = 0; break; case KBD_CTRL | 'e': case KBD_END: pos = astr_len (as); break; case KBD_CTRL | 'b': case KBD_LEFT: if (pos > 0) --pos; else ding (); break; case KBD_CTRL | 'f': case KBD_RIGHT: if (pos < astr_len (as)) ++pos; else ding (); break; case KBD_CTRL | 'k': /* FIXME: do kill-register save. */ if (pos < astr_len (as)) astr_truncate (as, pos); else ding (); break; case KBD_BS: if (pos > 0) astr_remove (as, --pos, 1); else ding (); break; case KBD_CTRL | 'd': case KBD_DEL: if (pos < astr_len (as)) astr_remove (as, pos, 1); else ding (); break; case KBD_INS: overwrite_mode = overwrite_mode ? 0 : 1; break; case KBD_META | 'v': case KBD_PGUP: if (cp == NULL) { ding (); break; } if (get_completion_flags (cp) & CFLAG_POPPEDUP) { completion_scroll_down (); thistab = lasttab; } break; case KBD_CTRL | 'v': case KBD_PGDN: if (cp == NULL) { ding (); break; } if (get_completion_flags (cp) & CFLAG_POPPEDUP) { completion_scroll_up (); thistab = lasttab; } break; case KBD_UP: case KBD_META | 'p': if (hp) { const char *elem = previous_history_element (hp); if (elem) { if (!saved) saved = astr_cpy (astr_new (), as); astr_cpy_cstr (as, elem); } } break; case KBD_DOWN: case KBD_META | 'n': if (hp) { const char *elem = next_history_element (hp); if (elem) astr_cpy_cstr (as, elem); else if (saved) { astr_cpy (as, saved); astr_delete (saved); saved = NULL; } } break; case KBD_TAB: got_tab: if (cp == NULL) { ding (); break; } if (lasttab != -1 && lasttab != COMPLETION_NOTMATCHED && get_completion_flags (cp) & CFLAG_POPPEDUP) { completion_scroll_up (); thistab = lasttab; } else { astr bs = astr_new (); astr_cpy (bs, as); thistab = completion_try (cp, bs, true); astr_delete (bs); switch (thistab) { case COMPLETION_MATCHED: case COMPLETION_MATCHEDNONUNIQUE: case COMPLETION_NONUNIQUE: { bs = astr_new (); if (get_completion_flags (cp) & CFLAG_FILENAME) astr_cat (bs, get_completion_path (cp)); astr_ncat_cstr (bs, get_completion_match (cp), get_completion_matchsize (cp)); if (strncmp (astr_cstr (as), astr_cstr (bs), astr_len (bs)) != 0) thistab = -1; astr_delete (as); as = bs; pos = astr_len (as); break; } case COMPLETION_NOTMATCHED: ding (); } } break; case ' ': if (cp != NULL) goto got_tab; /* FALLTHROUGH */ default: if (c > 255 || !isprint (c)) { ding (); break; } astr_insert_char (as, pos++, c); if (overwrite_mode && pos != astr_len (as)) astr_remove (as, pos, 1); } lasttab = thistab; } }