diff --git a/man/wofi.1 b/man/wofi.1 index a4039ba..7d71309 100644 --- a/man/wofi.1 +++ b/man/wofi.1 @@ -112,6 +112,10 @@ Specifies something to search for immediately on opening .TP .B \-o, \-\-monitor Sets the monitor to open on +.TP +.B \-r, \-\-pre\-display\-cmd +If set, the selectable entry won't be displayed as-is, but will instead be displayed based on the output of this command, which can be anything. Suggested to use with \fB"echo %s | some_cmd"\fR or \fB"some_cmd %s"\fR, as the string gets replaced in a printf-like fashion. This will not affect the output of wofi once a selection has been done, allowing you to display something else than the original output. + .SH CONFIGURATION Wofi has 3 main files used for configuration. All files are completely optional. diff --git a/man/wofi.5 b/man/wofi.5 index 4367af4..448727e 100644 --- a/man/wofi.5 +++ b/man/wofi.5 @@ -183,6 +183,8 @@ Specifies the layer to open on. The options are background, bottom, top, and ove .TP .B copy_exec=\fIPATH\fR Specifies the executable to pipe copy data into. $PATH will be scanned, this is not passed to a shell and must be an executable. Default is wl-copy. +.B pre_display_cmd=\fSTR\fR +Specifies a printf-like string which is used on the entries prior to displaying them. This command is only used to represent the label widget's string, and won't affect the the output of the selected label. .SH CSS SELECTORS Any GTK widget can be selected by using the name of its CSS node, these however might change with updates and are not guaranteed to stay constant. Wofi also provides certain widgets with names and classes which can be referenced from CSS to give access to the most important widgets easily. \fBwofi\fR(7) contains the current widget layout used by wofi so if you want to get into CSS directly using GTK widget names look there for info. diff --git a/src/main.c b/src/main.c index 6c7843d..71a4b88 100644 --- a/src/main.c +++ b/src/main.c @@ -63,39 +63,40 @@ static char* get_exec_name(char* path) { static void print_usage(char** argv) { printf("%s [options]\n", get_exec_name(argv[0])); printf("Options:\n"); - printf("--help\t\t-h\tDisplays this help message\n"); - printf("--fork\t\t-f\tForks the menu so you can close the terminal\n"); - printf("--conf\t\t-c\tSelects a config file to use\n"); - printf("--style\t\t-s\tSelects a stylesheet to use\n"); - printf("--color\t\t-C\tSelects a colors file to use\n"); - printf("--dmenu\t\t-d\tRuns in dmenu mode\n"); - printf("--show\t\t-S\tSpecifies the mode to run in\n"); - printf("--width\t\t-W\tSpecifies the surface width\n"); - printf("--height\t-H\tSpecifies the surface height\n"); - printf("--prompt\t-p\tPrompt to display\n"); - printf("--xoffset\t-x\tThe x offset\n"); - printf("--yoffset\t-y\tThe y offset\n"); - printf("--normal-window\t-n\tRender to a normal window\n"); - printf("--allow-images\t-I\tAllows images to be rendered\n"); - printf("--allow-markup\t-m\tAllows pango markup\n"); - printf("--cache-file\t-k\tSets the cache file to use\n"); - printf("--term\t\t-t\tSpecifies the terminal to use when running in a term\n"); - printf("--password\t-P\tRuns in password mode\n"); - printf("--exec-search\t-e\tMakes enter always use the search contents not the first result\n"); - printf("--hide-scroll\t-b\tHides the scroll bars\n"); - printf("--matching\t-M\tSets the matching method, default is contains\n"); - printf("--insensitive\t-i\tAllows case insensitive searching\n"); - printf("--parse-search\t-q\tParses the search text removing image escapes and pango\n"); - printf("--version\t-v\tPrints the version and then exits\n"); - printf("--location\t-l\tSets the location\n"); - printf("--no-actions\t-a\tDisables multiple actions for modes that support it\n"); - printf("--define\t-D\tSets a config option\n"); - printf("--lines\t\t-L\tSets the height in number of lines\n"); - printf("--columns\t-w\tSets the number of columns to display\n"); - printf("--sort-order\t-O\tSets the sort order\n"); - printf("--gtk-dark\t-G\tUses the dark variant of the current GTK theme\n"); - printf("--search\t-Q\tSearch for something immediately on open\n"); - printf("--monitor\t-o\tSets the monitor to open on\n"); + printf("--help\t\t\t-h\tDisplays this help message\n"); + printf("--fork\t\t\t-f\tForks the menu so you can close the terminal\n"); + printf("--conf\t\t\t-c\tSelects a config file to use\n"); + printf("--style\t\t\t-s\tSelects a stylesheet to use\n"); + printf("--color\t\t\t-C\tSelects a colors file to use\n"); + printf("--dmenu\t\t\t-d\tRuns in dmenu mode\n"); + printf("--show\t\t\t-S\tSpecifies the mode to run in\n"); + printf("--width\t\t\t-W\tSpecifies the surface width\n"); + printf("--height\t\t-H\tSpecifies the surface height\n"); + printf("--prompt\t\t-p\tPrompt to display\n"); + printf("--xoffset\t\t-x\tThe x offset\n"); + printf("--yoffset\t\t-y\tThe y offset\n"); + printf("--normal-window\t\t-n\tRender to a normal window\n"); + printf("--allow-images\t\t-I\tAllows images to be rendered\n"); + printf("--allow-markup\t\t-m\tAllows pango markup\n"); + printf("--cache-file\t\t-k\tSets the cache file to use\n"); + printf("--term\t\t\t-t\tSpecifies the terminal to use when running in a term\n"); + printf("--password\t\t-P\tRuns in password mode\n"); + printf("--exec-search\t\t-e\tMakes enter always use the search contents not the first result\n"); + printf("--hide-scroll\t\t-b\tHides the scroll bars\n"); + printf("--matching\t\t-M\tSets the matching method, default is contains\n"); + printf("--insensitive\t\t-i\tAllows case insensitive searching\n"); + printf("--parse-search\t\t-q\tParses the search text removing image escapes and pango\n"); + printf("--version\t\t-v\tPrints the version and then exits\n"); + printf("--location\t\t-l\tSets the location\n"); + printf("--no-actions\t\t-a\tDisables multiple actions for modes that support it\n"); + printf("--define\t\t-D\tSets a config option\n"); + printf("--lines\t\t\t-L\tSets the height in number of lines\n"); + printf("--columns\t\t-w\tSets the number of columns to display\n"); + printf("--sort-order\t\t-O\tSets the sort order\n"); + printf("--gtk-dark\t\t-G\tUses the dark variant of the current GTK theme\n"); + printf("--search\t\t-Q\tSearch for something immediately on open\n"); + printf("--monitor\t\t-o\tSets the monitor to open on\n"); + printf("--pre-display-cmd\t-r\tRuns command for the displayed entries, without changing the output. %%s for the real string\n"); exit(0); } @@ -106,7 +107,10 @@ void wofi_load_css(bool nyan) { ssize_t size = ftell(file); fseek(file, 0, SEEK_SET); char* data = malloc(size + 1); - fread(data, 1, size, file); + if (fread(data, 1, size, file) != 0) { + printf("failed to read stylesheet data from file"); + exit(EXIT_FAILURE); + } fclose(file); data[size] = 0; @@ -421,6 +425,12 @@ int main(int argc, char** argv) { .flag = NULL, .val = 'o' }, + { + .name = "pre-display-cmd", + .has_arg = required_argument, + .flag = NULL, + .val = 'r' + }, { .name = NULL, .has_arg = 0, @@ -457,13 +467,14 @@ int main(int argc, char** argv) { char* gtk_dark = NULL; char* search = NULL; char* monitor = NULL; + char* pre_display_cmd = NULL; struct wl_list options; wl_list_init(&options); struct option_node* node; int opt; - while((opt = getopt_long(argc, argv, "hfc:s:C:dS:W:H:p:x:y:nImk:t:P::ebM:iqvl:aD:L:w:O:GQ:o:", opts, NULL)) != -1) { + while((opt = getopt_long(argc, argv, "hfc:s:C:dS:W:H:p:x:y:nImk:t:P::ebM:iqvl:aD:L:w:O:GQ:o:r:", opts, NULL)) != -1) { switch(opt) { case 'h': print_usage(argv); @@ -572,6 +583,9 @@ int main(int argc, char** argv) { case 'o': monitor = optarg; break; + case 'r': + pre_display_cmd = optarg; + break; } } @@ -761,6 +775,9 @@ int main(int argc, char** argv) { if(monitor != NULL) { map_put(config, "monitor", monitor); } + if(pre_display_cmd != NULL) { + map_put(config, "pre_display_cmd", pre_display_cmd); + } struct sigaction sigact = {0}; sigact.sa_handler = sig; diff --git a/src/wofi.c b/src/wofi.c index 8890385..7a66946 100644 --- a/src/wofi.c +++ b/src/wofi.c @@ -106,6 +106,7 @@ static struct wl_list mode_list; static pthread_t mode_thread; static bool has_joined_mode = false; static char* copy_exec = NULL; +static char* pre_display_cmd = NULL; static struct map* keys; @@ -536,6 +537,40 @@ static gboolean _insert_widget(gpointer data) { if(node == NULL) { return FALSE; } + char* nodetext = NULL; + + if (!(pre_display_cmd == NULL)) { + FILE *fp_labeltext; + char *cmd_labeltext; + char line[128]; // you'd think this caps the line's length to 128, but it's just a buffer which due to the nature of fgets() splits on lines + unsigned int size = 0; + // first, prepare cmd_labeltext to be each entry's actual comamand to run, aka replacing 'cat %s' to be 'cat filename' + if ((asprintf(&cmd_labeltext, pre_display_cmd, node->text[0])) == -1) { + printf("error parsing pre_display_cmd to run\n"); + exit(EXIT_FAILURE); + } + // then, run the command + fp_labeltext = popen(cmd_labeltext, "r"); + if (fp_labeltext == NULL) { + printf("error executing '%s'\n", cmd_labeltext); + exit(EXIT_FAILURE); + } else if (fgets(line, sizeof(line), fp_labeltext)) { + // lastly, read the output of said command, and put it into the text variable to be used for the label widgets + // consider using 'printf %.10s as your --pre-display-cmd to limit a string to a determined width. 10 here is an example + size += strlen(line+1); // we need place for the \0 of strcpy + nodetext = (char *) realloc(nodetext, size); + strcpy(nodetext, line); + while (fgets(line, sizeof(line), fp_labeltext)) { + size += strlen(line); + nodetext = (char *) realloc(nodetext, size); + strncat(nodetext, line, size); + } + } + + pclose(fp_labeltext); + } else { + nodetext = *(node->text); + } GtkWidget* parent; if(node->action_count > 1 && !no_actions) { @@ -543,7 +578,7 @@ static gboolean _insert_widget(gpointer data) { g_signal_connect(parent, "activate", G_CALLBACK(expand), NULL); GtkWidget* box; if(node->builder == NULL) { - box = create_label(node->mode, node->text[0], node->search_text, node->actions[0]); + box = create_label(node->mode, nodetext, node->search_text, node->actions[0]); } else { box = GTK_WIDGET(node->builder->box); setup_label(node->builder->mode->name, WOFI_PROPERTY_BOX(box)); @@ -570,7 +605,7 @@ static gboolean _insert_widget(gpointer data) { } } else { if(node->builder == NULL) { - parent = create_label(node->mode, node->text[0], node->search_text, node->actions[0]); + parent = create_label(node->mode, nodetext, node->search_text, node->actions[0]); } else { parent = GTK_WIDGET(node->builder->box); setup_label(node->builder->mode->name, WOFI_PROPERTY_BOX(parent)); @@ -1234,7 +1269,10 @@ static void do_copy(void) { } int fds[2]; - pipe(fds); + if (pipe(fds) == -1) { + perror("pipe broken"); + exit(EXIT_FAILURE); + } if(fork() == 0) { close(fds[1]); dup2(fds[0], STDIN_FILENO); @@ -1244,7 +1282,9 @@ static void do_copy(void) { } close(fds[0]); - write(fds[1], action, strlen(action)); + if (!(write(fds[1], action, strlen(action)) == 0)) { + printf("fd pipe failed to write"); + } close(fds[1]); @@ -1674,6 +1714,8 @@ void wofi_init(struct map* _config) { char* monitor = map_get(config, "monitor"); char* layer = config_get(config, "layer", "top"); copy_exec = config_get(config, "copy_exec", "wl-copy"); + + pre_display_cmd = map_get(config, "pre_display_cmd"); keys = map_init_void();