diff --git a/src/dorem.c b/src/dorem.c index ecc28e09..cf49af13 100644 --- a/src/dorem.c +++ b/src/dorem.c @@ -406,7 +406,78 @@ int DoRem(ParsePtr p) return OK; } - if ( (r=TriggerReminder(p, &trig, &tim, dse, 0, NULL)) ) { + if (JSONMode) { + DynamicBuffer body; + int y, m, d; + char *s; + int if_depth = get_if_pointer() - get_base_if_pointer(); + DBufInit(&body); + int red=-1, green=-1, blue=-1; + r=TriggerReminder(p, &trig, &tim, dse, 0, &body, &red, &green, &blue); + if (r) { + FreeTrig(&trig); + return r; + } + /* Remove trailing newlines from body */ + s = (char *) DBufValue(&body) + DBufLen(&body) - 1; + while (s >= DBufValue(&body)) { + if (*s == '\n') { + *s = 0; + s--; + } else { + break; + } + } + if (!*DBufValue(&body)) { + FreeTrig(&trig); + return r; + } + if (JSONLinesEmitted) { + printf("},\n"); + } + JSONLinesEmitted++; + FromDSE(dse, &y, &m, &d); + printf("{\"date\":\"%04d-%02d-%02d\",", y, m+d, d); + PrintJSONKeyPairString("filename", GetCurrentFilename()); + PrintJSONKeyPairInt("lineno", LineNo); + if (LineNoStart != LineNo) { + PrintJSONKeyPairInt("lineno_start", LineNoStart); + } + PrintJSONKeyPairString("passthru", trig.passthru); + PrintJSONKeyPairString("tags", DBufValue(&(trig.tags))); + if (trig.infos) { + WriteJSONInfoChain(trig.infos); + } + if (trig.duration_days) { + PrintJSONKeyPairInt("duration", trig.duration_days); + } + if (tim.ttime != NO_TIME) { + PrintJSONKeyPairInt("time", tim.ttime); + } + if (p->nonconst_expr) { + PrintJSONKeyPairInt("nonconst_expr", 1); + } + if (if_depth) { + PrintJSONKeyPairInt("if_depth", if_depth); + } + if (tim.delta) { + PrintJSONKeyPairInt("tdelta", tim.delta); + } + if (tim.rep) { + PrintJSONKeyPairInt("trep", tim.rep); + } + if (red >= 0 && red <= 255 && green >= 0 && green <= 255 && blue >=0 && blue <= 255) { + PrintJSONKeyPairInt("r", red); + PrintJSONKeyPairInt("g", green); + PrintJSONKeyPairInt("b", blue); + } + + WriteJSONTrigger(&trig, 0); + printf("\"body\":\""); + PrintJSONString(DBufValue(&body)); + printf("\""); + } else { + r=TriggerReminder(p, &trig, &tim, dse, 0, NULL, NULL, NULL, NULL); FreeTrig(&trig); return r; } @@ -1217,7 +1288,7 @@ static int ParseScanFrom(ParsePtr s, Trigger *t, int type) /* Trigger the reminder if it's a RUN or MSG type. */ /* */ /***************************************************************/ -int TriggerReminder(ParsePtr p, Trigger *t, TimeTrig const *tim, int dse, int is_queued, DynamicBuffer *output) +int TriggerReminder(ParsePtr p, Trigger *t, TimeTrig const *tim, int dse, int is_queued, DynamicBuffer *output, int *rr, int *gg, int *bb) { int r, y, m, d; int adjusted_for_newline = 0; @@ -1290,7 +1361,9 @@ int TriggerReminder(ParsePtr p, Trigger *t, TimeTrig const *tim, int dse, int is if (!DoSubstFromString(DBufValue(&Banner), &buf, DSEToday, NO_TIME) && DBufLen(&buf)) { - printf("%s\n", DBufValue(&buf)); + if (!JSONMode) { + printf("%s\n", DBufValue(&buf)); + } } DBufFree(&buf); } @@ -1367,7 +1440,7 @@ int TriggerReminder(ParsePtr p, Trigger *t, TimeTrig const *tim, int dse, int is } /* Correct colors */ - if (UseVTColors) { + if (JSONMode || UseVTColors) { if (red == -1 && green == -1 && blue == -1) { if (DefaultColorR != -1 && DefaultColorG != -1 && DefaultColorB != -1) { red = DefaultColorR; @@ -1381,6 +1454,17 @@ int TriggerReminder(ParsePtr p, Trigger *t, TimeTrig const *tim, int dse, int is if (green > 255) green = 255; if (blue > 255) blue = 255; } + if (rr) *rr = red; + if (gg) *gg = green; + if (bb) *bb = blue; + + /* Don't ANSI-colorize JSON output! */ + if (JSONMode) { + is_color = 0; + red = -1; + green = -1; + blue = -1; + } } /* Put the substituted string into the substitution buffer */ diff --git a/src/globals.h b/src/globals.h index 0dfbfb80..f6b4bccc 100644 --- a/src/globals.h +++ b/src/globals.h @@ -57,6 +57,7 @@ EXTERN int WarnedAboutImplicit; EXTERN uid_t TrustedUsers[MAX_TRUSTED_USERS]; EXTERN INIT( int JSONMode, 0); +EXTERN INIT( int JSONLinesEmitted, 0); EXTERN INIT( int MaxLateMinutes, 0); EXTERN INIT( int NumTrustedUsers, 0); EXTERN INIT( char const *MsgCommand, NULL); diff --git a/src/init.c b/src/init.c index 1fe40014..0209c141 100644 --- a/src/init.c +++ b/src/init.c @@ -1141,6 +1141,7 @@ ProcessLongOption(char const *arg) } if (!strcmp(arg, "json")) { JSONMode = 1; + DontQueue = 1; return; } diff --git a/src/main.c b/src/main.c index 49d91d2f..1ca13b55 100644 --- a/src/main.c +++ b/src/main.c @@ -172,6 +172,9 @@ int main(int argc, char *argv[]) ShouldCache = (Iterations > 1); while (Iterations--) { + if (JSONMode) { + printf("[\n"); + } PerIterationInit(); DoReminders(); @@ -194,7 +197,9 @@ int main(int argc, char *argv[]) Eprint("%s", GetErr(E_PUSHF_NO_POP)); } if (!Daemon && !NextMode && !NumTriggered && !NumQueued) { - printf("%s\n", GetErr(E_NOREMINDERS)); + if (!JSONMode) { + printf("%s\n", GetErr(E_NOREMINDERS)); + } } else if (!Daemon && !NextMode && !NumTriggered) { printf(GetErr(M_QUEUED), NumQueued); printf("\n"); @@ -204,6 +209,12 @@ int main(int argc, char *argv[]) /* If there are sorted reminders, handle them */ if (SortByDate) IssueSortedReminders(); + if (JSONMode) { + if (JSONLinesEmitted) { + printf("}\n"); + } + printf("]\n"); + } /* If there are any background reminders queued up, handle them */ if (NumQueued || Daemon) { @@ -252,6 +263,7 @@ PerIterationInit(void) DefaultColorG = -1; DefaultColorB = -1; NumTriggered = 0; + JSONLinesEmitted = 0; ClearLastTriggers(); ClearDedupeTable(); } diff --git a/src/protos.h b/src/protos.h index 538fc997..7121a1ea 100644 --- a/src/protos.h +++ b/src/protos.h @@ -51,7 +51,7 @@ int DoRem (ParsePtr p); int DoFlush (ParsePtr p); void DoExit (ParsePtr p); int ParseRem (ParsePtr s, Trigger *trig, TimeTrig *tim); -int TriggerReminder (ParsePtr p, Trigger *t, TimeTrig const *tim, int dse, int is_queued, DynamicBuffer *output); +int TriggerReminder (ParsePtr p, Trigger *t, TimeTrig const *tim, int dse, int is_queued, DynamicBuffer *output, int *r, int *g, int *b); int ShouldTriggerReminder (Trigger const *t, TimeTrig const *tim, int dse, int *err); int DoSubst (ParsePtr p, DynamicBuffer *dbuf, Trigger *t, TimeTrig const *tt, int dse, int mode); int DoSubstFromString (char const *source, DynamicBuffer *dbuf, int dse, int tim); diff --git a/src/queue.c b/src/queue.c index d59ea169..d23df402 100644 --- a/src/queue.c +++ b/src/queue.c @@ -436,7 +436,7 @@ void HandleQueuedReminders(void) if (DaemonJSON) { DynamicBuffer out; DBufInit(&out); - (void) TriggerReminder(&p, &tcopy, &q->tt, DSEToday, 1, &out); + (void) TriggerReminder(&p, &tcopy, &q->tt, DSEToday, 1, &out, NULL, NULL, NULL); if (q->typ != RUN_TYPE) { printf("\"body\":\""); chomp(&out); @@ -445,7 +445,7 @@ void HandleQueuedReminders(void) } DBufFree(&out); } else { - (void) TriggerReminder(&p, &tcopy, &q->tt, DSEToday, 1, NULL); + (void) TriggerReminder(&p, &tcopy, &q->tt, DSEToday, 1, NULL, NULL, NULL, NULL); } if (IsServerMode() && !DaemonJSON && q->typ != RUN_TYPE) { printf("NOTE endreminder\n");