/** Command completion of the commands * * @param name String to match, changed to hint on exit * @param size Input buffer size * * @return Number of found matches * */ NO_TRACE static int cmdtab_compl(char *input, size_t size, indev_t *indev, hints_enum_func_t hints_enum) { const char *name = input; size_t found = 0; /* * Maximum Match Length: Length of longest matching common * substring in case more than one match is found. */ size_t max_match_len = size; size_t max_match_len_tmp = size; void *pos = NULL; const char *hint; const char *help; char *output = malloc(MAX_CMDLINE, 0); size_t hints_to_show = MAX_TAB_HINTS - 1; size_t total_hints_shown = 0; bool continue_showing_hints = true; output[0] = 0; while ((hint = hints_enum(name, NULL, &pos))) { if ((found == 0) || (str_length(hint) > str_length(output))) str_cpy(output, MAX_CMDLINE, hint); found++; } /* * If the number of possible completions is more than MAX_TAB_HINTS, * ask the user whether to display them or not. */ if (found > MAX_TAB_HINTS) { printf("\n"); continue_showing_hints = console_prompt_display_all_hints(indev, found); } if ((found > 1) && (str_length(output) != 0)) { printf("\n"); pos = NULL; while ((hint = hints_enum(name, &help, &pos))) { if (continue_showing_hints) { if (help) printf("%s%s (%s)\n", name, hint, help); else printf("%s%s\n", name, hint); --hints_to_show; ++total_hints_shown; if ((hints_to_show == 0) && (total_hints_shown != found)) { /* Ask user to continue */ continue_showing_hints = console_prompt_more_hints(indev, &hints_to_show); } } for (max_match_len_tmp = 0; (output[max_match_len_tmp] == hint[max_match_len_tmp]) && (max_match_len_tmp < max_match_len); ++max_match_len_tmp); max_match_len = max_match_len_tmp; } /* Keep only the characters common in all completions */ output[max_match_len] = 0; } if (found > 0) str_cpy(input, size, output); free(output); return found; }
/** Symtab completion * * @param input Search string, completes to symbol name * @param size Input buffer size * * @return 0 - nothing found, 1 - success, >1 print duplicates * */ int symtab_compl(char *input, size_t size, indev_t *indev) { #ifdef CONFIG_SYMTAB const char *name = input; /* Allow completion of pointers */ if ((name[0] == '*') || (name[0] == '&')) name++; /* Do not print all symbols */ if (str_length(name) == 0) return 0; size_t found = 0; size_t pos = 0; const char *hint; char output[MAX_SYMBOL_NAME]; /* * Maximum Match Length: Length of longest matching common substring in * case more than one match is found. */ size_t max_match_len = size; size_t max_match_len_tmp = size; size_t input_len = str_length(input); char *sym_name; size_t hints_to_show = MAX_TAB_HINTS - 1; size_t total_hints_shown = 0; bool continue_showing_hints = true; output[0] = 0; while ((hint = symtab_search_one(name, &pos))) pos++; pos = 0; while ((hint = symtab_search_one(name, &pos))) { if ((found == 0) || (str_length(output) > str_length(hint))) str_cpy(output, MAX_SYMBOL_NAME, hint); pos++; found++; } /* * If the number of possible completions is more than MAX_TAB_HINTS, * ask the user whether to display them or not. */ if (found > MAX_TAB_HINTS) { printf("\n"); continue_showing_hints = console_prompt_display_all_hints(indev, found); } if ((found > 1) && (str_length(output) != 0)) { printf("\n"); pos = 0; while (symtab_search_one(name, &pos)) { sym_name = symbol_table[pos].symbol_name; pos++; if (continue_showing_hints) { /* We are still showing hints */ printf("%s\n", sym_name); --hints_to_show; ++total_hints_shown; if ((hints_to_show == 0) && (total_hints_shown != found)) { /* Ask the user to continue */ continue_showing_hints = console_prompt_more_hints(indev, &hints_to_show); } } for (max_match_len_tmp = 0; (output[max_match_len_tmp] == sym_name[input_len + max_match_len_tmp]) && (max_match_len_tmp < max_match_len); ++max_match_len_tmp); max_match_len = max_match_len_tmp; } /* Keep only the characters common in all completions */ output[max_match_len] = 0; } if (found > 0) str_cpy(input, size, output); return found; #else return 0; #endif }