{"id":19230510,"url":"https://github.com/ctron/sikula","last_synced_at":"2026-02-26T01:35:15.081Z","repository":{"id":169764343,"uuid":"645815981","full_name":"ctron/sikula","owner":"ctron","description":"A simple query language","archived":false,"fork":false,"pushed_at":"2024-06-28T06:47:13.000Z","size":79,"stargazers_count":3,"open_issues_count":2,"forks_count":2,"subscribers_count":3,"default_branch":"main","last_synced_at":"2025-04-19T17:19:40.722Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ctron.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-05-26T13:55:08.000Z","updated_at":"2025-04-17T12:56:00.000Z","dependencies_parsed_at":null,"dependency_job_id":"68eb30b6-bb5f-4ba1-9661-a45e412b53d1","html_url":"https://github.com/ctron/sikula","commit_stats":null,"previous_names":["ctron/sikula"],"tags_count":12,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ctron%2Fsikula","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ctron%2Fsikula/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ctron%2Fsikula/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ctron%2Fsikula/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ctron","download_url":"https://codeload.github.com/ctron/sikula/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":249778775,"owners_count":21324293,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-09T15:39:38.267Z","updated_at":"2026-02-26T01:35:10.041Z","avatar_url":"https://github.com/ctron.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"# SiKuLa\n\n[![CI](https://github.com/ctron/sikula/workflows/CI/badge.svg)](https://github.com/ctron/sikula/actions?query=workflow%3A%22CI%22)\n[![GitHub release (latest SemVer)](https://img.shields.io/github/v/tag/ctron/sikula?sort=semver)](https://github.com/ctron/sikula/releases)\n[![crates.io](https://img.shields.io/crates/v/sikula.svg)](https://crates.io/crates/sikula)\n[![docs.rs](https://docs.rs/sikula/badge.svg)](https://docs.rs/sikula)\n\n\u003cu\u003eSi\u003c/u\u003emple \u003cu\u003eQu\u003c/u\u003eery \u003cu\u003eLa\u003c/u\u003enguage - [ˈziːˈkuːˈlaː]\n\n## Rationale\n\n_Another query language, are you serious?_\n\nActually it isn't that new. But naming it \"Query language similar to GitHub's search syntax\" (QLSTGHSS)\nwasn't a real option.\n\nThink of it more as an implementation of a familiar syntax.\n\n_What's the difference then?_\n\nThey are subtle. But I don't want to spoil the surprise. Or maybe I am just too lazy documenting it. 🤷\n\n## Example\n\nAssuming you have an enum defined for searching e-mails:\n\n```rust\nuse sikula::prelude::*;\n\n#[derive(Search, Clone, Debug, PartialEq, Eq)]\nenum DeriveResource\u003c'a\u003e {\n    /// Standard qualifier: `author:someone`.\n    #[search(sort, scope)]\n    Author(\u0026'a str),\n    /// Default primary: `warranty`.\n    #[search(default)]\n    Subject(Primary\u003c'a\u003e),\n    /// Non-default primary: `warranty in:message`, to search in both: `warranty in:message in:subject`.\n    #[search(scope)]\n    Message(Primary\u003c'a\u003e),\n\n    /// Predicate: `is:read`.\n    Read,\n\n    /// Numeric qualifier example:\n    /// * `size:100` (equals)\n    /// * `size:\u003e=100` (size greater than or equals 100)\n    /// * `size:100..200` (size between 100 inclusive and 200 exclusive)\n    /// * `size:*..200` (size up to 200 exclusive)\n    #[search(sort)]\n    Size(Ordered\u003cusize\u003e),\n\n    #[search(sort)]\n    Sent(Ordered\u003ctime::OffsetDateTime\u003e),\n\n    Label(Qualified\u003c'a, \u0026'a str\u003e),\n}\n```\n\nThe `Search` derive provides the trait implementation. The `#[search(default)]` attribute flags the variant `Subject`\nas default scopes for the primary search terms, marking `Subject` as the default if none was selected.\n\nIn general, there are three types of terms: Primary, Qualifiers, Predicates. Predicates are simple \"is this condition\ntrue\" style of filters. If an enum variant doesn't have any value, it is a predicate.\n\nQualifiers are additional matching criteria, which depend on the type of the value.\n\nWith the `#[search(sort)]` flag, a field can be used for sorting the result. \n\nNow, you can do the following queries:\n\n| Query                                             | Retrieves all entries…                                                                                |\n|---------------------------------------------------|-------------------------------------------------------------------------------------------------------|\n| `foo`                                             | … containing \"foo\" in the \"subject\"                                                                   |\n| `foo in:subject in:message`                       | … containing \"foo\" in either \"subject\" or \"message\"                                                   |\n| `foo in:subject in:message is:read`               | … containing \"foo\" in either \"subject\" or \"message\" being \"read\"                                      |\n| `foo bar`                                         | … containing \"foo\" and \"bar\" in the \"subject\"                                                         |\n| `size:\u003e10000`                                     | … having the \"size\" greater than 10000                                                                |\n| `size:100..200`                                   | … having the \"size\" between 100 (inclusive) and 200 (exclusive)                                       |\n| `-is:read`                                        | … being \"not read\"                                                                                    |\n| `foo sort:sent`                                   | … containing \"foo\" in the \"subject\", sorted by \"sent\" ascending                                       |\n| `foo -sort:sent`                                  | … containing \"foo\" in the \"subject\", sorted by \"sent\" descending                                      |\n| `author:\"Max Mustermann\"`                         | … having the \"author\" of `Max Mustermann`                                                             |\n| `author:\"Max Mustermann\" author:\"Eva Mustermann\"` | … having the \"author\" of `Max Mustermann` and `Eva Mustermann` (most likely no results will be found) |\n| `author:\"Max Mustermann\",\"Eva Mustermann\"`        | … having the \"author\" of `Max Mustermann` or `Eva Mustermann`                                         |\n| `foo OR bar`                                      | … containing \"foo\" or \"bar\" in the \"subject\"                                                          |\n| `foo AND bar`                                     | … containing \"foo\" and \"bar\" in the \"subject\"                                                         |\n| `foo OR bar AND baz`                              | … containing either \"foo\" or ( \"bar\" and \"baz\" ) in the \"subject\"                                     |\n| `(foo OR bar) AND baz`                            | … containing ( \"foo\" or \"bar\" ) and \"baz\" in the \"subject\"                                            |\n| `foo OR bar baz`                                  | … containing ( \"foo\" or \"bar\" ) and \"baz\" in the \"subject\"                                            |\n\nFor testing more examples with the resource above, you can run the `cli` example:\n\n```shell\ncargo run --example cli --features time -- -is:read AND foo\n```\n\nWhich will give you a structured output of the parsed query:\n\n```\nInput: '-is:read AND foo'\n\nMIR:\nQuery {\n    term: And {\n        scopes: [],\n        terms: [\n            Not(\n                Match {\n                    qualifier: Qualifier(\n                        [\n                            \"read\",\n                        ],\n                    ),\n                    expression: Predicate,\n                },\n            ),\n            Match {\n                qualifier: Qualifier(\n                    [],\n                ),\n                expression: Simple(\n                    \"foo\",\n                ),\n            },\n        ],\n    },\n    sorting: [],\n}\n\nLIR:\nQuery {\n    terms: And(\n        [\n            Not(\n                Match(\n                    Read,\n                ),\n            ),\n            Match(\n                Subject(\n                    Partial(\n                        \"foo\",\n                    ),\n                ),\n            ),\n        ],\n    ),\n    sorting: [],\n}\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fctron%2Fsikula","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fctron%2Fsikula","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fctron%2Fsikula/lists"}