add docs programs

This commit is contained in:
KK
2026-06-24 00:08:07 +02:00
parent 9577ad69c9
commit a7f6f8a3e0
3 changed files with 176 additions and 0 deletions

165
bin/docs-list.c Executable file
View File

@@ -0,0 +1,165 @@
#!/usr/bin/tcc -run
#include <ctype.h>
#include <dirent.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/wait.h>
#include <unistd.h>
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;
}

2
bin/man-list Executable file
View File

@@ -0,0 +1,2 @@
#!/bin/bash
man -k . | wmenu -i -l 20 | awk '{print $1}' | xargs -r man

9
bin/pydoc-list Executable file
View File

@@ -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"