Add /copy

master
C. McEnroe 2020-02-08 21:44:50 -05:00
parent 2db17e83a9
commit 3e68684148
5 changed files with 83 additions and 2 deletions

View File

@ -9,6 +9,7 @@
.Sh SYNOPSIS .Sh SYNOPSIS
.Nm .Nm
.Op Fl ev .Op Fl ev
.Op Fl C Ar copy
.Op Fl O Ar open .Op Fl O Ar open
.Op Fl a Ar auth .Op Fl a Ar auth
.Op Fl c Ar cert .Op Fl c Ar cert
@ -47,8 +48,17 @@ following their corresponding flags.
.Pp .Pp
The arguments are as follows: The arguments are as follows:
.Bl -tag -width Ds .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 .It Fl O Ar util , Cm open = Ar util
Set the command used by Set the utility used by
.Ic /open . .Ic /open .
The default is the first available of The default is the first available of
.Xr open 1 , .Xr open 1 ,
@ -160,6 +170,11 @@ Show or set the topic of the channel.
.Bl -tag -width Ds .Bl -tag -width Ds
.It Ic /close Op Ar name | num .It Ic /close Op Ar name | num
Close the named, numbered or current window. 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 .It Ic /debug
Toggle logging in the Toggle logging in the
.Sy <debug> .Sy <debug>

4
chat.c
View File

@ -81,9 +81,10 @@ int main(int argc, char *argv[]) {
const char *user = NULL; const char *user = NULL;
const char *real = 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[] = { const struct option LongOpts[] = {
{ "insecure", no_argument, NULL, '!' }, { "insecure", no_argument, NULL, '!' },
{ "copy", required_argument, NULL, 'C' },
{ "open", required_argument, NULL, 'O' }, { "open", required_argument, NULL, 'O' },
{ "sasl-plain", required_argument, NULL, 'a' }, { "sasl-plain", required_argument, NULL, 'a' },
{ "cert", required_argument, NULL, 'c' }, { "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))) { while (0 < (opt = getopt_config(argc, argv, Opts, LongOpts, NULL))) {
switch (opt) { switch (opt) {
break; case '!': insecure = true; break; case '!': insecure = true;
break; case 'C': urlCopyUtil = optarg;
break; case 'O': urlOpenUtil = optarg; break; case 'O': urlOpenUtil = optarg;
break; case 'a': sasl = true; self.plain = optarg; break; case 'a': sasl = true; self.plain = optarg;
break; case 'c': cert = optarg; break; case 'c': cert = optarg;

2
chat.h
View File

@ -170,9 +170,11 @@ size_t completeID(const char *str);
enum Color completeColor(size_t id, const char *str); enum Color completeColor(size_t id, const char *str);
extern const char *urlOpenUtil; extern const char *urlOpenUtil;
extern const char *urlCopyUtil;
void urlScan(size_t id, const char *nick, const char *mesg); void urlScan(size_t id, const char *nick, const char *mesg);
void urlOpenCount(size_t id, size_t count); void urlOpenCount(size_t id, size_t count);
void urlOpenMatch(size_t id, const char *str); void urlOpenMatch(size_t id, const char *str);
void urlCopyMatch(size_t id, const char *str);
FILE *configOpen(const char *path, const char *mode); FILE *configOpen(const char *path, const char *mode);
int getopt_config( int getopt_config(

View File

@ -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 { static const struct Handler {
const char *cmd; const char *cmd;
Command *fn; Command *fn;
} Commands[] = { } Commands[] = {
{ "/close", commandClose }, { "/close", commandClose },
{ "/copy", commandCopy },
{ "/debug", commandDebug }, { "/debug", commandDebug },
{ "/join", commandJoin }, { "/join", commandJoin },
{ "/me", commandMe }, { "/me", commandMe },

57
url.c
View File

@ -122,6 +122,47 @@ static void urlOpen(const char *url) {
_exit(EX_CONFIG); _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) { void urlOpenCount(size_t id, size_t count) {
for (size_t i = 1; i <= Cap; ++i) { for (size_t i = 1; i <= Cap; ++i) {
const struct URL *url = &ring.urls[(ring.len - i) % Cap]; 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;
}
}
}