char *filename_completion_function(const char *text, int state) {
printf("\n[COMP] Entering: text='%s', state=%d, last_state=%d\n",
text, state, comp_state.last_state);
// 拦截只敲 Tab 的情况
if (text == NULL || *text == '\0') {
printf("用户未输入任何文本,只敲 Tab,不提供补全\n");
return NULL;
}
// 特殊处理:dir f → dir flash:/
if (state == 0 && strncmp(text, "f", 1) == 0 && strncmp(text, "flash:/", 7) != 0 &&
(strlen(text) == 1 || (strlen(text) > 1 && text[1] == ' '))) {
reset_completion_state();
printf("\n -----------------flash reset---------------\n");
comp_state.persistent_path = XSTRDUP(MTYPE_TMP, "flash:/");
comp_state.base_dir = XSTRDUP(MTYPE_TMP, "/mnt/switch/");
comp_state.current_text = XSTRDUP(MTYPE_TMP, text);
comp_state.original_prefix = XSTRDUP(MTYPE_TMP, "");
comp_state.current_level = 0;
comp_state.max_level = 3;
// 生成 flash:/ 目录下的补全项
comp_state.matches = generate_current_dir_paths("/mnt/switch/", "", 1);
comp_state.count = 0;
if (comp_state.matches) {
while (comp_state.matches[comp_state.count]) {
comp_state.count++;
}
printf(" Generated %d matches\n", comp_state.count);
}
comp_state.last_state = -1;
// 返回 flash:/ 作为第一次补全结果
char *flash_path = XSTRDUP(MTYPE_TMP, "flash:/");
printf("22222222222222222 flash_path = %s\n", flash_path);
return flash_path;
}
// 检查是否是 flash:/ 开头
int is_flash = strncmp(text, "flash:/", 7) == 0;
if (is_flash) {
// 从缓存中读取匹配项
if (!comp_state.matches || comp_state.count == 0) {
return NULL;
}
printf("3333333333333333\n");
int next_index = (comp_state.last_state + 1) % comp_state.count;
comp_state.last_state = next_index;
char *match = comp_state.matches[next_index];
// 构建 flash:/xxx 格式的路径
char *flash_path = XCALLOC(MTYPE_TMP, strlen("flash:/") + strlen(match) + 2);
snprintf(flash_path, strlen("flash:/") + strlen(match) + 2, "flash:/%s", match);
printf("444444444444444 flash_path = %s\n", flash_path);
return flash_path;
}
char current_dir[PATH_MAX];
char abs_path[PATH_MAX];
int reset_completion = 0;
// 初始化新补全
if (state == 0) {
printf(" Starting new completion\n");
// 获取当前工作目录
getcwd(current_dir, sizeof(current_dir));
snprintf(abs_path, sizeof(abs_path), "%s/%s", current_dir, text);
if (access(abs_path, F_OK) != 0) {
reset_completion = 1;
}
printf("\n111filename_completion_function: reset_completion = %d, abs_path = '%s'\n", reset_completion, abs_path);
char *tmp_base = NULL;
char *tmp_prefix = NULL;
int tmp_level = 0;
parse_input_text(text, &tmp_base, &tmp_prefix, &tmp_level);
printf("\n222filename_completion_function: text = '%s', tmp_base = '%s', tmp_prefix = '%s'\n",
text, tmp_base, tmp_prefix);
int same_reset = 0;
struct stat st_tmp;
char tmp_path[PATH_MAX];
if (comp_state.matches && comp_state.matches[0]) {
for (int i = 0; comp_state.matches[i]; i++) {
printf("\n333filename_completion_function: comp_state.matches[%d] = '%s'\n", i, comp_state.matches[i]);
if (strncmp(comp_state.matches[i], tmp_prefix, strlen(tmp_prefix)) == 0) {
char *old_base = comp_state.base_dir ? comp_state.base_dir : "";
snprintf(tmp_path, sizeof(tmp_path), "%s/%s%s", current_dir, old_base, comp_state.matches[i]);
printf("\n444filename_completion_function: tmp_path = '%s', current_dir = '%s', comp_state.matches[%d] = '%s'\n",
tmp_path, current_dir, i, comp_state.matches[i]);
if (stat(tmp_path, &st_tmp) == 0 && S_ISDIR(st_tmp.st_mode)) {
same_reset = 1;
printf("\nfilename_completion_function: same_reset = %d\n", same_reset);
break;
}
}
}
}
printf("\n555filename_completion_function: current_dir = '%s', text = '%s', abs_path = '%s', reset_completion = %d, same_reset = %d\n",
current_dir, text, abs_path, reset_completion, same_reset);
printf("\n666filename_completion_function: 11111111 comp_state.persistent_path = '%s'\n", comp_state.persistent_path);
int same_context = is_same_completion_context(text);
printf(" Same context: %d\n", same_context);
if ((!same_context) || (reset_completion && same_reset) || (!comp_state.persistent_path || comp_state.persistent_path[0] == '\0')) {
reset_completion_state();
printf("\n -----------------common reset---------------\n");
char *current_base = NULL;
char *current_prefix = NULL;
int current_level = 0;
parse_input_text(text, ¤t_base, ¤t_prefix, ¤t_level);
printf("\n777filename_completion_function: current_base = '%s', current_prefix = '%s', current_level = %d\n",
current_base, current_prefix, current_level);
comp_state.base_dir = current_base;
comp_state.current_text = XSTRDUP(MTYPE_TMP, text);
comp_state.original_prefix = XSTRDUP(MTYPE_TMP, current_prefix);
comp_state.current_level = current_level;
comp_state.max_level = current_level + 3;
// 检查是否用户已经明确进入了子目录
int ends_with_slash = text[strlen(text) - 1] == '/';
if (ends_with_slash) {
comp_state.persistent_path = XSTRDUP(MTYPE_TMP, text);
comp_state.max_level = current_level + 3;
} else {
comp_state.persistent_path = XSTRDUP(MTYPE_TMP, current_base);
comp_state.max_level = current_level;
}
comp_state.matches = generate_current_dir_paths(current_base, current_prefix, current_level == 0);
comp_state.count = 0;
if (comp_state.matches) {
while (comp_state.matches[comp_state.count]) {
comp_state.count++;
}
printf(" Generated %d matches\n", comp_state.count);
} else {
comp_state.count = 0;
}
comp_state.last_state = -1; // 重置索引
}
}
printf("\n888filename_completion_function: comp_state.base_dir = '%s', comp_state.current_text = '%s', comp_state.original_prefix = '%s', comp_state.persistent_path = '%s'\n",
comp_state.base_dir, comp_state.current_text, comp_state.original_prefix, comp_state.persistent_path);
// 没有匹配项
if (!comp_state.matches || comp_state.count == 0) {
printf("[COMP] No matches found\n");
return NULL;
}
// 获取下一个匹配项
int next_index = (comp_state.last_state + 1) % comp_state.count;
comp_state.last_state = next_index;
char *match = comp_state.matches[next_index];
// 构建完整路径
char *full_path = NULL;
// 通用路径拼接逻辑
if (comp_state.base_dir && strlen(comp_state.base_dir) > 0) {
int base_len = strlen(comp_state.base_dir);
int needs_slash = base_len > 0 && comp_state.base_dir[base_len - 1] != '/';
full_path = XCALLOC(MTYPE_TMP, strlen(match) + base_len + 2);
if (needs_slash) {
snprintf(full_path, strlen(match) + base_len + 2, "%s/%s", comp_state.base_dir, match);
} else {
snprintf(full_path, strlen(match) + base_len + 2, "%s%s", comp_state.base_dir, match);
}
} else {
full_path = XSTRDUP(MTYPE_TMP, match);
}
printf("[COMP] Returning: '%s'\n", full_path);
return full_path;
}
在这个基础上优化里边flash:/相关的功能,现在当前如果没有其他f前缀的文件的话,是能正常补全成flash:/的,但是如果当前路径下有其他f前缀的文件呢,就有问题了