Full Code of mason-org/mason.nvim for AI

main 44d1e90e1f66 cached
225 files
850.9 KB
211.9k tokens
1 requests
Download .txt
Showing preview only (912K chars total). Download the full file or copy to clipboard to get everything.
Repository: mason-org/mason.nvim
Branch: main
Commit: 44d1e90e1f66
Files: 225
Total size: 850.9 KB

Directory structure:
gitextract_j3t903i2/

├── .cbfmt.toml
├── .editorconfig
├── .github/
│   ├── FUNDING.yml
│   ├── ISSUE_TEMPLATE/
│   │   ├── config.yml
│   │   ├── feature_request.yaml
│   │   ├── general_issue.yaml
│   │   ├── new_package_request.yaml
│   │   ├── package_installation_form.yaml
│   │   └── package_issue.yaml
│   └── workflows/
│       ├── cbfmt.yml
│       ├── release.yml
│       ├── selene.yml
│       ├── stylua.yml
│       └── tests.yml
├── .gitignore
├── CHANGELOG.md
├── CONTRIBUTING.md
├── LICENSE
├── Makefile
├── PACKAGES.md
├── README.md
├── SECURITY.md
├── doc/
│   ├── .gitignore
│   └── mason.txt
├── lua/
│   ├── mason/
│   │   ├── api/
│   │   │   └── command.lua
│   │   ├── health.lua
│   │   ├── init.lua
│   │   ├── providers/
│   │   │   ├── client/
│   │   │   │   ├── gh.lua
│   │   │   │   ├── golang.lua
│   │   │   │   ├── init.lua
│   │   │   │   ├── npm.lua
│   │   │   │   ├── openvsx.lua
│   │   │   │   ├── pypi.lua
│   │   │   │   └── rubygems.lua
│   │   │   └── registry-api/
│   │   │       └── init.lua
│   │   ├── settings.lua
│   │   ├── ui/
│   │   │   ├── colors.lua
│   │   │   ├── components/
│   │   │   │   ├── header.lua
│   │   │   │   ├── help/
│   │   │   │   │   ├── dap.lua
│   │   │   │   │   ├── formatter.lua
│   │   │   │   │   ├── init.lua
│   │   │   │   │   ├── linter.lua
│   │   │   │   │   └── lsp.lua
│   │   │   │   ├── json-schema.lua
│   │   │   │   ├── language-filter.lua
│   │   │   │   ├── main/
│   │   │   │   │   ├── init.lua
│   │   │   │   │   └── package_list.lua
│   │   │   │   └── tabs.lua
│   │   │   ├── init.lua
│   │   │   ├── instance.lua
│   │   │   └── palette.lua
│   │   └── version.lua
│   ├── mason-core/
│   │   ├── EventEmitter.lua
│   │   ├── async/
│   │   │   ├── control.lua
│   │   │   ├── init.lua
│   │   │   └── uv.lua
│   │   ├── fetch.lua
│   │   ├── fs.lua
│   │   ├── functional/
│   │   │   ├── data.lua
│   │   │   ├── function.lua
│   │   │   ├── init.lua
│   │   │   ├── list.lua
│   │   │   ├── logic.lua
│   │   │   ├── number.lua
│   │   │   ├── relation.lua
│   │   │   ├── string.lua
│   │   │   ├── table.lua
│   │   │   └── type.lua
│   │   ├── installer/
│   │   │   ├── InstallHandle.lua
│   │   │   ├── InstallLocation.lua
│   │   │   ├── InstallRunner.lua
│   │   │   ├── UninstallRunner.lua
│   │   │   ├── compiler/
│   │   │   │   ├── compilers/
│   │   │   │   │   ├── cargo.lua
│   │   │   │   │   ├── composer.lua
│   │   │   │   │   ├── gem.lua
│   │   │   │   │   ├── generic/
│   │   │   │   │   │   ├── build.lua
│   │   │   │   │   │   ├── download.lua
│   │   │   │   │   │   └── init.lua
│   │   │   │   │   ├── github/
│   │   │   │   │   │   ├── build.lua
│   │   │   │   │   │   ├── init.lua
│   │   │   │   │   │   └── release.lua
│   │   │   │   │   ├── golang.lua
│   │   │   │   │   ├── luarocks.lua
│   │   │   │   │   ├── mason.lua
│   │   │   │   │   ├── npm.lua
│   │   │   │   │   ├── nuget.lua
│   │   │   │   │   ├── opam.lua
│   │   │   │   │   ├── openvsx.lua
│   │   │   │   │   └── pypi.lua
│   │   │   │   ├── expr.lua
│   │   │   │   ├── init.lua
│   │   │   │   ├── link.lua
│   │   │   │   ├── schemas.lua
│   │   │   │   └── util.lua
│   │   │   ├── context/
│   │   │   │   ├── InstallContextCwd.lua
│   │   │   │   ├── InstallContextFs.lua
│   │   │   │   ├── InstallContextSpawn.lua
│   │   │   │   └── init.lua
│   │   │   ├── init.lua
│   │   │   ├── linker.lua
│   │   │   └── managers/
│   │   │       ├── cargo.lua
│   │   │       ├── common.lua
│   │   │       ├── composer.lua
│   │   │       ├── gem.lua
│   │   │       ├── golang.lua
│   │   │       ├── luarocks.lua
│   │   │       ├── npm.lua
│   │   │       ├── nuget.lua
│   │   │       ├── opam.lua
│   │   │       ├── powershell.lua
│   │   │       ├── pypi.lua
│   │   │       └── std.lua
│   │   ├── log.lua
│   │   ├── notify.lua
│   │   ├── optional.lua
│   │   ├── package/
│   │   │   ├── AbstractPackage.lua
│   │   │   └── init.lua
│   │   ├── path.lua
│   │   ├── pep440/
│   │   │   └── init.lua
│   │   ├── platform.lua
│   │   ├── process.lua
│   │   ├── providers.lua
│   │   ├── purl.lua
│   │   ├── receipt.lua
│   │   ├── result.lua
│   │   ├── semver.lua
│   │   ├── spawn.lua
│   │   ├── terminator.lua
│   │   └── ui/
│   │       ├── display.lua
│   │       ├── init.lua
│   │       └── state.lua
│   ├── mason-registry/
│   │   ├── api.lua
│   │   ├── index/
│   │   │   └── init.lua
│   │   ├── init.lua
│   │   ├── installer.lua
│   │   └── sources/
│   │       ├── file.lua
│   │       ├── github.lua
│   │       ├── init.lua
│   │       ├── lua.lua
│   │       ├── synthesized.lua
│   │       └── util.lua
│   ├── mason-test/
│   │   └── helpers.lua
│   └── mason-vendor/
│       ├── semver.lua
│       └── zzlib/
│           ├── inflate-bit32.lua
│           ├── inflate-bwo.lua
│           └── init.lua
├── selene.toml
├── stylua.toml
├── tests/
│   ├── fixtures/
│   │   ├── purl-test-suite-data.json
│   │   └── receipts/
│   │       ├── 1.0.json
│   │       ├── 1.1.json
│   │       └── 2.0.json
│   ├── helpers/
│   │   └── lua/
│   │       ├── dummy-registry/
│   │       │   ├── dummy.lua
│   │       │   ├── dummy2.lua
│   │       │   ├── index.lua
│   │       │   └── registry.lua
│   │       └── luassertx.lua
│   ├── mason/
│   │   ├── api/
│   │   │   └── command_spec.lua
│   │   └── setup_spec.lua
│   ├── mason-core/
│   │   ├── EventEmitter_spec.lua
│   │   ├── async/
│   │   │   └── async_spec.lua
│   │   ├── fetch_spec.lua
│   │   ├── fs_spec.lua
│   │   ├── functional/
│   │   │   ├── data_spec.lua
│   │   │   ├── function_spec.lua
│   │   │   ├── list_spec.lua
│   │   │   ├── logic_spec.lua
│   │   │   ├── number_spec.lua
│   │   │   ├── relation_spec.lua
│   │   │   ├── string_spec.lua
│   │   │   ├── table_spec.lua
│   │   │   └── type_spec.lua
│   │   ├── installer/
│   │   │   ├── InstallHandle_spec.lua
│   │   │   ├── InstallRunner_spec.lua
│   │   │   ├── compiler/
│   │   │   │   ├── compiler_spec.lua
│   │   │   │   ├── compilers/
│   │   │   │   │   ├── cargo_spec.lua
│   │   │   │   │   ├── composer_spec.lua
│   │   │   │   │   ├── gem_spec.lua
│   │   │   │   │   ├── generic/
│   │   │   │   │   │   ├── build_spec.lua
│   │   │   │   │   │   └── download_spec.lua
│   │   │   │   │   ├── github/
│   │   │   │   │   │   ├── build_spec.lua
│   │   │   │   │   │   └── release_spec.lua
│   │   │   │   │   ├── golang_spec.lua
│   │   │   │   │   ├── luarocks_spec.lua
│   │   │   │   │   ├── npm_spec.lua
│   │   │   │   │   ├── nuget_spec.lua
│   │   │   │   │   ├── opam_spec.lua
│   │   │   │   │   ├── openvsx_spec.lua
│   │   │   │   │   └── pypi_spec.lua
│   │   │   │   ├── expr_spec.lua
│   │   │   │   ├── link_spec.lua
│   │   │   │   └── util_spec.lua
│   │   │   ├── context_spec.lua
│   │   │   ├── linker_spec.lua
│   │   │   └── managers/
│   │   │       ├── cargo_spec.lua
│   │   │       ├── common_spec.lua
│   │   │       ├── composer_spec.lua
│   │   │       ├── gem_spec.lua
│   │   │       ├── golang_spec.lua
│   │   │       ├── luarocks_spec.lua
│   │   │       ├── npm_spec.lua
│   │   │       ├── nuget_spec.lua
│   │   │       ├── opam_spec.lua
│   │   │       ├── powershell_spec.lua
│   │   │       ├── pypi_spec.lua
│   │   │       └── std_spec.lua
│   │   ├── optional_spec.lua
│   │   ├── package/
│   │   │   └── package_spec.lua
│   │   ├── path_spec.lua
│   │   ├── pep440_spec.lua
│   │   ├── platform_spec.lua
│   │   ├── process_spec.lua
│   │   ├── providers/
│   │   │   └── provider_spec.lua
│   │   ├── purl_spec.lua
│   │   ├── receipt_spec.lua
│   │   ├── result_spec.lua
│   │   ├── spawn_spec.lua
│   │   ├── terminator_spec.lua
│   │   └── ui_spec.lua
│   ├── mason-registry/
│   │   ├── api_spec.lua
│   │   ├── registry_spec.lua
│   │   └── sources/
│   │       ├── collection_spec.lua
│   │       └── lua_spec.lua
│   └── minimal_init.vim
└── vim.yml

================================================
FILE CONTENTS
================================================

================================================
FILE: .cbfmt.toml
================================================
[languages]
lua = ["stylua -s -"]
sh = ["shellharden --transform "]


================================================
FILE: .editorconfig
================================================
root = true

[*]
indent_style = space
indent_size = 4
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace=true
max_line_length = 120
charset = utf-8

[*.md]
trim_trailing_whitespace=false


================================================
FILE: .github/FUNDING.yml
================================================
# These are supported funding model platforms

github: [williamboman] # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
patreon: # Replace with a single Patreon username
open_collective: # Replace with a single Open Collective username
ko_fi: # Replace with a single Ko-fi username
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
liberapay: # Replace with a single Liberapay username
issuehunt: # Replace with a single IssueHunt username
otechie: # Replace with a single Otechie username
lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry
custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']


================================================
FILE: .github/ISSUE_TEMPLATE/config.yml
================================================
---

contact_links:
  - name: Ask a question about mason.nvim or get support
    url: https://github.com/mason-org/mason.nvim/discussions/new?category=q-a
    about: Ask a question or request support for using mason.nvim


================================================
FILE: .github/ISSUE_TEMPLATE/feature_request.yaml
================================================
---

name: Feature request
description: Suggest an idea for this project
labels:
    - enhancement

body:
    - type: checkboxes
      attributes:
          label: I've searched open issues for similar requests
          description: If possible, please contribute to any [open issues](https://github.com/mason-org/mason.nvim/issues) instead of opening a new one.
          options:
              - label: "Yes"

    - type: textarea
      attributes:
          label: Is your feature request related to a problem? Please describe.
      validations:
          required: true

    - type: textarea
      attributes:
          label: Describe the solution you'd like
      validations:
          required: true

    - type: textarea
      attributes:
          label: Describe potential alternatives you've considered

    - type: textarea
      attributes:
          label: Additional context


================================================
FILE: .github/ISSUE_TEMPLATE/general_issue.yaml
================================================
---
name: Non-package-related issue
description: Report an issue not related to installation or usage of packages

body:
    - type: markdown
      attributes:
          value: |
              # Issue reporting guidelines

              1. This is not a general support board for package usage questions (e.g. "How do I do X?"). For questions, please refer to [the discussion board](https://github.com/mason-org/mason.nvim/discussions/categories/q-a) first! :)
              1. Before reporting an issue, make sure that you meet the minimum requirements mentioned in the README. Also review `:checkhealth mason` for potential problems.

              ---

    - type: checkboxes
      attributes:
          label: I've searched open issues for similar requests
          description: If possible, please contribute to any [open issues](https://github.com/mason-org/mason.nvim/issues?q=is%3Aissue) instead of opening a new one.
          options:
              - label: "Yes"

    - type: checkboxes
      attributes:
          label: I've recently downloaded the latest plugin version of mason.nvim
          options:
              - label: "Yes"

    - type: textarea
      attributes:
          label: Problem description
          description: A clear and short description of 1) what the issue is, and 2) why you think it's an issue with mason.nvim.
      validations:
          required: true

    - type: textarea
      attributes:
          label: Expected behavior
          description: A short description of the behavior you expected.
      validations:
          required: true

    - type: textarea
      attributes:
          label: Steps to reproduce
          placeholder: |
              1. ...
              2. ...
      validations:
          required: true

    - type: textarea
      attributes:
          label: "Neovim version (>= 0.10.0)"
          description: "Output of `nvim --version`"
          placeholder: |
              NVIM v0.10.0-dev
              Build type: Release
              LuaJIT 2.1.0-beta3
      validations:
          required: true

    - type: input
      attributes:
          label: "Operating system/version"
          description: "On Linux and Mac systems: `$ uname -a`"
      validations:
          required: true

    - type: textarea
      attributes:
          label: Healthcheck output
          placeholder: ":checkhealth mason"
          render: shell
      validations:
          required: true

    - type: textarea
      attributes:
          label: Screenshots
          description: If applicable, add screenshots to help explain your problem


================================================
FILE: .github/ISSUE_TEMPLATE/new_package_request.yaml
================================================
---

name: New package request
description: Request a new package not currently available
title: "[New package]: "
labels:
    - new-package-request

body:
    - type: checkboxes
      attributes:
          label: I've searched open & closed issues for similar requests
          description: If possible, please contribute to [existing issues](https://github.com/mason-org/mason.nvim/issues?q=is%3Aissue+label%3Anew-package-request) instead of opening a new one.
          options:
              - label: "Yes"

    - type: input
      attributes:
          label: Package name
          description: Which package would you like to request to be added?
      validations:
          required: true

    - type: input
      attributes:
          label: Package homepage
          description: e.g., a GitHub page
      validations:
          required: true

    - type: input
      attributes:
          label: Languages
          description: Which languages does this package target?
          placeholder: typescript, javascript

    - type: textarea
      attributes:
          label: How is this package distributed?
          description: Is the package distributed through a standardized channel (such as GitHub release files, npm, pip, etc.)? Leave empty if you don't know.


================================================
FILE: .github/ISSUE_TEMPLATE/package_installation_form.yaml
================================================
---

name: Package installation issue
description: Report an issue that occurs during the installation of a package
labels:
    - installation-issue

body:
    - type: markdown
      attributes:
          value: |
              # Issue reporting guidelines

              1. Before reporting an issue, make sure that you meet the minimum requirements mentioned in the README. Also review `:checkhealth mason` for potential problems.
              1. Please try to review the error yourself first and ensure it's not a problem that is local to your system only.

              ---

    - type: checkboxes
      attributes:
          label: I've searched open issues for similar requests
          description: If possible, please contribute to any [open issues](https://github.com/mason-org/mason.nvim/issues?q=is%3Aissue+label%3Ainstallation-issue) instead of opening a new one.
          options:
              - label: "Yes"

    - type: checkboxes
      attributes:
          label: I've recently downloaded the latest plugin version of mason.nvim
          options:
              - label: "Yes"

    - type: textarea
      attributes:
          label: Problem description
          description: A clear and short description of 1) what the issue is, and 2) why you think it's an issue with mason.nvim.
      validations:
          required: true

    - type: textarea
      attributes:
          label: Expected behavior
          description: A short description of the behavior you expected.
      validations:
          required: true

    - type: input
      attributes:
          label: Affected packages
          description: If this issue is specific to one or more packages, list them here. If not, write 'All'.
      validations:
          required: true

    - type: textarea
      attributes:
          label: Mason output
          description: Please provide the **installation output** available in the `:Mason` window, if possible.
          placeholder: "Please only provide the output of the package installation."
          render: Text

    - type: textarea
      attributes:
          label: Installation log
          description: "`:MasonLog`. Refer to `:help mason-debugging`"
          placeholder: "The default log level is not helpful for debugging purposes! Make sure you set the log level to DEBUG before installing the package (:h mason-debugging)."
          render: Text
      validations:
          required: true

    - type: textarea
      attributes:
          label: "Neovim version (>= 0.10.0)"
          description: "Output of `nvim --version`"
          placeholder: |
              NVIM v0.7.0-dev
              Build type: Release
              LuaJIT 2.1.0-beta3
      validations:
          required: true

    - type: input
      attributes:
          label: "Operating system/version"
          description: "On Linux and Mac systems: `$ uname -a`"
      validations:
          required: true

    - type: textarea
      attributes:
          label: Healthcheck
          placeholder: ":checkhealth mason"
          render: Text
      validations:
          required: true

    - type: textarea
      attributes:
          label: Screenshots
          description: If applicable, add screenshots to help explain your problem


================================================
FILE: .github/ISSUE_TEMPLATE/package_issue.yaml
================================================
---

name: Package issue
description: Report an issue with using a package installed via mason.nvim
labels:
    - package-issue

body:
    - type: markdown
      attributes:
          value: |
              # Issue reporting guidelines

              1. This is not a general support board for package usage questions (e.g. "How do I do X?"). For questions, please refer to [the discussion board](https://github.com/mason-org/mason.nvim/discussions/categories/q-a) first! :)
              1. Before reporting an issue, make sure that you meet the minimum requirements mentioned in the README. Also review `:checkhealth mason` for potential problems.
              1. General usage issues with packages should not be reported here. Please only report issues that you believe are a result of something that mason.nvim does.
              1. Please try to review errors yourself first and ensure it's not a problem that is local to your system only.

              ---

    - type: checkboxes
      attributes:
          label: I've searched open issues for similar requests
          description: If possible, please contribute to any open issues instead of opening a new one.
          options:
              - label: "Yes"

    - type: checkboxes
      attributes:
          label: I've manually reviewed logs to find potential errors
          description: Logs such as `:MasonLog`, `:LspLog`, etc. (don't paste logs without reviewing them yourself first)
          options:
              - label: "Yes"

    - type: checkboxes
      attributes:
          label: I've recently downloaded the latest plugin version of mason.nvim
          options:
              - label: "Yes"

    - type: textarea
      attributes:
          label: Problem description
          description: A clear and short description of 1) what the issue is, and 2) why you think it's an issue with mason.nvim.
      validations:
          required: true

    - type: textarea
      attributes:
          label: Expected behavior
          description: A description of the behavior you expected.
      validations:
          required: true

    - type: textarea
      attributes:
          label: Steps to reproduce
          placeholder: |
              1. ...
              2. ...
      validations:
          required: true

    - type: input
      attributes:
          label: Affected packages
          description: If this issue is specific to one or more packages, list them here. If not, write 'All'.
      validations:
          required: true

    - type: textarea
      attributes:
          label: "Neovim version (>= 0.10.0)"
          description: "Output of `nvim --version`"
          placeholder: |
              NVIM v0.10.0-dev
              Build type: Release
              LuaJIT 2.1.0-beta3
      validations:
          required: true

    - type: input
      attributes:
          label: "Operating system/version"
          description: "On Linux and Mac systems: `$ uname -a`"
      validations:
          required: true

    - type: textarea
      attributes:
          label: Healthcheck
          placeholder: ":checkhealth mason"
          render: Text
      validations:
          required: true

    - type: textarea
      id: screenshots
      attributes:
          label: Screenshots or recordings
          description: If applicable, add screenshots or recordings to help explain your problem.


================================================
FILE: .github/workflows/cbfmt.yml
================================================
name: cbfmt check

on:
    push:
        branches:
            - "main"
    pull_request:

jobs:
    cbfmt:
        runs-on: ubuntu-latest
        steps:
            - uses: actions/checkout@v4
            - name: Download cbfmt
              run: |
                  mkdir /tmp/cbfmt && cd $_
                  curl -fsSL -o cbfmt.tar.gz "https://github.com/lukas-reineke/cbfmt/releases/download/v0.2.0/cbfmt_linux-x86_64_v0.2.0.tar.gz"
                  tar --strip-components 1 -xvf cbfmt.tar.gz
                  mv cbfmt /usr/local/bin/
            - name: Download Stylua
              run: |
                  mkdir /tmp/stylua && cd $_
                  curl -fsSL -o stylua.zip "https://github.com/JohnnyMorganz/StyLua/releases/download/v0.20.0/stylua-linux.zip"
                  unzip -d /usr/local/bin stylua.zip
            - name: Download Shellharden
              run: |
                  mkdir /tmp/shellharden && cd $_
                  curl -fsSL -o shellharden.tar.gz https://github.com/anordal/shellharden/releases/download/v4.3.1/shellharden-x86_64-unknown-linux-gnu.tar.gz
                  tar -xvf shellharden.tar.gz
                  mv shellharden /usr/local/bin/
            - name: Run cbfmt check
              # Lua examples in README.md doesn't conform to Stylua rules, on purpose.
              run: find . -name '*.md' -not -path './dependencies/*' -not -path './README.md' -not -path './CHANGELOG.md' | xargs cbfmt --check


================================================
FILE: .github/workflows/release.yml
================================================
name: Release

on:
  push:
    branches:
      - "main"
permissions:
  contents: write
  pull-requests: write

jobs:
  release:
    name: release
    runs-on: ubuntu-latest
    steps:
      - uses: google-github-actions/release-please-action@v3
        id: release
        with:
          token: ${{ secrets.PAT }}
          release-type: simple
          package-name: mason.nvim
          extra-files: |
            README.md
            lua/mason/version.lua

      - uses: actions/checkout@v4

      - uses: rickstaa/action-create-tag@v1
        if: ${{ steps.release.outputs.release_created }}
        with:
          tag: stable
          message: "Current stable release: ${{ steps.release.outputs.tag_name }}"
          force_push_tag: true


================================================
FILE: .github/workflows/selene.yml
================================================
name: Selene check

on:
    push:
        branches:
            - "main"
    pull_request:

jobs:
    selene:
        runs-on: ubuntu-latest
        steps:
            - uses: actions/checkout@v4
            - name: Run Selene check
              uses: NTBBloodbath/selene-action@v1.0.0
              with:
                  # token is needed because the action allegedly downloads binary from github releases
                  token: ${{ secrets.GITHUB_TOKEN }}
                  args: lua/ tests/
                  version: 0.27.1


================================================
FILE: .github/workflows/stylua.yml
================================================
name: Stylua check

on:
    push:
        branches:
            - "main"
    pull_request:

jobs:
    stylua:
        runs-on: ubuntu-latest
        steps:
            - uses: actions/checkout@v4
            - name: Run Stylua check
              uses: JohnnyMorganz/stylua-action@v1.1.1
              with:
                  # token is needed because the action allegedly downloads binary from github releases
                  token: ${{ secrets.GITHUB_TOKEN }}
                  # CLI arguments
                  args: --check .
                  version: 0.20.0


================================================
FILE: .github/workflows/tests.yml
================================================
name: Tests

on:
    push:
        branches:
            - "main"
    pull_request:

jobs:
    tests:
        strategy:
            fail-fast: false
            matrix:
                nvim_version:
                    - v0.10.0
                    - v0.10.1
                    - v0.10.2
                    - v0.10.3
                    - v0.10.4
                    - v0.11.0
                    - v0.11.1
        runs-on: ubuntu-latest
        steps:
            - uses: actions/checkout@v4
            - uses: rhysd/action-setup-vim@v1
              with:
                  neovim: true
                  version: ${{ matrix.nvim_version }}
            - name: Run tests
              run: |
                set -e
                make test
                nvim -u NONE -E -R --headless +'helptags doc' +q


================================================
FILE: .gitignore
================================================
.luarc.json
/dependencies
/tests/fixtures/mason


================================================
FILE: CHANGELOG.md
================================================
# Changelog

## [2.2.1](https://github.com/mason-org/mason.nvim/compare/v2.2.0...v2.2.1) (2026-01-07)


### Bug Fixes

* **registry:** exclude synthesized registry when updating/installing registries ([#2054](https://github.com/mason-org/mason.nvim/issues/2054)) ([3fce8bd](https://github.com/mason-org/mason.nvim/commit/3fce8bd25e773bae4267c9e8f2cfbfda22aeb017))

## [2.2.0](https://github.com/mason-org/mason.nvim/compare/v2.1.0...v2.2.0) (2026-01-07)


### Features

* add support for removal of packages from a registry ([#2052](https://github.com/mason-org/mason.nvim/issues/2052)) ([69862d6](https://github.com/mason-org/mason.nvim/commit/69862d6c8dbe215489c3e48e624ff25f44437e55))


### Bug Fixes

* **installer:** attempt to recover from known fs error while finalizing installation on some file systems ([#1933](https://github.com/mason-org/mason.nvim/issues/1933)) ([198f075](https://github.com/mason-org/mason.nvim/commit/198f07572c0014774fb87371946e0f03b4908bce))
* **installer:** update cwd after uv_fs_rename() was successful ([#2033](https://github.com/mason-org/mason.nvim/issues/2033)) ([57e5a8a](https://github.com/mason-org/mason.nvim/commit/57e5a8addb8c71fb063ee4acda466c7cf6ad2800))

## [2.1.0](https://github.com/mason-org/mason.nvim/compare/v2.0.1...v2.1.0) (2025-09-30)


### Features

* **compiler:** make `supported_platforms` a universal source field ([#2002](https://github.com/mason-org/mason.nvim/issues/2002)) ([7dc4fac](https://github.com/mason-org/mason.nvim/commit/7dc4facca9702f95353d5a1f87daf23d78e31c2a))


### Bug Fixes

* **process:** close check handles ([#1995](https://github.com/mason-org/mason.nvim/issues/1995)) ([a1fbecc](https://github.com/mason-org/mason.nvim/commit/a1fbecc0fd76300e8fe84879fb1531f35cf7b018))
* **pypi:** add support for "compatible release" (~=) PEP440 expressions ([#2000](https://github.com/mason-org/mason.nvim/issues/2000)) ([9e25c98](https://github.com/mason-org/mason.nvim/commit/9e25c98d4826998460926f8c5c2284848d80ae89))
* **spawn:** always expand executable path on Windows ([#2021](https://github.com/mason-org/mason.nvim/issues/2021)) ([a83eabd](https://github.com/mason-org/mason.nvim/commit/a83eabdc8c49c0c93bf5bb162fa3b57404a9d095))
* **ui:** only set border to none if `'winborder'` doesn't exist ([#1984](https://github.com/mason-org/mason.nvim/issues/1984)) ([3671ab0](https://github.com/mason-org/mason.nvim/commit/3671ab0d40aa5bd24b1686562bd0a23391ecf76a))

## [2.0.1](https://github.com/mason-org/mason.nvim/compare/v2.0.0...v2.0.1) (2025-07-25)


### Bug Fixes

* **fetch:** add busybox wget support ([#1829](https://github.com/mason-org/mason.nvim/issues/1829)) ([8024d64](https://github.com/mason-org/mason.nvim/commit/8024d64e1330b86044fed4c8494ef3dcd483a67c))
* **pypi:** pass --no-user flag ([#1958](https://github.com/mason-org/mason.nvim/issues/1958)) ([1aceba8](https://github.com/mason-org/mason.nvim/commit/1aceba8bc158b5aaf90649077cad06744bc23ac4))
* **registry:** ensure there's no duplicate registry entries ([#1957](https://github.com/mason-org/mason.nvim/issues/1957)) ([3501b0f](https://github.com/mason-org/mason.nvim/commit/3501b0f96d9f2f878b1947cf3614bc02d053a0c0))
* **spawn:** fix calling vim.fn when inside fast event loop on Windows ([#1950](https://github.com/mason-org/mason.nvim/issues/1950)) ([888d6ee](https://github.com/mason-org/mason.nvim/commit/888d6ee499d8089a3a4be4309d239d6be1c1e6c0))
* **spawn:** fix locating exepath on Windows systems using a Unix `'shell'` ([#1991](https://github.com/mason-org/mason.nvim/issues/1991)) ([edd8f7b](https://github.com/mason-org/mason.nvim/commit/edd8f7bce8f86465349b24e235718eb3ea52878d))

## [2.0.0](https://github.com/mason-org/mason.nvim/compare/v1.11.0...v2.0.0) (2025-05-06)

This release has been an ongoing effort for quite some time now and is now ready for release. Most users should not
experience any breaking changes. If you use any of the Lua APIs that Mason provides you'll find an outline of the
changes below, breaking changes are marked with `Breaking Change`.

### Repository has been moved

The repository has been transferred to the [`mason-org`](https://github.com/mason-org) organization. The new URL is
https://github.com/mason-org/mason.nvim. The previous URL will continue to function as a redirect to the new URL but
users are recommended to update to the new location. 

### Addition of new maintainers ❤️

- [@mehalter](https://github.com/mehalter)
- [@Conarius](https://github.com/Conarius)
- [@chrisgrieser](https://github.com/chrisgrieser)

### Features
- Symlinks now uses relative paths instead of absolute paths.
- Uninstalled packages now display their available version in the `:Mason` UI.
- Packages in the `:Mason` UI now display the source [`purl`](https://github.com/package-url/purl-spec).
- Official support for [custom registries](https://github.com/mason-org/registry-examples).
- Make registry installations run concurrently.
- Add support for `'winborder'`.
- Display current `mason.nvim` version in the `:Mason` UI header.

### Bug Fixes
- Only attempt unlinking package if the receipt is found.
- Expand executable paths on Windows before passing to uv_spawn.
- Fix initializing UI state when using multiple registries.
- Fix the display of outdated packages in the Mason UI under certain conditions.

### Misc
- `Breaking Change` Minimum Neovim requirement changed from 0.7.0 to 0.10.0. 
- `Breaking Change` APIs related to custom packages written in Lua has been removed.
    - All `require("mason-core.installer.managers")` modules have been removed.
    - The package structure of Lua packages has changed, refer to [custom
      registries](https://github.com/mason-org/registry-examples) for information on how to continue using custom
      packages in Lua.

### Event changes

#### Package
- `Breaking Change` `install:success` now provides the receipt as payload argument.
- `Breaking Change` `install:failed` now provides the error as payload argument.
- `Breaking Change` `uninstall:success` now provides the receipt of the uninstalled package as payload argument.
- `uninstall:failed` is now emitted when package uninstallation fails.

#### Registry
- `Breaking Change` `package:install:success` now provides the receipt as payload argument.
- `Breaking Change` `package:install:failed` now provides the error as payload argument.
- `Breaking Change` `package:uninstall:success` now provides the receipt of the uninstalled package as payload argument.
- `package:uninstall:failed` is now emitted when package uninstallation fails.
- `Breaking Change` `update` is no longer emitted when registry is updated. It's replaced by the following events:
  - `update:start` when the registry starts updating
  - `update:success` when the registry is successfully updated
  - `update:failed` when the registry failed to update
  - `update:progress` is emitted when the registry update process makes progress when multiple registries are used

### Package API changes

#### `Package:get_install_path()` has been removed.
`Breaking Change`

This method has been removed to prepare for future changes.

If you're using this method to access an executable, please consider simply using the canonical name of the executable
as Mason adds these to your `PATH` by default. If you're using the method to access other files inside the package,
please consider accessing the `$MASON/share` directory instead.

Example:

_Clarification: The `$MASON` environment variable has been available since v1.0.0._

```lua
-- 1a. There's no need to reach into the package directory via Package:get_install_path() to access the executable
print(vim.fn.exepath("kotlin-debug-adapter"))
-- /Users/william/.local/share/nvim/mason/bin/kotlin-debug-adapter

-- 1b. Alternatively if you've configured Mason to not modify PATH
print(vim.fn.expand("$MASON/bin/kotlin-debug-adapter"))
-- /Users/william/.local/share/nvim/mason/bin/kotlin-debug-adapter

-- 2. To access other files inside the package directory, consider accessing them via the share/ directory
vim.print(vim.fn.globpath("$MASON/share/java-debug-adapter", "*.jar", true, true))
-- { "/Users/william/.local/share/nvim/mason/share/java-debug-adapter/com.microsoft.java.debug.plugin-0.53.1.jar", "/Users/william/.local/share/nvim/mason/share/java-debug-adapter/com.microsoft.java.debug.plugin.jar" }

-- 3. If you absolutely need to access the package directory (please consider raising an issue/PR in the registry if possible)
print(vim.fn.expand("$MASON/packages/kotlin-debug-adapter/adapter/bin/kotlin-debug-adapter"))
-- /Users/william/.local/share/nvim/mason/packages/kotlin-debug-adapter/adapter/bin/kotlin-debug-adapter
```

> [!NOTE]
> Why was this method removed? The contents of the package directory is not a stable interface and its structure may
> change without prior notice, for example to host multiple versions of a package. The only stable interfaces on the
> file system are files available in `bin/`, `share/` and `opt/` - these directories are only subject to breaking
> changes done by the underlying package itself.

---

#### `Package:uninstall(opts, callback)` is now asynchronous.
`Breaking Change`

This method now provides an asynchronous interface and accepts two new optional arguments `opts` and `callback`. `opts`
currently doesn't have any valid values other than an empty Lua table `{}`. `callback` is called when the package is
uninstalled, successfully or not. While the uninstall mechanism under the hood remains synchronous for the time being it
is not a guarantee going forward and users are recommended to always use the asynchronous version.

Example:

```lua
local registry = require("mason-registry")
local pkg = registry.get_package("lua-language-server")

pkg:uninstall({}, function (success, result)
    if success then
        -- Do something on success.
    else
        -- Do something on error.
    end
end)
```

---

#### `Package:check_new_version()` has been removed.
`Breaking Change`

`Package:check_new_version()` is replaced by `Package:get_latest_version()`. `Package:get_latest_version()` is a
synchronous API.

> [!NOTE]
> Similarly to before, this function returns the package version provided by the currently installed registry version.

Example:
```lua
local registry = require("mason-registry")
local pkg = registry.get_package("lua-language-server")
local latest_version = pkg:get_latest_version()
```

---

#### `Package:get_installed_version()` is now synchronous.
`Breaking Change`

This function no longer accepts a callback.

Example:
```lua
local registry = require("mason-registry")
local pkg = registry.get_package("lua-language-server")
if pkg:is_installed() then
    local installed_version = pkg:get_installed_version()
end
```

---

#### `Package:install()` will now error if the package is currently being installed.
`Breaking Change`

Use the new `Package:is_installing()` method to check whether an installation is already running.

---

#### `Package:uninstall()` will now error if the package is not already installed.
`Breaking Change`

Use the new `Package:is_installed()` method to check whether the package is installed.

---

#### `Package:install(opts, callback)` now accepts a callback.

This optional callback is called by Mason when package installation finishes, successfully or not.

Example:

```lua
local registry = require("mason-registry")
local pkg = registry.get_package("lua-language-server")

pkg:install({}, function (success, result)
    if success then
        -- Do something on success.
    else
        -- Do something on error.
    end
end)
```

### Custom registries

v2.0.0 introduces official support for custom registries. Currently supported registry protocols are `github:`, `file:`,
and `lua:`. Lua-based registries have been reworked, please see https://github.com/mason-org/registry-examples for examples. 

Thanks to all sponsors who continue to help finance monthly costs and all 181 contributors of mason.nvim and 246
contributors of the core registry!

## [1.11.0](https://github.com/williamboman/mason.nvim/compare/v1.10.0...v1.11.0) (2025-02-15)


### Features

* **pypi:** improve resolving suitable python version ([#1725](https://github.com/williamboman/mason.nvim/issues/1725)) ([0950b15](https://github.com/williamboman/mason.nvim/commit/0950b15060067f752fde13a779a994f59516ce3d))
* **ui:** add backdrop ([#1759](https://github.com/williamboman/mason.nvim/issues/1759)) ([0a3a85f](https://github.com/williamboman/mason.nvim/commit/0a3a85fa1a59e0bb0811c87556dee51f027b3358))


### Bug Fixes

* avoid calling vim.fn in fast event ([#1878](https://github.com/williamboman/mason.nvim/issues/1878)) ([3a444cb](https://github.com/williamboman/mason.nvim/commit/3a444cb7b0cee6b1e2ed31b7e76f37509075dc46))
* avoid calling vim.fn.has inside fast event ([#1705](https://github.com/williamboman/mason.nvim/issues/1705)) ([1b3d604](https://github.com/williamboman/mason.nvim/commit/1b3d60405d1d720b2c4927f19672e9479703b00f))
* fix usage of deprecated Neovim APIs ([#1703](https://github.com/williamboman/mason.nvim/issues/1703)) ([0f1cb65](https://github.com/williamboman/mason.nvim/commit/0f1cb65f436b769733d18b41572f617a1fb41f62))
* **fs:** fall back to `fs_stat` if entry type is not returned by `fs_readdir` ([#1783](https://github.com/williamboman/mason.nvim/issues/1783)) ([1114b23](https://github.com/williamboman/mason.nvim/commit/1114b2336e917d883c30f89cd63ba94050001b2d))
* **health:** support multidigit luarocks version numbers ([#1648](https://github.com/williamboman/mason.nvim/issues/1648)) ([751b1fc](https://github.com/williamboman/mason.nvim/commit/751b1fcbf3d3b783fcf8d48865264a9bcd8f9b10))
* **pypi:** allow access to system site packages by default ([#1584](https://github.com/williamboman/mason.nvim/issues/1584)) ([2be2600](https://github.com/williamboman/mason.nvim/commit/2be2600f9b5a61b0c6109a3fb161b3abe75e5195))
* **pypi:** exclude python3.12 from candidate list ([#1722](https://github.com/williamboman/mason.nvim/issues/1722)) ([f8ce876](https://github.com/williamboman/mason.nvim/commit/f8ce8768f296717c72b3910eee7bd5ac5223cdb9))
* **pypi:** prefer stock python3 if it satisfies version requirement ([#1736](https://github.com/williamboman/mason.nvim/issues/1736)) ([f96a318](https://github.com/williamboman/mason.nvim/commit/f96a31855fa8aea55599cea412fe611b85a874ed))
* **registry:** exhaust streaming parser when loading "file:" registries ([#1708](https://github.com/williamboman/mason.nvim/issues/1708)) ([49ff59a](https://github.com/williamboman/mason.nvim/commit/49ff59aded1047a773670651cfa40e76e63c6377))
* replace deprecated calls to vim.validate ([#1876](https://github.com/williamboman/mason.nvim/issues/1876)) ([5664dd5](https://github.com/williamboman/mason.nvim/commit/5664dd5deb3ac9527da90691543eb28df51c1ef8))
* **ui:** fix rendering JSON schemas ([#1757](https://github.com/williamboman/mason.nvim/issues/1757)) ([e2f7f90](https://github.com/williamboman/mason.nvim/commit/e2f7f9044ec30067bc11800a9e266664b88cda22))
* **ui:** reposition window if border is different than "none" ([#1859](https://github.com/williamboman/mason.nvim/issues/1859)) ([f9f3b46](https://github.com/williamboman/mason.nvim/commit/f9f3b464dda319288b8ce592e53f0d9cf9ca8b4e))


### Performance Improvements

* **registry:** significantly improve the "file:" protocol performance ([#1702](https://github.com/williamboman/mason.nvim/issues/1702)) ([098a56c](https://github.com/williamboman/mason.nvim/commit/098a56c385ca3a1a0d4682d129203dda35421b8e))

## [1.10.0](https://github.com/williamboman/mason.nvim/compare/v1.9.0...v1.10.0) (2024-01-29)


### Features

* don't use vim.g.python3_host_prog as a candidate for python ([#1606](https://github.com/williamboman/mason.nvim/issues/1606)) ([bce96d2](https://github.com/williamboman/mason.nvim/commit/bce96d2fd483e71826728c6f9ac721fc9dd7d2cf))
* **pypi:** attempt more python3 candidates ([#1608](https://github.com/williamboman/mason.nvim/issues/1608)) ([dcd0ea3](https://github.com/williamboman/mason.nvim/commit/dcd0ea30ccfc7d47e879878d1270d6847a519181))


### Bug Fixes

* **golang:** fix fetching package versions for packages containing subpath specifier ([#1607](https://github.com/williamboman/mason.nvim/issues/1607)) ([9c94168](https://github.com/williamboman/mason.nvim/commit/9c9416817c9f4e6f333c749327a1ed5355cfab61))
* **pypi:** fix variable shadowing ([#1610](https://github.com/williamboman/mason.nvim/issues/1610)) ([aa550fb](https://github.com/williamboman/mason.nvim/commit/aa550fb0649643eee89d5e64c67f81916e88a736))
* **ui:** don't indent empty lines ([#1597](https://github.com/williamboman/mason.nvim/issues/1597)) ([c7e6705](https://github.com/williamboman/mason.nvim/commit/c7e67059bb8ce7e126263471645c531d961b5e1d))

## [1.9.0](https://github.com/williamboman/mason.nvim/compare/v1.8.3...v1.9.0) (2024-01-06)


### Features

* add support for openvsx sources ([#1589](https://github.com/williamboman/mason.nvim/issues/1589)) ([6c68547](https://github.com/williamboman/mason.nvim/commit/6c685476df4f202e371bdd3d726729d6f3f8b9f0))


### Bug Fixes

* **cargo:** don't attempt to fetch versions when version targets commit SHA ([#1585](https://github.com/williamboman/mason.nvim/issues/1585)) ([a09da6a](https://github.com/williamboman/mason.nvim/commit/a09da6ac634926a299dd439da08bdb547a8ca011))

## [1.8.3](https://github.com/williamboman/mason.nvim/compare/v1.8.2...v1.8.3) (2023-11-08)


### Bug Fixes

* **pypi:** support MSYS2 virtual environments on Windows ([#1547](https://github.com/williamboman/mason.nvim/issues/1547)) ([3e2432a](https://github.com/williamboman/mason.nvim/commit/3e2432ad0bca01fc3356389b341aa3e5e2da9fd8))

## [1.8.2](https://github.com/williamboman/mason.nvim/compare/v1.8.1...v1.8.2) (2023-10-31)


### Bug Fixes

* **registry:** fix parsing registry identifiers that contain ":" ([#1542](https://github.com/williamboman/mason.nvim/issues/1542)) ([87eb3ac](https://github.com/williamboman/mason.nvim/commit/87eb3ac2ab4fcbf5326d8bde6842b073a3be65a7))

## [1.8.1](https://github.com/williamboman/mason.nvim/compare/v1.8.0...v1.8.1) (2023-10-10)


### Bug Fixes

* **health:** schedule vim.fn call ([#1514](https://github.com/williamboman/mason.nvim/issues/1514)) ([3ba3b79](https://github.com/williamboman/mason.nvim/commit/3ba3b79f73d5411e72c7df5445150f4e9278d4d7))

## [1.8.0](https://github.com/williamboman/mason.nvim/compare/v1.7.0...v1.8.0) (2023-09-04)


### Features

* **ui:** add setting to toggle help view ([#1468](https://github.com/williamboman/mason.nvim/issues/1468)) ([e1602c8](https://github.com/williamboman/mason.nvim/commit/e1602c868f938877057cb6f45e50859cb55cad96))


### Bug Fixes

* **registry:** reset registries state when setting registries ([#1474](https://github.com/williamboman/mason.nvim/issues/1474)) ([c811fbf](https://github.com/williamboman/mason.nvim/commit/c811fbf09c7642eebb37d6694f1a016a043f6ed3))
* **registry:** schedule vim.fn calls in FileRegistrySource ([#1471](https://github.com/williamboman/mason.nvim/issues/1471)) ([1c77412](https://github.com/williamboman/mason.nvim/commit/1c77412d7ff73e453cdc5366c8d7cd98d2242802))

## [1.7.0](https://github.com/williamboman/mason.nvim/compare/v1.6.2...v1.7.0) (2023-08-25)


### Features

* **cargo:** support fetching versions for git crates hosted on github ([#1459](https://github.com/williamboman/mason.nvim/issues/1459)) ([e9eb004](https://github.com/williamboman/mason.nvim/commit/e9eb0048cecc577a1eec534485d3e010487b46a7))
* **registry:** add file: source protocol ([#1457](https://github.com/williamboman/mason.nvim/issues/1457)) ([8544039](https://github.com/williamboman/mason.nvim/commit/85440397264a31208721e4501c93b23a4940b27e))


### Bug Fixes

* **std:** use gtar if available ([#1433](https://github.com/williamboman/mason.nvim/issues/1433)) ([a51c2d0](https://github.com/williamboman/mason.nvim/commit/a51c2d063c5377ee9e58c5f9cda7c7436787be72))
* **ui:** properly reset new package version state ([#1454](https://github.com/williamboman/mason.nvim/issues/1454)) ([68e6a15](https://github.com/williamboman/mason.nvim/commit/68e6a153d7cd1251eb85ebb48d2e351e9ab940b8))

## [1.6.2](https://github.com/williamboman/mason.nvim/compare/v1.6.1...v1.6.2) (2023-08-09)


### Bug Fixes

* **ui:** don't disable search mode if empty pattern and last-pattern is set ([#1445](https://github.com/williamboman/mason.nvim/issues/1445)) ([be6f680](https://github.com/williamboman/mason.nvim/commit/be6f680774a75a06ceede3bd7159df2388f49b04))

## [1.6.1](https://github.com/williamboman/mason.nvim/compare/v1.6.0...v1.6.1) (2023-07-21)


### Bug Fixes

* **installer:** retain unmapped source fields ([#1399](https://github.com/williamboman/mason.nvim/issues/1399)) ([0579574](https://github.com/williamboman/mason.nvim/commit/05795741895ee16062eabeb0d89bff7cbcd693fa))

## [1.6.0](https://github.com/williamboman/mason.nvim/compare/v1.5.1...v1.6.0) (2023-07-04)


### Features

* **ui:** display package deprecation message ([#1391](https://github.com/williamboman/mason.nvim/issues/1391)) ([b728115](https://github.com/williamboman/mason.nvim/commit/b7281153cd9167d2b1a5d8cbda1ba8d4ad9fa8c2))
* **ui:** don't use diagnostic messages for displaying deprecated, uninstalled, packages ([#1393](https://github.com/williamboman/mason.nvim/issues/1393)) ([c290d0e](https://github.com/williamboman/mason.nvim/commit/c290d0e4ab6da9cac1e26684e53fba0b615862ed))

## [1.5.1](https://github.com/williamboman/mason.nvim/compare/v1.5.0...v1.5.1) (2023-06-28)


### Bug Fixes

* **linker:** ensure exec wrapper target is executable ([#1380](https://github.com/williamboman/mason.nvim/issues/1380)) ([10da1a3](https://github.com/williamboman/mason.nvim/commit/10da1a33b4ac24ad4d76a9af91871720ac6b65e4))
* **purl:** percent-encoding is case insensitive ([#1382](https://github.com/williamboman/mason.nvim/issues/1382)) ([b68d3be](https://github.com/williamboman/mason.nvim/commit/b68d3be4b664671002221d43c82e74a0f1006b26))

## [1.5.0](https://github.com/williamboman/mason.nvim/compare/v1.4.0...v1.5.0) (2023-06-28)


### Features

* **command:** add completion for option flags for :MasonInstall ([#1379](https://github.com/williamboman/mason.nvim/issues/1379)) ([e507af7](https://github.com/williamboman/mason.nvim/commit/e507af7b996dae90404345abb2bc88540f931589))
* **installer:** write more installation output to stdout ([#1376](https://github.com/williamboman/mason.nvim/issues/1376)) ([758ac5b](https://github.com/williamboman/mason.nvim/commit/758ac5b35e823eee74a90f855b2a66afc51ec92d))


### Bug Fixes

* **installer:** timeout schema download after 5s ([#1374](https://github.com/williamboman/mason.nvim/issues/1374)) ([d114376](https://github.com/williamboman/mason.nvim/commit/d11437645af60449ff252b2c9abda103c5610520))

## [1.4.0](https://github.com/williamboman/mason.nvim/compare/v1.3.0...v1.4.0) (2023-06-21)


### Features

* **fetch:** add explicit default timeout to requests ([#1364](https://github.com/williamboman/mason.nvim/issues/1364)) ([82cae55](https://github.com/williamboman/mason.nvim/commit/82cae550c87466b1163b216bdb9c71cb71dd8f67))
* **fetch:** include mason.nvim version in User-Agent ([#1362](https://github.com/williamboman/mason.nvim/issues/1362)) ([e706d30](https://github.com/williamboman/mason.nvim/commit/e706d305fbcc8701bd30e31dd727aee2853b9db9))

## [1.3.0](https://github.com/williamboman/mason.nvim/compare/v1.2.1...v1.3.0) (2023-06-18)


### Features

* **health:** add advice for Debian/Ubuntu regarding python3 venv ([#1358](https://github.com/williamboman/mason.nvim/issues/1358)) ([6f3853e](https://github.com/williamboman/mason.nvim/commit/6f3853e5ae8c200e29d2e394e479d9c3f8e018f5))

## [1.2.1](https://github.com/williamboman/mason.nvim/compare/v1.2.0...v1.2.1) (2023-06-13)


### Bug Fixes

* **providers:** fix some client providers and add some more ([#1354](https://github.com/williamboman/mason.nvim/issues/1354)) ([6f44955](https://github.com/williamboman/mason.nvim/commit/6f4495590a0f9e121b483c9b1236fbabbd80da7a))

## [1.2.0](https://github.com/williamboman/mason.nvim/compare/v1.1.1...v1.2.0) (2023-06-13)


### Features

* **command:** improve completion for :MasonInstall ([#1353](https://github.com/williamboman/mason.nvim/issues/1353)) ([13e26c8](https://github.com/williamboman/mason.nvim/commit/13e26c81ff5074ee8f095a791cd37fc1cec37377))


### Bug Fixes

* **async:** always check channel state ([#1351](https://github.com/williamboman/mason.nvim/issues/1351)) ([f503346](https://github.com/williamboman/mason.nvim/commit/f5033463bb911a136e577fc6f339328f162e2b4a))
* **command:** run :MasonUpdate synchronously in headless mode ([#1347](https://github.com/williamboman/mason.nvim/issues/1347)) ([0276793](https://github.com/williamboman/mason.nvim/commit/02767937fc2e1b214c854a8fdde26ae1d3529dd6))
* **functional:** strip_prefix and strip_suffix should not use patterns ([#1352](https://github.com/williamboman/mason.nvim/issues/1352)) ([f99b702](https://github.com/williamboman/mason.nvim/commit/f99b70233e49db2229350bb82d9ddc6e2f4131c0))

## [1.1.1](https://github.com/williamboman/mason.nvim/compare/v1.1.0...v1.1.1) (2023-05-29)


### Bug Fixes

* **ui:** improve search mode UI and remove redundant whitespaces ([#1332](https://github.com/williamboman/mason.nvim/issues/1332)) ([a18c031](https://github.com/williamboman/mason.nvim/commit/a18c031c72a3c7576ba5dc60ee30de8290c8757c))

## [1.1.0](https://github.com/williamboman/mason.nvim/compare/v1.0.1...v1.1.0) (2023-05-18)


### Features

* **installer:** lock package installation ([#1290](https://github.com/williamboman/mason.nvim/issues/1290)) ([227f8a9](https://github.com/williamboman/mason.nvim/commit/227f8a9aaae495f481c768f8346edfceaf6d2951))
* **ui:** add keymap setting for toggling package installation log ([#1268](https://github.com/williamboman/mason.nvim/issues/1268)) ([48bb1cc](https://github.com/williamboman/mason.nvim/commit/48bb1cc33a1fefe94f5ce4972446a1c6ad849f15))
* **ui:** add search mode ([#1306](https://github.com/williamboman/mason.nvim/issues/1306)) ([3b59f25](https://github.com/williamboman/mason.nvim/commit/3b59f25d435fb1b8d36c4cc26410c3569f0bd795))
* **ui:** display "update all" hint ([#1296](https://github.com/williamboman/mason.nvim/issues/1296)) ([e634134](https://github.com/williamboman/mason.nvim/commit/e634134312bb936f472468a401c9cae6485ab54b))


### Bug Fixes

* **sources:** don't skip installation if fixed version is not currently installed ([#1297](https://github.com/williamboman/mason.nvim/issues/1297)) ([9c5edf1](https://github.com/williamboman/mason.nvim/commit/9c5edf13c2e6bd5223eebfeb4557ccc841acaa0e))
* **ui:** use vim.cmd("") for nvim-0.7.0 compatibility ([#1307](https://github.com/williamboman/mason.nvim/issues/1307)) ([e60b855](https://github.com/williamboman/mason.nvim/commit/e60b855bfa8c7d34387200daa6e54a5e22d3da05))

## [1.0.1](https://github.com/williamboman/mason.nvim/compare/v1.0.0...v1.0.1) (2023-04-26)


### Bug Fixes

* **pypi:** also provide install_extra_args to pypi.install ([#1263](https://github.com/williamboman/mason.nvim/issues/1263)) ([646ef07](https://github.com/williamboman/mason.nvim/commit/646ef07907e0960987c13c0b13f69eb808cc66ad))


================================================
FILE: CONTRIBUTING.md
================================================
-   [Contribution policy](#contribution-policy)
-   [Adding a new package](#adding-a-new-package)
-   [Code style](#code-style)
-   [Generated code](#generated-code)
-   [Tests](#tests)
-   [Adding or changing a feature](#adding-or-changing-a-feature)
-   [Commit style](#commit-style)
-   [Pull requests](#pull-requests)

# Contribution policy

The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT
RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in [BCP 14][bcp14],
[RFC2119][rfc2119], and [RFC8174][rfc8174] when, and only when, they appear in all capitals, as shown here.

[bcp14]: https://tools.ietf.org/html/bcp14
[rfc2119]: https://tools.ietf.org/html/rfc2119
[rfc8174]: https://tools.ietf.org/html/rfc8174

# Adding a new package

Core `mason.nvim` package definitions reside within the [`github:mason-org/mason-registry`
registry](https://github.com/mason-org/mason-registry/). Contributions to add new packages MUST be done there (refer to
the README and existing package definitions).

# Code style

This project adheres to Editorconfig, Selene, and Stylua code style & formatting rules. New patches MUST adhere to these
coding styles.

# Generated code

Some changes such as adding or changing a package definition will require generating some new code. The changes to
generated code MAY be included in a pull request. If it's not included in a pull request, it will automatically be
generated and pushed to your branch before merge.

Generating code can be done on Unix systems like so:

```sh
make generate
```

# Tests

[Tests](https://github.com/mason-org/mason.nvim/tree/main/tests) MAY be added or modified to reflect any new changes.
Tests can be executed on Unix systems like so:

```sh
make test
FILE=tests/mason-core/managers/luarocks_spec.lua make test
```

# Adding or changing a feature

Adding or changing a feature MUST be preceded with an issue where scope and acceptance criteria are agreed upon with
project maintainers before implementation.

# Commit style

Commits SHOULD follow the [conventional commits guidelines](https://www.conventionalcommits.org/en/v1.0.0/).

# Pull requests

Once a pull request is marked as ready for review (i.e. not in draft mode), new changes SHOULD NOT be force-pushed to
the branch. Merge commits SHOULD be preferred over rebases.


================================================
FILE: LICENSE
================================================
                                 Apache License
                           Version 2.0, January 2004
                        http://www.apache.org/licenses/

   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION

   1. Definitions.

      "License" shall mean the terms and conditions for use, reproduction,
      and distribution as defined by Sections 1 through 9 of this document.

      "Licensor" shall mean the copyright owner or entity authorized by
      the copyright owner that is granting the License.

      "Legal Entity" shall mean the union of the acting entity and all
      other entities that control, are controlled by, or are under common
      control with that entity. For the purposes of this definition,
      "control" means (i) the power, direct or indirect, to cause the
      direction or management of such entity, whether by contract or
      otherwise, or (ii) ownership of fifty percent (50%) or more of the
      outstanding shares, or (iii) beneficial ownership of such entity.

      "You" (or "Your") shall mean an individual or Legal Entity
      exercising permissions granted by this License.

      "Source" form shall mean the preferred form for making modifications,
      including but not limited to software source code, documentation
      source, and configuration files.

      "Object" form shall mean any form resulting from mechanical
      transformation or translation of a Source form, including but
      not limited to compiled object code, generated documentation,
      and conversions to other media types.

      "Work" shall mean the work of authorship, whether in Source or
      Object form, made available under the License, as indicated by a
      copyright notice that is included in or attached to the work
      (an example is provided in the Appendix below).

      "Derivative Works" shall mean any work, whether in Source or Object
      form, that is based on (or derived from) the Work and for which the
      editorial revisions, annotations, elaborations, or other modifications
      represent, as a whole, an original work of authorship. For the purposes
      of this License, Derivative Works shall not include works that remain
      separable from, or merely link (or bind by name) to the interfaces of,
      the Work and Derivative Works thereof.

      "Contribution" shall mean any work of authorship, including
      the original version of the Work and any modifications or additions
      to that Work or Derivative Works thereof, that is intentionally
      submitted to Licensor for inclusion in the Work by the copyright owner
      or by an individual or Legal Entity authorized to submit on behalf of
      the copyright owner. For the purposes of this definition, "submitted"
      means any form of electronic, verbal, or written communication sent
      to the Licensor or its representatives, including but not limited to
      communication on electronic mailing lists, source code control systems,
      and issue tracking systems that are managed by, or on behalf of, the
      Licensor for the purpose of discussing and improving the Work, but
      excluding communication that is conspicuously marked or otherwise
      designated in writing by the copyright owner as "Not a Contribution."

      "Contributor" shall mean Licensor and any individual or Legal Entity
      on behalf of whom a Contribution has been received by Licensor and
      subsequently incorporated within the Work.

   2. Grant of Copyright License. Subject to the terms and conditions of
      this License, each Contributor hereby grants to You a perpetual,
      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
      copyright license to reproduce, prepare Derivative Works of,
      publicly display, publicly perform, sublicense, and distribute the
      Work and such Derivative Works in Source or Object form.

   3. Grant of Patent License. Subject to the terms and conditions of
      this License, each Contributor hereby grants to You a perpetual,
      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
      (except as stated in this section) patent license to make, have made,
      use, offer to sell, sell, import, and otherwise transfer the Work,
      where such license applies only to those patent claims licensable
      by such Contributor that are necessarily infringed by their
      Contribution(s) alone or by combination of their Contribution(s)
      with the Work to which such Contribution(s) was submitted. If You
      institute patent litigation against any entity (including a
      cross-claim or counterclaim in a lawsuit) alleging that the Work
      or a Contribution incorporated within the Work constitutes direct
      or contributory patent infringement, then any patent licenses
      granted to You under this License for that Work shall terminate
      as of the date such litigation is filed.

   4. Redistribution. You may reproduce and distribute copies of the
      Work or Derivative Works thereof in any medium, with or without
      modifications, and in Source or Object form, provided that You
      meet the following conditions:

      (a) You must give any other recipients of the Work or
          Derivative Works a copy of this License; and

      (b) You must cause any modified files to carry prominent notices
          stating that You changed the files; and

      (c) You must retain, in the Source form of any Derivative Works
          that You distribute, all copyright, patent, trademark, and
          attribution notices from the Source form of the Work,
          excluding those notices that do not pertain to any part of
          the Derivative Works; and

      (d) If the Work includes a "NOTICE" text file as part of its
          distribution, then any Derivative Works that You distribute must
          include a readable copy of the attribution notices contained
          within such NOTICE file, excluding those notices that do not
          pertain to any part of the Derivative Works, in at least one
          of the following places: within a NOTICE text file distributed
          as part of the Derivative Works; within the Source form or
          documentation, if provided along with the Derivative Works; or,
          within a display generated by the Derivative Works, if and
          wherever such third-party notices normally appear. The contents
          of the NOTICE file are for informational purposes only and
          do not modify the License. You may add Your own attribution
          notices within Derivative Works that You distribute, alongside
          or as an addendum to the NOTICE text from the Work, provided
          that such additional attribution notices cannot be construed
          as modifying the License.

      You may add Your own copyright statement to Your modifications and
      may provide additional or different license terms and conditions
      for use, reproduction, or distribution of Your modifications, or
      for any such Derivative Works as a whole, provided Your use,
      reproduction, and distribution of the Work otherwise complies with
      the conditions stated in this License.

   5. Submission of Contributions. Unless You explicitly state otherwise,
      any Contribution intentionally submitted for inclusion in the Work
      by You to the Licensor shall be under the terms and conditions of
      this License, without any additional terms or conditions.
      Notwithstanding the above, nothing herein shall supersede or modify
      the terms of any separate license agreement you may have executed
      with Licensor regarding such Contributions.

   6. Trademarks. This License does not grant permission to use the trade
      names, trademarks, service marks, or product names of the Licensor,
      except as required for reasonable and customary use in describing the
      origin of the Work and reproducing the content of the NOTICE file.

   7. Disclaimer of Warranty. Unless required by applicable law or
      agreed to in writing, Licensor provides the Work (and each
      Contributor provides its Contributions) on an "AS IS" BASIS,
      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
      implied, including, without limitation, any warranties or conditions
      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
      PARTICULAR PURPOSE. You are solely responsible for determining the
      appropriateness of using or redistributing the Work and assume any
      risks associated with Your exercise of permissions under this License.

   8. Limitation of Liability. In no event and under no legal theory,
      whether in tort (including negligence), contract, or otherwise,
      unless required by applicable law (such as deliberate and grossly
      negligent acts) or agreed to in writing, shall any Contributor be
      liable to You for damages, including any direct, indirect, special,
      incidental, or consequential damages of any character arising as a
      result of this License or out of the use or inability to use the
      Work (including but not limited to damages for loss of goodwill,
      work stoppage, computer failure or malfunction, or any and all
      other commercial damages or losses), even if such Contributor
      has been advised of the possibility of such damages.

   9. Accepting Warranty or Additional Liability. While redistributing
      the Work or Derivative Works thereof, You may choose to offer,
      and charge a fee for, acceptance of support, warranty, indemnity,
      or other liability obligations and/or rights consistent with this
      License. However, in accepting such obligations, You may act only
      on Your own behalf and on Your sole responsibility, not on behalf
      of any other Contributor, and only if You agree to indemnify,
      defend, and hold each Contributor harmless for any liability
      incurred by, or claims asserted against, such Contributor by reason
      of your accepting any such warranty or additional liability.


================================================
FILE: Makefile
================================================
INSTALL_ROOT_DIR:=$(shell pwd)/tests/fixtures/mason
NVIM_HEADLESS:=nvim --headless --noplugin -u tests/minimal_init.vim

dependencies:
	git clone --depth 1 https://github.com/nvim-lua/plenary.nvim dependencies/pack/vendor/start/plenary.nvim
	git clone --depth 1 https://github.com/nvim-neotest/neotest dependencies/pack/vendor/start/neotest

.PHONY: clean_dependencies
clean_dependencies:
	rm -rf dependencies

.PHONY: clean_fixtures
clean_fixtures:
	rm -rf "${INSTALL_ROOT_DIR}"

.PHONY: clean
clean: clean_fixtures clean_dependencies

.PHONY: test
test: clean_fixtures dependencies
	INSTALL_ROOT_DIR=${INSTALL_ROOT_DIR} $(NVIM_HEADLESS) -c "call RunTests()"

# vim:noexpandtab


================================================
FILE: PACKAGES.md
================================================
Moved to https://mason-registry.dev/registry/list


================================================
FILE: README.md
================================================
![Linux](https://img.shields.io/badge/Linux-%23.svg?logo=linux&color=FCC624&logoColor=black)
![macOS](https://img.shields.io/badge/macOS-%23.svg?logo=apple&color=000000&logoColor=white)
![Windows](https://img.shields.io/badge/Windows-%23.svg?logo=windows&color=0078D6&logoColor=white)
[![GitHub CI](https://github.com/mason-org/mason.nvim/workflows/Tests/badge.svg)](https://github.com/mason-org/mason.nvim/actions?query=workflow%3ATests+branch%3Amain+event%3Apush)
[![Sponsors](https://img.shields.io/github/sponsors/williamboman)](https://github.com/sponsors/williamboman)

<h1>
    <img src="https://user-images.githubusercontent.com/6705160/177613416-0c0354d2-f431-40d8-87f0-21310f0bba0e.png" alt="mason.nvim" />
</h1>

<p align="center">
    Portable package manager for Neovim that runs everywhere Neovim runs.<br />
    Easily install and manage LSP servers, DAP servers, linters, and formatters.<br />
</p>
<p align="center">
    <code>:help mason.nvim</code>
</p>
<p align="center">
    <sup>Latest version: v2.2.1</sup> <!-- x-release-please-version -->
</p>

## Table of Contents

-   [Introduction](#introduction)
-   [Installation & Usage](#installation--usage)
    - [Recommended setup for `lazy.nvim`](#recommended-setup-for-lazynvim)
-   [Requirements](#requirements)
-   [Commands](#commands)
-   [Registries](#registries)
-   [Screenshots](#screenshots)
-   [Configuration](#configuration)

## Introduction

> [`:h mason-introduction`][help-mason-introduction]

`mason.nvim` is a Neovim plugin that allows you to easily manage external editor tooling such as LSP servers, DAP servers,
linters, and formatters through a single interface. It runs everywhere Neovim runs (across Linux, macOS, Windows, etc.),
with only a small set of [external requirements](#requirements) needed.

Packages are installed in Neovim's data directory ([`:h standard-path`][help-standard-path]) by default. Executables are
linked to a single `bin/` directory, which `mason.nvim` will add to Neovim's PATH during setup, allowing seamless access
from Neovim builtins (LSP client, shell, terminal, etc.) as well as other 3rd party plugins.

For a list of all available packages, see <https://mason-registry.dev/registry/list>.

## Installation & Usage

> [`:h mason-quickstart`][help-mason-quickstart]

Install using your plugin manager of choice. **Setup is required**:

```lua
require("mason").setup()
```

`mason.nvim` is optimized to load as little as possible during setup. Lazy-loading the plugin, or somehow deferring the
setup, is not recommended.

Refer to the [Configuration](#configuration) section for information about which settings are available.

### Recommended setup for `lazy.nvim`

The following is the recommended setup when using `lazy.nvim`. It will set up the plugin for you, meaning **you don't have
to call `require("mason").setup()` yourself**.

```lua
{
    "mason-org/mason.nvim",
    opts = {}
}
```

## Requirements

> [`:h mason-requirements`][help-mason-requirements]

`mason.nvim` relaxes the minimum requirements by attempting multiple different utilities (for example, `wget`,
`curl`, and `Invoke-WebRequest` are all perfect substitutes).
The _minimum_ recommended requirements are:

-   neovim `>= 0.10.0`
-   For Unix systems:
    -   `git(1)`
    -   `curl(1)` or `GNU wget(1)`
    -   `unzip(1)`
    -   GNU tar (`tar(1)` or `gtar(1)` depending on platform)
    -   `gzip(1)`
-   For Windows systems:
    -   pwsh or powershell
    -   git
    -   GNU tar
    -   One of the following:
        -   [7zip][7zip]
        -   [peazip][peazip]
        -   [archiver][archiver]
        -   [winzip][winzip]
        -   [WinRAR][winrar]

Note that `mason.nvim` will regularly shell out to external package managers, such as `cargo` and `npm`. Depending on
your personal usage, some of these will also need to be installed. Refer to `:checkhealth mason` for a full list.

[7zip]: https://www.7-zip.org/
[archiver]: https://github.com/mholt/archiver
[peazip]: https://peazip.github.io/
[winzip]: https://www.winzip.com/
[winrar]: https://www.win-rar.com/

## Commands

> [`:h mason-commands`][help-mason-commands]

-   `:Mason` - opens a graphical status window
-   `:MasonUpdate` - updates all managed registries
-   `:MasonInstall <package> ...` - installs/re-installs the provided packages
-   `:MasonUninstall <package> ...` - uninstalls the provided packages
-   `:MasonUninstallAll` - uninstalls all packages
-   `:MasonLog` - opens the `mason.nvim` log file in a new tab window

## Registries

Mason's core package registry is located at [mason-org/mason-registry](https://github.com/mason-org/mason-registry).
Before any packages can be used, the registry needs to be downloaded. This is done automatically for you when using the
different Mason commands (e.g. `:MasonInstall`), but can also be done manually by using the `:MasonUpdate` command.

If you're utilizing Mason's Lua APIs to access packages, it's recommended to use the
[`:h mason-registry.refresh()`][help-mason-registry-refresh] or [`:h mason-registry.update()`][help-mason-registry-update]
functions to ensure you have the latest package information before retrieving packages.

## Screenshots

|                                                                                                                                                        |                                                                                                                                                  |                                                                                                                                        |
| :----------------------------------------------------------------------------------------------------------------------------------------------------: | :----------------------------------------------------------------------------------------------------------------------------------------------: | :------------------------------------------------------------------------------------------------------------------------------------: |
|           <img alt="Main window" src="https://github.com/user-attachments/assets/b9a57d21-f551-45ad-a1e5-a9fd66291510">           |                 <img alt="Language search" src="https://github.com/user-attachments/assets/3d24fb7b-2c57-4948-923b-0a42bb627cbe">                 | <img alt="Language filter" src="https://github.com/user-attachments/assets/c0ca5818-3c74-4071-bc41-427a2cd1056d"> |
| <img alt="Package information" src="https://github.com/user-attachments/assets/6f9f6819-ac97-483d-a77c-8f6c6131ac85"> | <img alt="New package versions" src="https://github.com/user-attachments/assets/ff1adc4d-2fcc-46df-ab4c-291c891efa50"> |   <img alt="Help window" src="https://github.com/user-attachments/assets/1fbe75e4-fe69-4417-83e3-82329e1c236e">   |

## Configuration

> [`:h mason-settings`][help-mason-settings]

You may optionally configure certain behavior of `mason.nvim` when calling the `.setup()` function. Refer to the
[default configuration](#default-configuration) for a list of all available settings.

Example:

```lua
require("mason").setup({
    ui = {
        icons = {
            package_installed = "✓",
            package_pending = "➜",
            package_uninstalled = "✗"
        }
    }
})
```

### Configuration using `lazy.nvim`

```lua
{
    "mason-org/mason.nvim",
    opts = {
        ui = {
            icons = {
                package_installed = "✓",
                package_pending = "➜",
                package_uninstalled = "✗"
            }
        }
    }
}
```

### Default configuration

```lua
---@class MasonSettings
local DEFAULT_SETTINGS = {
    ---@since 1.0.0
    -- The directory in which to install packages.
    install_root_dir = path.concat { vim.fn.stdpath "data", "mason" },

    ---@since 1.0.0
    -- Where Mason should put its bin location in your PATH. Can be one of:
    -- - "prepend" (default, Mason's bin location is put first in PATH)
    -- - "append" (Mason's bin location is put at the end of PATH)
    -- - "skip" (doesn't modify PATH)
    ---@type '"prepend"' | '"append"' | '"skip"'
    PATH = "prepend",

    ---@since 1.0.0
    -- Controls to which degree logs are written to the log file. It's useful to set this to vim.log.levels.DEBUG when
    -- debugging issues with package installations.
    log_level = vim.log.levels.INFO,

    ---@since 1.0.0
    -- Limit for the maximum amount of packages to be installed at the same time. Once this limit is reached, any further
    -- packages that are requested to be installed will be put in a queue.
    max_concurrent_installers = 4,

    ---@since 1.0.0
    -- [Advanced setting]
    -- The registries to source packages from. Accepts multiple entries. Should a package with the same name exist in
    -- multiple registries, the registry listed first will be used.
    registries = {
        "github:mason-org/mason-registry",
    },

    ---@since 1.0.0
    -- The provider implementations to use for resolving supplementary package metadata (e.g., all available versions).
    -- Accepts multiple entries, where later entries will be used as fallback should prior providers fail.
    -- Builtin providers are:
    --   - mason.providers.registry-api  - uses the https://api.mason-registry.dev API
    --   - mason.providers.client        - uses only client-side tooling to resolve metadata
    providers = {
        "mason.providers.registry-api",
        "mason.providers.client",
    },

    github = {
        ---@since 1.0.0
        -- The template URL to use when downloading assets from GitHub.
        -- The placeholders are the following (in order):
        -- 1. The repository (e.g. "rust-lang/rust-analyzer")
        -- 2. The release version (e.g. "v0.3.0")
        -- 3. The asset name (e.g. "rust-analyzer-v0.3.0-x86_64-unknown-linux-gnu.tar.gz")
        download_url_template = "https://github.com/%s/releases/download/%s/%s",
    },

    pip = {
        ---@since 1.0.0
        -- Whether to upgrade pip to the latest version in the virtual environment before installing packages.
        upgrade_pip = false,

        ---@since 1.0.0
        -- These args will be added to `pip install` calls. Note that setting extra args might impact intended behavior
        -- and is not recommended.
        --
        -- Example: { "--proxy", "https://proxyserver" }
        install_args = {},
    },

    ui = {
        ---@since 1.0.0
        -- Whether to automatically check for new versions when opening the :Mason window.
        check_outdated_packages_on_open = true,

        ---@since 1.0.0
        -- The border to use for the UI window. Accepts same border values as |nvim_open_win()|.
        -- Defaults to `:h 'winborder'` if nil.
        border = nil,

        ---@since 1.11.0
        -- The backdrop opacity. 0 is fully opaque, 100 is fully transparent.
        backdrop = 60,

        ---@since 1.0.0
        -- Width of the window. Accepts:
        -- - Integer greater than 1 for fixed width.
        -- - Float in the range of 0-1 for a percentage of screen width.
        width = 0.8,

        ---@since 1.0.0
        -- Height of the window. Accepts:
        -- - Integer greater than 1 for fixed height.
        -- - Float in the range of 0-1 for a percentage of screen height.
        height = 0.9,

        icons = {
            ---@since 1.0.0
            -- The list icon to use for installed packages.
            package_installed = "◍",
            ---@since 1.0.0
            -- The list icon to use for packages that are installing, or queued for installation.
            package_pending = "◍",
            ---@since 1.0.0
            -- The list icon to use for packages that are not installed.
            package_uninstalled = "◍",
        },

        keymaps = {
            ---@since 1.0.0
            -- Keymap to expand a package
            toggle_package_expand = "<CR>",
            ---@since 1.0.0
            -- Keymap to install the package under the current cursor position
            install_package = "i",
            ---@since 1.0.0
            -- Keymap to reinstall/update the package under the current cursor position
            update_package = "u",
            ---@since 1.0.0
            -- Keymap to check for new version for the package under the current cursor position
            check_package_version = "c",
            ---@since 1.0.0
            -- Keymap to update all installed packages
            update_all_packages = "U",
            ---@since 1.0.0
            -- Keymap to check which installed packages are outdated
            check_outdated_packages = "C",
            ---@since 1.0.0
            -- Keymap to uninstall a package
            uninstall_package = "X",
            ---@since 1.0.0
            -- Keymap to cancel a package installation
            cancel_installation = "<C-c>",
            ---@since 1.0.0
            -- Keymap to apply language filter
            apply_language_filter = "<C-f>",
            ---@since 1.1.0
            -- Keymap to toggle viewing package installation log
            toggle_package_install_log = "<CR>",
            ---@since 1.8.0
            -- Keymap to toggle the help view
            toggle_help = "g?",
        },
    },
}
```

---

<sup>
👋 didn't find what you were looking for? Try looking in the <a href="./doc/mason.txt">help docs</a> <code>:help mason.nvim</code>!
</sup>

[help-mason-commands]: ./doc/mason.txt#L140
[help-mason-introduction]: ./doc/mason.txt#L11
[help-mason-quickstart]: ./doc/mason.txt#L42
[help-mason-registry-refresh]: ./doc/mason.txt#L520
[help-mason-registry-update]: ./doc/mason.txt#L513
[help-mason-requirements]: ./doc/mason.txt#L25
[help-mason-settings]: ./doc/mason.txt#L200
[help-standard-path]: https://neovim.io/doc/user/starting.html#standard-path


================================================
FILE: SECURITY.md
================================================
# Security policy

## Reporting a Vulnerability

Please report any suspected security vulnerabilities [here][new-advisory]. If the issue is confirmed, we will release a
patch as soon as possible depending on complexity. Please follow [responsible disclosure
practices](https://en.wikipedia.org/wiki/Coordinated_vulnerability_disclosure). Thanks!

[new-advisory]: https://github.com/mason-org/mason.nvim/security/advisories/new


================================================
FILE: doc/.gitignore
================================================
tags


================================================
FILE: doc/mason.txt
================================================
*mason.nvim*

Minimum version of neovim: 0.10.0

Author: William Boman
                                                            *mason-help-guide*
                                       Type |gO| to see the table of contents.
                        Press |K| on a helptag to jump to it: |mason-help-guide|

==============================================================================
INTRODUCTION                                              *mason-introduction*

`mason.nvim` is a Neovim plugin that allows you to easily manage external
editor tooling such as LSP servers, DAP servers, linters, and formatters
through a single interface. It runs everywhere Neovim runs (across Linux,
macOS, Windows, etc.), with only a small set of external requirements needed.

Packages are installed in Neovim's data directory (`:h standard-path`) by
default. Executables are linked to a single `bin/` directory, which
`mason.nvim` will add to Neovim's PATH during setup, allowing seamless access
from Neovim builtins (shell, terminal, etc.) as well as other 3rd party
plugins.

==============================================================================
REQUIREMENTS                                              *mason-requirements*

`mason.nvim` relaxes the minimum requirements by attempting multiple different
utilities (for example, `wget`, `curl`, and `Invoke-WebRequest` are all
perfect substitutes). The _minimum_ recommended requirements are:

-   neovim `>= 0.10.0`
-   For Unix systems: `git(1)`, `curl(1)` or `wget(1)`, `unzip(1)`, `tar(1)`,
    `gzip(1)`
-   For Windows systems: pwsh or powershell, git, tar, and 7zip or peazip or
    archiver or winzip or WinRAR

Note that Mason will regularly shell out to external package managers,
such as `cargo` and `npm`. Depending on your personal usage, some of these
will also need to be installed. Refer to `:checkhealth mason` for a full list.

==============================================================================
QUICK START                                                 *mason-quickstart*

-----------------
SETTING UP MASON.NVIM

First you'll need to set up Mason. This is done by calling the `setup()`
function:
>lua
    require("mason").setup()
<
Mason will do the following during setup:
    1) add Mason's `bin/` directory to the Neovim session's PATH
    2) register commands (|mason-commands|)

Refer to |mason-settings| for all available settings.

-----------------
INSTALLING PACKAGES

Install a package via |:MasonInstall|, for example:
>vim
    :MasonInstall stylua
<
You may also install multiple packages at a time:
>vim
    :MasonInstall stylua lua-language-server
<
To install a specific version of a package, you may provide it as part of the
package name, like so:
>vim
    :MasonInstall rust-analyzer@nightly
<
Please refer to each package's own release pages to find which versions are
available.

You may also install packages in headless mode. This will run the command in
blocking mode and the command won't yield back until all packages have
finished installing:
>sh
    $ nvim --headless -c "MasonInstall lua-language-server rust-analyzer" -c qall
<
Note: ~
    You may also use Mason's Lua API to programmatically manage package
    installations. Through this interface you will also gain access to more
    features to allow further customization.

-----------------
THE MASON WINDOW

To view the UI for mason, run: >vim
    :Mason
<

Through this UI you may explore which packages that are available, see which
installed packages have new versions available, install, uninstall, or update
packages, expand package information, and more. The UI comes with a set of
keybinds which you may find in the help view by pressing `g?` when the Mason
window is open.

==============================================================================
REGISTRIES                                                  *mason-registries*

`mason.nvim` sources package definitions from the registries it has been
configured with (see |mason-settings|). `mason.nvim` uses the core registry,
governed by `mason.nvim`, by default. This may be extended, or even entirely
overridden, through additional registries, like so:

>lua
    require("mason").setup {
        registries = {
            "lua:my-registry",
            "github:mason-org/mason-registry",
        },
    }
<

Packages are loaded from registries in the order they've been configured,
with registries appearing first in the list having precedence.

==============================================================================
HOW TO INSTALL PACKAGES                        *mason-how-to-install-packages*

You may install packages either via the command interface or via Mason's Lua
APIs. See |:MasonInstall| for more details.

==============================================================================
HOW TO USE PACKAGES                                *mason-how-to-use-packages*

Although many packages are perfectly usable out of the box through Neovim
builtins, it is recommended to use other 3rd party plugins to further
integrate these.

See also ~
    Execute external commands: |:!cmd|.
    Launch an embedded terminal: |terminal|.
    Launch background jobs: |jobstart| & |uv.spawn()| (via |vim.loop|)

==============================================================================
COMMANDS                                                      *mason-commands*

------------------------------------------------------------------------------
OPEN THE MASON WINDOW                                                 *:Mason*

:Mason

Opens the graphical status window.

Through this UI you may explore which packages that are available, see which
installed packages have new versions available, install, uninstall, or update
packages, expand package information, and more. The UI comes with a set of
keybinds which you may find in the help view by pressing `g?` when the Mason
window is open.

------------------------------------------------------------------------------
UPDATE REGISTRIES                                               *:MasonUpdate*
>vim
:MasonUpdate
<
Updates all managed registries.

------------------------------------------------------------------------------
INSTALLING PACKAGES                                            *:MasonInstall*
>vim
:MasonInstall <package> ...
<
Installs the provided packages. Packages may include a version specifier,
like so:
>vim
    :MasonInstall lua-language-server@v3.0.0
<
Runs in blocking fashion if there are no UIs attached (i.e. running in
headless mode):
>sh
    $ nvim --headless -c "MasonInstall stylua" -c "qall"
<
------------------------------------------------------------------------------
UNINSTALLING PACKAGES                                        *:MasonUninstall*
>vim
:MasonUninstall <package> ...
<

Uninstalls the provided packages.

------------------------------------------------------------------------------
UNINSTALLING ALL PACKAGES                                 *:MasonUninstallAll*
>vim
:MasonUninstallAll
<
Uninstalls all installed packages.

------------------------------------------------------------------------------
VIEW THE MASON LOG                                                 *:MasonLog*
>vim
:MasonLog
<
Opens the log file in a new tab window.

==============================================================================
SETTINGS                                                      *mason-settings*

You can configure certain behavior of mason when calling the `.setup()`
function.

Refer to the |mason-default-settings| for all available settings.

Example:
>lua
    require("mason").setup({
        ui = {
            icons = {
                package_installed = "✓",
                package_pending = "➜",
                package_uninstalled = "✗"
            }
        }
    })
<
                                                      *mason-default-settings*
>lua
    ---@class MasonSettings
    local DEFAULT_SETTINGS = {
        ---@since 1.0.0
        -- The directory in which to install packages.
        install_root_dir = path.concat { vim.fn.stdpath "data", "mason" },

        ---@since 1.0.0
        -- Where Mason should put its bin location in your PATH. Can be one of:
        -- - "prepend" (default, Mason's bin location is put first in PATH)
        -- - "append" (Mason's bin location is put at the end of PATH)
        -- - "skip" (doesn't modify PATH)
        ---@type '"prepend"' | '"append"' | '"skip"'
        PATH = "prepend",

        ---@since 1.0.0
        -- Controls to which degree logs are written to the log file. It's useful to set this to vim.log.levels.DEBUG when
        -- debugging issues with package installations.
        log_level = vim.log.levels.INFO,

        ---@since 1.0.0
        -- Limit for the maximum amount of packages to be installed at the same time. Once this limit is reached, any further
        -- packages that are requested to be installed will be put in a queue.
        max_concurrent_installers = 4,

        ---@since 1.0.0
        -- [Advanced setting]
        -- The registries to source packages from. Accepts multiple entries. Should a package with the same name exist in
        -- multiple registries, the registry listed first will be used.
        registries = {
            "github:mason-org/mason-registry",
        },

        ---@since 1.0.0
        -- The provider implementations to use for resolving supplementary package metadata (e.g., all available versions).
        -- Accepts multiple entries, where later entries will be used as fallback should prior providers fail.
        -- Builtin providers are:
        --   - mason.providers.registry-api  - uses the https://api.mason-registry.dev API
        --   - mason.providers.client        - uses only client-side tooling to resolve metadata
        providers = {
            "mason.providers.registry-api",
            "mason.providers.client",
        },

        github = {
            ---@since 1.0.0
            -- The template URL to use when downloading assets from GitHub.
            -- The placeholders are the following (in order):
            -- 1. The repository (e.g. "rust-lang/rust-analyzer")
            -- 2. The release version (e.g. "v0.3.0")
            -- 3. The asset name (e.g. "rust-analyzer-v0.3.0-x86_64-unknown-linux-gnu.tar.gz")
            download_url_template = "https://github.com/%s/releases/download/%s/%s",
        },

        pip = {
            ---@since 1.0.0
            -- Whether to upgrade pip to the latest version in the virtual environment before installing packages.
            upgrade_pip = false,

            ---@since 1.0.0
            -- These args will be added to `pip install` calls. Note that setting extra args might impact intended behavior
            -- and is not recommended.
            --
            -- Example: { "--proxy", "https://proxyserver" }
            install_args = {},
        },

        ui = {
            ---@since 1.0.0
            -- Whether to automatically check for new versions when opening the :Mason window.
            check_outdated_packages_on_open = true,

            ---@since 1.0.0
            -- The border to use for the UI window. Accepts same border values as |nvim_open_win()|.
            -- Defaults to `:h 'winborder'` if nil.
            border = nil,

            ---@since 1.11.0
            -- The backdrop opacity. 0 is fully opaque, 100 is fully transparent.
            backdrop = 60,

            ---@since 1.0.0
            -- Width of the window. Accepts:
            -- - Integer greater than 1 for fixed width.
            -- - Float in the range of 0-1 for a percentage of screen width.
            width = 0.8,

            ---@since 1.0.0
            -- Height of the window. Accepts:
            -- - Integer greater than 1 for fixed height.
            -- - Float in the range of 0-1 for a percentage of screen height.
            height = 0.9,

            icons = {
                ---@since 1.0.0
                -- The list icon to use for installed packages.
                package_installed = "◍",
                ---@since 1.0.0
                -- The list icon to use for packages that are installing, or queued for installation.
                package_pending = "◍",
                ---@since 1.0.0
                -- The list icon to use for packages that are not installed.
                package_uninstalled = "◍",
            },

            keymaps = {
                ---@since 1.0.0
                -- Keymap to expand a package
                toggle_package_expand = "<CR>",
                ---@since 1.0.0
                -- Keymap to install the package under the current cursor position
                install_package = "i",
                ---@since 1.0.0
                -- Keymap to reinstall/update the package under the current cursor position
                update_package = "u",
                ---@since 1.0.0
                -- Keymap to check for new version for the package under the current cursor position
                check_package_version = "c",
                ---@since 1.0.0
                -- Keymap to update all installed packages
                update_all_packages = "U",
                ---@since 1.0.0
                -- Keymap to check which installed packages are outdated
                check_outdated_packages = "C",
                ---@since 1.0.0
                -- Keymap to uninstall a package
                uninstall_package = "X",
                ---@since 1.0.0
                -- Keymap to cancel a package installation
                cancel_installation = "<C-c>",
                ---@since 1.0.0
                -- Keymap to apply language filter
                apply_language_filter = "<C-f>",
                ---@since 1.1.0
                -- Keymap to toggle viewing package installation log
                toggle_package_install_log = "<CR>",
                ---@since 1.8.0
                -- Keymap to toggle the help view
                toggle_help = "g?",
            },
        },
    }
<

==============================================================================
DOWNLOAD MIRRORS                                      *mason-download-mirrors*

------------------------------------------------------------------------------
GITHUB MIRROR                                   *mason-download-mirror-github*

    It's possible to customize the download URL used when downloading assets
    from GitHub releases by setting the `github.download_url_template`
    settings during setup, like so:
>lua
    require("mason").setup {
        github = {
            -- The template URL to use when downloading assets from GitHub.
            -- The placeholders are the following (in order):
            -- 1. The repository (e.g. "rust-lang/rust-analyzer")
            -- 2. The release version (e.g. "v0.3.0")
            -- 3. The asset name (e.g. "rust-analyzer-v0.3.0-x86_64-unknown-linux-gnu.tar.gz")
            download_url_template = "https://my.mirror.com/%s/releases/download/%s/%s",
        },
    }
<

==============================================================================
INSTALLATION ERRORS                                             *mason-errors*

                                                       *mason-provider-errors*
By default, Mason uses the api.mason-registry.dev API to resolve package
metadata. Calling this service may result in network errors on some networks
(e.g., SSL issues on corporate VPNs). If resolving the SSL error is not an
option, you will have to change the provider implementation. Mason provides a
client provider which calls underlying 3rd party service APIs directly, which
you can enable like so:
>lua
    require("mason").setup {
        providers = {
            "mason.providers.client",
            "mason.providers.registry-api",
        }
    }
<
    Note: ~
        The client provider have less overall coverage and may come with
        additional performance penalties (spawning slow commands, network &
        parsing overheads, etc.).

==============================================================================
DEBUGGING                                                    *mason-debugging*

To help with debugging issues with installing/uninstalling packages, please
make sure to set mason's log level to DEBUG or TRACE, like so:
>lua
    require("mason").setup {
        log_level = vim.log.levels.DEBUG
    }
<
You may find the logs by entering the command `:MasonLog`. Providing the
contents of this file when reporting an issue will help tremendously. Remember
to redo whatever is failing after changing the log level in order to capture
new log entries.

==============================================================================
Lua module: "mason"
>lua
    require("mason")
<
                                                               *mason.setup()*
setup({config})
    Sets up mason with the provided {config} (see |mason-settings|).

==============================================================================
Lua module: "mason-registry"
>lua
    require("mason-registry")
<
                                               *mason-registry.is_installed()*
is_installed({package_name})
    Checks whether the provided package name is installed. In many situations,
    this is a more efficient option than the Package:is_installed() method due
    to a smaller amount of modules required to load.

    Parameters:
        {package_name} - string

    Returns:
        boolean

                                                *mason-registry.get_package()*
get_package({package_name})
    Returns an instance of the Package class if the provided package name
    exists.

    This function errors if a package cannot be found.

    Parameters:
        {package_name} - string

    Returns:
        Package

                                                *mason-registry.has_package()*
has_package({package_name})
    Returns true if the provided package_name can be found in the registry.

    Parameters:
        {package_name} - string

    Returns:
        boolean

                                     *mason-registry.get_installed_packages()*
get_installed_packages()
    Returns all installed package instances. This is a slower function that
    loads more modules.

    Returns:
        Package[]

                                *mason-registry.get_installed_package_names()*
get_installed_package_names()
    Returns all installed package names. This is a fast function that doesn't
    load any extra modules.

    Returns:
        string[]

                                           *mason-registry.get_all_packages()*
get_all_packages()
    Returns all package instances. This is a slower function that loads more
    modules.

    Returns:
        Package[]

                                      *mason-registry.get_all_package_names()*
get_all_package_names()
    Returns all package names. This is a faster function than
    |mason-registry.get_all_packages()| because it loads fewer modules.

    Returns:
        string[]

                                      *mason-registry.get_all_package_specs()*
get_all_package_specs()
    Returns all package specifications. This is a faster function than
    |mason-registry.get_all_packages()| because it loads fewer modules.

    Returns:
        RegistryPackageSpec[]

                                                     *mason-registry.update()*
update({callback})
    Updates all managed registries.

    Parameters:
        {callback} - Callback of the signature `fun(success: boolean, updated_registries: RegistrySource[])`

                                                    *mason-registry.refresh()*
refresh({callback?})
    Refreshes all registries if needed. This is a convenience wrapper around
    |mason-registry.update()| that only updates registries if:
        1) registries haven't been updated in a while
        2) or, one or more registries are not installed

    Runs in a blocking fashion if no {callback} is provided. Note that when
    running in blocking fashion the entire editor is frozen, so prefer the
    asynchronous variant unless absolutely needed.

    Parameters:
        {callback?} (optional) - Invoked when the registry has been refreshed.

    Example:
>lua
        local registry = require("mason-registry")

        -- 1. synchronous
        registry.refresh()
        local packages = registry.get_all_packages()
        ...

        -- 2. asynchronous
        registry.refresh(function ()
            local packages = registry.get_all_packages()
            ...
        end)
<


vim:tw=78:ft=help:norl:expandtab:sw=4


================================================
FILE: lua/mason/api/command.lua
================================================
local _ = require "mason-core.functional"
local platform = require "mason-core.platform"

local function Mason()
    require("mason.ui").open()
end

vim.api.nvim_create_user_command("Mason", Mason, {
    desc = "Opens mason's UI window.",
    nargs = 0,
})

local get_valid_packages = _.filter_map(function(pkg_specifier)
    local Optional = require "mason-core.optional"
    local notify = require "mason-core.notify"
    local Package = require "mason-core.package"
    local registry = require "mason-registry"
    local package_name, version = Package.Parse(pkg_specifier)
    local ok, pkg = pcall(registry.get_package, package_name)
    if ok and pkg then
        return Optional.of { pkg = pkg, version = version }
    else
        notify(("%q is not a valid package."):format(pkg_specifier), vim.log.levels.ERROR)
        return Optional.empty()
    end
end)

---@param package_specifiers string[]
---@param opts? table<string, string | boolean>
local function MasonInstall(package_specifiers, opts)
    opts = opts or {}
    local a = require "mason-core.async"
    local registry = require "mason-registry"
    local Optional = require "mason-core.optional"

    local install_packages = _.filter_map(function(target)
        if target.pkg:is_installing() then
            return Optional.empty()
        else
            return Optional.of(target.pkg:install {
                version = target.version,
                debug = opts.debug,
                force = opts.force,
                strict = opts.strict,
                target = opts.target,
            })
        end
    end)

    if platform.is_headless then
        registry.refresh()
        local valid_packages = get_valid_packages(package_specifiers)
        if #valid_packages ~= #package_specifiers then
            -- When executing in headless mode we don't allow any of the provided packages to be invalid.
            -- This is to avoid things like scripts silently not erroring even if they've provided one or more invalid packages.
            return vim.cmd [[1cq]]
        end
        a.run_blocking(function()
            local results = {
                a.wait_all(_.map(
                    ---@param target { pkg: Package, version: string? }
                    function(target)
                        return function()
                            if target.pkg:is_installing() then
                                return
                            end
                            return a.wait(function(resolve)
                                local handle = target.pkg:install({
                                    version = target.version,
                                    debug = opts.debug,
                                    force = opts.force,
                                    strict = opts.strict,
                                    target = opts.target,
                                }, function(success, err)
                                    resolve { success, target.pkg, err }
                                end)
                                if not opts.quiet then
                                    handle
                                        :on("stdout", vim.schedule_wrap(vim.api.nvim_out_write))
                                        :on("stderr", vim.schedule_wrap(vim.api.nvim_err_write))
                                end
                            end)
                        end
                    end,
                    valid_packages
                )),
            }
            a.scheduler()

            local is_failure = _.compose(_.equals(false), _.head)
            if _.any(is_failure, results) then
                local failures = _.filter(is_failure, results)
                local failed_packages = _.map(_.nth(2), failures)
                for _, failure in ipairs(failures) do
                    local _, pkg, error = unpack(failure)
                    vim.api.nvim_err_writeln(("Package %s failed with the following error:"):format(pkg.name))
                    vim.api.nvim_err_writeln(tostring(error))
                end
                vim.cmd [[1cq]]
            end
        end)
    else
        local ui = require "mason.ui"
        ui.open()
        -- Important: We start installation of packages _after_ opening the UI. This gives the UI components a chance to
        -- register the necessary event handlers in time, avoiding desynced state.
        registry.refresh(function()
            local valid_packages = get_valid_packages(package_specifiers)
            install_packages(valid_packages)
            vim.schedule(function()
                ui.set_sticky_cursor "installing-section"
            end)
        end)
    end
end

local parse_opts = _.compose(
    _.from_pairs,
    _.map(_.compose(function(arg)
        if #arg == 2 then
            return arg
        else
            return { arg[1], true }
        end
    end, _.split "=", _.gsub("^%-%-", "")))
)

---@param args string[]
---@return table<string, true|string> opts, string[] args
local function parse_args(args)
    local opts_list, args = unpack(_.partition(_.starts_with "--", args))
    local opts = parse_opts(opts_list)
    return opts, args
end

vim.api.nvim_create_user_command("MasonInstall", function(opts)
    local command_opts, packages = parse_args(opts.fargs)
    MasonInstall(packages, command_opts)
end, {
    desc = "Install one or more packages.",
    nargs = "+",
    ---@param arg_lead string
    complete = function(arg_lead)
        local registry = require "mason-registry"
        registry.refresh()
        if _.starts_with("--", arg_lead) then
            return _.filter(_.starts_with(arg_lead), {
                "--debug",
                "--force",
                "--strict",
                "--target=",
            })
        elseif _.matches("^.+@", arg_lead) then
            local pkg_name, version = unpack(_.match("^(.+)@(.*)", arg_lead))
            local ok, pkg = pcall(registry.get_package, pkg_name)
            if not ok or not pkg then
                return {}
            end
            local a = require "mason-core.async"
            return a.run_blocking(function()
                return a.wait_first {
                    function()
                        return pkg:get_all_versions()
                            :map(
                                _.compose(
                                    _.map(_.concat(arg_lead)),
                                    _.map(_.strip_prefix(version)),
                                    _.filter(_.starts_with(version))
                                )
                            )
                            :get_or_else {}
                    end,
                    function()
                        a.sleep(4000)
                        return {}
                    end,
                }
            end)
        end

        local all_pkg_names = registry.get_all_package_names()
        return _.sort_by(_.identity, _.filter(_.starts_with(arg_lead), all_pkg_names))
    end,
})

---@param package_names string[]
local function MasonUninstall(package_names)
    local valid_packages = get_valid_packages(package_names)
    if #valid_packages > 0 then
        _.each(function(target)
            target.pkg:uninstall()
        end, valid_packages)
        require("mason.ui").open()
    end
end

vim.api.nvim_create_user_command("MasonUninstall", function(opts)
    MasonUninstall(opts.fargs)
end, {
    desc = "Uninstall one or more packages.",
    nargs = "+",
    ---@param arg_lead string
    complete = function(arg_lead)
        local registry = require "mason-registry"
        return _.sort_by(_.identity, _.filter(_.starts_with(arg_lead), registry.get_installed_package_names()))
    end,
})

local function MasonUninstallAll()
    local registry = require "mason-registry"
    require("mason.ui").open()
    for _, pkg in ipairs(registry.get_installed_packages()) do
        pkg:uninstall()
    end
end

vim.api.nvim_create_user_command("MasonUninstallAll", MasonUninstallAll, {
    desc = "Uninstall all packages.",
})

local function MasonUpdate()
    local notify = require "mason-core.notify"
    local registry = require "mason-registry"
    notify "Updating registries…"

    ---@param success boolean
    ---@param updated_registries RegistrySource[]
    local function handle_result(success, updated_registries)
        if success then
            local count = #updated_registries
            notify(("Successfully updated %d %s."):format(count, count == 1 and "registry" or "registries"))
        else
            notify(("Failed to update registries: %s"):format(updated_registries), vim.log.levels.ERROR)
        end
    end

    if platform.is_headless then
        local a = require "mason-core.async"
        a.run_blocking(function()
            local success, updated_registries = a.wait(registry.update)
            a.scheduler()
            handle_result(success, updated_registries)
        end)
    else
        registry.update(_.scheduler_wrap(handle_result))
    end
end

vim.api.nvim_create_user_command("MasonUpdate", MasonUpdate, {
    desc = "Update Mason registries.",
})

local function MasonLog()
    local log = require "mason-core.log"
    vim.cmd(([[tabnew %s]]):format(log.outfile))
end

vim.api.nvim_create_user_command("MasonLog", MasonLog, {
    desc = "Opens the mason.nvim log.",
})

return {
    Mason = Mason,
    MasonInstall = MasonInstall,
    MasonUninstall = MasonUninstall,
    MasonUninstallAll = MasonUninstallAll,
    MasonUpdate = MasonUpdate,
    MasonLog = MasonLog,
}


================================================
FILE: lua/mason/health.lua
================================================
local health = vim.health or require "health"
local Result = require "mason-core.result"
local _ = require "mason-core.functional"
local a = require "mason-core.async"
local control = require "mason-core.async.control"
local platform = require "mason-core.platform"
local providers = require "mason-core.providers"
local registry = require "mason-registry"
local settings = require "mason.settings"
local spawn = require "mason-core.spawn"
local version = require "mason.version"

local Semaphore = control.Semaphore

local M = {}

local report_start = _.scheduler_wrap(health.start or health.report_start)
local report_ok = _.scheduler_wrap(health.ok or health.report_ok)
local report_warn = _.scheduler_wrap(health.warn or health.report_warn)
local report_error = _.scheduler_wrap(health.error or health.report_error)

local sem = Semaphore:new(5)

---@async
---@param opts {cmd:string, args:string[], name: string, use_stderr: boolean?, version_check: (fun(version: string): string?), relaxed: boolean?, advice: string[]}
local function check(opts)
    local get_first_non_empty_line = _.compose(_.head, _.filter(_.complement(_.matches "^%s*$")), _.split "\n")

    local permit = sem:acquire()

    Result.try(function(try)
        local result = try(spawn[opts.cmd] {
            opts.args,
            on_spawn = function(_, stdio)
                local stdin = stdio[1]
                -- some processes (`sh` for example) will endlessly read from stdin, so we close it immediately
                if not stdin:is_closing() then
                    stdin:close()
                end
            end,
        })

        ---@type string?
        local version = get_first_non_empty_line(opts.use_stderr and result.stderr or result.stdout)

        if opts.version_check then
            local ok, version_mismatch = pcall(opts.version_check, version)
            if ok and version_mismatch then
                local report = opts.relaxed and report_warn or report_error
                report(("%s: unsupported version `%s`"):format(opts.name, version), { version_mismatch })
                return
            elseif not ok then
                local report = opts.relaxed and report_warn or report_error
                report(("%s: failed to parse version"):format(opts.name), { ("Error: %s"):format(version_mismatch) })
                return
            end
        end

        report_ok(("%s: `%s`"):format(opts.name, version or "Ok"))
    end):on_failure(function(err)
        local report = opts.relaxed and report_warn or report_error
        report(("%s: not available"):format(opts.name), opts.advice or { tostring(err) })
    end)
    permit:forget()
end

local function check_registries()
    report_start "mason.nvim [Registries]"
    a.wait(registry.refresh)
    for source in registry.sources:iterate { include_uninstalled = true } do
        if source:is_installed() then
            report_ok(("Registry `%s` is installed."):format(source:get_display_name()))
        else
            report_error(
                ("Registry `%s` is not installed."):format(source:get_display_name()),
                { "Run :MasonUpdate to install." }
            )
        end
    end
end

local function check_neovim()
    if vim.fn.has "nvim-0.10.0" == 1 then
        report_ok "neovim version >= 0.10.0"
    else
        report_error("neovim version < 0.10.0", { "Upgrade Neovim." })
    end
end

---@async
local function check_core_utils()
    report_start "mason.nvim [Core utils]"

    check { name = "unzip", cmd = "unzip", args = { "-v" }, relaxed = true }

    -- wget is used interchangeably with curl, but with lower priority, so we mark wget as relaxed
    check { cmd = "wget", args = { "--help" }, name = "wget", relaxed = true }
    check { cmd = "curl", args = { "--version" }, name = "curl" }
    check {
        cmd = "gzip",
        args = { "--version" },
        name = "gzip",
        use_stderr = platform.is.mac, -- Apple gzip prints version string to stderr
        relaxed = platform.is.win,
    }

    a.scheduler()
    local tar = vim.fn.executable "gtar" == 1 and "gtar" or "tar"
    check { cmd = tar, args = { "--version" }, name = tar }

    if platform.is.unix then
        check { cmd = "bash", args = { "--version" }, name = "bash" }
    end

    if platform.is.win then
        check {
            cmd = "pwsh",
            args = {
                "-NoProfile",
                "-Command",
                [[$PSVersionTable.PSVersion, $PSVersionTable.OS, $PSVersionTable.Platform -join " "]],
            },
            name = "pwsh",
        }
        check { cmd = "7z", args = { "--help" }, name = "7z", relaxed = true }
    end
end

local function check_thunk(opts)
    return function()
        check(opts)
    end
end

---@async
local function check_languages()
    report_start "mason.nvim [Languages]"

    a.wait_all {
        check_thunk {
            cmd = "go",
            args = { "version" },
            name = "Go",
            relaxed = true,
            version_check = function(version)
                -- Parses output such as "go version go1.17.3 darwin/arm64" into major, minor, patch components
                local _, _, major, minor = version:find "go(%d+)%.(%d+)"
                -- Due to https://go.dev/doc/go-get-install-deprecation
                if not (tonumber(major) >= 1 and tonumber(minor) >= 17) then
                    return "Go version must be >= 1.17."
                end
            end,
        },
        check_thunk {
            cmd = "cargo",
            args = { "--version" },
            name = "cargo",
            relaxed = true,
            version_check = function(version)
                local _, _, major, minor = version:find "(%d+)%.(%d+)%.(%d+)"
                if (tonumber(major) <= 1) and (tonumber(minor) < 60) then
                    return "Some cargo installations require Rust >= 1.60.0."
                end
            end,
        },
        check_thunk {
            cmd = "luarocks",
            args = { "--version" },
            name = "luarocks",
            relaxed = true,
            version_check = function(version)
                local _, _, major = version:find "(%d+)%.(%d+)%.(%d+)"
                if not (tonumber(major) >= 3) then
                    -- Because of usage of "--dev" flag
                    return "Luarocks version must be >= 3.0.0."
                end
            end,
        },
        check_thunk { cmd = "ruby", args = { "--version" }, name = "Ruby", relaxed = true },
        check_thunk { cmd = "gem", args = { "--version" }, name = "RubyGem", relaxed = true },
        check_thunk { cmd = "composer", args = { "--version" }, name = "Composer", relaxed = true },
        check_thunk { cmd = "php", args = { "--version" }, name = "PHP", relaxed = true },
        check_thunk {
            cmd = "npm",
            args = { "--version" },
            name = "npm",
            relaxed = true,
            version_check = function(version)
                -- Parses output such as "8.1.2" into major, minor, patch components
                local _, _, major = version:find "(%d+)%.(%d+)%.(%d+)"
                -- Based off of general observations of feature parity.
                -- In npm v7, peerDependencies are now automatically installed.
                if tonumber(major) < 7 then
                    return "npm version must be >= 7"
                end
            end,
        },
        check_thunk {
            cmd = "node",
            args = { "--version" },
            name = "node",
            relaxed = true,
            version_check = function(version)
                -- Parses output such as "v16.3.1" into major, minor, patch
                local _, _, major = version:find "v(%d+)%.(%d+)%.(%d+)"
                if tonumber(major) < 14 then
                    return "Node version must be >= 14"
                end
            end,
        },
        check_thunk { cmd = "javac", args = { "-version" }, name = "javac", relaxed = true },
        check_thunk { cmd = "java", args = { "-version" }, name = "java", use_stderr = true, relaxed = true },
        check_thunk { cmd = "julia", args = { "--version" }, name = "julia", relaxed = true },
        function()
            local python = platform.is.win and "python" or "python3"
            check { cmd = python, args = { "--version" }, name = "python", relaxed = true }
            check { cmd = python, args = { "-m", "pip", "--version" }, name = "pip", relaxed = true }
            check {
                cmd = python,
                args = { "-c", "import venv" },
                name = "python venv",
                relaxed = true,
                advice = {
                    [[On Debian/Ubuntu systems, you need to install the python3-venv package using the following command:

    apt-get install python3-venv]],
                },
            }
        end,
        function()
            a.scheduler()
            if vim.env.JAVA_HOME then
                check {
                    cmd = ("%s/bin/java"):format(vim.env.JAVA_HOME),
                    args = { "-version" },
                    name = "JAVA_HOME",
                    use_stderr = true,
                    relaxed = true,
                }
            end
        end,
    }
end

---@async
local function check_mason()
    providers.github
        .get_latest_release("mason-org/mason.nvim")
        :on_success(
            ---@param latest_release GitHubRelease
            function(latest_release)
                a.scheduler()
                if latest_release.tag_name ~= version.VERSION then
                    report_warn(("mason.nvim version %s"):format(version.VERSION), {
                        ("The latest version of mason.nvim is: %s"):format(latest_release.tag_name),
                    })
                else
                    report_ok(("mason.nvim version %s"):format(version.VERSION))
                end
            end
        )
        :on_failure(function()
            a.scheduler()
            report_ok(("mason.nvim version %s"):format(version.VERSION))
        end)

    report_ok(("PATH: %s"):format(settings.current.PATH))
    report_ok(("Providers: \n  %s"):format(_.join("\n  ", settings.current.providers)))
end

function M.check()
    report_start "mason.nvim"

    a.run_blocking(function()
        check_mason()
        check_neovim()
        check_registries()
        check_core_utils()
        check_languages()
        a.wait(vim.schedule)
    end)
end

return M


================================================
FILE: lua/mason/init.lua
================================================
local InstallLocation = require "mason-core.installer.InstallLocation"
local Registry = require "mason-registry"
local settings = require "mason.settings"

local M = {}

local function setup_autocmds()
    vim.api.nvim_create_autocmd("VimLeavePre", {
        callback = function()
            require("mason-core.terminator").terminate(5000)
        end,
        once = true,
    })
end

M.has_setup = false

---@param config MasonSettings?
function M.setup(config)
    if config then
        settings.set(config)
    end

    local global_location = InstallLocation.global()
    global_location:set_env { PATH = settings.current.PATH }
    for _, registry in ipairs(settings.current.registries) do
        Registry.sources:append(registry)
    end

    require "mason.api.command"
    setup_autocmds()
    M.has_setup = true
end

return M


================================================
FILE: lua/mason/providers/client/gh.lua
================================================
local _ = require "mason-core.functional"
local fetch = require "mason-core.fetch"
local spawn = require "mason-core.spawn"

local stringify_params = _.compose(_.join "&", _.map(_.join "="), _.sort_by(_.head), _.to_pairs)

---@param path string
---@param opts { params: table<string, any>? }?
---@return Result # JSON decoded response.
local function gh_api_call(path, opts)
    if opts and opts.params then
        local params = stringify_params(opts.params)
        path = ("%s?%s"):format(path, params)
    end
    return spawn
        .gh({ "api", path, env = { CLICOLOR_FORCE = 0 } })
        :map(_.prop "stdout")
        :or_else(function()
            return fetch(("https://api.github.com/%s"):format(path), {
                headers = {
                    Accept = "application/vnd.github.v3+json; q=1.0, application/json; q=0.8",
                },
            })
        end)
        :map_catching(vim.json.decode)
end

---@type GitHubProvider
return {
    get_latest_release = function(repo)
        local path = ("repos/%s/releases/latest"):format(repo)
        return gh_api_call(path)
    end,
    get_all_release_versions = function(repo)
        local path = ("repos/%s/releases"):format(repo)
        return gh_api_call(path):map(_.map(_.prop "tag_name"))
    end,
    get_all_tags = function(repo)
        local path = ("repos/%s/git/matching-refs/tags"):format(repo)
        return gh_api_call(path):map(_.map(_.compose(_.gsub("^refs/tags/", ""), _.prop "ref")))
    end,
}


================================================
FILE: lua/mason/providers/client/golang.lua
================================================
local _ = require "mason-core.functional"
local spawn = require "mason-core.spawn"

---@type GolangProvider
return {
    get_all_versions = function(pkg)
        return spawn
            .go({
                "list",
                "-json",
                "-m",
                "-versions",
                pkg,
            })
            :map(_.prop "stdout")
            :map_catching(vim.json.decode)
            :map(_.prop "Versions")
            :map(_.reverse)
    end,
}


================================================
FILE: lua/mason/providers/client/init.lua
================================================
---@type Provider
return {
    github = require "mason.providers.client.gh",
    npm = require "mason.providers.client.npm",
    pypi = require "mason.providers.client.pypi",
    rubygems = require "mason.providers.client.rubygems",
    golang = require "mason.providers.client.golang",
    openvsx = require "mason.providers.client.openvsx",
}


================================================
FILE: lua/mason/providers/client/npm.lua
================================================
local _ = require "mason-core.functional"
local spawn = require "mason-core.spawn"

---@type NpmProvider
return {
    get_latest_version = function(pkg)
        return spawn
            .npm({ "view", "--json", pkg .. "@latest" })
            :map(_.prop "stdout")
            :map_catching(vim.json.decode)
            :map(_.pick { "name", "version" })
    end,
    get_all_versions = function(pkg)
        return spawn
            .npm({ "view", "--json", pkg, "versions" })
            :map(_.prop "stdout")
            :map_catching(vim.json.decode)
            :map(_.reverse)
    end,
}


================================================
FILE: lua/mason/providers/client/openvsx.lua
================================================
local _ = require "mason-core.functional"
local fetch = require "mason-core.fetch"
local semver = require "mason-core.semver"

---@param path string
local function api_url(path)
    return ("https://open-vsx.org/api/%s"):format(path)
end

---@param version string
local function maybe_semver_sort(version)
    return semver.parse(version):get_or_else(version)
end

---@type OpenVSXProvider
return {
    get_latest_version = function(namespace, extension)
        return fetch(api_url("%s/%s"):format(namespace, extension)):map_catching(vim.json.decode):map(_.prop "version")
    end,
    get_all_versions = function(namespace, extension)
        return fetch(api_url("%s/%s/versions"):format(namespace, extension))
            :map_catching(vim.json.decode)
            :map(_.compose(_.keys, _.prop "versions"))
            :map(_.compose(_.reverse, _.sort_by(maybe_semver_sort)))
    end,
}


================================================
FILE: lua/mason/providers/client/pypi.lua
================================================
local Optional = require "mason-core.optional"
local Result = require "mason-core.result"
local _ = require "mason-core.functional"
local a = require "mason-core.async"
local fetch = require "mason-core.fetch"
local fs = require "mason-core.fs"
local platform = require "mason-core.platform"
local spawn = require "mason-core.spawn"

---@param args SpawnArgs
local function python(args)
    a.scheduler()
    local py_exec = platform.is.win and "python" or "python3"
    -- run in tmpdir in case pip inadvertently produces some output
    args.cwd = vim.fn.tempname()
    fs.async.mkdir(args.cwd)
    return spawn[py_exec](args)
end

---@async
---@param pkg string
local function get_all_versions(pkg)
    -- https://stackoverflow.com/a/26664162
    return python({
            "-m",
            "pip",
            "install",
            "--disable-pip-version-check",
            "--use-deprecated=legacy-resolver", -- for pip >= 20.3
            ("%s=="):format(pkg), -- invalid version specifier to trigger the wanted error message
        })
        :recover(_.prop "stderr")
        :map(_.compose(_.split ", ", _.head, _.match "%(from versions: (.+)%)"))
        :map(_.reverse)
end

---@param pkg string
local function synthesize_pkg(pkg)
    ---@param version Optional
    return function(version)
        return version
            :map(function(v)
                return { name = pkg, version = v }
            end)
            :ok_or "Unable to find latest version."
    end
end

---@type PyPiProvider
return {
    get_latest_version = function(pkg)
        return get_all_versions(pkg):map(_.compose(Optional.of_nilable, _.last)):and_then(synthesize_pkg(pkg))
    end,
    get_all_versions = get_all_versions,
    get_supported_python_versions = function(pkg, version)
        return fetch(("https://pypi.org/pypi/%s/%s/json"):format(pkg, version))
            :map_catching(vim.json.decode)
            :map(_.path { "info", "requires_python" })
            :and_then(function(requires_python)
                if type(requires_python) ~= "string" or requires_python == "" then
                    return Result.failure "Package does not specify supported Python versions."
                else
                    return Result.success(requires_python)
                end
            end)
    end,
}


================================================
FILE: lua/mason/providers/client/rubygems.lua
================================================
local Optional = require "mason-core.optional"
local _ = require "mason-core.functional"
local spawn = require "mason-core.spawn"

---@param gem string
---@param output string "$ gem list" output
local parse_gem_versions = _.curryN(function(gem, output)
    local lines = _.split("\n", output)
    return Optional.of_nilable(_.find_first(_.starts_with(gem), lines))
        :map(_.compose(_.head, _.match "%((.+)%)$"))
        :map(_.split ", ")
        :ok_or "Failed to parse gem list output."
end, 2)

---@async
---@param gem string
local function get_all_versions(gem)
    return spawn.gem({ "list", gem, "--remote", "--all" }):map(_.prop "stdout"):and_then(parse_gem_versions(gem))
end

---@type RubyGemsProvider
return {
    get_latest_version = function(gem)
        return get_all_versions(gem):map(_.head)
    end,
    get_all_versions = function(gem)
        return get_all_versions(gem)
    end,
}


================================================
FILE: lua/mason/providers/registry-api/init.lua
================================================
local Result = require "mason-core.result"
local _ = require "mason-core.functional"
local api = require "mason-registry.api"

---@type Provider
return {
    github = {
        get_latest_release = function(repo)
            return api.github.releases.latest { repo = repo }
        end,
        get_all_release_versions = function(repo)
            return api.github.releases.all { repo = repo }
        end,
        get_latest_tag = function(repo)
            return api.github.tags.latest { repo = repo }
        end,
        get_all_tags = function(repo)
            return api.github.tags.all { repo = repo }
        end,
    },
    npm = {
        get_latest_version = function(pkg)
            return api.npm.versions.latest { package = pkg }
        end,
        get_all_versions = function(pkg)
            return api.npm.versions.all { package = pkg }
        end,
    },
    pypi = {
        get_latest_version = function(pkg)
            return api.pypi.versions.latest { package = pkg }
        end,
        get_all_versions = function(pkg)
            return api.pypi.versions.all { package = pkg }
        end,
        get_supported_python_versions = function(pkg, version)
            return api.pypi.versions
                .get({ package = pkg, version = version })
                :map(_.prop "requires_python")
                :and_then(function(requires_python)
                    if type(requires_python) ~= "string" or requires_python == "" then
                        return Result.failure "Package does not specify supported Python versions."
                    else
                        return Result.success(requires_python)
                    end
                end)
        end,
    },
    rubygems = {
        get_latest_version = function(gem)
            return api.rubygems.versions.latest { gem = gem }
        end,
        get_all_versions = function(gem)
            return api.rubygems.versions.all { gem = gem }
        end,
    },
    packagist = {
        get_latest_version = function(pkg)
            return api.packagist.versions.latest { pkg = pkg }
        end,
        get_all_versions = function(pkg)
            return api.packagist.versions.all { pkg = pkg }
        end,
    },
    crates = {
        get_latest_version = function(crate)
            return api.crate.versions.latest { crate = crate }
        end,
        get_all_versions = function(crate)
            return api.crate.versions.all { crate = crate }
        end,
    },
    golang = {
        get_all_versions = function(pkg)
            return api.golang.versions.all { pkg = api.encode_uri_component(pkg) }
        end,
    },
    openvsx = {
        get_latest_version = function(namespace, extension)
            return api.openvsx.versions.latest { namespace = namespace, extension = extension }
        end,
        get_all_versions = function(namespace, extension)
            return api.openvsx.versions.all { namespace = namespace, extension = extension }
        end,
    },
}


================================================
FILE: lua/mason/settings.lua
================================================
local path = require "mason-core.path"

local M = {}

---@class MasonSettings
local DEFAULT_SETTINGS = {
    ---@since 1.0.0
    -- The directory in which to install packages.
    install_root_dir = path.concat { vim.fn.stdpath "data", "mason" },

    ---@since 1.0.0
    -- Where Mason should put its bin location in your PATH. Can be one of:
    -- - "prepend" (default, Mason's bin location is put first in PATH)
    -- - "append" (Mason's bin location is put at the end of PATH)
    -- - "skip" (doesn't modify PATH)
    ---@type '"prepend"' | '"append"' | '"skip"'
    PATH = "prepend",

    ---@since 1.0.0
    -- Controls to which degree logs are written to the log file. It's useful to set this to vim.log.levels.DEBUG when
    -- debugging issues with package installations.
    log_level = vim.log.levels.INFO,

    ---@since 1.0.0
    -- Limit for the maximum amount of packages to be installed at the same time. Once this limit is reached, any further
    -- packages that are requested to be installed will be put in a queue.
    max_concurrent_installers = 4,

    ---@since 1.0.0
    -- [Advanced setting]
    -- The registries to source packages from. Accepts multiple entries. Should a package with the same name exist in
    -- multiple registries, the registry listed first will be used.
    registries = {
        "github:mason-org/mason-registry",
    },

    ---@since 1.0.0
    -- The provider implementations to use for resolving supplementary package metadata (e.g., all available versions).
    -- Accepts multiple entries, where later entries will be used as fallback should prior providers fail.
    -- Builtin providers are:
    --   - mason.providers.registry-api  - uses the https://api.mason-registry.dev API
    --   - mason.providers.client        - uses only client-side tooling to resolve metadata
    providers = {
        "mason.providers.registry-api",
        "mason.providers.client",
    },

    github = {
        ---@since 1.0.0
        -- The template URL to use when downloading assets from GitHub.
        -- The placeholders are the following (in order):
        -- 1. The repository (e.g. "rust-lang/rust-analyzer")
        -- 2. The release version (e.g. "v0.3.0")
        -- 3. The asset name (e.g. "rust-analyzer-v0.3.0-x86_64-unknown-linux-gnu.tar.gz")
        download_url_template = "https://github.com/%s/releases/download/%s/%s",
    },

    pip = {
        ---@since 1.0.0
        -- Whether to upgrade pip to the latest version in the virtual environment before installing packages.
        upgrade_pip = false,

        ---@since 1.0.0
        -- These args will be added to `pip install` calls. Note that setting extra args might impact intended behavior
        -- and is not recommended.
        --
        -- Example: { "--proxy", "https://proxyserver" }
        install_args = {},
    },

    ui = {
        ---@since 1.0.0
        -- Whether to automatically check for new versions when opening the :Mason window.
        check_outdated_packages_on_open = true,

        ---@since 1.0.0
        -- The border to use for the UI window. Accepts same border values as |nvim_open_win()|.
        -- Defaults to `:h 'winborder'` if nil.
        border = nil,

        ---@since 1.11.0
        -- The backdrop opacity. 0 is fully opaque, 100 is fully transparent.
        backdrop = 60,

        ---@since 1.0.0
        -- Width of the window. Accepts:
        -- - Integer greater than 1 for fixed width.
        -- - Float in the range of 0-1 for a percentage of screen width.
        width = 0.8,

        ---@since 1.0.0
        -- Height of the window. Accepts:
        -- - Integer greater than 1 for fixed height.
        -- - Float in the range of 0-1 for a percentage of screen height.
        height = 0.9,

        icons = {
            ---@since 1.0.0
            -- The list icon to use for installed packages.
            package_installed = "◍",
            ---@since 1.0.0
            -- The list icon to use for packages that are installing, or queued for installation.
            package_pending = "◍",
            ---@since 1.0.0
            -- The list icon to use for packages that are not installed.
            package_uninstalled = "◍",
        },

        keymaps = {
            ---@since 1.0.0
            -- Keymap to expand a package
            toggle_package_expand = "<CR>",
            ---@since 1.0.0
            -- Keymap to install the package under the current cursor position
            install_package = "i",
            ---@since 1.0.0
            -- Keymap to reinstall/update the package under the current cursor position
            update_package = "u",
            ---@since 1.0.0
            -- Keymap to check for new version for the package under the current cursor position
            check_package_version = "c",
            ---@since 1.0.0
            -- Keymap to update all installed packages
            update_all_packages = "U",
            ---@since 1.0.0
            -- Keymap to check which installed packages are outdated
            check_outdated_packages = "C",
            ---@since 1.0.0
            -- Keymap to uninstall a package
            uninstall_package = "X",
            ---@since 1.0.0
            -- Keymap to cancel a package installation
            cancel_installation = "<C-c>",
            ---@since 1.0.0
            -- Keymap to apply language filter
            apply_language_filter = "<C-f>",
            ---@since 1.1.0
            -- Keymap to toggle viewing package installation log
            toggle_package_install_log = "<CR>",
            ---@since 1.8.0
            -- Keymap to toggle the help view
            toggle_help = "g?",
        },
    },
}

M._DEFAULT_SETTINGS = DEFAULT_SETTINGS
M.current = M._DEFAULT_SETTINGS

---@param opts MasonSettings
function M.set(opts)
    M.current = vim.tbl_deep_extend("force", vim.deepcopy(M.current), opts)
end

return M


================================================
FILE: lua/mason/ui/colors.lua
================================================
local hl_groups = {
    MasonBackdrop = { bg = "#000000", default = true },
    MasonNormal = { link = "NormalFloat", default = true },
    MasonHeader = { bold = true, fg = "#222222", bg = "#DCA561", default = true },
    MasonHeaderSecondary = { bold = true, fg = "#222222", bg = "#56B6C2", default = true },

    MasonHighlight = { fg = "#56B6C2", default = true },
    MasonHighlightBlock = { bg = "#56B6C2", fg = "#222222", default = true },
    MasonHighlightBlockBold = { bg = "#56B6C2", fg = "#222222", bold = true, default = true },

    MasonHighlightSecondary = { fg = "#DCA561", default = true },
    MasonHighlightBlockSecondary = { bg = "#DCA561", fg = "#222222", default = true },
    MasonHighlightBlockBoldSecondary = { bg = "#DCA561", fg = "#222222", bold = true, default = true },

    MasonLink = { link = "MasonHighlight", default = true },

    MasonMuted = { fg = "#888888", default = true },
    MasonMutedBlock = { bg = "#888888", fg = "#222222", default = true },
    MasonMutedBlockBold = { bg = "#888888", fg = "#222222", bold = true, default = true },

    MasonError = { link = "ErrorMsg", default = true },
    MasonWarning = { link = "WarningMsg", default = true },

    MasonHeading = { bold = true, default = true },
}

for name, hl in pairs(hl_groups) do
    vim.api.nvim_set_hl(0, name, hl)
end


================================================
FILE: lua/mason/ui/components/header.lua
================================================
local Ui = require "mason-core.ui"
local _ = require "mason-core.functional"
local p = require "mason.ui.palette"
local settings = require "mason.settings"
local version = require "mason.version"

---@param state InstallerUiState
return function(state)
    local uninstalled_registries = _.filter(_.prop_eq("is_installed", false), state.info.registries)

    return Ui.Node {
        Ui.CascadingStyleNode({ "CENTERED" }, {
            Ui.HlTextNode {
                Ui.When(state.view.is_showing_help, {
                    p.header_secondary(" " .. state.header.title_prefix .. " mason.nvim "),
                    p.header_secondary(version.VERSION .. " "),
                    p.none((" "):rep(#state.header.title_prefix + 1)),
                }, {
                    p.header " mason.nvim ",
                    p.header(version.VERSION .. " "),
                    state.view.is_searching and p.Comment " (search mode, press <Esc> to clear)" or p.none "",
                }),
                Ui.When(state.view.is_showing_help, {
                    p.none "        press ",
                    p.highlight_secondary(settings.current.ui.keymaps.toggle_help),
                    p.none " for package list",
                }, {
                    p.none "press ",
                    p.highlight(settings.current.ui.keymaps.toggle_help),
                    p.none " for help",
                }),
                { p.Comment "https://github.com/mason-org/mason.nvim" },
            },
        }),
        Ui.When(not state.info.registry_update.in_progress and #uninstalled_registries > 0, function()
            return Ui.CascadingStyleNode({ "INDENT" }, {
                Ui.EmptyLine(),
                Ui.HlTextNode {
                    {
                        p.warning "Uninstalled registries",
                    },
                    {
                        p.Comment "Packages from the following registries are unavailable. Press ",
                        p.highlight(settings.current.ui.keymaps.check_outdated_packages),
                        p.Comment " to install.",
                    },
                    unpack(_.map(function(registry)
                        return { p.none(" - " .. registry.name) }
                    end, uninstalled_registries)),
                },
                Ui.EmptyLine(),
            })
        end),
        Ui.When(
            not state.info.registry_update.in_progress and state.info.registry_update.error,
            Ui.CascadingStyleNode({ "INDENT" }, {
                Ui.HlTextNode {
                    {
                        p.error "Registry installation failed with the following error:",
                    },
                    {
                        p.none "  ",
                        p.Comment(state.info.registry_update.error),
                    },
                },
                Ui.EmptyLine(),
            })
        ),
    }
end


================================================
FILE: lua/mason/ui/components/help/dap.lua
================================================
local Ui = require "mason-core.ui"
local p = require "mason.ui.palette"

---@param state InstallerUiState
return function(state)
    return Ui.HlTextNode {
        {
            p.Bold "What is DAP?",
        },
        {
            p.none "The ",
            p.highlight_secondary "D",
            p.none "ebugger ",
            p.highlight_secondary "A",
            p.none "dapter ",
            p.highlight_secondary "P",
            p.none "rotocol defines the abstract protocol used",
        },
        {
            p.none "between a development tool (e.g. IDE or editor) and a debugger.",
        },
        {
            p.none "This provides editors with a standardized interface for enabling debugging",
        },
        {
            p.none "capabilities - such as pausing execution, stepping through statements,",
        },
        { p.none "and inspecting variables." },
        {},
        { p.none "For more information, see:" },
        { p.none " - https://microsoft.github.io/debug-adapter-protocol/" },
    }
end


================================================
FILE: lua/mason/ui/components/help/formatter.lua
================================================
local Ui = require "mason-core.ui"
local p = require "mason.ui.palette"

---@param state InstallerUiState
return function(state)
    return Ui.HlTextNode {
        {
            p.Bold "What is a formatter?",
        },
        { p.none "A code formatter is a tool that reformats code to fit a certain" },
        { p.none "formatting convention. This usually entails things like adjusting" },
        { p.none "indentation, breaking long lines into smaller lines, adding or" },
        { p.none "removing whitespaces. Formatting rules are often included as a" },
        { p.none "separate configuration file within the project." },
    }
end


================================================
FILE: lua/mason/ui/components/help/init.lua
================================================
local Ui = require "mason-core.ui"
local _ = require "mason-core.functional"
local log = require "mason-core.log"
local p = require "mason.ui.palette"
local settings = require "mason.settings"

local DAPHelp = require "mason.ui.components.help.dap"
local FormatterHelp = require "mason.ui.components.help.formatter"
local LSPHelp = require "mason.ui.components.help.lsp"
local LinterHelp = require "mason.ui.components.help.linter"

---@param state InstallerUiState
local function Ship(state)
    local ship_indent = { (" "):rep(state.view.ship_indentation), "" }
    -- stylua: ignore start
    local ship = {
        { ship_indent,             p.muted "/^v^\\", p.none "         |    |    |" },
        { ship_indent,                          p.none "             )_)  )_)  )_)     ", p.muted "/^v^\\" },
        { ship_indent, p.muted "   ", p.muted "/^v^\\", p.none "    )___))___))___)\\     ", p.highlight_secondary(state.view.ship_exclamation) },
        { ship_indent,                          p.none "           )____)____)_____)\\\\" },
        { ship_indent,                          p.none "         _____|____|____|____\\\\\\__" },
        { ship_indent,  p.muted "         ",            p.none "\\                   /" },
    }
    -- stylua: ignore end
    local water = {
        { p.highlight "  ^^^^^ ^^^^^^^^  ^^^^^ ^^^^^  ^^^^^ ^^^^ <><  " },
        { p.highlight "    ^^^^  ^^  ^^^    ^ ^^^    ^^^ <>< ^^^^     " },
        { p.highlight "     ><> ^^^     ^^    ><> ^^     ^^    ^      " },
    }
    if state.view.ship_indentation < 0 then
        for _, shipline in ipairs(ship) do
            local removed_chars = 0
            for _, span in ipairs(shipline) do
                local span_length = #span[1]
                local chars_to_remove = (math.abs(state.view.ship_indentation) - removed_chars)
                span[1] = string.sub(span[1], chars_to_remove + 1)
                removed_chars = removed_chars + (span_length - #span[1])
            end
        end
    end
    return Ui.Node {
        Ui.HlTextNode(ship),
        Ui.HlTextNode(water),
    }
end

---@param state InstallerUiState
local function GenericHelp(state)
    local keymap_tuples = {
        { "Toggle help", settings.current.ui.keymaps.toggle_help },
        { "Toggle package info", settings.current.ui.keymaps.toggle_package_expand },
        { "Toggle package installation log", settings.current.ui.keymaps.toggle_package_install_log },
        { "Apply language filter", settings.current.ui.keymaps.apply_language_filter },
        { "Install package", settings.current.ui.keymaps.install_package },
        { "Uninstall package", settings.current.ui.keymaps.uninstall_package },
        { "Update package", settings.current.ui.keymaps.update_package },
        { "Update all outdated packages", settings.current.ui.keymaps.update_all_packages },
        { "Check for new package version", settings.current.ui.keymaps.check_package_version },
        { "Check for new versions (all packages)", settings.current.ui.keymaps.check_outdated_packages },
        { "Cancel installation of package", settings.current.ui.keymaps.cancel_installation },
        { "Close window", "q" },
        { "Close window", "<Esc>" },
    }

    local is_current_settings_expanded = state.view.is_current_settings_expanded

    return Ui.Node {
        Ui.HlTextNode {
            { p.muted "Mason log: ", p.none(log.outfile) },
        },
        Ui.EmptyLine(),
        Ui.HlTextNode {
            {
                p.Bold "Registries",
            },
            {
                p.muted "Packages are sourced from the following registries:",
            },
            unpack(_.map(function(registry)
                return { p.none(" - " .. registry.name) }
            end, state.info.registries)),
        },
        Ui.EmptyLine(),
        Ui.Table {
            {
                p.Bold "Keyboard shortcuts",
            },
            unpack(_.map(function(keymap_tuple)
                return { p.muted(keymap_tuple[1]), p.highlight(keymap_tuple[2]) }
            end, keymap_tuples)),
        },
        Ui.EmptyLine(),
        Ui.HlTextNode {
            { p.Bold "Problems installing packages" },
            {
                p.muted "Make sure you meet the minimum requirements to install packages. For debugging, refer to:",
            },
        },
        Ui.CascadingStyleNode({ "INDENT" }, {
            Ui.HlTextNode {
                {
                    p.highlight ":help mason-debugging",
                },
                {
                    p.highlight ":checkhealth mason",
                },
            },
        }),
        Ui.EmptyLine(),
        Ui.HlTextNode {
            { p.Bold "Problems with package functionality" },
            { p.muted "Please refer to each package's own homepage for further assistance." },
        },
        Ui.EmptyLine(),
        Ui.HlTextNode {
            { p.Bold "How do I use installed packages?" },
            { p.muted "Mason only makes packages available for use. It does not automatically integrate" },
            { p.muted "these into Neovim. You have multiple different options for using any given" },
            { p.muted "package, and you are free to pick and choose as you see fit." },
            {
                p.muted "See ",
                p.highlight ":help mason-how-to-use-packages",
                p.muted " for a recommendation.",
            },
        },
        Ui.EmptyLine(),
        Ui.HlTextNode {
            { p.Bold "Missing a package?" },
            { p.muted "Please consider contributing to mason.nvim:" },
        },
        Ui.CascadingStyleNode({ "INDENT" }, {
            Ui.HlTextNode {
                {
                    p.none "- ",
                    p.highlight "https://github.com/mason-org/mason.nvim/blob/main/CONTRIBUTING.md",
                },
                {
                    p.none "- ",
                    p.highlight "https://github.com/mason-org/mason.nvim/blob/main/doc/reference.md",
                },
            },
        }),
        Ui.EmptyLine(),
        Ui.HlTextNode {
            {
                p.Bold(("%s Current settings"):format(is_current_settings_expanded and "↓" or "→")),
                p.highlight " :help mason-settings",
            },
        },
        Ui.Keybind(settings.current.ui.keymaps.toggle_package_expand, "TOGGLE_EXPAND_CURRENT_SETTINGS", nil),
        Ui.When(is_current_settings_expanded, function()
            local settings_split_by_newline = vim.split(vim.inspect(settings.current), "\n")
            local current_settings = _.map(function(line)
                return { p.muted(line) }
            end, settings_split_by_newline)
            return Ui.HlTextNode(current_settings)
        end),
    }
end

---@param state InstallerUiState
return function(state)
    ---@type INode
    local heading = Ui.Node {}
    if state.view.current == "LSP" then
        heading = Ui.Node {
            LSPHelp(state),
            Ui.EmptyLine(),
        }
    elseif state.view.current == "DAP" then
        heading = Ui.Node {
            DAPHelp(state),
            Ui.EmptyLine(),
        }
    elseif state.view.current == "Linter" then
        heading = Ui.Node {
            LinterHelp(state),
            Ui.EmptyLine(),
        }
    elseif state.view.current == "Formatter" then
        heading = Ui.Node {
            FormatterHelp(state),
            Ui.EmptyLine(),
        }
    end

    return Ui.CascadingStyleNode({ "INDENT" }, {
        Ui.HlTextNode(state.view.has_changed and p.none "" or p.Comment "(change view by pressing its number)"),
        heading,
        GenericHelp(state),
        Ui.EmptyLine(),
        Ship(state),
        Ui.EmptyLine(),
    })
end


================================================
FILE: lua/mason/ui/components/help/linter.lua
================================================
local Ui = require "mason-core.ui"
local p = require "mason.ui.palette"

---@param state InstallerUiState
return function(state)
    return Ui.HlTextNode {
        {
            p.Bold "What is a linter?",
        },
        { p.none "A linter is a static code analysis tool used to provide diagnostics around" },
        { p.none "programming errors, bugs, stylistic errors and suspicious constructs." },
        { p.none "Linters can be executed as a standalone program in a terminal, where it" },
        { p.none "usually expects one or more input files to lint. There are also Neovim plugins" },
        { p.none "that integrate these diagnostics inside the editor." },
    }
end


================================================
FILE: lua/mason/ui/components/help/lsp.lua
================================================
local Ui = require "mason-core.ui"
local p = require "mason.ui.palette"

---@param state InstallerUiState
return function(state)
    return Ui.HlTextNode {
        {
            p.Bold "What is LSP?",
        },
        {
            p.none "The ",
            p.highlight_secondary "L",
            p.none "anguage ",
            p.highlight_secondary "S",
            p.none "erver ",
            p.highlight_secondary "P",
            p.none "rotocol defines the protocol used between an",
        },
        {
            p.none "editor or IDE and a language server that provides language features",
        },
        {
            p.none "like auto complete, go to definition, find all references etc.",
        },
        {},
        {
            p.none "The term ",
            p.highlight_secondary "LSP",
            p.none " is often used to reference a server implementation of",
        },
        { p.none "the LSP protocol." },
        {},
        { p.none "For more information, see:" },
        { p.none " - https://microsoft.github.io/language-server-protocol/" },
        { p.none " - ", p.highlight ":help lsp" },
    }
end


================================================
FILE: lua/mason/ui/components/json-schema.lua
================================================
-- Here be dragons
local Ui = require "mason-core.ui"
local _ = require "mason-core.functional"
local settings = require "mason.settings"

local property_type_highlights = {
    ["string"] = "String",
    ["string[]"] = "String",
    ["boolean"] = "Boolean",
    ["number"] = "Number",
    ["number[]"] = "Number",
    ["integer"] = "Number",
    ["integer[]"] = "Number",
}

local function resolve_type(property_schema)
    if _.is_list(property_schema.type) then
        return table.concat(property_schema.type, " | ")
    elseif property_schema.type == "array" then
        if property_schema.items then
            return ("%s[]"):format(property_schema.items.type)
        else
            return property_schema.type
        end
    end

    return property_schema.type or "N/A"
end

local function Indent(indentation, children)
    -- create a list table with as many "INDENT" entries as the numeric indentation variable
    local indent = {}
    for _ = 1, indentation do
        table.insert(indent, "INDENT")
    end
    return Ui.CascadingStyleNode(indent, children)
end

---@param pkg Package
---@param schema_id string
---@param state UiPackageState
---@param schema table
---@param key string?
---@param level number?
---@param key_width number? The width the key should occupate in the UI to produce an even column.
---@param compound_key string?
local function JsonSchema(pkg, schema_id, state, schema, key, level, key_width, compound_key)
    level = level or 0
    compound_key = ("%s%s"):format(compound_key or "", key or "")
    local toggle_expand_keybind = Ui.Keybind(
        settings.current.ui.keymaps.toggle_package_expand,
        "TOGGLE_JSON_SCHEMA_KEY",
        { package = pkg, schema_id = schema_id, key = compound_key }
    )
    local node_is_expanded = state.expanded_json_schema_keys[schema_id][compound_key]
    local key_prefix = node_is_expanded and "↓ " or "→ "

    if (schema.type == "object" or schema.type == nil) and schema.properties then
        local nodes = {}
        if key then
            -- This node belongs to some parent object - render a heading for it.
            -- It'll act as the anchor for its children.
            local heading = Ui.HlTextNode {
                key_prefix .. key,
                node_is_expanded and "Bold" or "",
            }
            nodes[#nodes + 1] = heading
            nodes[#nodes + 1] = toggle_expand_keybind
        end

        -- All level 0 nodes are expanded by default - otherwise we'd not render anything at all
        if level == 0 or node_is_expanded then
            local max_property_length = 0
            local sorted_properties = {}
            for property in pairs(schema.properties) do
                max_property_length = math.max(max_property_length, vim.api.nvim_strwidth(property))
                sorted_properties[#sorted_properties + 1] = property
            end
            table.sort(sorted_properties)
            for _, property in ipairs(sorted_properties) do
                nodes[#nodes + 1] = Indent(level, {
                    JsonSchema(
                        pkg,
                        schema_id,
                        state,
                        schema.properties[property],
                        property,
                        level + 1,
                        max_property_length,
                        compound_key
                    ),
                })
            end
        end
        return Ui.Node(nodes)
    elseif schema.oneOf then
        local nodes = {}
        for i, alternative_schema in ipairs(schema.oneOf) do
            nodes[#nodes + 1] = JsonSchema(
                pkg,
                schema_id,
                state,
                alternative_schema,
                ("%s (alt. %d)"):format(key, i),
                level,
                key_width,
                compound_key
            )
        end
        return Ui.Node(nodes)
    elseif _.is_list(schema) then
        return Ui.Node(_.map(function(sub_schema)
            return JsonSchema(pkg, schema_id, state, sub_schema)
        end, schema))
    elseif level > 0 then -- Leaf nodes cannot occupy the root level.
        -- Leaf node (aka any type that isn't an object).
        local type = resolve_type(schema)
        local heading
        local label = (key_prefix .. key .. (" "):rep(key_width or 0)):sub(1, key_width + 5) -- + 5 to account for key_prefix plus some extra whitespace
        if schema.default ~= nil then
            heading = Ui.HlTextNode {
                {
                    {
                        label,
                        node_is_expanded and "Bold" or "",
                    },
                    {
                        " default: ",
                        "Comment",
                    },
                    {
                        vim.json.encode(schema.default),
                        property_type_highlights[type] or "MasonMuted",
                    },
                },
            }
        else
            heading = Ui.HlTextNode {
                label,
                node_is_expanded and "Bold" or "",
            }
        end

        return Ui.Node {
            heading,
            toggle_expand_keybind,
            Ui.When(node_is_expanded, function()
                local description = _.map(function(line)
                    return { { line, "Comment" } }
                end, vim.split(schema.description or "No description available.", "\n"))

                local type_highlight = property_type_highlights[type] or "MasonMuted"

                local table_rows = {
                    { { "type", "MasonMuted" }, { type, type_highlight } },
                }

                if _.is_list(schema.enum) then
                    for idx, enum in ipairs(schema.enum) do
                        local enum_description = ""
                        if schema.enumDescriptions and schema.enumDescriptions[idx] then
                            enum_description = "- " .. schema.enumDescriptions[idx]
                        end
                        table_rows[#table_rows + 1] = {
                            { idx == 1 and "possible values" or "", "MasonMuted" },
                            { vim.json.encode(enum), type_highlight },
                            { enum_description, "Comment" },
                        }
                    end
                end

                return Indent(level, {
                    Ui.HlTextNode(description),
                    Ui.Table(table_rows),
                })
            end),
        }
    else
        return Ui.Node {}
    end
end

return JsonSchema


================================================
FILE: lua/mason/ui/components/language-filter.lua
================================================
local Ui = require "mason-core.ui"
local p = require "mason.ui.palette"
local settings = require "mason.settings"

---@param state InstallerUiState
return function(state)
    return Ui.CascadingStyleNode({ "INDENT" }, {
        Ui.When(state.view.language_filter, function()
            return Ui.Node {
                Ui.EmptyLine(),
                Ui.HlTextNode {
                    {
                        p.Bold "Language Filter: ",
                        p.highlight(state.view.language_filter),
                        p.Comment " press <Esc> to clear",
                    },
                },
            }
        end),
        Ui.When(not state.view.language_filter, function()
            return Ui.Node {
                Ui.EmptyLine(),
                Ui.HlTextNode {
                    {
                        p.Bold "Language Filter:",
                        p.Comment(
                            (" press %s to apply filter"):format(settings.current.ui.keymaps.apply_language_filter)
                        ),
                    },
                },
            }
        end),
    })
end


================================================
FILE: lua/mason/ui/components/main/init.lua
================================================
local Ui = require "mason-core.ui"

local PackageList = require "mason.ui.components.main.package_list"

---@param state InstallerUiState
return function(state)
    return Ui.Node {
        Ui.EmptyLine(),
        PackageList(state),
    }
end


================================================
FILE: lua/mason/ui/components/main/package_list.lua
================================================
local Ui = require "mason-core.ui"
local _ = require "mason-core.functional"
local p = require "mason.ui.palette"
local settings = require "mason.settings"

local JsonSchema = require "mason.ui.components.json-schema"

---@param props { state: InstallerUiState, heading: INode, packages: Package[], list_item_renderer: (fun(package: Package, state: InstallerUiState): INode), hide_when_empty: boolean }
local function PackageListContainer(props)
    local items = {}
    for i = 1, #props.packages do
        local pkg = props.packages[i]
        if props.state.packages.visible[pkg.name] then
            items[#items + 1] = props.list_item_renderer(pkg, props.state)
        end
    end

    if props.hide_when_empty and #items == 0 then
        return Ui.Node {}
    end

    return Ui.Node {
        props.heading,
        Ui.VirtualTextNode { p.Comment(("(%d)"):format(#items)) },
        Ui.CascadingStyleNode({ "INDENT" }, items),
        Ui.When(
            #items == 0,
            Ui.CascadingStyleNode({ "CENTERED" }, {
                Ui.HlTextNode(p.Comment "No packages."),
            })
        ),
        Ui.EmptyLine(),
    }
end

---@param executables table<string, string>?
local function ExecutablesTable(executables)
    if not executables or _.size(executables) == 0 then
        return Ui.Node {}
    end
    local rows = {}
    for executable in pairs(executables) do
        table.insert(rows, { p.none "", p.Bold(executable) })
    end
    rows[1][1] = p.muted "executables"
    return rows
end

---@param state InstallerUiState
---@param pkg Package
---@param is_installed boolean
local function ExpandedPackageInfo(state, pkg, is_installed)
    local pkg_state = state.packages.states[pkg.name]
    return Ui.CascadingStyleNode({ "INDENT" }, {
        Ui.When(not is_installed and pkg.spec.deprecation, function()
            return Ui.HlTextNode(p.warning(("Deprecation message: %s"):format(pkg.spec.deprecation.message)))
        end),
        Ui.HlTextNode(_.map(function(line)
            return { p.Comment(line) }
        end, _.split("\n", pkg.spec.description))),
        Ui.EmptyLine(),
        Ui.Table(_.concat(
            _.filter(_.identity, {
                is_installed and {
                    p.muted "installed version",
                    pkg_state.version and p.Bold(pkg_state.version) or p.muted "-",
                } or {
                    p.muted "version",
                    p.Bold(pkg:get_latest_version()),
                },
                pkg_state.new_version and {
                    p.muted "latest version",
                    p.muted(pkg_state.new_version),
                },
                pkg_state.installed_purl and {
                    p.muted "installed purl",
                    p.highlight(pkg_state.installed_purl),
                } or {
                    p.muted "purl",
                    p.highlight(pkg.spec.source.id),
                },
                {
                    p.muted "homepage",
                    pkg.spec.homepage and p.highlight(pkg.spec.homepage) or p.muted "-",
                },
                {
                    p.muted "languages",
                    #pkg.spec.languages > 0 and p.Bold(table.concat(pkg.spec.languages, ", ")) or p.muted "-",
                },
                {
                    p.muted "categories",
                    #pkg.spec.categories > 0 and p.Bold(table.concat(pkg.spec.categories, ", ")) or p.muted "-",
                },
            }),
            Ui.When(is_installed, function()
                return ExecutablesTable(pkg_state.linked_executables)
            end)
        )),
        Ui.When(pkg_state.lsp_settings_schema ~= nil, function()
            local has_expanded = pkg_state.expanded_json_schemas["lsp"]
            return Ui.Node {
                Ui.EmptyLine(),
                Ui.HlTextNode {
                    {
                        p.Bold(("%s LSP server configuration schema"):format(has_expanded and "↓" or "→")),
                        p.Comment((" (press enter to %s)"):format(has_expanded and "collapse" or "expand")),
                    },
                },
                Ui.Keybind(
                    settings.current.ui.keymaps.toggle_package_expand,
                    "TOGGLE_JSON_SCHEMA",
                    { package = pkg, schema_id = "lsp" }
                ),
                Ui.When(has_expanded, function()
                    return Ui.CascadingStyleNode({ "INDENT" }, {
                        Ui.HlTextNode(
                            p.muted "This is a read-only overview of the settings this server accepts. Note that some settings might not apply to neovim."
                        ),
                        Ui.EmptyLine(),
                        JsonSchema(pkg, "lsp", pkg_state, pkg_state.lsp_settings_schema),
                    })
                end),
            }
        end),
        Ui.EmptyLine(),
    })
end

local get_package_search_keywords = _.compose(_.join ", ", _.map(_.to_lower), _.path { "spec", "languages" })

---@param state InstallerUiState
---@param pkg Package
---@param opts { keybinds: KeybindHandlerNode[], icon: string[], is_installed: boolean, sticky: StickyCursorNode? }
local function PackageComponent(state, pkg, opts)
    local pkg_state = state.packages.states[pkg.name]
    local is_expanded = state.packages.expanded == pkg.name
    local label = (is_expanded or pkg_state.has_transitioned) and p.Bold(" " .. pkg.name) or p.none(" " .. pkg.name)

    local package_line = {
        opts.icon,
        label,
    }

    local pkg_aliases = pkg:get_aliases()
    if #pkg_aliases > 0 then
        package_line[#package_line + 1] = p.Comment(" " .. table.concat(pkg:get_aliases(), ", "))
    end
    if state.view.is_searching then
        package_line[#package_line + 1] = p.Comment((" (keywords: %s)"):format(get_package_search_keywords(pkg)))
    end
    if not opts.is_installed and pkg.spec.deprecation ~= nil then
        package_line[#package_line + 1] = p.warning " deprecated"
    end

    return Ui.Node {
        Ui.HlTextNode { package_line },
        opts.sticky or Ui.Node {},
        Ui.When(opts.is_installed and pkg.spec.deprecation ~= nil, function()
            return Ui.DiagnosticsNode {
                message = ("deprecated: %s"):format(pkg.spec.deprecation.message),
                severity = vim.diagnostic.severity.WARN,
                source = ("Deprecated since version %s"):format(pkg.spec.deprecation.since),
            }
        end),
        Ui.Keybind(settings.current.ui.keymaps.check_package_version, "CHECK_NEW_PACKAGE_VERSION", pkg),
        Ui.When(pkg_state.new_version ~= nil, function()
            return Ui.DiagnosticsNode {
                message = ("new version available: %s -> %s"):format(pkg_state.version or "-", pkg_state.new_version),
                severity = vim.diagnostic.severity.INFO,
            }
        end),
        Ui.Node(opts.keybinds),
        Ui.When(is_expanded, function()
            return ExpandedPackageInfo(state, pkg, opts.is_installed)
        end),
    }
end

local get_outdated_packages_preview = _.if_else(
    _.compose(_.lte(4), _.size),
    _.compose(_.join ", ", _.map(_.prop "name")),
    _.compose(
        _.join ", ",
        _.converge(_.concat, {
            _.compose(_.map(_.prop "name"), _.take(3)),
            function(pkgs)
                return { ("and %d more…"):format(#pkgs - 3) }
            end,
        })
    )
)

---@param state InstallerUiState
local function Installed(state)
    return Ui.Node {
        Ui.Keybind(settings.current.ui.keymaps.check_outdated_packages, "UPDATE_REGISTRY", nil, true),
        PackageListContainer {
            state = state,
            heading = Ui.Node {
                Ui.HlTextNode(p.heading "Installed"),
                Ui.When(state.info.registry_update.in_progress, function()
                    local styling = state.info.registry_update.percentage_complete == 1 and p.highlight_block
                        or p.muted_block
                    local is_all_registries_installed = _.all(_.prop "is_installed", state.info.registries)
                    local registry_count = #state.info.registries
                    local text
                    if registry_count > 1 then
                        text = p.Comment(
                            is_all_registries_installed and ("updating %d registries "):format(registry_count)
                                or ("installing %d registries "):format(registry_count)
                        )
                    else
                        text = p.Comment(is_all_registries_installed and "updating registry " or "installing registry ")
                    end
                    return Ui.VirtualTextNode {
                        text,
                        styling(
                            ("%-4s"):format(math.floor(state.info.registry_update.percentage_complete * 100) .. "%")
                        ),
                        styling((" "):rep(state.info.registry_update.percentage_complete * 15)),
                    }
                end),
                Ui.When(
                    not state.info.registry_update.in_progress and #state.packages.outdated_packages > 0,
                    function()
                        return Ui.VirtualTextNode {
                            p.muted "Press ",
                            p.highlight(settings.current.ui.keymaps.update_all_packages),
                            p.muted " to update ",
                            p.highlight(tostring(#state.packages.outdated_packages)),
                            p.muted(#state.packages.outdated_packages > 1 and " packages " or " package "),
                            p.Comment(("(%s)"):format(get_outdated_packages_preview(state.packages.outdated_packages))),
                        }
                    end
                ),
            },
            packages = state.packages.installed,
            ---@param pkg Package
            list_item_renderer = function(pkg)
                return PackageComponent(state, pkg, {
                    is_installed = true,
                    icon = p.highlight(settings.current.ui.icons.package_installed),
                    keybinds = {
                        Ui.Keybind(settings.current.ui.keymaps.update_package, "INSTALL_PACKAGE", pkg),
                        Ui.Keybind(settings.current.ui.keymaps.uninstall_package, "UNINSTALL_PACKAGE", pkg),
                        Ui.Keybind(settings.current.ui.keymaps.toggle_package_expand, "TOGGLE_EXPAND_PACKAGE", pkg),
                    },
                    sticky = Ui.StickyCursor { id = ("%s-installed"):format(pkg.name) },
                })
            end,
        },
    }
end

---@param pkg Package
---@param state InstallerUiState
local function InstallingPackageComponent(pkg, state)
    ---@type UiPackageState
    local pkg_state = state.packages.states[pkg.name]
    local current_state = pkg_state.is_terminated and p.Comment " (cancelling)" or p.none ""
    local tail = pkg_state.short_tailed_output
            and ("▶ # [%d/%d] %s"):format(
                #pkg_state.tailed_output,
                #pkg_state.tailed_output,
                pkg_state.short_tailed_output
            )
        or ""
    return Ui.Node {
        Ui.HlTextNode {
            {
                pkg_state.has_failed and p.error(settings.current.ui.icons.package_uninstalled)
                    or p.highlight(settings.current.ui.icons.package_pending),
                p.none(" " .. pkg.name),
                current_state,
                pkg_state.latest_spawn and p.Comment((" $ %s"):format(pkg_state.latest_spawn)) or p.none "",
            },
        },
        Ui.StickyCursor { id = ("%s-installing"):format(pkg.name) },
        Ui.Keybind(settings.current.ui.keymaps.cancel_installation, "TERMINATE_PACKAGE_HANDLE", pkg),
        Ui.Keybind(settings.current.ui.keymaps.install_package, "INSTALL_PACKAGE", pkg),
        Ui.CascadingStyleNode({ "INDENT" }, {
            Ui.HlTextNode(pkg_state.is_log_expanded and p.Bold "▼ Displaying full log" or p.muted(tail)),
            Ui.Keybind(settings.current.ui.keymaps.toggle_package_install_log, "TOGGLE_INSTALL_LOG", pkg),
            Ui.StickyCursor { id = ("%s-toggle-install-log"):format(pkg.name) },
        }),
        Ui.When(pkg_state.is_log_expanded, function()
            return Ui.CascadingStyleNode({ "INDENT", "INDENT" }, {
                Ui.HlTextNode(_.map(function(line)
                    return { p.muted(line) }
                end, pkg_state.tailed_output)),
            })
        end),
    }
end

---@param state InstallerUiState
local function Installing(state)
    local packages = state.packages.installing
    return PackageListContainer {
        state = state,
        heading = Ui.Node {
            Ui.HlTextNode(p.heading "Installing"),
            Ui.StickyCursor { id = "installing-section" },
            Ui.Keybind(settings.current.ui.keymaps.cancel_installation, "TERMINATE_PACKAGE_HANDLES", packages),
        },
        hide_when_empty = true,
        packages = packages,
        ---@param pkg Package
        list_item_renderer = InstallingPackageComponent,
    }
end

---@param state InstallerUiState
local function Queued(state)
    local packages = state.packages.queued
    return PackageListContainer {
        state = state,
        heading = Ui.Node {
            Ui.HlTextNode(p.heading "Queued"),
            Ui.StickyCursor { id = "queued-section" },
            Ui.Keybind(settings.current.ui.keymaps.cancel_installation, "TERMINATE_PACKAGE_HANDLES", packages),
        },
        packages = packages,
        hide_when_empty = true,
        ---@param pkg Package
        list_item_renderer = function(pkg)
            return Ui.Node {
                Ui.HlTextNode {
                    { p.highlight(settings.current.ui.icons.package_pending), p.none(" " .. pkg.name) },
                },
                Ui.StickyCursor { id = ("%s-installing"):format(pkg.spec.name) },
                Ui.Keybind(settings.current.ui.keymaps.cancel_installation, "TERMINATE_PACKAGE_HANDLE", pkg),
            }
        end,
    }
end

---@param state InstallerUiState
local function Failed(state)
    local packages = state.packages.failed
    if #packages == 0 then
        return Ui.Node {}
    end
    return PackageListContainer {
        state = state,
        heading = Ui.HlTextNode(p.heading "Failed"),
        packages = packages,
        list_item_renderer = InstallingPackageComponent,
    }
end

---@param state InstallerUiState
local function Uninstalled(state)
    return PackageListContainer {
        state = state,
        heading = Ui.HlTextNode(p.heading "Available"),
        packages = state.packages.uninstalled,
        ---@param pkg Package
        list_item_renderer = function(pkg)
            return PackageComponent(state, pkg, {
                icon = p.muted(settings.current.ui.icons.package_uninstalled),
                keybinds = {
                    Ui.Keybind(settings.current.ui.keymaps.install_package, "INSTALL_PACKAGE", pkg),
                    Ui.Keybind(settings.current.ui.keymaps.toggle_package_expand, "TOGGLE_EXPAND_PACKAGE", pkg),
                },
                sticky = Ui.StickyCursor { id = ("%s-uninstalled"):format(pkg.name) },
            })
        end,
    }
end

---@param state InstallerUiState
return function(state)
    return Ui.CascadingStyleNode({ "INDENT" }, {
        Failed(state),
        Installing(state),
        Queued(state),
        Installed(state),
        Uninstalled(state),
    })
end


================================================
FILE: lua/mason/ui/components/tabs.lua
================================================
local Package = require "mason-core.package"
local Ui = require "mason-core.ui"
local p = require "mason.ui.palette"

---@param text string
---@param index integer
---@param is_active boolean
---@param use_secondary_highlight boolean
local function create_tab_span(text, index, is_active, use_secondary_highlight)
    local highlight_block = use_secondary_highlight and p.highlight_block_bold_secondary or p.highlight_block_bold

    if is_active then
        return {
            highlight_block " ",
            highlight_block("(" .. index .. ")"),
            highlight_block(" " .. text .. " "),
            p.none " ",
        }
    else
        return {
            p.muted_block " ",
            p.muted_block("(" .. index .. ")"),
            p.muted_block(" " .. text .. " "),
            p.none " ",
        }
    end
end

---@param state InstallerUiState
return function(state)
    local tabs = {}
    for i, text in ipairs { "All", Package.Cat.LSP, Package.Cat.DAP, Package.Cat.Linter, Package.Cat.Formatter } do
        vim.list_extend(tabs, create_tab_span(text, i, state.view.current == text, state.view.is_showing_help))
    end
    return Ui.CascadingStyleNode({ "INDENT" }, {
        Ui.HlTextNode { tabs },
        Ui.StickyCursor { id = "tabs" },
    })
end


================================================
FILE: lua/mason/ui/init.lua
================================================
local M = {}

function M.close()
    local api = require "mason.ui.instance"
    api.close()
end

function M.open()
    local api = require "mason.ui.instance"
    api.window.open()
end

---@param view string
function M.set_view(view)
    local api = require "mason.ui.instance"
    api.set_view(view)
end

---@param tag any
function M.set_sticky_cursor(tag)
    local api = require "mason.ui.instance"
    api.set_sticky_cursor(tag)
end

return M


================================================
FILE: lua/mason/ui/instance.lua
================================================
-- !!!
-- in dire need of rework, proceed with caution
-- !!!
local Package = require "mason-core.package"
local Ui = require "mason-core.ui"
local _ = require "mason-core.functional"
local a = require "mason-core.async"
local display = require "mason-core.ui.display"
local notify = require "mason-core.notify"
local registry = require "mason-registry"
local settings = require "mason.settings"

local Header = require "mason.ui.components.header"
local Help = require "mason.ui.components.help"
local LanguageFilter = require "mason.ui.components.language-filter"
local Main = require "mason.ui.components.main"
local Tabs = require "mason.ui.components.tabs"

require "mason.ui.colors"

---@param state InstallerUiState
local function GlobalKeybinds(state)
    return Ui.Node {
        Ui.Keybind(settings.current.ui.keymaps.toggle_help, "TOGGLE_HELP", nil, true),
        Ui.Keybind("q", "CLOSE_WINDOW", nil, true),
        Ui.When(not state.view.language_filter, Ui.Keybind("<Esc>", "CLOSE_WINDOW", nil, true)),
        Ui.When(state.view.language_filter, Ui.Keybind("<Esc>", "CLEAR_LANGUAGE_FILTER", nil, true)),
        Ui.When(state.view.is_searching, Ui.Keybind("<Esc>", "CLEAR_SEARCH_MODE", nil, true)),
        Ui.Keybind(settings.current.ui.keymaps.apply_language_filter, "LANGUAGE_FILTER", nil, true),
        Ui.Keybind(settings.current.ui.keymaps.update_all_packages, "UPDATE_ALL_PACKAGES", nil, true),

        Ui.Keybind("1", "SET_VIEW", "All", true),
        Ui.Keybind("2", "SET_VIEW", "LSP", true),
        Ui.Keybind("3", "SET_VIEW", "DAP", true),
        Ui.Keybind("4", "SET_VIEW", "Linter", true),
        Ui.Keybind("5", "SET_VIEW", "Formatter", true),
    }
end

---@class UiPackageState
---@field expanded_json_schema_keys table<string, table<string, boolean>>
---@field expanded_json_schemas table<string, boolean>
---@field has_expanded_before boolean
---@field has_transitioned boolean
---@field is_terminated boolean
---@field is_log_expanded boolean
---@field has_failed boolean
---@field latest_spawn string?
---@field linked_executables table<string, string>?
---@field installed_purl string?
---@field lsp_settings_schema table?
---@field new_version string?
---@field short_tailed_output string?
---@field tailed_output string[]
---@field version string?

---@class InstallerUiState
local INITIAL_STATE = {
    info = {
        ---@type string | nil
        used_disk_space = nil,
        ---@type { name: string, is_installed: boolean }[]
        registries = {},
        registry_update = {
            ---@type string?
            error = nil,
            in_progress = false,
            percentage_complete = 0,
        },
    },
    view = {
        is_searching = false,
        is_showing_help = false,
        is_current_settings_expanded = false,
        language_filter = nil,
        current = "All",
        has_changed = false,
        ship_indentation = 0,
        ship_exclamation = "",
    },
    header = {
        title_prefix = "", -- for animation
    },
    packages = {
        ---@type Package[]
        outdated_packages = {},
        ---@type Package[]
        all = {},
        ---@type table<string, boolean>
        visible = {},
        ---@type string|nil
        expanded = nil,
        ---@type table<string, UiPackageState>
        states = {},
        ---@type Package[]
        installed = {},
        ---@type Package[]
        installing = {},
        ---@type Package[]
        failed = {},
        ---@type Package[]
        queued = {},
        ---@type Package[]
        uninstalled = {},
    },
}

---@generic T
---@param list T[]
---@param item T
---@return T
local function remove(list, item)
    for i, v in ipairs(list) do
        if v == item then
            table.remove(list, i)
            return list
        end
    end
    return list
end

local window = display.new_view_only_win("mason.nvim", "mason")

window.view(
    ---@param state InstallerUiState
    function(state)
        return Ui.Node {
            GlobalKeybinds(state),
            Header(state),
            Tabs(state),
            Ui.When(state.view.is_showing_help, function()
                return Help(state)
            end),
            Ui.When(not state.view.is_showing_help, function()
                return Ui.Node {
                    LanguageFilter(state),
                    Main(state),
                }
            end),
        }
    end
)

local mutate_state, get_state = window.state(INITIAL_STATE)

window.events:on("search:enter", function()
    mutate_state(function(state)
        state.view.is_searching = true
    end)
    vim.schedule(function()
        vim.cmd "redraw"
    end)
end)

window.events:on("search:leave", function(search)
    if search == "" and vim.fn.getreg "/" == "" then
        mutate_state(function(state)
            state.view.is_searching = false
        end)
    end
end)

---@param pkg Package
---@param group string
---@param tail boolean? Whether to insert at the end.
local function mutate_package_grouping(pkg, group, tail)
    mutate_state(function(state)
        remove(state.packages.installing, pkg)
        remove(state.packages.queued, pkg)
        remove(state.packages.uninstalled, pkg)
        remove(state.packages.installed, pkg)
        remove(state.packages.failed, pkg)
        if tail then
            table.insert(state.packages[group], pkg)
        else
            table.insert(state.packages[group], 1, pkg)
        end
        state.packages.states[pkg.name].has_transitioned = true
    end)
end

---@param mutate_fn fun(state: InstallerUiState)
local function mutate_package_visibility(mutate_fn)
    mutate_state(function(state)
        mutate_fn(state)
        local view_predicate = {
            ["All"] = _.T,
            ["LSP"] = _.prop_satisfies(_.any(_.equals(Package.Cat.LSP)), "categories"),
            ["DAP"] = _.prop_satisfies(_.any(_.equals(Package.Cat.DAP)), "categories"),
            ["Linter"] = _.prop_satisfies(_.any(_.equals(Package.Cat.Linter)), "categories"),
            ["Formatter"] = _.prop_satisfies(_.any(_.equals(Package.Cat.Formatter)), "categories"),
        }
        local language_predicate = _.if_else(
            _.always(state.view.language_filter),
            _.prop_satisfies(_.any(_.equals(state.view.language_filter)), "languages"),
            _.T
        )
        for __, pkg in ipairs(state.packages.all) do
            state.packages.visible[pkg.name] =
                _.all_pass({ view_predicate[state.view.current], language_predicate }, pkg.spec)
        end
    end)
end

---@return UiPackageState
local function create_initial_package_state()
    return {
        expanded_json_schema_keys = {},
        expanded_json_schemas = {},
        has_expanded_before = false,
        has_transitioned = false,
        is_terminated = false,
        is_log_expanded = false,
        has_failed = false,
        latest_spawn = nil,
        linked_executables = nil,
        installed_purl = nil,
        lsp_settings_schema = nil,
        new_version = nil,
        short_tailed_output = nil,
        tailed_output = {},
        version = nil,
    }
end

---@param handle InstallHandle
local function setup_handle(handle)
    local function handle_state_change()
        if handle.state == "QUEUED" then
            mutate_package_grouping(handle.package, "queued", true)
        elseif handle.state == "ACTIVE" then
            mutate_package_grouping(handle.package, "installing", true)
        elseif handle.state == "CLOSED" then
            mutate_state(function(state)
                state.packages.states[handle.package.name].is_terminated = false
            end)
        end
    end

    local function handle_spawnhandle_change()
        mutate_state(function(state)
            state.packages.states[handle.package.name].latest_spawn =
                handle:peek_spawn_handle():map(tostring):map(_.gsub("\n", "\\n ")):or_else(nil)
        end)
    end

    ---@param chunk string
    local function handle_output(chunk)
        mutate_state(function(state)
            local pkg_state = state.packages.states[handle.package.name]
            local lines = vim.split(chunk, "\n")
            for i = 1, #lines do
                local line = lines[i]
                if i == 1 and pkg_state.tailed_output[#pkg_state.tailed_output] then
                    pkg_state.tailed_output[#pkg_state.tailed_output] = pkg_state.tailed_output[#pkg_state.tailed_output]
                        .. line
                else
                    pkg_state.tailed_output[#pkg_state.tailed_output + 1] = line
                end
                if not line:match "^%s*$" then
                    pkg_state.short_tailed_output = line:gsub("^%s+", "")
                end
            end
        end)
    end

    local function handle_terminate()
        mutate_state(function(state)
            state.packages.states[handle.package.name].is_terminated = handle.is_terminated
            if handle:is_queued() then
                -- This is really already handled by the "install:failed" handler, but for UX reasons we handle
                -- terminated, queued, handlers here. The reason for this is that a queued handler, which is
                -- aborted, will not fail its installation until it acquires a semaphore permit, leading to a weird
                -- UX that may be perceived as non-functional.
                mutate_package_grouping(handle.package, handle.package:is_installed() and "installed" or "uninstalled")
            end
        end)
    end

    handle:on("terminate", handle_terminate)
    handle:on("state:change", handle_state_change)
    handle:on("spawn_handles:change", handle_spawnhandle_change)
    handle:on("stdout", handle_output)
    handle:on("stderr", handle_output)

    -- hydrate initial state
    handle_state_change()
    handle_spawnhandle_change()
    mutate_state(function(state)
        state.packages.states[handle.package.name] = create_initial_package_state()
    end)
end

---@param pkg Package
local function hydrate_detailed_package_state(pkg)
    mutate_state(function(state)
        -- initialize expanded keys table
        state.packages.states[pkg.name].expanded_json_schema_keys["lsp"] = state.packages.states[pkg.name].expanded_json_schema_keys["lsp"]
            or {}
        state.packages.states[pkg.name].lsp_settings_schema = pkg:get_lsp_settings_schema():or_else(nil)
        state.packages.states[pkg.name].version = pkg:get_installed_version()
    end)

    pkg:get_receipt():if_present(
        ---@param receipt InstallReceipt
        function(receipt)
            mutate_state(function(state)
                state.packages.states[pkg.name].linked_executables = receipt:get_links().bin
                state.packages.states[pkg.name].installed_purl = receipt:get_installed_purl()
            end)
        end
    )
end

local help_animation
do
    local help_command = ":help"
    local help_command_len = #help_command
    help_animation = Ui.animation {
        function(tick)
            mutate_state(function(state)
                state.header.title_prefix = help_command:sub(help_command_len - tick, help_command_len)
            end)
        end,
        range = { 0, help_command_len },
        delay_ms = 80,
    }
end

local ship_animation = Ui.animation {
    function(tick)
        mutate_state(function(state)
            state.view.ship_indentation = tick
            if tick > -5 then
                state.view.ship_exclamation = "https://github.com/sponsors/williamboman"
            elseif tick > -27 then
                state.view.ship_exclamation = "Sponsor mason.nvim development!"
            else
                state.view.ship_exclamation = ""
            end
        end)
    end,
    range = { -35, 5 },
    delay_ms = 250,
}

local function toggle_help()
    mutate_state(function(state)
        state.view.is_showing_help = not state.view.is_showing_help
        if state.view.is_showing_help then
            help_animation()
            ship_animation()
        end
    end)
end

local function set_view(event)
    local view = event.payload
    mutate_package_visibility(function(state)
        state.view.current = view
        state.view.has_changed = true
    end)
    if window.is_open() then
        local cursor_line = window.get_cursor()[1]
        if cursor_line > (window.get_win_config().height * 0.75) then
            window.set_sticky_cursor "tabs"
        end
    end
end

local function terminate_package_handle(event)
    ---@type Package
    local pkg = event.payload
    pkg:get_install_handle():if_present(
        ---@param handle InstallHandle
        function(handle)
            if not handle:is_closed() then
                vim.schedule_wrap(notify)(("Cancelling installation of %q."):format(pkg.name))
                handle:terminate()
            end
        end
    )

    pkg:get_uninstall_handle():if_present(
        ---@param handle InstallHandle
        function(handle)
            if not handle:is_closed() then
                vim.schedule_wrap(notify)(("Cancelling uninstallation of %q."):format(pkg.name))
                handle:terminate()
            end
        end
    )
end

local function terminate_all_package_handles(event)
    ---@type Package[]
    local pkgs = _.list_copy(event.payload) -- we copy because list is mutated while iterating it
    for _, pkg in ipairs(pkgs) do
        pkg:get_install_handle():if_present(
            ---@param handle InstallHandle
            function(handle)
                if not handle:is_closed() then
                    handle:terminate()
                end
            end
        )
    end
end

local function install_package(event)
    ---@type AbstractPackage
    local pkg = event.payload
    if not pkg:is_installing() then
        pkg:install()
    end
    mutate_state(function(state)
        state.packages.outdated_packages = _.filter(_.complement(_.equals(pkg)), state.packages.outdated_packages)
    end)
end

local function uninstall_package(event)
    ---@type AbstractPackage
    local pkg = event.payload
    if not pkg:is_uninstalling() then
        pkg:uninstall()
    end
end

local function toggle_expand_package(event)
    ---@type Package
    local pkg = event.payload
    mutate_state(function(state)
        if state.packages.expanded == pkg.name then
            state.packages.expanded = nil
        else
            if not state.packages.states[pkg.name].has_expanded_before then
                hydrate_detailed_package_state(pkg)
                state.packages.states[pkg.name].has_expanded_before = true
            end
            state.packages.expanded = pkg.name
        end
    end)
end

---@param pkg Package
local function check_new_package_version(pkg)
    local installed_version = pkg:get_installed_version()
    mutate_state(function(state)
        state.packages.states[pkg.name].version = installed_version
    end)
    local latest_version = pkg:get_latest_version()
    if latest_version ~= installed_version and pkg:is_installable { version = latest_version } then
        mutate_state(function(state)
            state.packages.states[pkg.name].new_version = latest_version
        end)
        return true
    else
        mutate_state(function(state)
            state.packages.states[pkg.name].new_version = nil
        end)
        return false
    end
end

local function check_new_package_versions()
    mutate_state(function(state)
        local outdated_packages = {}
        for _, pkg in ipairs(state.packages.installed) do
            local current_version = pkg:get_installed_version()
            local latest_version = pkg:get_latest_version()
            if current_version ~= latest_version then
                state.packages.states[pkg.name].version = current_version
                state.packages.states[pkg.name].new_version = latest_version
                table.insert(outdated_packages, pkg)
            else
                state.packages.states[pkg.name].new_version = nil
            end
        end
        state.packages.outdated_packages = outdated_packages
    end)
end

local function toggle_json_schema(event)
    local package, schema_id = event.payload.package, event.payload.schema_id
    mutate_state(function(state)
        state.packages.states[package.name].expanded_json_schemas[schema_id] =
            not state.packages.states[package.name].expanded_json_schemas[schema_id]
    end)
end

local function toggle_json_schema_keys(event)
    local package, schema_id, key = event.payload.package, event.payload.schema_id, event.payload.key
    mutate_state(function(state)
        state.packages.states[package.name].expanded_json_schema_keys[schema_id][key] =
            not state.packages.states[package.name].expanded_json_schema_keys[schema_id][key]
    end)
end

local function filter()
    vim.ui.select(_.sort_by(_.identity, _.keys(Package.Lang)), {
        prompt = "Select language:",
        kind = "mason.ui.language-filter",
    }, function(choice)
        if not choice or choice == "" then
            return
        end
        mutate_package_visibility(function(state)
            state.view.language_filter = choice
        end)
    end)
end

local function clear_filter()
    mutate_package_visibility(function(state)
        state.view.language_filter = nil
    end)
end

local function clear_search_mode()
    mutate_state(function(state)
        state.view.is_searching = false
    end)
end

local function toggle_expand_current_settings()
    mutate_state(function(state)
        state.view.is_current_settings_expanded = not state.view.is_current_settings_expanded
    end)
end

local function update_all_packages()
    local state = get_state()
    _.each(function(pkg)
        pkg:install()
    end, state.packages.outdated_packages)
    mutate_state(function(state)
        state.packages.outdated_packages = {}
    end)
end

local function toggle_install_log(event)
    ---@type Package
    local pkg = event.payload
    mutate_state(function(state)
        state.packages.states[pkg.name].is_log_expanded = not state.packages.states[pkg.name].is_log_expanded
    end)
end

local effects = {
    ["CHECK_NEW_PACKAGE_VERSION"] = a.scope(_.compose(_.partial(pcall, check_new_package_version), _.prop "payload")),
    ["UPDATE_REGISTRY"] = function()
        registry.update()
    end,
    ["CLEAR_LANGUAGE_FILTER"] = clear_filter,
    ["CLEAR_SEARCH_MODE"] = clear_search_mode,
    ["CLOSE_WINDOW"] = window.close,
    ["INSTALL_PACKAGE"] = install_package,
    ["LANGUAGE_FILTER"] = filter,
    ["SET_VIEW"] = set_view,
    ["TERMINATE_PACKAGE_HANDLE"] = terminate_package_handle,
    ["TERMINATE_PACKAGE_HANDLES"] = terminate_all_package_handles,
    ["TOGGLE_EXPAND_CURRENT_SETTINGS"] = toggle_expand_current_settings,
    ["TOGGLE_EXPAND_PACKAGE"] = toggle_expand_package,
    ["TOGGLE_HELP"] = toggle_help,
    ["TOGGLE_INSTALL_LOG"] = toggle_install_log,
    ["TOGGLE_JSON_SCHEMA"] = toggle_json_schema,
    ["TOGGLE_JSON_SCHEMA_KEY"] = toggle_json_schema_keys,
    ["UNINSTALL_PACKAGE"] = uninstall_package,
    ["UPDATE_ALL_PACKAGES"] = update_all_packages,
}

local registered_packages = {}

---@param pkg Package
local function setup_package(pkg)
    if registered_packages[pkg] then
        return
    end

    mutate_state(function(state)
        for _, group in ipairs {
            state.packages.installed,
            state.packages.uninstalled,
            state.packages.failed,
            state.packages.outdated_packages,
        } do
            for i, existing_pkg in ipairs(group) do
                if existing_pkg.name == pkg.name and pkg ~= existing_pkg then
                    -- New package instance (i.e. from a new, updated, registry source).
                    -- Release the old package instance.
                    table.remove(group, i)
                end
            end
        end
    end)

    -- hydrate initial state
    mutate_state(function(state)
        state.packages.states[pkg.name] = create_initial_package_state()
        state.packages.visible[pkg.name] = true
        table.insert(state.packages[pkg:is_installed() and "installed" or "uninstalled"], pkg)
    end)

    pkg:get_install_handle():if_present(setup_handle)
    pkg:on("install:handle", setup_handle)

    pkg:on("install:success", function()
        vim.schedule(function()
            notify(("%s was successfully installed."):format(pkg.name))
        end)
        mutate_state(function(state)
            state.packages.states[pkg.name] = create_initial_package_state()
            if state.packages.expanded == pkg.name then
                hydrate_detailed_package_state(pkg)
            end
        end)
        mutate_package_grouping(pkg, "installed")
    end)

    pkg:on(
        "install:failed",
        ---@param handle InstallHandle
        function(handle)
            if handle.is_terminated then
                -- If installation was explicitly terminated - restore to "pristine" state
                mutate_state(function(state)
                    state.packages.states[pkg.name] = create_initial_package_state()
                end)
                mutate_package_grouping(pkg, pkg:is_installed() and "installed" or "uninstalled")
            else
                vim.schedule(function()
                    notify(("%s failed to install."):format(pkg.name), vim.log.levels.ERROR)
                end)
                mutate_package_grouping(pkg, "failed")
                mutate_state(function(state)
                    state.packages.states[pkg.name].has_failed = true
                end)
            end
        end
    )

    pkg:on("uninstall:success", function()
        if pkg:is_installing() then
            -- We don't care about uninstallations that occur during installation because it's expected behaviour and
            -- not constructive to surface to users.
            return
        end
        vim.schedule(function()
            notify(("%s was successfully uninstalled."):format(pkg.name))
        end)
        mutate_state(function(state)
            state.packages.states[pkg.name] = create_initial_package_state()
            state.packages.outdated_packages = _.filter(_.complement(_.equals(pkg)), state.packages.outdated_packages)
        end)
        mutate_package_grouping(pkg, "uninstalled")
    end)

    registered_packages[pkg] = true
end

local function update_registry_info()
    local registries = {}
    for source in registry.sources:iterate { include_uninstalled = true, include_synthesized = false } do
        table.insert(registries, {
            name = source:get_display_name(),
            is_installed = source:is_installed(),
        })
    end
    mutate_state(function(state)
        state.info.registries = registries
    end)
end

---@param packages Package[]
local function setup_packages(packages)
    for _, pkg in ipairs(_.sort_by(_.prop "name", packages)) do
        setup_package(pkg)
    
Download .txt
gitextract_j3t903i2/

├── .cbfmt.toml
├── .editorconfig
├── .github/
│   ├── FUNDING.yml
│   ├── ISSUE_TEMPLATE/
│   │   ├── config.yml
│   │   ├── feature_request.yaml
│   │   ├── general_issue.yaml
│   │   ├── new_package_request.yaml
│   │   ├── package_installation_form.yaml
│   │   └── package_issue.yaml
│   └── workflows/
│       ├── cbfmt.yml
│       ├── release.yml
│       ├── selene.yml
│       ├── stylua.yml
│       └── tests.yml
├── .gitignore
├── CHANGELOG.md
├── CONTRIBUTING.md
├── LICENSE
├── Makefile
├── PACKAGES.md
├── README.md
├── SECURITY.md
├── doc/
│   ├── .gitignore
│   └── mason.txt
├── lua/
│   ├── mason/
│   │   ├── api/
│   │   │   └── command.lua
│   │   ├── health.lua
│   │   ├── init.lua
│   │   ├── providers/
│   │   │   ├── client/
│   │   │   │   ├── gh.lua
│   │   │   │   ├── golang.lua
│   │   │   │   ├── init.lua
│   │   │   │   ├── npm.lua
│   │   │   │   ├── openvsx.lua
│   │   │   │   ├── pypi.lua
│   │   │   │   └── rubygems.lua
│   │   │   └── registry-api/
│   │   │       └── init.lua
│   │   ├── settings.lua
│   │   ├── ui/
│   │   │   ├── colors.lua
│   │   │   ├── components/
│   │   │   │   ├── header.lua
│   │   │   │   ├── help/
│   │   │   │   │   ├── dap.lua
│   │   │   │   │   ├── formatter.lua
│   │   │   │   │   ├── init.lua
│   │   │   │   │   ├── linter.lua
│   │   │   │   │   └── lsp.lua
│   │   │   │   ├── json-schema.lua
│   │   │   │   ├── language-filter.lua
│   │   │   │   ├── main/
│   │   │   │   │   ├── init.lua
│   │   │   │   │   └── package_list.lua
│   │   │   │   └── tabs.lua
│   │   │   ├── init.lua
│   │   │   ├── instance.lua
│   │   │   └── palette.lua
│   │   └── version.lua
│   ├── mason-core/
│   │   ├── EventEmitter.lua
│   │   ├── async/
│   │   │   ├── control.lua
│   │   │   ├── init.lua
│   │   │   └── uv.lua
│   │   ├── fetch.lua
│   │   ├── fs.lua
│   │   ├── functional/
│   │   │   ├── data.lua
│   │   │   ├── function.lua
│   │   │   ├── init.lua
│   │   │   ├── list.lua
│   │   │   ├── logic.lua
│   │   │   ├── number.lua
│   │   │   ├── relation.lua
│   │   │   ├── string.lua
│   │   │   ├── table.lua
│   │   │   └── type.lua
│   │   ├── installer/
│   │   │   ├── InstallHandle.lua
│   │   │   ├── InstallLocation.lua
│   │   │   ├── InstallRunner.lua
│   │   │   ├── UninstallRunner.lua
│   │   │   ├── compiler/
│   │   │   │   ├── compilers/
│   │   │   │   │   ├── cargo.lua
│   │   │   │   │   ├── composer.lua
│   │   │   │   │   ├── gem.lua
│   │   │   │   │   ├── generic/
│   │   │   │   │   │   ├── build.lua
│   │   │   │   │   │   ├── download.lua
│   │   │   │   │   │   └── init.lua
│   │   │   │   │   ├── github/
│   │   │   │   │   │   ├── build.lua
│   │   │   │   │   │   ├── init.lua
│   │   │   │   │   │   └── release.lua
│   │   │   │   │   ├── golang.lua
│   │   │   │   │   ├── luarocks.lua
│   │   │   │   │   ├── mason.lua
│   │   │   │   │   ├── npm.lua
│   │   │   │   │   ├── nuget.lua
│   │   │   │   │   ├── opam.lua
│   │   │   │   │   ├── openvsx.lua
│   │   │   │   │   └── pypi.lua
│   │   │   │   ├── expr.lua
│   │   │   │   ├── init.lua
│   │   │   │   ├── link.lua
│   │   │   │   ├── schemas.lua
│   │   │   │   └── util.lua
│   │   │   ├── context/
│   │   │   │   ├── InstallContextCwd.lua
│   │   │   │   ├── InstallContextFs.lua
│   │   │   │   ├── InstallContextSpawn.lua
│   │   │   │   └── init.lua
│   │   │   ├── init.lua
│   │   │   ├── linker.lua
│   │   │   └── managers/
│   │   │       ├── cargo.lua
│   │   │       ├── common.lua
│   │   │       ├── composer.lua
│   │   │       ├── gem.lua
│   │   │       ├── golang.lua
│   │   │       ├── luarocks.lua
│   │   │       ├── npm.lua
│   │   │       ├── nuget.lua
│   │   │       ├── opam.lua
│   │   │       ├── powershell.lua
│   │   │       ├── pypi.lua
│   │   │       └── std.lua
│   │   ├── log.lua
│   │   ├── notify.lua
│   │   ├── optional.lua
│   │   ├── package/
│   │   │   ├── AbstractPackage.lua
│   │   │   └── init.lua
│   │   ├── path.lua
│   │   ├── pep440/
│   │   │   └── init.lua
│   │   ├── platform.lua
│   │   ├── process.lua
│   │   ├── providers.lua
│   │   ├── purl.lua
│   │   ├── receipt.lua
│   │   ├── result.lua
│   │   ├── semver.lua
│   │   ├── spawn.lua
│   │   ├── terminator.lua
│   │   └── ui/
│   │       ├── display.lua
│   │       ├── init.lua
│   │       └── state.lua
│   ├── mason-registry/
│   │   ├── api.lua
│   │   ├── index/
│   │   │   └── init.lua
│   │   ├── init.lua
│   │   ├── installer.lua
│   │   └── sources/
│   │       ├── file.lua
│   │       ├── github.lua
│   │       ├── init.lua
│   │       ├── lua.lua
│   │       ├── synthesized.lua
│   │       └── util.lua
│   ├── mason-test/
│   │   └── helpers.lua
│   └── mason-vendor/
│       ├── semver.lua
│       └── zzlib/
│           ├── inflate-bit32.lua
│           ├── inflate-bwo.lua
│           └── init.lua
├── selene.toml
├── stylua.toml
├── tests/
│   ├── fixtures/
│   │   ├── purl-test-suite-data.json
│   │   └── receipts/
│   │       ├── 1.0.json
│   │       ├── 1.1.json
│   │       └── 2.0.json
│   ├── helpers/
│   │   └── lua/
│   │       ├── dummy-registry/
│   │       │   ├── dummy.lua
│   │       │   ├── dummy2.lua
│   │       │   ├── index.lua
│   │       │   └── registry.lua
│   │       └── luassertx.lua
│   ├── mason/
│   │   ├── api/
│   │   │   └── command_spec.lua
│   │   └── setup_spec.lua
│   ├── mason-core/
│   │   ├── EventEmitter_spec.lua
│   │   ├── async/
│   │   │   └── async_spec.lua
│   │   ├── fetch_spec.lua
│   │   ├── fs_spec.lua
│   │   ├── functional/
│   │   │   ├── data_spec.lua
│   │   │   ├── function_spec.lua
│   │   │   ├── list_spec.lua
│   │   │   ├── logic_spec.lua
│   │   │   ├── number_spec.lua
│   │   │   ├── relation_spec.lua
│   │   │   ├── string_spec.lua
│   │   │   ├── table_spec.lua
│   │   │   └── type_spec.lua
│   │   ├── installer/
│   │   │   ├── InstallHandle_spec.lua
│   │   │   ├── InstallRunner_spec.lua
│   │   │   ├── compiler/
│   │   │   │   ├── compiler_spec.lua
│   │   │   │   ├── compilers/
│   │   │   │   │   ├── cargo_spec.lua
│   │   │   │   │   ├── composer_spec.lua
│   │   │   │   │   ├── gem_spec.lua
│   │   │   │   │   ├── generic/
│   │   │   │   │   │   ├── build_spec.lua
│   │   │   │   │   │   └── download_spec.lua
│   │   │   │   │   ├── github/
│   │   │   │   │   │   ├── build_spec.lua
│   │   │   │   │   │   └── release_spec.lua
│   │   │   │   │   ├── golang_spec.lua
│   │   │   │   │   ├── luarocks_spec.lua
│   │   │   │   │   ├── npm_spec.lua
│   │   │   │   │   ├── nuget_spec.lua
│   │   │   │   │   ├── opam_spec.lua
│   │   │   │   │   ├── openvsx_spec.lua
│   │   │   │   │   └── pypi_spec.lua
│   │   │   │   ├── expr_spec.lua
│   │   │   │   ├── link_spec.lua
│   │   │   │   └── util_spec.lua
│   │   │   ├── context_spec.lua
│   │   │   ├── linker_spec.lua
│   │   │   └── managers/
│   │   │       ├── cargo_spec.lua
│   │   │       ├── common_spec.lua
│   │   │       ├── composer_spec.lua
│   │   │       ├── gem_spec.lua
│   │   │       ├── golang_spec.lua
│   │   │       ├── luarocks_spec.lua
│   │   │       ├── npm_spec.lua
│   │   │       ├── nuget_spec.lua
│   │   │       ├── opam_spec.lua
│   │   │       ├── powershell_spec.lua
│   │   │       ├── pypi_spec.lua
│   │   │       └── std_spec.lua
│   │   ├── optional_spec.lua
│   │   ├── package/
│   │   │   └── package_spec.lua
│   │   ├── path_spec.lua
│   │   ├── pep440_spec.lua
│   │   ├── platform_spec.lua
│   │   ├── process_spec.lua
│   │   ├── providers/
│   │   │   └── provider_spec.lua
│   │   ├── purl_spec.lua
│   │   ├── receipt_spec.lua
│   │   ├── result_spec.lua
│   │   ├── spawn_spec.lua
│   │   ├── terminator_spec.lua
│   │   └── ui_spec.lua
│   ├── mason-registry/
│   │   ├── api_spec.lua
│   │   ├── registry_spec.lua
│   │   └── sources/
│   │       ├── collection_spec.lua
│   │       └── lua_spec.lua
│   └── minimal_init.vim
└── vim.yml
Condensed preview — 225 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (929K chars).
[
  {
    "path": ".cbfmt.toml",
    "chars": 68,
    "preview": "[languages]\nlua = [\"stylua -s -\"]\nsh = [\"shellharden --transform \"]\n"
  },
  {
    "path": ".editorconfig",
    "chars": 206,
    "preview": "root = true\n\n[*]\nindent_style = space\nindent_size = 4\nend_of_line = lf\ninsert_final_newline = true\ntrim_trailing_whitesp"
  },
  {
    "path": ".github/FUNDING.yml",
    "chars": 818,
    "preview": "# These are supported funding model platforms\n\ngithub: [williamboman] # Replace with up to 4 GitHub Sponsors-enabled use"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/config.yml",
    "chars": 221,
    "preview": "---\n\ncontact_links:\n  - name: Ask a question about mason.nvim or get support\n    url: https://github.com/mason-org/mason"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/feature_request.yaml",
    "chars": 893,
    "preview": "---\n\nname: Feature request\ndescription: Suggest an idea for this project\nlabels:\n    - enhancement\n\nbody:\n    - type: ch"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/general_issue.yaml",
    "chars": 2611,
    "preview": "---\nname: Non-package-related issue\ndescription: Report an issue not related to installation or usage of packages\n\nbody:"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/new_package_request.yaml",
    "chars": 1282,
    "preview": "---\n\nname: New package request\ndescription: Request a new package not currently available\ntitle: \"[New package]: \"\nlabel"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/package_installation_form.yaml",
    "chars": 3276,
    "preview": "---\n\nname: Package installation issue\ndescription: Report an issue that occurs during the installation of a package\nlabe"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/package_issue.yaml",
    "chars": 3405,
    "preview": "---\n\nname: Package issue\ndescription: Report an issue with using a package installed via mason.nvim\nlabels:\n    - packag"
  },
  {
    "path": ".github/workflows/cbfmt.yml",
    "chars": 1458,
    "preview": "name: cbfmt check\n\non:\n    push:\n        branches:\n            - \"main\"\n    pull_request:\n\njobs:\n    cbfmt:\n        runs"
  },
  {
    "path": ".github/workflows/release.yml",
    "chars": 749,
    "preview": "name: Release\n\non:\n  push:\n    branches:\n      - \"main\"\npermissions:\n  contents: write\n  pull-requests: write\n\njobs:\n  r"
  },
  {
    "path": ".github/workflows/selene.yml",
    "chars": 533,
    "preview": "name: Selene check\n\non:\n    push:\n        branches:\n            - \"main\"\n    pull_request:\n\njobs:\n    selene:\n        ru"
  },
  {
    "path": ".github/workflows/stylua.yml",
    "chars": 566,
    "preview": "name: Stylua check\n\non:\n    push:\n        branches:\n            - \"main\"\n    pull_request:\n\njobs:\n    stylua:\n        ru"
  },
  {
    "path": ".github/workflows/tests.yml",
    "chars": 811,
    "preview": "name: Tests\n\non:\n    push:\n        branches:\n            - \"main\"\n    pull_request:\n\njobs:\n    tests:\n        strategy:\n"
  },
  {
    "path": ".gitignore",
    "chars": 48,
    "preview": ".luarc.json\n/dependencies\n/tests/fixtures/mason\n"
  },
  {
    "path": "CHANGELOG.md",
    "chars": 27194,
    "preview": "# Changelog\n\n## [2.2.1](https://github.com/mason-org/mason.nvim/compare/v2.2.0...v2.2.1) (2026-01-07)\n\n\n### Bug Fixes\n\n*"
  },
  {
    "path": "CONTRIBUTING.md",
    "chars": 2393,
    "preview": "-   [Contribution policy](#contribution-policy)\n-   [Adding a new package](#adding-a-new-package)\n-   [Code style](#code"
  },
  {
    "path": "LICENSE",
    "chars": 10141,
    "preview": "                                 Apache License\n                           Version 2.0, January 2004\n                   "
  },
  {
    "path": "Makefile",
    "chars": 679,
    "preview": "INSTALL_ROOT_DIR:=$(shell pwd)/tests/fixtures/mason\nNVIM_HEADLESS:=nvim --headless --noplugin -u tests/minimal_init.vim\n"
  },
  {
    "path": "PACKAGES.md",
    "chars": 50,
    "preview": "Moved to https://mason-registry.dev/registry/list\n"
  },
  {
    "path": "README.md",
    "chars": 13834,
    "preview": "![Linux](https://img.shields.io/badge/Linux-%23.svg?logo=linux&color=FCC624&logoColor=black)\n![macOS](https://img.shield"
  },
  {
    "path": "SECURITY.md",
    "chars": 427,
    "preview": "# Security policy\n\n## Reporting a Vulnerability\n\nPlease report any suspected security vulnerabilities [here][new-advisor"
  },
  {
    "path": "doc/.gitignore",
    "chars": 5,
    "preview": "tags\n"
  },
  {
    "path": "doc/mason.txt",
    "chars": 20718,
    "preview": "*mason.nvim*\n\nMinimum version of neovim: 0.10.0\n\nAuthor: William Boman\n                                                 "
  },
  {
    "path": "lua/mason/api/command.lua",
    "chars": 9596,
    "preview": "local _ = require \"mason-core.functional\"\nlocal platform = require \"mason-core.platform\"\n\nlocal function Mason()\n    req"
  },
  {
    "path": "lua/mason/health.lua",
    "chars": 10543,
    "preview": "local health = vim.health or require \"health\"\nlocal Result = require \"mason-core.result\"\nlocal _ = require \"mason-core.f"
  },
  {
    "path": "lua/mason/init.lua",
    "chars": 840,
    "preview": "local InstallLocation = require \"mason-core.installer.InstallLocation\"\nlocal Registry = require \"mason-registry\"\nlocal s"
  },
  {
    "path": "lua/mason/providers/client/gh.lua",
    "chars": 1497,
    "preview": "local _ = require \"mason-core.functional\"\nlocal fetch = require \"mason-core.fetch\"\nlocal spawn = require \"mason-core.spa"
  },
  {
    "path": "lua/mason/providers/client/golang.lua",
    "chars": 481,
    "preview": "local _ = require \"mason-core.functional\"\nlocal spawn = require \"mason-core.spawn\"\n\n---@type GolangProvider\nreturn {\n   "
  },
  {
    "path": "lua/mason/providers/client/init.lua",
    "chars": 345,
    "preview": "---@type Provider\nreturn {\n    github = require \"mason.providers.client.gh\",\n    npm = require \"mason.providers.client.n"
  },
  {
    "path": "lua/mason/providers/client/npm.lua",
    "chars": 594,
    "preview": "local _ = require \"mason-core.functional\"\nlocal spawn = require \"mason-core.spawn\"\n\n---@type NpmProvider\nreturn {\n    ge"
  },
  {
    "path": "lua/mason/providers/client/openvsx.lua",
    "chars": 893,
    "preview": "local _ = require \"mason-core.functional\"\nlocal fetch = require \"mason-core.fetch\"\nlocal semver = require \"mason-core.se"
  },
  {
    "path": "lua/mason/providers/client/pypi.lua",
    "chars": 2314,
    "preview": "local Optional = require \"mason-core.optional\"\nlocal Result = require \"mason-core.result\"\nlocal _ = require \"mason-core."
  },
  {
    "path": "lua/mason/providers/client/rubygems.lua",
    "chars": 909,
    "preview": "local Optional = require \"mason-core.optional\"\nlocal _ = require \"mason-core.functional\"\nlocal spawn = require \"mason-co"
  },
  {
    "path": "lua/mason/providers/registry-api/init.lua",
    "chars": 3013,
    "preview": "local Result = require \"mason-core.result\"\nlocal _ = require \"mason-core.functional\"\nlocal api = require \"mason-registry"
  },
  {
    "path": "lua/mason/settings.lua",
    "chars": 5925,
    "preview": "local path = require \"mason-core.path\"\n\nlocal M = {}\n\n---@class MasonSettings\nlocal DEFAULT_SETTINGS = {\n    ---@since 1"
  },
  {
    "path": "lua/mason/ui/colors.lua",
    "chars": 1331,
    "preview": "local hl_groups = {\n    MasonBackdrop = { bg = \"#000000\", default = true },\n    MasonNormal = { link = \"NormalFloat\", de"
  },
  {
    "path": "lua/mason/ui/components/header.lua",
    "chars": 2935,
    "preview": "local Ui = require \"mason-core.ui\"\nlocal _ = require \"mason-core.functional\"\nlocal p = require \"mason.ui.palette\"\nlocal "
  },
  {
    "path": "lua/mason/ui/components/help/dap.lua",
    "chars": 1038,
    "preview": "local Ui = require \"mason-core.ui\"\nlocal p = require \"mason.ui.palette\"\n\n---@param state InstallerUiState\nreturn functio"
  },
  {
    "path": "lua/mason/ui/components/help/formatter.lua",
    "chars": 644,
    "preview": "local Ui = require \"mason-core.ui\"\nlocal p = require \"mason.ui.palette\"\n\n---@param state InstallerUiState\nreturn functio"
  },
  {
    "path": "lua/mason/ui/components/help/init.lua",
    "chars": 7761,
    "preview": "local Ui = require \"mason-core.ui\"\nlocal _ = require \"mason-core.functional\"\nlocal log = require \"mason-core.log\"\nlocal "
  },
  {
    "path": "lua/mason/ui/components/help/linter.lua",
    "chars": 685,
    "preview": "local Ui = require \"mason-core.ui\"\nlocal p = require \"mason.ui.palette\"\n\n---@param state InstallerUiState\nreturn functio"
  },
  {
    "path": "lua/mason/ui/components/help/lsp.lua",
    "chars": 1145,
    "preview": "local Ui = require \"mason-core.ui\"\nlocal p = require \"mason.ui.palette\"\n\n---@param state InstallerUiState\nreturn functio"
  },
  {
    "path": "lua/mason/ui/components/json-schema.lua",
    "chars": 6639,
    "preview": "-- Here be dragons\nlocal Ui = require \"mason-core.ui\"\nlocal _ = require \"mason-core.functional\"\nlocal settings = require"
  },
  {
    "path": "lua/mason/ui/components/language-filter.lua",
    "chars": 1120,
    "preview": "local Ui = require \"mason-core.ui\"\nlocal p = require \"mason.ui.palette\"\nlocal settings = require \"mason.settings\"\n\n---@p"
  },
  {
    "path": "lua/mason/ui/components/main/init.lua",
    "chars": 244,
    "preview": "local Ui = require \"mason-core.ui\"\n\nlocal PackageList = require \"mason.ui.components.main.package_list\"\n\n---@param state"
  },
  {
    "path": "lua/mason/ui/components/main/package_list.lua",
    "chars": 15645,
    "preview": "local Ui = require \"mason-core.ui\"\nlocal _ = require \"mason-core.functional\"\nlocal p = require \"mason.ui.palette\"\nlocal "
  },
  {
    "path": "lua/mason/ui/components/tabs.lua",
    "chars": 1279,
    "preview": "local Package = require \"mason-core.package\"\nlocal Ui = require \"mason-core.ui\"\nlocal p = require \"mason.ui.palette\"\n\n--"
  },
  {
    "path": "lua/mason/ui/init.lua",
    "chars": 448,
    "preview": "local M = {}\n\nfunction M.close()\n    local api = require \"mason.ui.instance\"\n    api.close()\nend\n\nfunction M.open()\n    "
  },
  {
    "path": "lua/mason/ui/instance.lua",
    "chars": 25337,
    "preview": "-- !!!\n-- in dire need of rework, proceed with caution\n-- !!!\nlocal Package = require \"mason-core.package\"\nlocal Ui = re"
  },
  {
    "path": "lua/mason/ui/palette.lua",
    "chars": 864,
    "preview": "local M = {}\n\nlocal function hl(highlight)\n    return function(text)\n        return { text, highlight }\n    end\nend\n\n-- "
  },
  {
    "path": "lua/mason/version.lua",
    "chars": 211,
    "preview": "local M = {}\n\nM.VERSION = \"v2.2.1\" -- x-release-please-version\nM.MAJOR_VERSION = 2 -- x-release-please-major\nM.MINOR_VER"
  },
  {
    "path": "lua/mason-core/EventEmitter.lua",
    "chars": 2387,
    "preview": "local log = require \"mason-core.log\"\n---@class EventEmitter\n---@field private __event_handlers table<any, table<fun(), f"
  },
  {
    "path": "lua/mason-core/async/control.lua",
    "chars": 3731,
    "preview": "local a = require \"mason-core.async\"\n\n---@class Condvar\nlocal Condvar = {}\nCondvar.__index = Condvar\n\nfunction Condvar:n"
  },
  {
    "path": "lua/mason-core/async/init.lua",
    "chars": 5990,
    "preview": "local _ = require \"mason-core.functional\"\nlocal co = coroutine\n\nlocal exports = {}\n\nlocal Promise = {}\nPromise.__index ="
  },
  {
    "path": "lua/mason-core/async/uv.lua",
    "chars": 1013,
    "preview": "local a = require \"mason-core.async\"\n\n---@type table<UvMethod, async fun(...)>\nlocal M = setmetatable({}, {\n    __index "
  },
  {
    "path": "lua/mason-core/fetch.lua",
    "chars": 4837,
    "preview": "local Result = require \"mason-core.result\"\nlocal _ = require \"mason-core.functional\"\nlocal a = require \"mason-core.async"
  },
  {
    "path": "lua/mason-core/fs.lua",
    "chars": 5443,
    "preview": "local Path = require \"mason-core.path\"\nlocal a = require \"mason-core.async\"\nlocal log = require \"mason-core.log\"\nlocal s"
  },
  {
    "path": "lua/mason-core/functional/data.lua",
    "chars": 507,
    "preview": "local _ = {}\n\n_.table_pack = function(...)\n    return { n = select(\"#\", ...), ... }\nend\n\n---@generic T : string\n---@para"
  },
  {
    "path": "lua/mason-core/functional/function.lua",
    "chars": 3229,
    "preview": "local data = require \"mason-core.functional.data\"\n\nlocal _ = {}\n\n---@generic T : fun(...)\n---@param fn T\n---@param arity"
  },
  {
    "path": "lua/mason-core/functional/init.lua",
    "chars": 4272,
    "preview": "local _ = {}\n\nlocal function lazy_require(module)\n    return setmetatable({}, {\n        __index = function(m, k)\n       "
  },
  {
    "path": "lua/mason-core/functional/list.lua",
    "chars": 6889,
    "preview": "local data = require \"mason-core.functional.data\"\nlocal fun = require \"mason-core.functional.function\"\n\nlocal _ = {}\n\n--"
  },
  {
    "path": "lua/mason-core/functional/logic.lua",
    "chars": 1918,
    "preview": "local fun = require \"mason-core.functional.function\"\n\nlocal _ = {}\n\n---@generic T\n---@param predicates (fun(item: T): bo"
  },
  {
    "path": "lua/mason-core/functional/number.lua",
    "chars": 633,
    "preview": "local fun = require \"mason-core.functional.function\"\n\nlocal _ = {}\n\n---@param number number\n_.negate = function(number)\n"
  },
  {
    "path": "lua/mason-core/functional/relation.lua",
    "chars": 980,
    "preview": "local fun = require \"mason-core.functional.function\"\n\nlocal _ = {}\n\n_.equals = fun.curryN(function(expected, value)\n    "
  },
  {
    "path": "lua/mason-core/functional/string.lua",
    "chars": 3467,
    "preview": "local fun = require \"mason-core.functional.function\"\n\nlocal _ = {}\n\n---@param pattern string\n---@param str string\n_.matc"
  },
  {
    "path": "lua/mason-core/functional/table.lua",
    "chars": 2594,
    "preview": "local fun = require \"mason-core.functional.function\"\n\nlocal _ = {}\n\n---@generic T : table\n---@param tbl T\n---@return T\nl"
  },
  {
    "path": "lua/mason-core/functional/type.lua",
    "chars": 317,
    "preview": "local fun = require \"mason-core.functional.function\"\nlocal rel = require \"mason-core.functional.relation\"\n\nlocal _ = {}\n"
  },
  {
    "path": "lua/mason-core/installer/InstallHandle.lua",
    "chars": 6350,
    "preview": "local EventEmitter = require \"mason-core.EventEmitter\"\nlocal Optional = require \"mason-core.optional\"\nlocal _ = require "
  },
  {
    "path": "lua/mason-core/installer/InstallLocation.lua",
    "chars": 2410,
    "preview": "local Path = require \"mason-core.path\"\nlocal platform = require \"mason-core.platform\"\nlocal settings = require \"mason.se"
  },
  {
    "path": "lua/mason-core/installer/InstallRunner.lua",
    "chars": 7474,
    "preview": "local Result = require \"mason-core.result\"\nlocal _ = require \"mason-core.functional\"\nlocal a = require \"mason-core.async"
  },
  {
    "path": "lua/mason-core/installer/UninstallRunner.lua",
    "chars": 3885,
    "preview": "local InstallContext = require \"mason-core.installer.context\"\nlocal Result = require \"mason-core.result\"\nlocal _ = requi"
  },
  {
    "path": "lua/mason-core/installer/compiler/compilers/cargo.lua",
    "chars": 2189,
    "preview": "local Result = require \"mason-core.result\"\nlocal _ = require \"mason-core.functional\"\nlocal providers = require \"mason-co"
  },
  {
    "path": "lua/mason-core/installer/compiler/compilers/composer.lua",
    "chars": 899,
    "preview": "local Result = require \"mason-core.result\"\nlocal providers = require \"mason-core.providers\"\nlocal util = require \"mason-"
  },
  {
    "path": "lua/mason-core/installer/compiler/compilers/gem.lua",
    "chars": 961,
    "preview": "local Result = require \"mason-core.result\"\nlocal _ = require \"mason-core.functional\"\nlocal providers = require \"mason-co"
  },
  {
    "path": "lua/mason-core/installer/compiler/compilers/generic/build.lua",
    "chars": 1274,
    "preview": "local Result = require \"mason-core.result\"\nlocal _ = require \"mason-core.functional\"\nlocal common = require \"mason-core."
  },
  {
    "path": "lua/mason-core/installer/compiler/compilers/generic/download.lua",
    "chars": 1627,
    "preview": "local Result = require \"mason-core.result\"\nlocal _ = require \"mason-core.functional\"\nlocal common = require \"mason-core."
  },
  {
    "path": "lua/mason-core/installer/compiler/compilers/generic/init.lua",
    "chars": 1425,
    "preview": "local Result = require \"mason-core.result\"\nlocal _ = require \"mason-core.functional\"\n\nlocal M = {}\n\n---@param source Gen"
  },
  {
    "path": "lua/mason-core/installer/compiler/compilers/github/build.lua",
    "chars": 1468,
    "preview": "local Result = require \"mason-core.result\"\nlocal _ = require \"mason-core.functional\"\nlocal common = require \"mason-core."
  },
  {
    "path": "lua/mason-core/installer/compiler/compilers/github/init.lua",
    "chars": 1759,
    "preview": "local Result = require \"mason-core.result\"\n\nlocal M = {}\n\n---@param source GitHubReleaseSource | GitHubBuildSource\n---@p"
  },
  {
    "path": "lua/mason-core/installer/compiler/compilers/github/release.lua",
    "chars": 1888,
    "preview": "local Result = require \"mason-core.result\"\nlocal _ = require \"mason-core.functional\"\nlocal common = require \"mason-core."
  },
  {
    "path": "lua/mason-core/installer/compiler/compilers/golang.lua",
    "chars": 1327,
    "preview": "local Result = require \"mason-core.result\"\nlocal _ = require \"mason-core.functional\"\nlocal providers = require \"mason-co"
  },
  {
    "path": "lua/mason-core/installer/compiler/compilers/luarocks.lua",
    "chars": 1285,
    "preview": "local Result = require \"mason-core.result\"\nlocal _ = require \"mason-core.functional\"\n\nlocal M = {}\n\n---@param purl Purl\n"
  },
  {
    "path": "lua/mason-core/installer/compiler/compilers/mason.lua",
    "chars": 1121,
    "preview": "local Result = require \"mason-core.result\"\nlocal _ = require \"mason-core.functional\"\n\nlocal M = {}\n\n---@param source Reg"
  },
  {
    "path": "lua/mason-core/installer/compiler/compilers/npm.lua",
    "chars": 1239,
    "preview": "local Result = require \"mason-core.result\"\nlocal _ = require \"mason-core.functional\"\nlocal providers = require \"mason-co"
  },
  {
    "path": "lua/mason-core/installer/compiler/compilers/nuget.lua",
    "chars": 693,
    "preview": "local Result = require \"mason-core.result\"\n\nlocal M = {}\n\n---@param source RegistryPackageSource\n---@param purl Purl\nfun"
  },
  {
    "path": "lua/mason-core/installer/compiler/compilers/opam.lua",
    "chars": 688,
    "preview": "local Result = require \"mason-core.result\"\n\nlocal M = {}\n\n---@param source RegistryPackageSource\n---@param purl Purl\nfun"
  },
  {
    "path": "lua/mason-core/installer/compiler/compilers/openvsx.lua",
    "chars": 2081,
    "preview": "local Result = require \"mason-core.result\"\nlocal common = require \"mason-core.installer.managers.common\"\nlocal expr = re"
  },
  {
    "path": "lua/mason-core/installer/compiler/compilers/pypi.lua",
    "chars": 1629,
    "preview": "local Result = require \"mason-core.result\"\nlocal _ = require \"mason-core.functional\"\nlocal providers = require \"mason-co"
  },
  {
    "path": "lua/mason-core/installer/compiler/expr.lua",
    "chars": 3114,
    "preview": "local Result = require \"mason-core.result\"\nlocal _ = require \"mason-core.functional\"\nlocal platform = require \"mason-cor"
  },
  {
    "path": "lua/mason-core/installer/compiler/init.lua",
    "chars": 8966,
    "preview": "local Optional = require \"mason-core.optional\"\nlocal Purl = require \"mason-core.purl\"\nlocal Result = require \"mason-core"
  },
  {
    "path": "lua/mason-core/installer/compiler/link.lua",
    "chars": 10970,
    "preview": "local Optional = require \"mason-core.optional\"\nlocal Result = require \"mason-core.result\"\nlocal _ = require \"mason-core."
  },
  {
    "path": "lua/mason-core/installer/compiler/schemas.lua",
    "chars": 2727,
    "preview": "local Result = require \"mason-core.result\"\nlocal _ = require \"mason-core.functional\"\nlocal a = require \"mason-core.async"
  },
  {
    "path": "lua/mason-core/installer/compiler/util.lua",
    "chars": 3072,
    "preview": "local Optional = require \"mason-core.optional\"\nlocal Result = require \"mason-core.result\"\nlocal _ = require \"mason-core."
  },
  {
    "path": "lua/mason-core/installer/context/InstallContextCwd.lua",
    "chars": 1422,
    "preview": "local Result = require \"mason-core.result\"\nlocal fs = require \"mason-core.fs\"\nlocal path = require \"mason-core.path\"\n\n--"
  },
  {
    "path": "lua/mason-core/installer/context/InstallContextFs.lua",
    "chars": 3579,
    "preview": "local fs = require \"mason-core.fs\"\nlocal log = require \"mason-core.log\"\nlocal path = require \"mason-core.path\"\n\n---@clas"
  },
  {
    "path": "lua/mason-core/installer/context/InstallContextSpawn.lua",
    "chars": 1739,
    "preview": "local spawn = require \"mason-core.spawn\"\n\n---@class InstallContextSpawn\n---@field strict_mode boolean Whether spawn fail"
  },
  {
    "path": "lua/mason-core/installer/context/init.lua",
    "chars": 11222,
    "preview": "local InstallContextCwd = require \"mason-core.installer.context.InstallContextCwd\"\nlocal InstallContextFs = require \"mas"
  },
  {
    "path": "lua/mason-core/installer/init.lua",
    "chars": 197,
    "preview": "local InstallContext = require \"mason-core.installer.context\"\n\nlocal M = {}\n\n---@return InstallContext\nfunction M.contex"
  },
  {
    "path": "lua/mason-core/installer/linker.lua",
    "chars": 6067,
    "preview": "local Result = require \"mason-core.result\"\nlocal _ = require \"mason-core.functional\"\nlocal a = require \"mason-core.async"
  },
  {
    "path": "lua/mason-core/installer/managers/cargo.lua",
    "chars": 1367,
    "preview": "local Result = require \"mason-core.result\"\nlocal _ = require \"mason-core.functional\"\nlocal installer = require \"mason-co"
  },
  {
    "path": "lua/mason-core/installer/managers/common.lua",
    "chars": 3697,
    "preview": "local Result = require \"mason-core.result\"\nlocal _ = require \"mason-core.functional\"\nlocal a = require \"mason-core.async"
  },
  {
    "path": "lua/mason-core/installer/managers/composer.lua",
    "chars": 1214,
    "preview": "local Result = require \"mason-core.result\"\nlocal _ = require \"mason-core.functional\"\nlocal installer = require \"mason-co"
  },
  {
    "path": "lua/mason-core/installer/managers/gem.lua",
    "chars": 1850,
    "preview": "local Result = require \"mason-core.result\"\nlocal installer = require \"mason-core.installer\"\nlocal log = require \"mason-c"
  },
  {
    "path": "lua/mason-core/installer/managers/golang.lua",
    "chars": 1420,
    "preview": "local Result = require \"mason-core.result\"\nlocal _ = require \"mason-core.functional\"\nlocal installer = require \"mason-co"
  },
  {
    "path": "lua/mason-core/installer/managers/luarocks.lua",
    "chars": 1247,
    "preview": "local Result = require \"mason-core.result\"\nlocal _ = require \"mason-core.functional\"\nlocal installer = require \"mason-co"
  },
  {
    "path": "lua/mason-core/installer/managers/npm.lua",
    "chars": 3135,
    "preview": "local Result = require \"mason-core.result\"\nlocal _ = require \"mason-core.functional\"\nlocal installer = require \"mason-co"
  },
  {
    "path": "lua/mason-core/installer/managers/nuget.lua",
    "chars": 900,
    "preview": "local Result = require \"mason-core.result\"\nlocal installer = require \"mason-core.installer\"\nlocal log = require \"mason-c"
  },
  {
    "path": "lua/mason-core/installer/managers/opam.lua",
    "chars": 1026,
    "preview": "local Result = require \"mason-core.result\"\nlocal _ = require \"mason-core.functional\"\nlocal installer = require \"mason-co"
  },
  {
    "path": "lua/mason-core/installer/managers/powershell.lua",
    "chars": 1348,
    "preview": "local _ = require \"mason-core.functional\"\nlocal a = require \"mason-core.async\"\nlocal process = require \"mason-core.proce"
  },
  {
    "path": "lua/mason-core/installer/managers/pypi.lua",
    "chars": 8376,
    "preview": "local Optional = require \"mason-core.optional\"\nlocal Result = require \"mason-core.result\"\nlocal _ = require \"mason-core."
  },
  {
    "path": "lua/mason-core/installer/managers/std.lua",
    "chars": 7795,
    "preview": "local Result = require \"mason-core.result\"\nlocal _ = require \"mason-core.functional\"\nlocal a = require \"mason-core.async"
  },
  {
    "path": "lua/mason-core/log.lua",
    "chars": 6039,
    "preview": "local _ = require \"mason-core.functional\"\nlocal path = require \"mason-core.path\"\nlocal settings = require \"mason.setting"
  },
  {
    "path": "lua/mason-core/notify.lua",
    "chars": 160,
    "preview": "local TITLE = \"mason.nvim\"\n\nreturn function(msg, level)\n    level = level or vim.log.levels.INFO\n    vim.notify(msg, lev"
  },
  {
    "path": "lua/mason-core/optional.lua",
    "chars": 2721,
    "preview": "---@class Optional<T>\n---@field private _value unknown\nlocal Optional = {}\nOptional.__index = Optional\n\n---@param value "
  },
  {
    "path": "lua/mason-core/package/AbstractPackage.lua",
    "chars": 7155,
    "preview": "local EventEmitter = require \"mason-core.EventEmitter\"\nlocal InstallLocation = require \"mason-core.installer.InstallLoca"
  },
  {
    "path": "lua/mason-core/package/init.lua",
    "chars": 5818,
    "preview": "local AbstractPackage = require \"mason-core.package.AbstractPackage\"\nlocal InstallLocation = require \"mason-core.install"
  },
  {
    "path": "lua/mason-core/path.lua",
    "chars": 1319,
    "preview": "local M = {}\n\n---@param path_components string[]\n---@return string\nfunction M.concat(path_components)\n    return vim.fs."
  },
  {
    "path": "lua/mason-core/pep440/init.lua",
    "chars": 2025,
    "preview": "local function split_version(version)\n    local parts = {}\n    for part in version:gmatch \"[^.]+\" do\n        table.inser"
  },
  {
    "path": "lua/mason-core/platform.lua",
    "chars": 7182,
    "preview": "local _ = require \"mason-core.functional\"\n\nlocal M = {}\n\nlocal uname = vim.loop.os_uname()\n\n---@alias Platform\n---| '\"da"
  },
  {
    "path": "lua/mason-core/process.lua",
    "chars": 7706,
    "preview": "local _ = require \"mason-core.functional\"\nlocal log = require \"mason-core.log\"\nlocal platform = require \"mason-core.plat"
  },
  {
    "path": "lua/mason-core/providers.lua",
    "chars": 4734,
    "preview": "local Result = require \"mason-core.result\"\nlocal log = require \"mason-core.log\"\nlocal settings = require \"mason.settings"
  },
  {
    "path": "lua/mason-core/purl.lua",
    "chars": 7705,
    "preview": "local Optional = require \"mason-core.optional\"\nlocal Result = require \"mason-core.result\"\nlocal _ = require \"mason-core."
  },
  {
    "path": "lua/mason-core/receipt.lua",
    "chars": 5311,
    "preview": "local Optional = require \"mason-core.optional\"\nlocal Purl = require \"mason-core.purl\"\nlocal _ = require \"mason-core.func"
  },
  {
    "path": "lua/mason-core/result.lua",
    "chars": 4889,
    "preview": "---@class Failure\n---@field error any\nlocal Failure = {}\nFailure.__index = Failure\n\nfunction Failure:new(error)\n    ---@"
  },
  {
    "path": "lua/mason-core/semver.lua",
    "chars": 379,
    "preview": "local Result = require \"mason-core.result\"\nlocal semver = require \"mason-vendor.semver\"\n\nlocal M = {}\n\n---@param version"
  },
  {
    "path": "lua/mason-core/spawn.lua",
    "chars": 5236,
    "preview": "local Result = require \"mason-core.result\"\nlocal _ = require \"mason-core.functional\"\nlocal a = require \"mason-core.async"
  },
  {
    "path": "lua/mason-core/terminator.lua",
    "chars": 3146,
    "preview": "local a = require \"mason-core.async\"\n\n-- Hasta la vista, baby.\n--                      ______\n--                    <((("
  },
  {
    "path": "lua/mason-core/ui/display.lua",
    "chars": 21984,
    "preview": "local EventEmitter = require \"mason-core.EventEmitter\"\nlocal log = require \"mason-core.log\"\nlocal settings = require \"ma"
  },
  {
    "path": "lua/mason-core/ui/init.lua",
    "chars": 5444,
    "preview": "local _ = require \"mason-core.functional\"\nlocal M = {}\n\n---@alias NodeType\n---| '\"NODE\"'\n---| '\"CASCADING_STYLE\"'\n---| '"
  },
  {
    "path": "lua/mason-core/ui/state.lua",
    "chars": 640,
    "preview": "local M = {}\n\n---@generic T : table\n---@param initial_state T\n---@param subscriber fun(state: T)\nfunction M.create_state"
  },
  {
    "path": "lua/mason-registry/api.lua",
    "chars": 4035,
    "preview": "local _ = require \"mason-core.functional\"\nlocal fetch = require \"mason-core.fetch\"\n\nlocal api = {}\n\n-- https://github.co"
  },
  {
    "path": "lua/mason-registry/index/init.lua",
    "chars": 10,
    "preview": "return {}\n"
  },
  {
    "path": "lua/mason-registry/init.lua",
    "chars": 6060,
    "preview": "local EventEmitter = require \"mason-core.EventEmitter\"\nlocal InstallLocation = require \"mason-core.installer.InstallLoca"
  },
  {
    "path": "lua/mason-registry/installer.lua",
    "chars": 3014,
    "preview": "local a = require \"mason-core.async\"\nlocal log = require \"mason-core.log\"\nlocal OneShotChannel = require(\"mason-core.asy"
  },
  {
    "path": "lua/mason-registry/sources/file.lua",
    "chars": 6387,
    "preview": "local Result = require \"mason-core.result\"\nlocal _ = require \"mason-core.functional\"\nlocal a = require \"mason-core.async"
  },
  {
    "path": "lua/mason-registry/sources/github.lua",
    "chars": 6509,
    "preview": "local InstallLocation = require \"mason-core.installer.InstallLocation\"\nlocal Result = require \"mason-core.result\"\nlocal "
  },
  {
    "path": "lua/mason-registry/sources/init.lua",
    "chars": 6840,
    "preview": "local log = require \"mason-core.log\"\n\n---@class RegistrySource\n---@field id string\n---@field get_package fun(self: Regis"
  },
  {
    "path": "lua/mason-registry/sources/lua.lua",
    "chars": 2679,
    "preview": "local Result = require \"mason-core.result\"\nlocal _ = require \"mason-core.functional\"\nlocal util = require \"mason-registr"
  },
  {
    "path": "lua/mason-registry/sources/synthesized.lua",
    "chars": 3242,
    "preview": "local Package = require \"mason-core.package\"\nlocal Result = require \"mason-core.result\"\nlocal _ = require \"mason-core.fu"
  },
  {
    "path": "lua/mason-registry/sources/util.lua",
    "chars": 1361,
    "preview": "local Optional = require \"mason-core.optional\"\nlocal Package = require \"mason-core.package\"\nlocal _ = require \"mason-cor"
  },
  {
    "path": "lua/mason-test/helpers.lua",
    "chars": 1986,
    "preview": "local InstallContext = require \"mason-core.installer.context\"\nlocal InstallHandle = require \"mason-core.installer.Instal"
  },
  {
    "path": "lua/mason-vendor/semver.lua",
    "chars": 7214,
    "preview": "-- stylua: ignore start\n\nlocal semver = {\n  _VERSION     = '1.2.1',\n  _DESCRIPTION = 'semver for Lua',\n  _URL         = "
  },
  {
    "path": "lua/mason-vendor/zzlib/inflate-bit32.lua",
    "chars": 7173,
    "preview": "-- stylua: ignore start\n\n-- zzlib-bit32 - zlib decompression in Lua - version using bit/bit32 libraries\n\n-- Copyright (c"
  },
  {
    "path": "lua/mason-vendor/zzlib/inflate-bwo.lua",
    "chars": 6984,
    "preview": "-- stylua: ignore start\n\n-- zzlib - zlib decompression in Lua - version using Lua 5.3 bitwise operators\n\n-- Copyright (c"
  },
  {
    "path": "lua/mason-vendor/zzlib/init.lua",
    "chars": 5676,
    "preview": "-- stylua: ignore start\n\n-- zzlib - zlib decompression in Lua - Implementation-independent code\n\n-- Copyright (c) 2016-2"
  },
  {
    "path": "selene.toml",
    "chars": 126,
    "preview": "std=\"lua51+vim\"\nexclude = [\"lua/mason-vendor/*\"]\n\n[rules]\nunused_variable = \"allow\"\nshadowing = \"allow\"\nmixed_table = \"a"
  },
  {
    "path": "stylua.toml",
    "chars": 81,
    "preview": "indent_type = \"Spaces\"\ncall_parentheses = \"None\"\n\n[sort_requires]\nenabled = true\n"
  },
  {
    "path": "tests/fixtures/purl-test-suite-data.json",
    "chars": 20120,
    "preview": "[\n  {\n    \"description\": \"valid maven purl\",\n    \"purl\": \"pkg:maven/org.apache.commons/io@1.3.4\",\n    \"canonical_purl\": "
  },
  {
    "path": "tests/fixtures/receipts/1.0.json",
    "chars": 422,
    "preview": "{\n  \"schema_version\": \"1.0\",\n  \"primary_source\": {\n    \"type\": \"npm\",\n    \"package\": \"@angular/language-server\"\n  },\n  \""
  },
  {
    "path": "tests/fixtures/receipts/1.1.json",
    "chars": 564,
    "preview": "{\n  \"schema_version\": \"1.1\",\n  \"metrics\": {\n    \"start_time\": 1694752380220,\n    \"completion_time\": 1694752386830\n  },\n "
  },
  {
    "path": "tests/fixtures/receipts/2.0.json",
    "chars": 955,
    "preview": "{\n  \"links\": {\n    \"bin\": {\n      \"ngserver\": \"node_modules/.bin/ngserver\"\n    },\n    \"share\": {},\n    \"opt\": {}\n  },\n  "
  },
  {
    "path": "tests/helpers/lua/dummy-registry/dummy.lua",
    "chars": 356,
    "preview": "return {\n    name = \"dummy\",\n    description = [[This is a dummy package.]],\n    homepage = \"https://example.com\",\n    l"
  },
  {
    "path": "tests/helpers/lua/dummy-registry/dummy2.lua",
    "chars": 360,
    "preview": "return {\n    name = \"dummy2\",\n    description = [[This is a dummy2 package.]],\n    homepage = \"https://example.com\",\n   "
  },
  {
    "path": "tests/helpers/lua/dummy-registry/index.lua",
    "chars": 139,
    "preview": "return {\n    [\"dummy\"] = \"dummy-registry.dummy\",\n    [\"dummy2\"] = \"dummy-registry.dummy2\",\n    [\"registry\"] = \"dummy-reg"
  },
  {
    "path": "tests/helpers/lua/dummy-registry/registry.lua",
    "chars": 270,
    "preview": "return {\n    name = \"registry\",\n    description = [[This is a dummy package.]],\n    homepage = \"https://example.com\",\n  "
  },
  {
    "path": "tests/helpers/lua/luassertx.lua",
    "chars": 2672,
    "preview": "local a = require \"mason-core.async\"\nlocal assert = require \"luassert\"\nlocal match = require \"luassert.match\"\n\nlocal fun"
  },
  {
    "path": "tests/mason/api/command_spec.lua",
    "chars": 4398,
    "preview": "local log = require \"mason-core.log\"\nlocal match = require \"luassert.match\"\nlocal spy = require \"luassert.spy\"\nlocal stu"
  },
  {
    "path": "tests/mason/setup_spec.lua",
    "chars": 3225,
    "preview": "local InstallLocation = require \"mason-core.installer.InstallLocation\"\nlocal mason = require \"mason\"\nlocal match = requi"
  },
  {
    "path": "tests/mason-core/EventEmitter_spec.lua",
    "chars": 2306,
    "preview": "local log = require \"mason-core.log\"\nlocal match = require \"luassert.match\"\nlocal spy = require \"luassert.spy\"\n\nlocal Ev"
  },
  {
    "path": "tests/mason-core/async/async_spec.lua",
    "chars": 10661,
    "preview": "local _ = require \"mason-core.functional\"\nlocal a = require \"mason-core.async\"\nlocal assert = require \"luassert\"\nlocal c"
  },
  {
    "path": "tests/mason-core/fetch_spec.lua",
    "chars": 5359,
    "preview": "local Result = require \"mason-core.result\"\nlocal fetch = require \"mason-core.fetch\"\nlocal match = require \"luassert.matc"
  },
  {
    "path": "tests/mason-core/fs_spec.lua",
    "chars": 603,
    "preview": "local fs = require \"mason-core.fs\"\nlocal mason = require \"mason\"\n\ndescribe(\"fs\", function()\n    before_each(function()\n "
  },
  {
    "path": "tests/mason-core/functional/data_spec.lua",
    "chars": 621,
    "preview": "local _ = require \"mason-core.functional\"\n\ndescribe(\"functional: data\", function()\n    it(\"creates enums\", function()\n  "
  },
  {
    "path": "tests/mason-core/functional/function_spec.lua",
    "chars": 6038,
    "preview": "local _ = require \"mason-core.functional\"\nlocal match = require \"luassert.match\"\nlocal spy = require \"luassert.spy\"\n\ndes"
  },
  {
    "path": "tests/mason-core/functional/list_spec.lua",
    "chars": 11300,
    "preview": "local Optional = require \"mason-core.optional\"\nlocal _ = require \"mason-core.functional\"\nlocal spy = require \"luassert.s"
  },
  {
    "path": "tests/mason-core/functional/logic_spec.lua",
    "chars": 2162,
    "preview": "local _ = require \"mason-core.functional\"\nlocal spy = require \"luassert.spy\"\n\ndescribe(\"functional: logic\", function()\n "
  },
  {
    "path": "tests/mason-core/functional/number_spec.lua",
    "chars": 1706,
    "preview": "local _ = require \"mason-core.functional\"\n\ndescribe(\"functional: number\", function()\n    it(\"should negate numbers\", fun"
  },
  {
    "path": "tests/mason-core/functional/relation_spec.lua",
    "chars": 2278,
    "preview": "local _ = require \"mason-core.functional\"\n\ndescribe(\"functional: relation\", function()\n    it(\"should check equality\", f"
  },
  {
    "path": "tests/mason-core/functional/string_spec.lua",
    "chars": 3102,
    "preview": "local _ = require \"mason-core.functional\"\n\ndescribe(\"functional: string\", function()\n    it(\"matches string patterns\", f"
  },
  {
    "path": "tests/mason-core/functional/table_spec.lua",
    "chars": 3821,
    "preview": "local _ = require \"mason-core.functional\"\n\ndescribe(\"functional: table\", function()\n    it(\"retrieves property of table\""
  },
  {
    "path": "tests/mason-core/functional/type_spec.lua",
    "chars": 1254,
    "preview": "local _ = require \"mason-core.functional\"\n\ndescribe(\"functional: type\", function()\n    it(\"should check nil value\", func"
  },
  {
    "path": "tests/mason-core/installer/InstallHandle_spec.lua",
    "chars": 4101,
    "preview": "local InstallHandle = require \"mason-core.installer.InstallHandle\"\nlocal mock = require \"luassert.mock\"\nlocal spy = requ"
  },
  {
    "path": "tests/mason-core/installer/InstallRunner_spec.lua",
    "chars": 11740,
    "preview": "local InstallHandle = require \"mason-core.installer.InstallHandle\"\nlocal InstallLocation = require \"mason-core.installer"
  },
  {
    "path": "tests/mason-core/installer/compiler/compiler_spec.lua",
    "chars": 9978,
    "preview": "local Result = require \"mason-core.result\"\nlocal compiler = require \"mason-core.installer.compiler\"\nlocal match = requir"
  },
  {
    "path": "tests/mason-core/installer/compiler/compilers/cargo_spec.lua",
    "chars": 4994,
    "preview": "local Purl = require \"mason-core.purl\"\nlocal Result = require \"mason-core.result\"\nlocal cargo = require \"mason-core.inst"
  },
  {
    "path": "tests/mason-core/installer/compiler/compilers/composer_spec.lua",
    "chars": 1639,
    "preview": "local Purl = require \"mason-core.purl\"\nlocal Result = require \"mason-core.result\"\nlocal composer = require \"mason-core.i"
  },
  {
    "path": "tests/mason-core/installer/compiler/compilers/gem_spec.lua",
    "chars": 1722,
    "preview": "local Purl = require \"mason-core.purl\"\nlocal Result = require \"mason-core.result\"\nlocal gem = require \"mason-core.instal"
  },
  {
    "path": "tests/mason-core/installer/compiler/compilers/generic/build_spec.lua",
    "chars": 4407,
    "preview": "local Purl = require \"mason-core.purl\"\nlocal Result = require \"mason-core.result\"\nlocal generic = require \"mason-core.in"
  },
  {
    "path": "tests/mason-core/installer/compiler/compilers/generic/download_spec.lua",
    "chars": 4981,
    "preview": "local Purl = require \"mason-core.purl\"\nlocal Result = require \"mason-core.result\"\nlocal generic = require \"mason-core.in"
  },
  {
    "path": "tests/mason-core/installer/compiler/compilers/github/build_spec.lua",
    "chars": 3372,
    "preview": "local Purl = require \"mason-core.purl\"\nlocal Result = require \"mason-core.result\"\nlocal github = require \"mason-core.ins"
  },
  {
    "path": "tests/mason-core/installer/compiler/compilers/github/release_spec.lua",
    "chars": 11550,
    "preview": "local Purl = require \"mason-core.purl\"\nlocal Result = require \"mason-core.result\"\nlocal common = require \"mason-core.ins"
  },
  {
    "path": "tests/mason-core/installer/compiler/compilers/golang_spec.lua",
    "chars": 1793,
    "preview": "local Purl = require \"mason-core.purl\"\nlocal Result = require \"mason-core.result\"\nlocal golang = require \"mason-core.ins"
  },
  {
    "path": "tests/mason-core/installer/compiler/compilers/luarocks_spec.lua",
    "chars": 2694,
    "preview": "local Purl = require \"mason-core.purl\"\nlocal Result = require \"mason-core.result\"\nlocal luarocks = require \"mason-core.i"
  },
  {
    "path": "tests/mason-core/installer/compiler/compilers/npm_spec.lua",
    "chars": 1882,
    "preview": "local Purl = require \"mason-core.purl\"\nlocal Result = require \"mason-core.result\"\nlocal npm = require \"mason-core.instal"
  },
  {
    "path": "tests/mason-core/installer/compiler/compilers/nuget_spec.lua",
    "chars": 1584,
    "preview": "local Purl = require \"mason-core.purl\"\nlocal Result = require \"mason-core.result\"\nlocal nuget = require \"mason-core.inst"
  },
  {
    "path": "tests/mason-core/installer/compiler/compilers/opam_spec.lua",
    "chars": 1575,
    "preview": "local Purl = require \"mason-core.purl\"\nlocal Result = require \"mason-core.result\"\nlocal opam = require \"mason-core.insta"
  },
  {
    "path": "tests/mason-core/installer/compiler/compilers/openvsx_spec.lua",
    "chars": 5227,
    "preview": "local Purl = require \"mason-core.purl\"\nlocal Result = require \"mason-core.result\"\nlocal common = require \"mason-core.ins"
  },
  {
    "path": "tests/mason-core/installer/compiler/compilers/pypi_spec.lua",
    "chars": 2994,
    "preview": "local Purl = require \"mason-core.purl\"\nlocal Result = require \"mason-core.result\"\nlocal pypi = require \"mason-core.insta"
  },
  {
    "path": "tests/mason-core/installer/compiler/expr_spec.lua",
    "chars": 8668,
    "preview": "local Result = require \"mason-core.result\"\nlocal _ = require \"mason-core.functional\"\nlocal expr = require \"mason-core.in"
  },
  {
    "path": "tests/mason-core/installer/compiler/link_spec.lua",
    "chars": 8292,
    "preview": "local Purl = require \"mason-core.purl\"\nlocal Result = require \"mason-core.result\"\nlocal fs = require \"mason-core.fs\"\nloc"
  },
  {
    "path": "tests/mason-core/installer/compiler/util_spec.lua",
    "chars": 3029,
    "preview": "local Result = require \"mason-core.result\"\nlocal match = require \"luassert.match\"\nlocal platform = require \"mason-core.p"
  },
  {
    "path": "tests/mason-core/installer/context_spec.lua",
    "chars": 11086,
    "preview": "local a = require \"mason-core.async\"\nlocal match = require \"luassert.match\"\nlocal path = require \"mason-core.path\"\nlocal"
  },
  {
    "path": "tests/mason-core/installer/linker_spec.lua",
    "chars": 7687,
    "preview": "local a = require \"mason-core.async\"\nlocal fs = require \"mason-core.fs\"\nlocal path = require \"mason-core.path\"\nlocal reg"
  },
  {
    "path": "tests/mason-core/installer/managers/cargo_spec.lua",
    "chars": 3673,
    "preview": "local cargo = require \"mason-core.installer.managers.cargo\"\nlocal match = require \"luassert.match\"\nlocal spy = require \""
  },
  {
    "path": "tests/mason-core/installer/managers/common_spec.lua",
    "chars": 5987,
    "preview": "local Result = require \"mason-core.result\"\nlocal _ = require \"mason-core.functional\"\nlocal common = require \"mason-core."
  },
  {
    "path": "tests/mason-core/installer/managers/composer_spec.lua",
    "chars": 1161,
    "preview": "local composer = require \"mason-core.installer.managers.composer\"\nlocal match = require \"luassert.match\"\nlocal spy = req"
  },
  {
    "path": "tests/mason-core/installer/managers/gem_spec.lua",
    "chars": 1988,
    "preview": "local gem = require \"mason-core.installer.managers.gem\"\nlocal match = require \"luassert.match\"\nlocal spy = require \"luas"
  },
  {
    "path": "tests/mason-core/installer/managers/golang_spec.lua",
    "chars": 2012,
    "preview": "local golang = require \"mason-core.installer.managers.golang\"\nlocal match = require \"luassert.match\"\nlocal spy = require"
  },
  {
    "path": "tests/mason-core/installer/managers/luarocks_spec.lua",
    "chars": 2672,
    "preview": "local luarocks = require \"mason-core.installer.managers.luarocks\"\nlocal match = require \"luassert.match\"\nlocal spy = req"
  }
]

// ... and 25 more files (download for full content)

About this extraction

This page contains the full source code of the mason-org/mason.nvim GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 225 files (850.9 KB), approximately 211.9k tokens. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!