├── .envrc ├── .gitattributes ├── .github ├── ISSUE_TEMPLATE │ ├── bug_report.md │ └── feature_request.md └── workflows │ ├── build.yml │ ├── main.yml │ ├── update-nix.yml │ └── update-nixpkgs.yml ├── .gitignore ├── .mergify.yml ├── LICENSE ├── README.md ├── codemod ├── .envrc ├── .gitignore ├── Cargo.lock ├── Cargo.toml ├── README.md ├── flake-module.nix ├── prefixes.json ├── src │ ├── main.rs │ └── tests.rs └── test_data │ ├── args.nix │ ├── args │ └── default.nix │ ├── mixed.expect │ ├── mixed.nix │ ├── nested │ └── sample.nix │ └── simple.nix ├── devShell.nix ├── flake.lock ├── flake.nix ├── nixPlugin ├── .gitignore ├── CMakeLists.txt ├── flake-module.nix ├── package.nix └── plugin.cc ├── pasta ├── .envrc ├── README.md ├── default.nix ├── flake-module.nix ├── shell.nix └── src │ ├── eval.nix │ └── tools.nix ├── pesto ├── .envrc ├── .gitignore ├── Cargo.lock ├── Cargo.toml ├── README.md ├── flake-module.nix ├── json.json ├── src │ ├── alias.rs │ ├── bulk.rs │ ├── comment.rs │ ├── main.rs │ ├── markdown.rs │ ├── pasta.rs │ ├── position.rs │ └── tests.rs └── test_data │ ├── aliases │ ├── add.expect │ ├── add.json │ ├── escapeURL.expect │ ├── escapeURL.json │ ├── fold.expect │ ├── fold.json │ ├── foldl.expect │ ├── foldl.json │ ├── pipe.expect │ ├── pipe.json │ ├── strings.expect │ ├── strings.json │ ├── traceVal.expect │ └── traceVal.json │ ├── assets │ ├── ascii-table.nix │ ├── asserts.nix │ ├── attrsets.nix │ ├── cli.nix │ ├── customisation.nix │ ├── debug.nix │ ├── default.nix │ ├── deprecated.nix │ ├── derivations.nix │ ├── fetchers.nix │ ├── fileset │ │ ├── default.nix │ │ ├── internal.nix │ │ └── mock-splitRoot.nix │ ├── filesystem.nix │ ├── fixed-points.nix │ ├── flake.nix │ ├── generators.nix │ ├── gvariant.nix │ ├── kernel.nix │ ├── licenses.nix │ ├── lists.nix │ ├── meta.nix │ ├── minver.nix │ ├── modules.nix │ ├── options.nix │ ├── path │ │ ├── default.nix │ │ └── tests │ │ │ ├── default.nix │ │ │ ├── prop.nix │ │ │ └── unit.nix │ ├── source-types.nix │ ├── sources.nix │ ├── strings-with-deps.nix │ ├── strings.nix │ ├── systems │ │ ├── architectures.nix │ │ ├── default.nix │ │ ├── doubles.nix │ │ ├── examples.nix │ │ ├── flake-systems.nix │ │ ├── inspect.nix │ │ ├── parse.nix │ │ └── platforms.nix │ ├── tests │ │ ├── check-eval.nix │ │ ├── maintainer-module.nix │ │ ├── maintainers.nix │ │ ├── misc.nix │ │ ├── modules │ │ │ ├── adhoc-freeformType-survives-type-merge.nix │ │ │ ├── alias-with-priority-can-override.nix │ │ │ ├── alias-with-priority.nix │ │ │ ├── attrsOf-conditional-check.nix │ │ │ ├── attrsOf-lazy-check.nix │ │ │ ├── class-check.nix │ │ │ ├── declaration-positions.nix │ │ │ ├── declare-attrsOf.nix │ │ │ ├── declare-attrsOfSub-any-enable.nix │ │ │ ├── declare-bare-submodule-deep-option-duplicate.nix │ │ │ ├── declare-bare-submodule-deep-option.nix │ │ │ ├── declare-bare-submodule-nested-option.nix │ │ │ ├── declare-bare-submodule.nix │ │ │ ├── declare-coerced-value-unsound.nix │ │ │ ├── declare-coerced-value.nix │ │ │ ├── declare-either.nix │ │ │ ├── declare-enable-nested.nix │ │ │ ├── declare-enable.nix │ │ │ ├── declare-int-between-value.nix │ │ │ ├── declare-int-positive-value-nested.nix │ │ │ ├── declare-int-positive-value.nix │ │ │ ├── declare-int-unsigned-value.nix │ │ │ ├── declare-lazyAttrsOf.nix │ │ │ ├── declare-mkPackageOption.nix │ │ │ ├── declare-oneOf.nix │ │ │ ├── declare-set.nix │ │ │ ├── declare-submodule-via-evalModules.nix │ │ │ ├── declare-submoduleWith-modules.nix │ │ │ ├── declare-submoduleWith-noshorthand.nix │ │ │ ├── declare-submoduleWith-path.nix │ │ │ ├── declare-submoduleWith-shorthand.nix │ │ │ ├── declare-submoduleWith-special.nix │ │ │ ├── declare-variants.nix │ │ │ ├── default.nix │ │ │ ├── deferred-module-error.nix │ │ │ ├── deferred-module.nix │ │ │ ├── define-_module-args-custom.nix │ │ │ ├── define-attrsOfSub-bar-enable.nix │ │ │ ├── define-attrsOfSub-bar.nix │ │ │ ├── define-attrsOfSub-foo-enable-force.nix │ │ │ ├── define-attrsOfSub-foo-enable-if.nix │ │ │ ├── define-attrsOfSub-foo-enable.nix │ │ │ ├── define-attrsOfSub-foo-force-enable.nix │ │ │ ├── define-attrsOfSub-foo-if-enable.nix │ │ │ ├── define-attrsOfSub-foo.nix │ │ │ ├── define-attrsOfSub-force-foo-enable.nix │ │ │ ├── define-attrsOfSub-if-foo-enable.nix │ │ │ ├── define-bare-submodule-values.nix │ │ │ ├── define-enable-abort.nix │ │ │ ├── define-enable-force.nix │ │ │ ├── define-enable-throw.nix │ │ │ ├── define-enable-with-custom-arg.nix │ │ │ ├── define-enable-with-top-level-mkIf.nix │ │ │ ├── define-enable.nix │ │ │ ├── define-force-attrsOfSub-foo-enable.nix │ │ │ ├── define-force-enable.nix │ │ │ ├── define-freeform-keywords-shorthand.nix │ │ │ ├── define-if-attrsOfSub-foo-enable.nix │ │ │ ├── define-module-check.nix │ │ │ ├── define-option-dependently-nested.nix │ │ │ ├── define-option-dependently.nix │ │ │ ├── define-settingsDict-a-is-b.nix │ │ │ ├── define-shorthandOnlyDefinesConfig-true.nix │ │ │ ├── define-submoduleWith-noshorthand.nix │ │ │ ├── define-submoduleWith-shorthand.nix │ │ │ ├── define-value-int-negative.nix │ │ │ ├── define-value-int-positive.nix │ │ │ ├── define-value-int-zero.nix │ │ │ ├── define-value-list.nix │ │ │ ├── define-value-string-arbitrary.nix │ │ │ ├── define-value-string-bigint.nix │ │ │ ├── define-value-string-properties.nix │ │ │ ├── define-value-string.nix │ │ │ ├── define-variant.nix │ │ │ ├── disable-declare-enable.nix │ │ │ ├── disable-define-enable-string-path.nix │ │ │ ├── disable-define-enable.nix │ │ │ ├── disable-enable-modules.nix │ │ │ ├── disable-module-bad-key.nix │ │ │ ├── disable-module-with-key.nix │ │ │ ├── disable-module-with-toString-key.nix │ │ │ ├── disable-recursive │ │ │ │ ├── bar.nix │ │ │ │ ├── disable-bar.nix │ │ │ │ ├── disable-foo.nix │ │ │ │ ├── foo.nix │ │ │ │ └── main.nix │ │ │ ├── doRename-basic.nix │ │ │ ├── doRename-warnings.nix │ │ │ ├── emptyValues.nix │ │ │ ├── extendModules-168767-imports.nix │ │ │ ├── freeform-attrsOf.nix │ │ │ ├── freeform-lazyAttrsOf.nix │ │ │ ├── freeform-nested.nix │ │ │ ├── freeform-str-dep-unstr.nix │ │ │ ├── freeform-submodules.nix │ │ │ ├── freeform-unstr-dep-str.nix │ │ │ ├── functionTo │ │ │ │ ├── list-order.nix │ │ │ │ ├── merging-attrs.nix │ │ │ │ ├── merging-list.nix │ │ │ │ ├── submodule-options.nix │ │ │ │ ├── trivial.nix │ │ │ │ └── wrong-type.nix │ │ │ ├── gvariant.nix │ │ │ ├── import-configuration.nix │ │ │ ├── import-custom-arg.nix │ │ │ ├── import-from-store.nix │ │ │ ├── merge-module-with-key.nix │ │ │ ├── merge-typeless-option.nix │ │ │ ├── module-argument-default.nix │ │ │ ├── module-class-is-darwin.nix │ │ │ ├── module-class-is-nixos.nix │ │ │ ├── module-imports-_type-check.nix │ │ │ ├── optionTypeFile.nix │ │ │ ├── optionTypeMerging.nix │ │ │ ├── options-type-error-configuration.nix │ │ │ ├── options-type-error-typical-nested.nix │ │ │ ├── options-type-error-typical.nix │ │ │ ├── raw.nix │ │ │ ├── shorthand-meta.nix │ │ │ ├── submoduleFiles.nix │ │ │ ├── test-mergeAttrDefinitionsWithPrio.nix │ │ │ ├── types-anything │ │ │ │ ├── attrs-coercible.nix │ │ │ │ ├── equal-atoms.nix │ │ │ │ ├── functions.nix │ │ │ │ ├── lists.nix │ │ │ │ ├── mk-mods.nix │ │ │ │ └── nested-attrs.nix │ │ │ └── types.nix │ │ ├── release.nix │ │ ├── systems.nix │ │ └── teams.nix │ ├── trivial.nix │ ├── types.nix │ ├── versions.nix │ └── zip-int-bits.nix │ ├── atom │ ├── functor.expect │ ├── functor.nix │ ├── functor.pos │ ├── inherit.expect │ ├── inherit.nix │ ├── inherit.pos │ ├── partially_applied_1_lambda.expect │ ├── partially_applied_1_lambda.nix │ ├── partially_applied_1_lambda.pos │ ├── partially_applied_2_lambda.expect │ ├── partially_applied_2_lambda.nix │ ├── partially_applied_2_lambda.pos │ ├── trivial_lambda.expect │ ├── trivial_lambda.nix │ └── trivial_lambda.pos │ ├── bulk │ ├── data.expect │ └── data.json │ ├── content_format │ ├── add.expect │ ├── add.json │ ├── foldl'.expect │ └── foldl'.json │ ├── inheritance │ ├── add.expect │ ├── add.json │ ├── catAttrs.expect │ ├── catAttrs.json │ ├── concatStrings.expect │ ├── concatStrings.json │ ├── foldl.expect │ ├── foldl.json │ ├── strings.expect │ └── strings.json │ ├── makeOverridable │ └── test.json │ └── types │ ├── basic.expect │ ├── basic.md │ ├── many.expect │ ├── many.md │ ├── nested.expect │ └── nested.md ├── preCommit.nix ├── projects.toml ├── salt ├── README.md ├── flake-module.nix └── src │ ├── builtins.types.json │ └── manual-link.map.json ├── tests ├── .gitignore ├── __snapshots__ │ └── data.test.js.snap ├── data.test.js ├── jest.config.js ├── package-lock.json └── package.json ├── treefmt.toml └── website ├── .envrc ├── .eslintrc.json ├── .gitignore ├── .vscode └── settings.json ├── createEmotionCache.ts ├── default.nix ├── flake-module.nix ├── next-sitemap.config.js ├── next.config.mjs ├── package-lock.json ├── package.json ├── public ├── favicon.ico ├── favicon.png ├── google_logo.png ├── nix-snowflake.svg ├── search.xml ├── vercel.svg └── white.svg ├── shell.nix ├── src ├── app │ ├── api │ │ └── v1 │ │ │ └── data │ │ │ └── route.ts │ ├── f │ │ └── [...path] │ │ │ ├── layout.tsx │ │ │ └── page.tsx │ ├── layout.tsx │ ├── md │ │ ├── documentation │ │ │ └── page.mdx │ │ ├── layout.tsx │ │ ├── release │ │ │ └── 2024-1 │ │ │ │ └── page.mdx │ │ ├── tutorials │ │ │ ├── derivationStrict │ │ │ │ └── page.md │ │ │ └── functors │ │ │ │ └── page.mdx │ │ └── typing │ │ │ └── page.mdx │ ├── not-found.tsx │ ├── page.tsx │ ├── pkgs │ │ ├── layout.tsx │ │ └── page.tsx │ └── q │ │ ├── layout.tsx │ │ └── page.tsx ├── assets │ ├── nix-snowflake.svg │ └── white.svg ├── client.ts ├── components │ ├── BackButton.tsx │ ├── ClientSideLayoutContext.tsx │ ├── HighlightBaseline.tsx │ ├── Lambda.tsx │ ├── LastUpdatedFromCommit.tsx │ ├── Pagefind.tsx │ ├── PagefindResults.tsx │ ├── PositionInisghts.tsx │ ├── PositionLink.tsx │ ├── ResultPreview.tsx │ ├── SearchNav.tsx │ ├── SearchResults.tsx │ ├── ShareButton.tsx │ ├── emptyRecordsPlaceholder │ │ ├── emptyRecordsPlaceholder.tsx │ │ └── index.tsx │ ├── example.json │ ├── filter.tsx │ ├── functionOfTheDay │ │ ├── functionOfTheDay.tsx │ │ └── index.ts │ ├── image │ │ ├── image.tsx │ │ └── index.tsx │ ├── layout │ │ ├── Background.tsx │ │ ├── filterContext.tsx │ │ ├── header.tsx │ │ ├── index.ts │ │ ├── layout.tsx │ │ └── themeSwitch.tsx │ ├── markdownPreview │ │ ├── MarkdownPreview.tsx │ │ └── index.ts │ ├── preview │ │ ├── index.tsx │ │ └── preview.tsx │ ├── searchInput │ │ ├── index.tsx │ │ ├── pkgsSearch.tsx │ │ └── searchInput.tsx │ └── selectOption │ │ ├── index.ts │ │ └── selectOption.tsx ├── excerpt.ts ├── fonts │ └── index ├── mdx-components.tsx ├── models │ ├── data │ │ └── index.ts │ ├── internals.ts │ ├── nix.ts │ └── primop.ts ├── plugins.ts ├── queries │ ├── byQuery.ts │ ├── byType.ts │ ├── index.ts │ └── lib.ts ├── styles │ ├── globals.css │ └── theme │ │ ├── common.ts │ │ ├── index.tsx │ │ └── themeOptions.ts ├── types │ └── basicDataView.ts └── utils.ts └── tsconfig.json /.envrc: -------------------------------------------------------------------------------- 1 | use flake -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | pdefs.nix linguist-vendored 2 | */test_data/assets/* linguist-vendored -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: bug 6 | assignees: '' 7 | 8 | --- 9 | 10 | **What happened** 11 | The bug you encountered 12 | 13 | **Steps to Reproduce** 14 | Steps to reproduce the behavior: 15 | 1. Go to '...' 16 | 2. Click on '....' 17 | 3. Scroll down to '....' 18 | 4. See error 19 | 20 | **Expected behavior** 21 | A clear and concise description of what you expected to happen. 22 | 23 | **Screenshots** 24 | If applicable, add screenshots to help explain your problem. 25 | 26 | **Desktop (please complete the following information):** 27 | - OS: [e.g. iOS] 28 | - Browser [e.g. chrome, safari] 29 | - Version [e.g. 22] 30 | - Screen resolution (optional) 31 | 32 | or 33 | 34 | **Smartphone (please complete the following information):** 35 | - Device: [e.g. iPhone6] 36 | - OS: [e.g. iOS8.1] 37 | - Browser [e.g. stock browser, safari] 38 | - Version [e.g. 22] 39 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **If your Feature is adding / extending more functions** 11 | Tell us where to find the function / functions e.g. where in nixpkgs 12 | 13 | **Is your feature request related to a problem? Please describe.** 14 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 15 | 16 | **Describe the solution you'd like** 17 | A clear and concise description of what you want to happen. 18 | 19 | **Describe alternatives you've considered** 20 | A clear and concise description of any alternative solutions or features you've considered. 21 | 22 | **Additional context** 23 | Add any other context or screenshots about the feature request here. 24 | -------------------------------------------------------------------------------- /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | name: "artifact-build" 2 | on: 3 | push: 4 | pull_request: 5 | branches: [ "main" ] 6 | 7 | env: 8 | cloudflare_project: noogle 9 | 10 | jobs: 11 | build: 12 | runs-on: ubuntu-latest 13 | permissions: 14 | contents: read 15 | steps: 16 | - uses: actions/checkout@v4 17 | - uses: cachix/install-nix-action@v23 18 | with: 19 | nix_path: nixpkgs=channel:nixos-unstable 20 | - uses: cachix/cachix-action@v12 21 | with: 22 | name: nix-community 23 | authToken: '${{ secrets.CACHIX_AUTH_TOKEN }}' 24 | - run: nix build .#ui -L 25 | - name: Save output 26 | uses: actions/upload-artifact@v4 27 | with: 28 | path: ./result 29 | -------------------------------------------------------------------------------- /.github/workflows/update-nix.yml: -------------------------------------------------------------------------------- 1 | name: update-nixpkgs-master-lock 2 | on: 3 | workflow_dispatch: # allows manual triggering 4 | schedule: 5 | - cron: "0 0 * * *" # runs daily at 00:00 6 | 7 | jobs: 8 | lockfile: 9 | runs-on: ubuntu-latest 10 | steps: 11 | - name: Checkout repository 12 | uses: actions/checkout@v4 13 | - name: Install Nix 14 | uses: cachix/install-nix-action@v25 15 | with: 16 | extra_nix_config: | 17 | access-tokens = github.com=${{ secrets.GITHUB_TOKEN }} 18 | - name: Update flake.lock 19 | uses: DeterminateSystems/update-flake-lock@v25 20 | with: 21 | token: ${{ secrets.GH_ACTIONS }} 22 | pr-title: "Update: nixpkgs-master input" 23 | pr-labels: | 24 | auto-merge 25 | inputs: nixpkgs-master 26 | -------------------------------------------------------------------------------- /.github/workflows/update-nixpkgs.yml: -------------------------------------------------------------------------------- 1 | name: update-nix-master-lock 2 | on: 3 | workflow_dispatch: # allows manual triggering 4 | schedule: 5 | - cron: "0 1 * * *" # runs daily at 00:00 6 | 7 | jobs: 8 | lockfile: 9 | runs-on: ubuntu-latest 10 | steps: 11 | - name: Checkout repository 12 | uses: actions/checkout@v4 13 | - name: Install Nix 14 | uses: cachix/install-nix-action@v25 15 | with: 16 | extra_nix_config: | 17 | access-tokens = github.com=${{ secrets.GITHUB_TOKEN }} 18 | - name: Update flake.lock 19 | uses: DeterminateSystems/update-flake-lock@v25 20 | with: 21 | token: ${{ secrets.GH_ACTIONS }} 22 | pr-title: "Update: nix-master input" 23 | pr-labels: | 24 | auto-merge 25 | inputs: nix-master 26 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | # testing 3 | coverage 4 | 5 | # nix 6 | .direnv/ 7 | result 8 | result-* 9 | node_modules 10 | 11 | .pre-commit-config.yaml 12 | -------------------------------------------------------------------------------- /.mergify.yml: -------------------------------------------------------------------------------- 1 | queue_rules: 2 | - name: default 3 | queue_conditions: 4 | - base=main 5 | - label~=merge-queue|auto-merge|dependencies 6 | merge_conditions: 7 | - check-success=deploy 8 | merge_method: rebase 9 | 10 | pull_request_rules: 11 | - name: refactored queue action rule 12 | conditions: [] 13 | actions: 14 | queue: 15 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 Johannes Kirschbauer 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # [Noogle](https://noogle.dev) 2 | 3 | ![Website](https://img.shields.io/website?down_message=noogle.dev&up_message=noogle.dev&url=https%3A%2F%2Fnoogle.dev) 4 | ![GitHub top language](https://img.shields.io/github/languages/top/hsjobeki/noogle) 5 | ![GitHub Workflow Status](https://img.shields.io/github/actions/workflow/status/hsjobeki/noogle/main.yml) 6 | 7 | ## Noogle is a simple Nix API search engine. It lets you search Nix functions 8 | 9 | ## Current Features 10 | 11 | - [x] Beginners-friendly search for Nix and Nix-related functions. 12 | - Render documentation comments optimized for readability. 13 | - Search optimized for English language and Nix function-names. 14 | - [x] Filter by **type** signatures. 15 | - Function types are parsed and interpreted. 16 | - [x] Noogle also knows stuff that is not (yet) officially documented. 17 | - Types of `builtins` (including `builtins.derivation`). 18 | - Can be extended via markdown contributions to Noogle. 19 | - Always shows the latest docs based on the main branch of Nixpkgs. 20 | - [x] Outputs pre-rendered static HTML that is indexable by other search 21 | engines. 22 | - [x] Wasm based performant search. 23 | 24 | ## Nice features 25 | 26 | - Detect aliases of (most) `lib` and `builtins` functions 27 | - Override `builtins` documentation by documenting their alias in `nixpkgs.lib`. So you don't need to change and rebuild cpp nix anymore. 28 | - `nix` and `nixpkgs` are updated daily. All documentation changes will be picked up just the next day. 29 | 30 | --- 31 | 32 | All Indexing is done via the [pasta](./pasta/) module. PRs welcome! 33 | 34 | Additional data - such as types of builtins - are available in [salt](./salt) 35 | 36 | ## Contribute 37 | 38 | Contributions are very welcome just file a PR or issue. Indexed data can be 39 | added very easily in `./pasta/src/eval.nix`. 40 | 41 | > Note: Indexed data must evaluate! 42 | 43 | ### Build this page 44 | 45 | `nix build .#ui` 46 | 47 | This page generates static HTML pages. One page per API function. 48 | 49 | It automatically includes meta tags for other search engines like Google or 50 | Bing. 51 | 52 | Searching within the page is done via [pagefind](https://pagefind.app/) which is 53 | only available in the production build. 54 | 55 | ### Develop 56 | 57 | `nix develop` 58 | 59 | This command creates the `node_modules` directory with all needed dependencies 60 | based on `dream2nix`. 61 | -------------------------------------------------------------------------------- /codemod/.envrc: -------------------------------------------------------------------------------- 1 | source_up 2 | 3 | files=(../../flake.nix flake-module.nix Cargo.lock) 4 | if type nix_direnv_watch_file &>/dev/null; then 5 | nix_direnv_watch_file "${files[@]}" 6 | else 7 | watch_file "${files[@]}" 8 | fi 9 | 10 | use flake .#codemod --builders '' 11 | -------------------------------------------------------------------------------- /codemod/.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | result* 3 | -------------------------------------------------------------------------------- /codemod/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "codemod" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | [profile.dev] 8 | debug = true 9 | 10 | [dependencies] 11 | clap = { version = "4.4.4", features = ["derive"] } 12 | regex = "1.9.5" 13 | rnix = "0.11.0" 14 | rowan = { version = "*" } 15 | serde_json = "1.0.138" 16 | textwrap = "0.16.0" 17 | walkdir = "2.4.0" 18 | 19 | [dev-dependencies] 20 | expect-test = "1.4.0" 21 | -------------------------------------------------------------------------------- /codemod/README.md: -------------------------------------------------------------------------------- 1 | # Doc-comments Codemod 2 | 3 | A simple codemod based on [rnix](https://github.com/nix-community/rnix-parser). 4 | It migrates all comments automatically into the new markdown format. 5 | 6 | ## Features 7 | 8 | - Fully automatic. 9 | - Changes all files from all directories (if needed). 10 | - Markdown output. 11 | - Re-aligns the indentation. 12 | 13 | ## Example 14 | 15 | `input` 16 | ```nix 17 | /* Throw if pred is false, else return pred. 18 | Intended to be used to augment asserts with helpful error messages. 19 | 20 | Example: 21 | assertMsg false "nope" 22 | stderr> error: nope 23 | 24 | assert assertMsg ("foo" == "bar") "foo is not bar, silly"; "" 25 | stderr> error: foo is not bar, silly 26 | 27 | Type: 28 | assertMsg :: Bool -> String -> Bool 29 | */ 30 | assertMsg = 31 | ``` 32 | 33 | -> 34 | 35 | `output` 36 | ````nix 37 | /** 38 | Throw if pred is false, else return pred. 39 | Intended to be used to augment asserts with helpful error messages. 40 | 41 | # Example 42 | 43 | ```nix 44 | assertMsg false "nope" 45 | stderr> error: nope 46 | 47 | assert assertMsg ("foo" == "bar") "foo is not bar, silly"; "" 48 | stderr> error: foo is not bar, silly 49 | ``` 50 | 51 | # Type 52 | 53 | ``` 54 | assertMsg :: Bool -> String -> Bool 55 | ``` 56 | */ 57 | assertMsg = 58 | ```` 59 | 60 | ## Development 61 | 62 | Enter the devshell 63 | 64 | `nix develop .#codemod` 65 | -------------------------------------------------------------------------------- /codemod/flake-module.nix: -------------------------------------------------------------------------------- 1 | { inputs, ... }: { 2 | perSystem = { self', inputs', pkgs, system, ... }: 3 | let 4 | craneLib = inputs.crane.lib.${system}; 5 | # src = craneLib.cleanCargoSource (craneLib.path ./.); 6 | src = craneLib.path ./.; 7 | 8 | commonArgs = { 9 | inherit src; 10 | strictDeps = true; 11 | cargoArtifacts = craneLib.buildDepsOnly commonArgs; 12 | }; 13 | 14 | codemod = craneLib.buildPackage commonArgs; 15 | 16 | 17 | nixpkgs-migrated = pkgs.stdenv.mkDerivation { 18 | name = "nixpkgs-migrated"; 19 | src = inputs.nixpkgs-master; 20 | buildPhase = '' 21 | ${self'.packages.codemod}/bin/codemod . 22 | cp -r . $out 23 | ''; 24 | dontFixup = true; 25 | }; 26 | 27 | checks = { 28 | inherit codemod; 29 | codemod-clippy = craneLib.cargoClippy (commonArgs // { 30 | cargoClippyExtraArgs = "--all-targets -- --deny warnings"; 31 | }); 32 | codemod-fmt = craneLib.cargoFmt { inherit src; }; 33 | codemod-nextest = craneLib.cargoNextest (commonArgs // { 34 | partitions = 1; 35 | partitionType = "count"; 36 | }); 37 | }; 38 | in 39 | { 40 | packages = { inherit codemod nixpkgs-migrated; }; 41 | inherit checks; 42 | devShells.codemod = craneLib.devShell { 43 | # Inherit inputs from checks. 44 | inherit checks; 45 | }; 46 | }; 47 | } 48 | -------------------------------------------------------------------------------- /codemod/prefixes.json: -------------------------------------------------------------------------------- 1 | { 2 | "versions.nix": "lib.versions", 3 | "licenses.nix": "lib.licenses", 4 | "strings-with-deps.nix": "lib.stringsWithDeps", 5 | "modules.nix": "lib.modules", 6 | "path/default.nix": "lib.path", 7 | "fileset/internal.nix": "lib.fileset.internal", 8 | "systems/default.nix": "lib.systems.default", 9 | "options.nix": "lib.options", 10 | "sources.nix": "lib.sources" 11 | } 12 | -------------------------------------------------------------------------------- /codemod/src/tests.rs: -------------------------------------------------------------------------------- 1 | #[cfg(test)] 2 | mod tests { 3 | use std::{fs, path::PathBuf}; 4 | 5 | use crate::replace_all; 6 | use expect_test::expect_file; 7 | use rowan::ast::AstNode; 8 | 9 | #[test] 10 | fn test_snapshot_mixed() { 11 | let path: PathBuf = [env!("CARGO_MANIFEST_DIR"), "test_data", "mixed.nix"] 12 | .iter() 13 | .collect(); 14 | dbg!(&path); 15 | let src = fs::read_to_string(&path).unwrap(); 16 | let nix = rnix::Root::parse(&src).ok().expect("failed to parse input"); 17 | 18 | let (res, _count) = replace_all(nix.syntax().to_owned(), None); 19 | 20 | let actual = res.unwrap().to_string(); 21 | 22 | expect_file![path.with_extension("expect")].assert_eq(&actual); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /codemod/test_data/args.nix: -------------------------------------------------------------------------------- 1 | { 2 | /* 3 | Reduce a list by applying a binary operator from left to right, 4 | starting with an initial accumulator. 5 | 6 | Before each application of the operator, the accumulator value is evaluated. 7 | This behavior makes this function stricter than [`foldl`](#function-library-lib.lists.foldl). 8 | 9 | Unlike [`builtins.foldl'`](https://nixos.org/manual/nix/unstable/language/builtins.html#builtins-foldl'), 10 | the initial accumulator argument is evaluated before the first iteration. 11 | 12 | A call like 13 | 14 | ```nix 15 | foldl' op acc₀ [ x₀ x₁ x₂ ... xₙ₋₁ xₙ ] 16 | ``` 17 | 18 | is (denotationally) equivalent to the following, 19 | but with the added benefit that `foldl'` itself will never overflow the stack. 20 | 21 | ```nix 22 | let 23 | acc₁ = builtins.seq acc₀ (op acc₀ x₀ ); 24 | acc₂ = builtins.seq acc₁ (op acc₁ x₁ ); 25 | acc₃ = builtins.seq acc₂ (op acc₂ x₂ ); 26 | ... 27 | accₙ = builtins.seq accₙ₋₁ (op accₙ₋₁ xₙ₋₁); 28 | accₙ₊₁ = builtins.seq accₙ (op accₙ xₙ ); 29 | in 30 | accₙ₊₁ 31 | 32 | # Or ignoring builtins.seq 33 | op (op (... (op (op (op acc₀ x₀) x₁) x₂) ...) xₙ₋₁) xₙ 34 | ``` 35 | 36 | Type: foldl' :: (acc -> x -> acc) -> acc -> [x] -> acc 37 | 38 | Example: 39 | foldl' (acc: x: acc + x) 0 [1 2 3] 40 | => 6 41 | */ 42 | foldl' = 43 | /* The binary operation to run, where the two arguments are: 44 | 45 | 1. `acc`: The current accumulator value: Either the initial one for the first iteration, or the result of the previous iteration 46 | 2. `x`: The corresponding list element for this iteration 47 | */ 48 | op: 49 | # The initial accumulator value 50 | acc: 51 | # The list to fold 52 | list: 53 | 54 | # The builtin `foldl'` is a bit lazier than one might expect. 55 | # See https://github.com/NixOS/nix/pull/7158. 56 | # In particular, the initial accumulator value is not forced before the first iteration starts. 57 | builtins.seq acc 58 | (builtins.foldl' op acc list); 59 | } 60 | -------------------------------------------------------------------------------- /codemod/test_data/args/default.nix: -------------------------------------------------------------------------------- 1 | { 2 | /* 3 | Header 4 | 5 | Example: 6 | assertMsg false "nope" 7 | 8 | Type: 9 | assertMsg :: Bool -> String -> Bool 10 | 11 | */ 12 | stuff = 13 | # a arg 14 | a: 15 | # b arg 16 | b: a; 17 | } 18 | -------------------------------------------------------------------------------- /codemod/test_data/mixed.expect: -------------------------------------------------------------------------------- 1 | { 2 | /** 3 | Short tagline 4 | in multiline 5 | with empty lines 6 | 7 | indepentent block of lines 8 | should not be indented differently 9 | 10 | > Note: this is a note. 11 | 12 | ```nix 13 | { 14 | a = { 15 | b = { 16 | c = { 17 | d = 1; 18 | }; 19 | }; 20 | }; 21 | } 22 | ``` 23 | 24 | Codeblocks must keep indentation. 25 | 26 | 27 | # Inputs 28 | 29 | `dir` 30 | 31 | : 1\. Function argument 32 | 33 | # Type 34 | 35 | ``` 36 | Indent :: a -> 37 | { 38 | a: { 39 | b: { 40 | c: { 41 | d: Int; 42 | }; 43 | }; 44 | }; 45 | } 46 | ``` 47 | 48 | # Examples 49 | :::{.example} 50 | ## `packageDir` usage example 51 | 52 | ```nix 53 | packageDir "foo" 54 | => { 55 | foo = { 56 | src = ./.; 57 | }; 58 | } 59 | ``` 60 | 61 | ::: 62 | */ 63 | packageDir = dir: 1; 64 | } 65 | -------------------------------------------------------------------------------- /codemod/test_data/mixed.nix: -------------------------------------------------------------------------------- 1 | { 2 | /*Short tagline 3 | in multiline 4 | with empty lines 5 | 6 | indepentent block of lines 7 | should not be indented differently 8 | 9 | > Note: this is a note. 10 | 11 | ```nix 12 | { 13 | a = { 14 | b = { 15 | c = { 16 | d = 1; 17 | }; 18 | }; 19 | }; 20 | } 21 | ``` 22 | 23 | Codeblocks must keep indentation. 24 | 25 | Type: 26 | Indent :: a -> 27 | { 28 | a: { 29 | b: { 30 | c: { 31 | d: Int; 32 | }; 33 | }; 34 | }; 35 | } 36 | 37 | Example: 38 | packageDir "foo" 39 | => { 40 | foo = { 41 | src = ./.; 42 | }; 43 | } 44 | */ 45 | packageDir = dir: 1; 46 | } 47 | -------------------------------------------------------------------------------- /codemod/test_data/nested/sample.nix: -------------------------------------------------------------------------------- 1 | { 2 | /** 3 | Header 4 | 5 | # Example 6 | 7 | ```nix 8 | format me 9 | nested 1 10 | nested 2 11 | ``` 12 | 13 | # Type 14 | 15 | ``` 16 | some :: { 17 | nested :: Number; 18 | } 19 | ``` 20 | */ 21 | stuff = 1; 22 | /* Throw if pred is false, else return pred. 23 | Intended to be used to augment asserts with helpful error messages. 24 | 25 | Example: 26 | assertMsg false "nope" 27 | stderr> error: nope 28 | 29 | assert assertMsg ("foo" == "bar") "foo is not bar, silly"; "" 30 | stderr> error: foo is not bar, silly 31 | 32 | Type: 33 | assertMsg :: Bool -> String -> Bool 34 | */ 35 | fun = true; 36 | } 37 | -------------------------------------------------------------------------------- /codemod/test_data/simple.nix: -------------------------------------------------------------------------------- 1 | /** 2 | Map each attribute in the given set and merge them into a new attribute set. 3 | 4 | # Example 5 | 6 | ```nix 7 | concatMapAttrs 8 | (name: value: { 9 | ${name} = value; 10 | ${name + value} = value; 11 | }) 12 | { x = "a"; y = "b"; } 13 | => { x = "a"; xa = "a"; y = "b"; yb = "b"; } 14 | ``` 15 | 16 | # Type 17 | 18 | ``` 19 | concatMapAttrs :: (String -> a -> AttrSet) -> AttrSet -> AttrSet 20 | ``` 21 | */ 22 | 1 23 | -------------------------------------------------------------------------------- /devShell.nix: -------------------------------------------------------------------------------- 1 | { 2 | perSystem = { pkgs, self', config, ... }: { 3 | devShells.default = pkgs.mkShell { 4 | packages = [ pkgs.treefmt ]; 5 | shellHook = '' 6 | ${self'.checks.pre-commit-check.shellHook} 7 | ''; 8 | }; 9 | }; 10 | } 11 | -------------------------------------------------------------------------------- /flake.nix: -------------------------------------------------------------------------------- 1 | { 2 | description = "Noogle.dev | Discover the nix api surface"; 3 | inputs = { 4 | # --- sources of documentation --- 5 | # Updated automatically 6 | nixpkgs-master.url = "nixpkgs/master"; 7 | nix-master.url = "github:NixOS/nix/?ref=master"; 8 | 9 | # --- Other flake inputs --- 10 | nixpkgs.url = "nixpkgs/nixos-unstable"; 11 | # A custom nix version, to introspect lambda values. 12 | # nix.url = "github:hsjobeki/nix/?ref=feat/positions"; 13 | 14 | pre-commit-hooks = { 15 | url = "github:cachix/pre-commit-hooks.nix"; 16 | inputs.nixpkgs.follows = "nixpkgs"; 17 | }; 18 | 19 | systems.url = "github:nix-systems/default-linux"; 20 | flake-parts.url = "github:hercules-ci/flake-parts"; 21 | flake-parts.inputs.nixpkgs-lib.follows = "nixpkgs"; 22 | treefmt-nix.url = "github:numtide/treefmt-nix"; 23 | treefmt-nix.inputs.nixpkgs.follows = "nixpkgs"; 24 | 25 | crane.url = "github:ipetkov/crane"; 26 | crane.inputs.nixpkgs.follows = "nixpkgs"; 27 | }; 28 | 29 | outputs = inputs@{ flake-parts, systems, ... }: 30 | flake-parts.lib.mkFlake { inherit inputs; } ({ ... }: { 31 | systems = import systems; 32 | imports = [ 33 | ./devShell.nix 34 | ./preCommit.nix 35 | ./website/flake-module.nix 36 | ./salt/flake-module.nix 37 | ./pasta/flake-module.nix 38 | ./pesto/flake-module.nix 39 | # Deprecated. Will be removed. 40 | ./codemod/flake-module.nix 41 | # 42 | ./nixPlugin/flake-module.nix 43 | ]; 44 | perSystem = { inputs', ... }: { 45 | packages = { 46 | # nix = inputs'.nix-master.packages.nix-cli.overrideAttrs (prev: { 47 | # # doCheck = false; 48 | # mesonFlags = prev.mesonFlags or [] ++ [ 49 | # "-Dunit-tests=false" 50 | # ]; 51 | # }); 52 | }; 53 | }; 54 | }); 55 | } 56 | -------------------------------------------------------------------------------- /nixPlugin/.gitignore: -------------------------------------------------------------------------------- 1 | *.o 2 | *.so 3 | Makefile 4 | CMakeCache.txt 5 | CMakeFiles 6 | cmake_install.cmake 7 | nix-plugins-config.h 8 | -------------------------------------------------------------------------------- /nixPlugin/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required (VERSION 3.9) 2 | project (noogle-plugin) 3 | 4 | find_package(PkgConfig) 5 | 6 | pkg_check_modules(NIX REQUIRED nix-expr>=2.24 nix-main>=2.24 nix-store>=2.24) 7 | 8 | find_path(BOOST_INCLUDE_DIR boost/format.hpp) 9 | if(BOOST_INCLUDE_DIR STREQUAL "BOOST_INCLUDE_DIR-NOTFOUND") 10 | message(FATAL_ERROR "Could not find Boost formatting library.") 11 | endif() 12 | include_directories(${BOOST_INCLUDE_DIR}) 13 | 14 | if(APPLE) 15 | set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} -flat_namespace -undefined suppress") 16 | endif() 17 | 18 | add_library(noogle-plugin MODULE plugin.cc) 19 | 20 | target_include_directories(noogle-plugin PUBLIC ${CMAKE_CURRENT_BINARY_DIR}) 21 | target_include_directories(noogle-plugin PUBLIC ${NIX_INCLUDE_DIRS}) 22 | target_compile_options(noogle-plugin PUBLIC ${NIX_CFLAGS_OTHER}) 23 | 24 | install(TARGETS noogle-plugin DESTINATION lib/nix/plugins) 25 | -------------------------------------------------------------------------------- /nixPlugin/flake-module.nix: -------------------------------------------------------------------------------- 1 | { ... }: { 2 | perSystem = { pkgs, system, ... }: 3 | let 4 | nix = pkgs.nixVersions.nix_2_25; 5 | in 6 | { 7 | packages = { 8 | noogle-plugin = pkgs.callPackage ./package.nix { inherit system nix; }; 9 | }; 10 | devShells = { 11 | noogle-plugin = pkgs.mkShell { 12 | packages = [ nix ]; 13 | }; 14 | }; 15 | }; 16 | } 17 | -------------------------------------------------------------------------------- /nixPlugin/package.nix: -------------------------------------------------------------------------------- 1 | { pkgs 2 | , nix 3 | , system 4 | }: 5 | pkgs.llvmPackages.stdenv.mkDerivation { 6 | name = "noogle-plugin"; 7 | src = ./.; 8 | buildInputs = [ 9 | nix 10 | pkgs.boost 11 | ]; 12 | # For "safe" usage people should use this exact nix version 13 | passthru = { 14 | inherit nix; 15 | }; 16 | nativeBuildInputs = with pkgs; [ 17 | cmake 18 | pkg-config 19 | ]; 20 | CXXFLAGS = [ 21 | "-I${nix.dev}/include/nix" 22 | "-DHAVE_BOEHMGC" 23 | "-DSYSTEM='\"${system}\"'" 24 | ]; 25 | installPhase = '' 26 | mkdir -p $out/lib 27 | cp libnoogle-plugin.so $out/lib 28 | ''; 29 | } 30 | -------------------------------------------------------------------------------- /pasta/.envrc: -------------------------------------------------------------------------------- 1 | source_up 2 | 3 | files=(../../flake.nix flake-module.nix) 4 | if type nix_direnv_watch_file &>/dev/null; then 5 | nix_direnv_watch_file "${files[@]}" 6 | else 7 | watch_file "${files[@]}" 8 | fi 9 | 10 | use flake .#pasta --builders '' 11 | -------------------------------------------------------------------------------- /pasta/README.md: -------------------------------------------------------------------------------- 1 | # Dough -> Pasta 2 | 3 | We have to make our pasta from the Nixpkgs raw dough. 4 | 5 | Analyse arbitrary nix expressions. 6 | 7 | Contains tools, such as nix functions, that allow us to introspect the nix language. 8 | 9 | Evaluating expressions and their metadata allows for precise documentation building 10 | 11 | Evaluation requires a custom nix version available via devShell '.#pastaMaker' 12 | 13 | Analyses a given path in the expression tree. 14 | 15 | - Recursive tool, that works well with e.g., `pkgs.lib` or other sets that don't have hard evaluation errors inside them. Note: All kinds of recursions are reliably avoided. 16 | - Flat tool, that works on attribute sets, without recursing it. Since both tools are not lazy they require at least the analyzed value to have no hard errors. 17 | 18 | ## Features 19 | 20 | - Finding lambdas recursively 21 | - Adding metadata about lambdas 22 | - Attribute Source Position 23 | - Lambda Source position 24 | - Count Partially Applied 25 | - ... 26 | -------------------------------------------------------------------------------- /pasta/default.nix: -------------------------------------------------------------------------------- 1 | { pkgs, nixpkgs, noogle-plugin, ... }: 2 | let nix = noogle-plugin.passthru.nix; in 3 | pkgs.stdenv.mkDerivation { 4 | name = "pasta"; 5 | src = ./src; 6 | nativeBuildInputs = [ nix ]; 7 | buildPhase = '' 8 | nix-instantiate --extra-experimental-features 'nix-command flakes' --plugin-files ${noogle-plugin}/lib/libnoogle-plugin.so --eval --strict --json --store $PWD --show-trace \ 9 | eval.nix --arg 'pkgs' 'import ${nixpkgs} {}' --arg 'repo' '${nixpkgs.outPath}' -A all \ 10 | > $out 11 | ''; 12 | } 13 | -------------------------------------------------------------------------------- /pasta/flake-module.nix: -------------------------------------------------------------------------------- 1 | { inputs, ... }: { 2 | perSystem = { self', inputs', pkgs, lib, ... }: 3 | let 4 | # inherit (inputs'.nix.packages) nix; 5 | nixpkgs = self'.packages.nixpkgs-migrated; 6 | 7 | sourceInfo' = { 8 | inherit (inputs.nixpkgs-master.sourceInfo) rev lastModified; 9 | }; 10 | metaFile = builtins.toFile "meta.json" (builtins.toJSON sourceInfo'); 11 | in 12 | { 13 | packages = { 14 | pasta-meta = pkgs.stdenv.mkDerivation { 15 | name = "pasta-meta"; 16 | src = ./.; 17 | buildPhase = '' 18 | cat ${metaFile} > $out 19 | ''; 20 | }; 21 | pasta = pkgs.callPackage ./default.nix { 22 | inherit nixpkgs pkgs; 23 | inherit (self'.packages) noogle-plugin; 24 | }; 25 | }; 26 | devShells.pastaMaker = pkgs.callPackage ./shell.nix { inherit pkgs; inherit (self'.packages) noogle-plugin; }; 27 | }; 28 | } 29 | -------------------------------------------------------------------------------- /pasta/shell.nix: -------------------------------------------------------------------------------- 1 | { pkgs, noogle-plugin, ... }: 2 | let 3 | nix = noogle-plugin.passthru.nix; 4 | in 5 | pkgs.mkShell { 6 | buildInputs = [ nix ]; 7 | shellHook = '' 8 | echo "using a custom nix build: ${nix}" 9 | ''; 10 | } 11 | -------------------------------------------------------------------------------- /pesto/.envrc: -------------------------------------------------------------------------------- 1 | source_up 2 | 3 | watch_file ../../flake.nix flake-module.nix Cargo.lock 4 | 5 | # use the 6 | use flake .#pesto --builders '' 7 | -------------------------------------------------------------------------------- /pesto/.gitignore: -------------------------------------------------------------------------------- 1 | target 2 | out -------------------------------------------------------------------------------- /pesto/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "pesto" 3 | description = "Gien a list of positions extract doc-comment into markdown and frontmatter." 4 | version = "0.1.0" 5 | edition = "2021" 6 | 7 | 8 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 9 | [profile.release] 10 | debug = true 11 | 12 | [dependencies] 13 | rnix = "0.11.0" 14 | # version defined by rnix 15 | rowan = { version = "*" } 16 | regex = "1.9.5" 17 | textwrap = "0.16.0" 18 | walkdir = "2.4.0" 19 | clap = { version = "4.4.4", features = ["derive"] } 20 | serde = { version = "1.0", features = ["derive", "rc"] } 21 | serde_json = "1.0" 22 | expect-test = "1.4.0" 23 | serde_with = "3.4.0" 24 | serde_yaml = "0.9.27" 25 | comrak = "0.20.0" 26 | 27 | 28 | # [dev-dependencies] 29 | -------------------------------------------------------------------------------- /pesto/README.md: -------------------------------------------------------------------------------- 1 | # Pesto 2 | 3 | Pesto gives you the extra sauce on top of your lambda noodles. 4 | 5 | From a given lambda position extract doc comments and some metadata. 6 | 7 | ## Plugin for Noogle 8 | 9 | Extract 'nixdoc style comments' or doc-comment (RFC145) from a given file position. 10 | 11 | Usage: 12 | 13 | ```sh 14 | pesto --file "attrsets.nix" --line "11" --column "3" 15 | -> 16 | { 17 | "doc": "content", 18 | "arguments": {}, 19 | "countApplied": 3 20 | } 21 | ``` 22 | 23 | ## Contribute 24 | 25 | Generating test dataset 26 | 27 | `nix build .#pasta -L` 28 | 29 | Which can the be passed 30 | 31 | `cargo run -- --pos-file result --format json ./out.json` 32 | 33 | It is recommended to remove all unneeded entries and operate on minimal list that contains only one entry. 34 | -------------------------------------------------------------------------------- /pesto/flake-module.nix: -------------------------------------------------------------------------------- 1 | { inputs, ... }: { 2 | perSystem = { self', inputs', pkgs, system, ... }: 3 | let 4 | craneLib = inputs.crane.lib.${system}; 5 | src = craneLib.cleanCargoSource (craneLib.path ./.); 6 | 7 | commonArgs = { 8 | inherit src; 9 | strictDeps = true; 10 | cargoArtifacts = craneLib.buildDepsOnly commonArgs; 11 | }; 12 | 13 | pesto = craneLib.buildPackage commonArgs; 14 | 15 | data-json = pkgs.stdenv.mkDerivation { 16 | name = "pesto-data"; 17 | src = ./.; 18 | buildPhase = '' 19 | ${pesto}/bin/pesto --pos-file ${self'.packages.pasta} --format json --language ${self'.packages.salt}/language.json $out 20 | ''; 21 | }; 22 | 23 | checks = { 24 | inherit pesto; 25 | pesto-clippy = craneLib.cargoClippy (commonArgs // { 26 | cargoClippyExtraArgs = "--all-targets -- --deny warnings"; 27 | }); 28 | pesto-fmt = craneLib.cargoFmt { inherit src; }; 29 | pesto-nextest = craneLib.cargoNextest (commonArgs // { 30 | partitions = 1; 31 | partitionType = "count"; 32 | }); 33 | }; 34 | in 35 | { 36 | packages = { inherit pesto data-json; }; 37 | inherit checks; 38 | devShells.pesto = craneLib.devShell { 39 | # Inherit inputs from checks. 40 | inherit checks; 41 | }; 42 | }; 43 | } 44 | -------------------------------------------------------------------------------- /pesto/src/markdown.rs: -------------------------------------------------------------------------------- 1 | use comrak::nodes::{AstNode, NodeValue}; 2 | use comrak::{parse_document, Arena, Options}; 3 | 4 | fn iter_nodes<'a, F>(node: &'a AstNode<'a>, f: &mut F) 5 | where 6 | F: FnMut(&'a AstNode<'a>), 7 | { 8 | f(node); 9 | for c in node.children() { 10 | iter_nodes(c, f); 11 | } 12 | } 13 | 14 | /// Find the type signature 15 | /// 16 | /// Looks for any heading "# Type" (case insensitive) 17 | /// 18 | /// The first code or code_block in that section is the type signature 19 | pub fn find_type(content: &str) -> Option { 20 | // The returned nodes are created in the supplied Arena, and are bound by its lifetime. 21 | let arena = Arena::new(); 22 | 23 | let root = parse_document(&arena, content, &Options::default()); 24 | 25 | let mut signature: Option = None; 26 | let mut do_capture = false; 27 | iter_nodes(root, &mut |node| match &node.data.borrow().value { 28 | NodeValue::Heading(_) => { 29 | match node 30 | .first_child() 31 | .as_ref() 32 | .map(|n| n.data.borrow().value.clone()) 33 | { 34 | Some(NodeValue::Text(text)) if text.trim().to_lowercase() == "type" => { 35 | do_capture = true; 36 | } 37 | _ => { 38 | do_capture = false; 39 | } 40 | } 41 | } 42 | NodeValue::CodeBlock(code_block) => { 43 | if signature.is_none() && do_capture { 44 | signature = Some(code_block.literal.clone()); 45 | } 46 | } 47 | _ => (), 48 | }); 49 | signature 50 | } 51 | -------------------------------------------------------------------------------- /pesto/test_data/aliases/add.expect: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "aliases": [ 4 | [ 5 | "lib", 6 | "trivial", 7 | "add" 8 | ], 9 | [ 10 | "builtins", 11 | "add" 12 | ] 13 | ], 14 | "path": [ 15 | "lib", 16 | "add" 17 | ] 18 | }, 19 | { 20 | "aliases": [ 21 | [ 22 | "lib", 23 | "add" 24 | ], 25 | [ 26 | "builtins", 27 | "add" 28 | ] 29 | ], 30 | "path": [ 31 | "lib", 32 | "trivial", 33 | "add" 34 | ] 35 | }, 36 | { 37 | "aliases": [ 38 | [ 39 | "lib", 40 | "add" 41 | ], 42 | [ 43 | "lib", 44 | "trivial", 45 | "add" 46 | ] 47 | ], 48 | "path": [ 49 | "builtins", 50 | "add" 51 | ] 52 | } 53 | ] -------------------------------------------------------------------------------- /pesto/test_data/aliases/add.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "docs": { 4 | "attr": { 5 | "position": { 6 | "column": 23, 7 | "file": "test_data/assets/default.nix", 8 | "line": 68 9 | } 10 | }, 11 | "lambda": { 12 | "args": ["e1", "e2"], 13 | "arity": 2, 14 | "content": "\n Return the sum of the numbers *e1* and *e2*.\n ", 15 | "experimental": false, 16 | "countApplied": 0, 17 | "isPrimop": true, 18 | "name": "add", 19 | "position": null 20 | } 21 | }, 22 | "path": ["lib", "add"] 23 | }, 24 | { 25 | "docs": { 26 | "attr": { 27 | "position": { 28 | "column": 21, 29 | "file": "test_data/assets/trivial.nix", 30 | "line": 269 31 | } 32 | }, 33 | "lambda": { 34 | "args": ["e1", "e2"], 35 | "arity": 2, 36 | "content": "\n Return the sum of the numbers *e1* and *e2*.\n ", 37 | "experimental": false, 38 | "countApplied": 0, 39 | "isPrimop": true, 40 | "name": "add", 41 | "position": null 42 | } 43 | }, 44 | "path": ["lib", "trivial", "add"] 45 | }, 46 | { 47 | "docs": { 48 | "attr": { 49 | "position": null 50 | }, 51 | "lambda": { 52 | "args": ["e1", "e2"], 53 | "arity": 2, 54 | "content": "\n Return the sum of the numbers *e1* and *e2*.\n ", 55 | "countApplied": 0, 56 | "experimental": false, 57 | "isPrimop": true, 58 | "name": "add", 59 | "position": null 60 | } 61 | }, 62 | "path": ["builtins", "add"] 63 | } 64 | ] 65 | -------------------------------------------------------------------------------- /pesto/test_data/aliases/escapeURL.expect: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "aliases": [ 4 | [ 5 | "lib", 6 | "escapeURL" 7 | ] 8 | ], 9 | "path": [ 10 | "lib", 11 | "strings", 12 | "escapeURL" 13 | ] 14 | }, 15 | { 16 | "aliases": [ 17 | [ 18 | "lib", 19 | "strings", 20 | "escapeURL" 21 | ] 22 | ], 23 | "path": [ 24 | "lib", 25 | "escapeURL" 26 | ] 27 | }, 28 | { 29 | "aliases": [ 30 | [ 31 | "lib", 32 | "escapeRegex" 33 | ] 34 | ], 35 | "path": [ 36 | "lib", 37 | "strings", 38 | "escapeRegex" 39 | ] 40 | }, 41 | { 42 | "aliases": [ 43 | [ 44 | "lib", 45 | "strings", 46 | "escapeRegex" 47 | ] 48 | ], 49 | "path": [ 50 | "lib", 51 | "escapeRegex" 52 | ] 53 | } 54 | ] -------------------------------------------------------------------------------- /pesto/test_data/aliases/fold.expect: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "aliases": [ 4 | [ 5 | "lib", 6 | "lists", 7 | "foldr" 8 | ] 9 | ], 10 | "path": [ 11 | "lib", 12 | "lists", 13 | "fold" 14 | ] 15 | }, 16 | { 17 | "aliases": [ 18 | [ 19 | "lib", 20 | "lists", 21 | "fold" 22 | ] 23 | ], 24 | "path": [ 25 | "lib", 26 | "lists", 27 | "foldr" 28 | ] 29 | } 30 | ] -------------------------------------------------------------------------------- /pesto/test_data/aliases/fold.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "docs": { 4 | "attr": { 5 | "position": { 6 | "column": 3, 7 | "file": "test_data/assets/lib/lists.nix", 8 | "line": 108 9 | } 10 | }, 11 | "lambda": { 12 | "isPrimop": false, 13 | "position": { 14 | "column": 11, 15 | "file": "test_data/assets/lib/lists.nix", 16 | "line": 95 17 | } 18 | } 19 | }, 20 | "path": ["lib", "lists", "fold"] 21 | }, 22 | { 23 | "docs": { 24 | "attr": { 25 | "position": { 26 | "column": 3, 27 | "file": "test_data/assets/lib/lists.nix", 28 | "line": 95 29 | } 30 | }, 31 | "lambda": { 32 | "isPrimop": false, 33 | "position": { 34 | "column": 11, 35 | "file": "test_data/assets/lib/lists.nix", 36 | "line": 95 37 | } 38 | } 39 | }, 40 | "path": ["lib", "lists", "foldr"] 41 | } 42 | ] 43 | -------------------------------------------------------------------------------- /pesto/test_data/aliases/foldl.expect: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "aliases": [ 4 | [ 5 | "lib", 6 | "lists", 7 | "foldl'" 8 | ] 9 | ], 10 | "path": [ 11 | "lib", 12 | "foldl'" 13 | ] 14 | }, 15 | { 16 | "aliases": [ 17 | [ 18 | "lib", 19 | "foldl'" 20 | ] 21 | ], 22 | "path": [ 23 | "lib", 24 | "lists", 25 | "foldl'" 26 | ] 27 | }, 28 | { 29 | "aliases": [], 30 | "path": [ 31 | "builtins", 32 | "foldl'" 33 | ] 34 | } 35 | ] -------------------------------------------------------------------------------- /pesto/test_data/aliases/foldl.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "docs": { 4 | "attr": { 5 | "position": { 6 | "column": 25, 7 | "file": "test_data/assets/default.nix", 8 | "line": 92 9 | } 10 | }, 11 | "lambda": { 12 | "isPrimop": false, 13 | "position": { 14 | "column": 5, 15 | "file": "test_data/assets/lists.nix", 16 | "line": 204 17 | } 18 | } 19 | }, 20 | "path": ["lib", "foldl'"] 21 | }, 22 | { 23 | "docs": { 24 | "attr": { 25 | "position": { 26 | "column": 3, 27 | "file": "test_data/assets/lists.nix", 28 | "line": 198 29 | } 30 | }, 31 | "lambda": { 32 | "isPrimop": false, 33 | "position": { 34 | "column": 5, 35 | "file": "test_data/assets/lists.nix", 36 | "line": 204 37 | } 38 | } 39 | }, 40 | "path": ["lib", "lists", "foldl'"] 41 | }, 42 | { 43 | "docs": { 44 | "attr": { "position": null }, 45 | "lambda": { 46 | "args": ["op", "nul", "list"], 47 | "arity": 3, 48 | "countApplied": 0, 49 | "content": "\n Reduce a list by applying a binary operator, from left to right,\n e.g. `foldl' op nul [x0 x1 x2 ...] : op (op (op nul x0) x1) x2)\n ...`. For example, `foldl' (x: y: x + y) 0 [1 2 3]` evaluates to 6.\n The return value of each application of `op` is evaluated immediately,\n even for intermediate values.\n ", 50 | "experimental": false, 51 | "isPrimop": true, 52 | "name": "foldl'", 53 | "position": null 54 | } 55 | }, 56 | "path": ["builtins", "foldl'"] 57 | } 58 | ] 59 | -------------------------------------------------------------------------------- /pesto/test_data/aliases/pipe.expect: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "aliases": [ 4 | [ 5 | "lib", 6 | "trivial", 7 | "pipe" 8 | ] 9 | ], 10 | "path": [ 11 | "lib", 12 | "pipe" 13 | ] 14 | }, 15 | { 16 | "aliases": [ 17 | [ 18 | "lib", 19 | "pipe" 20 | ] 21 | ], 22 | "path": [ 23 | "lib", 24 | "trivial", 25 | "pipe" 26 | ] 27 | }, 28 | { 29 | "aliases": [], 30 | "path": [ 31 | "lib", 32 | "lists", 33 | "unique" 34 | ] 35 | } 36 | ] -------------------------------------------------------------------------------- /pesto/test_data/aliases/pipe.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "docs": { 4 | "attr": { 5 | "position": { 6 | "column": 27, 7 | "file": "test_data/assets/default.nix", 8 | "line": 73 9 | } 10 | }, 11 | "lambda": { 12 | "content": "\n Reduce a list by applying a binary operator, from left to right,\n e.g. `foldl' op nul [x0 x1 x2 ...] = op (op (op nul x0) x1) x2)\n ...`. For example, `foldl' (x: y: x + y) 0 [1 2 3]` evaluates to 6.\n The return value of each application of `op` is evaluated immediately,\n even for intermediate values.\n ", 13 | "countApplied": 1, 14 | "isPrimop": true, 15 | "position": null 16 | } 17 | }, 18 | "path": ["lib", "pipe"] 19 | }, 20 | { 21 | "docs": { 22 | "attr": { 23 | "position": { 24 | "column": 3, 25 | "file": "test_data/assets/trivial.nix", 26 | "line": 94 27 | } 28 | }, 29 | "lambda": { 30 | "content": "\n Reduce a list by applying a binary operator, from left to right,\n e.g. `foldl' op nul [x0 x1 x2 ...] = op (op (op nul x0) x1) x2)\n ...`. For example, `foldl' (x: y: x + y) 0 [1 2 3]` evaluates to 6.\n The return value of each application of `op` is evaluated immediately,\n even for intermediate values.\n ", 31 | "countApplied": 1, 32 | "isPrimop": true, 33 | "position": null 34 | } 35 | }, 36 | "path": ["lib", "trivial", "pipe"] 37 | }, 38 | { 39 | "docs": { 40 | "attr": { 41 | "position": { 42 | "column": 3, 43 | "file": "test_data/assets/lists.nix", 44 | "line": 864 45 | } 46 | }, 47 | "lambda": { 48 | "content": "\n Reduce a list by applying a binary operator, from left to right,\n e.g. `foldl' op nul [x0 x1 x2 ...] = op (op (op nul x0) x1) x2)\n ...`. For example, `foldl' (x: y: x + y) 0 [1 2 3]` evaluates to 6.\n The return value of each application of `op` is evaluated immediately,\n even for intermediate values.\n ", 49 | "countApplied": 2, 50 | "isPrimop": true, 51 | "position": null 52 | } 53 | }, 54 | "path": ["lib", "lists", "unique"] 55 | } 56 | ] 57 | -------------------------------------------------------------------------------- /pesto/test_data/aliases/strings.expect: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "aliases": [ 4 | [ 5 | "lib", 6 | "concatLines" 7 | ] 8 | ], 9 | "path": [ 10 | "lib", 11 | "strings", 12 | "concatLines" 13 | ] 14 | }, 15 | { 16 | "aliases": [ 17 | [ 18 | "lib", 19 | "strings", 20 | "concatLines" 21 | ] 22 | ], 23 | "path": [ 24 | "lib", 25 | "concatLines" 26 | ] 27 | } 28 | ] -------------------------------------------------------------------------------- /pesto/test_data/aliases/strings.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "docs": { 4 | "attr": { 5 | "position": { 6 | "column": 3, 7 | "file": "test_data/assets/strings.nix", 8 | "line": 243 9 | } 10 | }, 11 | "lambda": { 12 | "isPrimop": false, 13 | "position": { 14 | "column": 25, 15 | "file": "test_data/assets/strings.nix", 16 | "line": 84 17 | } 18 | } 19 | }, 20 | "path": ["lib", "strings", "concatLines"] 21 | }, 22 | { 23 | "docs": { 24 | "attr": { 25 | "position": { 26 | "column": 27, 27 | "file": "test_data/assets/default.nix", 28 | "line": 98 29 | } 30 | }, 31 | "lambda": { 32 | "isPrimop": false, 33 | "position": { 34 | "column": 25, 35 | "file": "test_data/assets/strings.nix", 36 | "line": 84 37 | } 38 | } 39 | }, 40 | "path": ["lib", "concatLines"] 41 | } 42 | ] 43 | -------------------------------------------------------------------------------- /pesto/test_data/aliases/traceVal.expect: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "aliases": [ 4 | [ 5 | "lib", 6 | "debug", 7 | "traceVal" 8 | ] 9 | ], 10 | "path": [ 11 | "lib", 12 | "traceVal" 13 | ] 14 | }, 15 | { 16 | "aliases": [ 17 | [ 18 | "lib", 19 | "traceVal" 20 | ] 21 | ], 22 | "path": [ 23 | "lib", 24 | "debug", 25 | "traceVal" 26 | ] 27 | }, 28 | { 29 | "aliases": [], 30 | "path": [ 31 | "lib", 32 | "fileset", 33 | "traceVal" 34 | ] 35 | } 36 | ] -------------------------------------------------------------------------------- /pesto/test_data/aliases/traceVal.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "docs": { 4 | "attr": { 5 | "position": { 6 | "column": 25, 7 | "file": "test_data/assets/lib/default.nix", 8 | "line": 153 9 | } 10 | }, 11 | "lambda": { 12 | "isPrimop": false, 13 | "position": { 14 | "column": 5, 15 | "file": "test_data/assets/lib/debug.nix", 16 | "line": 95 17 | } 18 | } 19 | }, 20 | "path": ["lib", "traceVal"] 21 | }, 22 | { 23 | "docs": { 24 | "attr": { 25 | "position": { 26 | "column": 3, 27 | "file": "test_data/assets/lib/debug.nix", 28 | "line": 114 29 | } 30 | }, 31 | "lambda": { 32 | "isPrimop": false, 33 | "position": { 34 | "column": 5, 35 | "file": "test_data/assets/lib/debug.nix", 36 | "line": 95 37 | } 38 | } 39 | }, 40 | "path": ["lib", "debug", "traceVal"] 41 | }, 42 | { 43 | "docs": { 44 | "attr": { 45 | "position": { 46 | "column": 3, 47 | "file": "test_data/assets/lib/fileset/default.nix", 48 | "line": 666 49 | } 50 | }, 51 | "lambda": { 52 | "isPrimop": false, 53 | "position": { 54 | "column": 5, 55 | "file": "test_data/assets/lib/fileset/default.nix", 56 | "line": 672 57 | } 58 | } 59 | }, 60 | "path": ["lib", "fileset", "traceVal"] 61 | } 62 | ] 63 | -------------------------------------------------------------------------------- /pesto/test_data/assets/ascii-table.nix: -------------------------------------------------------------------------------- 1 | { "\t" = 9; 2 | "\n" = 10; 3 | "\r" = 13; 4 | " " = 32; 5 | "!" = 33; 6 | "\"" = 34; 7 | "#" = 35; 8 | "$" = 36; 9 | "%" = 37; 10 | "&" = 38; 11 | "'" = 39; 12 | "(" = 40; 13 | ")" = 41; 14 | "*" = 42; 15 | "+" = 43; 16 | "," = 44; 17 | "-" = 45; 18 | "." = 46; 19 | "/" = 47; 20 | "0" = 48; 21 | "1" = 49; 22 | "2" = 50; 23 | "3" = 51; 24 | "4" = 52; 25 | "5" = 53; 26 | "6" = 54; 27 | "7" = 55; 28 | "8" = 56; 29 | "9" = 57; 30 | ":" = 58; 31 | ";" = 59; 32 | "<" = 60; 33 | "=" = 61; 34 | ">" = 62; 35 | "?" = 63; 36 | "@" = 64; 37 | "A" = 65; 38 | "B" = 66; 39 | "C" = 67; 40 | "D" = 68; 41 | "E" = 69; 42 | "F" = 70; 43 | "G" = 71; 44 | "H" = 72; 45 | "I" = 73; 46 | "J" = 74; 47 | "K" = 75; 48 | "L" = 76; 49 | "M" = 77; 50 | "N" = 78; 51 | "O" = 79; 52 | "P" = 80; 53 | "Q" = 81; 54 | "R" = 82; 55 | "S" = 83; 56 | "T" = 84; 57 | "U" = 85; 58 | "V" = 86; 59 | "W" = 87; 60 | "X" = 88; 61 | "Y" = 89; 62 | "Z" = 90; 63 | "[" = 91; 64 | "\\" = 92; 65 | "]" = 93; 66 | "^" = 94; 67 | "_" = 95; 68 | "`" = 96; 69 | "a" = 97; 70 | "b" = 98; 71 | "c" = 99; 72 | "d" = 100; 73 | "e" = 101; 74 | "f" = 102; 75 | "g" = 103; 76 | "h" = 104; 77 | "i" = 105; 78 | "j" = 106; 79 | "k" = 107; 80 | "l" = 108; 81 | "m" = 109; 82 | "n" = 110; 83 | "o" = 111; 84 | "p" = 112; 85 | "q" = 113; 86 | "r" = 114; 87 | "s" = 115; 88 | "t" = 116; 89 | "u" = 117; 90 | "v" = 118; 91 | "w" = 119; 92 | "x" = 120; 93 | "y" = 121; 94 | "z" = 122; 95 | "{" = 123; 96 | "|" = 124; 97 | "}" = 125; 98 | "~" = 126; 99 | } 100 | -------------------------------------------------------------------------------- /pesto/test_data/assets/asserts.nix: -------------------------------------------------------------------------------- 1 | { lib }: 2 | 3 | rec { 4 | 5 | /** 6 | Throw if pred is false, else return pred. 7 | Intended to be used to augment asserts with helpful error messages. 8 | 9 | # Example 10 | 11 | ```nix 12 | assertMsg false "nope" 13 | stderr> error: nope 14 | assert assertMsg ("foo" == "bar") "foo is not bar, silly"; "" 15 | stderr> error: foo is not bar, silly 16 | ``` 17 | 18 | # Type 19 | 20 | ``` 21 | assertMsg :: Bool -> String -> Bool 22 | ``` 23 | 24 | # Arguments 25 | 26 | - [pred] Predicate that needs to succeed, otherwise `msg` is thrown 27 | - [msg] Message to throw in case `pred` fails 28 | 29 | */ 30 | # TODO(Profpatsch): add tests that check stderr 31 | assertMsg = 32 | # Predicate that needs to succeed, otherwise `msg` is thrown 33 | pred: 34 | # Message to throw in case `pred` fails 35 | msg: 36 | pred || builtins.throw msg; 37 | 38 | /** 39 | Specialized `assertMsg` for checking if `val` is one of the elements 40 | of the list `xs`. Useful for checking enums. 41 | 42 | # Example 43 | 44 | ```nix 45 | let sslLibrary = "libressl"; 46 | in assertOneOf "sslLibrary" sslLibrary [ "openssl" "bearssl" ] 47 | stderr> error: sslLibrary must be one of [ 48 | stderr> "openssl" 49 | stderr> "bearssl" 50 | stderr> ], but is: "libressl" 51 | ``` 52 | 53 | # Type 54 | 55 | ``` 56 | assertOneOf :: String -> ComparableVal -> List ComparableVal -> Bool 57 | ``` 58 | 59 | # Arguments 60 | 61 | - [name] The name of the variable the user entered `val` into, for inclusion in the error message 62 | - [val] The value of what the user provided, to be compared against the values in `xs` 63 | - [xs] The list of valid values 64 | 65 | */ 66 | assertOneOf = 67 | # The name of the variable the user entered `val` into, for inclusion in the error message 68 | name: 69 | # The value of what the user provided, to be compared against the values in `xs` 70 | val: 71 | # The list of valid values 72 | xs: 73 | assertMsg 74 | (lib.elem val xs) 75 | "${name} must be one of ${ 76 | lib.generators.toPretty {} xs}, but is: ${ 77 | lib.generators.toPretty {} val}"; 78 | 79 | } 80 | -------------------------------------------------------------------------------- /pesto/test_data/assets/fetchers.nix: -------------------------------------------------------------------------------- 1 | # snippets that can be shared by multiple fetchers (pkgs/build-support) 2 | { lib }: 3 | { 4 | 5 | proxyImpureEnvVars = [ 6 | # We borrow these environment variables from the caller to allow 7 | # easy proxy configuration. This is impure, but a fixed-output 8 | # derivation like fetchurl is allowed to do so since its result is 9 | # by definition pure. 10 | "http_proxy" "https_proxy" "ftp_proxy" "all_proxy" "no_proxy" 11 | ]; 12 | 13 | } 14 | -------------------------------------------------------------------------------- /pesto/test_data/assets/fileset/mock-splitRoot.nix: -------------------------------------------------------------------------------- 1 | # This overlay implements mocking of the lib.path.splitRoot function 2 | # It pretends that the last component named "mock-root" is the root: 3 | # 4 | # splitRoot /foo/mock-root/bar/mock-root/baz 5 | # => { 6 | # root = /foo/mock-root/bar/mock-root; 7 | # subpath = "./baz"; 8 | # } 9 | self: super: { 10 | path = super.path // { 11 | splitRoot = path: 12 | let 13 | parts = super.path.splitRoot path; 14 | components = self.path.subpath.components parts.subpath; 15 | count = self.length components; 16 | rootIndex = count - self.lists.findFirstIndex 17 | (component: component == "mock-root") 18 | (self.length components) 19 | (self.reverseList components); 20 | root = self.path.append parts.root (self.path.subpath.join (self.take rootIndex components)); 21 | subpath = self.path.subpath.join (self.drop rootIndex components); 22 | in { 23 | inherit root subpath; 24 | }; 25 | }; 26 | } 27 | -------------------------------------------------------------------------------- /pesto/test_data/assets/flake.nix: -------------------------------------------------------------------------------- 1 | { 2 | description = "Library of low-level helper functions for nix expressions."; 3 | 4 | outputs = { self }: { lib = import ./.; }; 5 | } 6 | -------------------------------------------------------------------------------- /pesto/test_data/assets/kernel.nix: -------------------------------------------------------------------------------- 1 | { lib }: 2 | 3 | with lib; 4 | { 5 | 6 | 7 | # Keeping these around in case we decide to change this horrible implementation :) 8 | option = x: 9 | x // { optional = true; }; 10 | 11 | yes = { tristate = "y"; optional = false; }; 12 | no = { tristate = "n"; optional = false; }; 13 | module = { tristate = "m"; optional = false; }; 14 | unset = { tristate = null; optional = false; }; 15 | freeform = x: { freeform = x; optional = false; }; 16 | 17 | /** 18 | Common patterns/legacy used in common-config/hardened/config.nix 19 | 20 | # Arguments 21 | 22 | - [version] 23 | 24 | */ 25 | whenHelpers = version: { 26 | whenAtLeast = ver: mkIf (versionAtLeast version ver); 27 | whenOlder = ver: mkIf (versionOlder version ver); 28 | # range is (inclusive, exclusive) 29 | whenBetween = verLow: verHigh: mkIf (versionAtLeast version verLow && versionOlder version verHigh); 30 | }; 31 | 32 | } 33 | -------------------------------------------------------------------------------- /pesto/test_data/assets/minver.nix: -------------------------------------------------------------------------------- 1 | # Expose the minimum required version for evaluating Nixpkgs 2 | "2.3" 3 | -------------------------------------------------------------------------------- /pesto/test_data/assets/path/tests/default.nix: -------------------------------------------------------------------------------- 1 | { 2 | nixpkgs ? ../../.., 3 | system ? builtins.currentSystem, 4 | pkgs ? import nixpkgs { 5 | config = {}; 6 | overlays = []; 7 | inherit system; 8 | }, 9 | libpath ? ../.., 10 | # Random seed 11 | seed ? null, 12 | }: 13 | pkgs.runCommand "lib-path-tests" { 14 | nativeBuildInputs = with pkgs; [ 15 | nix 16 | jq 17 | bc 18 | ]; 19 | } '' 20 | # Needed to make Nix evaluation work 21 | export TEST_ROOT=$(pwd)/test-tmp 22 | export NIX_BUILD_HOOK= 23 | export NIX_CONF_DIR=$TEST_ROOT/etc 24 | export NIX_LOCALSTATE_DIR=$TEST_ROOT/var 25 | export NIX_LOG_DIR=$TEST_ROOT/var/log/nix 26 | export NIX_STATE_DIR=$TEST_ROOT/var/nix 27 | export NIX_STORE_DIR=$TEST_ROOT/store 28 | export PAGER=cat 29 | 30 | cp -r ${libpath} lib 31 | export TEST_LIB=$PWD/lib 32 | 33 | echo "Running unit tests lib/path/tests/unit.nix" 34 | nix-instantiate --eval --show-trace \ 35 | --argstr libpath "$TEST_LIB" \ 36 | lib/path/tests/unit.nix 37 | 38 | echo "Running property tests lib/path/tests/prop.sh" 39 | bash lib/path/tests/prop.sh ${toString seed} 40 | 41 | touch $out 42 | '' 43 | -------------------------------------------------------------------------------- /pesto/test_data/assets/source-types.nix: -------------------------------------------------------------------------------- 1 | { lib }: 2 | 3 | let 4 | defaultSourceType = tname: { 5 | shortName = tname; 6 | isSource = false; 7 | }; 8 | in lib.mapAttrs (tname: tset: defaultSourceType tname // tset) { 9 | 10 | fromSource = { 11 | isSource = true; 12 | }; 13 | 14 | binaryNativeCode = {}; 15 | 16 | binaryBytecode = {}; 17 | 18 | binaryFirmware = {}; 19 | } 20 | -------------------------------------------------------------------------------- /pesto/test_data/assets/systems/flake-systems.nix: -------------------------------------------------------------------------------- 1 | # See [RFC 46] for mandated platform support and ../../pkgs/stdenv for 2 | # implemented platform support. This list is mainly descriptive, i.e. all 3 | # system doubles for platforms where nixpkgs can do native compilation 4 | # reasonably well are included. 5 | # 6 | # [RFC 46]: https://github.com/NixOS/rfcs/blob/master/rfcs/0046-platform-support-tiers.md 7 | { }: 8 | 9 | [ 10 | # Tier 1 11 | "x86_64-linux" 12 | # Tier 2 13 | "aarch64-linux" 14 | "x86_64-darwin" 15 | # Tier 3 16 | "armv6l-linux" 17 | "armv7l-linux" 18 | "i686-linux" 19 | "mipsel-linux" 20 | 21 | # Other platforms with sufficient support in stdenv which is not formally 22 | # mandated by their platform tier. 23 | "aarch64-darwin" 24 | "armv5tel-linux" 25 | "powerpc64le-linux" 26 | "riscv64-linux" 27 | 28 | # "x86_64-freebsd" is excluded because it is mostly broken 29 | ] 30 | -------------------------------------------------------------------------------- /pesto/test_data/assets/tests/check-eval.nix: -------------------------------------------------------------------------------- 1 | # Throws an error if any of our lib tests fail. 2 | 3 | let tests = [ "misc" "systems" ]; 4 | all = builtins.concatLists (map (f: import (./. + "/${f}.nix")) tests); 5 | in if all == [] 6 | then null 7 | else throw (builtins.toJSON all) 8 | -------------------------------------------------------------------------------- /pesto/test_data/assets/tests/maintainer-module.nix: -------------------------------------------------------------------------------- 1 | { lib, ... }: 2 | let 3 | inherit (lib) types; 4 | in { 5 | options = { 6 | name = lib.mkOption { 7 | type = types.str; 8 | }; 9 | email = lib.mkOption { 10 | type = types.nullOr types.str; 11 | default = null; 12 | }; 13 | matrix = lib.mkOption { 14 | type = types.nullOr types.str; 15 | default = null; 16 | }; 17 | github = lib.mkOption { 18 | type = types.nullOr types.str; 19 | default = null; 20 | }; 21 | githubId = lib.mkOption { 22 | type = types.nullOr types.ints.unsigned; 23 | default = null; 24 | }; 25 | keys = lib.mkOption { 26 | type = types.listOf (types.submodule { 27 | options.fingerprint = lib.mkOption { type = types.str; }; 28 | }); 29 | default = []; 30 | }; 31 | }; 32 | } 33 | -------------------------------------------------------------------------------- /pesto/test_data/assets/tests/modules/adhoc-freeformType-survives-type-merge.nix: -------------------------------------------------------------------------------- 1 | { lib, ... }: { 2 | options.dummy = lib.mkOption { type = lib.types.anything; default = {}; }; 3 | freeformType = 4 | let 5 | a = lib.types.attrsOf (lib.types.submodule { options.bar = lib.mkOption { }; }); 6 | in 7 | # modifying types like this breaks type merging. 8 | # This test makes sure that type merging is not performed when only a single declaration exists. 9 | # Don't modify types in practice! 10 | a // { 11 | merge = loc: defs: { freeformItems = a.merge loc defs; }; 12 | }; 13 | config.foo.bar = "ok"; 14 | } 15 | -------------------------------------------------------------------------------- /pesto/test_data/assets/tests/modules/alias-with-priority-can-override.nix: -------------------------------------------------------------------------------- 1 | # This is a test to show that mkAliasOptionModule sets the priority correctly 2 | # for aliased options. 3 | # 4 | # This test shows that an alias with a high priority is able to override 5 | # a non-aliased option. 6 | 7 | { config, lib, ... }: 8 | 9 | with lib; 10 | 11 | { 12 | options = { 13 | # A simple boolean option that can be enabled or disabled. 14 | enable = lib.mkOption { 15 | type = types.nullOr types.bool; 16 | default = null; 17 | example = true; 18 | description = '' 19 | Some descriptive text 20 | ''; 21 | }; 22 | 23 | # mkAliasOptionModule sets warnings, so this has to be defined. 24 | warnings = mkOption { 25 | internal = true; 26 | default = []; 27 | type = types.listOf types.str; 28 | example = [ "The `foo' service is deprecated and will go away soon!" ]; 29 | description = '' 30 | This option allows modules to show warnings to users during 31 | the evaluation of the system configuration. 32 | ''; 33 | }; 34 | }; 35 | 36 | imports = [ 37 | # Create an alias for the "enable" option. 38 | (mkAliasOptionModule [ "enableAlias" ] [ "enable" ]) 39 | 40 | # Disable the aliased option with a high priority so it 41 | # should override the next import. 42 | ( { config, lib, ... }: 43 | { 44 | enableAlias = lib.mkForce false; 45 | } 46 | ) 47 | 48 | # Enable the normal (non-aliased) option. 49 | ( { config, lib, ... }: 50 | { 51 | enable = true; 52 | } 53 | ) 54 | ]; 55 | } 56 | -------------------------------------------------------------------------------- /pesto/test_data/assets/tests/modules/alias-with-priority.nix: -------------------------------------------------------------------------------- 1 | # This is a test to show that mkAliasOptionModule sets the priority correctly 2 | # for aliased options. 3 | # 4 | # This test shows that an alias with a low priority is able to be overridden 5 | # with a non-aliased option. 6 | 7 | { config, lib, ... }: 8 | 9 | with lib; 10 | 11 | { 12 | options = { 13 | # A simple boolean option that can be enabled or disabled. 14 | enable = lib.mkOption { 15 | type = types.nullOr types.bool; 16 | default = null; 17 | example = true; 18 | description = '' 19 | Some descriptive text 20 | ''; 21 | }; 22 | 23 | # mkAliasOptionModule sets warnings, so this has to be defined. 24 | warnings = mkOption { 25 | internal = true; 26 | default = []; 27 | type = types.listOf types.str; 28 | example = [ "The `foo' service is deprecated and will go away soon!" ]; 29 | description = '' 30 | This option allows modules to show warnings to users during 31 | the evaluation of the system configuration. 32 | ''; 33 | }; 34 | }; 35 | 36 | imports = [ 37 | # Create an alias for the "enable" option. 38 | (mkAliasOptionModule [ "enableAlias" ] [ "enable" ]) 39 | 40 | # Disable the aliased option, but with a default (low) priority so it 41 | # should be able to be overridden by the next import. 42 | ( { config, lib, ... }: 43 | { 44 | enableAlias = lib.mkDefault false; 45 | } 46 | ) 47 | 48 | # Enable the normal (non-aliased) option. 49 | ( { config, lib, ... }: 50 | { 51 | enable = true; 52 | } 53 | ) 54 | ]; 55 | } 56 | -------------------------------------------------------------------------------- /pesto/test_data/assets/tests/modules/attrsOf-conditional-check.nix: -------------------------------------------------------------------------------- 1 | { lib, config, ... }: { 2 | options.conditionalWorks = lib.mkOption { 3 | default = ! config.value ? foo; 4 | }; 5 | 6 | config.value.foo = lib.mkIf false "should not be defined"; 7 | } 8 | -------------------------------------------------------------------------------- /pesto/test_data/assets/tests/modules/attrsOf-lazy-check.nix: -------------------------------------------------------------------------------- 1 | { lib, config, ... }: { 2 | options.isLazy = lib.mkOption { 3 | default = ! config.value ? foo; 4 | }; 5 | 6 | config.value.bar = throw "is not lazy"; 7 | } 8 | -------------------------------------------------------------------------------- /pesto/test_data/assets/tests/modules/class-check.nix: -------------------------------------------------------------------------------- 1 | { lib, ... }: { 2 | options = { 3 | sub = { 4 | nixosOk = lib.mkOption { 5 | type = lib.types.submoduleWith { 6 | class = "nixos"; 7 | modules = [ ]; 8 | }; 9 | }; 10 | # Same but will have bad definition 11 | nixosFail = lib.mkOption { 12 | type = lib.types.submoduleWith { 13 | class = "nixos"; 14 | modules = [ ]; 15 | }; 16 | }; 17 | 18 | mergeFail = lib.mkOption { 19 | type = lib.types.submoduleWith { 20 | class = "nixos"; 21 | modules = [ ]; 22 | }; 23 | default = { }; 24 | }; 25 | }; 26 | }; 27 | imports = [ 28 | { 29 | options = { 30 | sub = { 31 | mergeFail = lib.mkOption { 32 | type = lib.types.submoduleWith { 33 | class = "darwin"; 34 | modules = [ ]; 35 | }; 36 | }; 37 | }; 38 | }; 39 | } 40 | ]; 41 | config = { 42 | _module.freeformType = lib.types.anything; 43 | ok = 44 | lib.evalModules { 45 | class = "nixos"; 46 | modules = [ 47 | ./module-class-is-nixos.nix 48 | ]; 49 | }; 50 | 51 | fail = 52 | lib.evalModules { 53 | class = "nixos"; 54 | modules = [ 55 | ./module-class-is-nixos.nix 56 | ./module-class-is-darwin.nix 57 | ]; 58 | }; 59 | 60 | fail-anon = 61 | lib.evalModules { 62 | class = "nixos"; 63 | modules = [ 64 | ./module-class-is-nixos.nix 65 | { _file = "foo.nix#darwinModules.default"; 66 | _class = "darwin"; 67 | config = {}; 68 | imports = []; 69 | } 70 | ]; 71 | }; 72 | 73 | sub.nixosOk = { _class = "nixos"; }; 74 | sub.nixosFail = { imports = [ ./module-class-is-darwin.nix ]; }; 75 | }; 76 | } 77 | -------------------------------------------------------------------------------- /pesto/test_data/assets/tests/modules/declaration-positions.nix: -------------------------------------------------------------------------------- 1 | { lib, options, ... }: 2 | let discardPositions = lib.mapAttrs (k: v: v); 3 | in 4 | # unsafeGetAttrPos is unspecified best-effort behavior, so we only want to consider this test on an evaluator that satisfies some basic assumptions about this function. 5 | assert builtins.unsafeGetAttrPos "a" { a = true; } != null; 6 | assert builtins.unsafeGetAttrPos "a" (discardPositions { a = true; }) == null; 7 | { 8 | imports = [ 9 | { 10 | options.imported.line10 = lib.mkOption { 11 | type = lib.types.int; 12 | }; 13 | 14 | # Simulates various patterns of generating modules such as 15 | # programs.firefox.nativeMessagingHosts.ff2mpv. We don't expect to get 16 | # line numbers for these, but we can fall back on knowing the file. 17 | options.generated = discardPositions { 18 | line18 = lib.mkOption { 19 | type = lib.types.int; 20 | }; 21 | }; 22 | 23 | options.submoduleLine34.extraOptLine23 = lib.mkOption { 24 | default = 1; 25 | type = lib.types.int; 26 | }; 27 | } 28 | ]; 29 | 30 | options.nested.nestedLine30 = lib.mkOption { 31 | type = lib.types.int; 32 | }; 33 | 34 | options.submoduleLine34 = lib.mkOption { 35 | default = { }; 36 | type = lib.types.submoduleWith { 37 | modules = [ 38 | ({ options, ... }: { 39 | options.submodDeclLine39 = lib.mkOption { }; 40 | }) 41 | { freeformType = with lib.types; lazyAttrsOf (uniq unspecified); } 42 | ]; 43 | }; 44 | }; 45 | 46 | config = { 47 | submoduleLine34.submodDeclLine39 = (options.submoduleLine34.type.getSubOptions [ ]).submodDeclLine39.declarationPositions; 48 | }; 49 | } 50 | -------------------------------------------------------------------------------- /pesto/test_data/assets/tests/modules/declare-attrsOf.nix: -------------------------------------------------------------------------------- 1 | { lib, ... }: 2 | let 3 | deathtrapArgs = lib.mapAttrs 4 | (k: _: throw "The module system is too strict, accessing an unused option's ${k} mkOption-attribute.") 5 | (lib.functionArgs lib.mkOption); 6 | in 7 | { 8 | options.value = lib.mkOption { 9 | type = lib.types.attrsOf lib.types.str; 10 | default = {}; 11 | }; 12 | options.testing-laziness-so-don't-read-me = lib.mkOption deathtrapArgs; 13 | } 14 | -------------------------------------------------------------------------------- /pesto/test_data/assets/tests/modules/declare-attrsOfSub-any-enable.nix: -------------------------------------------------------------------------------- 1 | { lib, ... }: 2 | 3 | let 4 | submod = { ... }: { 5 | options = { 6 | enable = lib.mkOption { 7 | default = false; 8 | example = true; 9 | type = lib.types.bool; 10 | description = '' 11 | Some descriptive text 12 | ''; 13 | }; 14 | }; 15 | }; 16 | in 17 | 18 | { 19 | options = { 20 | attrsOfSub = lib.mkOption { 21 | default = {}; 22 | example = {}; 23 | type = lib.types.attrsOf (lib.types.submodule [ submod ]); 24 | description = '' 25 | Some descriptive text 26 | ''; 27 | }; 28 | }; 29 | } 30 | -------------------------------------------------------------------------------- /pesto/test_data/assets/tests/modules/declare-bare-submodule-deep-option-duplicate.nix: -------------------------------------------------------------------------------- 1 | { lib, ... }: 2 | let 3 | inherit (lib) mkOption types; 4 | in 5 | { 6 | options.bare-submodule.deep = mkOption { 7 | type = types.int; 8 | default = 2; 9 | }; 10 | } 11 | -------------------------------------------------------------------------------- /pesto/test_data/assets/tests/modules/declare-bare-submodule-deep-option.nix: -------------------------------------------------------------------------------- 1 | { lib, ... }: 2 | let 3 | inherit (lib) mkOption types; 4 | in 5 | { 6 | options.bare-submodule.deep = mkOption { 7 | type = types.int; 8 | default = 2; 9 | }; 10 | } 11 | -------------------------------------------------------------------------------- /pesto/test_data/assets/tests/modules/declare-bare-submodule-nested-option.nix: -------------------------------------------------------------------------------- 1 | { config, lib, ... }: 2 | let 3 | inherit (lib) mkOption types; 4 | in 5 | { 6 | options.bare-submodule = mkOption { 7 | type = types.submoduleWith { 8 | shorthandOnlyDefinesConfig = config.shorthandOnlyDefinesConfig; 9 | modules = [ 10 | { 11 | options.nested = mkOption { 12 | type = types.int; 13 | default = 1; 14 | }; 15 | } 16 | ]; 17 | }; 18 | }; 19 | } 20 | -------------------------------------------------------------------------------- /pesto/test_data/assets/tests/modules/declare-bare-submodule.nix: -------------------------------------------------------------------------------- 1 | { config, lib, ... }: 2 | let 3 | inherit (lib) mkOption types; 4 | in 5 | { 6 | options.bare-submodule = mkOption { 7 | type = types.submoduleWith { 8 | modules = [ ]; 9 | shorthandOnlyDefinesConfig = config.shorthandOnlyDefinesConfig; 10 | }; 11 | default = {}; 12 | }; 13 | 14 | # config-dependent options: won't recommend, but useful for making this test parameterized 15 | options.shorthandOnlyDefinesConfig = mkOption { 16 | default = false; 17 | }; 18 | } 19 | -------------------------------------------------------------------------------- /pesto/test_data/assets/tests/modules/declare-coerced-value-unsound.nix: -------------------------------------------------------------------------------- 1 | { lib, ... }: 2 | 3 | { 4 | options = { 5 | value = lib.mkOption { 6 | default = "12"; 7 | type = lib.types.coercedTo lib.types.str lib.toInt lib.types.ints.s8; 8 | }; 9 | }; 10 | } 11 | -------------------------------------------------------------------------------- /pesto/test_data/assets/tests/modules/declare-coerced-value.nix: -------------------------------------------------------------------------------- 1 | { lib, ... }: 2 | 3 | { 4 | options = { 5 | value = lib.mkOption { 6 | default = 42; 7 | type = lib.types.coercedTo lib.types.int builtins.toString lib.types.str; 8 | }; 9 | }; 10 | } 11 | -------------------------------------------------------------------------------- /pesto/test_data/assets/tests/modules/declare-either.nix: -------------------------------------------------------------------------------- 1 | { lib, ... }: { 2 | options.value = lib.mkOption { 3 | type = lib.types.either lib.types.int lib.types.str; 4 | }; 5 | } 6 | -------------------------------------------------------------------------------- /pesto/test_data/assets/tests/modules/declare-enable-nested.nix: -------------------------------------------------------------------------------- 1 | { lib, ... }: 2 | 3 | { 4 | options.set = { 5 | enable = lib.mkOption { 6 | default = false; 7 | example = true; 8 | type = lib.types.bool; 9 | description = '' 10 | Some descriptive text 11 | ''; 12 | }; 13 | }; 14 | } 15 | -------------------------------------------------------------------------------- /pesto/test_data/assets/tests/modules/declare-enable.nix: -------------------------------------------------------------------------------- 1 | { lib, ... }: 2 | 3 | { 4 | options = { 5 | enable = lib.mkOption { 6 | default = false; 7 | example = true; 8 | type = lib.types.bool; 9 | description = '' 10 | Some descriptive text 11 | ''; 12 | }; 13 | }; 14 | } 15 | -------------------------------------------------------------------------------- /pesto/test_data/assets/tests/modules/declare-int-between-value.nix: -------------------------------------------------------------------------------- 1 | { lib, ... }: 2 | 3 | { 4 | options = { 5 | value = lib.mkOption { 6 | type = lib.types.ints.between (-21) 43; 7 | }; 8 | }; 9 | } 10 | -------------------------------------------------------------------------------- /pesto/test_data/assets/tests/modules/declare-int-positive-value-nested.nix: -------------------------------------------------------------------------------- 1 | { lib, ... }: 2 | 3 | { 4 | options.set = { 5 | value = lib.mkOption { 6 | type = lib.types.ints.positive; 7 | }; 8 | }; 9 | } 10 | -------------------------------------------------------------------------------- /pesto/test_data/assets/tests/modules/declare-int-positive-value.nix: -------------------------------------------------------------------------------- 1 | { lib, ... }: 2 | 3 | { 4 | options = { 5 | value = lib.mkOption { 6 | type = lib.types.ints.positive; 7 | }; 8 | }; 9 | } 10 | -------------------------------------------------------------------------------- /pesto/test_data/assets/tests/modules/declare-int-unsigned-value.nix: -------------------------------------------------------------------------------- 1 | { lib, ... }: 2 | 3 | { 4 | options = { 5 | value = lib.mkOption { 6 | type = lib.types.ints.unsigned; 7 | }; 8 | }; 9 | } 10 | -------------------------------------------------------------------------------- /pesto/test_data/assets/tests/modules/declare-lazyAttrsOf.nix: -------------------------------------------------------------------------------- 1 | { lib, ... }: { 2 | options.value = lib.mkOption { 3 | type = lib.types.lazyAttrsOf (lib.types.str // { emptyValue.value = "empty"; }); 4 | default = {}; 5 | }; 6 | } 7 | -------------------------------------------------------------------------------- /pesto/test_data/assets/tests/modules/declare-mkPackageOption.nix: -------------------------------------------------------------------------------- 1 | { lib, ... }: let 2 | pkgs.hello = { 3 | type = "derivation"; 4 | pname = "hello"; 5 | }; 6 | in { 7 | options = { 8 | package = lib.mkPackageOption pkgs "hello" { }; 9 | 10 | namedPackage = lib.mkPackageOption pkgs "Hello" { 11 | default = [ "hello" ]; 12 | }; 13 | 14 | namedPackageSingletonDefault = lib.mkPackageOption pkgs "Hello" { 15 | default = "hello"; 16 | }; 17 | 18 | pathPackage = lib.mkPackageOption pkgs [ "hello" ] { }; 19 | 20 | packageWithExample = lib.mkPackageOption pkgs "hello" { 21 | example = "pkgs.hello.override { stdenv = pkgs.clangStdenv; }"; 22 | }; 23 | 24 | packageWithPathExample = lib.mkPackageOption pkgs "hello" { 25 | example = [ "hello" ]; 26 | }; 27 | 28 | packageWithExtraDescription = lib.mkPackageOption pkgs "hello" { 29 | extraDescription = "Example extra description."; 30 | }; 31 | 32 | undefinedPackage = lib.mkPackageOption pkgs "hello" { 33 | default = null; 34 | }; 35 | 36 | nullablePackage = lib.mkPackageOption pkgs "hello" { 37 | nullable = true; 38 | default = null; 39 | }; 40 | 41 | nullablePackageWithDefault = lib.mkPackageOption pkgs "hello" { 42 | nullable = true; 43 | }; 44 | 45 | packageWithPkgsText = lib.mkPackageOption pkgs "hello" { 46 | pkgsText = "myPkgs"; 47 | }; 48 | 49 | packageFromOtherSet = let myPkgs = { 50 | hello = pkgs.hello // { pname = "hello-other"; }; 51 | }; in lib.mkPackageOption myPkgs "hello" { }; 52 | }; 53 | } 54 | -------------------------------------------------------------------------------- /pesto/test_data/assets/tests/modules/declare-oneOf.nix: -------------------------------------------------------------------------------- 1 | { lib, ... }: { 2 | options.value = lib.mkOption { 3 | type = lib.types.oneOf [ 4 | lib.types.int 5 | (lib.types.listOf lib.types.int) 6 | lib.types.str 7 | ]; 8 | }; 9 | } 10 | -------------------------------------------------------------------------------- /pesto/test_data/assets/tests/modules/declare-set.nix: -------------------------------------------------------------------------------- 1 | { lib, ... }: 2 | 3 | { 4 | options.set = lib.mkOption { 5 | default = { }; 6 | example = { a = 1; }; 7 | type = lib.types.attrsOf lib.types.int; 8 | description = '' 9 | Some descriptive text 10 | ''; 11 | }; 12 | } 13 | -------------------------------------------------------------------------------- /pesto/test_data/assets/tests/modules/declare-submodule-via-evalModules.nix: -------------------------------------------------------------------------------- 1 | { lib, ... }: { 2 | options.submodule = lib.mkOption { 3 | inherit (lib.evalModules { 4 | modules = [ 5 | { 6 | options.inner = lib.mkOption { 7 | type = lib.types.bool; 8 | default = false; 9 | }; 10 | } 11 | ]; 12 | }) type; 13 | default = {}; 14 | }; 15 | 16 | config.submodule = lib.mkMerge [ 17 | ({ lib, ... }: { 18 | options.outer = lib.mkOption { 19 | type = lib.types.bool; 20 | default = false; 21 | }; 22 | }) 23 | { 24 | inner = true; 25 | outer = true; 26 | } 27 | ]; 28 | } 29 | -------------------------------------------------------------------------------- /pesto/test_data/assets/tests/modules/declare-submoduleWith-modules.nix: -------------------------------------------------------------------------------- 1 | { lib, ... }: { 2 | options.submodule = lib.mkOption { 3 | type = lib.types.submoduleWith { 4 | modules = [ 5 | { 6 | options.inner = lib.mkOption { 7 | type = lib.types.bool; 8 | default = false; 9 | }; 10 | } 11 | ]; 12 | }; 13 | default = {}; 14 | }; 15 | 16 | config.submodule = lib.mkMerge [ 17 | ({ lib, ... }: { 18 | options.outer = lib.mkOption { 19 | type = lib.types.bool; 20 | default = false; 21 | }; 22 | }) 23 | { 24 | inner = true; 25 | outer = true; 26 | } 27 | ]; 28 | } 29 | -------------------------------------------------------------------------------- /pesto/test_data/assets/tests/modules/declare-submoduleWith-noshorthand.nix: -------------------------------------------------------------------------------- 1 | { lib, ... }: let 2 | sub.options.config = lib.mkOption { 3 | type = lib.types.bool; 4 | default = false; 5 | }; 6 | in { 7 | options.submodule = lib.mkOption { 8 | type = lib.types.submoduleWith { 9 | modules = [ sub ]; 10 | }; 11 | default = {}; 12 | }; 13 | } 14 | -------------------------------------------------------------------------------- /pesto/test_data/assets/tests/modules/declare-submoduleWith-path.nix: -------------------------------------------------------------------------------- 1 | { lib, ... }: { 2 | options.submodule = lib.mkOption { 3 | type = lib.types.submoduleWith { 4 | modules = [ 5 | ./declare-enable.nix 6 | ]; 7 | }; 8 | default = {}; 9 | }; 10 | 11 | config.submodule = ./define-enable.nix; 12 | } 13 | -------------------------------------------------------------------------------- /pesto/test_data/assets/tests/modules/declare-submoduleWith-shorthand.nix: -------------------------------------------------------------------------------- 1 | { lib, ... }: let 2 | sub.options.config = lib.mkOption { 3 | type = lib.types.bool; 4 | default = false; 5 | }; 6 | in { 7 | options.submodule = lib.mkOption { 8 | type = lib.types.submoduleWith { 9 | modules = [ sub ]; 10 | shorthandOnlyDefinesConfig = true; 11 | }; 12 | default = {}; 13 | }; 14 | } 15 | -------------------------------------------------------------------------------- /pesto/test_data/assets/tests/modules/declare-submoduleWith-special.nix: -------------------------------------------------------------------------------- 1 | { lib, ... }: { 2 | options.submodule = lib.mkOption { 3 | type = lib.types.submoduleWith { 4 | modules = [ 5 | ({ lib, ... }: { 6 | options.foo = lib.mkOption { 7 | default = lib.foo; 8 | }; 9 | }) 10 | ]; 11 | specialArgs.lib = lib // { 12 | foo = "foo"; 13 | }; 14 | }; 15 | default = {}; 16 | }; 17 | } 18 | -------------------------------------------------------------------------------- /pesto/test_data/assets/tests/modules/declare-variants.nix: -------------------------------------------------------------------------------- 1 | { lib, moduleType, ... }: 2 | let inherit (lib) mkOption types; 3 | in 4 | { 5 | options.variants = mkOption { 6 | type = types.lazyAttrsOf moduleType; 7 | default = {}; 8 | }; 9 | } 10 | -------------------------------------------------------------------------------- /pesto/test_data/assets/tests/modules/default.nix: -------------------------------------------------------------------------------- 1 | { lib ? import ../.., modules ? [] }: 2 | 3 | { 4 | inherit (lib.evalModules { 5 | inherit modules; 6 | specialArgs.modulesPath = ./.; 7 | }) config options; 8 | } 9 | -------------------------------------------------------------------------------- /pesto/test_data/assets/tests/modules/deferred-module-error.nix: -------------------------------------------------------------------------------- 1 | { config, lib, ... }: 2 | let 3 | inherit (lib) types mkOption setDefaultModuleLocation evalModules; 4 | inherit (types) deferredModule lazyAttrsOf submodule str raw enum; 5 | in 6 | { 7 | options = { 8 | deferred = mkOption { 9 | type = deferredModule; 10 | }; 11 | result = mkOption { 12 | default = (evalModules { modules = [ config.deferred ]; }).config.result; 13 | }; 14 | }; 15 | config = { 16 | deferred = { ... }: 17 | # this should be an attrset, so this fails 18 | true; 19 | }; 20 | } 21 | -------------------------------------------------------------------------------- /pesto/test_data/assets/tests/modules/deferred-module.nix: -------------------------------------------------------------------------------- 1 | { lib, ... }: 2 | let 3 | inherit (lib) types mkOption setDefaultModuleLocation; 4 | inherit (types) deferredModule lazyAttrsOf submodule str raw enum; 5 | in 6 | { 7 | imports = [ 8 | # generic module, declaring submodules: 9 | # - nodes. 10 | # - default 11 | # where all nodes include the default 12 | ({ config, ... }: { 13 | _file = "generic.nix"; 14 | options.nodes = mkOption { 15 | type = lazyAttrsOf (submodule { imports = [ config.default ]; }); 16 | default = {}; 17 | }; 18 | options.default = mkOption { 19 | type = deferredModule; 20 | default = { }; 21 | description = '' 22 | Module that is included in all nodes. 23 | ''; 24 | }; 25 | }) 26 | 27 | { 28 | _file = "default-1.nix"; 29 | default = { config, ... }: { 30 | options.settingsDict = lib.mkOption { type = lazyAttrsOf str; default = {}; }; 31 | options.bottom = lib.mkOption { type = enum []; }; 32 | }; 33 | } 34 | 35 | { 36 | _file = "default-a-is-b.nix"; 37 | default = ./define-settingsDict-a-is-b.nix; 38 | } 39 | 40 | { 41 | _file = "nodes-foo.nix"; 42 | nodes.foo.settingsDict.b = "beta"; 43 | } 44 | 45 | { 46 | _file = "the-file-that-contains-the-bad-config.nix"; 47 | default.bottom = "bogus"; 48 | } 49 | 50 | { 51 | _file = "nodes-foo-c-is-a.nix"; 52 | nodes.foo = { config, ... }: { 53 | settingsDict.c = config.settingsDict.a; 54 | }; 55 | } 56 | 57 | ]; 58 | } 59 | -------------------------------------------------------------------------------- /pesto/test_data/assets/tests/modules/define-_module-args-custom.nix: -------------------------------------------------------------------------------- 1 | { lib, ... }: 2 | 3 | { 4 | config = { 5 | _module.args.custom = true; 6 | }; 7 | } 8 | -------------------------------------------------------------------------------- /pesto/test_data/assets/tests/modules/define-attrsOfSub-bar-enable.nix: -------------------------------------------------------------------------------- 1 | { 2 | attrsOfSub.bar.enable = true; 3 | } 4 | -------------------------------------------------------------------------------- /pesto/test_data/assets/tests/modules/define-attrsOfSub-bar.nix: -------------------------------------------------------------------------------- 1 | { 2 | attrsOfSub.bar = {}; 3 | } 4 | -------------------------------------------------------------------------------- /pesto/test_data/assets/tests/modules/define-attrsOfSub-foo-enable-force.nix: -------------------------------------------------------------------------------- 1 | { lib, ... }: 2 | 3 | { 4 | attrsOfSub.foo.enable = lib.mkForce false; 5 | } 6 | -------------------------------------------------------------------------------- /pesto/test_data/assets/tests/modules/define-attrsOfSub-foo-enable-if.nix: -------------------------------------------------------------------------------- 1 | { config, lib, ... }: 2 | 3 | { 4 | attrsOfSub.foo.enable = lib.mkIf config.enable true; 5 | } 6 | -------------------------------------------------------------------------------- /pesto/test_data/assets/tests/modules/define-attrsOfSub-foo-enable.nix: -------------------------------------------------------------------------------- 1 | { 2 | attrsOfSub.foo.enable = true; 3 | } 4 | -------------------------------------------------------------------------------- /pesto/test_data/assets/tests/modules/define-attrsOfSub-foo-force-enable.nix: -------------------------------------------------------------------------------- 1 | { lib, ... }: 2 | 3 | { 4 | attrsOfSub.foo = lib.mkForce { 5 | enable = false; 6 | }; 7 | } 8 | -------------------------------------------------------------------------------- /pesto/test_data/assets/tests/modules/define-attrsOfSub-foo-if-enable.nix: -------------------------------------------------------------------------------- 1 | { config, lib, ... }: 2 | 3 | { 4 | attrsOfSub.foo = lib.mkIf config.enable { 5 | enable = true; 6 | }; 7 | } 8 | -------------------------------------------------------------------------------- /pesto/test_data/assets/tests/modules/define-attrsOfSub-foo.nix: -------------------------------------------------------------------------------- 1 | { 2 | attrsOfSub.foo = {}; 3 | } 4 | -------------------------------------------------------------------------------- /pesto/test_data/assets/tests/modules/define-attrsOfSub-force-foo-enable.nix: -------------------------------------------------------------------------------- 1 | { lib, ... }: 2 | 3 | { 4 | attrsOfSub = lib.mkForce { 5 | foo.enable = false; 6 | }; 7 | } 8 | -------------------------------------------------------------------------------- /pesto/test_data/assets/tests/modules/define-attrsOfSub-if-foo-enable.nix: -------------------------------------------------------------------------------- 1 | { config, lib, ... }: 2 | 3 | { 4 | attrsOfSub = lib.mkIf config.enable { 5 | foo.enable = true; 6 | }; 7 | } 8 | -------------------------------------------------------------------------------- /pesto/test_data/assets/tests/modules/define-bare-submodule-values.nix: -------------------------------------------------------------------------------- 1 | { 2 | bare-submodule.nested = 42; 3 | bare-submodule.deep = 420; 4 | } 5 | -------------------------------------------------------------------------------- /pesto/test_data/assets/tests/modules/define-enable-abort.nix: -------------------------------------------------------------------------------- 1 | { 2 | config.enable = abort "oops"; 3 | } 4 | -------------------------------------------------------------------------------- /pesto/test_data/assets/tests/modules/define-enable-force.nix: -------------------------------------------------------------------------------- 1 | { lib, ... }: 2 | 3 | { 4 | enable = lib.mkForce false; 5 | } 6 | -------------------------------------------------------------------------------- /pesto/test_data/assets/tests/modules/define-enable-throw.nix: -------------------------------------------------------------------------------- 1 | { 2 | config.enable = throw "oops"; 3 | } 4 | -------------------------------------------------------------------------------- /pesto/test_data/assets/tests/modules/define-enable-with-custom-arg.nix: -------------------------------------------------------------------------------- 1 | { lib, custom, ... }: 2 | 3 | { 4 | config = { 5 | enable = custom; 6 | }; 7 | } 8 | -------------------------------------------------------------------------------- /pesto/test_data/assets/tests/modules/define-enable-with-top-level-mkIf.nix: -------------------------------------------------------------------------------- 1 | { lib, ... }: 2 | # I think this might occur more realistically in a submodule 3 | { 4 | imports = [ (lib.mkIf true { enable = true; }) ]; 5 | } 6 | -------------------------------------------------------------------------------- /pesto/test_data/assets/tests/modules/define-enable.nix: -------------------------------------------------------------------------------- 1 | { 2 | enable = true; 3 | } 4 | -------------------------------------------------------------------------------- /pesto/test_data/assets/tests/modules/define-force-attrsOfSub-foo-enable.nix: -------------------------------------------------------------------------------- 1 | { lib, ... }: 2 | 3 | lib.mkForce { 4 | attrsOfSub.foo.enable = false; 5 | } 6 | -------------------------------------------------------------------------------- /pesto/test_data/assets/tests/modules/define-force-enable.nix: -------------------------------------------------------------------------------- 1 | { lib, ... }: 2 | 3 | lib.mkForce { 4 | enable = false; 5 | } 6 | -------------------------------------------------------------------------------- /pesto/test_data/assets/tests/modules/define-freeform-keywords-shorthand.nix: -------------------------------------------------------------------------------- 1 | { config, ... }: { 2 | class = { "just" = "data"; }; 3 | a = "one"; 4 | b = "two"; 5 | meta = "meta"; 6 | 7 | _module.args.result = 8 | let r = builtins.removeAttrs config [ "_module" ]; 9 | in builtins.trace (builtins.deepSeq r r) (r == { 10 | a = "one"; 11 | b = "two"; 12 | class = { "just" = "data"; }; 13 | meta = "meta"; 14 | }); 15 | } 16 | -------------------------------------------------------------------------------- /pesto/test_data/assets/tests/modules/define-if-attrsOfSub-foo-enable.nix: -------------------------------------------------------------------------------- 1 | { config, lib, ... }: 2 | 3 | lib.mkIf config.enable { 4 | attrsOfSub.foo.enable = true; 5 | } 6 | -------------------------------------------------------------------------------- /pesto/test_data/assets/tests/modules/define-module-check.nix: -------------------------------------------------------------------------------- 1 | { 2 | _module.check = false; 3 | } 4 | -------------------------------------------------------------------------------- /pesto/test_data/assets/tests/modules/define-option-dependently-nested.nix: -------------------------------------------------------------------------------- 1 | { lib, options, ... }: 2 | 3 | # Some modules may be distributed separately and need to adapt to other modules 4 | # that are distributed and versioned separately. 5 | { 6 | 7 | # Always defined, but the value depends on the presence of an option. 8 | config.set = { 9 | value = if options ? set.enable then 360 else 7; 10 | } 11 | # Only define if possible. 12 | // lib.optionalAttrs (options ? set.enable) { 13 | enable = true; 14 | }; 15 | 16 | } 17 | -------------------------------------------------------------------------------- /pesto/test_data/assets/tests/modules/define-option-dependently.nix: -------------------------------------------------------------------------------- 1 | { lib, options, ... }: 2 | 3 | # Some modules may be distributed separately and need to adapt to other modules 4 | # that are distributed and versioned separately. 5 | { 6 | 7 | # Always defined, but the value depends on the presence of an option. 8 | config = { 9 | value = if options ? enable then 360 else 7; 10 | } 11 | # Only define if possible. 12 | // lib.optionalAttrs (options ? enable) { 13 | enable = true; 14 | }; 15 | 16 | } 17 | -------------------------------------------------------------------------------- /pesto/test_data/assets/tests/modules/define-settingsDict-a-is-b.nix: -------------------------------------------------------------------------------- 1 | { config, ... }: { 2 | settingsDict.a = config.settingsDict.b; 3 | } 4 | -------------------------------------------------------------------------------- /pesto/test_data/assets/tests/modules/define-shorthandOnlyDefinesConfig-true.nix: -------------------------------------------------------------------------------- 1 | { shorthandOnlyDefinesConfig = true; } 2 | -------------------------------------------------------------------------------- /pesto/test_data/assets/tests/modules/define-submoduleWith-noshorthand.nix: -------------------------------------------------------------------------------- 1 | { 2 | submodule.config.config = true; 3 | } 4 | -------------------------------------------------------------------------------- /pesto/test_data/assets/tests/modules/define-submoduleWith-shorthand.nix: -------------------------------------------------------------------------------- 1 | { 2 | submodule.config = true; 3 | } 4 | -------------------------------------------------------------------------------- /pesto/test_data/assets/tests/modules/define-value-int-negative.nix: -------------------------------------------------------------------------------- 1 | { 2 | value = -23; 3 | } 4 | -------------------------------------------------------------------------------- /pesto/test_data/assets/tests/modules/define-value-int-positive.nix: -------------------------------------------------------------------------------- 1 | { 2 | value = 42; 3 | } 4 | -------------------------------------------------------------------------------- /pesto/test_data/assets/tests/modules/define-value-int-zero.nix: -------------------------------------------------------------------------------- 1 | { 2 | value = 0; 3 | } 4 | -------------------------------------------------------------------------------- /pesto/test_data/assets/tests/modules/define-value-list.nix: -------------------------------------------------------------------------------- 1 | { 2 | value = []; 3 | } 4 | -------------------------------------------------------------------------------- /pesto/test_data/assets/tests/modules/define-value-string-arbitrary.nix: -------------------------------------------------------------------------------- 1 | { 2 | value = "foobar"; 3 | } 4 | -------------------------------------------------------------------------------- /pesto/test_data/assets/tests/modules/define-value-string-bigint.nix: -------------------------------------------------------------------------------- 1 | { 2 | value = "1000"; 3 | } 4 | -------------------------------------------------------------------------------- /pesto/test_data/assets/tests/modules/define-value-string-properties.nix: -------------------------------------------------------------------------------- 1 | { lib, ... }: { 2 | 3 | imports = [{ 4 | value = lib.mkDefault "def"; 5 | }]; 6 | 7 | value = lib.mkMerge [ 8 | (lib.mkIf false "nope") 9 | "yes" 10 | ]; 11 | 12 | } 13 | -------------------------------------------------------------------------------- /pesto/test_data/assets/tests/modules/define-value-string.nix: -------------------------------------------------------------------------------- 1 | { 2 | value = "24"; 3 | } 4 | -------------------------------------------------------------------------------- /pesto/test_data/assets/tests/modules/define-variant.nix: -------------------------------------------------------------------------------- 1 | { config, lib, ... }: 2 | let inherit (lib) types mkOption attrNames; 3 | in 4 | { 5 | options = { 6 | attrs = mkOption { type = types.attrsOf lib.types.int; }; 7 | result = mkOption { }; 8 | resultFoo = mkOption { }; 9 | resultFooBar = mkOption { }; 10 | resultFooFoo = mkOption { }; 11 | }; 12 | config = { 13 | attrs.a = 1; 14 | variants.foo.attrs.b = 1; 15 | variants.bar.attrs.y = 1; 16 | variants.foo.variants.bar.attrs.z = 1; 17 | variants.foo.variants.foo.attrs.c = 3; 18 | resultFoo = lib.concatMapStringsSep " " toString (attrNames config.variants.foo.attrs); 19 | resultFooBar = lib.concatMapStringsSep " " toString (attrNames config.variants.foo.variants.bar.attrs); 20 | resultFooFoo = lib.concatMapStringsSep " " toString (attrNames config.variants.foo.variants.foo.attrs); 21 | }; 22 | } 23 | -------------------------------------------------------------------------------- /pesto/test_data/assets/tests/modules/disable-declare-enable.nix: -------------------------------------------------------------------------------- 1 | { lib, ... }: 2 | 3 | { 4 | disabledModules = [ ./declare-enable.nix ]; 5 | } 6 | -------------------------------------------------------------------------------- /pesto/test_data/assets/tests/modules/disable-define-enable-string-path.nix: -------------------------------------------------------------------------------- 1 | { lib, ... }: 2 | 3 | { 4 | disabledModules = [ (toString ./define-enable.nix) ]; 5 | } 6 | -------------------------------------------------------------------------------- /pesto/test_data/assets/tests/modules/disable-define-enable.nix: -------------------------------------------------------------------------------- 1 | { lib, ... }: 2 | 3 | { 4 | disabledModules = [ ./define-enable.nix ]; 5 | } 6 | -------------------------------------------------------------------------------- /pesto/test_data/assets/tests/modules/disable-enable-modules.nix: -------------------------------------------------------------------------------- 1 | { lib, ... }: 2 | 3 | { 4 | disabledModules = [ "define-enable.nix" "declare-enable.nix" ]; 5 | } 6 | -------------------------------------------------------------------------------- /pesto/test_data/assets/tests/modules/disable-module-bad-key.nix: -------------------------------------------------------------------------------- 1 | { lib, ... }: 2 | let 3 | inherit (lib) mkOption types; 4 | 5 | moduleWithKey = { config, ... }: { 6 | config = { 7 | enable = true; 8 | }; 9 | }; 10 | in 11 | { 12 | imports = [ 13 | ./declare-enable.nix 14 | ]; 15 | disabledModules = [ { } ]; 16 | } 17 | -------------------------------------------------------------------------------- /pesto/test_data/assets/tests/modules/disable-module-with-key.nix: -------------------------------------------------------------------------------- 1 | { lib, ... }: 2 | let 3 | inherit (lib) mkOption types; 4 | 5 | moduleWithKey = { 6 | key = "disable-module-with-key.nix#moduleWithKey"; 7 | config = { 8 | enable = true; 9 | }; 10 | }; 11 | in 12 | { 13 | options = { 14 | positive = mkOption { 15 | type = types.submodule { 16 | imports = [ 17 | ./declare-enable.nix 18 | moduleWithKey 19 | ]; 20 | }; 21 | default = {}; 22 | }; 23 | negative = mkOption { 24 | type = types.submodule { 25 | imports = [ 26 | ./declare-enable.nix 27 | moduleWithKey 28 | ]; 29 | disabledModules = [ moduleWithKey ]; 30 | }; 31 | default = {}; 32 | }; 33 | }; 34 | } 35 | -------------------------------------------------------------------------------- /pesto/test_data/assets/tests/modules/disable-module-with-toString-key.nix: -------------------------------------------------------------------------------- 1 | { lib, ... }: 2 | let 3 | inherit (lib) mkOption types; 4 | 5 | moduleWithKey = { 6 | key = 123; 7 | config = { 8 | enable = true; 9 | }; 10 | }; 11 | in 12 | { 13 | options = { 14 | positive = mkOption { 15 | type = types.submodule { 16 | imports = [ 17 | ./declare-enable.nix 18 | moduleWithKey 19 | ]; 20 | }; 21 | default = {}; 22 | }; 23 | negative = mkOption { 24 | type = types.submodule { 25 | imports = [ 26 | ./declare-enable.nix 27 | moduleWithKey 28 | ]; 29 | disabledModules = [ 123 ]; 30 | }; 31 | default = {}; 32 | }; 33 | }; 34 | } 35 | -------------------------------------------------------------------------------- /pesto/test_data/assets/tests/modules/disable-recursive/bar.nix: -------------------------------------------------------------------------------- 1 | { 2 | imports = [ 3 | ../declare-enable.nix 4 | ]; 5 | } 6 | -------------------------------------------------------------------------------- /pesto/test_data/assets/tests/modules/disable-recursive/disable-bar.nix: -------------------------------------------------------------------------------- 1 | { 2 | 3 | disabledModules = [ 4 | ./bar.nix 5 | ]; 6 | 7 | } 8 | -------------------------------------------------------------------------------- /pesto/test_data/assets/tests/modules/disable-recursive/disable-foo.nix: -------------------------------------------------------------------------------- 1 | { 2 | 3 | disabledModules = [ 4 | ./foo.nix 5 | ]; 6 | 7 | } 8 | -------------------------------------------------------------------------------- /pesto/test_data/assets/tests/modules/disable-recursive/foo.nix: -------------------------------------------------------------------------------- 1 | { 2 | imports = [ 3 | ../declare-enable.nix 4 | ]; 5 | } 6 | -------------------------------------------------------------------------------- /pesto/test_data/assets/tests/modules/disable-recursive/main.nix: -------------------------------------------------------------------------------- 1 | { 2 | imports = [ 3 | ./foo.nix 4 | ./bar.nix 5 | ]; 6 | 7 | enable = true; 8 | } 9 | -------------------------------------------------------------------------------- /pesto/test_data/assets/tests/modules/doRename-basic.nix: -------------------------------------------------------------------------------- 1 | { lib, ... }: { 2 | imports = [ 3 | (lib.doRename { from = ["a" "b"]; to = ["c" "d" "e"]; warn = true; use = x: x; visible = true; }) 4 | ]; 5 | options = { 6 | c.d.e = lib.mkOption {}; 7 | }; 8 | config = { 9 | a.b = 1234; 10 | }; 11 | } 12 | -------------------------------------------------------------------------------- /pesto/test_data/assets/tests/modules/doRename-warnings.nix: -------------------------------------------------------------------------------- 1 | { lib, config, ... }: { 2 | imports = [ 3 | (lib.doRename { from = ["a" "b"]; to = ["c" "d" "e"]; warn = true; use = x: x; visible = true; }) 4 | ]; 5 | options = { 6 | warnings = lib.mkOption { type = lib.types.listOf lib.types.str; }; 7 | c.d.e = lib.mkOption {}; 8 | result = lib.mkOption {}; 9 | }; 10 | config = { 11 | a.b = 1234; 12 | result = lib.concatStringsSep "%" config.warnings; 13 | }; 14 | } 15 | -------------------------------------------------------------------------------- /pesto/test_data/assets/tests/modules/emptyValues.nix: -------------------------------------------------------------------------------- 1 | { lib, ... }: 2 | let 3 | inherit (lib) types; 4 | in { 5 | 6 | options = { 7 | int = lib.mkOption { 8 | type = types.lazyAttrsOf types.int; 9 | }; 10 | list = lib.mkOption { 11 | type = types.lazyAttrsOf (types.listOf types.int); 12 | }; 13 | nonEmptyList = lib.mkOption { 14 | type = types.lazyAttrsOf (types.nonEmptyListOf types.int); 15 | }; 16 | attrs = lib.mkOption { 17 | type = types.lazyAttrsOf (types.attrsOf types.int); 18 | }; 19 | null = lib.mkOption { 20 | type = types.lazyAttrsOf (types.nullOr types.int); 21 | }; 22 | submodule = lib.mkOption { 23 | type = types.lazyAttrsOf (types.submodule {}); 24 | }; 25 | }; 26 | 27 | config = { 28 | int.a = lib.mkIf false null; 29 | list.a = lib.mkIf false null; 30 | nonEmptyList.a = lib.mkIf false null; 31 | attrs.a = lib.mkIf false null; 32 | null.a = lib.mkIf false null; 33 | submodule.a = lib.mkIf false null; 34 | }; 35 | 36 | } 37 | -------------------------------------------------------------------------------- /pesto/test_data/assets/tests/modules/extendModules-168767-imports.nix: -------------------------------------------------------------------------------- 1 | { lib 2 | , extendModules 3 | , ... 4 | }: 5 | with lib; 6 | { 7 | imports = [ 8 | 9 | { 10 | options.sub = mkOption { 11 | default = { }; 12 | type = types.submodule ( 13 | { config 14 | , extendModules 15 | , ... 16 | }: 17 | { 18 | options.value = mkOption { 19 | type = types.int; 20 | }; 21 | 22 | options.specialisation = mkOption { 23 | default = { }; 24 | inherit 25 | (extendModules { 26 | modules = [{ 27 | specialisation = mkOverride 0 { }; 28 | }]; 29 | }) 30 | type; 31 | }; 32 | } 33 | ); 34 | }; 35 | } 36 | 37 | { config.sub.value = 1; } 38 | 39 | 40 | ]; 41 | } 42 | -------------------------------------------------------------------------------- /pesto/test_data/assets/tests/modules/freeform-attrsOf.nix: -------------------------------------------------------------------------------- 1 | { lib, ... }: { 2 | freeformType = with lib.types; attrsOf (either str (attrsOf str)); 3 | } 4 | -------------------------------------------------------------------------------- /pesto/test_data/assets/tests/modules/freeform-lazyAttrsOf.nix: -------------------------------------------------------------------------------- 1 | { lib, ... }: { 2 | freeformType = with lib.types; lazyAttrsOf (either str (lazyAttrsOf str)); 3 | } 4 | -------------------------------------------------------------------------------- /pesto/test_data/assets/tests/modules/freeform-nested.nix: -------------------------------------------------------------------------------- 1 | { lib, ... }: 2 | let 3 | deathtrapArgs = lib.mapAttrs 4 | (k: _: throw "The module system is too strict, accessing an unused option's ${k} mkOption-attribute.") 5 | (lib.functionArgs lib.mkOption); 6 | in 7 | { 8 | options.nest.foo = lib.mkOption { 9 | type = lib.types.bool; 10 | default = false; 11 | }; 12 | options.nest.unused = lib.mkOption deathtrapArgs; 13 | config.nest.bar = "bar"; 14 | } 15 | -------------------------------------------------------------------------------- /pesto/test_data/assets/tests/modules/freeform-str-dep-unstr.nix: -------------------------------------------------------------------------------- 1 | { lib, config, ... }: { 2 | options.foo = lib.mkOption { 3 | type = lib.types.nullOr lib.types.str; 4 | default = null; 5 | }; 6 | 7 | config.foo = lib.mkIf (config ? value) config.value; 8 | } 9 | -------------------------------------------------------------------------------- /pesto/test_data/assets/tests/modules/freeform-submodules.nix: -------------------------------------------------------------------------------- 1 | { lib, options, ... }: with lib.types; { 2 | 3 | options.fooDeclarations = lib.mkOption { 4 | default = (options.free.type.getSubOptions [])._freeformOptions.foo.declarations; 5 | }; 6 | 7 | options.free = lib.mkOption { 8 | type = submodule { 9 | config._module.freeformType = lib.mkMerge [ 10 | (attrsOf (submodule { 11 | options.foo = lib.mkOption {}; 12 | })) 13 | (attrsOf (submodule { 14 | options.bar = lib.mkOption {}; 15 | })) 16 | ]; 17 | }; 18 | }; 19 | 20 | config.free.xxx.foo = 10; 21 | config.free.yyy.bar = 10; 22 | } 23 | -------------------------------------------------------------------------------- /pesto/test_data/assets/tests/modules/freeform-unstr-dep-str.nix: -------------------------------------------------------------------------------- 1 | { lib, config, ... }: { 2 | options.value = lib.mkOption { 3 | type = lib.types.nullOr lib.types.str; 4 | default = null; 5 | }; 6 | 7 | config.foo = lib.mkIf (config.value != null) config.value; 8 | } 9 | -------------------------------------------------------------------------------- /pesto/test_data/assets/tests/modules/functionTo/list-order.nix: -------------------------------------------------------------------------------- 1 | 2 | { lib, config, ... }: 3 | let 4 | inherit (lib) types; 5 | in { 6 | options = { 7 | fun = lib.mkOption { 8 | type = types.functionTo (types.listOf types.str); 9 | }; 10 | 11 | result = lib.mkOption { 12 | type = types.str; 13 | default = toString (config.fun { 14 | a = "a"; 15 | b = "b"; 16 | c = "c"; 17 | }); 18 | }; 19 | }; 20 | 21 | config.fun = lib.mkMerge [ 22 | (input: lib.mkAfter [ input.a ]) 23 | (input: [ input.b ]) 24 | ]; 25 | } 26 | -------------------------------------------------------------------------------- /pesto/test_data/assets/tests/modules/functionTo/merging-attrs.nix: -------------------------------------------------------------------------------- 1 | { lib, config, ... }: 2 | let 3 | inherit (lib) types; 4 | in { 5 | options = { 6 | fun = lib.mkOption { 7 | type = types.functionTo (types.attrsOf types.str); 8 | }; 9 | 10 | result = lib.mkOption { 11 | type = types.str; 12 | default = toString (lib.attrValues (config.fun { 13 | a = "a"; 14 | b = "b"; 15 | c = "c"; 16 | })); 17 | }; 18 | }; 19 | 20 | config.fun = lib.mkMerge [ 21 | (input: { inherit (input) a; }) 22 | (input: { inherit (input) b; }) 23 | (input: { 24 | b = lib.mkForce input.c; 25 | }) 26 | ]; 27 | } 28 | -------------------------------------------------------------------------------- /pesto/test_data/assets/tests/modules/functionTo/merging-list.nix: -------------------------------------------------------------------------------- 1 | { lib, config, ... }: 2 | let 3 | inherit (lib) types; 4 | in { 5 | options = { 6 | fun = lib.mkOption { 7 | type = types.functionTo (types.listOf types.str); 8 | }; 9 | 10 | result = lib.mkOption { 11 | type = types.str; 12 | default = toString (config.fun { 13 | a = "a"; 14 | b = "b"; 15 | c = "c"; 16 | }); 17 | }; 18 | }; 19 | 20 | config.fun = lib.mkMerge [ 21 | (input: [ input.a ]) 22 | (input: [ input.b ]) 23 | ]; 24 | } 25 | -------------------------------------------------------------------------------- /pesto/test_data/assets/tests/modules/functionTo/submodule-options.nix: -------------------------------------------------------------------------------- 1 | { lib, config, options, ... }: 2 | let 3 | inherit (lib) types; 4 | in 5 | { 6 | imports = [ 7 | 8 | # fun..a 9 | ({ ... }: { 10 | options = { 11 | fun = lib.mkOption { 12 | type = types.functionTo (types.submodule { 13 | options.a = lib.mkOption { default = "a"; }; 14 | }); 15 | }; 16 | }; 17 | }) 18 | 19 | # fun..b 20 | ({ ... }: { 21 | options = { 22 | fun = lib.mkOption { 23 | type = types.functionTo (types.submodule { 24 | options.b = lib.mkOption { default = "b"; }; 25 | }); 26 | }; 27 | }; 28 | }) 29 | ]; 30 | 31 | options = { 32 | result = lib.mkOption 33 | { 34 | type = types.str; 35 | default = lib.concatStringsSep " " (lib.attrValues (config.fun (throw "shouldn't use input param"))); 36 | }; 37 | 38 | optionsResult = lib.mkOption 39 | { 40 | type = types.str; 41 | default = lib.concatStringsSep " " 42 | (lib.concatLists 43 | (lib.mapAttrsToList 44 | (k: v: 45 | if k == "_module" 46 | then [ ] 47 | else [ (lib.showOption v.loc) ] 48 | ) 49 | ( 50 | (options.fun.type.getSubOptions [ "fun" ]) 51 | ) 52 | ) 53 | ); 54 | }; 55 | }; 56 | 57 | config.fun = lib.mkMerge 58 | [ 59 | (input: { b = "bee"; }) 60 | ]; 61 | } 62 | -------------------------------------------------------------------------------- /pesto/test_data/assets/tests/modules/functionTo/trivial.nix: -------------------------------------------------------------------------------- 1 | { lib, config, ... }: 2 | let 3 | inherit (lib) types; 4 | in { 5 | options = { 6 | fun = lib.mkOption { 7 | type = types.functionTo types.str; 8 | }; 9 | 10 | result = lib.mkOption { 11 | type = types.str; 12 | default = config.fun "input"; 13 | }; 14 | }; 15 | 16 | config.fun = input: "input is ${input}"; 17 | } 18 | -------------------------------------------------------------------------------- /pesto/test_data/assets/tests/modules/functionTo/wrong-type.nix: -------------------------------------------------------------------------------- 1 | 2 | { lib, config, ... }: 3 | let 4 | inherit (lib) types; 5 | in { 6 | options = { 7 | fun = lib.mkOption { 8 | type = types.functionTo types.str; 9 | }; 10 | 11 | result = lib.mkOption { 12 | type = types.str; 13 | default = config.fun 0; 14 | }; 15 | }; 16 | 17 | config.fun = input: input + 1; 18 | } 19 | -------------------------------------------------------------------------------- /pesto/test_data/assets/tests/modules/gvariant.nix: -------------------------------------------------------------------------------- 1 | { config, lib, ... }: 2 | 3 | { 4 | options = { 5 | examples = lib.mkOption { type = lib.types.attrs; }; 6 | assertion = lib.mkOption { type = lib.types.bool; }; 7 | }; 8 | 9 | config = { 10 | examples = with lib.gvariant; { 11 | bool = true; 12 | float = 3.14; 13 | int32 = mkInt32 (- 42); 14 | uint32 = mkUint32 42; 15 | int16 = mkInt16 (-42); 16 | uint16 = mkUint16 42; 17 | int64 = mkInt64 (-42); 18 | uint64 = mkUint64 42; 19 | array1 = [ "one" ]; 20 | array2 = mkArray [ (mkInt32 1) ]; 21 | array3 = mkArray [ (mkUint32 2) ]; 22 | emptyArray = mkEmptyArray type.uint32; 23 | string = "foo"; 24 | escapedString = '' 25 | '\ 26 | ''; 27 | tuple = mkTuple [ (mkInt32 1) [ "foo" ] ]; 28 | maybe1 = mkNothing type.string; 29 | maybe2 = mkJust (mkUint32 4); 30 | variant = mkVariant "foo"; 31 | dictionaryEntry = mkDictionaryEntry (mkInt32 1) [ "foo" ]; 32 | }; 33 | 34 | assertion = 35 | let 36 | mkLine = n: v: "${n} = ${toString (lib.gvariant.mkValue v)}"; 37 | result = lib.concatStringsSep "\n" (lib.mapAttrsToList mkLine config.examples); 38 | in 39 | (result + "\n") == '' 40 | array1 = @as ['one'] 41 | array2 = @ai [1] 42 | array3 = @au [@u 2] 43 | bool = true 44 | dictionaryEntry = @{ias} {1,@as ['foo']} 45 | emptyArray = @au [] 46 | escapedString = '\'\\\n' 47 | float = 3.140000 48 | int16 = @n -42 49 | int32 = -42 50 | int64 = @x -42 51 | maybe1 = @ms nothing 52 | maybe2 = just @u 4 53 | string = 'foo' 54 | tuple = @(ias) (1,@as ['foo']) 55 | uint16 = @q 42 56 | uint32 = @u 42 57 | uint64 = @t 42 58 | variant = <'foo'> 59 | ''; 60 | }; 61 | } 62 | -------------------------------------------------------------------------------- /pesto/test_data/assets/tests/modules/import-configuration.nix: -------------------------------------------------------------------------------- 1 | { lib, ... }: 2 | let 3 | myconf = lib.evalModules { modules = [ { } ]; }; 4 | in 5 | { 6 | imports = [ 7 | # We can't do this. A configuration is not equal to its set of a modules. 8 | # Equating those would lead to a mess, as specialArgs, anonymous modules 9 | # that can't be deduplicated, and possibly more come into play. 10 | myconf 11 | ]; 12 | } 13 | -------------------------------------------------------------------------------- /pesto/test_data/assets/tests/modules/import-custom-arg.nix: -------------------------------------------------------------------------------- 1 | { lib, custom, ... }: 2 | 3 | { 4 | imports = [] 5 | ++ lib.optional custom ./define-enable-force.nix; 6 | } 7 | -------------------------------------------------------------------------------- /pesto/test_data/assets/tests/modules/import-from-store.nix: -------------------------------------------------------------------------------- 1 | { lib, ... }: 2 | { 3 | 4 | imports = [ 5 | "${builtins.toFile "drv" "{}"}" 6 | ./declare-enable.nix 7 | ./define-enable.nix 8 | ]; 9 | 10 | } 11 | 12 | -------------------------------------------------------------------------------- /pesto/test_data/assets/tests/modules/merge-module-with-key.nix: -------------------------------------------------------------------------------- 1 | { lib, ... }: 2 | let 3 | inherit (lib) mkOption types; 4 | 5 | moduleWithoutKey = { 6 | config = { 7 | raw = "pear"; 8 | }; 9 | }; 10 | 11 | moduleWithKey = { 12 | key = __curPos.file + "#moduleWithKey"; 13 | config = { 14 | raw = "pear"; 15 | }; 16 | }; 17 | 18 | decl = { 19 | options = { 20 | raw = mkOption { 21 | type = types.lines; 22 | }; 23 | }; 24 | }; 25 | in 26 | { 27 | options = { 28 | once = mkOption { 29 | type = types.submodule { 30 | imports = [ 31 | decl 32 | moduleWithKey 33 | moduleWithKey 34 | ]; 35 | }; 36 | default = {}; 37 | }; 38 | twice = mkOption { 39 | type = types.submodule { 40 | imports = [ 41 | decl 42 | moduleWithoutKey 43 | moduleWithoutKey 44 | ]; 45 | }; 46 | default = {}; 47 | }; 48 | }; 49 | } 50 | -------------------------------------------------------------------------------- /pesto/test_data/assets/tests/modules/merge-typeless-option.nix: -------------------------------------------------------------------------------- 1 | { lib, ... }: 2 | 3 | let 4 | typeless = 5 | { lib, ... }: 6 | 7 | { 8 | options.group = lib.mkOption { }; 9 | }; 10 | childOfTypeless = 11 | { lib, ... }: 12 | 13 | { 14 | options.group.enable = lib.mkEnableOption "nothing"; 15 | }; 16 | in 17 | 18 | { 19 | imports = [ 20 | typeless 21 | childOfTypeless 22 | ]; 23 | 24 | config.group.enable = false; 25 | } 26 | -------------------------------------------------------------------------------- /pesto/test_data/assets/tests/modules/module-argument-default.nix: -------------------------------------------------------------------------------- 1 | { a ? false, lib, ... }: { 2 | options = { 3 | result = lib.mkOption {}; 4 | }; 5 | config = { 6 | _module.args.a = true; 7 | result = a; 8 | }; 9 | } 10 | -------------------------------------------------------------------------------- /pesto/test_data/assets/tests/modules/module-class-is-darwin.nix: -------------------------------------------------------------------------------- 1 | { 2 | _class = "darwin"; 3 | config = {}; 4 | } 5 | -------------------------------------------------------------------------------- /pesto/test_data/assets/tests/modules/module-class-is-nixos.nix: -------------------------------------------------------------------------------- 1 | { 2 | _class = "nixos"; 3 | config = {}; 4 | } 5 | -------------------------------------------------------------------------------- /pesto/test_data/assets/tests/modules/module-imports-_type-check.nix: -------------------------------------------------------------------------------- 1 | { 2 | imports = [ { _type = "flake"; } ]; 3 | } 4 | -------------------------------------------------------------------------------- /pesto/test_data/assets/tests/modules/optionTypeFile.nix: -------------------------------------------------------------------------------- 1 | { config, lib, ... }: { 2 | 3 | _file = "optionTypeFile.nix"; 4 | 5 | options.theType = lib.mkOption { 6 | type = lib.types.optionType; 7 | }; 8 | 9 | options.theOption = lib.mkOption { 10 | type = config.theType; 11 | default = {}; 12 | }; 13 | 14 | config.theType = lib.mkMerge [ 15 | (lib.types.submodule { 16 | options.nested = lib.mkOption { 17 | type = lib.types.int; 18 | }; 19 | }) 20 | (lib.types.submodule { 21 | _file = "other.nix"; 22 | options.nested = lib.mkOption { 23 | type = lib.types.str; 24 | }; 25 | }) 26 | ]; 27 | 28 | } 29 | -------------------------------------------------------------------------------- /pesto/test_data/assets/tests/modules/optionTypeMerging.nix: -------------------------------------------------------------------------------- 1 | { config, lib, ... }: { 2 | 3 | options.theType = lib.mkOption { 4 | type = lib.types.optionType; 5 | }; 6 | 7 | options.theOption = lib.mkOption { 8 | type = config.theType; 9 | }; 10 | 11 | config.theType = lib.mkMerge [ 12 | (lib.types.submodule { 13 | options.int = lib.mkOption { 14 | type = lib.types.int; 15 | default = 10; 16 | }; 17 | }) 18 | (lib.types.submodule { 19 | options.str = lib.mkOption { 20 | type = lib.types.str; 21 | }; 22 | }) 23 | ]; 24 | 25 | config.theOption.str = "hello"; 26 | 27 | } 28 | -------------------------------------------------------------------------------- /pesto/test_data/assets/tests/modules/options-type-error-configuration.nix: -------------------------------------------------------------------------------- 1 | { lib, ... }: { 2 | options = { 3 | # unlikely mistake, but we can catch any attrset with _type 4 | result = lib.evalModules { modules = []; }; 5 | }; 6 | } 7 | -------------------------------------------------------------------------------- /pesto/test_data/assets/tests/modules/options-type-error-typical-nested.nix: -------------------------------------------------------------------------------- 1 | { lib, ... }: { 2 | options = { 3 | result.here = lib.types.str; 4 | }; 5 | } 6 | -------------------------------------------------------------------------------- /pesto/test_data/assets/tests/modules/options-type-error-typical.nix: -------------------------------------------------------------------------------- 1 | { lib, ... }: { 2 | options = { 3 | result = lib.types.str; 4 | }; 5 | } 6 | -------------------------------------------------------------------------------- /pesto/test_data/assets/tests/modules/raw.nix: -------------------------------------------------------------------------------- 1 | { lib, ... }: { 2 | 3 | options = { 4 | processedToplevel = lib.mkOption { 5 | type = lib.types.raw; 6 | }; 7 | unprocessedNesting = lib.mkOption { 8 | type = lib.types.raw; 9 | }; 10 | multiple = lib.mkOption { 11 | type = lib.types.raw; 12 | }; 13 | priorities = lib.mkOption { 14 | type = lib.types.raw; 15 | }; 16 | }; 17 | 18 | config = { 19 | processedToplevel = lib.mkIf true 10; 20 | unprocessedNesting.foo = throw "foo"; 21 | multiple = lib.mkMerge [ 22 | "foo" 23 | "foo" 24 | ]; 25 | priorities = lib.mkMerge [ 26 | "foo" 27 | (lib.mkForce "bar") 28 | ]; 29 | }; 30 | } 31 | -------------------------------------------------------------------------------- /pesto/test_data/assets/tests/modules/shorthand-meta.nix: -------------------------------------------------------------------------------- 1 | { lib, ... }: 2 | let 3 | inherit (lib) types mkOption; 4 | in 5 | { 6 | imports = [ 7 | ({ config, ... }: { 8 | options = { 9 | meta.foo = mkOption { 10 | type = types.listOf types.str; 11 | }; 12 | result = mkOption { default = lib.concatStringsSep " " config.meta.foo; }; 13 | }; 14 | }) 15 | { 16 | meta.foo = [ "one" "two" ]; 17 | } 18 | ]; 19 | } 20 | -------------------------------------------------------------------------------- /pesto/test_data/assets/tests/modules/submoduleFiles.nix: -------------------------------------------------------------------------------- 1 | { lib, ... }: { 2 | options.submodule = lib.mkOption { 3 | default = {}; 4 | type = lib.types.submoduleWith { 5 | modules = [ ({ options, ... }: { 6 | options.value = lib.mkOption {}; 7 | 8 | options.internalFiles = lib.mkOption { 9 | default = options.value.files; 10 | }; 11 | })]; 12 | }; 13 | }; 14 | 15 | imports = [ 16 | { 17 | _file = "the-file.nix"; 18 | submodule.value = 10; 19 | } 20 | ]; 21 | } 22 | -------------------------------------------------------------------------------- /pesto/test_data/assets/tests/modules/test-mergeAttrDefinitionsWithPrio.nix: -------------------------------------------------------------------------------- 1 | { lib, options, ... }: 2 | 3 | let 4 | defs = lib.modules.mergeAttrDefinitionsWithPrio options._module.args; 5 | assertLazy = pos: throw "${pos.file}:${toString pos.line}:${toString pos.column}: The test must not evaluate this the assertLazy thunk, but it did. Unexpected strictness leads to unexpected errors and performance problems."; 6 | in 7 | 8 | { 9 | options.result = lib.mkOption { }; 10 | config._module.args = { 11 | default = lib.mkDefault (assertLazy __curPos); 12 | regular = null; 13 | force = lib.mkForce (assertLazy __curPos); 14 | unused = assertLazy __curPos; 15 | }; 16 | config.result = 17 | assert defs.default.highestPrio == (lib.mkDefault (assertLazy __curPos)).priority; 18 | assert defs.regular.highestPrio == lib.modules.defaultOverridePriority; 19 | assert defs.force.highestPrio == (lib.mkForce (assertLazy __curPos)).priority; 20 | true; 21 | } 22 | -------------------------------------------------------------------------------- /pesto/test_data/assets/tests/modules/types-anything/attrs-coercible.nix: -------------------------------------------------------------------------------- 1 | { lib, ... }: { 2 | 3 | options.value = lib.mkOption { 4 | type = lib.types.anything; 5 | }; 6 | 7 | config.value = { 8 | outPath = "foo"; 9 | err = throw "err"; 10 | }; 11 | 12 | } 13 | -------------------------------------------------------------------------------- /pesto/test_data/assets/tests/modules/types-anything/equal-atoms.nix: -------------------------------------------------------------------------------- 1 | { lib, ... }: { 2 | 3 | options.value = lib.mkOption { 4 | type = lib.types.anything; 5 | }; 6 | 7 | config = lib.mkMerge [ 8 | { 9 | value.int = 0; 10 | value.bool = false; 11 | value.string = ""; 12 | value.path = /.; 13 | value.null = null; 14 | value.float = 0.1; 15 | } 16 | { 17 | value.int = 0; 18 | value.bool = false; 19 | value.string = ""; 20 | value.path = /.; 21 | value.null = null; 22 | value.float = 0.1; 23 | } 24 | ]; 25 | 26 | } 27 | -------------------------------------------------------------------------------- /pesto/test_data/assets/tests/modules/types-anything/functions.nix: -------------------------------------------------------------------------------- 1 | { lib, config, ... }: { 2 | 3 | options.value = lib.mkOption { 4 | type = lib.types.anything; 5 | }; 6 | 7 | options.applied = lib.mkOption { 8 | default = lib.mapAttrs (name: fun: fun null) config.value; 9 | }; 10 | 11 | config = lib.mkMerge [ 12 | { 13 | value.single-lambda = x: x; 14 | value.multiple-lambdas = x: { inherit x; }; 15 | value.merging-lambdas = x: { inherit x; }; 16 | } 17 | { 18 | value.multiple-lambdas = x: [ x ]; 19 | value.merging-lambdas = y: { inherit y; }; 20 | } 21 | ]; 22 | 23 | } 24 | -------------------------------------------------------------------------------- /pesto/test_data/assets/tests/modules/types-anything/lists.nix: -------------------------------------------------------------------------------- 1 | { lib, ... }: { 2 | 3 | options.value = lib.mkOption { 4 | type = lib.types.anything; 5 | }; 6 | 7 | config = lib.mkMerge [ 8 | { 9 | value = [ null ]; 10 | } 11 | { 12 | value = [ null ]; 13 | } 14 | ]; 15 | 16 | } 17 | -------------------------------------------------------------------------------- /pesto/test_data/assets/tests/modules/types-anything/mk-mods.nix: -------------------------------------------------------------------------------- 1 | { lib, ... }: { 2 | 3 | options.value = lib.mkOption { 4 | type = lib.types.anything; 5 | }; 6 | 7 | config = lib.mkMerge [ 8 | { 9 | value.mkiffalse = lib.mkIf false {}; 10 | } 11 | { 12 | value.mkiftrue = lib.mkIf true {}; 13 | } 14 | { 15 | value.mkdefault = lib.mkDefault 0; 16 | } 17 | { 18 | value.mkdefault = 1; 19 | } 20 | { 21 | value.mkmerge = lib.mkMerge [ 22 | {} 23 | ]; 24 | } 25 | { 26 | value.mkbefore = lib.mkBefore true; 27 | } 28 | { 29 | value.nested = lib.mkMerge [ 30 | { 31 | foo = lib.mkDefault 0; 32 | bar = lib.mkIf false 0; 33 | } 34 | (lib.mkIf true { 35 | foo = lib.mkIf true (lib.mkForce 1); 36 | bar = { 37 | baz = lib.mkDefault "baz"; 38 | }; 39 | }) 40 | ]; 41 | } 42 | ]; 43 | 44 | } 45 | -------------------------------------------------------------------------------- /pesto/test_data/assets/tests/modules/types-anything/nested-attrs.nix: -------------------------------------------------------------------------------- 1 | { lib, ... }: { 2 | 3 | options.value = lib.mkOption { 4 | type = lib.types.anything; 5 | }; 6 | 7 | config = lib.mkMerge [ 8 | { 9 | value.foo = null; 10 | } 11 | { 12 | value.l1.foo = null; 13 | } 14 | { 15 | value.l1.l2.foo = null; 16 | } 17 | { 18 | value.l1.l2.l3.foo = null; 19 | } 20 | ]; 21 | 22 | } 23 | -------------------------------------------------------------------------------- /pesto/test_data/assets/tests/modules/types.nix: -------------------------------------------------------------------------------- 1 | { lib, ... }: 2 | let 3 | inherit (builtins) 4 | storeDir; 5 | inherit (lib) 6 | types 7 | mkOption 8 | ; 9 | in 10 | { 11 | options = { 12 | pathInStore = mkOption { type = types.lazyAttrsOf types.pathInStore; }; 13 | }; 14 | config = { 15 | pathInStore.ok1 = "${storeDir}/0lz9p8xhf89kb1c1kk6jxrzskaiygnlh-bash-5.2-p15.drv"; 16 | pathInStore.ok2 = "${storeDir}/0fb3ykw9r5hpayd05sr0cizwadzq1d8q-bash-5.2-p15"; 17 | pathInStore.ok3 = "${storeDir}/0fb3ykw9r5hpayd05sr0cizwadzq1d8q-bash-5.2-p15/bin/bash"; 18 | pathInStore.bad1 = ""; 19 | pathInStore.bad2 = "${storeDir}"; 20 | pathInStore.bad3 = "${storeDir}/"; 21 | pathInStore.bad4 = "${storeDir}/.links"; # technically true, but not reasonable 22 | pathInStore.bad5 = "/foo/bar"; 23 | }; 24 | } 25 | -------------------------------------------------------------------------------- /pesto/test_data/assets/tests/release.nix: -------------------------------------------------------------------------------- 1 | { # The pkgs used for dependencies for the testing itself 2 | # Don't test properties of pkgs.lib, but rather the lib in the parent directory 3 | pkgs ? import ../.. {} // { lib = throw "pkgs.lib accessed, but the lib tests should use nixpkgs' lib path directly!"; }, 4 | nix ? pkgs.nix, 5 | nixVersions ? [ pkgs.nixVersions.minimum nix pkgs.nixVersions.unstable ], 6 | }: 7 | 8 | let 9 | lib = import ../.; 10 | testWithNix = nix: 11 | pkgs.runCommand "nixpkgs-lib-tests-nix-${nix.version}" { 12 | buildInputs = [ 13 | (import ./check-eval.nix) 14 | (import ./maintainers.nix { 15 | inherit pkgs; 16 | lib = import ../.; 17 | }) 18 | (import ./teams.nix { 19 | inherit pkgs; 20 | lib = import ../.; 21 | }) 22 | (import ../path/tests { 23 | inherit pkgs; 24 | }) 25 | ]; 26 | nativeBuildInputs = [ 27 | nix 28 | ] ++ lib.optional pkgs.stdenv.isLinux pkgs.inotify-tools; 29 | strictDeps = true; 30 | } '' 31 | datadir="${nix}/share" 32 | export TEST_ROOT=$(pwd)/test-tmp 33 | export NIX_BUILD_HOOK= 34 | export NIX_CONF_DIR=$TEST_ROOT/etc 35 | export NIX_LOCALSTATE_DIR=$TEST_ROOT/var 36 | export NIX_LOG_DIR=$TEST_ROOT/var/log/nix 37 | export NIX_STATE_DIR=$TEST_ROOT/var/nix 38 | export NIX_STORE_DIR=$TEST_ROOT/store 39 | export PAGER=cat 40 | cacheDir=$TEST_ROOT/binary-cache 41 | 42 | nix-store --init 43 | 44 | cp -r ${../.} lib 45 | echo "Running lib/tests/modules.sh" 46 | bash lib/tests/modules.sh 47 | 48 | echo "Running lib/tests/filesystem.sh" 49 | TEST_LIB=$PWD/lib bash lib/tests/filesystem.sh 50 | 51 | echo "Running lib/tests/sources.sh" 52 | TEST_LIB=$PWD/lib bash lib/tests/sources.sh 53 | 54 | echo "Running lib/fileset/tests.sh" 55 | TEST_LIB=$PWD/lib bash lib/fileset/tests.sh 56 | 57 | echo "Running lib/tests/systems.nix" 58 | [[ $(nix-instantiate --eval --strict lib/tests/systems.nix | tee /dev/stderr) == '[ ]' ]]; 59 | 60 | mkdir $out 61 | echo success > $out/${nix.version} 62 | ''; 63 | 64 | in 65 | pkgs.symlinkJoin { 66 | name = "nixpkgs-lib-tests"; 67 | paths = map testWithNix nixVersions; 68 | } 69 | -------------------------------------------------------------------------------- /pesto/test_data/assets/tests/teams.nix: -------------------------------------------------------------------------------- 1 | # to run these tests: 2 | # nix-build nixpkgs/lib/tests/teams.nix 3 | # If it builds, all tests passed 4 | { pkgs ? import ../.. {}, lib ? pkgs.lib }: 5 | 6 | let 7 | inherit (lib) types; 8 | 9 | teamModule = { config, ... }: { 10 | options = { 11 | shortName = lib.mkOption { 12 | type = types.str; 13 | }; 14 | scope = lib.mkOption { 15 | type = types.str; 16 | }; 17 | enableFeatureFreezePing = lib.mkOption { 18 | type = types.bool; 19 | default = false; 20 | }; 21 | members = lib.mkOption { 22 | type = types.listOf (types.submodule 23 | (import ./maintainer-module.nix { inherit lib; }) 24 | ); 25 | default = []; 26 | }; 27 | githubTeams = lib.mkOption { 28 | type = types.listOf types.str; 29 | default = []; 30 | }; 31 | }; 32 | }; 33 | 34 | checkTeam = team: uncheckedAttrs: 35 | let 36 | prefix = [ "lib" "maintainer-team" team ]; 37 | checkedAttrs = (lib.modules.evalModules { 38 | inherit prefix; 39 | modules = [ 40 | teamModule 41 | { 42 | _file = toString ../../maintainers/team-list.nix; 43 | config = uncheckedAttrs; 44 | } 45 | ]; 46 | }).config; 47 | in checkedAttrs; 48 | 49 | checkedTeams = lib.mapAttrs checkTeam lib.teams; 50 | in pkgs.writeTextDir "maintainer-teams.json" (builtins.toJSON checkedTeams) 51 | -------------------------------------------------------------------------------- /pesto/test_data/assets/versions.nix: -------------------------------------------------------------------------------- 1 | /** 2 | Version string functions. 3 | */ 4 | { lib }: 5 | 6 | rec { 7 | 8 | /** 9 | Break a version string into its component parts. 10 | 11 | # Example 12 | 13 | ```nix 14 | splitVersion "1.2.3" 15 | => ["1" "2" "3"] 16 | ``` 17 | */ 18 | splitVersion = builtins.splitVersion or (lib.splitString "."); 19 | 20 | /** 21 | Get the major version string from a string. 22 | 23 | # Example 24 | 25 | ```nix 26 | major "1.2.3" 27 | => "1" 28 | ``` 29 | 30 | # Arguments 31 | 32 | - [v] 33 | 34 | */ 35 | major = v: builtins.elemAt (splitVersion v) 0; 36 | 37 | /** 38 | Get the minor version string from a string. 39 | 40 | # Example 41 | 42 | ```nix 43 | minor "1.2.3" 44 | => "2" 45 | ``` 46 | 47 | # Arguments 48 | 49 | - [v] 50 | 51 | */ 52 | minor = v: builtins.elemAt (splitVersion v) 1; 53 | 54 | /** 55 | Get the patch version string from a string. 56 | 57 | # Example 58 | 59 | ```nix 60 | patch "1.2.3" 61 | => "3" 62 | ``` 63 | 64 | # Arguments 65 | 66 | - [v] 67 | 68 | */ 69 | patch = v: builtins.elemAt (splitVersion v) 2; 70 | 71 | /** 72 | Get string of the first two parts (major and minor) 73 | of a version string. 74 | 75 | # Example 76 | 77 | ```nix 78 | majorMinor "1.2.3" 79 | => "1.2" 80 | ``` 81 | 82 | # Arguments 83 | 84 | - [v] 85 | 86 | */ 87 | majorMinor = v: 88 | builtins.concatStringsSep "." 89 | (lib.take 2 (splitVersion v)); 90 | 91 | /** 92 | Pad a version string with zeros to match the given number of components. 93 | 94 | # Example 95 | 96 | ```nix 97 | pad 3 "1.2" 98 | => "1.2.0" 99 | pad 3 "1.3-rc1" 100 | => "1.3.0-rc1" 101 | pad 3 "1.2.3.4" 102 | => "1.2.3" 103 | ``` 104 | 105 | # Arguments 106 | 107 | - [n] 108 | - [version] 109 | 110 | */ 111 | pad = n: version: let 112 | numericVersion = lib.head (lib.splitString "-" version); 113 | versionSuffix = lib.removePrefix numericVersion version; 114 | in lib.concatStringsSep "." (lib.take n (lib.splitVersion numericVersion ++ lib.genList (_: "0") n)) + versionSuffix; 115 | 116 | } 117 | -------------------------------------------------------------------------------- /pesto/test_data/assets/zip-int-bits.nix: -------------------------------------------------------------------------------- 1 | /** 2 | Helper function to implement a fallback for the bit operators 3 | `bitAnd`, `bitOr` and `bitXor` on older nix version. 4 | See ./trivial.nix 5 | */ 6 | f: x: y: 7 | let 8 | # (intToBits 6) -> [ 0 1 1 ] 9 | intToBits = x: 10 | if x == 0 || x == -1 then 11 | [] 12 | else 13 | let 14 | headbit = if (x / 2) * 2 != x then 1 else 0; # x & 1 15 | tailbits = if x < 0 then ((x + 1) / 2) - 1 else x / 2; # x >> 1 16 | in 17 | [headbit] ++ (intToBits tailbits); 18 | 19 | # (bitsToInt [ 0 1 1 ] 0) -> 6 20 | # (bitsToInt [ 0 1 0 ] 1) -> -6 21 | bitsToInt = l: signum: 22 | if l == [] then 23 | (if signum == 0 then 0 else -1) 24 | else 25 | (builtins.head l) + (2 * (bitsToInt (builtins.tail l) signum)); 26 | 27 | xsignum = if x < 0 then 1 else 0; 28 | ysignum = if y < 0 then 1 else 0; 29 | zipListsWith' = fst: snd: 30 | if fst==[] && snd==[] then 31 | [] 32 | else if fst==[] then 33 | [(f xsignum (builtins.head snd))] ++ (zipListsWith' [] (builtins.tail snd)) 34 | else if snd==[] then 35 | [(f (builtins.head fst) ysignum )] ++ (zipListsWith' (builtins.tail fst) [] ) 36 | else 37 | [(f (builtins.head fst) (builtins.head snd))] ++ (zipListsWith' (builtins.tail fst) (builtins.tail snd)); 38 | in 39 | assert (builtins.isInt x) && (builtins.isInt y); 40 | bitsToInt (zipListsWith' (intToBits x) (intToBits y)) (f xsignum ysignum) 41 | -------------------------------------------------------------------------------- /pesto/test_data/atom/functor.expect: -------------------------------------------------------------------------------- 1 | Some(NixDocComment { content: Some("Docs"), count_applied: None }) -------------------------------------------------------------------------------- /pesto/test_data/atom/functor.nix: -------------------------------------------------------------------------------- 1 | let 2 | /**Docs*/ 3 | foo = { 4 | __functor = self: x: self; 5 | }; 6 | in 7 | { inherit foo; } 8 | -------------------------------------------------------------------------------- /pesto/test_data/atom/functor.pos: -------------------------------------------------------------------------------- 1 | { 2 | "line": 3, 3 | "column": 9 4 | } 5 | -------------------------------------------------------------------------------- /pesto/test_data/atom/inherit.expect: -------------------------------------------------------------------------------- 1 | Some(NixDocComment { content: None, count_applied: None }) -------------------------------------------------------------------------------- /pesto/test_data/atom/inherit.nix: -------------------------------------------------------------------------------- 1 | let 2 | inherit (self.asserts) assertMsg assertOneOf; 3 | in 1 4 | -------------------------------------------------------------------------------- /pesto/test_data/atom/inherit.pos: -------------------------------------------------------------------------------- 1 | { 2 | "line": 2, 3 | "column": 25 4 | } 5 | -------------------------------------------------------------------------------- /pesto/test_data/atom/partially_applied_1_lambda.expect: -------------------------------------------------------------------------------- 1 | Some(NixDocComment { content: None, count_applied: Some(1) }) -------------------------------------------------------------------------------- /pesto/test_data/atom/partially_applied_1_lambda.nix: -------------------------------------------------------------------------------- 1 | let 2 | /**Docs*/ 3 | foo = x: y: z: b: x; 4 | in foo 5 | -------------------------------------------------------------------------------- /pesto/test_data/atom/partially_applied_1_lambda.pos: -------------------------------------------------------------------------------- 1 | { 2 | "line": 3, 3 | "column": 12 4 | } 5 | -------------------------------------------------------------------------------- /pesto/test_data/atom/partially_applied_2_lambda.expect: -------------------------------------------------------------------------------- 1 | Some(NixDocComment { content: None, count_applied: Some(3) }) -------------------------------------------------------------------------------- /pesto/test_data/atom/partially_applied_2_lambda.nix: -------------------------------------------------------------------------------- 1 | let 2 | /**Docs*/ 3 | foo = x: y: z: b: x; 4 | in foo 5 | -------------------------------------------------------------------------------- /pesto/test_data/atom/partially_applied_2_lambda.pos: -------------------------------------------------------------------------------- 1 | { 2 | "line": 3, 3 | "column": 18 4 | } 5 | -------------------------------------------------------------------------------- /pesto/test_data/atom/trivial_lambda.expect: -------------------------------------------------------------------------------- 1 | Some(NixDocComment { content: Some("Docs"), count_applied: Some(0) }) -------------------------------------------------------------------------------- /pesto/test_data/atom/trivial_lambda.nix: -------------------------------------------------------------------------------- 1 | let 2 | /**Docs*/ 3 | # TODO: fix it later 4 | foo = x: x; 5 | in foo 6 | -------------------------------------------------------------------------------- /pesto/test_data/atom/trivial_lambda.pos: -------------------------------------------------------------------------------- 1 | { 2 | "line": 4, 3 | "column": 9 4 | } 5 | -------------------------------------------------------------------------------- /pesto/test_data/content_format/add.expect: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "name": "lib.add", 4 | "content": "\nReturn the sum of the numbers *e1* and *e2*.\n" 5 | }, 6 | { 7 | "name": "lib.trivial.add", 8 | "content": "\nReturn the sum of the numbers *e1* and *e2*.\n" 9 | }, 10 | { 11 | "name": "builtins.add", 12 | "content": "\nReturn the sum of the numbers *e1* and *e2*.\n" 13 | } 14 | ] -------------------------------------------------------------------------------- /pesto/test_data/content_format/add.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "docs": { 4 | "attr": { 5 | "position": { 6 | "column": 23, 7 | "file": "test_data/assets/default.nix", 8 | "line": 68 9 | } 10 | }, 11 | "lambda": { 12 | "args": ["e1", "e2"], 13 | "arity": 2, 14 | "content": "\n Return the sum of the numbers *e1* and *e2*.\n ", 15 | "experimental": false, 16 | "isPrimop": true, 17 | "name": "add", 18 | "position": null 19 | } 20 | }, 21 | "path": ["lib", "add"] 22 | }, 23 | { 24 | "docs": { 25 | "attr": { 26 | "position": { 27 | "column": 21, 28 | "file": "test_data/assets/trivial.nix", 29 | "line": 269 30 | } 31 | }, 32 | "lambda": { 33 | "args": ["e1", "e2"], 34 | "arity": 2, 35 | "content": "\n Return the sum of the numbers *e1* and *e2*.\n ", 36 | "experimental": false, 37 | "isPrimop": true, 38 | "name": "add", 39 | "position": null 40 | } 41 | }, 42 | "path": ["lib", "trivial", "add"] 43 | }, 44 | { 45 | "docs": { 46 | "attr": { "content": "", "position": null }, 47 | "lambda": { 48 | "content": "\n Return the sum of the numbers *e1* and *e2*.\n ", 49 | "countApplied": 0, 50 | "isPrimop": true, 51 | "position": null 52 | } 53 | }, 54 | "path": ["builtins", "add"] 55 | } 56 | ] 57 | -------------------------------------------------------------------------------- /pesto/test_data/content_format/foldl'.expect: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "name": "lib.lists.foldl'", 4 | "content": "\n Reduce a list by applying a binary operator from left to right,\n starting with an initial accumulator.\n Before each application of the operator, the accumulator value is evaluated.\n This behavior makes this function stricter than [`foldl`](#function-library-lib.lists.foldl).\n Unlike [`builtins.foldl'`](https://nixos.org/manual/nix/unstable/language/builtins.html#builtins-foldl'),\n the initial accumulator argument is evaluated before the first iteration.\n A call like\n ```nix\n foldl' op acc₀ [ x₀ x₁ x₂ ... xₙ₋₁ xₙ ]\n ```\n is (denotationally) equivalent to the following,\n but with the added benefit that `foldl'` itself will never overflow the stack.\n ```nix\n let\n acc₁ = builtins.seq acc₀ (op acc₀ x₀ );\n acc₂ = builtins.seq acc₁ (op acc₁ x₁ );\n acc₃ = builtins.seq acc₂ (op acc₂ x₂ );\n ...\n accₙ = builtins.seq accₙ₋₁ (op accₙ₋₁ xₙ₋₁);\n accₙ₊₁ = builtins.seq accₙ (op accₙ xₙ );\n in\n accₙ₊₁\n # Or ignoring builtins.seq\n op (op (... (op (op (op acc₀ x₀) x₁) x₂) ...) xₙ₋₁) xₙ\n ```\n\n # Example\n\n ```nix\n foldl' (acc: x: acc + x) 0 [1 2 3]\n => 6\n ```\n\n # Type\n\n ```\n foldl' :: (acc -> x -> acc) -> acc -> [x] -> acc\n ```\n\n # Arguments\n\n - [op] The binary operation to run, where the two arguments are:\n\n1. `acc`: The current accumulator value: Either the initial one for the first iteration, or the result of the previous iteration\n2. `x`: The corresponding list element for this iteration\n - [acc] The initial accumulator value\n - [list] The list to fold\n\n" 5 | } 6 | ] -------------------------------------------------------------------------------- /pesto/test_data/content_format/foldl'.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "docs": { 4 | "attr": { 5 | "position": { 6 | "column": 3, 7 | "file": "test_data/assets/lib/lists.nix", 8 | "line": 198 9 | } 10 | }, 11 | "lambda": { 12 | "isPrimop": false, 13 | "position": { 14 | "column": 5, 15 | "file": "test_data/assets/lib/lists.nix", 16 | "line": 204 17 | } 18 | } 19 | }, 20 | "path": ["lib", "lists", "foldl'"] 21 | } 22 | ] 23 | -------------------------------------------------------------------------------- /pesto/test_data/inheritance/add.expect: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "name": "lib.add", 4 | "source": "lib.add" 5 | }, 6 | { 7 | "name": "lib.trivial.add", 8 | "source": "lib.trivial.add" 9 | }, 10 | { 11 | "name": "builtins.add", 12 | "source": "builtins.add" 13 | } 14 | ] -------------------------------------------------------------------------------- /pesto/test_data/inheritance/add.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "docs": { 4 | "attr": { 5 | "position": { 6 | "column": 23, 7 | "file": "test_data/assets/default.nix", 8 | "line": 68 9 | } 10 | }, 11 | "lambda": { 12 | "args": ["e1", "e2"], 13 | "arity": 2, 14 | "content": "\n Return the sum of the numbers *e1* and *e2*.\n ", 15 | "experimental": false, 16 | "isPrimop": true, 17 | "name": "add", 18 | "position": null 19 | } 20 | }, 21 | "path": ["lib", "add"] 22 | }, 23 | { 24 | "docs": { 25 | "attr": { 26 | "position": { 27 | "column": 21, 28 | "file": "test_data/assets/trivial.nix", 29 | "line": 269 30 | } 31 | }, 32 | "lambda": { 33 | "args": ["e1", "e2"], 34 | "arity": 2, 35 | "content": "\n Return the sum of the numbers *e1* and *e2*.\n ", 36 | "experimental": false, 37 | "isPrimop": true, 38 | "name": "add", 39 | "position": null 40 | } 41 | }, 42 | "path": ["lib", "trivial", "add"] 43 | }, 44 | { 45 | "docs": { 46 | "attr": { "content": "", "position": null }, 47 | "lambda": { 48 | "content": "\n Return the sum of the numbers *e1* and *e2*.\n ", 49 | "countApplied": 0, 50 | "isPrimop": true, 51 | "position": null 52 | } 53 | }, 54 | "path": ["builtins", "add"] 55 | } 56 | ] 57 | -------------------------------------------------------------------------------- /pesto/test_data/inheritance/catAttrs.expect: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "name": "builtins.catAttrs", 4 | "source": "lib.attrsets.catAttrs" 5 | }, 6 | { 7 | "name": "lib.catAttrs", 8 | "source": "lib.attrsets.catAttrs" 9 | }, 10 | { 11 | "name": "lib.attrsets.catAttrs", 12 | "source": "lib.attrsets.catAttrs" 13 | } 14 | ] -------------------------------------------------------------------------------- /pesto/test_data/inheritance/catAttrs.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "docs": { 4 | "attr": { 5 | "position": null 6 | }, 7 | "lambda": { 8 | "args": ["attr", "list"], 9 | "arity": 2, 10 | "content": "\n Collect each attribute named *attr* from a list of attribute\n sets. Attrsets that don't contain the named attribute are\n ignored. For example,\n\n ```nix\n builtins.catAttrs \"a\" [{a = 1;} {b = 0;} {a = 2;}]\n ```\n\n evaluates to `[1 2]`.\n ", 11 | "countApplied": 0, 12 | "experimental": false, 13 | "isPrimop": true, 14 | "name": "catAttrs", 15 | "position": null 16 | } 17 | }, 18 | "path": ["builtins", "catAttrs"] 19 | }, 20 | { 21 | "docs": { 22 | "attr": { 23 | "position": { 24 | "column": 28, 25 | "file": "test_data/assets/lib/default.nix", 26 | "line": 82 27 | } 28 | }, 29 | "lambda": { 30 | "args": ["attr", "list"], 31 | "arity": 2, 32 | "content": "\n Collect each attribute named *attr* from a list of attribute\n sets. Attrsets that don't contain the named attribute are\n ignored. For example,\n\n ```nix\n builtins.catAttrs \"a\" [{a = 1;} {b = 0;} {a = 2;}]\n ```\n\n evaluates to `[1 2]`.\n ", 33 | "countApplied": 0, 34 | "experimental": false, 35 | "isPrimop": true, 36 | "name": "catAttrs", 37 | "position": null 38 | } 39 | }, 40 | "path": ["lib", "catAttrs"] 41 | }, 42 | { 43 | "docs": { 44 | "attr": { 45 | "position": { 46 | "column": 3, 47 | "file": "test_data/assets/lib/attrsets.nix", 48 | "line": 398 49 | } 50 | }, 51 | "lambda": { 52 | "args": ["attr", "list"], 53 | "arity": 2, 54 | "content": "\n Collect each attribute named *attr* from a list of attribute\n sets. Attrsets that don't contain the named attribute are\n ignored. For example,\n\n ```nix\n builtins.catAttrs \"a\" [{a = 1;} {b = 0;} {a = 2;}]\n ```\n\n evaluates to `[1 2]`.\n ", 55 | "countApplied": 0, 56 | "experimental": false, 57 | "isPrimop": true, 58 | "name": "catAttrs", 59 | "position": null 60 | } 61 | }, 62 | "path": ["lib", "attrsets", "catAttrs"] 63 | } 64 | ] 65 | -------------------------------------------------------------------------------- /pesto/test_data/inheritance/concatStrings.expect: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "name": "pkgs.lib.strings.concatStrings", 4 | "source": "pkgs.lib.strings.concatStrings" 5 | } 6 | ] -------------------------------------------------------------------------------- /pesto/test_data/inheritance/concatStrings.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "docs": { 4 | "attr": { 5 | "position": { 6 | "column": 3, 7 | "file": "test_data/assets/strings.nix", 8 | "line": 60 9 | } 10 | }, 11 | "lambda": { 12 | "content": "\n Concatenate a list of strings with a separator between each\n element, e.g. `concatStringsSep \"/\" [\"usr\" \"local\" \"bin\"] ==\n \"usr/local/bin\"`.\n ", 13 | "countApplied": 1, 14 | "isPrimop": true, 15 | "position": null 16 | } 17 | }, 18 | "path": ["pkgs", "lib", "strings", "concatStrings"] 19 | } 20 | ] 21 | -------------------------------------------------------------------------------- /pesto/test_data/inheritance/foldl.expect: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "name": "lib.foldl'", 4 | "source": "lib.lists.foldl'" 5 | }, 6 | { 7 | "name": "lib.lists.foldl'", 8 | "source": "lib.lists.foldl'" 9 | }, 10 | { 11 | "name": "builtins.foldl'", 12 | "source": "builtins.foldl'" 13 | } 14 | ] -------------------------------------------------------------------------------- /pesto/test_data/inheritance/foldl.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "docs": { 4 | "attr": { 5 | "position": { 6 | "column": 25, 7 | "file": "test_data/assets/default.nix", 8 | "line": 92 9 | } 10 | }, 11 | "lambda": { 12 | "isPrimop": false, 13 | "position": { 14 | "column": 5, 15 | "file": "test_data/assets/lists.nix", 16 | "line": 204 17 | } 18 | } 19 | }, 20 | "path": ["lib", "foldl'"] 21 | }, 22 | { 23 | "docs": { 24 | "attr": { 25 | "position": { 26 | "column": 3, 27 | "file": "test_data/assets/lists.nix", 28 | "line": 198 29 | } 30 | }, 31 | "lambda": { 32 | "isPrimop": false, 33 | "position": { 34 | "column": 5, 35 | "file": "test_data/assets/lists.nix", 36 | "line": 204 37 | } 38 | } 39 | }, 40 | "path": ["lib", "lists", "foldl'"] 41 | }, 42 | { 43 | "docs": { 44 | "attr": { "position": null }, 45 | "lambda": { 46 | "args": ["op", "nul", "list"], 47 | "arity": 3, 48 | "content": "\n Reduce a list by applying a binary operator, from left to right,\n e.g. `foldl' op nul [x0 x1 x2 ...] : op (op (op nul x0) x1) x2)\n ...`. For example, `foldl' (x: y: x + y) 0 [1 2 3]` evaluates to 6.\n The return value of each application of `op` is evaluated immediately,\n even for intermediate values.\n ", 49 | "experimental": false, 50 | "isPrimop": true, 51 | "name": "foldl'", 52 | "position": null 53 | } 54 | }, 55 | "path": ["builtins", "foldl'"] 56 | } 57 | ] 58 | -------------------------------------------------------------------------------- /pesto/test_data/inheritance/strings.expect: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "name": "lib.strings.concatLines", 4 | "source": "lib.strings.concatLines" 5 | }, 6 | { 7 | "name": "lib.concatLines", 8 | "source": "lib.strings.concatLines" 9 | } 10 | ] -------------------------------------------------------------------------------- /pesto/test_data/inheritance/strings.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "docs": { 4 | "attr": { 5 | "position": { 6 | "column": 3, 7 | "file": "test_data/assets/strings.nix", 8 | "line": 243 9 | } 10 | }, 11 | "lambda": { 12 | "isPrimop": false, 13 | "position": { 14 | "column": 25, 15 | "file": "test_data/assets/strings.nix", 16 | "line": 84 17 | } 18 | } 19 | }, 20 | "path": ["lib", "strings", "concatLines"] 21 | }, 22 | { 23 | "docs": { 24 | "attr": { 25 | "position": { 26 | "column": 27, 27 | "file": "test_data/assets/default.nix", 28 | "line": 98 29 | } 30 | }, 31 | "lambda": { 32 | "isPrimop": false, 33 | "position": { 34 | "column": 25, 35 | "file": "test_data/assets/strings.nix", 36 | "line": 84 37 | } 38 | } 39 | }, 40 | "path": ["lib", "concatLines"] 41 | } 42 | ] 43 | -------------------------------------------------------------------------------- /pesto/test_data/makeOverridable/test.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "docs": { 4 | "attr": { 5 | "position": { 6 | "column": 3, 7 | "file": "/nix/store/sv1ix2lrwxbflx43b1pqbpj5y1fm5frk-nixpkgs-migrated/pkgs/top-level/all-packages.nix", 8 | "line": 937 9 | } 10 | }, 11 | "lambda": { 12 | "countApplied": 1, 13 | "isFunctor": true, 14 | "isPrimop": false, 15 | "position": { 16 | "column": 17, 17 | "file": "/nix/store/sv1ix2lrwxbflx43b1pqbpj5y1fm5frk-nixpkgs-migrated/lib/customisation.nix", 18 | "line": 136 19 | } 20 | } 21 | }, 22 | "path": ["pkgs", "fetchgit"] 23 | }, 24 | { 25 | "docs": { 26 | "attr": { 27 | "position": { 28 | "column": 3, 29 | "file": "/nix/store/sv1ix2lrwxbflx43b1pqbpj5y1fm5frk-nixpkgs-migrated/pkgs/top-level/all-packages.nix", 30 | "line": 922 31 | } 32 | }, 33 | "lambda": { 34 | "countApplied": 1, 35 | "isFunctor": true, 36 | "isPrimop": false, 37 | "position": { 38 | "column": 17, 39 | "file": "/nix/store/sv1ix2lrwxbflx43b1pqbpj5y1fm5frk-nixpkgs-migrated/lib/customisation.nix", 40 | "line": 136 41 | } 42 | } 43 | }, 44 | "path": ["pkgs", "fetchcvs"] 45 | }, 46 | { 47 | "docs": { 48 | "attr": { 49 | "position": { 50 | "column": 3, 51 | "file": "/nix/store/qivk4lp6jhrfrdxlncnkdyg2aza6d83d-nixpkgs-migrated/pkgs/top-level/all-packages.nix", 52 | "line": 1181 53 | } 54 | }, 55 | "lambda": { 56 | "countApplied": 1, 57 | "isFunctor": true, 58 | "isPrimop": false, 59 | "position": { 60 | "column": 17, 61 | "file": "/nix/store/qivk4lp6jhrfrdxlncnkdyg2aza6d83d-nixpkgs-migrated/lib/customisation.nix", 62 | "line": 136 63 | } 64 | } 65 | }, 66 | "path": ["pkgs", "fetchFromGitHub"] 67 | } 68 | ] 69 | -------------------------------------------------------------------------------- /pesto/test_data/types/basic.expect: -------------------------------------------------------------------------------- 1 | Some( 2 | "foo :: String -> Bool\n", 3 | ) -------------------------------------------------------------------------------- /pesto/test_data/types/basic.md: -------------------------------------------------------------------------------- 1 | # Type 2 | 3 | ```typed-nix 4 | foo :: String -> Bool 5 | ``` 6 | -------------------------------------------------------------------------------- /pesto/test_data/types/many.expect: -------------------------------------------------------------------------------- 1 | Some( 2 | "foo :: String -> Bool\n", 3 | ) -------------------------------------------------------------------------------- /pesto/test_data/types/many.md: -------------------------------------------------------------------------------- 1 | # no type 2 | 3 | ```typed-nix 4 | Not shown 5 | ``` 6 | 7 | # type 8 | 9 | ```typed-nix 10 | foo :: String -> Bool 11 | ``` 12 | -------------------------------------------------------------------------------- /pesto/test_data/types/nested.expect: -------------------------------------------------------------------------------- 1 | Some( 2 | "foo :: { foo :: a} -> a\n", 3 | ) -------------------------------------------------------------------------------- /pesto/test_data/types/nested.md: -------------------------------------------------------------------------------- 1 | ## Example 2 | 3 | Lorem ipsum 4 | 5 | ## Some other type heading 6 | 7 | Lorem ipsum 8 | 9 | # Invalid H1 10 | 11 | Lorem ipsum 12 | 13 | ## Type 14 | 15 | Lorem ipsum 16 | 17 | - Item1 18 | - Item2 19 | 20 | ``` 21 | foo :: { foo :: a} -> a 22 | ``` 23 | 24 | ``` 25 | irrelevant 26 | ``` 27 | -------------------------------------------------------------------------------- /preCommit.nix: -------------------------------------------------------------------------------- 1 | { self, ... }: { 2 | perSystem = 3 | { pkgs 4 | , self' 5 | , system 6 | , ... 7 | }: 8 | let 9 | formatters = with pkgs; [ 10 | nixfmt 11 | nodePackages.prettier #3.0.0 installed over nixpkgs 12 | rustfmt 13 | ]; 14 | in 15 | { 16 | checks.pre-commit-check = self.inputs.pre-commit-hooks.lib.${system}.run { 17 | src = ./.; 18 | hooks = { 19 | treefmt.enable = true; 20 | statix.enable = true; 21 | }; 22 | excludes = [ "indexer/test" ".github" "scripts/data" "test_data" ]; 23 | settings = { 24 | statix.ignore = [ "indexer/test" "test_data" ]; 25 | nixfmt.width = 80; 26 | treefmt.package = pkgs.writeShellApplication { 27 | name = "treefmt"; 28 | runtimeInputs = 29 | [ 30 | pkgs.treefmt 31 | ] 32 | ++ formatters; 33 | text = '' 34 | exec treefmt "$@" 35 | ''; 36 | }; 37 | }; 38 | }; 39 | }; 40 | } 41 | -------------------------------------------------------------------------------- /projects.toml: -------------------------------------------------------------------------------- 1 | # projects.toml file describing inputs for dream2nix 2 | # 3 | # To re-generate this file, run: 4 | # nix run .#detect-projects $source 5 | # ... where `$source` points to the source of your project. 6 | # 7 | # If the local flake is unavailable, alternatively execute the app from the 8 | # upstream dream2nix flake: 9 | # nix run github:nix-community/dream2nix#detect-projects $source 10 | 11 | [noogle] 12 | name = "noogle" 13 | relPath = "website" 14 | subsystem = "nodejs" 15 | translator = "package-lock" 16 | builder = "strict-builder" 17 | translators = ["package-lock", "package-json"] 18 | 19 | [noogle.subsystemInfo] 20 | nodejs = 18 21 | 22 | [indexer] 23 | name = "indexer" 24 | relPath = "indexer" 25 | subsystem = "rust" 26 | translator = "cargo-lock" 27 | translators = ["cargo-lock", "cargo-toml"] 28 | 29 | [indexer.subsystemInfo] 30 | workspaceMembers = [] 31 | [[indexer.subsystemInfo.crates]] 32 | name = "indexer" 33 | relPath = "indexer" 34 | version = "0.1.0" 35 | 36 | [builtins-data] 37 | name = "builtins-data" 38 | relPath = "scripts" 39 | subsystem = "nodejs" 40 | translator = "package-lock" 41 | builder = "strict-builder" 42 | translators = ["package-lock", "package-json"] 43 | 44 | [builtins-data.subsystemInfo] 45 | nodejs = 18 46 | 47 | 48 | [tests] 49 | name = "tests" 50 | relPath = "tests" 51 | subsystem = "nodejs" 52 | translator = "package-lock" 53 | builder = "strict-builder" 54 | translators = ["package-lock", "package-json"] 55 | 56 | [tests.subsystemInfo] 57 | nodejs = 18 58 | -------------------------------------------------------------------------------- /salt/README.md: -------------------------------------------------------------------------------- 1 | # Some salt for our noodles 2 | 3 | Unfortunately, not all functions have all data. 4 | 5 | Some locally defined content 6 | 7 | - type declarations of all builtins. 8 | -------------------------------------------------------------------------------- /salt/flake-module.nix: -------------------------------------------------------------------------------- 1 | { inputs, ... }: { 2 | perSystem = { self', inputs', pkgs, system, ... }: 3 | let 4 | nix-manual = "${inputs.nix-master}/doc/manual/source/language/derivations.md"; 5 | # pkgs = import inputs.nixpkgs-master { inherit system; }; 6 | nix = inputs'.nix-master.packages.nix-cli; 7 | 8 | sourceInfo' = { 9 | inherit (inputs.nix-master.sourceInfo) rev lastModified; 10 | }; 11 | metaFile = builtins.toFile "meta.json" (builtins.toJSON sourceInfo'); 12 | nix-meta = pkgs.stdenv.mkDerivation { 13 | name = "salt-meta"; 14 | src = ./.; 15 | buildPhase = '' 16 | cat ${metaFile} > $out 17 | ''; 18 | }; 19 | 20 | 21 | # https://github.com/NixOS/nix/blob/master/doc/manual/src/language/derivations.md 22 | salt = pkgs.stdenv.mkDerivation { 23 | pname = "salt-data"; 24 | version = "0.1.0"; 25 | src = ./src; 26 | installPhase = '' 27 | mkdir $out 28 | cp -rf . $out 29 | cp ${nix-manual} $out 30 | 31 | ${nix}/bin/nix __dump-language > $out/language.json 32 | ''; 33 | }; 34 | in 35 | { 36 | packages = { 37 | inherit salt nix-meta; 38 | }; 39 | }; 40 | } 41 | -------------------------------------------------------------------------------- /salt/src/manual-link.map.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "id": "derivation", 4 | "file": "derivations.md" 5 | } 6 | ] 7 | -------------------------------------------------------------------------------- /tests/.gitignore: -------------------------------------------------------------------------------- 1 | 2 | node_modules 3 | data/* -------------------------------------------------------------------------------- /tests/data.test.js: -------------------------------------------------------------------------------- 1 | import libData from "./data/lib.json"; 2 | import trivialBuilders from "./data/trivial-builders.json"; 3 | import builtins from "./data/builtins.json"; 4 | 5 | it("has not changed lib data", () => { 6 | expect(libData).toMatchSnapshot(); 7 | }); 8 | it("has not changed trivial-builders data", () => { 9 | expect(trivialBuilders).toMatchSnapshot(); 10 | }); 11 | it("has not changed builtins data", () => { 12 | expect(builtins).toMatchSnapshot(); 13 | }); 14 | -------------------------------------------------------------------------------- /tests/jest.config.js: -------------------------------------------------------------------------------- 1 | /** @type {import('jest').Config} */ 2 | 3 | import { defaults } from "jest-config"; 4 | 5 | const config = { 6 | ...defaults, 7 | // transform: {}, 8 | }; 9 | 10 | export default config; 11 | -------------------------------------------------------------------------------- /tests/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "tests", 3 | "version": "1.0.0", 4 | "description": "", 5 | "module": "index.js", 6 | "type": "module", 7 | "scripts": { 8 | "test": "NODE_OPTIONS=--experimental-vm-modules npx jest" 9 | }, 10 | "author": "", 11 | "license": "ISC", 12 | "devDependencies": { 13 | "jest": "^29.4.3" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /treefmt.toml: -------------------------------------------------------------------------------- 1 | [formatter.nix] 2 | command = "nixpkgs-fmt" 3 | includes = ["*.nix"] 4 | excludes = ["*/test_data/*"] 5 | -------------------------------------------------------------------------------- /website/.envrc: -------------------------------------------------------------------------------- 1 | source_up 2 | 3 | files=(../../flake.nix flake-module.nix package-lock.json) 4 | if type nix_direnv_watch_file &>/dev/null; then 5 | nix_direnv_watch_file "${files[@]}" 6 | else 7 | watch_file "${files[@]}" 8 | fi 9 | 10 | use flake .#ui --builders '' 11 | -------------------------------------------------------------------------------- /website/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "next/core-web-vitals", 3 | "rules": { 4 | "originalKeywordKind": "off" 5 | } 6 | } -------------------------------------------------------------------------------- /website/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | node_modules 5 | .pnp 6 | .pnp.js 7 | 8 | # testing 9 | coverage 10 | src/models/data/* 11 | !src/models/data/index.ts 12 | 13 | src/fonts/* 14 | !src/fonts/index 15 | 16 | 17 | # nix 18 | .direnv/ 19 | 20 | 21 | # next.js 22 | /.next/ 23 | /out/ 24 | 25 | # production 26 | /build 27 | 28 | # misc 29 | .DS_Store 30 | *.pem 31 | result 32 | result-* 33 | 34 | # debug 35 | npm-debug.log* 36 | yarn-debug.log* 37 | yarn-error.log* 38 | .pnpm-debug.log* 39 | 40 | # local env files 41 | .env*.local 42 | 43 | # vercel 44 | .vercel 45 | 46 | # typescript 47 | *.tsbuildinfo 48 | next-env.d.ts 49 | -------------------------------------------------------------------------------- /website/.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "typescript.tsdk": "node_modules/typescript/lib" 3 | } -------------------------------------------------------------------------------- /website/createEmotionCache.ts: -------------------------------------------------------------------------------- 1 | import createCache from "@emotion/cache"; 2 | 3 | const createEmotionCache = () => { 4 | return createCache({ key: "css", prepend: true }); 5 | }; 6 | 7 | export default createEmotionCache; 8 | -------------------------------------------------------------------------------- /website/default.nix: -------------------------------------------------------------------------------- 1 | { pkgs, hooks, nodejs }: 2 | 3 | pkgs.buildNpmPackage { 4 | pname = "noogle"; 5 | version = "0.1.0"; 6 | src = ./.; 7 | 8 | inherit nodejs; 9 | 10 | npmDeps = pkgs.importNpmLock { 11 | npmRoot = ./.; 12 | }; 13 | 14 | preConfigure = hooks.prepare; 15 | 16 | postBuild = '' 17 | npx next-sitemap 18 | ''; 19 | 20 | installPhase = '' 21 | runHook preInstall 22 | npx pagefind --site ./out 23 | mv out $out 24 | runHook postInstall 25 | ''; 26 | 27 | npmConfigHook = pkgs.importNpmLock.npmConfigHook; 28 | } 29 | -------------------------------------------------------------------------------- /website/flake-module.nix: -------------------------------------------------------------------------------- 1 | { ... }: { 2 | perSystem = { self', pkgs, ... }: 3 | let 4 | nodejs = pkgs.nodejs_20; 5 | 6 | hooks = { 7 | prepare = 8 | let 9 | data_path = "src/models/data"; 10 | fonts_path = "src/fonts"; 11 | in 12 | '' 13 | # New data 14 | cp -f ${self'.packages.data-json} ${data_path}/data.json 15 | cp -f ${self'.packages.pasta-meta} ${data_path}/lib-meta.json 16 | cp -f ${self'.packages.nix-meta} ${data_path}/nix-meta.json 17 | cp -rf ${self'.packages.salt}/* ${data_path} 18 | chmod -R +w ${data_path} 19 | 20 | # Website fonts 21 | echo "Copying fonts (1/2)..." 22 | cp -rf ${pkgs.inter}/share/fonts/truetype/* ${fonts_path} 23 | echo "Copying fonts (2/2)..." 24 | cp -rf ${pkgs.fira-code}/share/fonts/truetype/* ${fonts_path} 25 | chmod -R +w ${fonts_path} 26 | ''; 27 | }; 28 | base = pkgs.callPackage ./default.nix { inherit nodejs hooks; }; 29 | in 30 | { 31 | packages = { ui = base; }; 32 | devShells.ui = pkgs.callPackage ./shell.nix { 33 | inherit pkgs hooks nodejs; 34 | inherit (self'.packages) data-json pasta-meta; 35 | }; 36 | }; 37 | } 38 | -------------------------------------------------------------------------------- /website/next-sitemap.config.js: -------------------------------------------------------------------------------- 1 | /** @type {import('next-sitemap').IConfig} */ 2 | module.exports = { 3 | output: "export", 4 | siteUrl: "https://noogle.dev", 5 | generateRobotsTxt: true, // (optional) 6 | changefreq: "daily", 7 | }; 8 | -------------------------------------------------------------------------------- /website/next.config.mjs: -------------------------------------------------------------------------------- 1 | import rehypeHighlight from "rehype-highlight"; 2 | import bash from "highlight.js/lib/languages/bash"; 3 | import haskell from "highlight.js/lib/languages/haskell"; 4 | import nix from "highlight.js/lib/languages/nix"; 5 | import mdx from "@next/mdx"; 6 | import remarkGfm from "remark-gfm"; 7 | 8 | const withMDX = mdx({ 9 | options: { 10 | remarkPlugins: [remarkGfm], 11 | rehypePlugins: [ 12 | [ 13 | rehypeHighlight, 14 | { 15 | detect: true, 16 | languages: { nix, haskell, bash, default: nix }, 17 | }, 18 | ], 19 | ], 20 | }, 21 | }); 22 | 23 | /** @type {import('next').NextConfig} */ 24 | const nextConfig = { 25 | pageExtensions: ["js", "jsx", "mdx", "ts", "tsx"], 26 | compress: true, 27 | optimizeFonts: true, 28 | output: "export", 29 | reactStrictMode: true, 30 | swcMinify: true, 31 | images: { 32 | loader: "custom", 33 | }, 34 | }; 35 | 36 | // module.exports = nextConfig; 37 | export default withMDX(nextConfig); 38 | -------------------------------------------------------------------------------- /website/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "noogle", 3 | "version": "0.1.0", 4 | "private": true, 5 | "scripts": { 6 | "dev": "next dev", 7 | "build": "next build", 8 | "start": "next start", 9 | "lint": "next lint", 10 | "build:all": "npm run build && npx pagefind -s ./out" 11 | }, 12 | "dependencies": { 13 | "@emotion/cache": "^11.11.0", 14 | "@emotion/react": "^11.10.5", 15 | "@emotion/styled": "^11.10.5", 16 | "@fontsource/roboto": "^5.0.0", 17 | "@jsdevtools/rehype-toc": "^3.0.2", 18 | "@mdx-js/loader": "^3.0.0", 19 | "@mdx-js/react": "^3.0.0", 20 | "@mui/icons-material": "^5.10.9", 21 | "@mui/material": "^5.10.13", 22 | "@mui/material-nextjs": "^5.15.0", 23 | "@next/mdx": "^14.0.4", 24 | "@types/mdx": "^2.0.10", 25 | "@vcarl/remark-headings": "^0.1.0", 26 | "axios": "^1.7.2", 27 | "date-fns": "^3.6.0", 28 | "hast": "^1.0.0", 29 | "hast-util-to-string": "^3.0.0", 30 | "highlight.js": "^11.7.0", 31 | "minisearch": "^6.3.0", 32 | "next": "^14.1.2", 33 | "next-mdx-remote": "^4.4.1", 34 | "next-sitemap": "^4.2.3", 35 | "notistack": "^3.0.0", 36 | "pagefind": "^1.0.4", 37 | "parse5": "^7.1.2", 38 | "react": "^18.2.0", 39 | "react-dom": "^18.2.0", 40 | "react-highlight": "^0.15.0", 41 | "react-hot-toast": "^2.4.1", 42 | "react-mark.js": "^9.0.7", 43 | "react-markdown": "^9.0.0", 44 | "react-minisearch": "^6.0.2", 45 | "rehype": "^13.0.1", 46 | "rehype-autolink-headings": "^7.1.0", 47 | "rehype-highlight": "^7.0.0", 48 | "rehype-slug": "^6.0.0", 49 | "rehype-stringify": "^10.0.0", 50 | "remark-definition-list": "^2.0.0", 51 | "remark-directive": "^3.0.0", 52 | "remark-frontmatter": "^5.0.0", 53 | "remark-gfm": "^4.0.0", 54 | "remark-heading-id": "^1.0.1", 55 | "remark-parse": "^11.0.0", 56 | "remark-rehype": "^11.0.0", 57 | "remark-stringify": "^11.0.0", 58 | "remark-unlink": "^5.0.0", 59 | "seedrandom": "^3.0.5", 60 | "unified": "^11.0.4", 61 | "unist-util-visit": "^5.0.0", 62 | "usehooks-ts": "^2.9.1" 63 | }, 64 | "devDependencies": { 65 | "@types/node": "18.18.1", 66 | "@types/react": "^18.0.25", 67 | "@types/react-dom": "18.2.8", 68 | "@types/react-highlight": "^0.12.5", 69 | "@types/seedrandom": "^3.0.4", 70 | "@typescript-eslint/eslint-plugin": "^6.7.3", 71 | "@typescript-eslint/parser": "^6.7.3", 72 | "eslint": "8.50.0", 73 | "eslint-config-next": "^14.0.3" 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /website/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nix-community/noogle/a28bf7d00258ea18d43ac8ef0cf0429fe4432fe9/website/public/favicon.ico -------------------------------------------------------------------------------- /website/public/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nix-community/noogle/a28bf7d00258ea18d43ac8ef0cf0429fe4432fe9/website/public/favicon.png -------------------------------------------------------------------------------- /website/public/google_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nix-community/noogle/a28bf7d00258ea18d43ac8ef0cf0429fe4432fe9/website/public/google_logo.png -------------------------------------------------------------------------------- /website/public/search.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | Noogle 5 | Search for nix functions by name. 6 | UTF-8 7 | https://noogle.dev/favicon.png 8 | 9 | https://noogle.dev 10 | 11 | -------------------------------------------------------------------------------- /website/public/vercel.svg: -------------------------------------------------------------------------------- 1 | 3 | 4 | -------------------------------------------------------------------------------- /website/shell.nix: -------------------------------------------------------------------------------- 1 | { mkShell, importNpmLock, nodejs, hooks, ... }: 2 | 3 | mkShell { 4 | packages = [ 5 | importNpmLock.hooks.linkNodeModulesHook 6 | nodejs 7 | ]; 8 | 9 | npmDeps = importNpmLock.buildNodeModules { 10 | npmRoot = ./.; 11 | inherit nodejs; 12 | }; 13 | 14 | preConfigure = hooks.prepare; 15 | 16 | shellHook = '' 17 | export PATH="$PATH:$(realpath ./node_modules)/.bin" 18 | ''; 19 | } 20 | -------------------------------------------------------------------------------- /website/src/app/api/v1/data/route.ts: -------------------------------------------------------------------------------- 1 | import { data, builtinTypes, upstreamInfo, nixInfo } from "@/models/data"; 2 | 3 | export async function GET(request: Request) { 4 | return Response.json({ data, builtinTypes, upstreamInfo, nixInfo }); 5 | } 6 | -------------------------------------------------------------------------------- /website/src/app/f/[...path]/layout.tsx: -------------------------------------------------------------------------------- 1 | import { FilterProvider } from "@/components/layout/filterContext"; 2 | import { Header } from "@/components/layout/header"; 3 | import { Container } from "@mui/material"; 4 | import { ReactNode, Suspense } from "react"; 5 | import { SearchInput } from "@/components/searchInput"; 6 | 7 | export default function SearchLayout({ 8 | children, 9 | params, 10 | }: { 11 | children: ReactNode; 12 | params: { path: string[] }; 13 | }) { 14 | return ( 15 | <> 16 | 17 | 18 |
} /> 19 | 20 | 21 | 34 | {children} 35 | 36 | 37 | ); 38 | } 39 | -------------------------------------------------------------------------------- /website/src/app/layout.tsx: -------------------------------------------------------------------------------- 1 | import "../styles/globals.css"; 2 | import { AppRouterCacheProvider } from "@mui/material-nextjs/v13-appRouter"; 3 | import localFont from "next/font/local"; 4 | import { ClientSideLayoutContext } from "@/components/ClientSideLayoutContext"; 5 | import { Metadata } from "next"; 6 | 7 | export const metadata: Metadata = { 8 | title: "Noogle - Simply find Nix API reference documentation.", 9 | description: 10 | "Nix API reference. Includes nix, nixpkgs and nixos. Search nix functions within the nix ecosystem based on type, name, description, example, category and more.", 11 | creator: "@hsjobeki", 12 | abstract: "Nix and NixOS API Documentation", 13 | robots: { index: true, notranslate: true, nocache: true }, 14 | icons: "/favicon.png", 15 | }; 16 | 17 | const inter = localFont({ 18 | src: "../fonts/InterVariable.ttf", 19 | display: "swap", 20 | }); 21 | 22 | export default function RootLayout({ 23 | children, 24 | }: { 25 | children: React.ReactNode; 26 | }) { 27 | return ( 28 | 29 | 30 | {/* */} 31 | 37 | 38 | 39 | 44 | 45 | {/* */} 46 | {children} 47 | 48 | 49 | 50 | 51 | ); 52 | } 53 | -------------------------------------------------------------------------------- /website/src/app/md/documentation/page.mdx: -------------------------------------------------------------------------------- 1 | # Contribute Documentation 2 | 3 | Writing good documentation is hard. Any contribution towards having a better documentation is highly profitable. Thank you a lot for reading this tutorial. 4 | 5 | ## Doc-comments 6 | 7 | Doc-comments, short for documentation comments, are special comments in source code that are specifically formatted to provide documentation for the 8 | associated code. 9 | 10 | These comments serve as a source of reference documentation for noogle, 11 | offering valuable information about the purpose, functionality, and usage of the code elements they document. 12 | 13 | ## Placement 14 | 15 | Please place your doc-comments as shown below. 16 | 17 | ```nix 18 | /**Doc comment for foo*/ 19 | foo = x: x; 20 | ``` 21 | 22 | Sometimes the placement shown above wont work out. 23 | In any case you can place the documentation directly before the lamba. (only whitespace allowed) 24 | 25 | ```nix 26 | /**Doc comment*/ 27 | x: x; 28 | ``` 29 | 30 | **For contributing to [nixpkgs]() check their documentation [contributing guide](https://github.com/NixOS/nixpkgs/blob/master/doc/README.md)** 31 | -------------------------------------------------------------------------------- /website/src/app/md/layout.tsx: -------------------------------------------------------------------------------- 1 | import { HighlightBaseline } from "@/components/HighlightBaseline"; 2 | import { FilterProvider } from "@/components/layout/filterContext"; 3 | import { Header } from "@/components/layout/header"; 4 | import { SearchInput } from "@/components/searchInput"; 5 | import { Container } from "@mui/material"; 6 | import { ReactNode, Suspense } from "react"; 7 | 8 | export default function SearchLayout({ children }: { children: ReactNode }) { 9 | return ( 10 | <> 11 | 12 | 13 |
} /> 14 | 15 | 16 | 17 | 25 | {children} 26 | 27 | 28 | ); 29 | } 30 | -------------------------------------------------------------------------------- /website/src/app/md/tutorials/derivationStrict/page.md: -------------------------------------------------------------------------------- 1 | ## derivationStrict 2 | 3 | 🚧🚧🚧 under construction 🚧🚧🚧 4 | 5 | Is the fundamental primop that is used to bootstrap `builtins.derivation`. 6 | 7 | derivationStrict is usually not used anywhere else, unless you want to bootstrap your own fundamental derivation. 8 | 9 | derivation strict is a function that takes an attribute set of the following attributes 10 | 11 | and returns an attribute set, which can be used to bootstrap the nix build plane. 12 | The returned attribute set is not a derivation and cannot be built. 13 | 14 | A buildable derivation must contain at least the following attributes: 15 | 16 | TODO: 17 | -------------------------------------------------------------------------------- /website/src/app/md/tutorials/functors/page.mdx: -------------------------------------------------------------------------------- 1 | # Functors in nix 2 | 3 | **Functors combine functions and attribute sets** 4 | 5 | ## Understanding Functors 6 | 7 | A functor is a polymorphic data type that can represent both a 8 | **lambda function** (`x: x`) and an **attribute set** (`{ key = value; }`). 9 | 10 | This means that the Atribute set can hold data in the form of attributes. 11 | 12 | And also be a lambda function that can operate on that data. 13 | 14 | -> The lambda function can access the attributes of the attribute set often called `self`. 15 | 16 | ## Examples of Functors 17 | 18 | In the following example, `build` is both an attribute set and a lambda. 19 | `__functor` is a reserved attribute name that turns the attribute set `build` into a **functor**. 20 | 21 | ```nix 22 | { 23 | build = { 24 | foo = 1; 25 | __functor = self: _arg: self.foo; 26 | }; 27 | } 28 | ``` 29 | 30 | The attribute set `build` can now be used as a lambda via `function application`. 31 | 32 | ```nix 33 | nix-repl> build "linux" 34 | => 1 35 | ``` 36 | 37 | But at the same time `build` is still an Attribute set. 38 | 39 | ```nix 40 | nix-repl> build 41 | => { __functor = «lambda»; foo = 1; } 42 | ``` 43 | 44 | ## Applications of Functors 45 | 46 | Functors find practical applications including some in nixpkgs: 47 | 48 | - `lib.makeOverridable` 49 | - `lib.setFunctionArgs` 50 | - `lib.mirrorFunctionArgs` 51 | - `lib.types` and `lib.options` 52 | - and many more. 53 | 54 | ## When to use a functor 55 | 56 | (Noogle opinion) 57 | 58 | The use of functor should be avoided and is often **unnecessary**. 59 | 60 | Using them can add up in **complexity** and makes is hard to learn and maintain a certain piece of code. 61 | -------------------------------------------------------------------------------- /website/src/app/page.tsx: -------------------------------------------------------------------------------- 1 | import { Filter } from "@/components/filter"; 2 | import { FunctionOfTheDay } from "@/components/functionOfTheDay"; 3 | import { LandingPageLayout } from "@/components/layout"; 4 | import { FilterProvider } from "@/components/layout/filterContext"; 5 | import { SearchInput } from "@/components/searchInput"; 6 | import { Box, Typography, Link } from "@mui/material"; 7 | import type {} from "@mui/material/themeCssVarsAugmentation"; 8 | import localFont from "next/font/local"; 9 | import { Suspense } from "react"; 10 | 11 | const fira = localFont({ 12 | src: "../fonts/FiraCode-VF.ttf", 13 | display: "swap", 14 | }); 15 | 16 | export default function Home() { 17 | return ( 18 | 19 | 27 | 28 | 38 | Noogλe 39 | 40 | 41 | 42 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | ); 66 | } 67 | -------------------------------------------------------------------------------- /website/src/app/pkgs/layout.tsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | import { FilterProvider } from "@/components/layout/filterContext"; 3 | import { Header } from "@/components/layout/header"; 4 | import { PkgsSearch } from "@/components/searchInput/pkgsSearch"; 5 | import { Container } from "@mui/material"; 6 | import { ReactNode, Suspense } from "react"; 7 | 8 | export default function SearchLayout({ 9 | children, 10 | params, 11 | }: { 12 | children: ReactNode; 13 | params: { path: string[] }; 14 | }) { 15 | return ( 16 | <> 17 | 18 | 19 |
} /> 20 | 21 | 36 | {children} 37 | 38 | 39 | 40 | 41 | ); 42 | } 43 | -------------------------------------------------------------------------------- /website/src/app/q/layout.tsx: -------------------------------------------------------------------------------- 1 | import { FilterProvider } from "@/components/layout/filterContext"; 2 | import { Header } from "@/components/layout/header"; 3 | import { SearchInput } from "@/components/searchInput"; 4 | import { ReactNode, Suspense } from "react"; 5 | 6 | export default function SearchLayout({ children }: { children: ReactNode }) { 7 | return ( 8 | <> 9 | 10 | 11 |
} /> 12 | {children} 13 | 14 | 15 | 16 | ); 17 | } 18 | -------------------------------------------------------------------------------- /website/src/app/q/page.tsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | // import { PagefindSearch } from "@/components/Pagefind"; 3 | import { PagefindResults } from "@/components/PagefindResults"; 4 | // import { SearchResults } from "@/components/SearchResults"; 5 | import { LinearProgress } from "@mui/material"; 6 | import { Suspense } from "react"; 7 | 8 | export default function Q() { 9 | return ( 10 | }> 11 | 12 | {/* */} 13 | 14 | ); 15 | } 16 | -------------------------------------------------------------------------------- /website/src/client.ts: -------------------------------------------------------------------------------- 1 | import seedrandom from "seedrandom"; 2 | 3 | const date = new Date(); 4 | 5 | const dayOfYear = (date: Date) => { 6 | const diff = Number(date) - Number(new Date(date.getFullYear(), 0, 0)); 7 | return Math.floor(diff / 1000 / 60 / 60 / 24); 8 | }; 9 | 10 | const seed = dayOfYear(date).toString() + date.getFullYear().toString(); 11 | const rng = seedrandom(seed); 12 | const FOTD_RND = rng(); 13 | 14 | type Config = { 15 | init?: number; 16 | }; 17 | export function pseudoRandomIntInclusive( 18 | min: number, 19 | max: number, 20 | config?: Config 21 | ) { 22 | min = Math.ceil(min); 23 | max = Math.floor(max); 24 | const randomNumber = config?.init || FOTD_RND; 25 | return Math.floor(randomNumber * (max - min + 1) + min); // The maximum is inclusive and the minimum is inclusive 26 | } 27 | -------------------------------------------------------------------------------- /website/src/components/BackButton.tsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | import { ChevronLeft } from "@mui/icons-material"; 3 | import { IconButton } from "@mui/material"; 4 | import { useSessionStorage } from "usehooks-ts"; 5 | import { FilterOptions, useFilter } from "./layout/filterContext"; 6 | import { useRouter } from "next/navigation"; 7 | 8 | export const BackButton = () => { 9 | const [currentFilterOptions] = useSessionStorage( 10 | "currentFilterOptions", 11 | null 12 | ); 13 | const router = useRouter(); 14 | const { submit } = useFilter(); 15 | 16 | const handleBack = () => { 17 | if (currentFilterOptions !== null) { 18 | submit(currentFilterOptions); 19 | } else { 20 | router.push("/"); 21 | } 22 | }; 23 | return ( 24 | handleBack()} aria-label="Back"> 25 | 26 | 27 | ); 28 | }; 29 | -------------------------------------------------------------------------------- /website/src/components/ClientSideLayoutContext.tsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | import { CssBaseline } from "@mui/material"; 3 | import { cssThemeOptions } from "@/styles/theme"; 4 | import { ReactNode, useEffect, useState } from "react"; 5 | import { Toaster } from "react-hot-toast"; 6 | import { 7 | Experimental_CssVarsProvider as CssVarsProvider, 8 | experimental_extendTheme as extendTheme, 9 | getInitColorSchemeScript, 10 | useColorScheme, 11 | } from "@mui/material/styles"; 12 | 13 | const theme = extendTheme(cssThemeOptions); 14 | 15 | const ModeTracker = () => { 16 | const { setMode } = useColorScheme(); 17 | const [mounted, setMounted] = useState(false); 18 | 19 | useEffect( 20 | () => { 21 | setMounted(true); 22 | const persistedMode = localStorage.getItem("mui-mode"); 23 | if (!persistedMode) { 24 | setMode("dark"); 25 | } 26 | }, 27 | // eslint-disable-next-line react-hooks/exhaustive-deps 28 | [] 29 | ); 30 | 31 | if (!mounted) { 32 | // for server-side rendering 33 | // learn more at https://github.com/pacocoursey/next-themes#avoid-hydration-mismatch 34 | return null; 35 | } 36 | 37 | return <>; 38 | }; 39 | 40 | export const ClientSideLayoutContext = ({ 41 | children, 42 | }: { 43 | children: ReactNode; 44 | }) => { 45 | return ( 46 | <> 47 | {getInitColorSchemeScript()} 48 | 49 | 50 | 51 | 52 | {children} 53 | 54 | 55 | ); 56 | }; 57 | -------------------------------------------------------------------------------- /website/src/components/HighlightBaseline.tsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | import { useColorScheme } from "@mui/material"; 3 | import { useEffect } from "react"; 4 | 5 | export const HighlightBaseline = () => { 6 | const { mode } = useColorScheme(); 7 | useEffect(() => { 8 | console.log({ mode }); 9 | // @ts-ignore - don't check type of css module 10 | import("highlight.js/styles/github-dark.css"); 11 | if (mode === "dark") { 12 | } else { 13 | // @ts-ignore - don't check type of css module 14 | // import("highlight.js/styles/github.css"); 15 | } 16 | }, [mode]); 17 | return <>; 18 | }; 19 | -------------------------------------------------------------------------------- /website/src/components/LastUpdatedFromCommit.tsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | 3 | import { useMemo } from "react"; 4 | import { fromUnixTime, formatDistanceToNow, formatISO } from "date-fns"; 5 | import { Chip, Link, Tooltip } from "@mui/material"; 6 | 7 | interface LastUpdatedFromCommitProps { 8 | lastModified: number; 9 | rev: string; 10 | type: "nix" | "nixpkgs"; 11 | } 12 | export const LastUpdatedFromCommit = ({ 13 | lastModified, 14 | rev, 15 | type, 16 | }: LastUpdatedFromCommitProps) => { 17 | const date = useMemo(() => { 18 | const date = fromUnixTime(lastModified); 19 | return { 20 | repr: formatISO(date, { representation: "date" }), 21 | distance: formatDistanceToNow(date), 22 | }; 23 | }, [lastModified]); 24 | return ( 25 | 26 | 30 | {"Docs pulled from | "} 31 | 41 | This Revision 42 | 43 | {" | " + date.distance + " ago"} 44 | 45 | } 46 | variant="outlined" 47 | color="primary" 48 | size="small" 49 | /> 50 | 51 | ); 52 | }; 53 | -------------------------------------------------------------------------------- /website/src/components/PositionInisghts.tsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | 3 | import { DocMeta } from "@/models/data"; 4 | import { Box, Button, Collapse, Typography } from "@mui/material"; 5 | import { useState } from "react"; 6 | import CodeIcon from "@mui/icons-material/Code"; 7 | 8 | export const PositionInsights = ({ meta }: { meta: DocMeta }) => { 9 | // const { attr_position, lambda_position, count_applied, content_meta } = meta; 10 | 11 | const [open, setOpen] = useState(true); 12 | // const is_inherited = 13 | // JSON.stringify(content_meta?.path) !== JSON.stringify(meta.path); 14 | 15 | return ( 16 | <> 17 | 18 | 25 | 26 | 27 | is_inherited 28 | 29 | 30 | ); 31 | }; 32 | -------------------------------------------------------------------------------- /website/src/components/ShareButton.tsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | import { Share } from "@mui/icons-material"; 3 | import { IconButton } from "@mui/material"; 4 | import toast from "react-hot-toast"; 5 | 6 | export const ShareButton = () => { 7 | const handleShare = () => { 8 | const handle = window.location.href; 9 | navigator.clipboard.writeText(handle); 10 | toast.success("link copied to clipboard"); 11 | }; 12 | 13 | return ( 14 | handleShare()}> 15 | 16 | 17 | ); 18 | }; 19 | -------------------------------------------------------------------------------- /website/src/components/emptyRecordsPlaceholder/emptyRecordsPlaceholder.tsx: -------------------------------------------------------------------------------- 1 | import { Card, CardContent, CardProps, Typography } from "@mui/material"; 2 | 3 | import InboxIcon from "@mui/icons-material/Inbox"; 4 | 5 | interface EmptyRecordsPlaceholderProps { 6 | title: string; 7 | subtitle?: string; 8 | icon?: React.ReactNode; 9 | CardProps?: CardProps; 10 | } 11 | 12 | export const EmptyRecordsPlaceholder = ( 13 | props: EmptyRecordsPlaceholderProps 14 | ) => { 15 | const { title, subtitle, icon, CardProps = {} } = props; 16 | return ( 17 | 27 | 37 | 38 | {icon || ( 39 | 40 | )} 41 | 42 | 43 | 48 | {title} 49 | 50 | 51 | 56 | {subtitle} 57 | 58 | 59 | 60 | ); 61 | }; 62 | -------------------------------------------------------------------------------- /website/src/components/emptyRecordsPlaceholder/index.tsx: -------------------------------------------------------------------------------- 1 | export { EmptyRecordsPlaceholder } from "./emptyRecordsPlaceholder"; 2 | -------------------------------------------------------------------------------- /website/src/components/functionOfTheDay/index.ts: -------------------------------------------------------------------------------- 1 | export {FunctionOfTheDay} from "./functionOfTheDay" -------------------------------------------------------------------------------- /website/src/components/image/image.tsx: -------------------------------------------------------------------------------- 1 | import NextImage, { ImageLoaderProps, ImageProps } from "next/image"; 2 | 3 | // opt-out of image optimization, no-op 4 | const customLoader = ({ src }: ImageLoaderProps) => { 5 | return src; 6 | }; 7 | 8 | export function Image(props: ImageProps) { 9 | return ; 10 | } 11 | -------------------------------------------------------------------------------- /website/src/components/image/index.tsx: -------------------------------------------------------------------------------- 1 | export { Image } from "./image"; 2 | -------------------------------------------------------------------------------- /website/src/components/layout/Background.tsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | import { Box } from "@mui/material"; 3 | import { ReactNode } from "react"; 4 | 5 | export const Background = ({ children }: { children: ReactNode }) => { 6 | return ( 7 | 17 | {children} 18 | 19 | ); 20 | }; 21 | -------------------------------------------------------------------------------- /website/src/components/layout/index.ts: -------------------------------------------------------------------------------- 1 | export { LandingPageLayout } from "./layout"; 2 | -------------------------------------------------------------------------------- /website/src/components/layout/themeSwitch.tsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | import { DarkMode, LightMode } from "@mui/icons-material"; 3 | import { IconButton, Tooltip, useColorScheme } from "@mui/material"; 4 | 5 | export const ThemeSwitch = () => { 6 | const { mode, setMode } = useColorScheme(); 7 | 8 | return ( 9 | <> 10 | {mode === "dark" ? ( 11 | 12 | setMode("light")}> 13 | 14 | 15 | 16 | ) : ( 17 | 18 | setMode("dark")}> 19 | 20 | 21 | 22 | )} 23 | 24 | ); 25 | }; 26 | -------------------------------------------------------------------------------- /website/src/components/markdownPreview/MarkdownPreview.tsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | import { useColorScheme } from "@mui/material"; 3 | import nix from "highlight.js/lib/languages/nix"; 4 | import haskell from "highlight.js/lib/languages/haskell"; 5 | import bash from "highlight.js/lib/languages/bash"; 6 | import { useEffect } from "react"; 7 | import ReactMarkdown from "react-markdown"; 8 | import rehypeHighlight from "rehype-highlight"; 9 | import { HighlightBaseline } from "../HighlightBaseline"; 10 | import { 11 | remarkDefinitionList, 12 | defListHastHandlers, 13 | } from "remark-definition-list"; 14 | import { 15 | replaceComponents, 16 | sanitizeDirectives, 17 | styleDirectives, 18 | } from "@/plugins"; 19 | import remarkDirective from "remark-directive"; 20 | 21 | interface MarkdownPreviewProps { 22 | description: string; 23 | } 24 | export const MarkdownPreview = (props: MarkdownPreviewProps) => { 25 | const { description } = props; 26 | const { mode } = useColorScheme(); 27 | useEffect(() => { 28 | console.log({ mode }); 29 | // @ts-ignore - don't check type of css module 30 | import("highlight.js/styles/github-dark.css"); 31 | if (mode === "dark") { 32 | } else { 33 | // @ts-ignore - don't check type of css module 34 | // import("highlight.js/styles/github.css"); 35 | } 36 | }, [mode]); 37 | 38 | return ( 39 | <> 40 | 41 | 65 | {sanitizeDirectives(description)} 66 | 67 | 68 | ); 69 | }; 70 | -------------------------------------------------------------------------------- /website/src/components/markdownPreview/index.ts: -------------------------------------------------------------------------------- 1 | export {MarkdownPreview} from "./MarkdownPreview" -------------------------------------------------------------------------------- /website/src/components/preview/index.tsx: -------------------------------------------------------------------------------- 1 | export { Preview } from "./preview"; 2 | -------------------------------------------------------------------------------- /website/src/components/searchInput/index.tsx: -------------------------------------------------------------------------------- 1 | export { SearchInput } from "./searchInput"; 2 | -------------------------------------------------------------------------------- /website/src/components/selectOption/index.ts: -------------------------------------------------------------------------------- 1 | export {SelectOption} from "./selectOption" -------------------------------------------------------------------------------- /website/src/components/selectOption/selectOption.tsx: -------------------------------------------------------------------------------- 1 | import { NixType } from "@/models/nix"; 2 | import { 3 | FormControl, 4 | FormControlLabel, 5 | FormLabel, 6 | Radio, 7 | RadioGroup, 8 | Typography, 9 | } from "@mui/material"; 10 | 11 | interface SelectOptionProps { 12 | label: string; 13 | handleChange: (value: string) => void; 14 | value: string; 15 | 16 | options: { 17 | value: string; 18 | label: string; 19 | }[]; 20 | } 21 | 22 | export const SelectOption = (props: SelectOptionProps) => { 23 | const { label, handleChange, options, value } = props; 24 | 25 | const _handleChange = (event: React.ChangeEvent) => { 26 | const newVal = (event.target as HTMLInputElement).value as NixType; 27 | handleChange(newVal); 28 | }; 29 | 30 | return ( 31 | 36 | 44 | {label} 45 | 46 | 47 | 57 | {options.map(({ value, label }) => ( 58 | } 62 | label={label} 63 | /> 64 | ))} 65 | 66 | 67 | ); 68 | }; 69 | -------------------------------------------------------------------------------- /website/src/excerpt.ts: -------------------------------------------------------------------------------- 1 | import type { Root } from "hast"; 2 | import { toString as hastToString } from "hast-util-to-string"; 3 | import type { Plugin } from "unified"; 4 | import { EXIT, visit } from "unist-util-visit"; 5 | 6 | export interface RehypeExtractExcerptOptions { 7 | /** The var name of the vFile.data export. defaults to `excerpt` */ 8 | name?: string; 9 | 10 | /** The character length to truncate the excerpt. defaults to 140 */ 11 | maxLength?: number; 12 | 13 | /** The ellipsis to add to the excerpt. defaults to `...` */ 14 | ellipsis?: string; 15 | 16 | /** Truncate the excerpt at word boundary. defaults to `true` */ 17 | wordBoundaries?: boolean; 18 | 19 | /** The HTML tag name for the excerpt content. defaults to `p` */ 20 | tagName?: string; 21 | } 22 | 23 | const defaults: RehypeExtractExcerptOptions = { 24 | name: "excerpt", 25 | maxLength: 140, 26 | ellipsis: "...", 27 | wordBoundaries: true, 28 | tagName: "p", 29 | }; 30 | 31 | const rehypeExtractExcerpt: Plugin<[RehypeExtractExcerptOptions?], Root> = ( 32 | userOptions?: RehypeExtractExcerptOptions 33 | ) => { 34 | const options = { ...defaults, ...userOptions }; 35 | 36 | function truncateExcerpt( 37 | str: string, 38 | maxLength: number, 39 | ellipsis: string, 40 | wordBoundaries: boolean 41 | ): string { 42 | if (str.length > maxLength) { 43 | if (wordBoundaries) { 44 | return `${str.slice( 45 | 0, 46 | str.lastIndexOf(" ", maxLength - 1) 47 | )}${ellipsis}`; 48 | } 49 | return `${str.slice(0, maxLength)}${ellipsis}`; 50 | } 51 | return str; 52 | } 53 | 54 | return (tree, vfile) => { 55 | const excerpt: string[] = []; 56 | 57 | visit(tree, "element", (node) => { 58 | if (node.tagName !== options.tagName) { 59 | return; 60 | } 61 | 62 | excerpt.push( 63 | truncateExcerpt( 64 | hastToString(node), 65 | options.maxLength!, 66 | options.ellipsis!, 67 | options.wordBoundaries! 68 | ) 69 | ); 70 | 71 | return EXIT; 72 | }); 73 | vfile.data[options.name!] = excerpt[0]; 74 | }; 75 | }; 76 | 77 | export { rehypeExtractExcerpt }; 78 | -------------------------------------------------------------------------------- /website/src/fonts/index: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nix-community/noogle/a28bf7d00258ea18d43ac8ef0cf0429fe4432fe9/website/src/fonts/index -------------------------------------------------------------------------------- /website/src/mdx-components.tsx: -------------------------------------------------------------------------------- 1 | import type { MDXComponents } from "mdx/types"; 2 | 3 | export function useMDXComponents(components: MDXComponents): MDXComponents { 4 | return { 5 | ...components, 6 | }; 7 | } 8 | -------------------------------------------------------------------------------- /website/src/models/data/index.ts: -------------------------------------------------------------------------------- 1 | import all from "./data.json" assert { type: "json" }; 2 | import types from "./builtins.types.json" assert { type: "json" }; 3 | import links from "./manual-link.map.json" assert { type: "json" }; 4 | import libMeta from "./lib-meta.json" assert { type: "json" }; 5 | import nixMeta from "./nix-meta.json" assert { type: "json" }; 6 | 7 | export type ManualLink = { 8 | id: string; 9 | file: string; 10 | }; 11 | 12 | export const manualLinks = links as ManualLink[]; 13 | 14 | export type FilePosition = { 15 | file: string; 16 | line: number; 17 | column: number; 18 | }; 19 | 20 | export type PositionType = "Lambda" | "Attribute"; 21 | export type SourceOrigin = { 22 | position?: FilePosition; 23 | path?: ValuePath; 24 | pos_type?: PositionType; 25 | }; 26 | 27 | export type PrimopMatter = { 28 | name?: string; 29 | args?: string[]; 30 | experimental?: boolean; 31 | arity?: number; 32 | }; 33 | export type ValuePath = string[]; 34 | 35 | export type DocMeta = { 36 | title: string; 37 | path: ValuePath; 38 | aliases?: ValuePath[]; 39 | is_primop?: boolean; 40 | is_functor?: boolean; 41 | primop_meta?: PrimopMatter; 42 | attr_position?: FilePosition; 43 | attr_expr?: string; 44 | lambda_position?: FilePosition; 45 | lambda_expr?: string; 46 | count_applied?: number; 47 | content_meta?: SourceOrigin; 48 | signature?: string; 49 | }; 50 | export type ContentSource = { 51 | content?: string; 52 | source?: SourceOrigin; 53 | }; 54 | 55 | export type Doc = { 56 | meta: DocMeta; 57 | content?: ContentSource; 58 | }; 59 | 60 | export const data: Doc[] = all as unknown as Doc[]; 61 | 62 | export type BuiltinType = { fn_type: string }; 63 | export type BuiltinTypes = { 64 | [fn_name: string]: BuiltinType; 65 | }; 66 | 67 | export const builtinTypes = types as BuiltinTypes; 68 | 69 | export type UpstreamInfo = { 70 | rev: string; 71 | lastModified: number; 72 | }; 73 | 74 | export const upstreamInfo = libMeta as UpstreamInfo; 75 | export const nixInfo = nixMeta as UpstreamInfo; 76 | -------------------------------------------------------------------------------- /website/src/models/internals.ts: -------------------------------------------------------------------------------- 1 | import { Doc, data } from "./data"; 2 | import { NixType } from "./nix"; 3 | 4 | export type ViewMode = "explore" | "browse"; 5 | 6 | export type ComputedState = { 7 | FOTD: boolean; 8 | }; 9 | 10 | export type PageState = { 11 | data: Doc[]; 12 | selected: string | null; 13 | term: string; 14 | filter: Filter; 15 | page: number; 16 | itemsPerPage: number; 17 | viewMode: ViewMode; 18 | } & ComputedState; 19 | 20 | export type InitialPageState = Omit; 21 | 22 | export const initialPageState: InitialPageState = { 23 | data, 24 | selected: null, 25 | term: "", 26 | filter: { from: "any", to: "any" }, 27 | page: 1, 28 | itemsPerPage: 10, 29 | viewMode: "explore", 30 | }; 31 | 32 | export type Filter = { to: NixType; from: NixType }; 33 | 34 | export const normalizePath = (id: string) => { 35 | if (!id.includes("-")) return id; 36 | return id 37 | .split("-") 38 | .map((substr, idx) => { 39 | if (idx === 0) return substr; 40 | 41 | const start = substr.slice(0, 1); 42 | const end = substr.slice(1); 43 | return start.toUpperCase() + end; 44 | }) 45 | .join(""); 46 | }; 47 | -------------------------------------------------------------------------------- /website/src/models/primop.ts: -------------------------------------------------------------------------------- 1 | import { PrimopMatter } from "./data"; 2 | 3 | export const getPrimopDescription = (meta: PrimopMatter) => { 4 | const args = meta?.args?.map((a) => `__${a}__`) || []; 5 | return !meta?.arity 6 | ? "" 7 | : `Takes __${meta?.arity}__ arguments\n\n ${args.join(", ")} \n\n`; 8 | }; 9 | -------------------------------------------------------------------------------- /website/src/queries/byQuery.ts: -------------------------------------------------------------------------------- 1 | // import { DocItem, MetaData } from "@/models/nix"; 2 | 3 | // export const byQuery = 4 | // (rawTerm: string) => 5 | // (data: MetaData): MetaData => { 6 | // const term = rawTerm.toLowerCase(); 7 | // return data 8 | // .reduce( 9 | // (results: (DocItem & { relevance: number })[], docItem: DocItem) => { 10 | // const matchesOn = Object.keys(docItem).filter((key) => { 11 | // const rawValue = String(docItem[key as keyof DocItem]); 12 | // if (rawValue === null || rawValue === undefined) { 13 | // return false; 14 | // } 15 | // const value = Array.isArray(rawValue) 16 | // ? rawValue.join("\n").toLowerCase() 17 | // : rawValue.toLowerCase(); 18 | // if (value.includes(term)) { 19 | // return true; 20 | // } 21 | // return false; 22 | // }); 23 | // if (matchesOn?.length) { 24 | // results.push({ 25 | // ...docItem, 26 | // relevance: getRelevance(matchesOn as (keyof DocItem)[]), 27 | // }); 28 | // } 29 | // return results; 30 | // }, 31 | // [] 32 | // ) 33 | // .sort((a, b) => b.relevance - a.relevance); 34 | // }; 35 | 36 | // const getRelevance = (matchesOn: (keyof DocItem)[]): number => { 37 | // const relevanceMap = { 38 | // id: 10, 39 | // name: 5, 40 | // fn_type: 4, 41 | // category: 3, 42 | // example: 2, 43 | // description: 1, 44 | // line: 1, 45 | // }; 46 | // return matchesOn.reduce((count, key) => { 47 | // return count + relevanceMap[key]; 48 | // }, 0); 49 | // }; 50 | -------------------------------------------------------------------------------- /website/src/queries/byType.ts: -------------------------------------------------------------------------------- 1 | // import { MetaData, NixType } from "@/models/nix"; 2 | // import { getTypes } from "./lib"; 3 | 4 | // export const byType = 5 | // ({ to, from }: { to: NixType; from: NixType }) => 6 | // (data: MetaData): MetaData => { 7 | // if (to === "any" && from === "any") { 8 | // return data; 9 | // } else { 10 | // return data.filter( 11 | // // TODO: Implement proper type matching 12 | // ({ name, fn_type }) => { 13 | // if (fn_type) { 14 | // const parsedType = getTypes(name, fn_type); 15 | // return ( 16 | // parsedType.args.includes(from) && parsedType.types.includes(to) 17 | // ); 18 | // } else { 19 | // return to === "any" && from === "any"; 20 | // } 21 | // } 22 | // ); 23 | // } 24 | // }; 25 | -------------------------------------------------------------------------------- /website/src/queries/index.ts: -------------------------------------------------------------------------------- 1 | export { pipe } from "./lib"; 2 | -------------------------------------------------------------------------------- /website/src/queries/lib.ts: -------------------------------------------------------------------------------- 1 | import { NixType, nixTypes } from "@/models/nix"; 2 | 3 | export function pipe(...fns: ((arr: T) => T)[]) { 4 | return (x: T) => fns.reduce((v, f) => f(v), x); 5 | } 6 | 7 | export function getTypes( 8 | fnName: string, 9 | fnType: string | undefined 10 | ): { args: NixType[]; types: NixType[] } { 11 | if (fnType) { 12 | let cleanType = fnType.replace(/ /g, "").replace(`${fnName}::`, ""); 13 | const tokens = cleanType 14 | .split(/(::|->|\[|\]|\{|\}|\(|\))/gm) 15 | .filter(Boolean); 16 | const lastArrowIdx = tokens.lastIndexOf("->"); 17 | if (lastArrowIdx) { 18 | // Function has at least on return value 19 | const interpretToken = (token: string) => { 20 | if (token === "(" || token === ")") { 21 | return "function" as NixType; 22 | } else if (token === "[" || token === "]") { 23 | return "list" as NixType; 24 | } else if (token === "{" || token === "}") { 25 | return "attrset" as NixType; 26 | } else if (nixTypes.includes(token.toLowerCase() as NixType)) { 27 | return token.toLowerCase() as NixType; 28 | } else if ( 29 | token.length === 1 && 30 | ["a", "b", "c", "d", "e"].includes(token) 31 | ) { 32 | return "any" as NixType; 33 | } else { 34 | return undefined; 35 | } 36 | }; 37 | const returnValueTokens = tokens.slice(lastArrowIdx + 1); 38 | const types = returnValueTokens 39 | .map(interpretToken) 40 | .filter(Boolean) 41 | .filter((e, i, s) => s.indexOf(e) === i); 42 | const args = tokens 43 | .slice(0, lastArrowIdx) 44 | .map(interpretToken) 45 | .filter(Boolean) 46 | .filter((e, i, s) => s.indexOf(e) === i); 47 | return { args, types } as { args: NixType[]; types: NixType[] }; 48 | } 49 | } 50 | return { args: ["any"], types: ["any"] }; 51 | } 52 | -------------------------------------------------------------------------------- /website/src/styles/theme/common.ts: -------------------------------------------------------------------------------- 1 | import { CssVarsThemeOptions } from "@mui/material"; 2 | 3 | const commonOptions: Partial = { 4 | typography: { 5 | fontFamily: "inherit", 6 | h1: { 7 | fontSize: "2.9rem", 8 | }, 9 | h2: { 10 | fontSize: "2.6rem", 11 | }, 12 | h3: { 13 | fontSize: "2.3rem", 14 | }, 15 | }, 16 | }; 17 | 18 | export { commonOptions }; 19 | -------------------------------------------------------------------------------- /website/src/styles/theme/index.tsx: -------------------------------------------------------------------------------- 1 | export { cssThemeOptions } from "./themeOptions"; 2 | -------------------------------------------------------------------------------- /website/src/types/basicDataView.ts: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | 3 | export type BasicDataItem = { 4 | item: React.ReactNode; 5 | key: string; 6 | }; 7 | 8 | export type BasicDataViewProps = { 9 | items: BasicDataItem[]; 10 | pageCount?: number; 11 | handleSearch?: (term: string) => void; 12 | }; 13 | -------------------------------------------------------------------------------- /website/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | 3 | "compilerOptions": { 4 | "target": "es6", 5 | "lib": [ 6 | "dom", 7 | "dom.iterable", 8 | "esnext" 9 | ], 10 | "allowJs": true, 11 | "noUnusedLocals": true, 12 | "skipLibCheck": true, 13 | "strict": true, 14 | "forceConsistentCasingInFileNames": true, 15 | "noEmit": true, 16 | "esModuleInterop": true, 17 | "module": "esnext", 18 | "moduleResolution": "node", 19 | "resolveJsonModule": true, 20 | "isolatedModules": true, 21 | "jsx": "preserve", 22 | "incremental": true, 23 | "plugins": [ 24 | { 25 | "name": "next" 26 | } 27 | ], 28 | "paths": { 29 | "@/*": ["./src/*"] 30 | } 31 | 32 | }, 33 | "include": [ 34 | "next-env.d.ts", 35 | "src/**/*.ts", 36 | "src/**/*.tsx", 37 | ".next/types/**/*.ts" 38 | ], 39 | "exclude": [ 40 | "node_modules", 41 | "result" 42 | ] 43 | } 44 | --------------------------------------------------------------------------------