size_t str_common_utf(const basic_string<C>& s1, const basic_string<C>& s2, size_t start = 0) noexcept { size_t n = str_common(s1, s2, start); if (n == 0 || sizeof(C) == 4) return n; size_t pos = start + n; if (! is_following_unit(s1[pos]) && ! is_following_unit(s2[pos])) return n; --pos; while (pos > start && is_following_unit(s1[pos])) --pos; return pos - start; }
void msh_auto_complete(char *prefix) { int length, min_length; const char *name_ptr, *cmd_name; struct finsh_syscall *index; min_length = 0; name_ptr = RT_NULL; if (*prefix == '\0') { msh_help(0, RT_NULL); return; } #ifdef RT_USING_DFS /* check whether a spare in the command */ { char *ptr; ptr = prefix + rt_strlen(prefix); while (ptr != prefix) { if (*ptr == ' ') { msh_auto_complete_path(ptr + 1); break; } ptr --; } #ifdef RT_USING_MODULE /* There is a chance that the user want to run the module directly. So * try to complete the file names. If the completed path is not a * module, the system won't crash anyway. */ if (ptr == prefix) { msh_auto_complete_path(ptr); } #endif } #endif /* checks in internal command */ { for (index = _syscall_table_begin; index < _syscall_table_end; FINSH_NEXT_SYSCALL(index)) { /* skip finsh shell function */ if (strncmp(index->name, "__cmd_", 6) != 0) continue; cmd_name = (const char *) &index->name[6]; if (strncmp(prefix, cmd_name, strlen(prefix)) == 0) { if (min_length == 0) { /* set name_ptr */ name_ptr = cmd_name; /* set initial length */ min_length = strlen(name_ptr); } length = str_common(name_ptr, cmd_name); if (length < min_length) min_length = length; rt_kprintf("%s\n", cmd_name); } } } /* auto complete string */ if (name_ptr != NULL) { rt_strncpy(prefix, name_ptr, min_length); } return ; }
void msh_auto_complete_path(char *path) { DIR *dir = RT_NULL; struct dirent *dirent = RT_NULL; char *full_path, *ptr, *index; if (!path) return; full_path = (char *)rt_malloc(256); if (full_path == RT_NULL) return; /* out of memory */ if (*path != '/') { getcwd(full_path, 256); if (full_path[rt_strlen(full_path) - 1] != '/') strcat(full_path, "/"); } else *full_path = '\0'; index = RT_NULL; ptr = path; for (;;) { if (*ptr == '/') index = ptr + 1; if (!*ptr) break; ptr ++; } if (index == RT_NULL) index = path; if (index != RT_NULL) { char *dest = index; /* fill the parent path */ ptr = full_path; while (*ptr) ptr ++; for (index = path; index != dest;) *ptr++ = *index++; *ptr = '\0'; dir = opendir(full_path); if (dir == RT_NULL) /* open directory failed! */ { rt_free(full_path); return; } /* restore the index position */ index = dest; } /* auto complete the file or directory name */ if (*index == '\0') /* display all of files and directories */ { for (;;) { dirent = readdir(dir); if (dirent == RT_NULL) break; rt_kprintf("%s\n", dirent->d_name); } } else { int length, min_length; min_length = 0; for (;;) { dirent = readdir(dir); if (dirent == RT_NULL) break; /* matched the prefix string */ if (strncmp(index, dirent->d_name, rt_strlen(index)) == 0) { if (min_length == 0) { min_length = rt_strlen(dirent->d_name); /* save dirent name */ strcpy(full_path, dirent->d_name); } length = str_common(dirent->d_name, full_path); if (length < min_length) { min_length = length; } } } if (min_length) { if (min_length < rt_strlen(full_path)) { /* list the candidate */ rewinddir(dir); for (;;) { dirent = readdir(dir); if (dirent == RT_NULL) break; if (strncmp(index, dirent->d_name, rt_strlen(index)) == 0) rt_kprintf("%s\n", dirent->d_name); } } length = index - path; memcpy(index, full_path, min_length); path[length + min_length] = '\0'; } } closedir(dir); rt_free(full_path); }