From a7f6f8a3e0aaf5177e018c0cf93344b015a1cda2 Mon Sep 17 00:00:00 2001 From: KK Date: Wed, 24 Jun 2026 00:08:07 +0200 Subject: [PATCH] add docs programs --- bin/docs-list.c | 165 ++++++++++++++++++++++++++++++++++++++++++++++++ bin/man-list | 2 + bin/pydoc-list | 9 +++ 3 files changed, 176 insertions(+) create mode 100755 bin/docs-list.c create mode 100755 bin/man-list create mode 100755 bin/pydoc-list diff --git a/bin/docs-list.c b/bin/docs-list.c new file mode 100755 index 0000000..5eed69e --- /dev/null +++ b/bin/docs-list.c @@ -0,0 +1,165 @@ +#!/usr/bin/tcc -run +#include +#include +#include +#include +#include +#include +#include + +void print_man_dir(FILE *menu, const char *dir) { + DIR *d = opendir(dir); + if (!d) { + return; + } + + struct dirent *ent; + while ((ent = readdir(d))) { + if (ent->d_name[0] == '.') { + continue; + } + + char file[512]; + snprintf(file, sizeof(file), "%s", ent->d_name); + + const char *suffixes[] = {".gz", ".bz2", ".xz", ".lzma", ".zst"}; + for (size_t i = 0; i < sizeof(suffixes) / sizeof(suffixes[0]); i++) { + size_t flen = strlen(file); + size_t slen = strlen(suffixes[i]); + if (flen > slen && strcmp(file + flen - slen, suffixes[i]) == 0) { + file[flen - slen] = '\0'; + break; + } + } + + char *dot = strrchr(file, '.'); + if (!dot || dot == file || !dot[1]) { + continue; + } + + *dot++ = '\0'; + fprintf(menu, "%s (%s)\tman\n", file, dot); + } + + closedir(d); +} + +void print_man_pages(FILE *menu, const char *root) { + DIR *d = opendir(root); + if (!d) { + return; + } + + struct dirent *ent; + char path[4096]; + while ((ent = readdir(d))) { + if (strncmp(ent->d_name, "man", 3) != 0) { + continue; + } + + snprintf(path, sizeof(path), "%s/%s", root, ent->d_name); + print_man_dir(menu, path); + } + + closedir(d); +} + +int main(void) { + char path[] = "/tmp/docs-list.XXXXXX"; + int fd = mkstemp(path); + if (fd < 0) { + perror("mkstemp"); + return 1; + } + + FILE *menu = fdopen(fd, "w"); + if (!menu) { + perror("fdopen"); + unlink(path); + return 1; + } + + char line[8192]; + FILE *manpath = popen("manpath 2>/dev/null", "r"); + if (manpath && fgets(line, sizeof(line), manpath)) { + line[strcspn(line, "\n")] = '\0'; + for (char *dir = strtok(line, ":"); dir; dir = strtok(NULL, ":")) { + print_man_pages(menu, dir); + } + } + if (manpath) { + pclose(manpath); + } + + FILE *pydoc = popen("python -c 'import pkgutil; [print(m) for m in sorted({m.name for m in pkgutil.iter_modules()})]'", "r"); + if (pydoc) { + while (fgets(line, sizeof(line), pydoc)) { + line[strcspn(line, "\n")] = '\0'; + fprintf(menu, "%s\tpydoc\n", line); + } + pclose(pydoc); + } + + fclose(menu); + + char command[1024]; + snprintf(command, sizeof(command), "wmenu -i -l 20 < '%s'", path); + + FILE *wmenu = popen(command, "r"); + if (!wmenu) { + perror("wmenu"); + unlink(path); + return 1; + } + + if (!fgets(line, sizeof(line), wmenu)) { + pclose(wmenu); + unlink(path); + return 0; + } + + int status = pclose(wmenu); + unlink(path); + if (status != 0) { + return WIFEXITED(status) ? WEXITSTATUS(status) : 1; + } + + line[strcspn(line, "\n")] = '\0'; + char *kind = strrchr(line, '\t'); + if (!kind) { + return 0; + } + *kind++ = '\0'; + + if (strcmp(kind, "man") == 0) { + char *s = line; + char name[256] = {0}; + char section[64] = {0}; + size_t i = 0; + + while (*s && !isspace((unsigned char)*s) && *s != '(' && i < sizeof(name) - 1) { + name[i++] = *s++; + } + + char *open = strchr(s, '('); + char *close = open ? strchr(open + 1, ')') : NULL; + if (open && close && close > open + 1) { + size_t len = close - open - 1; + if (len >= sizeof(section)) { + len = sizeof(section) - 1; + } + memcpy(section, open + 1, len); + } + + if (name[0] && section[0]) { + execlp("foot", "foot", "-e", "man", section, name, NULL); + } else if (name[0]) { + execlp("foot", "foot", "-e", "man", name, NULL); + } + } else if (strcmp(kind, "pydoc") == 0 && line[0]) { + execlp("foot", "foot", "-e", "python", "-m", "pydoc", line, NULL); + } + + perror("foot"); + return 1; +} diff --git a/bin/man-list b/bin/man-list new file mode 100755 index 0000000..6f9cff7 --- /dev/null +++ b/bin/man-list @@ -0,0 +1,2 @@ +#!/bin/bash +man -k . | wmenu -i -l 20 | awk '{print $1}' | xargs -r man diff --git a/bin/pydoc-list b/bin/pydoc-list new file mode 100755 index 0000000..3372978 --- /dev/null +++ b/bin/pydoc-list @@ -0,0 +1,9 @@ +#!/bin/sh +module="$( +python - <<'PY' | wmenu -i -l 20 +import pkgutil +for m in sorted({m.name for m in pkgutil.iter_modules()}): + print(m) +PY +)" +[ -n "$module" ] && foot -e python -m pydoc "$module"