diff options
author | Artyom Skrobov <tyomitch@gmail.com> | 2021-04-07 13:09:39 -0400 |
---|---|---|
committer | Damien George <damien@micropython.org> | 2021-05-02 23:11:10 +1000 |
commit | f85ea8d4fe12251100989287f1cfe14af8650217 (patch) | |
tree | 3db728249156623600c216ac44da0005b3b1d5b1 /py/repl.c | |
parent | befbff31b73d5373b5933a3762a3a3c6e871e8da (diff) |
py/repl: Refactor autocomplete to reduce nesting.
Originally at adafruit#4548
Signed-off-by: Artyom Skrobov <tyomitch@gmail.com>
Diffstat (limited to 'py/repl.c')
-rw-r--r-- | py/repl.c | 203 |
1 files changed, 103 insertions, 100 deletions
@@ -161,131 +161,134 @@ size_t mp_repl_autocomplete(const char *str, size_t len, const mp_print_t *print mp_obj_t obj = MP_OBJ_FROM_PTR(&mp_module___main__); mp_obj_t dest[2]; + const char *s_start; + size_t s_len; + for (;;) { // get next word in string to complete - const char *s_start = str; + s_start = str; while (str < top && *str != '.') { ++str; } - size_t s_len = str - s_start; + s_len = str - s_start; - if (str < top) { - // a complete word, lookup in current object - qstr q = qstr_find_strn(s_start, s_len); - if (q == MP_QSTRnull) { - // lookup will fail - return 0; - } - mp_load_method_protected(obj, q, dest, true); - obj = dest[0]; // attribute, method, or MP_OBJ_NULL if nothing found + if (str == top) { + // end of string, do completion on this partial name + break; + } - if (obj == MP_OBJ_NULL) { - // lookup failed - return 0; - } + // a complete word, lookup in current object + qstr q = qstr_find_strn(s_start, s_len); + if (q == MP_QSTRnull) { + // lookup will fail + return 0; + } + mp_load_method_protected(obj, q, dest, true); + obj = dest[0]; // attribute, method, or MP_OBJ_NULL if nothing found - // skip '.' to move to next word - ++str; + if (obj == MP_OBJ_NULL) { + // lookup failed + return 0; + } - } else { - // end of string, do completion on this partial name + // skip '.' to move to next word + ++str; + } - // look for matches - const char *match_str = NULL; - size_t match_len = 0; - qstr q_first = 0, q_last = 0; - for (qstr q = MP_QSTR_ + 1; q < nqstr; ++q) { - size_t d_len; - const char *d_str = (const char *)qstr_data(q, &d_len); - // special case; filter out words that begin with underscore - // unless there's already a partial match - if (s_len == 0 && d_str[0] == '_') { - continue; - } - if (s_len <= d_len && strncmp(s_start, d_str, s_len) == 0) { - mp_load_method_protected(obj, q, dest, true); - if (dest[0] != MP_OBJ_NULL) { - if (match_str == NULL) { - match_str = d_str; - match_len = d_len; - } else { - // search for longest common prefix of match_str and d_str - // (assumes these strings are null-terminated) - for (size_t j = s_len; j <= match_len && j <= d_len; ++j) { - if (match_str[j] != d_str[j]) { - match_len = j; - break; - } - } - } - if (q_first == 0) { - q_first = q; + // look for matches + const char *match_str = NULL; + size_t match_len = 0; + qstr q_first = 0, q_last = 0; + for (qstr q = MP_QSTR_ + 1; q < nqstr; ++q) { + size_t d_len; + const char *d_str = (const char *)qstr_data(q, &d_len); + // special case; filter out words that begin with underscore + // unless there's already a partial match + if (s_len == 0 && d_str[0] == '_') { + continue; + } + if (s_len <= d_len && strncmp(s_start, d_str, s_len) == 0) { + mp_load_method_protected(obj, q, dest, true); + if (dest[0] != MP_OBJ_NULL) { + if (match_str == NULL) { + match_str = d_str; + match_len = d_len; + } else { + // search for longest common prefix of match_str and d_str + // (assumes these strings are null-terminated) + for (size_t j = s_len; j <= match_len && j <= d_len; ++j) { + if (match_str[j] != d_str[j]) { + match_len = j; + break; } - q_last = q; } } - } - - // nothing found - if (q_first == 0) { - if (s_len == 0) { - *compl_str = " "; - return 4; + if (q_first == 0) { + q_first = q; } - // If there're no better alternatives, and if it's first word - // in the line, try to complete "import". - if (s_start == org_str) { - static const char import_str[] = "import "; - if (memcmp(s_start, import_str, s_len) == 0) { - *compl_str = import_str + s_len; - return sizeof(import_str) - 1 - s_len; - } - } - - return 0; + q_last = q; } + } + } - // 1 match found, or multiple matches with a common prefix - if (q_first == q_last || match_len > s_len) { - *compl_str = match_str + s_len; - return match_len - s_len; + // nothing found + if (q_first == 0) { + if (s_len == 0) { + *compl_str = " "; + return 4; + } + // If there're no better alternatives, and if it's first word + // in the line, try to complete "import". + if (s_start == org_str) { + static const char import_str[] = "import "; + if (memcmp(s_start, import_str, s_len) == 0) { + *compl_str = import_str + s_len; + return sizeof(import_str) - 1 - s_len; } + } - // multiple matches found, print them out + return 0; + } - #define WORD_SLOT_LEN (16) - #define MAX_LINE_LEN (4 * WORD_SLOT_LEN) + // 1 match found, or multiple matches with a common prefix + if (q_first == q_last || match_len > s_len) { + *compl_str = match_str + s_len; + return match_len - s_len; + } - int line_len = MAX_LINE_LEN; // force a newline for first word - for (qstr q = q_first; q <= q_last; ++q) { - size_t d_len; - const char *d_str = (const char *)qstr_data(q, &d_len); - if (s_len <= d_len && strncmp(s_start, d_str, s_len) == 0) { - mp_load_method_protected(obj, q, dest, true); - if (dest[0] != MP_OBJ_NULL) { - int gap = (line_len + WORD_SLOT_LEN - 1) / WORD_SLOT_LEN * WORD_SLOT_LEN - line_len; - if (gap < 2) { - gap += WORD_SLOT_LEN; - } - if (line_len + gap + d_len <= MAX_LINE_LEN) { - // TODO optimise printing of gap? - for (int j = 0; j < gap; ++j) { - mp_print_str(print, " "); - } - mp_print_str(print, d_str); - line_len += gap + d_len; - } else { - mp_printf(print, "\n%s", d_str); - line_len = d_len; - } + // multiple matches found, print them out + + #define WORD_SLOT_LEN (16) + #define MAX_LINE_LEN (4 * WORD_SLOT_LEN) + + int line_len = MAX_LINE_LEN; // force a newline for first word + for (qstr q = q_first; q <= q_last; ++q) { + size_t d_len; + const char *d_str = (const char *)qstr_data(q, &d_len); + if (s_len <= d_len && strncmp(s_start, d_str, s_len) == 0) { + mp_load_method_protected(obj, q, dest, true); + if (dest[0] != MP_OBJ_NULL) { + int gap = (line_len + WORD_SLOT_LEN - 1) / WORD_SLOT_LEN * WORD_SLOT_LEN - line_len; + if (gap < 2) { + gap += WORD_SLOT_LEN; + } + if (line_len + gap + d_len <= MAX_LINE_LEN) { + // TODO optimise printing of gap? + for (int j = 0; j < gap; ++j) { + mp_print_str(print, " "); } + mp_print_str(print, d_str); + line_len += gap + d_len; + } else { + mp_printf(print, "\n%s", d_str); + line_len = d_len; } } - mp_print_str(print, "\n"); - - return (size_t)(-1); // indicate many matches } } + mp_print_str(print, "\n"); + + return (size_t)(-1); // indicate many matches } #endif // MICROPY_HELPER_REPL |