aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordec05eba <dec05eba@protonmail.com>2021-05-26 03:39:06 +0200
committerdec05eba <dec05eba@protonmail.com>2021-05-26 03:39:06 +0200
commit3757fe80b30801119bda41ab0445e915271129fc (patch)
tree62d282f929d02b96656ec3f8fab5ccef1f839a14
parent4fabc85d2a59383c67239c488fb2c717657b5954 (diff)
Allow use of multiple ranges when using cleanup command
-rwxr-xr-xautomediabin116640 -> 116664 bytes
-rwxr-xr-xbuild.sh2
-rwxr-xr-xopen_media.py2
-rwxr-xr-xread_manga.py2
-rw-r--r--src/main.c169
-rw-r--r--src/track_remove_parser.c133
-rw-r--r--src/track_remove_parser.h17
7 files changed, 237 insertions, 88 deletions
diff --git a/automedia b/automedia
index 268884e..0eb5eb6 100755
--- a/automedia
+++ b/automedia
Binary files differ
diff --git a/build.sh b/build.sh
index fb79f4a..6b88949 100755
--- a/build.sh
+++ b/build.sh
@@ -2,4 +2,4 @@
CFLAGS="-O3 -s -flto -Wall -Wextra -Werror"
[ -z "$RELEASE" ] && CFLAGS="-O0 -g3 -Wall -Wextra -Werror";
-musl-gcc -static src/main.c src/program.c src/alloc.c src/buffer.c src/fileutils.c src/transmission.c src/rss.c src/html.c src/rss_html_common.c src/download.c src/stringutils.c src/episode.c depends/cJSON.c -o automedia $CFLAGS
+musl-gcc -static src/main.c src/program.c src/alloc.c src/buffer.c src/fileutils.c src/transmission.c src/rss.c src/html.c src/rss_html_common.c src/download.c src/stringutils.c src/episode.c src/track_remove_parser.c depends/cJSON.c -o automedia $CFLAGS
diff --git a/open_media.py b/open_media.py
index 1f87975..ded438e 100755
--- a/open_media.py
+++ b/open_media.py
@@ -82,7 +82,7 @@ def main():
files.append(filename)
files = sorted(files, key=sort_images)
- process = subprocess.Popen(["sxiv", "-a", "-i", "-f"], stdin=subprocess.PIPE)
+ process = subprocess.Popen(["sxiv", "-a", "-i"], stdin=subprocess.PIPE)
files_fullpath = []
for filename in files:
files_fullpath.append(os.path.join(media_path, filename))
diff --git a/read_manga.py b/read_manga.py
index 4ad25c7..bff0955 100755
--- a/read_manga.py
+++ b/read_manga.py
@@ -77,5 +77,5 @@ for chapter in chapters_by_oldest[start_index:]:
images_str.append(os.path.join(image_dir, image))
index += 1
-process = subprocess.Popen(["sxiv", "-a", "-i", "-f"], stdin=subprocess.PIPE)
+process = subprocess.Popen(["sxiv", "-a", "-i"], stdin=subprocess.PIPE)
process.communicate("\n".join(images_str).encode())
diff --git a/src/main.c b/src/main.c
index a49acdb..04ae6fe 100644
--- a/src/main.c
+++ b/src/main.c
@@ -7,6 +7,7 @@
#include "rss.h"
#include "rss_html_common.h"
#include "html.h"
+#include "track_remove_parser.h"
#include "../depends/cJSON.h"
#include "alloc.h"
@@ -734,6 +735,13 @@ static void command_cleanup(int argc, char **argv, const char *rss_config_dir, c
++index;
}
+ char *track_items_selected = alloc_or_crash(num_tracked_items);
+ Buffer /*size_t*/ tracks_to_remove;
+ buffer_init(&tracks_to_remove);
+
+ Buffer /*Range*/ track_remove_ranges;
+ buffer_init(&track_remove_ranges);
+
if(tracked_items.size == 0) {
fprintf(stderr, "There is no media that hasn't been updated in the last %ld %s\n", days, days == 1 ? "day" : "days");
goto cleanup;
@@ -744,117 +752,108 @@ static void command_cleanup(int argc, char **argv, const char *rss_config_dir, c
fprintf(stderr, "==> ");
fflush(stderr);
- char resp[128];
+ char resp[512];
if(!fgets(resp, sizeof(resp), stdin)) {
fprintf(stderr, "Failed to read response from stdin\n");
goto cleanup;
}
+
char *response_str = strip(resp);
int response_len = strlen(response_str);
if(response_len == 0) {
- fprintf(stderr, "Invalid input, expected number range\n");
+ fprintf(stderr, "Invalid input. Expected numbers and/or number ranges\n");
continue;
}
- int start_range = 0;
- int end_range = 0;
- int num_variables_read = sscanf(response_str, "%d-%d", &start_range, &end_range);
+ memset(track_items_selected, 0, num_tracked_items);
+ buffer_clear(&tracks_to_remove);
+ buffer_clear(&track_remove_ranges);
- if(num_variables_read == 0) {
- fprintf(stderr, "Invalid input, expected number range\n");
- } else if(num_variables_read == 1) {
- int index = start_range - 1;
- if(index < 0 || index >= num_tracked_items) {
- fprintf(stderr, "Invalid item selected: %d, expected a value between 1 and %d\n", start_range, num_tracked_items);
- continue;
- }
+ if(track_remove_parser_parse(response_str, response_len, &track_remove_ranges) != 0)
+ continue;
- const char *name = path_get_filename((list_begin + index)->item_tracked_path);
- for(;;) {
- fprintf(stderr, "==> Are you sure you want to stop tracking %s/%s? Yes/No: \n", index < num_rss_items ? "rss" : "html", name);
- fprintf(stderr, "==> ");
- fflush(stderr);
-
- char resp[128];
- if(!fgets(resp, sizeof(resp), stdin)) {
- fprintf(stderr, "Failed to read response from stdin\n");
- goto cleanup;
- }
- char *response_str = strip(resp);
- int response_len = strlen(response_str);
- if(response_len == 0)
- continue;
+ Range *track_remove_it = buffer_begin(&track_remove_ranges);
+ Range *track_remove_end = buffer_end(&track_remove_ranges);
- if(response_str[0] == 'n' || response_str[0] == 'N') {
- goto cleanup;
- } else if(response_str[0] == 'y' || response_str[0] == 'Y') {
- if(remove_recursive((list_begin + index)->item_tracked_path) != 0) {
- fprintf(stderr, "Failed to remove %s/%s\n", index < num_rss_items ? "rss" : "html", name);
- goto cleanup;
- }
-
- fprintf(stderr, "Removed %s/%s\n", index < num_rss_items ? "rss" : "html", name);
- goto cleanup;
- }
- }
- } else if(num_variables_read == 2) {
- int start_index_f = start_range - 1;
+ int valid_ranges = 1;
+ for(; track_remove_it != track_remove_end; ++track_remove_it) {
+ int start_index_f = track_remove_it->start - 1;
if(start_index_f < 0 || start_index_f >= num_tracked_items) {
- fprintf(stderr, "Invalid item start range: %d, expected a value between 1 and %d\n", start_range, num_tracked_items);
- continue;
+ fprintf(stderr, "Invalid item start range: %d, expected a value between 1 and %d\n", track_remove_it->start, num_tracked_items);
+ valid_ranges = 0;
+ break;
}
- int end_index_f = end_range - 1;
+ int end_index_f = track_remove_it->end - 1;
if(end_index_f < start_index_f || end_index_f >= num_tracked_items) {
- fprintf(stderr, "Invalid item end range: %d, expected a value between %d and %d\n", end_index_f, start_range, num_tracked_items);
- continue;
+ fprintf(stderr, "Invalid item end range: %d, expected a value between %d and %d\n", end_index_f, track_remove_it->start, num_tracked_items);
+ valid_ranges = 0;
+ break;
}
- for(;;) {
- fprintf(stderr, "==> Are you sure you want to stop tracking:\n");
- TrackedItemData *list_it = list_begin + start_index_f;
- TrackedItemData *list_end = list_begin + end_range;
- int index = 0;
- for(; list_it != list_end; ++list_it) {
- const char *name = path_get_filename(list_it->item_tracked_path);
- printf(" %s/%s\n", index < num_rss_items ? "rss" : "html", name);
- ++index;
- }
-
- fprintf(stderr, "==> Yes/No: ");
- fflush(stderr);
-
- char resp[128];
- if(!fgets(resp, sizeof(resp), stdin)) {
- fprintf(stderr, "Failed to read response from stdin\n");
- goto cleanup;
- }
- char *response_str = strip(resp);
- int response_len = strlen(response_str);
- fprintf(stderr, "response len: %d\n", response_len);
- if(response_len == 0)
+ for(size_t i = start_index_f; i <= (size_t)end_index_f; ++i) {
+ if(track_items_selected[i])
continue;
- if(response_str[0] == 'n' || response_str[0] == 'N') {
- goto cleanup;
- } else if(response_str[0] == 'y' || response_str[0] == 'Y') {
- TrackedItemData *list_it = list_begin + start_index_f;
- TrackedItemData *list_end = list_begin + end_range;
- for(; list_it != list_end; ++list_it) {
- const char *name = path_get_filename(list_it->item_tracked_path);
- if(remove_recursive(list_it->item_tracked_path) != 0) {
- fprintf(stderr, "Failed to remove %s/%s\n", index < num_rss_items ? "rss" : "html", name);
- goto cleanup;
- }
- fprintf(stderr, "Removed %s/%s\n", index < num_rss_items ? "rss" : "html", name);
- }
- goto cleanup;
- }
+ track_items_selected[i] = 1;
+ buffer_append(&tracks_to_remove, &i, sizeof(i));
+ }
+ }
+
+ if(!valid_ranges)
+ continue;
+
+ for(;;) {
+ size_t *tracks_to_remove_it = buffer_begin(&tracks_to_remove);
+ size_t *tracks_to_remove_end = buffer_end(&tracks_to_remove);
+ fprintf(stderr, "==> Are you sure you want to stop tracking:\n");
+ for(; tracks_to_remove_it != tracks_to_remove_end; ++tracks_to_remove_it) {
+ const size_t track_index = *tracks_to_remove_it;
+ TrackedItemData *track_item = &list_begin[track_index];
+ const char *name = path_get_filename(track_item->item_tracked_path);
+ printf(" %s/%s\n", track_index < (size_t)num_rss_items ? "rss" : "html", name);
}
+
+ fprintf(stderr, "==> Yes/No: ");
+ fflush(stderr);
+
+ if(!fgets(resp, sizeof(resp), stdin)) {
+ fprintf(stderr, "Failed to read response from stdin\n");
+ goto cleanup;
+ }
+
+ response_str = strip(resp);
+ response_len = strlen(response_str);
+ if(response_len == 0)
+ continue;
+
+ if(response_str[0] == 'n' || response_str[0] == 'N') {
+ goto cleanup;
+ } else if(response_str[0] == 'y' || response_str[0] == 'Y') {
+ break;
+ }
+ }
+
+ size_t *tracks_to_remove_it = buffer_begin(&tracks_to_remove);
+ size_t *tracks_to_remove_end = buffer_end(&tracks_to_remove);
+ for(; tracks_to_remove_it != tracks_to_remove_end; ++tracks_to_remove_it) {
+ const size_t track_index = *tracks_to_remove_it;
+ TrackedItemData *track_item = &list_begin[track_index];
+ const char *name = path_get_filename(track_item->item_tracked_path);
+ if(remove_recursive(track_item->item_tracked_path) != 0) {
+ fprintf(stderr, "Failed to remove %s/%s\n", track_index < (size_t)num_rss_items ? "rss" : "html", name);
+ goto cleanup;
+ }
+ fprintf(stderr, "Removed %s/%s\n", track_index < (size_t)num_rss_items ? "rss" : "html", name);
}
+ break;
}
cleanup:
+ buffer_deinit(&track_remove_ranges);
+ buffer_deinit(&tracks_to_remove);
+ free(track_items_selected);
+
list_it = buffer_begin(&tracked_items);
list_end = buffer_end(&tracked_items);
for(; list_it != list_end; ++list_it) {
diff --git a/src/track_remove_parser.c b/src/track_remove_parser.c
new file mode 100644
index 0000000..61c2375
--- /dev/null
+++ b/src/track_remove_parser.c
@@ -0,0 +1,133 @@
+#include "track_remove_parser.h"
+#include <stdio.h>
+
+typedef enum {
+ TR_TOK_RANGE,
+ TR_TOK_END_OF_FILE,
+ TR_TOK_INVALID
+} TrackRemoveToken;
+
+typedef struct {
+ const char *str;
+ size_t size;
+ size_t offset;
+ Range range;
+} TrackRemoveTokenizer;
+
+static int is_number(char c) {
+ return c >= '0' && c <= '9';
+}
+
+/* Returns non-0 value on overflow */
+static int string_to_num_unchecked(const char *str, size_t size, int *number) {
+ int result = 0;
+ for(size_t i = 0; i < size; ++i) {
+ const int result_before = result;
+ result *= 10;
+ result += (str[i] - '0');
+ /* overflow */
+ if(result <= result_before)
+ return 1;
+ }
+ *number = result;
+ return 0;
+}
+
+static void track_remover_tokenizer_init(TrackRemoveTokenizer *self, const char *str, size_t size) {
+ self->str = str;
+ self->size = size;
+ self->offset = 0;
+ self->range.start = 0;
+ self->range.end = 0;
+}
+
+static int track_remover_tokenizer_get_char(TrackRemoveTokenizer *self) {
+ if(self->offset < self->size)
+ return self->str[self->offset];
+ else
+ return '\0';
+}
+
+static TrackRemoveToken track_remover_tokenizer_next(TrackRemoveTokenizer *self) {
+ char c;
+ for(;;) {
+ c = track_remover_tokenizer_get_char(self);
+ if(c != ' ' && c != '\t')
+ break;
+ ++self->offset;
+ }
+
+ if(c >= '1' && c <= '9') {
+ size_t number_start = self->offset;
+ ++self->offset;
+
+ for(;;) {
+ c = track_remover_tokenizer_get_char(self);
+ if(!is_number(c))
+ break;
+ ++self->offset;
+ }
+
+ if(string_to_num_unchecked(self->str + number_start, self->offset - number_start, &self->range.start) != 0)
+ return TR_TOK_INVALID;
+
+ self->range.end = self->range.start;
+ if(c != '-')
+ return TR_TOK_RANGE;
+
+ ++self->offset;
+ c = track_remover_tokenizer_get_char(self);
+ if(!is_number(c))
+ return TR_TOK_INVALID;
+
+ number_start = self->offset;
+ ++self->offset;
+
+ for(;;) {
+ c = track_remover_tokenizer_get_char(self);
+ if(!is_number(c))
+ break;
+ ++self->offset;
+ }
+
+ if(string_to_num_unchecked(self->str + number_start, self->offset - number_start, &self->range.end) != 0)
+ return TR_TOK_INVALID;
+
+ return TR_TOK_RANGE;
+ } else if(c == '\0') {
+ return TR_TOK_END_OF_FILE;
+ } else {
+ return TR_TOK_INVALID;
+ }
+}
+
+int track_remove_parser_parse(const char *str, size_t size, Buffer /*Range*/ *ranges) {
+ int num_ranges = 0;
+ TrackRemoveTokenizer tokenizer;
+ track_remover_tokenizer_init(&tokenizer, str, size);
+
+ for(;;) {
+ TrackRemoveToken token = track_remover_tokenizer_next(&tokenizer);
+ if(token == TR_TOK_RANGE) {
+ if(tokenizer.range.start > tokenizer.range.end) {
+ fprintf(stderr, "Invalid number range. The start range can't be past the end range\n");
+ return 1;
+ }
+
+ buffer_append(ranges, &tokenizer.range, sizeof(tokenizer.range));
+ ++num_ranges;
+ } else if(token == TR_TOK_END_OF_FILE) {
+ break;
+ } else {
+ fprintf(stderr, "Invalid input. Expected numbers and/or number ranges\n");
+ return 1;
+ }
+ }
+
+ if(num_ranges == 0) {
+ fprintf(stderr, "Invalid input. Expected numbers and/or number ranges\n");
+ return 1;
+ }
+
+ return 0;
+}
diff --git a/src/track_remove_parser.h b/src/track_remove_parser.h
new file mode 100644
index 0000000..1783cc8
--- /dev/null
+++ b/src/track_remove_parser.h
@@ -0,0 +1,17 @@
+#ifndef TRACK_REMOVE_PARSER_H
+#define TRACK_REMOVE_PARSER_H
+
+#include "buffer.h"
+
+typedef struct {
+ int start;
+ int end;
+} Range;
+
+/*
+ |ranges| should be initialized before calling this.
+ Returns 0 on success.
+*/
+int track_remove_parser_parse(const char *str, size_t size, Buffer /*Range*/ *ranges);
+
+#endif