wmenu-run: Populate items from PATH - wmenu - 🔧 fork of wmenu
 (HTM) git clone git@git.drkhsh.at/wmenu.git
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) README
 (DIR) LICENSE
       ---
 (DIR) commit 8f19d6a8d2f34aeb4060d4374eb204b270ffbaa8
 (DIR) parent 92d3b294aeff5b36916782847bae4389c10e8f17
 (HTM) Author: adnano <me@adnano.co>
       Date:   Fri,  3 May 2024 19:10:28 -0400
       
       wmenu-run: Populate items from PATH
       
       Diffstat:
         M menu.c                              |      87 ++++++++++++++++++-------------
         M menu.h                              |       4 ++--
         M wmenu-run.c                         |      19 +++++++++++++------
         M wmenu.c                             |       2 +-
       
       4 files changed, 68 insertions(+), 44 deletions(-)
       ---
 (DIR) diff --git a/menu.c b/menu.c
       @@ -35,6 +35,36 @@ struct menu *menu_create() {
                return menu;
        }
        
       +static void free_pages(struct menu *menu) {
       +        struct page *next = menu->pages;
       +        while (next) {
       +                struct page *page = next;
       +                next = page->next;
       +                free(page);
       +        }
       +}
       +
       +static void free_item(struct item *item) {
       +        free(item->text);
       +        free(item);
       +}
       +
       +static void free_items(struct menu *menu) {
       +        struct item *next = menu->items;
       +        while (next) {
       +                struct item *item = next;
       +                next = item->next;
       +                free_item(item);
       +        }
       +}
       +
       +// Destroys the menu, freeing memory associated with it.
       +void menu_destroy(struct menu *menu) {
       +        free_pages(menu);
       +        free_items(menu);
       +        free(menu);
       +}
       +
        static bool parse_color(const char *color, uint32_t *result) {
                if (color[0] == '#') {
                        ++color;
       @@ -136,19 +166,34 @@ void menu_getopts(struct menu *menu, int argc, char *argv[]) {
        }
        
        // Add an item to the menu.
       -void menu_add_item(struct menu *menu, char *text) {
       -        struct item *item = calloc(1, sizeof *item);
       -        if (!item) {
       +void menu_add_item(struct menu *menu, char *text, bool sort) {
       +        struct item *new = calloc(1, sizeof(struct item));
       +        if (!new) {
                        return;
                }
       -        item->text = text;
       +        new->text = text;
       +
       +        if (sort) {
       +                for (struct item **item = &menu->items; *item; item = &(*item)->next) {
       +                        int result = strcmp(new->text, (*item)->text);
       +                        if (result == 0) {
       +                                free_item(new);
       +                                return;
       +                        }
       +                        if (result < 0) {
       +                                new->next = *item;
       +                                *item = new;
       +                                return;
       +                        }
       +                }
       +        }
        
                if (menu->lastitem) {
       -                menu->lastitem->next = item;
       +                menu->lastitem->next = new;
                } else {
       -                menu->items = item;
       +                menu->items = new;
                }
       -        menu->lastitem = item;
       +        menu->lastitem = new;
        }
        
        static void append_page(struct page *page, struct page **first, struct page **last) {
       @@ -637,31 +682,3 @@ void menu_keypress(struct menu *menu, enum wl_keyboard_key_state key_state,
                        }
                }
        }
       -
       -// Frees menu pages.
       -static void free_pages(struct menu *menu) {
       -        struct page *next = menu->pages;
       -        while (next) {
       -                struct page *page = next;
       -                next = page->next;
       -                free(page);
       -        }
       -}
       -
       -// Frees menu items.
       -static void free_items(struct menu *menu) {
       -        struct item *next = menu->items;
       -        while (next) {
       -                struct item *item = next;
       -                next = item->next;
       -                free(item->text);
       -                free(item);
       -        }
       -}
       -
       -// Destroys the menu, freeing memory associated with it.
       -void menu_destroy(struct menu *menu) {
       -        free_pages(menu);
       -        free_items(menu);
       -        free(menu);
       -}
 (DIR) diff --git a/menu.h b/menu.h
       @@ -74,12 +74,12 @@ struct menu {
        };
        
        struct menu *menu_create();
       +void menu_destroy(struct menu *menu);
        void menu_getopts(struct menu *menu, int argc, char *argv[]);
       -void menu_add_item(struct menu *menu, char *text);
       +void menu_add_item(struct menu *menu, char *text, bool sort);
        void menu_render_items(struct menu *menu);
        void menu_paste(struct menu *menu, const char *text, ssize_t len);
        void menu_keypress(struct menu *menu, enum wl_keyboard_key_state key_state,
                        xkb_keysym_t sym);
       -void menu_destroy(struct menu *menu);
        
        #endif
 (DIR) diff --git a/wmenu-run.c b/wmenu-run.c
       @@ -1,4 +1,5 @@
        #define _POSIX_C_SOURCE 200809L
       +#include <dirent.h>
        #include <errno.h>
        #include <stdlib.h>
        #include <string.h>
       @@ -9,13 +10,19 @@
        #include "xdg-activation-v1-client-protocol.h"
        
        static void read_items(struct menu *menu) {
       -        char buf[sizeof menu->input];
       -        while (fgets(buf, sizeof buf, stdin)) {
       -                char *p = strchr(buf, '\n');
       -                if (p) {
       -                        *p = '\0';
       +        char *path = getenv("PATH");
       +        for (char *p = strtok(path, ":"); p != NULL; p = strtok(NULL, ":")) {
       +                DIR *dir = opendir(p);
       +                if (dir == NULL) {
       +                        continue;
                        }
       -                menu_add_item(menu, strdup(buf));
       +                for (struct dirent *ent = readdir(dir); ent != NULL; ent = readdir(dir)) {
       +                        if (ent->d_name[0] == '.') {
       +                                continue;
       +                        }
       +                        menu_add_item(menu, strdup(ent->d_name), true);
       +                }
       +                closedir(dir);
                }
        }
        
 (DIR) diff --git a/wmenu.c b/wmenu.c
       @@ -12,7 +12,7 @@ static void read_items(struct menu *menu) {
                        if (p) {
                                *p = '\0';
                        }
       -                menu_add_item(menu, strdup(buf));
       +                menu_add_item(menu, strdup(buf), false);
                }
        }