Add module "menu"

This commit is contained in:
Alex Kotov 2021-11-16 22:19:03 +05:00
parent 7c717ee221
commit 29536e5ebf
Signed by: kotovalexarian
GPG Key ID: 553C0EBBEB5D5F08
4 changed files with 88 additions and 20 deletions

View File

@ -3,7 +3,7 @@
include config.mk
SRC = atoms.c drw.c dwm.c helpers.c layouts.c settings.c spawn.c tags.c util.c
SRC = atoms.c drw.c dwm.c helpers.c layouts.c menu.c settings.c spawn.c tags.c util.c
OBJ = ${SRC:.c=.o}
DWM_SRC = dwm/handlers.c dwm/layouts.c dwm/swallow.c dwm/systray.c
@ -21,7 +21,7 @@ options:
${CC} -c $< -o $@ ${CFLAGS}
dwm.o: ${DWM_SRC} ${DWM_HDR}
${OBJ}: atoms.h drw.h config.def.h config.mk helpers.h layouts.h settings.h spawn.h tags.h util.h
${OBJ}: atoms.h drw.h config.def.h config.mk helpers.h layouts.h menu.h settings.h spawn.h tags.h util.h
polytreewm: ${OBJ}
${CC} -o $@ ${OBJ} ${LDFLAGS}

22
dwm.c
View File

@ -20,7 +20,6 @@
*
* To understand everything else, start reading main().
*/
#include <errno.h>
#include <locale.h>
#include <signal.h>
#include <stdarg.h>
@ -50,6 +49,7 @@
#include "drw.h"
#include "helpers.h"
#include "layouts.h"
#include "menu.h"
#include "settings.h"
#include "spawn.h"
#include "tags.h"
@ -1243,25 +1243,11 @@ movemouse(const Arg *arg)
// TODO: this function really needs to be refactored
void
nametag(const Arg *arg) {
char *p, name[TAGS_CUSTOM_NAME_SIZE];
FILE *f;
int i;
char name[TAGS_CUSTOM_NAME_SIZE];
errno = 0; // popen(3p) says on failure it "may" set errno
if(!(f = popen("rofi -dmenu -p \"Tag name\"", "r"))) {
fprintf(stderr, "polytreewm: popen 'rofi -dmenu -p \"Tag name\"' failed%s%s\n", errno ? ": " : "", errno ? strerror(errno) : "");
return;
}
if (!(p = fgets(name, TAGS_CUSTOM_NAME_SIZE, f)) && (i = errno) && ferror(f))
fprintf(stderr, "polytreewm: fgets failed: %s\n", strerror(i));
if (pclose(f) < 0)
fprintf(stderr, "polytreewm: pclose failed: %s\n", strerror(errno));
if(!p)
return;
if((p = strchr(name, '\n')))
*p = '\0';
if (!menu_run(name, TAGS_CUSTOM_NAME_SIZE, "Tag name")) return;
for (i = 0; i < TAGS_COUNT; ++i) {
for (int i = 0; i < TAGS_COUNT; ++i) {
if (selmon->tagset[selmon->seltags] & (1 << i)) {
tags_rename(i, name);
}

73
menu.c Normal file
View File

@ -0,0 +1,73 @@
#include "menu.h"
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#define COMMAND_SIZE 256
bool menu_run(
char *const buffer,
const size_t buffer_size,
const char *prompt
) {
// TODO: maybe we should assert here
if (buffer == NULL || buffer_size < 2) return false;
if (prompt == NULL) {
prompt = "";
}
for (const char *s = prompt; *s; ++s) {
// Simple check to ensure that the prompt
// string doesn't need to be escaped.
// TODO: maybe we should assert here
if (*s == '"') return false;
}
char command[COMMAND_SIZE];
const int command_slen =
snprintf(command, COMMAND_SIZE, "rofi -dmenu -p \"%s\"", prompt);
// Simple check to ensure that the prompt string is not too long.
// TODO: maybe we should assert here
if (command_slen >= COMMAND_SIZE) return false;
errno = 0; // popen(3p) says on failure it "may" set errno
FILE *f = popen(command, "r");
if (!f) {
perror("polytreewm: menu: popen failed");
return false;
}
const char *const buffer_result = fgets(buffer, buffer_size, f);
// Just to ensure that string is null-terminated.
// The man page fgets(3) is not very clear about that.
buffer[buffer_size - 1] = '\0';
if (!buffer_result) {
perror("polytreewm: menu: fgets failed");
pclose(f);
return false;
}
// Fail on both pipe error and not successfull exit status.
if (pclose(f) != EXIT_SUCCESS) {
perror("polytreewm: menu: pclose failed");
return false;
}
for (char *s = buffer; *s; ++s) {
if (*s == '\n') {
if (*(s + 1) == '\0') {
*s = '\0';
} else {
*s = ' ';
}
}
}
return true;
}

9
menu.h Normal file
View File

@ -0,0 +1,9 @@
#ifndef _MENU_H
#define _MENU_H
#include <stdbool.h>
#include <stddef.h>
bool menu_run(char *buffer, size_t buffer_size, const char *prompt);
#endif // _MENU_H