summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--catgirl.117
-rw-r--r--chat.c4
-rw-r--r--chat.h2
-rw-r--r--command.c5
-rw-r--r--url.c57
5 files changed, 83 insertions, 2 deletions
diff --git a/catgirl.1 b/catgirl.1
index 6129b71..4dabb4f 100644
--- a/catgirl.1
+++ b/catgirl.1
@@ -9,6 +9,7 @@
.Sh SYNOPSIS
.Nm
.Op Fl ev
+.Op Fl C Ar copy
.Op Fl O Ar open
.Op Fl a Ar auth
.Op Fl c Ar cert
@@ -47,8 +48,17 @@ following their corresponding flags.
.Pp
The arguments are as follows:
.Bl -tag -width Ds
+.It Fl C Ar util , Cm copy = Ar util
+Set the utility used by
+.Ic /copy .
+The default is the first available of
+.Xr pbcopy 1 ,
+.Xr wl-copy 1 ,
+.Xr xclip 1 ,
+.Xr xsel 1 .
+.
.It Fl O Ar util , Cm open = Ar util
-Set the command used by
+Set the utility used by
.Ic /open .
The default is the first available of
.Xr open 1 ,
@@ -160,6 +170,11 @@ Show or set the topic of the channel.
.Bl -tag -width Ds
.It Ic /close Op Ar name | num
Close the named, numbered or current window.
+.It Ic /copy Op Ar nick | substring
+Copy the most recent URL from
+.Ar nick
+or matching
+.Ar substring .
.It Ic /debug
Toggle logging in the
.Sy <debug>
diff --git a/chat.c b/chat.c
index 77aa61d..dbad242 100644
--- a/chat.c
+++ b/chat.c
@@ -81,9 +81,10 @@ int main(int argc, char *argv[]) {
const char *user = NULL;
const char *real = NULL;
- const char *Opts = "!O:a:c:eh:j:k:n:p:r:u:vw:";
+ const char *Opts = "!C:O:a:c:eh:j:k:n:p:r:u:vw:";
const struct option LongOpts[] = {
{ "insecure", no_argument, NULL, '!' },
+ { "copy", required_argument, NULL, 'C' },
{ "open", required_argument, NULL, 'O' },
{ "sasl-plain", required_argument, NULL, 'a' },
{ "cert", required_argument, NULL, 'c' },
@@ -104,6 +105,7 @@ int main(int argc, char *argv[]) {
while (0 < (opt = getopt_config(argc, argv, Opts, LongOpts, NULL))) {
switch (opt) {
break; case '!': insecure = true;
+ break; case 'C': urlCopyUtil = optarg;
break; case 'O': urlOpenUtil = optarg;
break; case 'a': sasl = true; self.plain = optarg;
break; case 'c': cert = optarg;
diff --git a/chat.h b/chat.h
index 3084359..8bc8e81 100644
--- a/chat.h
+++ b/chat.h
@@ -170,9 +170,11 @@ size_t completeID(const char *str);
enum Color completeColor(size_t id, const char *str);
extern const char *urlOpenUtil;
+extern const char *urlCopyUtil;
void urlScan(size_t id, const char *nick, const char *mesg);
void urlOpenCount(size_t id, size_t count);
void urlOpenMatch(size_t id, const char *str);
+void urlCopyMatch(size_t id, const char *str);
FILE *configOpen(const char *path, const char *mode);
int getopt_config(
diff --git a/command.c b/command.c
index 4100928..feb52b7 100644
--- a/command.c
+++ b/command.c
@@ -154,11 +154,16 @@ static void commandOpen(size_t id, char *params) {
}
}
+static void commandCopy(size_t id, char *params) {
+ urlCopyMatch(id, params);
+}
+
static const struct Handler {
const char *cmd;
Command *fn;
} Commands[] = {
{ "/close", commandClose },
+ { "/copy", commandCopy },
{ "/debug", commandDebug },
{ "/join", commandJoin },
{ "/me", commandMe },
diff --git a/url.c b/url.c
index c9c4d5c..7ab1e53 100644
--- a/url.c
+++ b/url.c
@@ -122,6 +122,47 @@ static void urlOpen(const char *url) {
_exit(EX_CONFIG);
}
+const char *urlCopyUtil;
+static const char *CopyUtils[] = { "pbcopy", "wl-copy", "xclip", "xsel" };
+
+static void urlCopy(const char *url) {
+ int rw[2];
+ int error = pipe(rw);
+ if (error) err(EX_OSERR, "pipe");
+
+ ssize_t len = write(rw[1], url, strlen(url));
+ if (len < 0) err(EX_IOERR, "write");
+
+ error = close(rw[1]);
+ if (error) err(EX_IOERR, "close");
+
+ pid_t pid = fork();
+ if (pid < 0) err(EX_OSERR, "fork");
+ if (pid) {
+ close(rw[0]);
+ return;
+ }
+
+ dup2(rw[0], STDIN_FILENO);
+ dup2(procPipe[1], STDOUT_FILENO);
+ dup2(procPipe[1], STDERR_FILENO);
+ close(rw[0]);
+ if (urlCopyUtil) {
+ execlp(urlCopyUtil, urlCopyUtil, NULL);
+ warn("%s", urlCopyUtil);
+ _exit(EX_CONFIG);
+ }
+ for (size_t i = 0; i < ARRAY_LEN(CopyUtils); ++i) {
+ execlp(CopyUtils[i], CopyUtils[i], NULL);
+ if (errno != ENOENT) {
+ warn("%s", CopyUtils[i]);
+ _exit(EX_CONFIG);
+ }
+ }
+ warnx("no copy utility found");
+ _exit(EX_CONFIG);
+}
+
void urlOpenCount(size_t id, size_t count) {
for (size_t i = 1; i <= Cap; ++i) {
const struct URL *url = &ring.urls[(ring.len - i) % Cap];
@@ -143,3 +184,19 @@ void urlOpenMatch(size_t id, const char *str) {
}
}
}
+
+void urlCopyMatch(size_t id, const char *str) {
+ for (size_t i = 1; i <= Cap; ++i) {
+ const struct URL *url = &ring.urls[(ring.len - i) % Cap];
+ if (!url->url) break;
+ if (url->id != id) continue;
+ if (
+ !str
+ || (url->nick && !strcmp(url->nick, str))
+ || strstr(url->url, str)
+ ) {
+ urlCopy(url->url);
+ break;
+ }
+ }
+}