@@ -24,6 +24,8 @@ enum delete_mode {
24
24
enum match_type {
25
25
MATCH_REGEX ,
26
26
MATCH_LITERAL ,
27
+ MATCH_COUNT_NEWEST ,
28
+ MATCH_COUNT_OLDEST ,
27
29
};
28
30
29
31
/**
@@ -37,6 +39,10 @@ struct clipdel_state {
37
39
union {
38
40
regex_t rgx ;
39
41
const char * needle ;
42
+ struct {
43
+ uint64_t current ;
44
+ uint64_t num_delete ;
45
+ } count ;
40
46
};
41
47
};
42
48
@@ -59,6 +65,15 @@ static enum cs_remove_action _nonnull_ remove_if_match(uint64_t hash _unused_,
59
65
expect (ret == 0 || ret == REG_NOMATCH );
60
66
matches = ret == 0 ;
61
67
break ;
68
+ case MATCH_COUNT_NEWEST :
69
+ case MATCH_COUNT_OLDEST :
70
+ if (state -> count .current < state -> count .num_delete ) {
71
+ matches = true;
72
+ ++ state -> count .current ;
73
+ } else {
74
+ matches = false;
75
+ }
76
+ break ;
62
77
default :
63
78
die ("unreachable\n" );
64
79
}
@@ -73,21 +88,27 @@ static enum cs_remove_action _nonnull_ remove_if_match(uint64_t hash _unused_,
73
88
}
74
89
75
90
int main (int argc , char * argv []) {
76
- const char usage [] = "Usage: clipdel [-d] [-F] [-v] pattern" ;
91
+ const char usage [] = "Usage: clipdel [-d] [-F] [-N] [-n] [- v] pattern" ;
77
92
78
93
_drop_ (config_free ) struct config cfg = setup ("clipdel" );
79
94
80
95
struct clipdel_state state = {0 };
81
96
82
97
int opt ;
83
- while ((opt = getopt (argc , argv , "dFvh " )) != -1 ) {
98
+ while ((opt = getopt (argc , argv , "dFNnvh " )) != -1 ) {
84
99
switch (opt ) {
85
100
case 'd' :
86
101
state .mode = DELETE_REAL ;
87
102
break ;
88
103
case 'F' :
89
104
state .type = MATCH_LITERAL ;
90
105
break ;
106
+ case 'N' :
107
+ state .type = MATCH_COUNT_OLDEST ;
108
+ break ;
109
+ case 'n' :
110
+ state .type = MATCH_COUNT_NEWEST ;
111
+ break ;
91
112
case 'v' :
92
113
state .invert_match = true;
93
114
break ;
@@ -109,6 +130,7 @@ int main(int argc, char *argv[]) {
109
130
_drop_ (cs_destroy ) struct clip_store cs ;
110
131
expect (cs_init (& cs , snip_fd , content_dir_fd ) == 0 );
111
132
133
+ enum cs_iter_direction direction = CS_ITER_OLDEST_FIRST ;
112
134
switch (state .type ) {
113
135
case MATCH_REGEX :
114
136
die_on (regcomp (& state .rgx , argv [optind ], REG_EXTENDED | REG_NOSUB ),
@@ -117,11 +139,20 @@ int main(int argc, char *argv[]) {
117
139
case MATCH_LITERAL :
118
140
state .needle = argv [optind ];
119
141
break ;
142
+ case MATCH_COUNT_NEWEST :
143
+ case MATCH_COUNT_OLDEST :
144
+ die_on (str_to_uint64 (argv [optind ], & state .count .num_delete ) < 0 ,
145
+ "Bad argument, expected integer: %s\n" , argv [optind ]);
146
+ state .count .current = 0 ;
147
+ if (state .type == MATCH_COUNT_NEWEST ) {
148
+ direction = CS_ITER_NEWEST_FIRST ;
149
+ }
150
+ break ;
120
151
default :
121
152
die ("unreachable\n" );
122
153
}
123
154
124
- expect (cs_remove (& cs , CS_ITER_OLDEST_FIRST , remove_if_match , & state ) == 0 );
155
+ expect (cs_remove (& cs , direction , remove_if_match , & state ) == 0 );
125
156
126
157
if (state .type == MATCH_REGEX ) {
127
158
regfree (& state .rgx );
0 commit comments