Introduction
Introduction Statistics Contact Development Disclaimer Help
let user choose extra fields to print and custom date formats - ics2txt - conve…
git clone git://bitreich.org/ics2txt git://enlrupgkhuxnvlhsf6lc3fziv5h2hhfrinws…
Log
Files
Refs
Tags
README
---
commit 8894359aa6ad4ccc485901a8af9db03d1a2b4d5f
parent 65778fa74c2e72ca67a8dc4f6c1f0021f8ce2de4
Author: Josuah Demangeon <[email protected]>
Date: Fri, 18 Jun 2021 08:58:21 +0200
let user choose extra fields to print and custom date formats
Diffstat:
M ical.c | 2 +-
M ics2tsv.c | 111 ++++++++++++++++++++++++++++-…
M util.c | 8 +++-----
M util.h | 2 +-
4 files changed, 108 insertions(+), 15 deletions(-)
---
diff --git a/ical.c b/ical.c
@@ -297,7 +297,7 @@ ical_getline(char **contentline, char **line, size_t *sz, F…
num++;
strchomp(*line);
- if (strappend(contentline, *line) < 0)
+ if (strappend(contentline, *line) == NULL)
return -1;
if ((c = fgetc(fp)) == EOF)
goto end;
diff --git a/ics2tsv.c b/ics2tsv.c
@@ -3,31 +3,49 @@
#include <stdlib.h>
#include <string.h>
#include <strings.h>
+#include <time.h>
+#include <unistd.h>
#include "ical.h"
#include "util.h"
-#define FIELDS_MAX 64
+#define FIELDS_MAX 128
typedef struct Field Field;
typedef struct Block Block;
+struct Field {
+ char *key;
+ char *value;
+};
+
struct Block {
time_t beg, end;
char *fields[FIELDS_MAX];
};
-Block block;
+static char default_fields[] = "CATEGORIES,LOCATION,SUMMARY,DESCRIPTION";
+static char *flag_s = ",";
+static char *flag_t = NULL;
+static char *flag_f = default_fields;
+static char *fields[FIELDS_MAX];
+static Block block;
static int
fn_field_name(IcalParser *p, char *name)
{
+ (void)p;
+ (void)name;
+
return 0;
}
static int
fn_block_begin(IcalParser *p, char *name)
{
+ (void)p;
+ (void)name;
+
memset(&block, 0, sizeof block);
return 0;
}
@@ -35,9 +53,30 @@ fn_block_begin(IcalParser *p, char *name)
static int
fn_block_end(IcalParser *p, char *name)
{
+ char buf[128];
+ struct tm tm = {0};
+
+ (void)name;
+
if (p->blocktype == ICAL_BLOCK_OTHER)
return 0;
- printf("%s\t%lld\t%lld", p->current->name, block.beg, block.end);
+ fputs(p->current->name, stdout);
+
+ /* printing dates with %s is much much slower than %lld */
+ if (flag_t == NULL) {
+ printf("\t%lld\t%lld", block.beg, block.end);
+ } else {
+ strftime(buf, sizeof buf, flag_t, gmtime_r(&block.beg, &tm));
+ printf("\t%s", buf);
+ strftime(buf, sizeof buf, flag_t, gmtime_r(&block.end, &tm));
+ printf("\t%s", buf);
+ }
+
+ for (int i = 0; fields[i] != NULL; i++) {
+ fputc('\t', stdout);
+ if (block.fields[i] != NULL)
+ fputs(block.fields[i], stdout);
+ }
printf("\n");
return 0;
}
@@ -45,13 +84,17 @@ fn_block_end(IcalParser *p, char *name)
static int
fn_param_value(IcalParser *p, char *name, char *value)
{
+ (void)p;
+ (void)name;
+ (void)value;
+
return 0;
}
static int
fn_field_value(IcalParser *p, char *name, char *value)
{
- static char *fieldmap[][2] = {
+ static char *map[][2] = {
[ICAL_BLOCK_VEVENT] = { "DTSTART", "DTEND" },
[ICAL_BLOCK_VTODO] = { NULL, "DUE" },
[ICAL_BLOCK_VJOURNAL] = { "DTSTAMP", NULL },
@@ -61,22 +104,48 @@ fn_field_value(IcalParser *p, char *name, char *value)
};
char *beg, *end;
- beg = fieldmap[p->blocktype][0];
+ /* fill the date fields */
+ beg = map[p->blocktype][0];
if (beg != NULL && strcasecmp(name, beg) == 0)
if (ical_get_time(p, value, &block.beg) != 0)
return -1;
- end = fieldmap[p->blocktype][1];
+ end = map[p->blocktype][1];
if (end != NULL && strcasecmp(name, end) == 0)
if (ical_get_time(p, value, &block.end) != 0)
return -1;
+
+ /* fill text fields as requested with -o F1,F2... */
+ for (int i = 0; fields[i] != NULL; i++) {
+ if (strcasecmp(name, fields[i]) == 0) {
+ if (block.fields[i] == NULL) {
+ if ((block.fields[i] = strdup(value)) == NULL)
+ return ical_err(p, strerror(errno));
+ } else {
+ if (strappend(&block.fields[i], flag_s) == NUL…
+ strappend(&block.fields[i], value) == NULL)
+ return ical_err(p, strerror(errno));
+ }
+ }
+ }
+
return 0;
}
+static void
+usage(void)
+{
+ fprintf(stderr, "usage: %s [-f fields] [-s subsep] [-t timefmt] [file.…
+ exit(1);
+}
+
int
main(int argc, char **argv)
{
IcalParser p = {0};
- arg0 = *argv++;
+ size_t i;
+ int c;
+
+ arg0 = *argv;
p.fn_field_name = fn_field_name;
p.fn_block_begin = fn_block_begin;
@@ -84,7 +153,33 @@ main(int argc, char **argv)
p.fn_param_value = fn_param_value;
p.fn_field_value = fn_field_value;
- if (*argv == NULL) {
+ while ((c = getopt(argc, argv, "f:s:t:")) != -1) {
+ switch (c) {
+ case 'f':
+ flag_f = optarg;
+ break;
+ case 's':
+ flag_s = optarg;
+ break;
+ case 't':
+ flag_t = optarg;
+ break;
+ case '?':
+ usage();
+ break;
+ }
+ }
+ argv += optind;
+ argc -= optind;
+
+ i = 0;
+ do {
+ if (i >= sizeof fields / sizeof *fields - 1)
+ err("too many fields specified with -o flag");
+ } while ((fields[i++] = strsep(&flag_f, ",")) != NULL);
+ fields[i] = NULL;
+
+ if (*argv == NULL || strcmp(*argv, "-") == 0) {
debug("converting *stdin*");
if (ical_parse(&p, stdin) < 0)
err("parsing *stdin*:%d: %s", p.linenum, p.errmsg);
diff --git a/util.c b/util.c
@@ -110,7 +110,7 @@ strchomp(char *line)
line[--len] = '\0';
}
-int
+char *
strappend(char **dp, char const *s)
{
size_t dlen, slen;
@@ -118,13 +118,11 @@ strappend(char **dp, char const *s)
dlen = (*dp == NULL) ? 0 : strlen(*dp);
slen = strlen(s);
-
if ((mem = realloc(*dp, dlen + slen + 1)) == NULL)
- return -1;
+ return NULL;
*dp = mem;
-
memcpy(*dp + dlen, s, slen + 1);
- return 0;
+ return *dp;
}
/** memory **/
diff --git a/util.h b/util.h
@@ -15,7 +15,7 @@ void debug(char const *fmt, ...);
size_t strlcpy(char *, char const *, size_t);
char *strsep(char **, char const *);
void strchomp(char *);
-int strappend(char **, char const *);
+char *strappend(char **, char const *);
size_t strlcat(char *, char const *, size_t);
/** memory **/
You are viewing proxied material from bitreich.org. The copyright of proxied material belongs to its original authors. Any comments or complaints in relation to proxied material should be directed to the original authors of the content concerned. Please see the disclaimer for more details.