# Selectors
As you have seen in the Readme and the [file format documentation](https://github.com/typst/hayagriva/blob/main/docs/file-format.md), a Hayagriva entry not only has a type but also parents that can have their own type. With this architecture, differentiation between articles from blogs, newspapers, and conference proceedings is easy without having a dedicated type for each of them!
However, this also means that you cannot just match on the top-level type of an entry to make all the distinctions that you or your citation and reference styles may require.
Enter selectors: They provide a convenient way to query entries by structure and retrieve parents that hold crucial information for your use case.
Two ways of macro usage are offered: Either as a string (used on the command line) or, if you are depending on Hayagriva as a library, with the `select!` macro. Library users can parse string selectors using `Selector::parse`. The Readme explains the fundamental differences between the two formats. If there are divergences between both forms, we will provide both variants as examples.
## Entry type selector
The most basic selectors are entry types; they will match any entry that has the same top-level type:
| Variant | Example |
|-------------|------------------------------------------------------|
| **String:** | `thesis` |
| **Macro:** | `Thesis` |
This works with any of the [entry types](https://github.com/typst/hayagriva/blob/main/docs/file-format.md#entry-type). Be aware that you have to capitalize exactly like in the EntryType struct variants when using the macro.
The string selectors are case-insensitive.
## Wildcard
There is also a wildcard selector that applies to every entry:
```
*
```
This might seem pointless on its own but is quite useful in conjunction with other selector constructs.
## Required fields
Sometimes you want to filter for entries that have certain fields set. This can be accomplished with the fields selector. Attach square brackets to a selector and put the fields you want to be set inside, separated by commas. All specified fields have to contain some value for the selector to match.
| Variant | Example |
|-------------|------------------------------------------------------|
| **String:** | `artwork[archive, archive-location]` |
| **Macro:** | `Artwork["archive", "archive-location"]` |
This example finds all artworks with a known archive (including its location). The macro needs the attributes to be strings.
## Negation
The exclamation mark allows you to select everything that does not match the following selector.
| Variant | Example |
|-------------|------------------------------------------------------|
| **String:** | `!article` |
| **Macro:** | `!Article` |
## Disjunction
The disjunction operator `|` allows you to offer multiple alternative selectors, only one of which has to be matched for the whole construction to match. Think about it as an 'or.'
| Variant | Example 1 |
|-------------|------------------------------------------------------|
| **String:** | `anthology \| *[volume]` |
| **Macro:** | `Anthology \| (*["volume"])` |
<!-- The pipe character (|) is escaped with a backslash because it would otherwise break GitHub's Markdown tables. When writing real selectors, of course, omit the backslash. -->
Either an anthology or anything with a volume field.
| Variant | Example 2 |
|-------------|------------------------------------------------------|
| **String:** | `(video \| audio \| web[runtime])[affiliated]` |
| **Macro:** | `(Video \| Audio \| (Web["runtime"]))["affiliated"]` |
Matches every video, audio, and web (with runtime field) entry, given that it has the affiliated field set.
## Ancestrage
Require that a parent has to match some selector with the `>` operator. The conditions to its left have to apply for the top-level, the selector on the right side must match any of the parents. The operator can also be chained to examine nested parents.
| Variant | Example 1 |
|-------------|------------------------------------------------------|
| **String:** | `article > proceedings` |
| **Macro:** | `Article > Proceedings` |
This selector finds published conference articles.
| Variant | Example 2 |
|-------------|------------------------------------------------------|
| **String:** | `chapter > (book \| anthology) > (book \| anthology)`|
| **Macro:** | `Chapter > (Book \| Anthology) > (Book \| Anthology)`|
This selects a chapter in a monograph (a long-form text on a subject published in another book).
## Bindings
_Less interesting for CLI users._
Once you know that a matching entry has some parents, you might need to access their fields. You can be sure you got the right parent with bindings.
Create a binding using the `:` operator. To the left of the selector, you provide a name which you can freely choose. The parent (or the top-level entry) that matches the selector to the right will then appear in the resulting map under the key that you have chosen.
| Variant | Example |
|-------------|------------------------------------------------------|
| **String:** | `article > parent:(blog \| newspaper)` |
| **Macro:** | `Article > ("parent":(Blog \| Newspaper))` |
The binding name has to be a string for macro use.
This binds the blog or newspaper parent of an article to 'parent' if the selector matches.
It is possible to write selectors that only sometimes bind a variable if it matches.
You could reformulate the right part of the above selector as `(parent:blog | newspaper)`, then it would not bind 'parent' if the selector matches with a newspaper-type parent.
Note that all bindings within a negation are discarded.
## Require multiple parents
Sometimes, a single parent does not provide the full picture. For example, a dataset (type repository) could be both published on the web and presented in a paper, so it would have a `web` and an `article` parent (with the latter possibly having an `periodical` or `proceedings` parent). To capture such entries with selectors, we need to define multiple conditions for parents, that all must be satisfied. This can be done using the `&`-operator. The operator may only be used to the right of an [ancestrage operator](#ancestrage).
| Variant | Example |
|-------------|------------------------------------------------------|
| **String:** | `article > (conference & video)` |
| **Macro:** | `Article > (Conference & Video)` |
This selector matches conference talks published as a video.