seq: add thread selectors

pull/2/head
Christian Neukirchen 8 years ago
parent 516c3ec6f2
commit 1d67157f09

@ -8,6 +8,7 @@
This manpage documents the message syntax used
by the tools
.Xr maddr 1 ,
.Xr magrep 1 ,
.Xr mflag 1 ,
.Xr mhdr 1 ,
.Xr mless 1 ,
@ -31,7 +32,7 @@ to all messages in the
directory.
.Pp
Sequences have the format
.Sq Ar start Ns Li \&: Ns Ar stop ,
.Sq Ar start Ns Cm ":" Ns Ar stop ,
where
.Ar start
and
@ -49,14 +50,28 @@ is the empty string,
.Li \&-1
will be used instead.
Thus,
.Sq Li \&:
.Sq Cm ":"
represents the whole sequence.
If the sequence does not contain a
.Sq Li \&: ,
.Sq Cm ":" ,
it is considered to be a single message, equivalent to the range
.Sq Ar start Ns Li \&: Ns Ar start
.Sq Ar start Ns Cm ":" Ns Ar start
of size one.
.Pp
If the sequence is threaded, the following
syntax may be used:
.Sq Ar msg Ns Cm "="
refers to the whole thread that contains
.Ar msg .
.Sq Ar msg Ns Cm "^"
refers to the parent of the message
.Ar msg
and may be repeated to refer to grand-parents.
.Sq Ar msg Ns Cm "_"
refers to the subthread headed by
.Ar msg
(i.e. all messages below with more indentation).
.Pp
There are four special shortcuts:
.Bl -tag -width 3n
.It Sq Li \&.

129
seq.c

@ -203,16 +203,135 @@ parse_relnum(char *a, long cur, long last, long *out)
}
static int
parse_range(char *a, long *start, long *stop, long cur, long lines)
parse_thread(char *map, long a, long *starto, long *stopo)
{
char *s, *t;
long line;
long start = 0, stop = 0, state = 0;
for (s = map, line = 0; s; s = t+1) {
t = strchr(s, '\n');
if (!t)
break;
line++;
if (!iswsp(*s)) {
if (state == 0) {
start = line;
} else if (state == 1) {
stop = line - 1;
state = 2;
break;
}
}
if (line == a)
state = 1;
while (*s && iswsp(*s))
s++;
}
if (state == 1) {
stop = line;
state = 2;
}
if (state == 2) {
*starto = start;
*stopo = stop;
return 1;
}
return 0;
}
static int
parse_subthread(char *map, long a, long *stopo)
{
char *s, *t;
long line;
long stop = 0;
int minindent = -1;
for (s = map, line = 0; s; s = t+1) {
t = strchr(s, '\n');
if (!t)
break;
line++;
int indent = 0;
while (*s && iswsp(*s)) {
s++;
indent++;
}
if (line == a)
minindent = indent;
if (line > a && indent <= minindent) {
stop = line - 1;
break;
}
}
if (line < a)
return 0;
if (minindent == -1)
stop = line;
*stopo = stop;
return 1;
}
static int
parse_parent(char *map, long *starto, long *stopo)
{
char *s, *t;
long line;
int previndent[32] = { 0 };
for (s = map, line = 0; s; s = t+1) {
t = strchr(s, '\n');
if (!t)
break;
line++;
int indent = 0;
while (*s && iswsp(*s)) {
s++;
indent++;
}
if (indent > 31)
indent = 31;
previndent[indent] = line;
if (line == *starto) {
if (previndent[indent-1]) {
*starto = *stopo = previndent[indent-1];
return 1;
} else {
return 0;
}
}
}
return 0;
}
static int
parse_range(char *map, char *a, long *start, long *stop, long cur, long lines)
{
*start = *stop = 1;
while (*a && *a != ':') {
while (*a && *a != ':' && *a != '=' && *a != '_' && *a != '^') {
char *b = parse_relnum(a, cur, lines, start);
if (a == b)
return 0;
a = b;
}
while (*a == '^') {
a++;
if (!parse_parent(map, start, stop))
return 0;
}
if (*a == ':') {
a++;
if (!*a) {
@ -222,6 +341,10 @@ parse_range(char *a, long *start, long *stop, long cur, long lines)
if (a == b)
return 0;
}
} else if (*a == '=') {
return parse_thread(map, *start, start, stop);
} else if (*a == '_') {
return parse_subthread(map, *start, stop);
} else if (!*a) {
*stop = *start;
} else {
@ -279,7 +402,7 @@ blaze822_seq_next(char *map, char *range, struct blaze822_seq_iter *iter)
find_cur(map, iter);
if (!iter->start) {
if (!parse_range(range, &iter->start, &iter->stop,
if (!parse_range(map, range, &iter->start, &iter->stop,
iter->cur, iter->lines)) {
fprintf(stderr, "can't parse range: %s\n", range);
return 0;

Loading…
Cancel
Save