From 76c49475cea16512cb319a5222f657254f487cc5 Mon Sep 17 00:00:00 2001 From: Marq Schneider Date: Thu, 29 Jul 2010 21:43:07 -0500 Subject: [PATCH] Added custom formats for list operation. Added printf()-style '%' and '\' sequences for custom list formats. Updated btcli manpage to reflect change and start -a. Closes GH-8 --- cli/list.c | 110 +++++++++++++++++++++++++++++++++++++++++++--------- doc/btcli.1 | 50 ++++++++++++++++++++++++ 2 files changed, 141 insertions(+), 19 deletions(-) diff --git a/cli/list.c b/cli/list.c index ce7cc64..cca03a6 100644 --- a/cli/list.c +++ b/cli/list.c @@ -6,7 +6,7 @@ usage_list(void) printf( "List torrents.\n" "\n" - "Usage: list [-a] [-i]\n" + "Usage: list [-a] [-i] [-f ]\n" " list torrent ...\n" "\n" "Arguments:\n" @@ -26,10 +26,12 @@ usage_list(void) } struct item { - unsigned num; - char *name; + unsigned num, peers; + char *name, *dir; + char hash[SHAHEXSIZE]; char st; - long long cgot, csize, totup; + long long cgot, csize, totup, downloaded, uploaded, rate_up, rate_down; + uint32_t torrent_pieces, pieces_have, pieces_seen; BTPDQ_ENTRY(item) entry; }; @@ -63,33 +65,95 @@ list_cb(int obji, enum ipc_err objerr, struct ipc_get_res *res, void *arg) diemsg("list failed for '%s' (%s).\n", itms->argv[obji], ipc_strerror(objerr)); itms->count++; - itm->num = (unsigned)res[IPC_TVAL_NUM].v.num; + itm->num = (unsigned)res[IPC_TVAL_NUM].v.num; + itm->peers = (unsigned)res[IPC_TVAL_PCOUNT].v.num; itm->st = tstate_char(res[IPC_TVAL_STATE].v.num); if (res[IPC_TVAL_NAME].type == IPC_TYPE_ERR) asprintf(&itm->name, "%s", ipc_strerror(res[IPC_TVAL_NAME].v.num)); else asprintf(&itm->name, "%.*s", (int)res[IPC_TVAL_NAME].v.str.l, res[IPC_TVAL_NAME].v.str.p); - itm->totup = res[IPC_TVAL_TOTUP].v.num; - itm->cgot = res[IPC_TVAL_CGOT].v.num; - itm->csize = res[IPC_TVAL_CSIZE].v.num; + if (res[IPC_TVAL_DIR].type == IPC_TYPE_ERR) + asprintf(&itm->dir, "%s", ipc_strerror(res[IPC_TVAL_DIR].v.num)); + else + asprintf(&itm->dir, "%.*s", (int)res[IPC_TVAL_DIR].v.str.l, + res[IPC_TVAL_DIR].v.str.p); + bin2hex(res[IPC_TVAL_IHASH].v.str.p, itm->hash, 20); + itm->cgot = res[IPC_TVAL_CGOT].v.num; + itm->csize = res[IPC_TVAL_CSIZE].v.num; + itm->totup = res[IPC_TVAL_TOTUP].v.num; + itm->downloaded = res[IPC_TVAL_SESSDWN].v.num; + itm->uploaded = res[IPC_TVAL_SESSUP].v.num; + itm->rate_up = res[IPC_TVAL_RATEUP].v.num; + itm->rate_down = res[IPC_TVAL_RATEDWN].v.num; + itm->torrent_pieces = (uint32_t)res[IPC_TVAL_PCCOUNT].v.num; + itm->pieces_seen = (uint32_t)res[IPC_TVAL_PCSEEN].v.num; + itm->pieces_have = (uint32_t)res[IPC_TVAL_PCGOT].v.num; + itm_insert(itms, itm); } void -print_items(struct items* itms) +print_items(struct items* itms, char *format) { struct item *p; + char *it; BTPDQ_FOREACH(p, &itms->hd, entry) { - printf("%-40.40s %4u %c. ", p->name, p->num, p->st); - print_percent(p->cgot, p->csize); - print_size(p->csize); - print_ratio(p->totup, p->csize); - printf("\n"); + if(format) { + for (it = format; *it; ++it) { + switch (*it) { + case '%': + ++it; + switch (*it) { + case '%': putchar('%'); break; + case '#': printf("%u", p->num); break; + case '^': printf("%lld", p->rate_up); break; + + case 'A': printf("%u", p->pieces_seen); break; + case 'D': printf("%lld", p->downloaded); break; + case 'H': printf("%u", p->pieces_have); break; + case 'P': printf("%u", p->peers); break; + case 'S': printf("%c", p->st); break; + case 'U': printf("%lld", p->uploaded); break; + case 'T': printf("%u", p->torrent_pieces); break; + + case 'd': printf("%s", p->dir); break; + case 'g': printf("%lld", p->cgot); break; + case 'h': printf("%s", p->hash); break; + case 'n': printf("%s", p->name); break; + case 'p': print_percent(p->cgot, p->csize); break; + case 'r': print_ratio(p->totup, p->csize); break; + case 's': print_size(p->csize); break; + case 't': printf("%lld", p->csize); break; + case 'u': printf("%lld", p->totup); break; + case 'v': printf("%lld", p->rate_down); break; + + case '\0': continue; + } + break; + case '\\': + ++it; + switch (*it) { + case 'n': putchar('\n'); break; + case 't': putchar('\t'); break; + case '\0': continue; + } + break; + default: putchar(*it); break; + } + } + } else { + printf("%-40.40s %4u %c. ", p->name, p->num, p->st); + print_percent(p->cgot, p->csize); + print_size(p->csize); + print_ratio(p->totup, p->csize); + printf("\n"); + } } } static struct option list_opts [] = { + { "format", required_argument, NULL, 'f' }, { "help", no_argument, NULL, 'H' }, {NULL, 0, NULL, 0} }; @@ -98,17 +162,24 @@ void cmd_list(int argc, char **argv) { int ch, inactive = 0, active = 0; + char *format = NULL; enum ipc_err code; enum ipc_twc twc; - enum ipc_tval keys[] = { IPC_TVAL_NUM, IPC_TVAL_STATE, IPC_TVAL_NAME, - IPC_TVAL_TOTUP, IPC_TVAL_CSIZE, IPC_TVAL_CGOT }; + enum ipc_tval keys[] = { IPC_TVAL_NUM, IPC_TVAL_STATE, IPC_TVAL_NAME, + IPC_TVAL_TOTUP, IPC_TVAL_CSIZE, IPC_TVAL_CGOT, IPC_TVAL_PCOUNT, + IPC_TVAL_PCCOUNT, IPC_TVAL_PCSEEN, IPC_TVAL_PCGOT, IPC_TVAL_SESSUP, + IPC_TVAL_SESSDWN, IPC_TVAL_RATEUP, IPC_TVAL_RATEDWN, IPC_TVAL_IHASH, + IPC_TVAL_DIR }; size_t nkeys = sizeof(keys) / sizeof(keys[0]); struct items itms; - while ((ch = getopt_long(argc, argv, "ai", list_opts, NULL)) != -1) { + while ((ch = getopt_long(argc, argv, "aif:", list_opts, NULL)) != -1) { switch (ch) { case 'a': active = 1; break; + case 'f': + format = optarg; + break; case 'i': inactive = 1; break; @@ -149,6 +220,7 @@ cmd_list(int argc, char **argv) code = btpd_tget(ipc, itms.tps, itms.ntps, keys, nkeys, list_cb, &itms); if (code != IPC_OK) diemsg("command failed (%s).\n", ipc_strerror(code)); - printf("%-40.40s NUM ST HAVE SIZE RATIO\n", "NAME"); - print_items(&itms); + if (format == NULL) + printf("%-40.40s NUM ST HAVE SIZE RATIO\n", "NAME"); + print_items(&itms, format); } diff --git a/doc/btcli.1 b/doc/btcli.1 index 268d638..f1bed7e 100644 --- a/doc/btcli.1 +++ b/doc/btcli.1 @@ -56,6 +56,52 @@ List active torrents. .TP \fB\-i\fR List inactive torrents. +.TP +\fB\-f\fR format +Specifies a custom format to use while displaying torrents. The following is a +list of the characters that can be used: +.RS 8 +.PP +\fB%n\fR - torrent name +.br +\fB%#\fR - torrent number +.br +\fB%h\fR - torrent hash +.br +\fB%d\fR - download directory +.br +\fB%t\fR - state +.br +\fB%P\fR - peer count +.PP +\fB%^\fR - upload rate +.br +\fB%v\fR - download rate +.PP +\fB%D\fR - downloaded bytes +.br +\fB%U\fR - uploaded bytes +.br +\fB%g\fR - bytes got +.br +\fB%u\fR - bytes uploaded +.br +\fB%s\fR - total size, (formatted: prints K, M, G) +.br +\fB%S\fR - total size, in bytes +.PP +\fB%A\fR - available pieces +.br +\fB%T\fR - total pieces +.br +\fB%H\fR - have pieces +.PP +\fB%p\fR - percent have (formatted) +.br +\fB%r\fR - ratio +.PP +\fB%%\fR - a percent symbol: '%' +.RE .SH "STAT OPTIONS" .TP \fB\-i\fR @@ -63,6 +109,10 @@ Display individual lines for each torrent. .TP \fB\-n\fR Display the name of each torrent. Implies '-i'. +.SH "START OPTIONS" +.TP +\fB\-a\fR +Activate all non-active torrents. .SH "STOP OPTIONS" .TP \fB\-a\fR