about summary refs log tree commit diff
diff options
context:
space:
mode:
authorChristian Neukirchen <chneukirchen@gmail.com>2016-08-05 20:05:24 +0200
committerChristian Neukirchen <chneukirchen@gmail.com>2016-08-05 20:05:24 +0200
commit1d67157f0901bcb8eaeaa3c70c7d9204e3ceb6a1 (patch)
treeb50348493b3a3393054a5aa9ebedecbf561a4374
parent516c3ec6f26e59efe174e1d73afbf82d653efa89 (diff)
downloadmblaze-1d67157f0901bcb8eaeaa3c70c7d9204e3ceb6a1.tar.gz
mblaze-1d67157f0901bcb8eaeaa3c70c7d9204e3ceb6a1.tar.xz
mblaze-1d67157f0901bcb8eaeaa3c70c7d9204e3ceb6a1.zip
seq: add thread selectors
-rw-r--r--man/mmsg.723
-rw-r--r--seq.c129
2 files changed, 145 insertions, 7 deletions
diff --git a/man/mmsg.7 b/man/mmsg.7
index e903aa4..f792bac 100644
--- 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
index fd541b3..de1d24c 100644
--- 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;