Skip to content

Commit 5fed60a

Browse files
committed
bins: Add clipdelmenu
It only took 8 years, but it is finally here! Closes #57.
1 parent 8ba23d8 commit 5fed60a

5 files changed

Lines changed: 110 additions & 2 deletions

File tree

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
src/clipmenud
22
src/clipctl
33
src/clipdel
4+
src/clipdelmenu
45
src/clipmenu
56
src/clipserve
67
tests/test

Makefile

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,10 @@ c_files := $(wildcard src/*.c)
1717
h_files := $(wildcard src/*.h)
1818
libs := $(filter $(c_files:.c=.o), $(h_files:.h=.o))
1919

20-
man1_files = clipctl.1 clipdel.1 clipmenu.1 clipmenud.1 clipserve.1
20+
man1_files = clipctl.1 clipdel.1 clipdelmenu.1 clipmenu.1 clipmenud.1 clipserve.1
2121
man5_files = clipmenu.conf.5
2222

23-
bins := clipctl clipmenud clipdel clipserve clipmenu
23+
bins := clipctl clipmenud clipdel clipdelmenu clipserve clipmenu
2424

2525
all: $(addprefix src/,$(bins))
2626

man/clipdelmenu.1

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
.TH CLIPDELMENU 1
2+
.SH NAME
3+
clipdelmenu \- interactive launcher for deleting clipboard entries
4+
.SH SYNOPSIS
5+
.B clipdelmenu
6+
[OPTION...]
7+
.SH DESCRIPTION
8+
.B clipdelmenu
9+
provides an interactive interface for browsing and deleting clipboard entries
10+
stored by clipmenud. It launches a menu using a configured launcher
11+
(e.g., dmenu, rofi, or another custom command) and displays a numbered list of
12+
stored clips. Once a selection is made, the chosen clip is permanently deleted
13+
from the clip store.
14+
.SH OPTIONS
15+
.TP
16+
.B \-h, \--help
17+
Display the help message (invokes the manual page).
18+
19+
Other than that, command-line arguments are passed directly to the underlying
20+
launcher.
21+
.SH CONFIGURATION
22+
See
23+
.BR clipmenu.conf (5).
24+
.SH DEPENDENCIES
25+
clipdelmenu requires a launcher capable of a dmenu-like interface (e.g., rofi or a
26+
custom command). Population of the clipstore requires
27+
.BR clipmenud
28+
to be running.
29+
.SH SEE ALSO
30+
.BR clipctl (1),
31+
.BR clipdel (1),
32+
.BR clipmenu (1),
33+
.BR clipmenud (1),
34+
.BR clipmenu.conf (5)
35+
.SH AUTHOR
36+
Chris Down
37+
.MT chris@chrisdown.name
38+
.ME
39+
.SH REPORTING BUGS
40+
Please send bug reports to
41+
.UR https://github.com/cdown/clipmenu/issues
42+
.UE .

src/clipdelmenu.c

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
#include <fcntl.h>
2+
#include <stdint.h>
3+
#include <unistd.h>
4+
5+
#include "config.h"
6+
#include "menu_util.h"
7+
#include "store.h"
8+
#include "util.h"
9+
10+
struct delete_state {
11+
uint64_t hash_to_delete;
12+
};
13+
14+
static enum cs_remove_action _nonnull_
15+
remove_if_hash_match(uint64_t hash, const char *line _unused_, void *private) {
16+
const struct delete_state *state = private;
17+
return hash == state->hash_to_delete ? CS_ACTION_REMOVE : CS_ACTION_KEEP;
18+
}
19+
20+
static int _nonnull_ clipdelmenu_action(struct config *cfg, uint64_t hash) {
21+
_drop_(close) int content_dir_fd = open(get_cache_dir(cfg), O_RDONLY);
22+
_drop_(close) int snip_fd =
23+
open(get_line_cache_path(cfg), O_RDWR | O_CREAT, 0600);
24+
expect(content_dir_fd >= 0 && snip_fd >= 0);
25+
26+
_drop_(cs_destroy) struct clip_store cs;
27+
expect(cs_init(&cs, snip_fd, content_dir_fd) == 0);
28+
29+
struct delete_state del_state = {.hash_to_delete = hash};
30+
expect(cs_remove(&cs, CS_ITER_NEWEST_FIRST, remove_if_hash_match,
31+
&del_state) == 0);
32+
33+
return 0;
34+
}
35+
36+
int main(int argc, char *argv[]) {
37+
menu_set_user_args(argc, argv);
38+
39+
_drop_(config_free) struct config cfg = setup("clipdelmenu");
40+
exec_man_on_help(argc, argv);
41+
42+
return menu_prompt_and_act(&cfg, "clipdelmenu", clipdelmenu_action);
43+
}

tests/x_integration_tests

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,28 @@ check_nr_clips 4
173173
[[ $(clipdel -dvN 2) == $'wibble\nwobble' ]]
174174
check_nr_clips 2
175175

176+
# Test clipdelmenu
177+
primary test1
178+
primary test2
179+
primary test3
180+
settle
181+
check_nr_clips 5
182+
183+
# Should delete the selected entry
184+
SELECT='[4] test2' clipdelmenu
185+
settle
186+
check_nr_clips 4
187+
188+
# Verify test2 is gone and test1, test3 remain
189+
clipmenu || true
190+
[[ "$(< "$l_out")" == *"test1"* ]]
191+
[[ "$(< "$l_out")" == *"test3"* ]]
192+
[[ "$(< "$l_out")" != *"test2"* ]]
193+
194+
# Delete the others
195+
SELECT='[3] test1' clipdelmenu
196+
SELECT='[3] test3' clipdelmenu
197+
176198
# Check selecting starts serving
177199
xsel -pc
178200

0 commit comments

Comments
 (0)