raidgrep filtering language
`raidgrep` is a bit of a misnomer, as the program should probably be called `evtcfind` instead, as it works more akin to `find` rather than `grep`: While the basic idea was to find logs by a player name, other useful predicates have since emerged (such as #4, #3, #2 and filtering by date). The switch `-f`/`--fields` has also been added so that we can select whether we want to match the account name or the player name (or both). Yet, handling the flags can become cumbersome and doesn't provide the full power (as they are always conjunctive, i.e. all predicates must be fulfilled). `find` is in a similar position where they support a lot of predicates (such as `-name`, `-atime`, `-empty`), and their "solution" is separate expression language which supports `-and`, `-or`, grouping by parenthesis, ... `raidgrep` could be updated to allow for a similar language. Something like `raidgrep --bosses=dhuum,desmina "Emma Hydes"` could become something like `raidgrep -bosses dhuum,desmina -player "Emma Hydes"`, or more specifically even `raidgrep (-boss dhuum -or -boss desmina) -and -player "Emma Hydes"`. Just like `find`, we would provide some useful shortcuts, e.g. predicates are implicitly joined by `-and` if not otherwise given, or shorthands like `-bosses` which take a comma-separated list instead of requiring manual `-or`s. The shorthand of `raidgrep [NAME]` could still exist for the common case of finding a log by player/account name. In a similar vein though, even that expression language would maybe not be enough, as some predicates (such as name or profession matching) apply to a single player instead of the whole log. The current behavior is that one of the players must match for the whole log to be included, but we could also provide something like quantified boolean expressions, with a syntax like `exists(player p: p.name == "Emma Hydes")`. This would open up a lot of possibilities, for example: * Find all logs with a Chronomancer called "Godric .*": `exists(player p: p.name ~ "Godric .*" and p.profession == Chronomancer)`. * Find all logs where only scourges are in: `all(player p: p.profession == Scourge)`. * Find all logs where someone called Romeo and someone called Juliet are in: `exists(player p: p.name == "Romeo") and exists(player p: p.name == "Juliet")`. One thing that we would need to take care of though is the current "early filters", which can filter out logs just by the header, before we have to parse every single event. We could use something like a [three-valued logic](https://en.wikipedia.org/wiki/Three-valued_logic) (similar to SQL's `NULL`), and only do the full parsing if the state is "Inconclusive" or "True". A different question would be the compatibility with the proposed "oneline" output format (see #5), as we'd need to know which player is in the match.
issue