On Tue, Sep 23 21:29, Nicolas Seufert wrote: > Anbei mein erster und wenig erfolgreicher Versuch, apps/sh beizubringen, > bei der tab-completion auch Programme in $PATH zu berücksichtigen. > Das Ganze macht noch nicht ganz was erwünscht ist, würde es auch nicht > wenn es funktionierte. > - Der Inhalt von $PATH wird atm nur einmalig beim Start von sh gelesen. > - Bei der Anzeige der zur Verfügung stehenden Befehle werden > augenscheinlich die ersten 2 Zeichen des nächsten Befehlsnamens durch > willkürliche ersetzt (?!) > Kritik und natürlich Hinweise sind immer willkommen. > > kaffeefilter > Index: src/include/collections.h > =================================================================== > --- src/include/collections.h (Revision 923) > +++ src/include/collections.h (Arbeitskopie) > @@ -12,6 +12,7 @@ > void list_destroy(list_t* list); > list_t* list_push(list_t* list, void* value); > void* list_pop(list_t* list); > +void list_merge_into(list_t* target, list_t* to_merge); > bool list_is_empty(list_t* list); > void* list_get_element_at(list_t* list, int index); > list_t* list_insert(list_t* list, int index, void* value); > Index: src/lib/collections/list.c > =================================================================== > --- src/lib/collections/list.c (Revision 923) > +++ src/lib/collections/list.c (Arbeitskopie) > @@ -163,7 +163,7 @@ > } > > return value; > -} > +} > > /** > * Gibt einen Knoten aus der Liste zur?ck. Wird von allen Funktionen benutzt, Whitespace-Aenderungen sind grundsaetzlich nicht wirklich erwuenscht in den Patches, und besonders wenn noch Trailing Spaces dazukommen, also weg damit. ;-) > @@ -212,6 +212,21 @@ > } > > /** > + * Vereinigt zwei Listen, indem eine Liste in die Ziel-Liste > + * eingefuegt wird und das Quell-Listenhandle zerstoert wird. > + * @param target Ziel-Liste > + * @param to_merge Quell-Liste > + */ > +void list_merge_into(list_t* target, list_t* to_merge) > +{ > + if ((!target) || (!to_merge)) return; > + (list_get_node_at(to_merge, ((to_merge->size)-1)))->next = target->anchor; > + target->anchor = to_merge->anchor; > + target->size += to_merge->size; > + free(to_merge); > + } void list_merge_into(list_t* dest, list_t* source) { struct list_node* node; if (!dest || !source) { return; } node = list_get_node_at(source, source->size -1); node->next = dest->anchor; dest->size += source->size; free(source); } Für ein paar Klammern weniger und ein paar Leerzeilen sind wir immer dankbar. ;-) > + > +/** > * Fragt den Wert eines Listenelements ab. > * > * @param list Liste, deren Element abgefragt werden soll Ich würde mal vorschlagen das du das hier in zwei Patches aufspaltest. > Index: src/modules/c/shell/completion.c > =================================================================== > --- src/modules/c/shell/completion.c (Revision 923) > +++ src/modules/c/shell/completion.c (Arbeitskopie) > @@ -44,6 +44,8 @@ > > #include "shell.h" > > +static list_t* executables_in_path; > + > /** > * Completion-Handler fuer Readline > * > @@ -56,13 +58,23 @@ > /** > * Matches in Befehlen suchen > * > + * @param word Wort, das vervollstaendigt werden soll > * @return Pointer auf Array oder NULL wenn keine Gefunden wurden > */ > static char** shell_command_matches(const char* word); > > /** > + * Matches in Befehlen suchen, die nicht in shell_commands[] > + * vorhanden sind. > + * > + * @param word Wort, das vervollstaendigt werden soll > + * @return Pointer auf list_t oder NULL bei null Uebereinstimmungen > + */ > +static list_t* shell_executable_matches(const char* word); > +/** > * Matches in Umgebungsvariabeln suchen > * > + * @param word Wort, das vervollstaendigt werden soll > * @return Pointer auf Array oder NULL wenn keine Gefunden wurden > */ > static char** shell_envvar_matches(const char* word); > @@ -70,6 +82,7 @@ > /** > * Matches in Dateien > * > + * @param word Wort, das vervollstaendigt werden soll > * @return Pointer auf Array oder NULL wenn keine Gefunden wurden > */ > static char** shell_file_matches(const char* word); > @@ -84,6 +97,7 @@ > */ > void completion_init() > { > + update_path_env(); Das wäre von mir aus gesehen praktischer wenn man das einfach in update_path_env zusammensucht. > rl_attempted_completion_function = rl_completion; > } > > @@ -110,6 +124,26 @@ > return matches; > } > > +void update_path_env(void) > +{ > + io_resource_t* dir; > + io_direntry_t* dentry; > + list_t* executables; > + > + const char* path = getenv("PATH"); Wenn wir hier mehrere Verzeichnisse haben, kommt das nicht gut raus. Versuchs mal irgendwie so: dirname = strtok(path, ";"); while (dirname != NULL) { ... dirname = strtok(NULL, ";"); } > + if ((dir = directory_open(path)) == NULL) return; if (!(dir = directory_open(path))) { return; } > + executables = list_create(); > + while ((dentry = directory_read(dir))) { > + if (dentry->type == IO_DIRENTRY_DIR) continue; if (dentry->type != IO_DIRENTRY_DIR) { > + list_push(executables, strdup (dentry->name)); } > + } > + > + list_destroy(executables_in_path); > + executables_in_path = executables; > +} > + > + So, genug für heute, ich gehe auch schlafen. ;-) -- Antoine Kaufmann <toni@xxxxxxxxxxxxxxxx>
Attachment:
pgp9tklEJxWx5.pgp
Description: PGP signature