mblaze

Unix utilities to deal with Maildir - my mirror
git clone https://pi.duncano.de/git/mblaze.git
Log | Files | Refs | README | COPYING

commit 1d67157f0901bcb8eaeaa3c70c7d9204e3ceb6a1
parent 516c3ec6f26e59efe174e1d73afbf82d653efa89
Author: Christian Neukirchen <chneukirchen@gmail.com>
Date:   Fri,  5 Aug 2016 20:05:24 +0200

seq: add thread selectors

Diffstat:
man/mmsg.7 | 23+++++++++++++++++++----
seq.c | 129+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
2 files changed, 145 insertions(+), 7 deletions(-)

diff --git a/man/mmsg.7 b/man/mmsg.7 @@ -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 \&. diff --git a/seq.c b/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;