浏览代码

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
master
Marq Schneider 14 年前
父节点
当前提交
76c49475ce
共有 2 个文件被更改,包括 141 次插入19 次删除
  1. +91
    -19
      cli/list.c
  2. +50
    -0
      doc/btcli.1

+ 91
- 19
cli/list.c 查看文件

@@ -6,7 +6,7 @@ usage_list(void)
printf( printf(
"List torrents.\n" "List torrents.\n"
"\n" "\n"
"Usage: list [-a] [-i]\n" "Usage: list [-a] [-i] [-f <format>]\n"
" list torrent ...\n" " list torrent ...\n"
"\n" "\n"
"Arguments:\n" "Arguments:\n"
@@ -26,10 +26,12 @@ usage_list(void)
} }


struct item { struct item {
unsigned num; unsigned num, peers;
char *name; char *name, *dir;
char hash[SHAHEXSIZE];
char st; 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; 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], diemsg("list failed for '%s' (%s).\n", itms->argv[obji],
ipc_strerror(objerr)); ipc_strerror(objerr));
itms->count++; 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); itm->st = tstate_char(res[IPC_TVAL_STATE].v.num);
if (res[IPC_TVAL_NAME].type == IPC_TYPE_ERR) if (res[IPC_TVAL_NAME].type == IPC_TYPE_ERR)
asprintf(&itm->name, "%s", ipc_strerror(res[IPC_TVAL_NAME].v.num)); asprintf(&itm->name, "%s", ipc_strerror(res[IPC_TVAL_NAME].v.num));
else else
asprintf(&itm->name, "%.*s", (int)res[IPC_TVAL_NAME].v.str.l, asprintf(&itm->name, "%.*s", (int)res[IPC_TVAL_NAME].v.str.l,
res[IPC_TVAL_NAME].v.str.p); res[IPC_TVAL_NAME].v.str.p);
itm->totup = res[IPC_TVAL_TOTUP].v.num; if (res[IPC_TVAL_DIR].type == IPC_TYPE_ERR)
itm->cgot = res[IPC_TVAL_CGOT].v.num; asprintf(&itm->dir, "%s", ipc_strerror(res[IPC_TVAL_DIR].v.num));
itm->csize = res[IPC_TVAL_CSIZE].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); itm_insert(itms, itm);
} }


void void
print_items(struct items* itms) print_items(struct items* itms, char *format)
{ {
struct item *p; struct item *p;
char *it;
BTPDQ_FOREACH(p, &itms->hd, entry) { BTPDQ_FOREACH(p, &itms->hd, entry) {
printf("%-40.40s %4u %c. ", p->name, p->num, p->st); if(format) {
print_percent(p->cgot, p->csize); for (it = format; *it; ++it) {
print_size(p->csize); switch (*it) {
print_ratio(p->totup, p->csize); case '%':
printf("\n"); ++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 [] = { static struct option list_opts [] = {
{ "format", required_argument, NULL, 'f' },
{ "help", no_argument, NULL, 'H' }, { "help", no_argument, NULL, 'H' },
{NULL, 0, NULL, 0} {NULL, 0, NULL, 0}
}; };
@@ -98,17 +162,24 @@ void
cmd_list(int argc, char **argv) cmd_list(int argc, char **argv)
{ {
int ch, inactive = 0, active = 0; int ch, inactive = 0, active = 0;
char *format = NULL;
enum ipc_err code; enum ipc_err code;
enum ipc_twc twc; enum ipc_twc twc;
enum ipc_tval keys[] = { IPC_TVAL_NUM, IPC_TVAL_STATE, IPC_TVAL_NAME, enum ipc_tval keys[] = { IPC_TVAL_NUM, IPC_TVAL_STATE, IPC_TVAL_NAME,
IPC_TVAL_TOTUP, IPC_TVAL_CSIZE, IPC_TVAL_CGOT }; 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]); size_t nkeys = sizeof(keys) / sizeof(keys[0]);
struct items itms; 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) { switch (ch) {
case 'a': case 'a':
active = 1; active = 1;
break; break;
case 'f':
format = optarg;
break;
case 'i': case 'i':
inactive = 1; inactive = 1;
break; break;
@@ -149,6 +220,7 @@ cmd_list(int argc, char **argv)
code = btpd_tget(ipc, itms.tps, itms.ntps, keys, nkeys, list_cb, &itms); code = btpd_tget(ipc, itms.tps, itms.ntps, keys, nkeys, list_cb, &itms);
if (code != IPC_OK) if (code != IPC_OK)
diemsg("command failed (%s).\n", ipc_strerror(code)); diemsg("command failed (%s).\n", ipc_strerror(code));
printf("%-40.40s NUM ST HAVE SIZE RATIO\n", "NAME"); if (format == NULL)
print_items(&itms); printf("%-40.40s NUM ST HAVE SIZE RATIO\n", "NAME");
print_items(&itms, format);
} }

+ 50
- 0
doc/btcli.1 查看文件

@@ -56,6 +56,52 @@ List active torrents.
.TP .TP
\fB\-i\fR \fB\-i\fR
List inactive torrents. 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" .SH "STAT OPTIONS"
.TP .TP
\fB\-i\fR \fB\-i\fR
@@ -63,6 +109,10 @@ Display individual lines for each torrent.
.TP .TP
\fB\-n\fR \fB\-n\fR
Display the name of each torrent. Implies '-i'. Display the name of each torrent. Implies '-i'.
.SH "START OPTIONS"
.TP
\fB\-a\fR
Activate all non-active torrents.
.SH "STOP OPTIONS" .SH "STOP OPTIONS"
.TP .TP
\fB\-a\fR \fB\-a\fR


||||||
x
 
000:0
正在加载...
取消
保存