Add /copy
parent
2db17e83a9
commit
3e68684148
17
catgirl.1
17
catgirl.1
|
@ -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
4
chat.c
|
@ -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
2
chat.h
|
@ -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(
|
||||||
|
|
|
@ -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
57
url.c
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue