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
================================================



[](https://github.com/mason-org/mason.nvim/actions?query=workflow%3ATests+branch%3Amain+event%3Apush)
[](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)
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": "\n\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.