summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Friesel <derf@finalrewind.org>2018-11-18 21:26:43 +0100
committerDaniel Friesel <derf@finalrewind.org>2018-11-18 21:26:43 +0100
commit55c27c4babcf63989192f930ba7a75dac691e1e5 (patch)
tree98dce8b6dd50468039c77d37740fb9ea651325c9
parent05ab8b3318c187c26205a6d5c0d7e6295d252b94 (diff)
--start-at: Compare basenames if exact match failed
This more closely resembles the expected behaviour of --start-at, but may lead to mismatches if several files in the filelist have the same basename. Closes #206 Related to #372 and #420
-rw-r--r--man/feh.pre23
-rw-r--r--src/slideshow.c46
2 files changed, 56 insertions, 13 deletions
diff --git a/man/feh.pre b/man/feh.pre
index 173410e..e401ab5 100644
--- a/man/feh.pre
+++ b/man/feh.pre
@@ -729,20 +729,17 @@ to sort numbers naturally, so that e.g. 10.jpg comes after 2.jpg.
Start the filelist at
.Ar filename .
.
-Note that at the moment,
+If you use relative paths in your filelist,
.Ar filename
-must match an
-.Pq expanded
-path in the filelist.
-So, if the file to be matched is passed via an absolute path in the filelist,
-.Ar filename
-must be an absolute path.
-If the file is passed via a relative path,
-.Ar filename
-must be an identical relative path.
-This is a known issue.
-See also
-.Sx USAGE EXAMPLES .
+should also be a relative path.
+If you use absolute paths, it should also be an absolute path.
+.
+If
+.Nm
+cannot find an exact match, it will compare basenames
+.Pq filenames without the directory suffix .
+Note that this may lead to mismatches if several files in your filelist
+have the same basename.
.
.It Cm -T , --theme Ar theme
.
diff --git a/src/slideshow.c b/src/slideshow.c
index 145bee1..145ced1 100644
--- a/src/slideshow.c
+++ b/src/slideshow.c
@@ -37,6 +37,24 @@ void init_slideshow_mode(void)
int success = 0;
gib_list *l = filelist, *last = NULL;
+ /*
+ * In theory, --start-at FILENAME is simple: Look for a file called
+ * FILENAME, start the filelist there, done.
+ *
+ * In practice, there are cases where this isn't sufficient. For instance,
+ * a user running 'feh --start-at hello.jpg /tmp' will expect feh to start
+ * at /tmp/hello.jpg, as if they had used
+ * 'feh --start-at /tmp/hello.jpg /tmp'. Similarly, XDG Desktop files
+ * may lead to the invocation 'feh --start-at /tmp/hello.jpg .' in /tmp,
+ * expecting the behaviour of 'feh --start-at ./hello.jpg .'.
+ *
+ * Since a good user experience is not about being technically correct, but
+ * about delivering the expected behaviour, we do some fuzzy matching
+ * here. In the worst case, this will cause --start-at to start at the
+ * wrong file.
+ */
+
+ // Try finding an exact filename match first
for (; l && opt.start_list_at; l = l->next) {
if (!strcmp(opt.start_list_at, FEH_FILE(l->data)->filename)) {
opt.start_list_at = NULL;
@@ -44,6 +62,34 @@ void init_slideshow_mode(void)
}
}
+ /*
+ * If it didn't work (opt.start_list_at is still set): Fall back to
+ * comparing just the filenames without directory prefixes. This may lead
+ * to false positives, but for now that's just the way it is.
+ */
+ if (opt.start_list_at) {
+ char *current_filename;
+ char *start_at_filename = strrchr(opt.start_list_at, '/');
+ if (start_at_filename) {
+ start_at_filename++; // We only care about the part after the '/'
+ } else {
+ start_at_filename = opt.start_list_at;
+ }
+ for (l = filelist; l && opt.start_list_at; l = l->next) {
+ current_filename = strrchr(FEH_FILE(l->data)->filename, '/');
+ if (current_filename) {
+ current_filename++; // We only care about the part after the '/'
+ } else {
+ current_filename = FEH_FILE(l->data)->filename;
+ }
+ if (!strcmp(start_at_filename, current_filename)) {
+ opt.start_list_at = NULL;
+ break;
+ }
+ }
+ }
+
+ // If that didn't work either, we're out of luck.
if (opt.start_list_at)
eprintf("--start-at %s: File not found in filelist",
opt.start_list_at);