about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--chat.h3
-rw-r--r--chatte.18
-rw-r--r--input.c11
-rw-r--r--url.c25
4 files changed, 38 insertions, 9 deletions
diff --git a/chat.h b/chat.h
index 2ee80db..9bd1d3c 100644
--- a/chat.h
+++ b/chat.h
@@ -158,7 +158,8 @@ void tabReject(void);
 
 void urlScan(struct Tag tag, const char *str);
 void urlList(struct Tag tag);
-void urlOpen(struct Tag tag, size_t at, size_t to);
+void urlOpenMatch(struct Tag tag, const char *substr);
+void urlOpenRange(struct Tag tag, size_t at, size_t to);
 
 void logOpen(const char *path);
 void logFmt(
diff --git a/chatte.1 b/chatte.1
index 4dce17b..980b152 100644
--- a/chatte.1
+++ b/chatte.1
@@ -131,6 +131,14 @@ The default
 .Ar range
 is 1.
 .
+.It Ic /open Ar substring
+Open the most recent URL
+appearing in the current view
+matching
+.Ar substring
+with
+.Xr open 1 .
+.
 .It Ic /part
 Leave the current channel.
 .
diff --git a/input.c b/input.c
index 6e95b11..4497010 100644
--- a/input.c
+++ b/input.c
@@ -14,6 +14,7 @@
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
+#include <ctype.h>
 #include <err.h>
 #include <stdbool.h>
 #include <stdio.h>
@@ -107,9 +108,13 @@ static void inputUrl(struct Tag tag, char *params) {
 	urlList(tag);
 }
 static void inputOpen(struct Tag tag, char *params) {
-	size_t at = (params ? strtoul(strsep(&params, "-,"), NULL, 0) : 1);
-	size_t to = (params ? strtoul(params, NULL, 0) : at);
-	urlOpen(tag, at - 1, to);
+	if (params && !isdigit(params[0])) {
+		urlOpenMatch(tag, params);
+	} else {
+		size_t at = (params ? strtoul(strsep(&params, "-,"), NULL, 0) : 1);
+		size_t to = (params ? strtoul(params, NULL, 0) : at);
+		urlOpenRange(tag, at - 1, to);
+	}
 }
 
 static void inputView(struct Tag tag, char *params) {
diff --git a/url.c b/url.c
index 902128a..a398778 100644
--- a/url.c
+++ b/url.c
@@ -43,7 +43,7 @@ static struct {
 	size_t end;
 } ring;
 
-static void push(struct Tag tag, const char *url, size_t len) {
+static void ringPush(struct Tag tag, const char *url, size_t len) {
 	free(ring.buf[ring.end].url);
 	ring.buf[ring.end].tag = tag.id;
 	ring.buf[ring.end].url = strndup(url, len);
@@ -51,13 +51,17 @@ static void push(struct Tag tag, const char *url, size_t len) {
 	ring.end = (ring.end + 1) & (RingLen - 1);
 }
 
+static struct Entry ringEntry(size_t i) {
+	return ring.buf[(ring.end + i) & (RingLen - 1)];
+}
+
 void urlScan(struct Tag tag, const char *str) {
 	while (str[0]) {
 		size_t len = 1;
 		for (size_t i = 0; i < SchemesLen; ++i) {
 			if (strncmp(str, Schemes[i], strlen(Schemes[i]))) continue;
 			len = strcspn(str, " >\"");
-			push(tag, str, len);
+			ringPush(tag, str, len);
 		}
 		str = &str[len];
 	}
@@ -66,18 +70,29 @@ void urlScan(struct Tag tag, const char *str) {
 void urlList(struct Tag tag) {
 	uiHide();
 	for (size_t i = 0; i < RingLen; ++i) {
-		struct Entry entry = ring.buf[(ring.end + i) & (RingLen - 1)];
+		struct Entry entry = ringEntry(i);
 		if (!entry.url || entry.tag != tag.id) continue;
 		printf("%s\n", entry.url);
 	}
 }
 
-void urlOpen(struct Tag tag, size_t at, size_t to) {
+void urlOpenMatch(struct Tag tag, const char *substr) {
+	for (size_t i = RingLen - 1; i < RingLen; --i) {
+		struct Entry entry = ringEntry(i);
+		if (!entry.url || entry.tag != tag.id) continue;
+		if (!strstr(entry.url, substr)) continue;
+		char *argv[] = { "open", entry.url, NULL };
+		eventPipe(argv);
+		break;
+	}
+}
+
+void urlOpenRange(struct Tag tag, size_t at, size_t to) {
 	size_t argc = 1;
 	char *argv[2 + RingLen] = { "open" };
 	size_t tagIndex = 0;
 	for (size_t i = RingLen - 1; i < RingLen; --i) {
-		struct Entry entry = ring.buf[(ring.end + i) & (RingLen - 1)];
+		struct Entry entry = ringEntry(i);
 		if (!entry.url || entry.tag != tag.id) continue;
 		if (tagIndex >= at && tagIndex < to) argv[argc++] = entry.url;
 		tagIndex++;