Add -N flag for notifications

master
C. McEnroe 2020-02-12 20:12:34 -05:00
parent 4198f67aa2
commit 180bbc7b38
5 changed files with 72 additions and 17 deletions

View File

@ -1,4 +1,4 @@
.Dd February 11, 2020 .Dd February 12, 2020
.Dt CATGIRL 1 .Dt CATGIRL 1
.Os .Os
. .
@ -11,6 +11,7 @@
.Op Fl Rev .Op Fl Rev
.Op Fl C Ar copy .Op Fl C Ar copy
.Op Fl H Ar hash .Op Fl H Ar hash
.Op Fl N Ar send
.Op Fl O Ar open .Op Fl O Ar open
.Op Fl S Ar bind .Op Fl S Ar bind
.Op Fl a Ar auth .Op Fl a Ar auth
@ -66,6 +67,16 @@ The default is the first available of
Set the initial value of Set the initial value of
the nick color hash function. the nick color hash function.
. .
.It Fl N Ar util , Cm notify = Ar util
Send notifications using a utility.
Use more than once to add arguments to
.Ar util .
Two additional arguments are passed to
.Ar util :
a title and a description,
appropriate for
.Xr notify-send 1 .
.
.It Fl O Ar util , Cm open = Ar util .It Fl O Ar util , Cm open = Ar util
Set the utility used by Set the utility used by
.Ic /open . .Ic /open .

4
chat.c
View File

@ -94,11 +94,12 @@ 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 = "!C:H:O:RS:a:c:eh:j:k:n:p:r:s:u:vw:"; const char *Opts = "!C:H:N:O:RS:a:c:eh:j:k:n:p:r:s:u:vw:";
const struct option LongOpts[] = { const struct option LongOpts[] = {
{ "insecure", no_argument, NULL, '!' }, { "insecure", no_argument, NULL, '!' },
{ "copy", required_argument, NULL, 'C' }, { "copy", required_argument, NULL, 'C' },
{ "hash", required_argument, NULL, 'H' }, { "hash", required_argument, NULL, 'H' },
{ "notify", required_argument, NULL, 'N' },
{ "open", required_argument, NULL, 'O' }, { "open", required_argument, NULL, 'O' },
{ "restrict", no_argument, NULL, 'R' }, { "restrict", no_argument, NULL, 'R' },
{ "bind", required_argument, NULL, 'S' }, { "bind", required_argument, NULL, 'S' },
@ -124,6 +125,7 @@ int main(int argc, char *argv[]) {
break; case '!': insecure = true; break; case '!': insecure = true;
break; case 'C': utilPush(&urlCopyUtil, optarg); break; case 'C': utilPush(&urlCopyUtil, optarg);
break; case 'H': hashInit = strtoul(optarg, NULL, 0); break; case 'H': hashInit = strtoul(optarg, NULL, 0);
break; case 'N': utilPush(&uiNotifyUtil, optarg);
break; case 'O': utilPush(&urlOpenUtil, optarg); break; case 'O': utilPush(&urlOpenUtil, optarg);
break; case 'R': self.restricted = true; break; case 'R': self.restricted = true;
break; case 'S': bind = optarg; break; case 'S': bind = optarg;

29
chat.h
View File

@ -146,7 +146,22 @@ const char *commandIsNotice(size_t id, const char *input);
const char *commandIsAction(size_t id, const char *input); const char *commandIsAction(size_t id, const char *input);
void commandComplete(void); void commandComplete(void);
enum { UtilCap = 16 };
struct Util {
size_t argc;
const char *argv[UtilCap];
};
static inline void utilPush(struct Util *util, const char *arg) {
if (1 + util->argc < UtilCap) {
util->argv[util->argc++] = arg;
} else {
errx(EX_CONFIG, "too many utility arguments");
}
}
enum Heat { Cold, Warm, Hot }; enum Heat { Cold, Warm, Hot };
extern struct Util uiNotifyUtil;
void uiInit(void); void uiInit(void);
void uiShow(void); void uiShow(void);
void uiHide(void); void uiHide(void);
@ -196,20 +211,6 @@ void completeClear(size_t id);
size_t completeID(const char *str); size_t completeID(const char *str);
enum Color completeColor(size_t id, const char *str); enum Color completeColor(size_t id, const char *str);
enum { UtilCap = 16 };
struct Util {
size_t argc;
const char *argv[UtilCap];
};
static inline void utilPush(struct Util *util, const char *arg) {
if (1 + util->argc < UtilCap) {
util->argv[util->argc++] = arg;
} else {
errx(EX_CONFIG, "too many utility arguments");
}
}
extern struct Util urlOpenUtil; extern struct Util urlOpenUtil;
extern struct Util urlCopyUtil; extern struct Util urlCopyUtil;
void urlScan(size_t id, const char *nick, const char *mesg); void urlScan(size_t id, const char *nick, const char *mesg);

View File

@ -0,0 +1,9 @@
#!/usr/bin/osascript
on run argv
if count of argv is 2 then
display notification (item 2 of argv) with title (item 1 of argv)
else
display notification (item 1 of argv)
end if
end run

34
ui.c
View File

@ -530,6 +530,35 @@ static int wordWrap(WINDOW *win, const char *str) {
return lines; return lines;
} }
struct Util uiNotifyUtil;
static void notify(size_t id, const char *str) {
if (!uiNotifyUtil.argc) return;
struct Util util = uiNotifyUtil;
utilPush(&util, idNames[id]);
size_t len = 0;
char buf[1024] = "";
while (*str && len < sizeof(buf)) {
size_t run;
struct Style style = Reset;
styleParse(&style, &str, &run);
len += snprintf(&buf[len], sizeof(buf) - len, "%.*s", (int)run, str);
str += run;
}
utilPush(&util, buf);
pid_t pid = fork();
if (pid < 0) err(EX_OSERR, "fork");
if (pid) return;
close(STDIN_FILENO);
dup2(procPipe[1], STDOUT_FILENO);
dup2(procPipe[1], STDERR_FILENO);
execvp(util.argv[0], (char *const *)util.argv);
warn("%s", util.argv[0]);
_exit(EX_CONFIG);
}
void uiWrite(size_t id, enum Heat heat, const time_t *src, const char *str) { void uiWrite(size_t id, enum Heat heat, const time_t *src, const char *str) {
struct Window *window = windowFor(id); struct Window *window = windowFor(id);
time_t clock = (src ? *src : time(NULL)); time_t clock = (src ? *src : time(NULL));
@ -548,7 +577,10 @@ void uiWrite(size_t id, enum Heat heat, const time_t *src, const char *str) {
lines += wordWrap(window->pad, str); lines += wordWrap(window->pad, str);
window->unreadLines += lines; window->unreadLines += lines;
if (window->scroll) windowScroll(window, lines); if (window->scroll) windowScroll(window, lines);
if (heat > Warm) beep(); if (window->mark && heat > Warm) {
beep();
notify(id, str);
}
} }
void uiFormat( void uiFormat(