diff --git a/.cmake-format.yaml b/.cmake-format.yaml deleted file mode 100644 index 9ff5d51..0000000 --- a/.cmake-format.yaml +++ /dev/null @@ -1,2 +0,0 @@ ---- -line_width: 120 diff --git a/.cmakelintrc b/.cmakelintrc deleted file mode 100644 index 10473ce..0000000 --- a/.cmakelintrc +++ /dev/null @@ -1 +0,0 @@ -filter=-whitespace/indent,-linelength,-readability/wonkycase diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml index 209d62f..3a2c475 100644 --- a/.github/FUNDING.yml +++ b/.github/FUNDING.yml @@ -1,4 +1,5 @@ --- +patreon: user?u=83975719 custom: - "https://user-images.githubusercontent.com/32936898/199681341-1c5cfa61-4411-4b67-b268-7cd87c5867bb.png" - "https://user-images.githubusercontent.com/32936898/199681363-1094a0be-85ca-49cf-a410-19b3d7965120.png" diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 2698f37..b32b7a9 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -15,42 +15,50 @@ permissions: contents: write env: - CMAKE_GENERATOR: Ninja PYTHONUTF8: "1" - python-version: 3.x + # https://github.com/tree-sitter/py-tree-sitter/pull/161 + python-version: "3.11" cache: pip jobs: - build-wheels-and-test: + test: strategy: fail-fast: false matrix: runs-on: - ubuntu-latest - # Undefined symbols for architecture x86_64: - # "_tree_sitter_bash_external_scanner_create" - # - macos-latest - # error LNK2001: unresolved external symbol - # tree_sitter_bash_external_scanner_create - # - windows-latest - runs-on: ${{ matrix.runs-on }} + - macos-latest + - windows-latest + runs-on: ${{matrix.runs-on}} steps: - - uses: actions/checkout@v3 - - uses: docker/setup-qemu-action@v2.2.0 - if: runner.os == 'Linux' - - uses: pypa/cibuildwheel@v2.14.1 - - uses: actions/upload-artifact@v3 + - uses: actions/checkout@v4 + - uses: actions/setup-python@v5 with: - path: | - wheelhouse/*.whl - + python-version: ${{env.python-version}} + cache: ${{env.cache}} + cache-dependency-path: |- + requirements.txt + requirements/dev.txt + - name: Install dependencies + run: | + pip install -e '.[dev]' + - name: Test + run: | + pytest --cov + - uses: codecov/codecov-action@v4 build: - needs: - - build-wheels-and-test - runs-on: ubuntu-latest + needs: test + strategy: + fail-fast: false + matrix: + runs-on: + - ubuntu-latest + - macos-latest + - windows-latest + runs-on: ${{matrix.runs-on}} steps: - - uses: actions/checkout@v3 - - uses: actions/setup-python@v4 + - uses: actions/checkout@v4 + - uses: actions/setup-python@v5 with: python-version: ${{env.python-version}} cache: ${{env.cache}} @@ -60,28 +68,24 @@ jobs: - name: Install dependencies run: | pip install build - - name: Build sdist + - name: Build run: | - pyproject-build -s - - uses: actions/upload-artifact@v3 - if: ${{ ! startsWith(github.ref, 'refs/tags/') }} + pyproject-build + - uses: pypa/gh-action-pypi-publish@release/v1 + if: runner.os == 'Linux' && startsWith(github.ref, 'refs/tags/') + with: + password: ${{secrets.PYPI_API_TOKEN}} + - uses: actions/upload-artifact@v4 + if: runner.os == 'Linux' && ! startsWith(github.ref, 'refs/tags/') with: path: | dist/* - - uses: actions/download-artifact@v3 - with: - name: artifact - path: dist - - uses: softprops/action-gh-release@v1 - if: startsWith(github.ref, 'refs/tags/') + - uses: softprops/action-gh-release@v2 + if: runner.os == 'Linux' && startsWith(github.ref, 'refs/tags/') with: # body_path: build/CHANGELOG.md files: | dist/* - - uses: pypa/gh-action-pypi-publish@release/v1 - if: startsWith(github.ref, 'refs/tags/') - with: - password: ${{ secrets.PYPI_API_TOKEN }} deploy-aur: needs: build @@ -89,8 +93,9 @@ jobs: if: startsWith(github.ref, 'refs/tags/') steps: - uses: Freed-Wu/update-aur-package@v1.0.11 + if: startsWith(github.ref, 'refs/tags/') with: - package_name: autotools-language-server + package_name: termux-language-server ssh_private_key: ${{secrets.AUR_SSH_PRIVATE_KEY}} deploy-nur: @@ -102,5 +107,5 @@ jobs: run: > curl -X POST -d '{"ref":"main"}' -H "Accept: application/vnd.github.v3+json" - -H "Authorization: Bearer ${{ secrets.GH_TOKEN }}" + -H "Authorization: Bearer ${{secrets.GH_TOKEN}}" https://api.github.com/repos/Freed-Wu/nur-packages/actions/workflows/version.yml/dispatches diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 58e3573..4e06c28 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,9 +1,9 @@ --- -exclude: (^templates/.*|.*\.json$) +exclude: ^templates/|\.json$ repos: - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v4.5.0 + rev: v6.0.0 hooks: - id: check-added-large-files - id: fix-byte-order-marker @@ -23,11 +23,11 @@ repos: - id: check-toml - id: check-json - repo: https://github.com/Lucas-C/pre-commit-hooks - rev: v1.5.4 + rev: v1.5.5 hooks: - id: remove-crlf - repo: https://github.com/codespell-project/codespell - rev: v2.2.6 + rev: v2.4.1 hooks: - id: codespell additional_dependencies: @@ -39,80 +39,60 @@ repos: args: - --msg-filename - repo: https://github.com/editorconfig-checker/editorconfig-checker.python - rev: 2.7.2 + rev: 3.4.1 hooks: - id: editorconfig-checker - repo: https://github.com/jumanjihouse/pre-commit-hooks rev: 3.0.0 hooks: - id: check-mailmap + # https://github.com/koalaman/shellcheck/issues/2909 + - id: shellcheck + exclude_types: + - zsh - repo: https://github.com/rhysd/actionlint - rev: v1.6.26 + rev: v1.7.8 hooks: - id: actionlint - repo: https://github.com/adrienverge/yamllint - rev: v1.32.0 + rev: v1.37.1 hooks: - id: yamllint - repo: https://github.com/executablebooks/mdformat - rev: 0.7.17 + rev: 1.0.0 hooks: - id: mdformat additional_dependencies: - mdformat-pyproject - mdformat-gfm - - mdformat-myst + # - mdformat-myst - mdformat-toc - mdformat-deflist - mdformat-beautysh - - mdformat-black + - mdformat-ruff - mdformat-config + - mdformat-web - repo: https://github.com/DavidAnson/markdownlint-cli2 - rev: v0.10.0 + rev: v0.18.1 hooks: - id: markdownlint-cli2 additional_dependencies: - markdown-it-texmath - - repo: https://github.com/psf/black - rev: 23.9.1 + - repo: https://github.com/scop/pre-commit-shfmt + rev: v3.12.0-2 hooks: - - id: black - - repo: https://github.com/PyCQA/isort - rev: 5.12.0 + - id: shfmt + - repo: https://github.com/astral-sh/ruff-pre-commit + rev: v0.14.3 hooks: - - id: isort - - repo: https://github.com/pycqa/pydocstyle - rev: 6.3.0 - hooks: - - id: pydocstyle - additional_dependencies: - - tomli + - id: ruff-check + - id: ruff-format - repo: https://github.com/kumaraditya303/mirrors-pyright - rev: v1.1.329 + rev: v1.1.407 hooks: - id: pyright - - repo: https://github.com/PyCQA/bandit - rev: 1.7.5 - hooks: - - id: bandit - args: - - -cpyproject.toml - additional_dependencies: - - tomli - - repo: https://github.com/cmake-lint/cmake-lint - rev: 1.4.2 - hooks: - - id: cmakelint - - repo: https://github.com/cheshirekow/cmake-format-precommit - rev: v0.6.13 - hooks: - - id: cmake-format - additional_dependencies: - - pyyaml - - id: cmake-lint - additional_dependencies: - - pyyaml ci: skip: + - shellcheck - pyright diff --git a/.readthedocs.yaml b/.readthedocs.yaml index 1da6547..77d51fb 100644 --- a/.readthedocs.yaml +++ b/.readthedocs.yaml @@ -5,7 +5,8 @@ version: 2 build: os: ubuntu-22.04 tools: - python: "3" + # https://github.com/grantjenks/py-tree-sitter-languages/issues/30 + python: "3.11" formats: - htmlzip diff --git a/.shellcheckrc b/.shellcheckrc new file mode 100644 index 0000000..ef97b52 --- /dev/null +++ b/.shellcheckrc @@ -0,0 +1,2 @@ +shell=bash +disable=SC2034,SC2154 diff --git a/CMakeLists.txt b/CMakeLists.txt deleted file mode 100644 index 21c5bf2..0000000 --- a/CMakeLists.txt +++ /dev/null @@ -1,12 +0,0 @@ -# https://github.com/tree-sitter/tree-sitter-bash/issues/227 -cmake_minimum_required(VERSION 3.10) -include(FetchContent) -FetchContent_Declare(tree-sitter-bash GIT_REPOSITORY "https://github.com/tree-sitter/tree-sitter-bash") -FetchContent_MakeAvailable(tree-sitter-bash) -include_directories(${tree-sitter-bash_SOURCE_DIR}/src) -add_library(parser SHARED ${tree-sitter-bash_SOURCE_DIR}/src/parser.c) -if(NOT DEFINED SKBUILD_PLATLIB_DIR) - set(SKBUILD_PLATLIB_DIR ${CMAKE_SOURCE_DIR}/src) -endif() -set(CMAKE_INSTALL_LIBDIR ${SKBUILD_PLATLIB_DIR}/termux_language_server/data/lib) -install(TARGETS parser RUNTIME) diff --git a/README.md b/README.md index 2721959..a002044 100644 --- a/README.md +++ b/README.md @@ -37,34 +37,75 @@ [![pypi/implementation](https://shields.io/pypi/implementation/termux-language-server)](https://pypi.org/project/termux-language-server/#files) [![pypi/pyversions](https://shields.io/pypi/pyversions/termux-language-server)](https://pypi.org/project/termux-language-server/#files) -Language server for -[termux](https://termux.dev)'s -[`build.sh`](https://github.com/termux/termux-packages/wiki/Creating-new-package) -and -[`*.subpackage.sh`](https://github.com/termux/termux-packages/wiki/Creating-new-package#writing-a-subpackage-script). - -`build.sh` is a subtype of bash. -This language server only provides extra features for `build.sh` which +Language server for some specific bash scripts: + +- Android [Termux](https://termux.dev) + - [`build.sh`](https://github.com/termux/termux-packages/wiki/Creating-new-package) + - [`*.subpackage.sh`](https://github.com/termux/termux-packages/wiki/Creating-new-package#writing-a-subpackage-script) +- [ArchLinux](https://archlinux.org)/Windows [Msys2](https://msys2.org) + - [`PKGBUILD`](https://wiki.archlinux.org/title/PKGBUILD) + - [`*.install`](https://wiki.archlinux.org/title/PKGBUILD#install) + - [`makepkg.conf`](https://man.archlinux.org/man/makepkg.conf.5.en) +- [Gentoo](https://www.gentoo.org/) + - [`*.ebuild`](https://dev.gentoo.org/~zmedico/portage/doc/man/ebuild.5.html) + - `*.eclass` + - [`make.conf`](https://dev.gentoo.org/~zmedico/portage/doc/man/make.conf.5.html) + - [`color.map`](https://dev.gentoo.org/~zmedico/portage/doc/man/color.map.5.html) +- Debian/Ubuntu + - [`devscripts.conf` and `.devscripts`](https://manpages.ubuntu.com/manpages/bionic/man5/devscripts.conf.5.html) +- zsh + - [`*.mdd`](https://github.com/zsh-users/zsh/blob/57248b88830ce56adc243a40c7773fb3825cab34/Etc/zsh-development-guide#L285-L288) + +This language server only provides extra features which [bash-language-server](https://github.com/bash-lsp/bash-language-server) doesn't support: - [x] [Diagnostic](https://microsoft.github.io/language-server-protocol/specifications/specification-current#diagnostic): - - [x] required variables. Such as: `TERMUX_PKG_VERSION` - - [x] variable type. Such as: `TERMUX_PKG_DEPENDS` shouldn't be a function - - [x] [variable order](https://github.com/termux/termux-packages/wiki/Creating-new-package#table-of-available-package-control-fields) - - [x] unsorted comma separated value. Such as - `TERMUX_PKG_RECOMMENDS="python-sentencepiece, python-numpy"` - should be `TERMUX_PKG_RECOMMENDS="python-numpy, python-sentencepiece"` - - [ ] variable value. Such as: `TERMUX_PKG_AUTO_UPDATE` should be - `true` or `false` + - [x] error + - [x] required variables + - [x] variable type: string/array/function + - [x] variable values + - [x] warning + - [x] variable order + - [x] unsorted values + - [x] style check + - [x] `PKGBUILD`: by [namcap](https://wiki.archlinux.org/title/Namcap) - [x] [Document Formatting](https://microsoft.github.io/language-server-protocol/specifications/specification-current#textDocument_formatting): - - [x] sort some variables - - [x] sort comma separated value + - [x] sort variables + - [x] sort values - [x] [Document Link](https://microsoft.github.io/language-server-protocol/specifications/specification-current#textDocument_documentLink): - jump to - + - [x] `build.sh`: + - [x] `PKGBUILD`: + - [x] ArchLinux: + - [x] Windows Msys2: + - [ ] `ebuild`: - [x] [Hover](https://microsoft.github.io/language-server-protocol/specifications/specification-current#textDocument_hover) -- [x] [Completion](https://microsoft.github.io/language-server-protocol/specifications/specification-current#textDocument_completion): +- [x] [Completion](https://microsoft.github.io/language-server-protocol/specifications/specification-current#textDocument_completion) + - [x] builtin variables + - [x] package names + - [ ] `build.sh` + - [x] `PKGBUILD`: by [pyalpm](https://github.com/ornitorrincos/pyalpm) + - [ ] `ebuild` +- [ ] [Code Action](https://microsoft.github.io/language-server-protocol/specifications/specification-current#textDocument_codeAction) + - [ ] `PKGBUILD` + - [ ] generate a template by the name of directory containing `PKGBUILD`, the + templates comes from: + - [ ] customized by user + - [ ] [pip2pkgbuild](https://github.com/wenLiangcan/pip2pkgbuild) + - [ ] [cpan2aur](https://metacpan.org/release/CPANPLUS-Dist-Arch) + - [ ] [gem2arch](https://github.com/anatol/gem2arch) + - [ ] [arch-hs](https://github.com/berberman/arch-hs) + - [ ] update `.SRCINFO` by `makepkg --printsrcinfo > .SRCINFO` + - [ ] update `pkgsums` by [`updpkgsums`](https://gitlab.archlinux.org/pacman/pacman-contrib) + - [ ] update version by a `nvcheck.toml` to tell this + program where to search new version: + +```toml +[package_name] +source = "github" +github = "author_name/repo_name" +use_max_tag = true +``` Other features: @@ -80,21 +121,28 @@ Other features: ### Document Link -![document link](https://github.com/termux/termux-language-server/assets/32936898/9149386d-0e19-4f88-9931-dba8a3d960bc) +![document link](https://github.com/Freed-Wu/pkgbuild-language-server/assets/32936898/d3777f3c-9b75-41f9-b6b3-1c4ec55c7283) ### Hover -![document hover](https://github.com/termux/termux-language-server/assets/32936898/5dfbe6d1-6bff-4ffd-bc8e-ad2c2895af52) +![keyword](https://github.com/Freed-Wu/requirements-language-server/assets/32936898/91bfde00-28f7-4376-8b7a-10a0bd56ba51) + +![package](https://github.com/Freed-Wu/pkgbuild-language-server/assets/32936898/3d9fa906-35ea-4063-a9eb-06282d3e8596) ### Completion -![completion](https://github.com/termux/termux-language-server/assets/32936898/11f2bafc-cb3b-4559-9c3e-6df474e819bd) +![completion](https://github.com/Freed-Wu/pkgbuild-language-server/assets/32936898/c060690c-071b-41a0-bde5-dce338f4e779) + +![arch](https://github.com/termux/termux-language-server/assets/32936898/e10b40c6-515e-4d50-9526-d32ea26b9238) + +![license](https://github.com/termux/termux-language-server/assets/32936898/13109df3-30ba-4371-ad0a-aa7f46c8e80a) + +![depends](https://github.com/termux/termux-language-server/assets/32936898/a70b41ae-cf4b-44cc-bb10-a54cb5488f30) + +## How Does It Work + +See [here](https://github.com/neomutt/lsp-tree-sitter#usage). Read [![readthedocs](https://shields.io/readthedocs/termux-language-server)](https://termux-language-server.readthedocs.io) to know more. - -## Similar Projects - -- [pkgbuild-language-server](https://github.com/Freed-Wu/pkgbuild-language-server): - ArchLinux's `PKGBUILD`. diff --git a/docs/conf.py b/docs/conf.py index 009c886..7d81290 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -2,6 +2,7 @@ https://www.sphinx-doc.org/en/master/usage/configuration.html """ + from termux_language_server import __version__ as version # type: ignore from termux_language_server._metainfo import ( # type: ignore author, diff --git a/docs/resources/configure.md b/docs/resources/configure.md index c3275ef..2d0454c 100644 --- a/docs/resources/configure.md +++ b/docs/resources/configure.md @@ -1,22 +1,32 @@ # Configure -## (Neo)[Vim](https://www.vim.org) +- For windows, change `~/.config` to `~/AppData/Local` +- For macOS, change `~/.config` to `~/Library` + +## [Neovim](https://neovim.io) / [Vim](https://www.vim.org) ### [coc.nvim](https://github.com/neoclide/coc.nvim) +`~/.config/nvim/coc-settings.json`: + ```json { "languageserver": { "termux": { "command": "termux-language-server", - "filetypes": ["sh"] - }, + "filetypes": [ + "sh" + ] + } } } ``` ### [vim-lsp](https://github.com/prabirshrestha/vim-lsp) +Neovim - `~/.config/nvim/init.vim`:\ +Vim - `~/.config/vim/vimrc`: + ```vim if executable('termux-language-server') augroup lsp @@ -30,32 +40,66 @@ if executable('termux-language-server') endif ``` -## [Neovim](https://neovim.io) +### [nvim-lspconfig](https://github.com/neovim/nvim-lspconfig) (upstream configs) + +Example via [`lazy.nvim`](https://github.com/folke/lazy.nvim)\ +For other options see: [nvim-lspconfig#install](https://github.com/neovim/nvim-lspconfig#install)\ +Or the documentation for your plugin manager of choice. + +`~/.config/nvim/init.vim`: ```lua -vim.api.nvim_create_autocmd({ "BufEnter" }, { - pattern = { "build.sh" "*.subpackage.sh" }, - callback = function() - vim.lsp.start({ - name = "termux", - cmd = { "termux-language-server" } - }) - end, +require('lazy').setup({ + -- [...] + { 'neovim/nvim-lspconfig' }, + -- [...] }) + +vim.lsp.enable('termux_language_server') ``` ## [Emacs](https://www.gnu.org/software/emacs) +`~/.config/emacs/init.el`: + ```elisp (make-lsp-client :new-connection (lsp-stdio-connection `(,(executable-find "termux-language-server"))) - :activation-fn (lsp-activate-on "build.sh" "*.subpackage.sh") + :activation-fn (lsp-activate-on "build.sh" "*.subpackage.sh" "PKGBUILD" +"*.install" "makepkg.conf" "*.ebuild" "*.eclass" "color.map" "make.conf") :server-id "termux"))) ``` +## [Helix](https://helix-editor.com/) + +`~/.config/helix/languages.toml`: + +```toml +[[language]] +name = "sh" +language-servers = ["termux-language-server"] + +[language_server.termux-language-server] +command = "termux-language-server" +``` + +## [KaKoune](https://kakoune.org/) + +### [kak-lsp](https://github.com/kak-lsp/kak-lsp) + +`~/.config/kak-lsp/kak-lsp.toml`: + +```toml +[language_server.termux-language-server] +filetypes = ["sh"] +command = "termux-language-server" +``` + ## [Sublime](https://www.sublimetext.com) +`~/.config/sublime-text-3/Packages/Preferences.sublime-settings`: + ```json { "clients": { @@ -69,3 +113,18 @@ vim.api.nvim_create_autocmd({ "BufEnter" }, { } } ``` + +## [Visual Studio Code](https://code.visualstudio.com/) + +[Official support for generic LSP clients is pending](https://github.com/microsoft/vscode/issues/137885). + +### [vscode-glspc](https://gitlab.com/ruilvo/vscode-glspc) + +`~/.config/Code/User/settings.json`: + +```json +{ + "glspc.serverPath": "termux-language-server", + "glspc.languageId": "bash" +} +``` diff --git a/docs/resources/install.md b/docs/resources/install.md index 6f8fd0d..284bc1b 100644 --- a/docs/resources/install.md +++ b/docs/resources/install.md @@ -25,25 +25,13 @@ yay -S termux-language-server ( python3.withPackages ( p: with p; [ - nur.repos.termux.termux-language-server + nur.repos.Freed-Wu.termux-language-server ] ) ) } ``` -## [Nix](https://nixos.org) - -```sh -nix shell github:termux/termux-language-server -``` - -Run without installation: - -```sh -nix run github:termux/termux-language-server -- --help -``` - ## [PYPI](https://pypi.org/project/termux-language-server) ```sh diff --git a/pyproject.toml b/pyproject.toml index 281c499..6a0f024 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,11 +1,11 @@ [build-system] -requires = ["scikit-build-core"] -build-backend = "scikit_build_core.build" +requires = ["setuptools_scm[toml] >= 6.2", "setuptools-generate >= 0.0.6"] +build-backend = "setuptools.build_meta" # https://setuptools.pypa.io/en/latest/userguide/pyproject_config.html [project] name = "termux-language-server" -description = "termux language server" +description = "Language server for build.sh, PKGBUILD, ebuild" readme = "README.md" # type_a | type_b requires-python = ">= 3.10" @@ -27,17 +27,10 @@ classifiers = [ "Programming Language :: Python :: Implementation :: CPython", "Programming Language :: Python :: Implementation :: PyPy", ] -# dynamic = ["version", "dependencies", "optional-dependencies"] -# https://github.com/pypa/twine/issues/753 -dynamic = ["version"] -dependencies = ["colorama", "jinja2", "platformdirs", "pygls", "tree-sitter"] - -[project.optional-dependencies] -dev = ["pytest-cov"] -web = ["beautifulsoup4"] +dynamic = ["version", "dependencies", "optional-dependencies"] [[project.authors]] -name = "Wu Zhenyu" +name = "Wu, Zhenyu" email = "wuzhenyu@ustc.edu" [project.license] @@ -51,50 +44,85 @@ Source = "https://github.com/termux/termux-language-server" [project.scripts] termux-language-server = "termux_language_server.__main__:main" +pkgbuild-language-server = "termux_language_server.__main__:main" +portage-language-server = "termux_language_server.__main__:main" + +[tool.setuptools.data-files] +"share/man/man1" = [ + "sdist/termux-language-server.1", + "sdist/pkgbuild-language-server.1", + "sdist/portage-language-server.1", +] +"share/bash-completion/completions" = [ + "sdist/termux-language-server", + "sdist/pkgbuild-language-server", + "sdist/portage-language-server", +] +"share/zsh/site-functions" = [ + "sdist/_termux-language-server", + "sdist/_pkgbuild-language-server", + "sdist/_portage-language-server", +] [tool.scikit-build] experimental = true -[tool.scikit-build.metadata.version] -provider = "scikit_build_core.metadata.setuptools_scm" - -[tool.scikit-build.sdist] -include = ["src/termux_language_server/_version.py"] - -[[tool.scikit-build.generate]] -path = "termux_language_server/_metainfo.py" -template-path = "templates/metainfo.py" - [tool.setuptools.dynamic.dependencies] file = "requirements.txt" # begin: scripts/update-pyproject.toml.pl +[tool.setuptools.dynamic.optional-dependencies.colorize] +file = "requirements/colorize.txt" + [tool.setuptools.dynamic.optional-dependencies.dev] file = "requirements/dev.txt" -[tool.setuptools.dynamic.optional-dependencies.web] -file = "requirements/web.txt" +[tool.setuptools.dynamic.optional-dependencies.misc] +file = "requirements/misc.txt" + +[tool.setuptools.dynamic.optional-dependencies.pkgbuild] +file = "requirements/pkgbuild.txt" # end: scripts/update-pyproject.toml.pl [tool.setuptools_scm] write_to = "src/termux_language_server/_version.py" +[tool.setuptools-generate] +write-to = "src/termux_language_server/_metainfo.py" + +[tool.setuptools-generate.metainfo-template] +file = "templates/metainfo.py.j2" + [tool.mdformat] number = true -[tool.black] -line-length = 79 +[tool.doq] +template_path = "templates" -[tool.isort] -line_length = 79 -profile = "black" +[tool.ruff] +line-length = 79 -# https://github.com/PyCQA/pydocstyle/issues/418 -[tool.pydocstyle] -add_ignore = "D205, D400" +[tool.ruff.lint] +select = [ + # pycodestyle + "E", + # pyflakes + "F", + # pyupgrade + "UP", + # flake8-bugbear + "B", + # flake8-simplify + "SIM", + # isort + "I", +] +ignore = ["D205", "D400"] +preview = true -[tool.doq] -template_path = "templates" +[tool.ruff.format] +docstring-code-format = true +preview = true [tool.coverage.report] exclude_lines = [ @@ -103,9 +131,6 @@ exclude_lines = [ "\\s*import tomli as tomllib", ] -[tool.bandit.assert_used] -skips = ["*_test.py", "*/test_*.py"] - [tool.cibuildwheel] archs = ["all"] skip = "*37-* *38-* *39-*" diff --git a/requirements.txt b/requirements.txt index 75f17e1..93dcfd8 100755 --- a/requirements.txt +++ b/requirements.txt @@ -1,7 +1,12 @@ #!/usr/bin/env -S pip install -r -colorama -jinja2 +# https://python-jsonschema.readthedocs.io/en/stable/validate/#validating-formats +# validate hostname +fqdn +lsp-tree-sitter >= 0.1.0 +# ~/.config/pacman/template.md.j2 platformdirs -pygls -tree-sitter +pygls >= 2.0.0 +# validate uri +rfc3987 +tree-sitter-bash diff --git a/requirements/colorize.txt b/requirements/colorize.txt new file mode 100755 index 0000000..b0dfd7e --- /dev/null +++ b/requirements/colorize.txt @@ -0,0 +1,3 @@ +#!/usr/bin/env -S pip install -r + +lsp-tree-sitter[colorize] diff --git a/requirements/ebuild.txt b/requirements/ebuild.txt new file mode 100755 index 0000000..b227c03 --- /dev/null +++ b/requirements/ebuild.txt @@ -0,0 +1,3 @@ +#!/usr/bin/env -S pip install -r + +portage diff --git a/requirements/misc.txt b/requirements/misc.txt new file mode 100755 index 0000000..0402fb8 --- /dev/null +++ b/requirements/misc.txt @@ -0,0 +1,4 @@ +#!/usr/bin/env -S pip install -r + +license-expression +lsp-tree-sitter[misc] diff --git a/requirements/pkgbuild.txt b/requirements/pkgbuild.txt new file mode 100755 index 0000000..86b6ddf --- /dev/null +++ b/requirements/pkgbuild.txt @@ -0,0 +1,4 @@ +#!/usr/bin/env -S pip install -r + +# git+git://gitlab.archlinux.org/pacman/namcap +pyalpm diff --git a/requirements/web.txt b/requirements/web.txt deleted file mode 100755 index f115f73..0000000 --- a/requirements/web.txt +++ /dev/null @@ -1,4 +0,0 @@ -#!/usr/bin/env -S pip install -r -# See . - -beautifulsoup4 diff --git a/src/termux_language_server/__init__.py b/src/termux_language_server/__init__.py index 9b415f3..1f3e0fe 100644 --- a/src/termux_language_server/__init__.py +++ b/src/termux_language_server/__init__.py @@ -1,6 +1,9 @@ r"""Provide ``__version__`` for `importlib.metadata.version() `_. """ + +from typing import Literal + try: from ._version import __version__, __version_tuple__ # type: ignore except ImportError: # for setuptools-generate @@ -8,3 +11,18 @@ __version_tuple__ = (0, 0, 0, __version__, "") __all__ = ["__version__", "__version_tuple__"] + +FILETYPE = Literal[ + "build.sh", + "subpackage.sh", + "PKGBUILD", + "makepkg.conf", + "install", + "ebuild", + "make.conf", + "color.map", + "mdd", + "devscripts.conf", +] +PACKAGE_NAME = r"[a-z][a-z0-9-]*" +CSV = f"{PACKAGE_NAME}(, {PACKAGE_NAME})*" diff --git a/src/termux_language_server/__main__.py b/src/termux_language_server/__main__.py index e8d0c46..21957b8 100644 --- a/src/termux_language_server/__main__.py +++ b/src/termux_language_server/__main__.py @@ -1,17 +1,22 @@ r"""This module can be called by `python -m `_. """ + from argparse import ArgumentParser, RawDescriptionHelpFormatter -from contextlib import suppress from datetime import datetime +from . import FILETYPE, __version__ from . import __name__ as NAME -from . import __version__ + +try: + import shtab +except ImportError: + from . import _shtab as shtab NAME = NAME.replace("_", "-") VERSION = rf"""{NAME} {__version__} Copyright (C) {datetime.now().year} -Written by Wu Zhenyu +Written by Wu, Zhenyu """ EPILOG = """ Report bugs to . @@ -24,44 +29,92 @@ def get_parser(): epilog=EPILOG, formatter_class=RawDescriptionHelpFormatter, ) - with suppress(ImportError): - import shtab - - shtab.add_argument_to(parser) + shtab.add_argument_to(parser) parser.add_argument("--version", version=VERSION, action="version") parser.add_argument( - "--check", - nargs="*", - default=[], - help="check file's errors and warnings", + "--generate-schema", + choices=FILETYPE.__args__, # type: ignore + help="generate schema in an output format", ) parser.add_argument( - "--format", - nargs="*", - default=[], - help="format files", + "--output-format", + choices=["json", "yaml", "toml"], + default="json", + help="output format: %(default)s", + ) + parser.add_argument( + "--indent", + type=int, + default=2, + help="generated json, yaml's indent, ignored by toml: %(default)s", ) parser.add_argument( "--color", choices=["auto", "always", "never"], default="auto", - help="when to display color", + help="when to display color, default: %(default)s", ) + parser.add_argument( + "--check", + nargs="*", + default={}, + help="check file's errors and warnings", + ).complete = shtab.FILE # type: ignore + parser.add_argument( + "--format", + nargs="*", + default={}, + help="format files", + ).complete = shtab.FILE # type: ignore + parser.add_argument( + "--convert", + nargs="*", + default={}, + help="convert files to output format", + ).complete = shtab.FILE # type: ignore return parser def main(): r"""Parse arguments and provide shell completions.""" - parser = get_parser() - args = parser.parse_args() + args = get_parser().parse_args() + + if args.generate_schema or args.format or args.check or args.convert: + from lsp_tree_sitter.diagnose import check + from lsp_tree_sitter.format import format + from lsp_tree_sitter.utils import pprint + + from .finders import DIAGNOSTICS_FINDER_CLASSES, FORMAT_FINDER_CLASSES + from .schema import BashTrie + from .utils import get_filetype, parser - from .parser import parse - from .utils import check, format + if args.generate_schema: + from .misc import get_schema - format(args.format, parse) - result = check(args.check, parse, args.color) - if args.format or args.check: - exit(result) + kwargs = ( + {"indent": args.indent} if args.output_format != "toml" else {} + ) + pprint( + get_schema(args.generate_schema), + filetype=args.output_format, + **kwargs, + ) + for file in args.convert: + pprint( + BashTrie.from_file(file, parser.parse).to_json(), + filetype=args.output_format, + indent=args.indent, + ) + format(args.format, parser.parse, FORMAT_FINDER_CLASSES, get_filetype) + exit( + check( + args.check, + parser.parse, + DIAGNOSTICS_FINDER_CLASSES, + get_filetype, + args.color, + ) + ) from .server import TermuxLanguageServer diff --git a/src/termux_language_server/_shtab.py b/src/termux_language_server/_shtab.py new file mode 100644 index 0000000..8b15ce7 --- /dev/null +++ b/src/termux_language_server/_shtab.py @@ -0,0 +1,16 @@ +r"""Fake shtab +============== +""" + +from argparse import ArgumentParser +from typing import Any + +FILE = None +DIRECTORY = DIR = None + + +def add_argument_to(parser: ArgumentParser, *args: Any, **kwargs: Any): + from argparse import Action + + Action.complete = None # type: ignore + return parser diff --git a/src/termux_language_server/assets/jinja2/template.md.j2 b/src/termux_language_server/assets/jinja2/template.md.j2 new file mode 100644 index 0000000..2eb52a8 --- /dev/null +++ b/src/termux_language_server/assets/jinja2/template.md.j2 @@ -0,0 +1,33 @@ +{{ pkg.desc }} + +- version: **{{ pkg.version }}** +- arch: **{{ pkg.arch }}** +- url: <{{ pkg.url }}> +- licenses: +{%-for license in pkg.licenses %} + {{ loop.index }}. *{{ license }}* +{%-endfor %} +- groups: +{%-for group in pkg.groups %} + {{ loop.index }}. *{{ group }}* +{%-endfor %} +- depends: +{%-for depend in pkg.depends %} + {{ loop.index }}. {{ depend }} +{%-endfor %} +- optdepends: +{%-for optdepend in pkg.optdepends %} + {{ loop.index }}. {{ optdepend }} +{%-endfor %} +- provides: +{%-for provide in pkg.provides %} + {{ loop.index }}. {{ provide }} +{%-endfor %} +- conflicts: +{%-for conflict in pkg.conflicts %} + {{ loop.index }}. {{ conflict }} +{%-endfor %} +- replaces: +{%-for replace in pkg.replaces %} + {{ loop.index }}. {{ replace }} +{%-endfor %} diff --git a/src/termux_language_server/assets/json/PKGBUILD.json b/src/termux_language_server/assets/json/PKGBUILD.json new file mode 100644 index 0000000..eba9174 --- /dev/null +++ b/src/termux_language_server/assets/json/PKGBUILD.json @@ -0,0 +1,948 @@ +{ + "$id": "https://github.com/termux/termux-language-server/blob/main/src/termux_language_server/assets/json/PKGBUILD.json", + "$schema": "http://json-schema.org/draft-07/schema#", + "$comment": "Don't edit this file directly! It is generated by `termux-language-server --generate-schema=PKGBUILD`.", + "type": "object", + "patternProperties": { + "^package($|_.*)": { + "description": "The package() function is used to install files into the directory that will become the root directory of the built package and is run after all the optional functions listed below. The packaging stage is run using fakeroot to ensure correct file permissions in the resulting package. All other functions will be run as the user calling makepkg.", + "const": 0 + }, + "^prepare($|_.*)": { + "description": "An optional prepare() function can be specified in which operations to prepare the sources for building, such as patching, are performed. This function is run after the source extraction and before the build() function. The prepare() function is skipped when source extraction is skipped.", + "const": 0 + }, + "^build($|_.*)": { + "description": "The optional build() function is used to compile and/or adjust the source files in preparation to be installed by the package() function.", + "const": 0 + }, + "^check($|_.*)": { + "description": "An optional check() function can be specified in which a package's test-suite may be run. This function is run between the build() and package() functions. Be sure any exotic commands used are covered by the checkdepends array.", + "const": 0 + } + }, + "properties": { + "pkgname": { + "description": "Either the name of the package or an array of names for split packages. Valid characters for members of this array are alphanumerics, and any of the following characters: \"@ . \\_ + -\". Additionally, names are not allowed to start with hyphens or dots.", + "oneOf": [ + { + "type": "array", + "items": { + "type": "string" + }, + "uniqueItems": true + }, + { + "type": "string" + } + ] + }, + "pkgver": { + "description": "The version of the software as released from the author (e.g., *2.7.1*). The variable is not allowed to contain colons, forward slashes, hyphens or whitespace.\nThe pkgver variable can be automatically updated by providing a pkgver() function in the PKGBUILD that outputs the new package version. This is run after downloading and extracting the sources and running the prepare() function (if present), so it can use those files in determining the new pkgver. This is most useful when used with sources from version control systems (see below).", + "oneOf": [ + { + "type": "string" + }, + { + "const": 0 + } + ] + }, + "pkgrel": { + "description": "This is the release number specific to the distribution. This allows package maintainers to make updates to the package's configure flags, for example. This is typically set to *1* for each new upstream software release and incremented for intermediate PKGBUILD updates. The variable is a positive integer, with an optional subrelease level specified by adding another positive integer separated by a period (i.e. in the form x.y).", + "type": "string" + }, + "epoch": { + "description": "Used to force the package to be seen as newer than any previous versions with a lower epoch, even if the version number would normally not trigger such an upgrade. This value is required to be a positive integer; the default value if left unspecified is *0*. This is useful when the version numbering scheme of a package changes (or is alphanumeric), breaking normal version comparison logic. See **pacman**(8) for more information on version comparisons.", + "type": "string" + }, + "pkgdesc": { + "description": "This should be a brief description of the package and its functionality. Try to keep the description to one line of text and to not use the package's name.", + "type": "string" + }, + "url": { + "description": "The URL to the VCS repository. This must include the VCS in the URL protocol for makepkg to recognize this as a VCS source. If the protocol does not include the VCS name, it can be added by prefixing the URL with vcs+. For example, using a Git repository over HTTPS would have a source URL in the form: git+https://\\....", + "type": "string", + "format": "uri" + }, + "license": { + "description": "This field specifies the license(s) that apply to the package. Commonly used licenses can be found in */usr/share/licenses/common*. If you see the package's license there, simply reference it in the license field (e.g., license=(GPL)). If the package provides a license not available in */usr/share/licenses/common*, then you should include it in the package itself and set license=(custom) or license=(custom:LicenseName). The license should be placed in *\\$pkgdir/usr/share/licenses/\\$pkgname/* when building the package. If multiple licenses are applicable, list all of them: license=(GPL FDL).", + "type": "array", + "items": { + "oneOf": [ + { + "type": "string", + "enum": [ + "389-exception", + "Abstyles", + "CDL-1.0", + "DOC", + "GNAT-exception", + "AdaCore-doc", + "APL-1.0", + "Adobe-Glyph", + "Adobe-2006", + "ADSL", + "AFL-1.1", + "AFL-1.2", + "AFL-2.0", + "AFL-2.1", + "AFL-3.0", + "Afmparse", + "Aladdin", + "AGPL-1.0-only", + "AGPL-1.0-or-later", + "AGPL-3.0-only", + "AGPL-3.0-or-later", + "Giftware", + "LicenseRef-.amazon.com.-AmznSL-1.0", + "AMDPLPA", + "AML", + "AMPAS", + "ANTLR-PD", + "ANTLR-PD-fallback", + "Apache-1.0", + "Apache-1.1", + "Apache-2.0", + "APAFML", + "App-s2p", + "Swift-exception", + "APSL-1.0", + "APSL-1.1", + "APSL-1.2", + "APSL-2.0", + "Arphic-1999", + "Artistic-1.0", + "Artistic-1.0-cl8", + "Artistic-2.0", + "ClArtistic", + "Artistic-1.0-Perl", + "AAL", + "Autoconf-exception-2.0", + "Autoconf-exception-3.0", + "Autoconf-exception-generic", + "Baekmuk", + "Bahyph", + "Barr", + "Beerware", + "Bison-exception-2.2", + "Bitstream-Vera", + "BitTorrent-1.0", + "BitTorrent-1.1", + "blessing", + "BlueOak-1.0.0", + "BSL-1.0", + "Bootloader-exception", + "Borceux", + "Brian-Gladman-3-Clause", + "BSD-1-Clause", + "BSD-2-Clause-Views", + "BSD-3-Clause-No-Military-License", + "BSD-3-Clause-No-Nuclear-Warranty", + "BSD-3-Clause-Open-MPI", + "BSD-4-Clause-Shortened", + "BSD-3-Clause-Attribution", + "BSD-Advertising-Acknowledgement", + "BSD-3-Clause", + "BSD-4-Clause", + "BSD-4-Clause-UC", + "BSD-4.3RENO", + "BSD-2-Clause-Patent", + "BSD-Protection", + "BSD-2-Clause", + "BSD-Source-Code", + "0BSD", + "BUSL-1.1", + "BSD-4.3TAHOE", + "bzip2-1.0.6", + "C-UDA-1.0", + "CATOSL-1.1", + "CAL-1.0", + "CAL-1.0-Combined-Work-Exception", + "Caldera", + "OGL-Canada-2.0", + "CMU-Mach", + "CC-BY-1.0", + "CC-BY-2.0", + "CC-BY-2.5", + "CC-BY-2.5-AU", + "CC-BY-3.0", + "CC-BY-3.0-AT", + "CC-BY-3.0-DE", + "CC-BY-3.0-IGO", + "CC-BY-3.0-NL", + "CC-BY-3.0-US", + "CC-BY-4.0", + "CC-BY-NC-1.0", + "CC-BY-NC-2.0", + "CC-BY-NC-2.5", + "CC-BY-NC-3.0", + "CC-BY-NC-3.0-DE", + "CC-BY-NC-4.0", + "CC-BY-NC-ND-1.0", + "CC-BY-NC-ND-2.0", + "CC-BY-NC-ND-2.5", + "CC-BY-NC-ND-3.0", + "CC-BY-NC-ND-3.0-DE", + "CC-BY-NC-ND-3.0-IGO", + "CC-BY-NC-ND-4.0", + "CC-BY-NC-SA-1.0", + "CC-BY-NC-SA-2.0", + "CC-BY-NC-SA-2.0-DE", + "CC-BY-NC-SA-2.0-FR", + "CC-BY-NC-SA-2.0-UK", + "CC-BY-NC-SA-2.5", + "CC-BY-NC-SA-3.0", + "CC-BY-NC-SA-3.0-DE", + "CC-BY-NC-SA-3.0-IGO", + "CC-BY-NC-SA-4.0", + "CC-BY-ND-1.0", + "CC-BY-ND-2.0", + "CC-BY-ND-2.5", + "CC-BY-ND-3.0", + "CC-BY-ND-3.0-DE", + "CC-BY-ND-4.0", + "CC-BY-SA-1.0", + "CC-BY-SA-2.0", + "CC-BY-SA-2.0-UK", + "CC-BY-SA-2.1-JP", + "CC-BY-SA-2.5", + "CC-BY-SA-3.0", + "CC-BY-SA-3.0-AT", + "CC-BY-SA-3.0-DE", + "CC-BY-SA-4.0", + "CC-PDDC", + "CC0-1.0", + "CDDL-1.0", + "CDDL-1.1", + "CDLA-Permissive-1.0", + "CDLA-Permissive-2.0", + "CDLA-Sharing-1.0", + "CECILL-1.0", + "CECILL-1.1", + "CECILL-2.0", + "CECILL-2.1", + "CECILL-B", + "CECILL-C", + "CERN-OHL-1.1", + "CERN-OHL-1.2", + "CERN-OHL-P-2.0", + "CERN-OHL-S-2.0", + "CERN-OHL-W-2.0", + "CFITSIO", + "checkmk", + "Classpath-exception-2.0", + "BSD-3-Clause-Clear", + "Clips", + "CLISP-exception-2.0", + "BSD-Attribution-HPND-disclaimer", + "MIT-CMU", + "CNRI-Jython", + "CNRI-Python", + "CNRI-Python-GPL-Compatible", + "COIL-1.0", + "Condor-1.1", + "copyleft-next-0.3.0", + "copyleft-next-0.3.1", + "Cornell-Lossless-JPEG", + "CPAL-1.0", + "CPL-1.0", + "CPOL-1.02", + "Crossword", + "CrystalStacker", + "Community-Spec-1.0", + "CUA-OPL-1.0", + "Cube", + "curl", + "D-FSL-1.0", + "diffmark", + "DigiRule-FOSS-exception", + "DL-DE-BY-2.0", + "Plexus", + "Dotseqn", + "DRL-1.0", + "DSDP", + "dvipdfm", + "ECL-1.0", + "ECL-2.0", + "eCos-2.0", + "eCos-exception-2.0", + "RHeCos-1.1", + "EFL-1.0", + "EFL-2.0", + "eGenix", + "Elastic-2.0", + "MIT-advertising", + "MIT-enna", + "Entessa", + "EPICS", + "EPL-1.0", + "EPL-2.0", + "ErlPL-1.1", + "etalab-2.0", + "EUDatagrid", + "EUPL-1.0", + "EUPL-1.1", + "EUPL-1.2", + "Eurosym", + "Fair", + "OML", + "Fawkes-Runtime-exception", + "FLTK-exception", + "Font-exception-2.0", + "Frameworx-1.0", + "FDK-AAC", + "FreeBSD-DOC", + "FreeImage", + "freertos-exception-2.0", + "FTL", + "FSFAP", + "FSFUL", + "FSFULLR", + "FSFULLRWD", + "GCC-exception-3.1", + "GCC-exception-2.0", + "GFDL-1.1-only", + "GFDL-1.1-invariants-only", + "GFDL-1.1-invariants-or-later", + "GFDL-1.1-no-invariants-only", + "GFDL-1.1-no-invariants-or-later", + "GFDL-1.1-or-later", + "GFDL-1.2-only", + "GFDL-1.2-invariants-only", + "GFDL-1.2-invariants-or-later", + "GFDL-1.2-no-invariants-only", + "GFDL-1.2-no-invariants-or-later", + "GFDL-1.2-or-later", + "GFDL-1.3-only", + "GFDL-1.3-invariants-only", + "GFDL-1.3-invariants-or-later", + "GFDL-1.3-no-invariants-only", + "GFDL-1.3-no-invariants-or-later", + "GFDL-1.3-or-later", + "GL2PS", + "Glide", + "Glulxe", + "GLWTPL", + "gnu-javamail-exception", + "gnuplot", + "GPL-1.0-only", + "GPL-1.0-or-later", + "GPL-2.0-only", + "GPL-2.0-with-autoconf-exception", + "GPL-2.0-with-classpath-exception", + "GPL-2.0-with-font-exception", + "GPL-2.0-with-GCC-exception", + "GPL-2.0-or-later", + "GPL-3.0-only", + "GPL-3.0-with-autoconf-exception", + "GPL-3.0-with-GCC-exception", + "GPL-3.0-linking-exception", + "GPL-3.0-linking-source-exception", + "GPL-3.0-or-later", + "GPL-CC-1.0", + "Graphics-Gems", + "gSOAP-1.3b", + "GStreamer-exception-2005", + "GStreamer-exception-2008", + "HaskellReport", + "Spencer-99", + "Hippocratic-2.1", + "HPND", + "HPND-export-US", + "HPND-sell-variant-MIT-disclaimer", + "Spencer-94", + "i2p-gpl-java-exception", + "IBM-pibs", + "IPL-1.0", + "IEC-Code-Components-EULA", + "IJG", + "IJG-short", + "ImageMagick", + "Imlib2", + "xpp", + "Info-ZIP", + "QPL-1.0-INRIA-2004-exception", + "Intel-ACPI", + "Intel", + "Interbase-1.0", + "IPA", + "ISC", + "Jam", + "JasPer-2.0", + "JPL-image", + "JPNIC", + "JSON", + "Kazlib", + "KiCad-libraries-exception", + "Knuth-CTAN", + "LAL-1.2", + "LAL-1.3", + "Latex2e", + "BSD-3-Clause-LBNL", + "Leptonica", + "LGPL-2.0-only", + "LGPL-2.0-or-later", + "LGPL-2.1-only", + "LGPL-2.1-or-later", + "LGPL-3.0-only", + "LGPL-3.0-linking-exception", + "LGPL-3.0-or-later", + "LGPLLR", + "GD", + "xlock", + "Libpng", + "libpng-2.0", + "Libtool-exception", + "libutil-David-Nugent", + "LiLiQ-P-1.1", + "LiLiQ-R-1.1", + "LiLiQ-Rplus-1.1", + "Linux-OpenIB", + "Linux-syscall-note", + "LLVM-exception", + "LOOP", + "LPPL-1.0", + "LPPL-1.1", + "LPPL-1.2", + "LPPL-1.3a", + "LPPL-1.3c", + "LPL-1.0", + "LPL-1.02", + "LZMA-exception", + "LZMA-SDK-9.11-to-9.20", + "LZMA-SDK-9.22", + "mplus", + "MakeIndex", + "HPND-Markus-Kuhn", + "Martin-Birgmeier", + "mif-exception", + "Minpack", + "MirOS", + "MIT", + "MIT-0", + "MIT-feh", + "MIT-Wu", + "Xerox", + "MIT-Modern-Variant", + "MITNFA", + "NTP", + "SSPL-1.0", + "Motosoto", + "mpi-permissive", + "mpich2", + "MPL-1.0", + "MPL-1.1", + "MPL-2.0", + "MPL-2.0-no-copyleft-exception", + "MS-LPL", + "MS-PL", + "MS-RL", + "MTLL", + "MulanPSL-1.0", + "MulanPSL-2.0", + "Multics", + "Mup", + "NAIST-2003", + "NASA-1.3", + "Naumen", + "NBPL-1.0", + "NCGL-UK-2.0", + "Net-SNMP", + "NetCDF", + "Newsletr", + "NGPL", + "NICTA-1.0", + "NIST-PD", + "NIST-PD-fallback", + "NLOD-1.0", + "NLOD-2.0", + "NLPL", + "Nokia", + "NOSL", + "NPOSL-3.0", + "Noweb", + "NPL-1.0", + "NPL-1.1", + "NRL", + "NTP-0", + "O-UDA-1.0", + "OCaml-LGPL-linking-exception", + "OCCT-exception-1.0", + "OCCT-PL", + "OCLC-2.0", + "ODbL-1.0", + "ODC-By-1.0", + "OFFIS", + "OFL-1.0", + "OFL-1.0-no-RFN", + "OFL-1.0-RFN", + "OFL-1.1", + "OFL-1.1-no-RFN", + "OFL-1.1-RFN", + "OGC-1.0", + "OGDL-Taiwan-1.0", + "OGL-UK-1.0", + "OGL-UK-2.0", + "OGL-UK-3.0", + "OPL-1.0", + "OGTSL", + "OpenJDK-assembly-exception-1.0", + "OLDAP-1.1", + "OLDAP-1.2", + "OLDAP-1.3", + "OLDAP-1.4", + "OLDAP-2.0", + "OLDAP-2.0.1", + "OLDAP-2.1", + "OLDAP-2.2", + "OLDAP-2.2.1", + "OLDAP-2.2.2", + "OLDAP-2.3", + "OLDAP-2.4", + "OLDAP-2.5", + "OLDAP-2.6", + "OLDAP-2.7", + "OLDAP-2.8", + "OpenPBS-2.3", + "OPUBL-1.0", + "SSH-OpenSSH", + "x11vnc-openssl-exception", + "OpenSSL", + "openvpn-openssl-exception", + "BSD-3-Clause-No-Nuclear-License-2014", + "OSET-PL-2.1", + "HP-1986", + "OSL-1.0", + "OSL-1.1", + "OSL-2.0", + "OSL-2.1", + "OSL-3.0", + "Parity-6.0.0", + "Parity-7.0.0", + "PDDL-1.0", + "PHP-3.0", + "PHP-3.01", + "PolyForm-Noncommercial-1.0.0", + "PolyForm-Small-Business-1.0.0", + "PostgreSQL", + "PS-or-PDF-font-exception-20170817", + "PSF-2.0", + "psfrag", + "psutils", + "Python-2.0", + "Python-2.0.1", + "Qhull", + "QPL-1.0", + "QPL-1.0-INRIA-2004", + "Qt-GPL-exception-1.0", + "Qt-LGPL-exception-1.1", + "Qwt-exception-1.0", + "Rdisc", + "Spencer-86", + "BSD-3-Clause-Modification", + "RSCPL", + "RPL-1.1", + "RPL-1.5", + "RPSL-1.0", + "RSA-MD", + "Ruby", + "SAX-PD", + "Saxpath", + "SCEA", + "SchemeReport", + "libselinux-1.0", + "Sendmail", + "Sendmail-8.23", + "iMatix", + "SGI-B-1.1", + "SGI-B-2.0", + "SGI-B-1.0", + "SHL-0.5", + "SHL-0.51", + "SHL-2.0", + "SHL-2.1", + "SimPL-2.0", + "Sleepycat", + "SMPPL", + "SNIA", + "snprintf", + "SPL-1.0", + "SMLNJ", + "SugarCRM-1.1.3", + "BSD-3-Clause-No-Nuclear-License", + "SISSL", + "SISSL-1.2", + "SunPro", + "SWI-exception", + "SWL", + "Watcom-1.0", + "Symlinks", + "TAPR-OHL-1.0", + "SSH-short", + "TCL", + "TCP-wrappers", + "TPL-1.0", + "HTMLTIDY", + "TMate", + "TORQUE-1.1", + "TOSL", + "TPDL", + "TTWL", + "TU-Berlin-1.0", + "TU-Berlin-2.0", + "u-boot-exception-2.0", + "UCAR", + "UCL-1.0", + "Unicode-DFS-2015", + "Unicode-DFS-2016", + "Unicode-TOU", + "Universal-FOSS-exception-1.0", + "Unlicense", + "NCSA", + "UPL-1.0", + "Linux-man-pages-copyleft", + "Vim", + "VOSTROM", + "VSL-1.0", + "W3C", + "W3C-19980720", + "W3C-20150513", + "w3m", + "Wsuipa", + "WTFPL", + "wxWindows", + "WxWindows-exception-3.1", + "ICU", + "Bitstream-Charter", + "X11-distribute-modifications-variant", + "HPND-sell-variant", + "MIT-open-group", + "libtiff", + "X11", + "XFree86-1.1", + "xinetd", + "Xnet", + "XSkat", + "YPL-1.0", + "YPL-1.1", + "Zed", + "Zend-2.0", + "Zimbra-1.3", + "Zimbra-1.4", + "Zlib", + "zlib-acknowledgement", + "ZPL-1.1", + "ZPL-2.0", + "ZPL-2.1", + "AGPL3", + "Apache", + "Artistic2.0", + "Boost", + "CCPL", + "CDDL", + "CPL", + "EPL", + "FDL1.2", + "FDL1.3", + "GPL2", + "GPL3", + "LGPL2.1", + "LGPL3", + "LPPL", + "MPL", + "MPL2", + "PHP", + "PSF", + "PerlArtistic", + "Unlicense", + "W3C", + "ZPL", + "WTFPL", + "AGPL", + "APACHE", + "FDL", + "GPL", + "LGPL", + "RUBY", + "Ruby", + "custom" + ] + }, + { + "type": "string", + "pattern": "custom:.+" + } + ] + }, + "uniqueItems": true + }, + "install": { + "description": "Specifies a special install script that is to be included in the package. This file should reside in the same directory as the PKGBUILD and will be copied into the package by makepkg. It does not need to be included in the source array (e.g., install=\\$pkgname.install).", + "type": "string" + }, + "changelog": { + "description": "Specifies a changelog file that is to be included in the package. The changelog file should end in a single newline. This file should reside in the same directory as the PKGBUILD and will be copied into the package by makepkg. It does not need to be included in the source array (e.g., changelog=\\$pkgname.changelog).", + "type": "string" + }, + "source": { + "description": "An array of source files required to build the package. Source files must either reside in the same directory as the PKGBUILD, or be a fully-qualified URL that makepkg can use to download the file. To simplify the maintenance of PKGBUILDs, use the \\$pkgname and \\$pkgver variables when specifying the download location, if possible. Compressed files will be extracted automatically unless found in the noextract array described below.\nAdditional architecture-specific sources can be added by appending an underscore and the architecture name e.g., *source_x86_64=()*. There must be a corresponding integrity array with checksums, e.g. *cksums_x86_64=()*.\nIt is also possible to change the name of the downloaded file, which is helpful with weird URLs and for handling multiple source files with the same name. The syntax is: source=(filename::url).\nmakepkg also supports building developmental versions of packages using sources downloaded from version control systems (VCS). For more information, see Using VCS Sources below.\nFiles in the source array with extensions .sig, .sign or, .asc are recognized by makepkg as PGP signatures and will be automatically used to verify the integrity of the corresponding source file.", + "type": "array", + "items": { + "type": "string" + }, + "uniqueItems": true + }, + "validpgpkeys": { + "description": "An array of PGP fingerprints. If this array is non-empty, makepkg will only accept signatures from the keys listed here and will ignore the trust values from the keyring. If the source file was signed with a subkey, makepkg will still use the primary key for comparison.\nOnly full fingerprints are accepted. They must be uppercase and must not contain whitespace characters.", + "type": "array", + "items": { + "type": "string" + }, + "uniqueItems": true + }, + "noextract": { + "description": "An array of file names corresponding to those from the source array. Files listed here will not be extracted with the rest of the source files. This is useful for packages that use compressed data directly.", + "type": "array", + "items": { + "type": "string" + }, + "uniqueItems": true + }, + "cksums": { + "description": "This array contains CRC checksums for every source file specified in the source array (in the same order). makepkg will use this to verify source file integrity during subsequent builds. If *SKIP* is put in the array in place of a normal hash, the integrity check for that source file will be skipped. To easily generate cksums, run \"makepkg -g \\>\\> PKGBUILD\". If desired, move the cksums line to an appropriate location. Note that checksums generated by \\\"makepkg -g\\\" should be verified using checksum values provided by the software developer.", + "type": "array", + "items": { + "type": "string" + } + }, + "md5sums": { + "description": "Alternative integrity checks that makepkg supports; these all behave similar to the cksums option described above. To enable use and generation of these checksums, be sure to set up the INTEGRITY_CHECK option in **makepkg.conf**(5).", + "type": "array", + "items": { + "type": "string" + } + }, + "sha1sums": { + "description": "Alternative integrity checks that makepkg supports; these all behave similar to the cksums option described above. To enable use and generation of these checksums, be sure to set up the INTEGRITY_CHECK option in **makepkg.conf**(5).", + "type": "array", + "items": { + "type": "string" + } + }, + "sha224sums": { + "description": "Alternative integrity checks that makepkg supports; these all behave similar to the cksums option described above. To enable use and generation of these checksums, be sure to set up the INTEGRITY_CHECK option in **makepkg.conf**(5).", + "type": "array", + "items": { + "type": "string" + } + }, + "sha256sums": { + "description": "Alternative integrity checks that makepkg supports; these all behave similar to the cksums option described above. To enable use and generation of these checksums, be sure to set up the INTEGRITY_CHECK option in **makepkg.conf**(5).", + "type": "array", + "items": { + "type": "string" + } + }, + "sha384sums": { + "description": "Alternative integrity checks that makepkg supports; these all behave similar to the cksums option described above. To enable use and generation of these checksums, be sure to set up the INTEGRITY_CHECK option in **makepkg.conf**(5).", + "type": "array", + "items": { + "type": "string" + } + }, + "sha512sums": { + "description": "Alternative integrity checks that makepkg supports; these all behave similar to the cksums option described above. To enable use and generation of these checksums, be sure to set up the INTEGRITY_CHECK option in **makepkg.conf**(5).", + "type": "array", + "items": { + "type": "string" + } + }, + "b2sums": { + "description": "Alternative integrity checks that makepkg supports; these all behave similar to the cksums option described above. To enable use and generation of these checksums, be sure to set up the INTEGRITY_CHECK option in **makepkg.conf**(5).", + "type": "array", + "items": { + "type": "string" + } + }, + "groups": { + "description": "An array of symbolic names that represent groups of packages, allowing you to install multiple packages by requesting a single target. For example, one could install all KDE packages by installing the *kde* group.", + "type": "array", + "items": { + "type": "string" + }, + "uniqueItems": true + }, + "arch": { + "description": "Defines on which architectures the given package is available (e.g., arch=(i686 x86_64)). Packages that contain no architecture specific files should use arch=(any). Valid characters for members of this array are alphanumerics and \"\\_\".", + "type": "array", + "items": { + "type": "string", + "enum": [ + "any", + "pentium4", + "i486", + "i686", + "x86_64", + "x86_64_v3", + "arm", + "armv6h", + "armv7h", + "armv8", + "aarch64" + ] + }, + "uniqueItems": true + }, + "backup": { + "description": "An array of file names, without preceding slashes, that should be backed up if the package is removed or upgraded. This is commonly used for packages placing configuration files in */etc*. See \\\"Handling Config Files\\\" in **pacman**(8) for more information.", + "type": "array", + "items": { + "type": "string" + }, + "uniqueItems": true + }, + "depends": { + "description": "An array of packages this package depends on to run. Entries in this list should be surrounded with single quotes and contain at least the package name. Entries can also include a version requirement of the form *name\\<\\>version*, where \\<\\> is one of five comparisons: \\>= (greater than or equal to), \\<= (less than or equal to), = (equal to), \\> (greater than), or \\< (less than).\nIf the dependency name appears to be a library (ends with .so), makepkg will try to find a binary that depends on the library in the built package and append the version needed by the binary. Appending the version yourself disables automatic detection.\nAdditional architecture-specific depends can be added by appending an underscore and the architecture name e.g., *depends_x86_64=()*.", + "type": "array", + "items": { + "type": "string" + }, + "uniqueItems": true + }, + "makedepends": { + "description": "An array of packages this package depends on to build but are not needed at runtime. Packages in this list follow the same format as depends.\nAdditional architecture-specific makedepends can be added by appending an underscore and the architecture name e.g., *makedepends_x86_64=()*.", + "type": "array", + "items": { + "type": "string" + }, + "uniqueItems": true + }, + "checkdepends": { + "description": "An array of packages this package depends on to run its test suite but are not needed at runtime. Packages in this list follow the same format as depends. These dependencies are only considered when the check() function is present and is to be run by makepkg.\nAdditional architecture-specific checkdepends can be added by appending an underscore and the architecture name e.g., *checkdepends_x86_64=()*.", + "type": "array", + "items": { + "type": "string" + }, + "uniqueItems": true + }, + "optdepends": { + "description": "An array of packages (and accompanying reasons) that are not essential for base functionality, but may be necessary to make full use of the contents of this package. optdepends are currently for informational purposes only and are not utilized by pacman during dependency resolution. Packages in this list follow the same format as depends, with an optional description appended. The format for specifying optdepends descriptions is:\noptdepends=(python: for library bindings) ", + "type": "array", + "items": { + "type": "string" + }, + "uniqueItems": true + }, + "conflicts": { + "description": "An array of packages that will conflict with this package (i.e. they cannot both be installed at the same time). This directive follows the same format as depends. Versioned conflicts are supported using the operators as described in depends.\nAdditional architecture-specific conflicts can be added by appending an underscore and the architecture name e.g., *conflicts_x86_64=()*.", + "type": "array", + "items": { + "type": "string" + }, + "uniqueItems": true + }, + "provides": { + "description": "An array of \"virtual provisions\" this package provides. This allows a package to provide dependencies other than its own package name. For example, the dcron package can provide *cron*, which allows packages to depend on *cron* rather than *dcron OR fcron*.\nVersioned provisions are also possible, in the *name=version* format. For example, dcron can provide *cron=2.0* to satisfy the *cron\\>=2.0* dependency of other packages. Provisions involving the \\> and \\< operators are invalid as only specific versions of a package may be provided.\nIf the provision name appears to be a library (ends with .so), makepkg will try to find the library in the built package and append the correct version. Appending the version yourself disables automatic detection.\nAdditional architecture-specific provides can be added by appending an underscore and the architecture name e.g., *provides_x86_64=()*.", + "type": "array", + "items": { + "type": "string" + }, + "uniqueItems": true + }, + "replaces": { + "description": "An array of packages this package should replace. This can be used to handle renamed/combined packages. For example, if the *j2re* package is renamed to *jre*, this directive allows future upgrades to continue as expected even though the package has moved. Versioned replaces are supported using the operators as described in depends.\nSysupgrade is currently the only pacman operation that utilizes this field. A normal sync or upgrade will not use its value.\nAdditional architecture-specific replaces can be added by appending an underscore and the architecture name e.g., *replaces_x86_64=()*.", + "type": "array", + "items": { + "type": "string" + }, + "uniqueItems": true + }, + "options": { + "description": "This array allows you to override some of makepkg's default behavior when building packages. To set an option, just include the option name in the options array. To reverse the default behavior, place an \"!\" at the front of the option. Only specify the options you specifically want to override, the rest will be taken from **makepkg.conf**(5). **NOTE:** *force* is a now-removed option in favor of the top level *epoch* variable.\n**strip**\nStrip symbols from binaries and libraries. If you frequently use a debugger on programs or libraries, it may be helpful to disable this option.", + "type": "array", + "items": { + "type": "string" + }, + "uniqueItems": true + }, + "srcdir": { + "description": "This contains the directory where makepkg extracts, or copies, all source files.\nAll of the packaging functions defined above are run starting inside \\$srcdir", + "type": "string" + }, + "pkgdir": { + "description": "This contains the directory where makepkg bundles the installed package. This directory will become the root directory of your built package. This variable should only be used in the package() function.", + "type": "string" + }, + "startdir": { + "description": "This contains the absolute path to the directory where the PKGBUILD is located, which is usually the output of \\$(pwd) when makepkg is started. Use of this variable is deprecated and strongly discouraged.", + "type": "string" + }, + "pkgbase": { + "description": "The name used to refer to the group of packages in the output of makepkg and in the naming of source-only tarballs. If not specified, the first element in the pkgname array is used. Valid characters for this variable are alphanumerics, and any of the following characters: \"@ . \\_ + -\". Additionally, the variable is not allowed to start with hyphens or dots.", + "type": "string" + }, + "directory": { + "description": "(optional) Specifies an alternate directory name for makepkg to download the VCS source into.", + "type": "string" + }, + "fragment": { + "description": "(optional) Allows specifying a revision number or branch for makepkg to checkout from the VCS. A fragment has the form type=value, for example to checkout a given revision the source line would be source=(url#revision=123). The available types depends on the VCS being used:\n**bzr**\nrevision (see bzr help revisionspec for details)", + "type": "string" + }, + "query": { + "description": "(optional) Allows specifying whether a VCS checkout should be checked for PGP-signed revisions. The source line should have the format source=(url#fragment?signed) or source=(url?signed#fragment). Currently only supported by Git.", + "type": "string" + }, + "mingw_arch": { + "type": "array", + "description": "A list of MSYS2 environments the package is built for. Defaults to an empty list.", + "items": { + "type": "string", + "enum": [ + "mingw32", + "mingw64", + "ucrt64", + "clang64", + "clang32", + "clangarm64" + ] + }, + "uniqueItems": true + }, + "msys2_references": { + "type": "array", + "description": "Maps the package to external resources, such as other package repositories.", + "items": { + "type": "string", + "pattern": "(archlinux|aur|cygwin|cygwin-mingw64|pypi|gentoo|internal)(|: .*)" + }, + "uniqueItems": true + }, + "msys2_changelog_url": { + "type": "string", + "description": "NEWS file in git or the GitHub releases page. In case there are multiple, the one that is more useful for packagers.", + "format": "uri" + }, + "msys2_documentation_url": { + "type": "string", + "description": "URL to the documentation for the API, tools, etc., in case it's a different website than the homepage.", + "format": "uri" + }, + "msys2_repository_url": { + "type": "string", + "description": "URL to the web view of the repository, e.g., on GitHub or GitLab.", + "format": "uri" + }, + "msys2_issue_tracker_url": { + "type": "string", + "description": "URL to the bug tracker, mailing list archive, etc.", + "format": "uri" + }, + "msys2_pgp_keys_url": { + "type": "string", + "description": "URL to a website containing which keys are used to sign releases.", + "format": "uri" + } + } +} diff --git a/src/termux_language_server/assets/json/build.sh.json b/src/termux_language_server/assets/json/build.sh.json new file mode 100644 index 0000000..cbe98d3 --- /dev/null +++ b/src/termux_language_server/assets/json/build.sh.json @@ -0,0 +1,620 @@ +{ + "$id": "https://github.com/termux/termux-language-server/blob/main/src/termux_language_server/assets/json/build.sh.json", + "$schema": "http://json-schema.org/draft-07/schema#", + "$comment": "Don't edit this file directly! It is generated by `termux-language-server --generate-schema=build.sh`.", + "type": "object", + "required": [ + "TERMUX_PKG_HOMEPAGE", + "TERMUX_PKG_DESCRIPTION", + "TERMUX_PKG_LICENSE", + "TERMUX_PKG_VERSION", + "TERMUX_PKG_AUTO_UPDATE" + ], + "properties": { + "TERMUX_PKG_HOMEPAGE": { + "type": "string", + "description": "Home page URL.", + "format": "uri" + }, + "TERMUX_PKG_DESCRIPTION": { + "type": "string", + "description": "Short, one-line description of package." + }, + "TERMUX_PKG_LICENSE": { + "type": "string", + "description": "Package license.", + "pattern": "(389-exception|Abstyles|CDL-1.0|DOC|GNAT-exception|AdaCore-doc|APL-1.0|Adobe-Glyph|Adobe-2006|ADSL|AFL-1.1|AFL-1.2|AFL-2.0|AFL-2.1|AFL-3.0|Afmparse|Aladdin|AGPL-1.0-only|AGPL-1.0-or-later|AGPL-3.0-only|AGPL-3.0-or-later|Giftware|LicenseRef-.amazon.com.-AmznSL-1.0|AMDPLPA|AML|AMPAS|ANTLR-PD|ANTLR-PD-fallback|Apache-1.0|Apache-1.1|Apache-2.0|APAFML|App-s2p|Swift-exception|APSL-1.0|APSL-1.1|APSL-1.2|APSL-2.0|Arphic-1999|Artistic-1.0|Artistic-1.0-cl8|Artistic-2.0|ClArtistic|Artistic-1.0-Perl|AAL|Autoconf-exception-2.0|Autoconf-exception-3.0|Autoconf-exception-generic|Baekmuk|Bahyph|Barr|Beerware|Bison-exception-2.2|Bitstream-Vera|BitTorrent-1.0|BitTorrent-1.1|blessing|BlueOak-1.0.0|BSL-1.0|Bootloader-exception|Borceux|Brian-Gladman-3-Clause|BSD-1-Clause|BSD-2-Clause-Views|BSD-3-Clause-No-Military-License|BSD-3-Clause-No-Nuclear-Warranty|BSD-3-Clause-Open-MPI|BSD-4-Clause-Shortened|BSD-3-Clause-Attribution|BSD-Advertising-Acknowledgement|BSD-3-Clause|BSD-4-Clause|BSD-4-Clause-UC|BSD-4.3RENO|BSD-2-Clause-Patent|BSD-Protection|BSD-2-Clause|BSD-Source-Code|0BSD|BUSL-1.1|BSD-4.3TAHOE|bzip2-1.0.6|C-UDA-1.0|CATOSL-1.1|CAL-1.0|CAL-1.0-Combined-Work-Exception|Caldera|OGL-Canada-2.0|CMU-Mach|CC-BY-1.0|CC-BY-2.0|CC-BY-2.5|CC-BY-2.5-AU|CC-BY-3.0|CC-BY-3.0-AT|CC-BY-3.0-DE|CC-BY-3.0-IGO|CC-BY-3.0-NL|CC-BY-3.0-US|CC-BY-4.0|CC-BY-NC-1.0|CC-BY-NC-2.0|CC-BY-NC-2.5|CC-BY-NC-3.0|CC-BY-NC-3.0-DE|CC-BY-NC-4.0|CC-BY-NC-ND-1.0|CC-BY-NC-ND-2.0|CC-BY-NC-ND-2.5|CC-BY-NC-ND-3.0|CC-BY-NC-ND-3.0-DE|CC-BY-NC-ND-3.0-IGO|CC-BY-NC-ND-4.0|CC-BY-NC-SA-1.0|CC-BY-NC-SA-2.0|CC-BY-NC-SA-2.0-DE|CC-BY-NC-SA-2.0-FR|CC-BY-NC-SA-2.0-UK|CC-BY-NC-SA-2.5|CC-BY-NC-SA-3.0|CC-BY-NC-SA-3.0-DE|CC-BY-NC-SA-3.0-IGO|CC-BY-NC-SA-4.0|CC-BY-ND-1.0|CC-BY-ND-2.0|CC-BY-ND-2.5|CC-BY-ND-3.0|CC-BY-ND-3.0-DE|CC-BY-ND-4.0|CC-BY-SA-1.0|CC-BY-SA-2.0|CC-BY-SA-2.0-UK|CC-BY-SA-2.1-JP|CC-BY-SA-2.5|CC-BY-SA-3.0|CC-BY-SA-3.0-AT|CC-BY-SA-3.0-DE|CC-BY-SA-4.0|CC-PDDC|CC0-1.0|CDDL-1.0|CDDL-1.1|CDLA-Permissive-1.0|CDLA-Permissive-2.0|CDLA-Sharing-1.0|CECILL-1.0|CECILL-1.1|CECILL-2.0|CECILL-2.1|CECILL-B|CECILL-C|CERN-OHL-1.1|CERN-OHL-1.2|CERN-OHL-P-2.0|CERN-OHL-S-2.0|CERN-OHL-W-2.0|CFITSIO|checkmk|Classpath-exception-2.0|BSD-3-Clause-Clear|Clips|CLISP-exception-2.0|BSD-Attribution-HPND-disclaimer|MIT-CMU|CNRI-Jython|CNRI-Python|CNRI-Python-GPL-Compatible|COIL-1.0|Condor-1.1|copyleft-next-0.3.0|copyleft-next-0.3.1|Cornell-Lossless-JPEG|CPAL-1.0|CPL-1.0|CPOL-1.02|Crossword|CrystalStacker|Community-Spec-1.0|CUA-OPL-1.0|Cube|curl|D-FSL-1.0|diffmark|DigiRule-FOSS-exception|DL-DE-BY-2.0|Plexus|Dotseqn|DRL-1.0|DSDP|dvipdfm|ECL-1.0|ECL-2.0|eCos-2.0|eCos-exception-2.0|RHeCos-1.1|EFL-1.0|EFL-2.0|eGenix|Elastic-2.0|MIT-advertising|MIT-enna|Entessa|EPICS|EPL-1.0|EPL-2.0|ErlPL-1.1|etalab-2.0|EUDatagrid|EUPL-1.0|EUPL-1.1|EUPL-1.2|Eurosym|Fair|OML|Fawkes-Runtime-exception|FLTK-exception|Font-exception-2.0|Frameworx-1.0|FDK-AAC|FreeBSD-DOC|FreeImage|freertos-exception-2.0|FTL|FSFAP|FSFUL|FSFULLR|FSFULLRWD|GCC-exception-3.1|GCC-exception-2.0|GFDL-1.1-only|GFDL-1.1-invariants-only|GFDL-1.1-invariants-or-later|GFDL-1.1-no-invariants-only|GFDL-1.1-no-invariants-or-later|GFDL-1.1-or-later|GFDL-1.2-only|GFDL-1.2-invariants-only|GFDL-1.2-invariants-or-later|GFDL-1.2-no-invariants-only|GFDL-1.2-no-invariants-or-later|GFDL-1.2-or-later|GFDL-1.3-only|GFDL-1.3-invariants-only|GFDL-1.3-invariants-or-later|GFDL-1.3-no-invariants-only|GFDL-1.3-no-invariants-or-later|GFDL-1.3-or-later|GL2PS|Glide|Glulxe|GLWTPL|gnu-javamail-exception|gnuplot|GPL-1.0-only|GPL-1.0-or-later|GPL-2.0-only|GPL-2.0-with-autoconf-exception|GPL-2.0-with-classpath-exception|GPL-2.0-with-font-exception|GPL-2.0-with-GCC-exception|GPL-2.0-or-later|GPL-3.0-only|GPL-3.0-with-autoconf-exception|GPL-3.0-with-GCC-exception|GPL-3.0-linking-exception|GPL-3.0-linking-source-exception|GPL-3.0-or-later|GPL-CC-1.0|Graphics-Gems|gSOAP-1.3b|GStreamer-exception-2005|GStreamer-exception-2008|HaskellReport|Spencer-99|Hippocratic-2.1|HPND|HPND-export-US|HPND-sell-variant-MIT-disclaimer|Spencer-94|i2p-gpl-java-exception|IBM-pibs|IPL-1.0|IEC-Code-Components-EULA|IJG|IJG-short|ImageMagick|Imlib2|xpp|Info-ZIP|QPL-1.0-INRIA-2004-exception|Intel-ACPI|Intel|Interbase-1.0|IPA|ISC|Jam|JasPer-2.0|JPL-image|JPNIC|JSON|Kazlib|KiCad-libraries-exception|Knuth-CTAN|LAL-1.2|LAL-1.3|Latex2e|BSD-3-Clause-LBNL|Leptonica|LGPL-2.0-only|LGPL-2.0-or-later|LGPL-2.1-only|LGPL-2.1-or-later|LGPL-3.0-only|LGPL-3.0-linking-exception|LGPL-3.0-or-later|LGPLLR|GD|xlock|Libpng|libpng-2.0|Libtool-exception|libutil-David-Nugent|LiLiQ-P-1.1|LiLiQ-R-1.1|LiLiQ-Rplus-1.1|Linux-OpenIB|Linux-syscall-note|LLVM-exception|LOOP|LPPL-1.0|LPPL-1.1|LPPL-1.2|LPPL-1.3a|LPPL-1.3c|LPL-1.0|LPL-1.02|LZMA-exception|LZMA-SDK-9.11-to-9.20|LZMA-SDK-9.22|mplus|MakeIndex|HPND-Markus-Kuhn|Martin-Birgmeier|mif-exception|Minpack|MirOS|MIT|MIT-0|MIT-feh|MIT-Wu|Xerox|MIT-Modern-Variant|MITNFA|NTP|SSPL-1.0|Motosoto|mpi-permissive|mpich2|MPL-1.0|MPL-1.1|MPL-2.0|MPL-2.0-no-copyleft-exception|MS-LPL|MS-PL|MS-RL|MTLL|MulanPSL-1.0|MulanPSL-2.0|Multics|Mup|NAIST-2003|NASA-1.3|Naumen|NBPL-1.0|NCGL-UK-2.0|Net-SNMP|NetCDF|Newsletr|NGPL|NICTA-1.0|NIST-PD|NIST-PD-fallback|NLOD-1.0|NLOD-2.0|NLPL|Nokia|NOSL|NPOSL-3.0|Noweb|NPL-1.0|NPL-1.1|NRL|NTP-0|O-UDA-1.0|OCaml-LGPL-linking-exception|OCCT-exception-1.0|OCCT-PL|OCLC-2.0|ODbL-1.0|ODC-By-1.0|OFFIS|OFL-1.0|OFL-1.0-no-RFN|OFL-1.0-RFN|OFL-1.1|OFL-1.1-no-RFN|OFL-1.1-RFN|OGC-1.0|OGDL-Taiwan-1.0|OGL-UK-1.0|OGL-UK-2.0|OGL-UK-3.0|OPL-1.0|OGTSL|OpenJDK-assembly-exception-1.0|OLDAP-1.1|OLDAP-1.2|OLDAP-1.3|OLDAP-1.4|OLDAP-2.0|OLDAP-2.0.1|OLDAP-2.1|OLDAP-2.2|OLDAP-2.2.1|OLDAP-2.2.2|OLDAP-2.3|OLDAP-2.4|OLDAP-2.5|OLDAP-2.6|OLDAP-2.7|OLDAP-2.8|OpenPBS-2.3|OPUBL-1.0|SSH-OpenSSH|x11vnc-openssl-exception|OpenSSL|openvpn-openssl-exception|BSD-3-Clause-No-Nuclear-License-2014|OSET-PL-2.1|HP-1986|OSL-1.0|OSL-1.1|OSL-2.0|OSL-2.1|OSL-3.0|Parity-6.0.0|Parity-7.0.0|PDDL-1.0|PHP-3.0|PHP-3.01|PolyForm-Noncommercial-1.0.0|PolyForm-Small-Business-1.0.0|PostgreSQL|PS-or-PDF-font-exception-20170817|PSF-2.0|psfrag|psutils|Python-2.0|Python-2.0.1|Qhull|QPL-1.0|QPL-1.0-INRIA-2004|Qt-GPL-exception-1.0|Qt-LGPL-exception-1.1|Qwt-exception-1.0|Rdisc|Spencer-86|BSD-3-Clause-Modification|RSCPL|RPL-1.1|RPL-1.5|RPSL-1.0|RSA-MD|Ruby|SAX-PD|Saxpath|SCEA|SchemeReport|libselinux-1.0|Sendmail|Sendmail-8.23|iMatix|SGI-B-1.1|SGI-B-2.0|SGI-B-1.0|SHL-0.5|SHL-0.51|SHL-2.0|SHL-2.1|SimPL-2.0|Sleepycat|SMPPL|SNIA|snprintf|SPL-1.0|SMLNJ|SugarCRM-1.1.3|BSD-3-Clause-No-Nuclear-License|SISSL|SISSL-1.2|SunPro|SWI-exception|SWL|Watcom-1.0|Symlinks|TAPR-OHL-1.0|SSH-short|TCL|TCP-wrappers|TPL-1.0|HTMLTIDY|TMate|TORQUE-1.1|TOSL|TPDL|TTWL|TU-Berlin-1.0|TU-Berlin-2.0|u-boot-exception-2.0|UCAR|UCL-1.0|Unicode-DFS-2015|Unicode-DFS-2016|Unicode-TOU|Universal-FOSS-exception-1.0|Unlicense|NCSA|UPL-1.0|Linux-man-pages-copyleft|Vim|VOSTROM|VSL-1.0|W3C|W3C-19980720|W3C-20150513|w3m|Wsuipa|WTFPL|wxWindows|WxWindows-exception-3.1|ICU|Bitstream-Charter|X11-distribute-modifications-variant|HPND-sell-variant|MIT-open-group|libtiff|X11|XFree86-1.1|xinetd|Xnet|XSkat|YPL-1.0|YPL-1.1|Zed|Zend-2.0|Zimbra-1.3|Zimbra-1.4|Zlib|zlib-acknowledgement|ZPL-1.1|ZPL-2.0|ZPL-2.1)(,(389-exception|Abstyles|CDL-1.0|DOC|GNAT-exception|AdaCore-doc|APL-1.0|Adobe-Glyph|Adobe-2006|ADSL|AFL-1.1|AFL-1.2|AFL-2.0|AFL-2.1|AFL-3.0|Afmparse|Aladdin|AGPL-1.0-only|AGPL-1.0-or-later|AGPL-3.0-only|AGPL-3.0-or-later|Giftware|LicenseRef-.amazon.com.-AmznSL-1.0|AMDPLPA|AML|AMPAS|ANTLR-PD|ANTLR-PD-fallback|Apache-1.0|Apache-1.1|Apache-2.0|APAFML|App-s2p|Swift-exception|APSL-1.0|APSL-1.1|APSL-1.2|APSL-2.0|Arphic-1999|Artistic-1.0|Artistic-1.0-cl8|Artistic-2.0|ClArtistic|Artistic-1.0-Perl|AAL|Autoconf-exception-2.0|Autoconf-exception-3.0|Autoconf-exception-generic|Baekmuk|Bahyph|Barr|Beerware|Bison-exception-2.2|Bitstream-Vera|BitTorrent-1.0|BitTorrent-1.1|blessing|BlueOak-1.0.0|BSL-1.0|Bootloader-exception|Borceux|Brian-Gladman-3-Clause|BSD-1-Clause|BSD-2-Clause-Views|BSD-3-Clause-No-Military-License|BSD-3-Clause-No-Nuclear-Warranty|BSD-3-Clause-Open-MPI|BSD-4-Clause-Shortened|BSD-3-Clause-Attribution|BSD-Advertising-Acknowledgement|BSD-3-Clause|BSD-4-Clause|BSD-4-Clause-UC|BSD-4.3RENO|BSD-2-Clause-Patent|BSD-Protection|BSD-2-Clause|BSD-Source-Code|0BSD|BUSL-1.1|BSD-4.3TAHOE|bzip2-1.0.6|C-UDA-1.0|CATOSL-1.1|CAL-1.0|CAL-1.0-Combined-Work-Exception|Caldera|OGL-Canada-2.0|CMU-Mach|CC-BY-1.0|CC-BY-2.0|CC-BY-2.5|CC-BY-2.5-AU|CC-BY-3.0|CC-BY-3.0-AT|CC-BY-3.0-DE|CC-BY-3.0-IGO|CC-BY-3.0-NL|CC-BY-3.0-US|CC-BY-4.0|CC-BY-NC-1.0|CC-BY-NC-2.0|CC-BY-NC-2.5|CC-BY-NC-3.0|CC-BY-NC-3.0-DE|CC-BY-NC-4.0|CC-BY-NC-ND-1.0|CC-BY-NC-ND-2.0|CC-BY-NC-ND-2.5|CC-BY-NC-ND-3.0|CC-BY-NC-ND-3.0-DE|CC-BY-NC-ND-3.0-IGO|CC-BY-NC-ND-4.0|CC-BY-NC-SA-1.0|CC-BY-NC-SA-2.0|CC-BY-NC-SA-2.0-DE|CC-BY-NC-SA-2.0-FR|CC-BY-NC-SA-2.0-UK|CC-BY-NC-SA-2.5|CC-BY-NC-SA-3.0|CC-BY-NC-SA-3.0-DE|CC-BY-NC-SA-3.0-IGO|CC-BY-NC-SA-4.0|CC-BY-ND-1.0|CC-BY-ND-2.0|CC-BY-ND-2.5|CC-BY-ND-3.0|CC-BY-ND-3.0-DE|CC-BY-ND-4.0|CC-BY-SA-1.0|CC-BY-SA-2.0|CC-BY-SA-2.0-UK|CC-BY-SA-2.1-JP|CC-BY-SA-2.5|CC-BY-SA-3.0|CC-BY-SA-3.0-AT|CC-BY-SA-3.0-DE|CC-BY-SA-4.0|CC-PDDC|CC0-1.0|CDDL-1.0|CDDL-1.1|CDLA-Permissive-1.0|CDLA-Permissive-2.0|CDLA-Sharing-1.0|CECILL-1.0|CECILL-1.1|CECILL-2.0|CECILL-2.1|CECILL-B|CECILL-C|CERN-OHL-1.1|CERN-OHL-1.2|CERN-OHL-P-2.0|CERN-OHL-S-2.0|CERN-OHL-W-2.0|CFITSIO|checkmk|Classpath-exception-2.0|BSD-3-Clause-Clear|Clips|CLISP-exception-2.0|BSD-Attribution-HPND-disclaimer|MIT-CMU|CNRI-Jython|CNRI-Python|CNRI-Python-GPL-Compatible|COIL-1.0|Condor-1.1|copyleft-next-0.3.0|copyleft-next-0.3.1|Cornell-Lossless-JPEG|CPAL-1.0|CPL-1.0|CPOL-1.02|Crossword|CrystalStacker|Community-Spec-1.0|CUA-OPL-1.0|Cube|curl|D-FSL-1.0|diffmark|DigiRule-FOSS-exception|DL-DE-BY-2.0|Plexus|Dotseqn|DRL-1.0|DSDP|dvipdfm|ECL-1.0|ECL-2.0|eCos-2.0|eCos-exception-2.0|RHeCos-1.1|EFL-1.0|EFL-2.0|eGenix|Elastic-2.0|MIT-advertising|MIT-enna|Entessa|EPICS|EPL-1.0|EPL-2.0|ErlPL-1.1|etalab-2.0|EUDatagrid|EUPL-1.0|EUPL-1.1|EUPL-1.2|Eurosym|Fair|OML|Fawkes-Runtime-exception|FLTK-exception|Font-exception-2.0|Frameworx-1.0|FDK-AAC|FreeBSD-DOC|FreeImage|freertos-exception-2.0|FTL|FSFAP|FSFUL|FSFULLR|FSFULLRWD|GCC-exception-3.1|GCC-exception-2.0|GFDL-1.1-only|GFDL-1.1-invariants-only|GFDL-1.1-invariants-or-later|GFDL-1.1-no-invariants-only|GFDL-1.1-no-invariants-or-later|GFDL-1.1-or-later|GFDL-1.2-only|GFDL-1.2-invariants-only|GFDL-1.2-invariants-or-later|GFDL-1.2-no-invariants-only|GFDL-1.2-no-invariants-or-later|GFDL-1.2-or-later|GFDL-1.3-only|GFDL-1.3-invariants-only|GFDL-1.3-invariants-or-later|GFDL-1.3-no-invariants-only|GFDL-1.3-no-invariants-or-later|GFDL-1.3-or-later|GL2PS|Glide|Glulxe|GLWTPL|gnu-javamail-exception|gnuplot|GPL-1.0-only|GPL-1.0-or-later|GPL-2.0-only|GPL-2.0-with-autoconf-exception|GPL-2.0-with-classpath-exception|GPL-2.0-with-font-exception|GPL-2.0-with-GCC-exception|GPL-2.0-or-later|GPL-3.0-only|GPL-3.0-with-autoconf-exception|GPL-3.0-with-GCC-exception|GPL-3.0-linking-exception|GPL-3.0-linking-source-exception|GPL-3.0-or-later|GPL-CC-1.0|Graphics-Gems|gSOAP-1.3b|GStreamer-exception-2005|GStreamer-exception-2008|HaskellReport|Spencer-99|Hippocratic-2.1|HPND|HPND-export-US|HPND-sell-variant-MIT-disclaimer|Spencer-94|i2p-gpl-java-exception|IBM-pibs|IPL-1.0|IEC-Code-Components-EULA|IJG|IJG-short|ImageMagick|Imlib2|xpp|Info-ZIP|QPL-1.0-INRIA-2004-exception|Intel-ACPI|Intel|Interbase-1.0|IPA|ISC|Jam|JasPer-2.0|JPL-image|JPNIC|JSON|Kazlib|KiCad-libraries-exception|Knuth-CTAN|LAL-1.2|LAL-1.3|Latex2e|BSD-3-Clause-LBNL|Leptonica|LGPL-2.0-only|LGPL-2.0-or-later|LGPL-2.1-only|LGPL-2.1-or-later|LGPL-3.0-only|LGPL-3.0-linking-exception|LGPL-3.0-or-later|LGPLLR|GD|xlock|Libpng|libpng-2.0|Libtool-exception|libutil-David-Nugent|LiLiQ-P-1.1|LiLiQ-R-1.1|LiLiQ-Rplus-1.1|Linux-OpenIB|Linux-syscall-note|LLVM-exception|LOOP|LPPL-1.0|LPPL-1.1|LPPL-1.2|LPPL-1.3a|LPPL-1.3c|LPL-1.0|LPL-1.02|LZMA-exception|LZMA-SDK-9.11-to-9.20|LZMA-SDK-9.22|mplus|MakeIndex|HPND-Markus-Kuhn|Martin-Birgmeier|mif-exception|Minpack|MirOS|MIT|MIT-0|MIT-feh|MIT-Wu|Xerox|MIT-Modern-Variant|MITNFA|NTP|SSPL-1.0|Motosoto|mpi-permissive|mpich2|MPL-1.0|MPL-1.1|MPL-2.0|MPL-2.0-no-copyleft-exception|MS-LPL|MS-PL|MS-RL|MTLL|MulanPSL-1.0|MulanPSL-2.0|Multics|Mup|NAIST-2003|NASA-1.3|Naumen|NBPL-1.0|NCGL-UK-2.0|Net-SNMP|NetCDF|Newsletr|NGPL|NICTA-1.0|NIST-PD|NIST-PD-fallback|NLOD-1.0|NLOD-2.0|NLPL|Nokia|NOSL|NPOSL-3.0|Noweb|NPL-1.0|NPL-1.1|NRL|NTP-0|O-UDA-1.0|OCaml-LGPL-linking-exception|OCCT-exception-1.0|OCCT-PL|OCLC-2.0|ODbL-1.0|ODC-By-1.0|OFFIS|OFL-1.0|OFL-1.0-no-RFN|OFL-1.0-RFN|OFL-1.1|OFL-1.1-no-RFN|OFL-1.1-RFN|OGC-1.0|OGDL-Taiwan-1.0|OGL-UK-1.0|OGL-UK-2.0|OGL-UK-3.0|OPL-1.0|OGTSL|OpenJDK-assembly-exception-1.0|OLDAP-1.1|OLDAP-1.2|OLDAP-1.3|OLDAP-1.4|OLDAP-2.0|OLDAP-2.0.1|OLDAP-2.1|OLDAP-2.2|OLDAP-2.2.1|OLDAP-2.2.2|OLDAP-2.3|OLDAP-2.4|OLDAP-2.5|OLDAP-2.6|OLDAP-2.7|OLDAP-2.8|OpenPBS-2.3|OPUBL-1.0|SSH-OpenSSH|x11vnc-openssl-exception|OpenSSL|openvpn-openssl-exception|BSD-3-Clause-No-Nuclear-License-2014|OSET-PL-2.1|HP-1986|OSL-1.0|OSL-1.1|OSL-2.0|OSL-2.1|OSL-3.0|Parity-6.0.0|Parity-7.0.0|PDDL-1.0|PHP-3.0|PHP-3.01|PolyForm-Noncommercial-1.0.0|PolyForm-Small-Business-1.0.0|PostgreSQL|PS-or-PDF-font-exception-20170817|PSF-2.0|psfrag|psutils|Python-2.0|Python-2.0.1|Qhull|QPL-1.0|QPL-1.0-INRIA-2004|Qt-GPL-exception-1.0|Qt-LGPL-exception-1.1|Qwt-exception-1.0|Rdisc|Spencer-86|BSD-3-Clause-Modification|RSCPL|RPL-1.1|RPL-1.5|RPSL-1.0|RSA-MD|Ruby|SAX-PD|Saxpath|SCEA|SchemeReport|libselinux-1.0|Sendmail|Sendmail-8.23|iMatix|SGI-B-1.1|SGI-B-2.0|SGI-B-1.0|SHL-0.5|SHL-0.51|SHL-2.0|SHL-2.1|SimPL-2.0|Sleepycat|SMPPL|SNIA|snprintf|SPL-1.0|SMLNJ|SugarCRM-1.1.3|BSD-3-Clause-No-Nuclear-License|SISSL|SISSL-1.2|SunPro|SWI-exception|SWL|Watcom-1.0|Symlinks|TAPR-OHL-1.0|SSH-short|TCL|TCP-wrappers|TPL-1.0|HTMLTIDY|TMate|TORQUE-1.1|TOSL|TPDL|TTWL|TU-Berlin-1.0|TU-Berlin-2.0|u-boot-exception-2.0|UCAR|UCL-1.0|Unicode-DFS-2015|Unicode-DFS-2016|Unicode-TOU|Universal-FOSS-exception-1.0|Unlicense|NCSA|UPL-1.0|Linux-man-pages-copyleft|Vim|VOSTROM|VSL-1.0|W3C|W3C-19980720|W3C-20150513|w3m|Wsuipa|WTFPL|wxWindows|WxWindows-exception-3.1|ICU|Bitstream-Charter|X11-distribute-modifications-variant|HPND-sell-variant|MIT-open-group|libtiff|X11|XFree86-1.1|xinetd|Xnet|XSkat|YPL-1.0|YPL-1.1|Zed|Zend-2.0|Zimbra-1.3|Zimbra-1.4|Zlib|zlib-acknowledgement|ZPL-1.1|ZPL-2.0|ZPL-2.1))*" + }, + "TERMUX_PKG_LICENSE_FILE": { + "type": "string", + "description": "Name of license file, if it is not found automatically." + }, + "TERMUX_PKG_MAINTAINER": { + "type": "string", + "description": "Package maintainer.", + "default": "@termux" + }, + "TERMUX_PKG_API_LEVEL": { + "type": "string", + "description": "Android API level for which package should be compiled." + }, + "TERMUX_PKG_VERSION": { + "type": "string", + "description": "Original package version." + }, + "TERMUX_PKG_REVISION": { + "type": "string", + "description": "Package revision. Bumped on each package rebuild." + }, + "TERMUX_PKG_SKIP_SRC_EXTRACT": { + "type": "string", + "description": "Whether to omit source code downloading and extraction. Default is false.", + "default": "false", + "enum": [ + "true", + "false" + ] + }, + "TERMUX_PKG_SRCURL": { + "type": "string", + "description": "URL from which source archive should be downloaded, either an archive or a git url ending with .git", + "format": "uri" + }, + "TERMUX_PKG_SHA256": { + "type": "string", + "description": "SHA-256 checksum of source archive." + }, + "TERMUX_PKG_GIT_BRANCH": { + "type": "string", + "description": "Branch to checkout in termux_step_git_clone_src. Default is v$TERMUX_PKG_VERSION." + }, + "TERMUX_PKG_METAPACKAGE": { + "type": "string", + "description": "Whether to make package treated as metapackage. Default is false.", + "default": "false", + "enum": [ + "true", + "false" + ] + }, + "TERMUX_PKG_DEPENDS": { + "type": "string", + "description": "Comma-separated list of dependency package names.", + "pattern": "[a-z][a-z0-9-]*(, [a-z][a-z0-9-]*)*" + }, + "TERMUX_PKG_BUILD_DEPENDS": { + "type": "string", + "description": "Comma-separated list of build-time only dependencies.", + "pattern": "[a-z][a-z0-9-]*(, [a-z][a-z0-9-]*)*" + }, + "TERMUX_PKG_BREAKS": { + "type": "string", + "description": "Comma-separated list of packages that are incompatible with the current one.", + "pattern": "[a-z][a-z0-9-]*(, [a-z][a-z0-9-]*)*" + }, + "TERMUX_PKG_CONFLICTS": { + "type": "string", + "description": "Comma-separated list of packages which have file name collisions with the current one.", + "pattern": "[a-z][a-z0-9-]*(, [a-z][a-z0-9-]*)*" + }, + "TERMUX_PKG_REPLACES": { + "type": "string", + "description": "Comma-separated list of packages being replaced by current one.", + "pattern": "[a-z][a-z0-9-]*(, [a-z][a-z0-9-]*)*" + }, + "TERMUX_PKG_PROVIDES": { + "type": "string", + "description": "Comma-separated list of virtual packages being provided by current one.", + "pattern": "[a-z][a-z0-9-]*(, [a-z][a-z0-9-]*)*" + }, + "TERMUX_PKG_RECOMMENDS": { + "type": "string", + "description": "Comma-separated list of non-absolute dependencies - packages usually used with the current one.", + "pattern": "[a-z][a-z0-9-]*(, [a-z][a-z0-9-]*)*" + }, + "TERMUX_PKG_SUGGESTS": { + "type": "string", + "description": "Comma-separated list of packages that are related to or enhance the current one.", + "pattern": "[a-z][a-z0-9-]*(, [a-z][a-z0-9-]*)*" + }, + "TERMUX_PKG_ESSENTIAL": { + "type": "string", + "description": "Whether to treat package as essential which cannot be uninstalled in usual way. Default is false.", + "default": "false", + "enum": [ + "true", + "false" + ] + }, + "TERMUX_PKG_NO_STATICSPLIT": { + "type": "string", + "description": "Whether to split static libraries into a subpackage. Default is false.", + "default": "false", + "enum": [ + "true", + "false" + ] + }, + "TERMUX_PKG_STATICSPLIT_EXTRA_PATTERNS": { + "type": "string", + "description": "Extra patterns to include in static package. It must be relative to $TERMUX_PREFIX. For example: to include *.h files from $TERMUX_PREFIX/lib, specify lib/*.h. You can use bash globstar patterns to recurse sub-directories." + }, + "TERMUX_PKG_IS_HASKELL_LIB": { + "type": "string", + "description": "Whether the package is haskell library. Default is false.", + "default": "false", + "enum": [ + "true", + "false" + ] + }, + "TERMUX_PKG_BUILD_IN_SRC": { + "type": "string", + "description": "Whether to perform build in a source code directory. Default is false.", + "default": "false", + "enum": [ + "true", + "false" + ] + }, + "TERMUX_PKG_HAS_DEBUG": { + "type": "string", + "description": "Whether debug builds are possible for package. Default is true.", + "default": "true", + "enum": [ + "true", + "false" + ] + }, + "TERMUX_PKG_PLATFORM_INDEPENDENT": { + "type": "string", + "description": "Whether to treat package as platform independent. Default is false.", + "default": "false", + "enum": [ + "true", + "false" + ] + }, + "TERMUX_PKG_EXCLUDED_ARCHES": { + "type": "string", + "description": "Comma-separated list of CPU architectures for which package cannot be compiled.", + "pattern": "[a-z][a-z0-9-]*(, [a-z][a-z0-9-]*)*" + }, + "TERMUX_PKG_HOSTBUILD": { + "type": "string", + "description": "Whether package require building for host. Default is false.", + "default": "false", + "enum": [ + "true", + "false" + ] + }, + "TERMUX_PKG_FORCE_CMAKE": { + "type": "string", + "description": "Whether to prefer CMake over Autotools configure script. Default is false.", + "default": "false", + "enum": [ + "true", + "false" + ] + }, + "TERMUX_PKG_EXTRA_CONFIGURE_ARGS": { + "type": "string", + "description": "Extra arguments passed to build system configuration utility." + }, + "TERMUX_PKG_EXTRA_HOSTBUILD_CONFIGURE_ARGS": { + "type": "string", + "description": "Extra arguments passed to build system configuration utility when performing host build." + }, + "TERMUX_PKG_EXTRA_MAKE_ARGS": { + "type": "string", + "description": "Extra arguments passed to utility make." + }, + "TERMUX_PKG_MAKE_INSTALL_TARGET": { + "type": "string", + "description": "Equivalent for install argument passed to utility make in the installation process." + }, + "TERMUX_PKG_RM_AFTER_INSTALL": { + "type": "string", + "description": "List of files that should be removed after installation process." + }, + "TERMUX_PKG_CONFFILES": { + "type": "string", + "description": "A space or newline separated list of package configuration files that should not be overwritten on update." + }, + "TERMUX_PKG_SERVICE_SCRIPT": { + "type": "string", + "description": "Array of even length containing daemon name(s) and script(s) for use with termux-services/runit." + }, + "TERMUX_PKG_GO_USE_OLDER": { + "type": "string", + "description": "Use the older supported release of Go (1.19.7). Default is false.", + "default": "false", + "enum": [ + "true", + "false" + ] + }, + "TERMUX_PKG_NO_STRIP": { + "type": "string", + "description": "Disable stripping binaries. Default is false.", + "default": "false", + "enum": [ + "true", + "false" + ] + }, + "TERMUX_PKG_NO_SHEBANG_FIX": { + "type": "string", + "description": "Skip fixing shebang accordingly to $TERMUX_PREFIX. Default is false.", + "default": "false", + "enum": [ + "true", + "false" + ] + }, + "TERMUX_PKG_NO_ELF_CLEANER": { + "type": "string", + "description": "Disable running of termux-elf-cleaner on built binaries. Default is false.", + "default": "false", + "enum": [ + "true", + "false" + ] + }, + "TERMUX_PKG_AUTO_UPDATE": { + "type": "string", + "description": "Whether to enable automatic updates for this package. Currently packages hosted on GitHub, Gitlab or tracked by repology can be auto updated. For using your own method see here. After writing build.sh you can check if package can be auto-updated using script at scripts/bin/check-auto-update." + }, + "TERMUX_PKG_UPDATE_VERSION_REGEXP": { + "type": "string", + "description": "Regex to extract version from the new computed version. \u2022 grep -P is set, so you can use perl regex.Use case: any api may return new version as Release_8.9.0, but we want only 8.9.0. So, we can extract it using \\d+\\.\\d+\\.\\d+.", + "format": "regex" + }, + "TERMUX_PKG_UPDATE_METHOD": { + "type": "string", + "description": "Which method to use for auto-update. Can be github, gitlab or repology. By default it is decided on the basis of TERMUX_PKG_SRCURL", + "enum": [ + "github", + "gitlab", + "repology" + ] + }, + "TERMUX_PKG_UPDATE_TAG_TYPE": { + "type": "string", + "description": "Whether to get latest-release-tag or newest-tag (sorted by commit date) if using github or gitlab method for auto-update. By default if TERMUX_PKG_SRCURL ends in .git then newest-tag is fetched otherwise latest-release-tag." + }, + "TERMUX_GITLAB_API_HOST": { + "type": "string", + "description": "Which host to use for gitlab api. Default gitlab.com", + "default": "gitlab.com", + "format": "hostname" + }, + "termux_step_get_source": { + "description": "Obtain package source code and put it in $TERMUX_PKG_SRCDIR.", + "const": 0 + }, + "termux_step_post_get_source": { + "description": "Hook to run commands immediately after obtaining source code.", + "const": 0 + }, + "termux_step_handle_host_build": { + "description": "Determine whether a host build is required.", + "const": 0 + }, + "termux_step_host_build": { + "description": "Perform a host build.", + "const": 0 + }, + "termux_step_pre_configure": { + "description": "Hook to run commands before source configuration.", + "const": 0 + }, + "termux_step_configure": { + "description": "Configure sources. By default, it determines build system automatically.", + "const": 0 + }, + "termux_step_post_configure": { + "description": "Hook to run commands immediately after configuration.", + "const": 0 + }, + "termux_step_make": { + "description": "Compile the source code.", + "const": 0 + }, + "termux_step_make_install": { + "description": "Install the compiled artifacts.", + "const": 0 + }, + "termux_step_post_make_install": { + "description": "Hook to run commands immediately after installation.", + "const": 0 + }, + "termux_step_install_service_scripts": { + "description": "Installs scripts for termux-services", + "const": 0 + }, + "termux_step_install_license": { + "description": "Link or copy package-specific LICENSE to ./share/doc/$TERMUX_PKG_NAME.", + "const": 0 + }, + "termux_step_extract_into_massagedir": { + "description": "Extract files modified in $TERMUX_PREFIX.", + "const": 0 + }, + "termux_step_post_massage": { + "description": "Final hook before creating *.deb file(s).", + "const": 0 + }, + "termux_step_create_debscripts": { + "description": "Create maintainer scripts, e.g. pre/post installation hooks.", + "const": 0 + }, + "termux_pkg_auto_update": { + "description": "By default, decide which method (gitlab, github or repology) to use for update, but can be overrided to use custom method (See here).", + "const": 0 + } + }, + "propertyNames": { + "not": { + "anyOf": [ + { + "const": "TERMUX_ON_DEVICE_BUILD", + "description": "If set, assume that building on device." + }, + { + "const": "TERMUX_BUILD_IGNORE_LOCK", + "description": "If set to true, ignore build process lock." + }, + { + "const": "TERMUX_BUILD_LOCK_FILE", + "description": "Path to build process lock file." + }, + { + "const": "TERMUX_HOST_PLATFORM", + "description": "Host platform definition. Usually $TERMUX_ARCH-linux-android." + }, + { + "const": "TERMUX_PKG_BUILDDIR", + "description": "Path to build directory of current package." + }, + { + "const": "TERMUX_PKG_BUILDER_DIR", + "description": "Path to directory where located build.sh of current package." + }, + { + "const": "TERMUX_PKG_BUILDER_SCRIPT", + "description": "Path to build.sh of current package." + }, + { + "const": "TERMUX_PKG_CACHEDIR", + "description": "Path to source cache directory of current package." + }, + { + "const": "TERMUX_PKG_MASSAGEDIR", + "description": "Path to directory where package content will be extracted from $TERMUX_PREFIX." + }, + { + "const": "TERMUX_PKG_PACKAGEDIR", + "description": "Path to directory where components of *.deb archive of current package will be created." + }, + { + "const": "TERMUX_PKG_SRCDIR", + "description": "Path to source directory of current package." + }, + { + "const": "TERMUX_PKG_TMPDIR", + "description": "Path to temporary directory specific for current package." + }, + { + "const": "TERMUX_COMMON_CACHEDIR", + "description": "Path to global cache directory where build tools are stored." + }, + { + "const": "TERMUX_SCRIPTDIR", + "description": "Path to directory with utility scripts." + }, + { + "const": "TERMUX_PKG_NAME", + "description": "Name of current package." + }, + { + "const": "TERMUX_REPO_URL", + "description": "Array of APT repository URLs from which dependencies will be downloaded if ./build-package.sh got option -i or -I." + }, + { + "const": "TERMUX_REPO_DISTRIBUTION", + "description": "Array of distribution names in addition for TERMUX_REPO_URL." + }, + { + "const": "TERMUX_REPO_COMPONENT", + "description": "Array of repository component names in addition for TERMUX_REPO_URL." + }, + { + "const": "TERMUX_PACKAGE_FORMAT", + "description": "Package output format." + }, + { + "const": "termux_error_exit", + "description": "Stop script and output error." + }, + { + "const": "termux_download", + "description": "Utility function to download any file." + }, + { + "const": "termux_setup_golang", + "description": "Setup Go Build environment." + }, + { + "const": "termux_setup_cmake", + "description": "Setup CMake configure system." + }, + { + "const": "termux_setup_ninja", + "description": "Setup Ninja make system." + }, + { + "const": "termux_setup_meson", + "description": "Setup Meson configure system." + }, + { + "const": "termux_setup_protobuf", + "description": "Setup Protobuf compiler." + }, + { + "const": "termux_setup_rust", + "description": "Setup Cargo Build." + }, + { + "const": "termux_setup_ghc_cross_compiler", + "description": "Setup ghc cross-compiler targeting Android." + }, + { + "const": "termux_setup_ghc", + "description": "Setup ghc compiler for host build." + }, + { + "const": "termux_setup_jailbreak_cabal", + "description": "Setup jailbreak-cabal utility. It is used to remove version constraints from Haskell (with cabal build system)" + }, + { + "const": "termux_step_setup_variables", + "description": "Setup essential variables like directory locations and flags." + }, + { + "const": "termux_step_handle_buildarch", + "description": "Determine architecture to build for." + }, + { + "const": "termux_step_setup_build_folders", + "description": "Delete old src and build directories if they exist." + }, + { + "const": "termux_step_start_build", + "description": "Initialize build environment. Source package's build.sh." + }, + { + "const": "termux_step_get_dependencies", + "description": "Download or build specified dependencies of the package." + }, + { + "const": "termux_step_get_repo_files", + "description": "Fetch APT packages information when -i or -I option was supplied." + }, + { + "const": "termux_extract_dep_info", + "description": "Obtain package architecture and version for downloading." + }, + { + "const": "termux_step_create_timestamp_file", + "description": "Make timestamp to determine which files have been installed by the build." + }, + { + "const": "termux_download_deb", + "description": "Download dependency *.deb packages for installation." + }, + { + "const": "termux_git_clone_src", + "description": "Obtain source by git clone, is run if $TERMUX_PKG_SRCURL ends with \".git\"." + }, + { + "const": "termux_download_src_archive", + "description": "Download zip or tar archive with package source code." + }, + { + "const": "termux_unpack_src_archive", + "description": "Extract downloaded archive into $TERMUX_PKG_SRCDIR." + }, + { + "const": "termux_step_setup_toolchain", + "description": "Setup NDK standalone toolchain." + }, + { + "const": "termux_step_patch_package", + "description": "Apply to source code all *.patch files located in package's directory." + }, + { + "const": "termux_step_replace_guess_scripts", + "description": "Replace config.sub and config.guess scripts." + }, + { + "const": "termux_step_configure_haskell_build", + "description": "Haskell packages build configuration." + }, + { + "const": "termux_step_configure_autotools", + "description": "Autotools build configuration." + }, + { + "const": "termux_step_configure_cmake", + "description": "CMake build configuration." + }, + { + "const": "termux_step_configure_meson", + "description": "Meson build configuration." + }, + { + "const": "termux_step_massage", + "description": "Strip binaries, remove unneeded files." + }, + { + "const": "termux_create_debian_subpackages", + "description": "Creates all subpackages (debian format)." + }, + { + "const": "termux_create_pacman_subpackages", + "description": "Creates all subpackages (pacman format)." + }, + { + "const": "termux_step_create_debian_package", + "description": "Create *.deb package." + }, + { + "const": "termux_step_create_pacman_package", + "description": "Create *.pkg.tar.xz package." + }, + { + "const": "termux_step_create_pacman_install_hook", + "description": "Convert result of termux_step_create_debscripts to pacman-compatible format." + }, + { + "const": "termux_step_finish_build", + "description": "Notification of finish." + }, + { + "const": "termux_error_exit", + "description": "Function to write error message to stderr and exit." + }, + { + "const": "termux_github_api_get_tag", + "description": "Query GitHub API for: \u2022 latest-release-tag: useful for projects using github's release mechanism. \u2022 newest-tag(sorted by commit date): useful for projects having tags but no releases." + }, + { + "const": "termux_gitlab_api_get_tag", + "description": "same as above, but for gitlab" + }, + { + "const": "termux_repology_api_get_latest_version", + "description": "Query repology api for latest version." + }, + { + "const": "termux_github_auto_update", + "description": "Default update method for packages hosted on github.com. It decides which type of tag to fetch based on TERMUX_PKG_SRCURL." + }, + { + "const": "termux_gitlab_auto_update", + "description": "Default update method for packages hosted on gitlab.com (or host specified by TERMUX_GITLAB_API_HOST). It decides which type of tag to fetch based on TERMUX_PKG_SRCURL." + }, + { + "const": "termux_pkg_upgrade_version", + "description": "Write the latest version and updated checksum, check whether updated package builds properly and then push changes to repo." + }, + { + "const": "termux_pkg_is_update_needed", + "description": "Check whether LATEST_VERSION is greater than TERMUX_PKG_VERSION or not. Called if --skip-version-check was not passed to termux_pkg_upgrade_version. NOTE: You should not call it manually otherwise if TERMUX_PKG_UPDATE_VERSION_REGEXP is used, it won't compare versions extracted from it. Version is extracted by termux_pkg_upgrade_version." + } + ] + } + } +} diff --git a/src/termux_language_server/assets/json/color.map.json b/src/termux_language_server/assets/json/color.map.json new file mode 100644 index 0000000..04144aa --- /dev/null +++ b/src/termux_language_server/assets/json/color.map.json @@ -0,0 +1,104 @@ +{ + "$id": "https://github.com/termux/termux-language-server/blob/main/src/termux_language_server/assets/json/color.map.json", + "$schema": "http://json-schema.org/draft-07/schema#", + "$comment": "Don't edit this file directly! It is generated by `termux-language-server --generate-schema=color.map`.", + "type": "object", + "properties": { + "NORMAL": { + "description": "```sh\nNORMAL = \"normal\"\n```\nDefines color used for some words occuring in other contexts than those below.", + "type": "string" + }, + "BAD": { + "description": "```sh\nBAD = \"red\"\n```\nDefines color used for some words occuring in bad context.", + "type": "string" + }, + "BRACKET": { + "description": "```sh\nBRACKET = \"blue\"\n```\nDefines color used for brackets.", + "type": "string" + }, + "GOOD": { + "description": "```sh\nGOOD = \"green\"\n```\nDefines color used for some words occuring in good context.", + "type": "string" + }, + "HILITE": { + "description": "```sh\nHILITE = \"teal\"\n```\nDefines color used for highlighted words.", + "type": "string" + }, + "INFORM": { + "description": "```sh\nINFORM = \"darkgreen\"\n```\nDefines color used for informational words.", + "type": "string" + }, + "MERGE_LIST_PROGRESS": { + "description": "```sh\nMERGE_LIST_PROGRESS = \"yellow\"\n```\nDefines color used for numbers indicating merge progress.", + "type": "string" + }, + "PKG_BLOCKER": { + "description": "```sh\nPKG_BLOCKER = \"red\"\n```\nDefines color used for unsatisfied blockers.", + "type": "string" + }, + "PKG_BLOCKER_SATISFIED": { + "description": "```sh\nPKG_BLOCKER_SATISFIED = \"teal\"\n```\nDefines color used for satisfied blockers.", + "type": "string" + }, + "PKG_MERGE": { + "description": "```sh\nPKG_MERGE = \"darkgreen\"\n```\nDefines color used for packages planned to be merged.", + "type": "string" + }, + "PKG_MERGE_SYSTEM": { + "description": "```sh\nPKG_MERGE_SYSTEM = \"darkgreen\"\n```\nDefines color used for system packages planned to be merged.", + "type": "string" + }, + "PKG_MERGE_WORLD": { + "description": "```sh\nPKG_MERGE_WORLD = \"green\"\n```\nDefines color used for world packages planned to be merged.", + "type": "string" + }, + "PKG_BINARY_MERGE": { + "description": "```sh\nPKG_BINARY_MERGE = \"purple\"\n```\nDefines color used for packages planned to be merged using a binary package.", + "type": "string" + }, + "PKG_BINARY_MERGE_SYSTEM": { + "description": "```sh\nPKG_BINARY_MERGE_SYSTEM = \"purple\"\n```\nDefines color used for system packages planned to be merged using a binary package.", + "type": "string" + }, + "PKG_BINARY_MERGE_WORLD": { + "description": "```sh\nPKG_BINARY_MERGE_WORLD = \"fuchsia\"\n```\nDefines color used for world packages planned to be merged using a binary package.", + "type": "string" + }, + "PKG_NOMERGE": { + "description": "```sh\nPKG_NOMERGE = \"teal\"\n```\nDefines color used for packages not planned to be merged.", + "type": "string" + }, + "PKG_NOMERGE_SYSTEM": { + "description": "```sh\nPKG_NOMERGE_SYSTEM = \"teal\"\n```\nDefines color used for system packages not planned to be merged.", + "type": "string" + }, + "PKG_NOMERGE_WORLD": { + "description": "```sh\nPKG_NOMERGE_WORLD = \"blue\"\n```\nDefines color used for world packages not planned to be merged.", + "type": "string" + }, + "PKG_UNINSTALL": { + "description": "```sh\nPKG_UNINSTALL = \"red\"\n```\nDefines color used for packages planned to be uninstalled in order to resolve conflicts.", + "type": "string" + }, + "PROMPT_CHOICE_DEFAULT": { + "description": "```sh\nPROMPT_CHOICE_DEFAULT = \"green\"\n```\nDefines color used for the default choice at a prompt.", + "type": "string" + }, + "PROMPT_CHOICE_OTHER": { + "description": "```sh\nPROMPT_CHOICE_OTHER = \"red\"\n```\nDefines color used for a non-default choice at a prompt.", + "type": "string" + }, + "SECURITY_WARN": { + "description": "```sh\nSECURITY_WARN = \"red\"\n```\nDefines color used for security warnings.", + "type": "string" + }, + "UNMERGE_WARN": { + "description": "```sh\nUNMERGE_WARN = \"red\"\n```\nDefines color used for unmerge warnings.", + "type": "string" + }, + "WARN": { + "description": "```sh\nWARN = \"yellow\"\n```\nDefines color used for warnings.", + "type": "string" + } + } +} diff --git a/src/termux_language_server/assets/json/devscripts.conf.json b/src/termux_language_server/assets/json/devscripts.conf.json new file mode 100644 index 0000000..0768e96 --- /dev/null +++ b/src/termux_language_server/assets/json/devscripts.conf.json @@ -0,0 +1,634 @@ +{ + "$id": "https://github.com/termux/termux-language-server/blob/main/src/termux_language_server/assets/json/build.sh.json", + "$schema": "http://json-schema.org/draft-07/schema#", + "$comment": "/etc/devscripts.conf", + "type": "object", + "properties": { + "DEVSCRIPTS_CHECK_DIRNAME_LEVEL": { + "type": "string", + "enum": ["0", "1", "2"], + "default": "1", + "description": "Several programs check the directory name and refuse to function if it does not match the name of the package being worked on. (The details are described in the individual manpages.) These two variables control this behaviour, corresponding to the --check-dirname-level and --check-dirname-regex command line options. The possible values of DEVSCRIPTS_CHECK_DIRNAME_LEVEL are:\n 0 never check the directory name\n 1 check the directory name only if the program has changed directory\n 2 always check the directory name" + }, + "DEVSCRIPTS_CHECK_DIRNAME_REGEX": { + "type": "string", + "format": "regex", + "default": "PACKAGE(-.+)?", + "description": "The variable DEVSCRIPTS_DIRNAME_REGEXP is a Perl regex which defines what is considered a valid directory name for the source package PACKAGE; if it includes a '/', then it must match the full directory path, otherwise it must match the full directory name" + }, + "BTS_OFFLINE": { + "type": "string", + "enum": ["yes", "no"], + "default": "no", + "description": "Default bts show/bugs to run in offline mode?" + }, + "BTS_CACHE": { + "type": "string", + "enum": ["yes", "no"], + "default": "yes", + "description": "Cache all visited bug reports once a cache has been established for the first time?" + }, + "BTS_CACHE_MODE": { + "type": "string", + "enum": ["min", "max", "full"], + "default": "min", + "description": "How much to mirror when caching? The minimal amount (min), the mbox version as well (mbox) or the whole works (full)?" + }, + "BTS_FORCE_REFRESH": { + "type": "string", + "enum": ["yes", "no"], + "default": "no", + "description": "Always refresh the cache, even if nothing's changed?" + }, + "BTS_MAIL_READER": { + "type": "string", + "default": "mutt -f %s", + "description": "How do we read an mbox? This will be split on whitespace, then %s is replaced by the mbox name and %% by a single %." + }, + "BTS_SENDMAIL_COMMAND": { + "type": "string", + "default": "/usr/sbin/sendmail", + "description": "What sendmail command do we use? This will be split on whitespace." + }, + "BTS_ONLY_NEW": { + "type": "string", + "enum": ["yes", "no"], + "default": "no", + "description": "Download only new bugs when caching? If set to yes, don't check for updates in bugs we already have." + }, + "BTS_SMTP_HOST": { + "type": "string", + "default": "reportbug.debian.org", + "description": "Which SMTP host should be used? Note that if both an SMTP host and sendmail command are specified in the configuration file(s), the SMTP host will be used unless overridden by --sendmail on the command line" + }, + "BTS_SMTP_AUTH_USERNAME": { + "type": "string", + "default": "user", + "description": "If the SMTP host specified above requires authentication, the following options may be used to specify the username and password to use. If only a username is provided then the password will be prompted for before sending the e-mail" + }, + "BTS_SMTP_AUTH_PASSWORD": { + "type": "string", + "default": "pass", + "description": "If the SMTP host specified above requires authentication, the following options may be used to specify the username and password to use. If only a username is provided then the password will be prompted for before sending the e-mail" + }, + "BTS_SMTP_HELO": { + "type": "string", + "default": "foo.example.com", + "description": "Specify a HELO to use when connecting to the SMTP host. If not supplied and the file /etc/mailname exists, its contents will be used as the HELO" + }, + "BTS_INCLUDE_RESOLVED": { + "type": "string", + "enum": ["yes", "no"], + "default": "yes", + "description": "Include resolved bugs when caching?" + }, + "BTS_SUPPRESS_ACKS": { + "type": "string", + "enum": ["yes", "no"], + "default": "no", + "description": "Suppress BTS acknowledgment e-mails (ignored by the control bot)" + }, + "BTS_INTERACTIVE": { + "type": "string", + "enum": ["yes", "no"], + "default": "no", + "description": "Allow the generated message to be edited and, if necessary, abandoned before sending it to the control bot?\nIf set to yes, prompt for confirmation / edit / abandonment.\nIf set to force, spawn an editor and then proceed as if set to yes" + }, + "BTS_DEFAULT_CC": { + "type": "string", + "default": "example@example.com", + "description": "Specify a list of e-mail addresses to which a carbon copy of the generated e-mail to the control bot should automatically be sent." + }, + "BTS_SERVER": { + "type": "string", + "default": "https://bugs.debian.org", + "description": "Which debbugs server should be used?" + }, + "DEBCHANGE_PRESERVE": { + "type": "string", + "enum": ["yes", "no"], + "default": "no", + "description": "Preserve the source tree dirname if the upstream version changes?" + }, + "DEBCHANGE_QUERY_BTS": { + "type": "string", + "enum": ["yes", "no"], + "default": "yes", + "description": "Query the BTS when --closes is being used?" + }, + "DEBCHANGE_RELEASE_HEURISTIC": { + "type": "string", + "enum": ["log", "changelog"], + "default": "log", + "description": "Select a heuristic to use to determine whether the package has released. See the debchange man page for details." + }, + "DEBCHANGE_MULTIMAINT": { + "type": "string", + "enum": ["yes", "no"], + "default": "yes", + "description": "Introduce multiple-maintainer markers in changelog sections?" + }, + "DEBCHANGE_MULTIMAINT_MERGE": { + "type": "string", + "enum": ["yes", "no"], + "default": "no", + "description": "When appending to a multiple-maintainer changelog, if there are existing changes made by the current maintainer, should new changelog entries be appended to the existing entries?" + }, + "DEBCHANGE_MAINTTRAILER": { + "type": "string", + "enum": ["yes", "no"], + "default": "yes", + "description": "When appending entries to the changelog, should the trailer line be maintained as-is?" + }, + "DEBCHANGE_TZ": { + "type": "string", + "default": "UTC", + "description": "Use a fixed timezone in changelog entries?" + }, + "DEBCHANGE_LOWER_VERSION_PATTERN": { + "type": "string", + "default": "bpo", + "description": "Allow a new version to be lower than the current package version if the new version matches the specified regular expression" + }, + "DEBCHANGE_AUTO_NMU": { + "type": "string", + "enum": ["yes", "no"], + "default": "yes", + "description": "Attempt to automatically determine whether the current changelog stanza represents an NMU?" + }, + "DEBCHANGE_FORCE_SAVE_ON_RELEASE": { + "type": "string", + "enum": ["yes", "no"], + "default": "yes", + "description": "When --release was used and an editor presented, force the changelog to be explicitly saved in the editor? If this is set to \"no\" then the changes made by --release will be automatically saved." + }, + "DEBCHECKOUT_AUTH_URLS": { + "type": "string", + "default": "", + "description": "List of space-separated pairs REGEXP/REPLACEMENT_TEXT to define custom rules to enable authenticated mode." + }, + "DEBCHECKOUT_SOURCE": { + "type": "string", + "default": "auto", + "description": "For debian-dir-only repositories, also retrieve the source package, unpack it, and move the missing files over." + }, + "DEBCHECKOUT_USER": { + "type": "string", + "default": "", + "description": "Username for authenticated mode, can be overridden with -u|--user." + }, + "DEBCLEAN_CLEANDEBS": { + "type": "string", + "enum": ["yes", "no"], + "default": "no", + "description": "Remove .deb, .changes, .dsc and .upload files?" + }, + "DEBCOMMIT_STRIP_MESSAGE": { + "type": "string", + "enum": ["yes", "no"], + "default": "no", + "description": "Strip a leading \"* \" from commit messages taken from changelogs?" + }, + "DEBCOMMIT_SIGN_TAGS": { + "type": "string", + "enum": ["yes", "no"], + "default": "yes", + "description": "Sign created tags using gnupg?" + }, + "DEBCOMMIT_RELEASE_USE_CHANGELOG": { + "type": "string", + "enum": ["yes", "no"], + "default": "no", + "description": "Take any uncommitted changes in the changelog in to account when determining the commit message for a release?" + }, + "DEBCOMMIT_SIGN_COMMITS": { + "type": "string", + "enum": ["yes", "no"], + "default": "no", + "description": "Sign commits using gnupg?" + }, + "DEBDIFF_DIRS": { + "type": "string", + "enum": ["yes", "no"], + "default": "no", + "description": "Show directory names which appear in the filelist?" + }, + "DEBDIFF_CONTROL": { + "type": "string", + "enum": ["yes", "no"], + "default": "yes", + "description": "Compare control files?" + }, + "DEBDIFF_CONTROLFILES": { + "type": "string", + "default": "control", + "description": "Which control files to compare? A comma-separated list, with possibilities such as postinst, config and so on; ALL means compare all control files." + }, + "DEBDIFF_SHOW_MOVED": { + "type": "string", + "enum": ["yes", "no"], + "default": "no", + "description": "Show files which have moved between .debs?" + }, + "DEBDIFF_WDIFF_OPT": { + "type": "string", + "default": "", + "description": "Option to pass to wdiff" + }, + "DEBDIFF_SHOW_DIFFSTAT": { + "type": "string", + "enum": ["yes", "no"], + "default": "no", + "description": "Include the output of diffstat?" + }, + "DEBDIFF_WDIFF_SOURCE_CONTROL": { + "type": "string", + "enum": ["yes", "no"], + "default": "no", + "description": "Compare control files in source packages using wdiff?" + }, + "DEBDIFF_AUTO_VER_SORT": { + "type": "string", + "enum": ["yes", "no"], + "default": "no", + "description": "Always compare package in version order, rather than the order specified on the command line?" + }, + "DEBDIFF_UNPACK_TARBALLS": { + "type": "string", + "enum": ["yes", "no"], + "default": "yes", + "description": "Unpack tarballs found in the top level source directory." + }, + "DEBDIFF_APPLY_PATCHES": { + "type": "string", + "enum": ["yes", "no"], + "default": "no", + "description": "Apply patches when comparing 3.0 (quilt)-format packages" + }, + "DEBRELEASE_UPLOADER": { + "type": "string", + "enum": ["dupload", "dput"], + "default": "dupload", + "description": "This specifies which uploader program to use. As of devscripts 2.22.1ubuntu1 the recognised values are \"dupload\" (default) and \"dput\". Check the debrelease(1) manpage for any recent changes to this variable" + }, + "DEBRELEASE_DEBS_DIR": { + "type": "string", + "default": "..", + "description": "This specifies the directory, relative to the top of the source tree, in which the .changes and .debs files are to be found. Note that this also affects debc and debi." + }, + "DEBSIGN_ALWAYS_RESIGN": { + "type": "string", + "enum": ["yes", "no"], + "default": "no", + "description": "Always re-sign files even if they are already signed, without prompting." + }, + "DEBSIGN_PROGRAM": { + "type": "string", + "default": "", + "description": "Which signing program to use? gpg and pgp are the usual values; the default is determined as described in the manpage. Corresponds to -p option" + }, + "DEBSIGN_SIGNLIKE": { + "type": "string", + "default": "", + "description": "How the signing program works; must be either gpg or pgp as of devscripts version 2.22.1ubuntu1. The default is described in the manpage. Corresponds to -sgpg and -spgp." + }, + "DEBSIGN_MAINT": { + "type": "string", + "default": "", + "description": "Maintainer name (only used to determine GPG keyid; -m option)" + }, + "DEBSIGN_KEYID": { + "type": "string", + "default": "", + "description": "GPG keyid to use (-k option)" + }, + "DEBSNAP_DESTDIR": { + "type": "string", + "default": "", + "description": "Where to put the directory named -/ default: source-$package_name if unset" + }, + "DEBSNAP_VERBOSE": { + "type": "string", + "enum": ["yes", "no"], + "default": "no", + "description": "Verbosely show messages" + }, + "DEBSNAP_BASE_URL": { + "type": "string", + "default": "https://snapshot.debian.org", + "description": "The base URL of the archive to download from" + }, + "DEBSNAP_CLEAN_REGEX": { + "type": "string", + "format": "regex", + "default": "s@\\([^/]*\\)/[^/]*/\\(.*\\)@\\1/\\2@", + "description": "A sed regexp to transform pool//f/foo into the desired layout default: make the directory from pool//f/foo to pool/f/foo" + }, + "DEBSNAP_SOURCES_GZ_PATH": { + "type": "string", + "default": "source/Sources.gz", + "description": "Where the Sources.gz lives, subdirectory of DEBSNAP_BASE_URL//" + }, + "DEBUILD_PRESERVE_ENV": { + "type": "string", + "enum": ["yes", "no"], + "default": "no", + "description": "Do we preserve the whole environment except for PATH?" + }, + "DEBUILD_PRESERVE_ENVVARS": { + "type": "string", + "default": "", + "description": "Are there any environment variables we should preserve? This should be a comma-separated list." + }, + "DEBUILD_TGZ_CHECK": { + "type": "string", + "enum": ["yes", "no"], + "default": "yes", + "description": "Do we check for the existence of the .orig.tar.gz before calling dpkg-buildpackage?" + }, + "DEBUILD_ROOTCMD": { + "type": "string", + "default": "fakeroot", + "description": "Corresponds to the dpkg-buildpackage -r option." + }, + "DEBUILD_DPKG_BUILDPACKAGE_OPTS": { + "type": "string", + "default": "", + "description": "Extra options given to dpkg-buildpackage before any command-line options specified. Single options containing spaces should be quoted, for example \"-m'Julian Gilbey ' -us -uc\" If this contains a -r, -d or -D option, this will also be recognised when running debuild binary|binary-arch|..." + }, + "DEBUILD_LINTIAN": { + "type": "string", + "enum": ["yes", "no"], + "default": "yes", + "description": "Do we run lintian at the end of a full run?" + }, + "DEBUILD_LINTIAN_OPTS": { + "type": "string", + "default": "", + "description": "Extra options given to lintian before any command-line options specified." + }, + "DEBUILD_PREPEND_PATH": { + "type": "string", + "default": "/usr/lib/ccache", + "description": "Colon-separated list of options to be added to the beginning of PATH once it has been sanitised" + }, + "DEBUILD_SIGNING_USERNAME": { + "type": "string", + "default": "user@host", + "description": "Credentials to pass to debrsign when signing dsc / changes files Setting this option to a non-blank string implies using debrsign" + }, + "DEBUILD_DPKG_BUILDPACKAGE_HOOK": { + "type": "string", + "default": "", + "description": "Hooks; see the manpage for details of these" + }, + "DEBUILD_CLEAN_HOOK": { + "type": "string", + "default": "", + "description": "Hooks; see the manpage for details of these" + }, + "DEBUILD_DPKG_SOURCE_HOOK": { + "type": "string", + "default": "", + "description": "Hooks; see the manpage for details of these" + }, + "DEBUILD_BUILD_HOOK": { + "type": "string", + "default": "", + "description": "Hooks; see the manpage for details of these" + }, + "DEBUILD_BINARY_HOOK": { + "type": "string", + "default": "", + "description": "Hooks; see the manpage for details of these" + }, + "DEBUILD_FINAL_CLEAN_HOOK": { + "type": "string", + "default": "", + "description": "Hooks; see the manpage for details of these" + }, + "DEBUILD_LINTIAN_HOOK": { + "type": "string", + "default": "", + "description": "Hooks; see the manpage for details of these" + }, + "DEBUILD_SIGNING_HOOK": { + "type": "string", + "default": "", + "description": "Hooks; see the manpage for details of these" + }, + "DEBUILD_POST_DPKG_BUILDPACKAGE_HOOK": { + "type": "string", + "default": "", + "description": "Hooks; see the manpage for details of these" + }, + "DGET_PATH": { + "type": "string", + "default": "", + "description": "Extra directories to search for files in addition to /var/cache/apt/archives. This is a colon-separated list of directories." + }, + "DGET_UNPACK": { + "type": "string", + "default": "yes", + "enum": ["yes", "no"], + "description": "Unpack downloaded source packages" + }, + "DGET_VERIFY": { + "type": "string", + "default": "yes", + "enum": ["yes", "no"], + "description": "Verify source package signatures using dscverify" + }, + "DPKG_DEPCHECK_OPTIONS": { + "type": "string", + "default": "", + "description": "Extra options given to dpkg-depcheck before any command-line options specified. For example: \"-b --features=-catch-alternatives\"" + }, + "DPKGSIG_KEYID": { + "type": "string", + "default": "", + "description": "This key ID takes precedence over the rest" + }, + "DPKGSIG_SIGN_CHANGES": { + "type": "string", + "default": "auto", + "description": "Do we sign the .changes and .dsc files? See the manpage for more info. Valid options are no, auto, yes, full and force_full." + }, + "DPKGSIG_CACHE_PASS": { + "type": "string", + "default": "auto", + "description": "Do we cache the gpg passphrase by default? This can be dangerous!" + }, + "DSCVERIFY_KEYRINGS": { + "type": "string", + "default": "", + "description": "A colon separated list of extra keyrings to read." + }, + "GREP_EXCUSES_MAINTAINER": { + "type": "string", + "default": "", + "description": "This specifies a default maintainer name or email to hunt for" + }, + "GREP_EXCUSES_FTP_MASTER": { + "type": "string", + "default": "", + "description": "Is this running on ftp-master.debian.org? If so, we use the local excuses file" + }, + "MKBUILDDEPS_TOOL": { + "type": "string", + "default": "/usr/bin/apt-get --no-install-recommends", + "description": "Which tool to use for installing build depends?" + }, + "MKBUILDDEPS_REMOVE_AFTER_INSTALL": { + "type": "string", + "enum": ["yes", "no"], + "default": "yes", + "description": "Remove package files after install?" + }, + "MKBUILDDEPS_ROOTCMD": { + "type": "string", + "default": "", + "description": "Tool used to gain root privileges to install the deb" + }, + "NMUDIFF_DELAY": { + "type": "string", + "default": "3", + "pattern": "\\d+", + "description": "Number of days to indicate that an NMU upload has been delayed by using the DELAYED upload queue. 0 indicates no delay. Defaults to \"XX\" which adds a placeholder to the e-mail." + }, + "NMUDIFF_MUTT": { + "type": "string", + "enum": ["yes", "no"], + "default": "yes", + "description": "Should we use mutt to edit and send the message or just a plain old editor?" + }, + "NMUDIFF_NEWREPORT": { + "type": "string", + "default": "maybe", + "enum": ["yes", "no", "maybe"], + "description": "Should we always submit a new report (yes), always send to the bugs which are being closed (no), or send to the bug being closed if there is only one of them, otherwise send a new report (maybe)?" + }, + "PLOTCHANGELOG_OPTIONS": { + "type": "string", + "default": "", + "description": "Command line options to use (space separated). None of the options should contain spaces. Use the PLOTCHANGELOG_GNUPLOT variable for the --gnuplot command line option." + }, + "PLOTCHANGELOG_GNUPLOT": { + "type": "string", + "default": "", + "description": "Here we can give gnuplot options. Any command line --gnuplot commands will be appended to these." + }, + "PTS_UNTIL": { + "type": "string", + "default": "now + 30 days", + "description": "How long will we subscribe for by default? The default is 30 days. Setting this to 'forever' means that no unsubscription request will be scheduled." + }, + "RMADISON_URL_MAP_EXAMPLE": { + "type": "string", + "default": "http://example.com/madison.cgi", + "description": "Add a custom URL to the default list of shorthands so one can use it with -u without having to specify the full URL" + }, + "RMADISON_DEFAULT_URL": { + "type": "string", + "default": "debian", + "description": "Default URL to use if none is specified on the command line." + }, + "RMADISON_ARCHITECTURE": { + "type": "string", + "default": "source,i386,amd64,all", + "description": "Default architecture to use if none is specified on the command line. use --architecture='*' to run an unrestricted query when RMADISON_ARCHITECTURE is set." + }, + "USCAN_DOWNLOAD": { + "type": "string", + "default": "yes", + "enum": ["yes", "no"], + "description": "Should we download newer upstream files we come across?" + }, + "USCAN_PASV": { + "type": "string", + "default": "default", + "enum": ["yes", "no", "default"], + "description": "Should we use FTP PASV mode for ftp:// links? 'default' means let Net::FTP(3) make the choice (primarily based on the FTP_PASSIVE environment variable); 'yes' and 'no' override the default" + }, + "USCAN_SYMLINK": { + "type": "string", + "default": "yes", + "enum": ["yes", "no", "rename", "symlink"], + "description": "Should we create a symlink from the downloaded tar.gz file to pkg_version.orig.tar.gz, rename it like this or do nothing? Options are 'symlink'/'yes', 'rename' or 'no'" + }, + "USCAN_DEHS_OUTPUT": { + "type": "string", + "default": "no", + "enum": ["yes", "no"], + "description": "Should we use DEHS style output (XML format)?" + }, + "USCAN_VERBOSE": { + "type": "string", + "default": "no", + "enum": ["yes", "no"], + "description": "Should we give verbose output?" + }, + "USCAN_USER_AGENT": { + "type": "string", + "default": "Debian uscan X.Y.Z", + "description": "What user agent string should we send with requests? (Default is 'Debian uscan X.Y.Z')" + }, + "USCAN_DESTDIR": { + "type": "string", + "default": "..", + "description": "Where should downloaded files be placed?" + }, + "USCAN_REPACK": { + "type": "string", + "default": "no", + "enum": ["yes", "no"], + "description": "Automatically repack bzipped tar or zip archives to gzipped tars?" + }, + "USCAN_EXCLUSION": { + "type": "string", + "default": "yes", + "enum": ["yes", "no"], + "description": "Use the Files-Excluded field in debian/copyright to determine whether the orig tarball needs to be repacked to remove non-DFSG content?" + }, + "UUPDATE_PRISTINE": { + "type": "string", + "default": "yes", + "enum": ["yes", "no"], + "description": "Should we retain the pristine upstream source wherever possible?" + }, + "UUPDATE_SYMLINK_ORIG": { + "type": "string", + "default": "yes", + "enum": ["yes", "no"], + "description": "Should we symlink the .orig.tar.gz file to its new name or copy it instead? yes=symlink, no=copy" + }, + "UUPDATE_ROOTCMD": { + "type": "string", + "default": "", + "description": "Corresponds to the dpkg-buildpackage -r option and debuild DEBUILD_ROOTCMD option. Normally, this can be left empty, as then the debuild setting will be used." + }, + "WHOUPLOADS_DATE": { + "type": "string", + "default": "no", + "enum": ["yes", "no"], + "description": "Display the date of the upload?" + }, + "WHOUPLOADS_MAXUPLOADS": { + "type": "string", + "default": "3", + "pattern": "\\d+", + "description": "Maximum number of uploads to display per package" + }, + "WHOUPLOADS_KEYRINGS": { + "type": "string", + "default": "/usr/share/keyrings/debian-keyring.gpg:/usr/share/keyrings/debian-keyring.pgp:/usr/share/keyrings/debian-maintainers.gpg:/usr/share/keyrings/debian-nonupload.gpg", + "description": "Colon-separated list of keyrings to examine by default" + } + }, + "patternProperties": { + "DEBUILD_SET_ENVVAR_.*": { + "type": "string", + "description": "How to set a preserved environment variable" + } + } +} diff --git a/src/termux_language_server/assets/json/ebuild.json b/src/termux_language_server/assets/json/ebuild.json new file mode 100644 index 0000000..2a9a460 --- /dev/null +++ b/src/termux_language_server/assets/json/ebuild.json @@ -0,0 +1,545 @@ +{ + "$id": "https://github.com/termux/termux-language-server/blob/main/src/termux_language_server/assets/json/ebuild.json", + "$schema": "http://json-schema.org/draft-07/schema#", + "$comment": "Don't edit this file directly! It is generated by `termux-language-server --generate-schema=ebuild`.", + "type": "object", + "properties": { + "ARCH": { + "description": "This variable contains the official Gentoo-specific acronym for the current architecture of the running system. For an authoritative list please review /var/db/repos/gentoo/profiles/arch.list.", + "type": "string" + }, + "P": { + "description": "This variable contains the package name without the ebuild revision. This variable must NEVER be modified.", + "type": "string" + }, + "PN": { + "description": "Contains the name of the script without the version number.", + "type": "string" + }, + "PV": { + "description": "Contains the version number without the revision.", + "type": "string" + }, + "PR": { + "description": "Contains the revision number or 'r0' if no revision number exists.", + "type": "string" + }, + "PVR": { + "description": "Contains the version number with the revision (if any).", + "type": "string" + }, + "PF": { + "description": "Contains the full package name PN-PVR", + "type": "string" + }, + "CATEGORY": { + "description": "Contains the package category name.", + "type": "string" + }, + "A": { + "description": "Contains all source files required for the package. This variable must not be defined. It is autogenerated from the SRC_URI variable.", + "type": "string" + }, + "WORKDIR": { + "description": "```sh\nWORKDIR = \"${PORTAGE_TMPDIR}/portage/${CATEGORY}/${PF}/work\"\n```\nContains the path to the package build root. Do not modify this variable.", + "type": "string" + }, + "FILESDIR": { + "description": "```sh\nFILESDIR = \"${PORTAGE_TMPDIR}/${CATEGORY}/${PF}/files\"\n```\nContains the path to the directory in which package-specific auxiliary files are located. Do not modify this variable.", + "type": "string" + }, + "EBUILD_PHASE": { + "description": "Contains the abreviated name of the phase function that is currently executing, such as \"setup\", \"unpack\", \"compile\", or \"preinst\".", + "type": "string" + }, + "EBUILD_PHASE_FUNC": { + "description": "Beginning with EAPI 5, contains the full name of the phase function that is currently executing, such as \"pkg_setup\", \"src_unpack\", \"src_compile\", or \"pkg_preinst\".", + "type": "string" + }, + "EPREFIX": { + "description": "Beginning with EAPI 3, contains the offset that this Portage was configured for during installation. The offset is sometimes necessary in an ebuild or eclass, and is available in such cases as ${EPREFIX}. EPREFIX does not contain a trailing slash, therefore an absent offset is represented by the empty string. Do not modify this variable.", + "type": "string" + }, + "S": { + "description": "```sh\nS = \"${WORKDIR}/${P}\"\n```\nContains the path to the temporary build directory. This variable is used by the functions src_compile and src_install. Both are executed with S as the current directory. This variable may be modified to match the extraction directory of a tarball for the package.", + "type": "string" + }, + "T": { + "description": "```sh\nT = \"${PORTAGE_TMPDIR}/portage/${CATEGORY}/${PF}/temp\"\n```\nContains the path to a temporary directory. You may use this for whatever you like.", + "type": "string" + }, + "D": { + "description": "```sh\nD = \"${PORTAGE_TMPDIR}/portage/${CATEGORY}/${PF}/image/\"\n```\nContains the path to the temporary install directory. Every write operation that does not involve the helper tools and functions (found below) should be prefixed with ${D}. Beginning with EAPI 3, the offset prefix often needs to be taken into account here, for which the variable ${ED} is provided (see below). Note that with EAPI 7, any trailing slash contained in this path will be automatically removed for ease of concatenating paths within ebuilds. Do not modify this variable.", + "type": "string" + }, + "ED": { + "description": "```sh\nED = \"${PORTAGE_TMPDIR}/portage/${CATEGORY}/${PF}/image/${EPREFIX}/\"\n```\nBeginning with EAPI 3, contains the path \"${D%/}${EPREFIX}/\" for convenience purposes. For EAPI values prior to EAPI 3 which do not support ED, helpers use D where they would otherwise use ED. Note that with EAPI 7, any trailing slash contained in this path will be automatically removed for ease of concatenating paths within ebuilds. Do not modify this variable.", + "type": "string" + }, + "MERGE_TYPE": { + "description": "Beginning with EAPI 4, the MERGE_TYPE variable can be used to query the current merge type. This variable will contain one of the following possible values: Value Meaning binary previously-built which is scheduled for merge buildonly source-build which is not scheduled for merge source source-build which is scheduled for merge", + "type": "string" + }, + "PROVIDES_EXCLUDE": { + "description": "```sh\nPROVIDES_EXCLUDE = [space delimited list of fnmatch patterns]\n```\nSonames and file paths matched by these fnmatch patterns will be excluded during genertion of PROVIDES metadata (see portage(5)). Patterns are delimited by whitespace, and it is possible to create patterns containing quoted whitespace.", + "type": "string" + }, + "PORTAGE_LOG_FILE": { + "description": "Contains the path of the build log. If PORTAGE_LOGDIR variable is unset then PORTAGE_LOG_FILE=\"${T}/build.log\".", + "type": "string" + }, + "PORTAGE_SOCKS5_PROXY": { + "description": "Contains the UNIX socket path to SOCKSv5 proxy providing host network access. Available only when running inside network-sandbox and a proxy is available (see network-sandbox in make.conf(5)).", + "type": "string" + }, + "REPLACED_BY_VERSION": { + "description": "Beginning with EAPI 4, the REPLACED_BY_VERSION variable can be used in pkg_prerm and pkg_postrm to query the package version that is replacing the current package. If there is no replacement package, the variable will be empty, otherwise it will contain a single version number.", + "type": "string" + }, + "REPLACING_VERSIONS": { + "description": "Beginning with EAPI 4, the REPLACING_VERSIONS variable can be used in pkg_pretend, pkg_setup, pkg_preinst and pkg_postinst to query the package version(s) that the current package is replacing. If there are no packages to replace, the variable will be empty, otherwise it will contain a space-separated list of version numbers corresponding to the package version(s) being replaced. Typically, this variable will not contain more than one version, but according to PMS it can contain more.", + "type": "string" + }, + "REQUIRES_EXCLUDE": { + "description": "```sh\nREQUIRES_EXCLUDE = [space delimited list of fnmatch patterns]\n```\nSonames and file paths matched by these fnmatch patterns will be excluded during generation of REQUIRES metadata (see portage(5)). Patterns are delimited by whitespace, and it is possible to create patterns containing quoted whitespace.", + "type": "string" + }, + "ROOT": { + "description": "```sh\nROOT = \"/\"\n```\nPlease note an important recent change regarding the ROOT variable -- in EAPI 7 ebuilds, this variable will default to \"\" rather than the traditional \"/\" within ebuilds when pointing to the root filesystem, and when set to a non-root path this variable will never contain a trailing slash. This has the added convenience of eliminating the need to specify \"${ROOT%/}\" when concatenating paths, making the use of ROOT more elegant. This applies to the variables EROOT, D and ED as well. Please make note that this will mean that ebuilds must use different logic in conditionals to determine if they are installing to the root filesystem -- use [[ \"$ROOT\" == \"\" ]] instead of [[ \"$ROOT\" == \"/\" ]].", + "type": "string" + }, + "EROOT": { + "description": "```sh\nEROOT = \"${ROOT%/}${EPREFIX}/\"\n```\nBeginning with EAPI 3, contains \"${ROOT%/}${EPREFIX}/\" for convenience purposes. Do not modify this variable. Also see the important note regarding ROOT with EAPI 7, above. As with ROOT, EROOT will be defined as \"\" when set to the root filesystem and never have a trailing slash within an ebuild.", + "type": "string" + }, + "BROOT": { + "description": "```sh\nBROOT = \"${EPREFIX}\"\n```\nBeginning with EAPI 7, the absolute path to the root directory containing build dependencies satisfied by BDEPEND, typically executable build tools. This includes any applicable offset prefix. Do not modify this variable.", + "type": "string" + }, + "DESCRIPTION": { + "description": "```sh\nDESCRIPTION = \"A happy little package\"\n```\nShould contain a short description of the package.", + "type": "string" + }, + "EAPI": { + "description": "```sh\nEAPI = \"0\"\n```\nDefines the ebuild API version to which this package conforms. If not defined then it defaults to \"0\". If portage does not recognize the EAPI value then it will mask the package and refuse to perform any operations with it since this means that a newer version of portage needs to be installed first. For maximum backward compatiblity, a package should conform to the lowest possible EAPI. Note that anyone who uses the ebuild(1) command with this package will be required to have a version of portage that recognizes the EAPI to which this package conforms.", + "type": "string" + }, + "SRC_URI": { + "description": "```sh\nSRC_URI = \"https://example.com/path/${P}.tar.gz\"\n```\nContains a list of URIs for the required source files. It can contain multiple URIs for a single source file. The list is processed in order if the file was not found on any of the GENTOO_MIRRORS. Beginning with EAPI 2, the output file name of a given URI may be customized with a \"->\" operator on the right hand side, followed by the desired output file name. All tokens, including the operator and output file name, should be separated by whitespace.", + "type": "string" + }, + "HOMEPAGE": { + "description": "```sh\nHOMEPAGE = \"https://example.com/\"\n```\nShould contain a list of URIs for the sources main sites and other further package dependent information.", + "type": "string" + }, + "KEYWORDS": { + "description": "```sh\nKEYWORDS = [-~][x86,ppc,sparc,mips,alpha,arm,hppa,...]\n```\n", + "type": "string" + }, + "SLOT": { + "description": "This sets the SLOT for packages that may need to have multiple versions co-exist. By default you should set SLOT=\"0\". If you are unsure, then do not fiddle with this until you seek some guidance from some guru. This value should NEVER be left undefined.", + "type": "string" + }, + "LICENSE": { + "description": "This should be a space delimited list of licenses that the package falls under. This _must_ be set to a matching license in /var/db/repos/gentoo/licenses/. If the license does not exist in the repository yet, you must add it first.", + "type": "string", + "pattern": "(0BSD|2dboy-EULA|9wm|Activision|aczoom|adom|AFL-2.1|AFL-3.0|AGPL-3|AGPL-3+|AIFFWriter.m|Aladdin|Alasir|all-rights-reserved|Allegro|alternate|AMD-GPU-PRO-EULA|amiwm|AMPAS|android|AnyDesk-TOS|Apache-1.0|Apache-1.1|Apache-2.0|Apache-2.0-with-LLVM-exceptions|APL-1.0|APSL-2|aquafont|Arkkra|Arphic|Artistic|Artistic-2|Aseprite-EULA|astrolog|Atmel|Autodesk|Avago|AVASYS|AvP|BAEKMUK|bakoma|bass|battalion|baudline|BEER-WARE|bertini|bestcrypt|bh-luxi|BigelowHolmes|BitstreamCyberbit|BitstreamVera|BL|blackshades|blat|boehm-gc|bonnie|Boost-1.0|Broadcom|broadcom_bcm20702|Brother|BSD|BSD-1|BSD-2|BSD-2-with-patent|BSD-4|BSD-with-attribution|BSD-with-disclosure|buddy|bufexplorer.vim|BUILDLIC|bungie-marathon|BUSL-1.1|BZIP2|C3|Canon-IJ|Canon-UFR-II|CAOSL|CAPYBARA-EULA|CARA|CC-BY-1.0|CC-BY-2.0|CC-BY-2.5|CC-BY-3.0|CC-BY-4.0|CC-BY-NC-4.0|CC-BY-NC-ND-2.0|CC-BY-NC-ND-2.5|CC-BY-NC-ND-3.0|CC-BY-NC-ND-4.0|CC-BY-NC-SA-1.0|CC-BY-NC-SA-2.5|CC-BY-NC-SA-3.0|CC-BY-NC-SA-4.0|CC-BY-ND-3.0|CC-BY-ND-4.0|CC-BY-SA-1.0|CC-BY-SA-2.0|CC-BY-SA-2.5|CC-BY-SA-3.0|CC-BY-SA-4.0|CC-PD|CC-SA-1.0|CC-Sampling-Plus-1.0|CC0-1.0|CDDL|CDDL-1.1|CDDL-Schily|CDF|CeCILL-2|CeCILL-B|CeCILL-C|Cenon|charm|ChexQuest3|circlemud|Clarified-Artistic|Clear-BSD|clustalw|CNRI|Cockos|Cockroach|codehaus-classworlds|Coherent-Graphics|coldspringharbor|colt|comi|CPAL-1.0|CPL-0.5|CPL-1.0|CPOL|crafty|CROSSOVER-3|Crypt-IDEA|CSL-2.0|curl|DCC|Dell-EULA|DES|descent-data|dgen-sdl|Digium|docbook|dom4j|DOOM-COLLECTORS-EDITION|drascula|Dreamweb|dropbox|DUKE3D|DUMB-0.9.3|DXX-Rebirth|EAPL|ECL-2.0|Elastic|Elastic-2.0|ElementTree|Elm|Emacs|EPL-1.0|EPL-2.0|EPSON|ErlPL-1.1|eschalon-book-1-demo|eternal_lands|ETQW|EUPL-1.1|EUPL-1.2|exljbris-free|Exolab|f.lux|FAH-EULA-2014|FAH-special-permission|fairuse|fasta|FastCGI|FDL-1.1|FDL-1.1+|FDL-1.2|FDL-1.2+|FDL-1.3|FDL-1.3+|feh|FESTIVAL|File-MMagic|finchtv|FIPL-1.0|Flashpix|FLEX|flexmock|Flightradar24|FLTK|fmdrv|FoilTeX|fping|FraunhoferFDK|Free-Art-1.2|Free-Art-1.3|free-noncomm|freedist|freetts|frozenbyte-eula|FSFAP|FTDI|FTL|FVWM|galaxyhack|Gameplay-Group-EULA|gcc-runtime-library-exception-3.1|gd|geant4|geekbench|genymotion|Geogebra|GIMPS|Glulxe|gmap|gnuplot|GOG-EULA|google-chrome|GPL-1|GPL-1+|GPL-2|GPL-2+|GPL-2+-with-eCos-exception-2|GPL-2+-with-openssl-exception|GPL-2+-with-Pyinstaller-Bootloader-exception|GPL-2-with-classpath-exception|GPL-2-with-exceptions|GPL-2-with-font-exception|GPL-2-with-linking-exception|GPL-2-with-MySQL-FLOSS-exception|GPL-3|GPL-3+|GPL-3+-with-autoconf-exception|GPL-3+-with-font-exception|GPL-3-with-font-exception|GPL-3-with-openssl-exception|grass-ipafonts|GregoryRubin|gsm|gSOAP|gSOAP-1.3b|guild|HappyBunny|Hauppauge-Firmware|HIDAPI|HoMM2-Demo|hp-proliant-essentials|hpe|HPL|hplip-plugin|HPND|HRP|HSL|HTML-Tidy|Hugo|hylafaxplus|HyperSpec|iASL|IBM|icaclient|icu|IDEA|IDEA_Academic|IDEA_Classroom|IDEA_OpenSource|IDEA_Personal|IDPL|IJG|imagemagick|Info-ZIP|Inform|inmon-sflow|inner-net|Intel-SDP|intel-ucode|Interbase-1.0|Introversion|ipadic|IPAfont|ipw2100-fw|ipw2200-fw|ISC|Ispell|ISSL|ITS4|IUPAC-InChi|jardinains|JasPer2.0|JDOM|JetBrains-business|JetBrains-classroom|JetBrains-educational|JetBrains-individual|jfontain|JOVE|JoyPixels|JPRS|JSON|julius|Kermit|Khronos-CLHPP|knights-demo|Kryoflux-MAME|kyocera-mita-ppds|LA_OPT_BASE_LICENSE|lablgtk-examples|LambdaMOO|LaTeX-Calendar|lcc|LDP-1|LDP-1a|Legends|levee|Lexmark-EU2-0111|LGPL-2|LGPL-2+|LGPL-2-with-linking-exception|LGPL-2.1|LGPL-2.1+|LGPL-2.1-with-linking-exception|LGPL-3|LGPL-3+|LGPL-3-with-linking-exception|LGrind-Jacobson|lha|libgcc|LIBGLOSS|libmng|libpng|libpng2|libstdc++|libtiff|LICENSE-BITSTREAM|linux-fw-redistributable|LLGPL-2.1|LogMeIn|LOKI-EULA|LOTW|LPL-1.02|LPPL-1.0|LPPL-1.2|LPPL-1.3|LPPL-1.3a|LPPL-1.3c|LSI|LSI-tw_cli|lsof|lure|mac|MagentaMgOpen|MAJESTY-DEMO|MakeMKV-EULA|man-pages|man-pages-posix-2013|mapm|marginalhacks|Markwardt|master-pdf-editor|matplotlib|MaxMind2|MBROLA-VOICES|mekanix|Mellanox-AS-IS|metapackage|MicroChip-PK2|MicroChip-SDCC|Microsemi|microsoft-azurevpnclient|microsoft-edge|Microsoft-vscode|Midisport|MILO|Mini-XML|minpack|MirOS|MIT|MIT-0|MIT-with-advertising|mm|mmix|modeller|Mojang|MOLDEN|molmol|Moria|Mozart|MPEG-4|mpg123-el|mpich2|MPL-1.0|MPL-1.1|MPL-2.0|mplus-fonts|Ms-PL|Ms-RL|MSMS|MSttfEULA|MTA-0.5|myspell-en_CA-KevinAtkinson|myspell-ru_RU-AlexanderLebedev|namd|NCSA-AMD|NCSA-HDF|netcat|nethack|netlogo|netperf|NEWLIB|ngrep|no-source-code|Nokia-Qt-LGPL-Exception-1.1|nomachine|NOSA|NPL-1.1|NPSL-0.95|NVIDIA-CUDA|NVIDIA-cuDNN|NVIDIA-NVLM|NVIDIA-r1|NVIDIA-r2|NVIDIA-SDK|OAL-1.0.1|OASIS-Open|OFFIS|OFL-1.0|OFL-1.1|OGL-1.0a|Old-MIT|olivia|Ookla|Open-CASCADE-LGPL-2.1-Exception-1.0|openafs-krb5-a|openknights|OPENLDAP|openssl|Openwall|OPERA-2018|OPL|OSGi-Specification-2.0|OSL-1.1|OSL-2.0|OSL-2.1|OTN|otter|PAK128.German|PAPERS-PLEASE|par|PassMark-EULA|PCRE|PEL|penguzzle|perforce|PerlDL|photopc|PHP-2.02|PHP-3|PHP-3.01|phrack|PICO-8|pkcrack|PLAN9|Plex|pngcrush|pngnq|POSTGRESQL|Primate-Plunge|Princeton|procheck|prog-express|PSF-2|PSF-2.4|PSTT|psutils|public-domain|PUEL-11|PyCharm|PyCharm_Academic|PyCharm_Classroom|PyCharm_OpenSource|PyCharm_Preview|PYTHON|Q2EULA|Q3AEULA-20000111|qlogic-fibre-channel-firmware|QPL-1.0|quake1-demodata|quake1-killer|quake1-teamfortress|quake1-textures|quake2-demodata|QUAKE4|queen|qwt|RAR|raspberrypi-videocore-bin|rc|rdisc|regexp-UofT|repoze|Resounding|richardson|rpi-eeprom|RSA|RtMidi|Ruby|Ruby-BSD|rwpng|sash|scanlogd|sdlsasteroids|SDRplay|Sendmail|Sendmail-Open-Source|SFI-SCLA|sfpg|SGI-B-2.0|SGMLUG|shmux|shorten|SIP|SIR-TECH|Skype-TOS|Sleepycat|SMAIL|Snd|Snes9x|SOFA|Soltys|SpeedTouch-USB-Firmware|Spencer-99|spideroak|Spotify|SPS|SSLeay|SSPL-1|Stanford|stardock-images|Steam|STRIDE|Stuffit|Sublime|sun-bcla-j2me|sun-bcla-jai|sun-bcla-jsapi|Sun-BSD-no-nuclear-2005|supermicro|SURF|sus4-copyright|swiss-prot|symlinks|Sympow-BSD|Synology|szip|tablelist|TADS2|TADS3|tanuki-community|tarsnap|tcltk|tcp_wrappers_license|teamspeak3|teamspeak5|TeamViewer|Tenable-Master-Agreement|TeX|TeX-other-free|Texinfo-manual|TextMate-bundle|the-Click-license|THINKTANKS|TIK|Time-Format|Time-modules|timescale|Tinker|tkMOO|tm-align|torque-2.5|Toyoda|Transmission-OpenSSL-exception|trf|trio|truecrypt-3.0|tsm|ttf2pt1|ubiquiti|UbuntuFontLicense-1.0|UCAR-BSD|UCAR-Unidata|unafold|unicode|Unicode-3.0|Unicode-DFS-2016|Unlicense|unRAR|UoI-NCSA|UPL-1.0|UPX-exception|urbanterror-4.2-maps|URI|URT|ut2003|ut2003-demo|VGBA|vim|vim.org|Vivaldi|vlgothic|vmd|VOSTROM|VTK|W3C|w3m|Watcom-1.0|WidePix|wm2|WolframCDFPlayer|worklog-assistant|worldofpadman|WPS-EULA|WTFPL-2|wxWinFDL-3|wxWinLL-3|wxWinLL-3.1|xbatt|xbattle|xboing|XC|Xdebug|xearth|XEphem|xgraph|XMAME|xmlformat|xref.lisp|xrick|xtrs|xv|Yacht-Club-Games-EULA|YDSLA|Zend-2.0|zi-labone|ZLIB|ZPL|ZSH)(( |\\n)(0BSD|2dboy-EULA|9wm|Activision|aczoom|adom|AFL-2.1|AFL-3.0|AGPL-3|AGPL-3+|AIFFWriter.m|Aladdin|Alasir|all-rights-reserved|Allegro|alternate|AMD-GPU-PRO-EULA|amiwm|AMPAS|android|AnyDesk-TOS|Apache-1.0|Apache-1.1|Apache-2.0|Apache-2.0-with-LLVM-exceptions|APL-1.0|APSL-2|aquafont|Arkkra|Arphic|Artistic|Artistic-2|Aseprite-EULA|astrolog|Atmel|Autodesk|Avago|AVASYS|AvP|BAEKMUK|bakoma|bass|battalion|baudline|BEER-WARE|bertini|bestcrypt|bh-luxi|BigelowHolmes|BitstreamCyberbit|BitstreamVera|BL|blackshades|blat|boehm-gc|bonnie|Boost-1.0|Broadcom|broadcom_bcm20702|Brother|BSD|BSD-1|BSD-2|BSD-2-with-patent|BSD-4|BSD-with-attribution|BSD-with-disclosure|buddy|bufexplorer.vim|BUILDLIC|bungie-marathon|BUSL-1.1|BZIP2|C3|Canon-IJ|Canon-UFR-II|CAOSL|CAPYBARA-EULA|CARA|CC-BY-1.0|CC-BY-2.0|CC-BY-2.5|CC-BY-3.0|CC-BY-4.0|CC-BY-NC-4.0|CC-BY-NC-ND-2.0|CC-BY-NC-ND-2.5|CC-BY-NC-ND-3.0|CC-BY-NC-ND-4.0|CC-BY-NC-SA-1.0|CC-BY-NC-SA-2.5|CC-BY-NC-SA-3.0|CC-BY-NC-SA-4.0|CC-BY-ND-3.0|CC-BY-ND-4.0|CC-BY-SA-1.0|CC-BY-SA-2.0|CC-BY-SA-2.5|CC-BY-SA-3.0|CC-BY-SA-4.0|CC-PD|CC-SA-1.0|CC-Sampling-Plus-1.0|CC0-1.0|CDDL|CDDL-1.1|CDDL-Schily|CDF|CeCILL-2|CeCILL-B|CeCILL-C|Cenon|charm|ChexQuest3|circlemud|Clarified-Artistic|Clear-BSD|clustalw|CNRI|Cockos|Cockroach|codehaus-classworlds|Coherent-Graphics|coldspringharbor|colt|comi|CPAL-1.0|CPL-0.5|CPL-1.0|CPOL|crafty|CROSSOVER-3|Crypt-IDEA|CSL-2.0|curl|DCC|Dell-EULA|DES|descent-data|dgen-sdl|Digium|docbook|dom4j|DOOM-COLLECTORS-EDITION|drascula|Dreamweb|dropbox|DUKE3D|DUMB-0.9.3|DXX-Rebirth|EAPL|ECL-2.0|Elastic|Elastic-2.0|ElementTree|Elm|Emacs|EPL-1.0|EPL-2.0|EPSON|ErlPL-1.1|eschalon-book-1-demo|eternal_lands|ETQW|EUPL-1.1|EUPL-1.2|exljbris-free|Exolab|f.lux|FAH-EULA-2014|FAH-special-permission|fairuse|fasta|FastCGI|FDL-1.1|FDL-1.1+|FDL-1.2|FDL-1.2+|FDL-1.3|FDL-1.3+|feh|FESTIVAL|File-MMagic|finchtv|FIPL-1.0|Flashpix|FLEX|flexmock|Flightradar24|FLTK|fmdrv|FoilTeX|fping|FraunhoferFDK|Free-Art-1.2|Free-Art-1.3|free-noncomm|freedist|freetts|frozenbyte-eula|FSFAP|FTDI|FTL|FVWM|galaxyhack|Gameplay-Group-EULA|gcc-runtime-library-exception-3.1|gd|geant4|geekbench|genymotion|Geogebra|GIMPS|Glulxe|gmap|gnuplot|GOG-EULA|google-chrome|GPL-1|GPL-1+|GPL-2|GPL-2+|GPL-2+-with-eCos-exception-2|GPL-2+-with-openssl-exception|GPL-2+-with-Pyinstaller-Bootloader-exception|GPL-2-with-classpath-exception|GPL-2-with-exceptions|GPL-2-with-font-exception|GPL-2-with-linking-exception|GPL-2-with-MySQL-FLOSS-exception|GPL-3|GPL-3+|GPL-3+-with-autoconf-exception|GPL-3+-with-font-exception|GPL-3-with-font-exception|GPL-3-with-openssl-exception|grass-ipafonts|GregoryRubin|gsm|gSOAP|gSOAP-1.3b|guild|HappyBunny|Hauppauge-Firmware|HIDAPI|HoMM2-Demo|hp-proliant-essentials|hpe|HPL|hplip-plugin|HPND|HRP|HSL|HTML-Tidy|Hugo|hylafaxplus|HyperSpec|iASL|IBM|icaclient|icu|IDEA|IDEA_Academic|IDEA_Classroom|IDEA_OpenSource|IDEA_Personal|IDPL|IJG|imagemagick|Info-ZIP|Inform|inmon-sflow|inner-net|Intel-SDP|intel-ucode|Interbase-1.0|Introversion|ipadic|IPAfont|ipw2100-fw|ipw2200-fw|ISC|Ispell|ISSL|ITS4|IUPAC-InChi|jardinains|JasPer2.0|JDOM|JetBrains-business|JetBrains-classroom|JetBrains-educational|JetBrains-individual|jfontain|JOVE|JoyPixels|JPRS|JSON|julius|Kermit|Khronos-CLHPP|knights-demo|Kryoflux-MAME|kyocera-mita-ppds|LA_OPT_BASE_LICENSE|lablgtk-examples|LambdaMOO|LaTeX-Calendar|lcc|LDP-1|LDP-1a|Legends|levee|Lexmark-EU2-0111|LGPL-2|LGPL-2+|LGPL-2-with-linking-exception|LGPL-2.1|LGPL-2.1+|LGPL-2.1-with-linking-exception|LGPL-3|LGPL-3+|LGPL-3-with-linking-exception|LGrind-Jacobson|lha|libgcc|LIBGLOSS|libmng|libpng|libpng2|libstdc++|libtiff|LICENSE-BITSTREAM|linux-fw-redistributable|LLGPL-2.1|LogMeIn|LOKI-EULA|LOTW|LPL-1.02|LPPL-1.0|LPPL-1.2|LPPL-1.3|LPPL-1.3a|LPPL-1.3c|LSI|LSI-tw_cli|lsof|lure|mac|MagentaMgOpen|MAJESTY-DEMO|MakeMKV-EULA|man-pages|man-pages-posix-2013|mapm|marginalhacks|Markwardt|master-pdf-editor|matplotlib|MaxMind2|MBROLA-VOICES|mekanix|Mellanox-AS-IS|metapackage|MicroChip-PK2|MicroChip-SDCC|Microsemi|microsoft-azurevpnclient|microsoft-edge|Microsoft-vscode|Midisport|MILO|Mini-XML|minpack|MirOS|MIT|MIT-0|MIT-with-advertising|mm|mmix|modeller|Mojang|MOLDEN|molmol|Moria|Mozart|MPEG-4|mpg123-el|mpich2|MPL-1.0|MPL-1.1|MPL-2.0|mplus-fonts|Ms-PL|Ms-RL|MSMS|MSttfEULA|MTA-0.5|myspell-en_CA-KevinAtkinson|myspell-ru_RU-AlexanderLebedev|namd|NCSA-AMD|NCSA-HDF|netcat|nethack|netlogo|netperf|NEWLIB|ngrep|no-source-code|Nokia-Qt-LGPL-Exception-1.1|nomachine|NOSA|NPL-1.1|NPSL-0.95|NVIDIA-CUDA|NVIDIA-cuDNN|NVIDIA-NVLM|NVIDIA-r1|NVIDIA-r2|NVIDIA-SDK|OAL-1.0.1|OASIS-Open|OFFIS|OFL-1.0|OFL-1.1|OGL-1.0a|Old-MIT|olivia|Ookla|Open-CASCADE-LGPL-2.1-Exception-1.0|openafs-krb5-a|openknights|OPENLDAP|openssl|Openwall|OPERA-2018|OPL|OSGi-Specification-2.0|OSL-1.1|OSL-2.0|OSL-2.1|OTN|otter|PAK128.German|PAPERS-PLEASE|par|PassMark-EULA|PCRE|PEL|penguzzle|perforce|PerlDL|photopc|PHP-2.02|PHP-3|PHP-3.01|phrack|PICO-8|pkcrack|PLAN9|Plex|pngcrush|pngnq|POSTGRESQL|Primate-Plunge|Princeton|procheck|prog-express|PSF-2|PSF-2.4|PSTT|psutils|public-domain|PUEL-11|PyCharm|PyCharm_Academic|PyCharm_Classroom|PyCharm_OpenSource|PyCharm_Preview|PYTHON|Q2EULA|Q3AEULA-20000111|qlogic-fibre-channel-firmware|QPL-1.0|quake1-demodata|quake1-killer|quake1-teamfortress|quake1-textures|quake2-demodata|QUAKE4|queen|qwt|RAR|raspberrypi-videocore-bin|rc|rdisc|regexp-UofT|repoze|Resounding|richardson|rpi-eeprom|RSA|RtMidi|Ruby|Ruby-BSD|rwpng|sash|scanlogd|sdlsasteroids|SDRplay|Sendmail|Sendmail-Open-Source|SFI-SCLA|sfpg|SGI-B-2.0|SGMLUG|shmux|shorten|SIP|SIR-TECH|Skype-TOS|Sleepycat|SMAIL|Snd|Snes9x|SOFA|Soltys|SpeedTouch-USB-Firmware|Spencer-99|spideroak|Spotify|SPS|SSLeay|SSPL-1|Stanford|stardock-images|Steam|STRIDE|Stuffit|Sublime|sun-bcla-j2me|sun-bcla-jai|sun-bcla-jsapi|Sun-BSD-no-nuclear-2005|supermicro|SURF|sus4-copyright|swiss-prot|symlinks|Sympow-BSD|Synology|szip|tablelist|TADS2|TADS3|tanuki-community|tarsnap|tcltk|tcp_wrappers_license|teamspeak3|teamspeak5|TeamViewer|Tenable-Master-Agreement|TeX|TeX-other-free|Texinfo-manual|TextMate-bundle|the-Click-license|THINKTANKS|TIK|Time-Format|Time-modules|timescale|Tinker|tkMOO|tm-align|torque-2.5|Toyoda|Transmission-OpenSSL-exception|trf|trio|truecrypt-3.0|tsm|ttf2pt1|ubiquiti|UbuntuFontLicense-1.0|UCAR-BSD|UCAR-Unidata|unafold|unicode|Unicode-3.0|Unicode-DFS-2016|Unlicense|unRAR|UoI-NCSA|UPL-1.0|UPX-exception|urbanterror-4.2-maps|URI|URT|ut2003|ut2003-demo|VGBA|vim|vim.org|Vivaldi|vlgothic|vmd|VOSTROM|VTK|W3C|w3m|Watcom-1.0|WidePix|wm2|WolframCDFPlayer|worklog-assistant|worldofpadman|WPS-EULA|WTFPL-2|wxWinFDL-3|wxWinLL-3|wxWinLL-3.1|xbatt|xbattle|xboing|XC|Xdebug|xearth|XEphem|xgraph|XMAME|xmlformat|xref.lisp|xrick|xtrs|xv|Yacht-Club-Games-EULA|YDSLA|Zend-2.0|zi-labone|ZLIB|ZPL|ZSH))*" + }, + "IUSE": { + "description": "This should be a list of any and all USE flags that are leveraged within your build script. The only USE flags that should not be listed here are arch related flags (see KEYWORDS). Beginning with EAPI 1, it is possible to prefix flags with + or - in order to create default settings that respectively enable or disable the corresponding USE flags. For details about USE flag stacking order, refer to the USE_ORDER variable in make.conf(5). Given the default USE_ORDER setting, negative IUSE default settings are effective only for negation of repo-level USE settings, since profile and user configuration settings override them.", + "type": "string" + }, + "DEPEND": { + "description": "This should contain a list of all packages that are required for the program to compile (aka buildtime dependencies). These are usually libraries and headers.", + "type": "string" + }, + "RDEPEND": { + "description": "This should contain a list of all packages that are required for this program to run (aka runtime dependencies). These are usually libraries.", + "type": "string" + }, + "BDEPEND": { + "description": "This should contain a list of all packages that are required to be executable during compilation of this program (aka native build dependencies). These are usually tools, like interpreters or (cross-)compilers. They will be installed into the system performing the build.", + "type": "string" + }, + "IDEPEND": { + "description": "This should contain a list of all packages that are required to be executable during merging of this package (aka native install-time dependencies). These are usually post-install tooling, like cache generators. They will be installed into the system performing the merge.", + "type": "string" + }, + "PDEPEND": { + "description": "This should contain a list of all packages that should be merged after this one (aka post merge dependencies), but which may be installed by the package manager at any time, if that is not possible.", + "type": "string" + }, + "REQUIRED_USE": { + "description": "Beginning with EAPI 4, the REQUIRED_USE variable can be used to specify combinations of USE flags that are allowed or not allowed. Elements can be nested when necessary.", + "type": "string" + }, + "RESTRICT": { + "description": "This should be a space delimited list of portage features to restrict. You may use conditional syntax to vary restrictions as seen above in DEPEND.", + "type": "string" + }, + "PROPERTIES": { + "description": "A space delimited list of properties, with conditional syntax support.", + "type": "string" + }, + "DOCS": { + "description": "Beginning with EAPI 4, an array or space-delimited list of documentation files for the default src_install function to install using dodoc. If undefined, a reasonable default list is used. See the documentation for src_install below.", + "type": "string" + }, + "PATCHES": { + "description": "Beginning with EAPI 6, an array of patches for applying in the default src_prepare function using eapply.", + "type": "string" + }, + "Usage": { + "description": "```sh\nUsage Notes\n```\nSeveral QA variables are provided which allow an ebuild to manipulate some of the QA checks performed by portage. Use of these variables in ebuilds should be kept to an absolute minimum otherwise they defeat the purpose of the QA checks, and their use is subject to agreement of the QA team. They are primarily intended for use by ebuilds that install closed-source binary objects that cannot be altered.", + "const": 0 + }, + "QA_AM_MAINTAINER_MODE": { + "description": "This should contain a list of lines containing automake missing --run commands. The lines may contain regular expressions with escape-quoted special characters.", + "type": "string" + }, + "QA_CONFIG_IMPL_DECL_SKIP": { + "description": "This should contain a list of function names to ignore when checking for -Wimplicit-function-declaration in configure logs. This should only be used for false positives.", + "type": "string" + }, + "QA_CONFIGURE_OPTIONS": { + "description": "This should contain a list of configure options which trigger warnings about unrecognized options. The options may contain regular expressions with escape-quoted special characters.", + "type": "string" + }, + "QA_DESKTOP_FILE": { + "description": "This should contain a list of file paths, relative to the image directory, of desktop files which should not be validated. The paths may contain regular expressions with escape-quoted special characters.", + "type": "string" + }, + "QA_DT_NEEDED": { + "description": "This should contain a list of file paths, relative to the image directory, of shared libraries that lack NEEDED entries. The paths may contain regular expressions with escape-quoted special characters.", + "type": "string" + }, + "QA_EXECSTACK": { + "description": "This should contain a list of file paths, relative to the image directory, of objects that require executable stack in order to run. The paths may contain fnmatch patterns.", + "type": "string" + }, + "QA_FLAGS_IGNORED": { + "description": "This should contain a list of file paths, relative to the image directory, of files that do not contain .GCC.command.line sections or contain .hash sections. The paths may contain regular expressions with escape-quoted special characters.", + "type": "string" + }, + "QA_MULTILIB_PATHS": { + "description": "This should contain a list of file paths, relative to the image directory, of files that should be ignored for the multilib-strict checks. The paths may contain regular expressions with escape-quoted special characters.", + "type": "string" + }, + "QA_PKGCONFIG_VERSION": { + "description": "If set, then portage verifies that all pkg-config .pc files have a Version field with the value of QA_PKGCONFIG_VERSION. For example, set QA_PKGCONFIG_VERSION=${PV} if your package is expected to install all pkg-config .pc files with a Version field containing PV.", + "type": "string" + }, + "QA_PREBUILT": { + "description": "This should contain a list of file paths, relative to the image directory, of files that are pre-built binaries. Paths listed here will be appended to each of the QA_* variables listed below. The paths may contain fnmatch-like patterns which will be internally translated to regular expressions for the QA_* variables that support regular expressions instead of fnmatch patterns. The translation mechanism simply replaces \"*\" with \".*\".", + "type": "string" + }, + "QA_PRESTRIPPED": { + "description": "This should contain a list of file paths, relative to the image directory, of files that contain pre-stripped binaries. The paths may contain regular expressions with escape-quoted special characters.", + "type": "string" + }, + "QA_SONAME": { + "description": "This should contain a list of file paths, relative to the image directory, of shared libraries that lack SONAMEs. The paths may contain regular expressions with escape-quoted special characters.", + "type": "string" + }, + "QA_SONAME_NO_SYMLINK": { + "description": "This should contain a list of file paths, relative to the image directory, of shared libraries that have SONAMEs but should not have a corresponding SONAME symlink in the same directory. The paths may contain regular expressions with escape-quoted special characters.", + "type": "string" + }, + "QA_TEXTRELS": { + "description": "This variable can be set to a list of file paths, relative to the image directory, of files that contain text relocations that cannot be eliminated. The paths may contain fnmatch patterns.", + "type": "string" + }, + "QA_WX_LOAD": { + "description": "This should contain a list of file paths, relative to the image directory, of files that contain writable and executable segments. These are rare. The paths may contain fnmatch patterns.", + "type": "string" + }, + "inherit": { + "description": "Inherit is portage's maintenance of extra classes of functions that are external to ebuilds and provided as inheritable capabilities and data. They define functions and set data types as drop-in replacements, expanded, and simplified routines for extremely common tasks to streamline the build process. Call to inherit cannot depend on conditions which can vary in given ebuild. Specification of the eclasses contains only their name and not the .eclass extension. Also note that the inherit statement must come before other variable declarations unless these variables are used in global scope of eclasses.", + "const": 0 + }, + "pkg_pretend": { + "description": "Beginning with EAPI 4, this function can be defined in order to check that miscellaneous requirements are met. It is called as early as possible, before any attempt is made to satisfy dependencies. If the function detects a problem then it should call eerror and die. The environment (variables, functions, temporary directories, etc..) that is used to execute pkg_pretend is not saved and therefore is not available in phases that execute afterwards.", + "const": 0 + }, + "pkg_nofetch": { + "description": "This function will be executed when the files in SRC_URI cannot be fetched for any reason. If you turn on fetch in RESTRICT, this is useful for displaying information to the user on *how* to obtain said files. All you have to do is output a message and let the function return. Do not end the function with a call to die.", + "const": 0 + }, + "pkg_setup": { + "description": "This function can be used if the package needs specific setup actions or checks to be preformed before anything else. Initial working directory: $PORTAGE_TMPDIR", + "const": 0 + }, + "src_unpack": { + "description": "This function is used to unpack all the sources in A to WORKDIR. If not defined in the ebuild script it calls unpack ${A}. Any patches and other pre configure/compile modifications should be done here. Initial working directory: $WORKDIR", + "const": 0 + }, + "src_prepare": { + "description": "All preparation of source code, such as application of patches, should be done here. This function is supported beginning with EAPI 2. Initial working directory: $S", + "const": 0 + }, + "src_configure": { + "description": "All necessary steps for configuration should be done here. This function is supported beginning with EAPI 2. Initial working directory: $S", + "const": 0 + }, + "src_compile": { + "description": "With less than EAPI 2, all necessary steps for both configuration and compilation should be done here. Beginning with EAPI 2, only compilation steps should be done here. Initial working directory: $S", + "const": 0 + }, + "src_test": { + "description": "Run all package specific test cases. The default is to run 'emake check' followed 'emake test'. Prior to EAPI 5, the default src_test implementation will automatically pass the -j1 option as the last argument to emake, and beginning with EAPI 5 it will allow the tests to run in parallel. Initial working directory: $S", + "const": 0 + }, + "src_install": { + "description": "Should contain everything required to install the package in the temporary install directory. Initial working directory: $S", + "const": 0 + }, + "pkg_preinst": { + "description": "```sh\npkg_preinst pkg_postinst\n```\nAll modifications required on the live-filesystem before and after the package is merged should be placed here. Also commentary for the user should be listed here as it will be displayed last. Initial working directory: $PWD", + "const": 0 + }, + "pkg_prerm": { + "description": "```sh\npkg_prerm pkg_postrm\n```\nLike the pkg_*inst functions but for unmerge. Initial working directory: $PWD", + "const": 0 + }, + "pkg_config": { + "description": "This function should contain optional basic configuration steps. Initial working directory: $PWD", + "const": 0 + }, + "default": { + "description": "Calls the default phase function implementation for the currently executing phase. This function is supported beginning with EAPI 2.", + "const": 0 + }, + "default_*": { + "description": "Beginning with EAPI 2, the default pkg_nofetch and src_* phase functions are accessible via a function having a name that begins with default_ and ends with the respective phase function name. For example, a call to a function with the name default_src_compile is equivalent to a call to the default src_compile implementation. Default Phase Functions default_src_unpack default_src_prepare default_src_configure default_src_compile default_src_test", + "const": 0 + }, + "assert": { + "description": "```sh\nassert [reason]\n```\nChecks the value of the shell's PIPESTATUS array variable, and if any component is non-zero (indicating failure), calls die with reason as a failure message.", + "const": 0 + }, + "die": { + "description": "```sh\ndie [reason]\n```\nCauses the current emerge process to be aborted. The final display will include reason.", + "const": 0 + }, + "nonfatal": { + "description": "```sh\nnonfatal \n```\nExecute helper and do not call die if it fails. The nonfatal helper is available beginning with EAPI 4.", + "const": 0 + }, + "use": { + "description": "```sh\nuse \n```\nIf USE item is in the USE variable, the function will silently return 0 (aka shell true). If USE item is not in the USE variable, the function will silently return 1 (aka shell false). usev is a verbose version of use. Example: if use gnome ; then \tguiconf=\"--enable-gui=gnome --with-x\" elif use gtk ; then \tguiconf=\"--enable-gui=gtk --with-x\" elif use X ; then \tguiconf=\"--enable-gui=athena --with-x\" else \t# No gui version will be built \tguiconf=\"\" fi", + "const": 0 + }, + "usev": { + "description": "```sh\nusev \n```\nLike use, but also echoes USE item when use returns true.", + "const": 0 + }, + "usex": { + "description": "```sh\nusex [true output] [false output] [true suffix] [false suffix]\n```\nIf USE flag is set, echo [true output][true suffix] (defaults to \"yes\"), otherwise echo [false output][false suffix] (defaults to \"no\"). The usex helper is available beginning with EAPI 5.", + "const": 0 + }, + "use_with": { + "description": "```sh\nuse_with [configure name] [configure opt]\n```\nUseful for creating custom options to pass to a configure script. If USE item is in the USE variable and a configure opt is specified, then the string --with-[configure name]=[configure opt] will be echoed. If configure opt is not specified, then just --with-[configure name] will be echoed. If USE item is not in the USE variable, then the string --without-[configure name] will be echoed. If configure name is not specified, then USE item will be used in its place. Beginning with EAPI 4, an empty configure opt argument is recognized. In EAPI 3 and earlier, an empty configure opt argument is treated as if it weren't provided. Examples: USE=\"opengl\" myconf=$(use_with opengl) (myconf now has the value \"--with-opengl\") USE=\"jpeg\" myconf=$(use_with jpeg libjpeg) (myconf now has the value \"--with-libjpeg\") USE=\"\" myconf=$(use_with jpeg libjpeg) (myconf now has the value \"--without-libjpeg\") USE=\"sdl\" myconf=$(use_with sdl SDL all-plugins) (myconf now has the value \"--with-SDL=all-plugins\")", + "const": 0 + }, + "use_enable": { + "description": "```sh\nuse_enable [configure name] [configure opt]\n```\nSame as use_with above, except that the configure options are --enable- instead of --with- and --disable- instead of --without-. Beginning with EAPI 4, an empty configure opt argument is recognized. In EAPI 3 and earlier, an empty configure opt argument is treated as if it weren't provided.", + "const": 0 + }, + "has": { + "description": "```sh\nhas \n```\nIf item is in item list, then has returns 0. Otherwise, 1 is returned. There is another version, hasv, that will conditionally echo item. The item list is delimited by the IFS variable. This variable has a default value of ' ', or a space. It is a bash(1) setting.", + "const": 0 + }, + "hasv": { + "description": "```sh\nhasv \n```\nLike has, but also echoes item when has returns true. Banned in EAPI 8.", + "const": 0 + }, + "has_version": { + "description": "```sh\nhas_version [-b] [-d] [-r] [--host-root] \n```\nCheck to see if category/package-version is installed. The parameter accepts all values that are acceptable in the DEPEND variable. The function returns 0 if category/package-version is installed, 1 otherwise. The package is searched for in ROOT by default.", + "const": 0 + }, + "best_version": { + "description": "```sh\nbest_version [-b] [-d] [-r] [--host-root] \n```\nThis function will look up package name in the database of currently installed packages and echo the \"best version\" of the package that is found or nothing if no version is installed. The package is searched for in ROOT by default. It accepts the same options as has_version.", + "const": 0 + }, + "einfo": { + "description": "```sh\neinfo \"disposable message\"\n```\nSame as elog, but should be used when the message isn't important to the user (like progress or status messages during the build process).", + "const": 0 + }, + "elog": { + "description": "```sh\nelog \"informative message\"\n```\nIf you need to display a message that you wish the user to read and take notice of, then use elog. It works just like echo(1), but adds a little more to the output so as to catch the user's eye. The message will also be logged by portage for later review.", + "const": 0 + }, + "ewarn": { + "description": "```sh\newarn \"warning message\"\n```\nSame as einfo, but should be used when showing a warning to the user.", + "const": 0 + }, + "eqawarn": { + "description": "```sh\neqawarn \"QA warning message\"\n```\nSame as einfo, but should be used when showing a QA warning to the user.", + "const": 0 + }, + "eerror": { + "description": "```sh\neerror \"error message\"\n```\nSame as einfo, but should be used when showing an error to the user.", + "const": 0 + }, + "ebegin": { + "description": "```sh\nebegin \"helpful message\"\n```\nLike einfo, we output a helpful message and then hint that the following operation may take some time to complete. Once the task is finished, you need to call eend.", + "const": 0 + }, + "eend": { + "description": "```sh\neend [\"error message\"]\n```\nFollowup the ebegin message with an appropriate \"OK\" or \"!!\" (for errors) marker. If status is non-zero, then the additional error message is displayed.", + "const": 0 + }, + "unpack": { + "description": "```sh\nunpack [list of more sources]\n```\nThis function uncompresses and/or untars a list of sources into the current directory. The function will append source to the DISTDIR variable.", + "const": 0 + }, + "eapply": { + "description": "```sh\neapply [patch options] \n```\nApplies patches to the ${WORKDIR} with specified options. Default patch level is -p1. If a directory specified, all patches from it with .patch or .diff suffix are applied. This function is available beginning with EAPI 6, replacing old epatch.eclass(5) functions.", + "const": 0 + }, + "eapply_user": { + "description": "Applies user-provided patches to the ${WORKDIR} from Portage config directory tree. For directory syntax and applying rules, see /etc/portage/patches/ section in portage(5). This function is available beginning with EAPI 6, replacing old epatch.eclass(5) functions.", + "const": 0 + }, + "econf": { + "description": "```sh\neconf [configure options]\n```\nThis is used as a replacement for configure. Performs:", + "const": 0 + }, + "emake": { + "description": "```sh\nemake [make options]\n```\nThis must be used in place of `make` in ebuilds. Performs `${MAKE:-make} ${MAKEOPTS} make options ${EXTRA_EMAKE}`, and calls `die` automatically starting with EAPI 4.", + "const": 0 + }, + "einstall": { + "description": "```sh\neinstall [make options]\n```\nThis is used as a replacement for make install. Performs:", + "const": 0 + }, + "docompress": { + "description": "```sh\ndocompress [-x] [list of more paths]\n```\nBeginning with EAPI 4, the docompress helper is used to manage lists of files to be included or excluded from optional compression. If the first argument is -x, add each of its subsequent arguments to the exclusion list. Otherwise, add each argument to the inclusion list. The inclusion list initially contains /usr/share/doc, /usr/share/info, and /usr/share/man. The exclusion list initially contains /usr/share/doc/${PF}/html. The optional compression shall be carried out after src_install has completed, and before the execution of any subsequent phase function. For each item in the inclusion list, pretend it has the value of the D variable prepended, then: If it is a directory, act as if every file or directory immediately under this directory were in the inclusion list. If the item is a file, it may be compressed unless it has been excluded as described below. If the item does not exist, it is ignored. Whether an item is to be excluded is determined as follows: For each item in the exclusion list, pretend it has the value of the D variable prepended, then: If it is a directory, act as if every file or directory immediately under this directory were in the exclusion list. If the item is a file, it shall not be compressed. If the item does not exist, it is ignored.", + "const": 0 + }, + "dosed": { + "description": "```sh\ndosed \"s:orig:change:g\" \n```\nBeginning with EAPI 4, the dosed helper no longer exists. Ebuilds should call sed(1) directly (and assume that it is GNU sed).", + "const": 0 + }, + "dodir": { + "description": "```sh\ndodir [more paths]\n```\nCreates directories inside of ${ED}. 'dodir /usr/lib/apache' creates ${ED}/usr/lib/apache. Note that the do* functions will run dodir for you. If this directory will be empty when it is merged, then please use keepdir instead.", + "const": 0 + }, + "diropts": { + "description": "```sh\ndiropts [options for install(1)]\n```\nCan be used to define options for the install function used in dodir. The default is -m0755.", + "const": 0 + }, + "into": { + "description": "```sh\ninto \n```\nSets the root (DESTTREE) for other functions like dobin, dosbin, doman, doinfo, dolib. The default root is /usr.", + "const": 0 + }, + "keepdir": { + "description": "```sh\nkeepdir [more paths]\n```\nSimilar to dodir, but used to create directories that would otherwise be empty. The treatment of completely-empty directories is undefined by PMS, and using keepdir ensures that they are tracked.", + "const": 0 + }, + "dobin": { + "description": "```sh\ndobin [list of more binaries]\n```\nInstalls a binary or a list of binaries into DESTTREE/bin. Creates all necessary dirs.", + "const": 0 + }, + "dosbin": { + "description": "```sh\ndosbin [list of more binaries]\n```\nInstalls a binary or a list of binaries into DESTTREE/sbin. Creates all necessary dirs.", + "const": 0 + }, + "doinitd": { + "description": "```sh\ndoinitd [list of more init.d scripts]\n```\nInstall Gentoo init.d scripts. They will be installed into the correct location for Gentoo init.d scripts (/etc/init.d/). Creates all necessary dirs.", + "const": 0 + }, + "doconfd": { + "description": "```sh\ndoconfd [list of more conf.d file]\n```\nInstall Gentoo conf.d files. They will be installed into the correct location for Gentoo conf.d files (/etc/conf.d/). Creates all necessary dirs.", + "const": 0 + }, + "doenvd": { + "description": "```sh\ndoenvd [list of more env.d entries]\n```\nInstall Gentoo env.d entries. They will be installed into the correct location for Gentoo env.d entries (/etc/env.d/). Creates all necessary dirs.", + "const": 0 + }, + "dolib": { + "description": "```sh\ndolib [list of more libraries]\n```\n", + "const": 0 + }, + "dolib.a": { + "description": "```sh\ndolib.a [list of more libraries]\n```\n", + "const": 0 + }, + "dolib.so": { + "description": "```sh\ndolib.so [list of more libraries]\n```\n", + "const": 0 + }, + "libopts": { + "description": "```sh\nlibopts [options for install(1)]\n```\nCan be used to define options for the install function used in the dolib functions. The default is -m0644. libopts is banned in EAPI 7.", + "const": 0 + }, + "doman": { + "description": "```sh\ndoman [-i18n=] [list of more man-pages]\n```\nInstalls manual-pages into /usr/share/man/man[0-9n] depending on the manual file ending. The files are compressed if they are not already. You can specify locale-specific manpages with the -i18n option. Then the man-page will be installed into /usr/share/man//man[0-9n]. Beginning with EAPI 2, a locale-specific manpage which contains a locale in the file name will be installed in /usr/share/man//man[0-9n], with the locale portion of the file name removed, and the -i18n option has no effect. For example, with EAPI 2, a manpage named foo..1 will be installed as /usr/share/man//man1/foo.1. Beginning with EAPI 4, the -i18n option takes precedence over the locale suffix of the file name.", + "const": 0 + }, + "dohard": { + "description": "```sh\ndohard \n```\nBeginning with EAPI 4, the dohard helper no longer exists. Ebuilds should call ln(1) directly.", + "const": 0 + }, + "dosym": { + "description": "```sh\ndosym [-r] \n```\n", + "const": 0 + }, + "doheader": { + "description": "```sh\ndoheader [-r] [list of more files]\n```\nInstalls the given header files into /usr/include/, by default with file mode 0644 (this can be overridden with the insopts function). Setting -r sets recursive. The doheader helper is available beginning with EAPI 5.", + "const": 0 + }, + "dohtml": { + "description": "```sh\ndohtml [-a filetypes] [-r] [-x list-of-dirs-to-ignore] [list-of-files-and-dirs]\n```\nInstalls the files in the list of files (space-separated list) into /usr/share/doc/${PF}/html provided the file ends in .htm, .html, .css, .js, .gif, .jpeg, .jpg, or .png. Setting -a limits what types of files will be included, -A appends to the default list, setting -x sets which dirs to exclude (CVS excluded by default), -p sets a document prefix, -r sets recursive. dohtml is banned in EAPI 7: use dodoc and docinto instead.", + "const": 0 + }, + "doinfo": { + "description": "```sh\ndoinfo [list of more info-files]\n```\nInstalls info-pages into DESTDIR/info. Files are automatically gzipped. Creates all necessary dirs.", + "const": 0 + }, + "domo": { + "description": "```sh\ndomo [list of more locale-files]\n```\nInstalls locale-files into DESTDIR/usr/share/locale/[LANG] depending on local-file's ending. Creates all necessary dirs.", + "const": 0 + }, + "fowners": { + "description": "```sh\nfowners [-h|-H|-L|-P|-R] [user][:group] [files]\n```\n", + "const": 0 + }, + "fperms": { + "description": "```sh\nfperms [-R] [files]\n```\n", + "const": 0 + }, + "insinto": { + "description": "```sh\ninsinto [path]\n```\nSets the destination path for the doins function. The default path is /.", + "const": 0 + }, + "insopts": { + "description": "```sh\ninsopts [options for install(1)]\n```\nCan be used to define options for the install function used in doins. The default is -m0644.", + "const": 0 + }, + "doins": { + "description": "```sh\ndoins [-r] [list of more files]\n```\nInstalls files into the path controlled by insinto. This function uses install(1). Creates all necessary dirs. Setting -r sets recursive. Beginning with EAPI 4, both doins and newins preserve symlinks. In EAPI 3 and earlier, symlinks are dereferenced rather than preserved.", + "const": 0 + }, + "exeinto": { + "description": "```sh\nexeinto [path]\n```\nSets the destination path for the doexe function. The default path is /.", + "const": 0 + }, + "exeopts": { + "description": "```sh\nexeopts [options for install(1)]\n```\nCan be used to define options for the install function used in doexe. The default is -m0755.", + "const": 0 + }, + "doexe": { + "description": "```sh\ndoexe [list of more executables]\n```\nInstalls executables into the path controlled by exeinto. This function uses install(1). Creates all necessary dirs. Behavior is undefined if exeinto has not yet been called.", + "const": 0 + }, + "docinto": { + "description": "```sh\ndocinto [path]\n```\nSets the subdir used by dodoc and dohtml when installing into the document tree (based in /usr/share/doc/${PF}/). Default is no subdir, or just \"\".", + "const": 0 + }, + "dodoc": { + "description": "```sh\ndodoc [-r] [list of more documents]\n```\nInstalls a document or a list of documents into /usr/share/doc/${PF}/. Documents are marked for compression. Creates all necessary dirs. Beginning with EAPI 4, there is support for recursion, enabled by the new -r option.", + "const": 0 + } + } +} diff --git a/src/termux_language_server/assets/json/install.json b/src/termux_language_server/assets/json/install.json new file mode 100644 index 0000000..6c809a0 --- /dev/null +++ b/src/termux_language_server/assets/json/install.json @@ -0,0 +1,32 @@ +{ + "$id": "https://github.com/termux/termux-language-server/blob/main/src/termux_language_server/assets/json/install.json", + "$schema": "http://json-schema.org/draft-07/schema#", + "$comment": "Don't edit this file directly! It is generated by `termux-language-server --generate-schema=install`.", + "type": "object", + "patternProperties": { + "^pre_install($|_.*)": { + "description": "Run right before files are extracted. One argument is passed: new package full version string.", + "const": 0 + }, + "^post_install($|_.*)": { + "description": "Run right after files are extracted. One argument is passed: new package full version string.", + "const": 0 + }, + "^pre_upgrade($|_.*)": { + "description": "Run right before files are extracted. Two arguments are passed in this order: new package full version string, old package full version string.", + "const": 0 + }, + "^post_upgrade($|_.*)": { + "description": "Run after files are extracted. Two arguments are passed in this order: new package full version string, old package full version string.", + "const": 0 + }, + "^pre_remove($|_.*)": { + "description": "Run right before files are removed. One argument is passed: old package full version string.", + "const": 0 + }, + "^post_remove($|_.*)": { + "description": "Run right after files are removed. One argument is passed: old package full version string.", + "const": 0 + } + } +} diff --git a/src/termux_language_server/assets/json/make.conf.json b/src/termux_language_server/assets/json/make.conf.json new file mode 100644 index 0000000..93c9964 --- /dev/null +++ b/src/termux_language_server/assets/json/make.conf.json @@ -0,0 +1,428 @@ +{ + "$id": "https://github.com/termux/termux-language-server/blob/main/src/termux_language_server/assets/json/make.conf.json", + "$schema": "http://json-schema.org/draft-07/schema#", + "$comment": "Don't edit this file directly! It is generated by `termux-language-server --generate-schema=make.conf`.", + "type": "object", + "properties": { + "ACCEPT_CHOSTS": { + "description": "```sh\nACCEPT_CHOSTS = [space delimited list of CHOST values]\n```\nSpecifies acceptable CHOST values. Regular expression syntax is supported, so it is necessary to escape CHOST characters if they have special meaning in regular expressions. Defaults to the value of $CHOST.", + "type": "string" + }, + "ACCEPT_KEYWORDS": { + "description": "```sh\nACCEPT_KEYWORDS = [space delimited list of KEYWORDS]\n```\nEnable testing of ebuilds that have not yet been deemed 'stable'. Users of the 'x86' architecture would set this to '~x86' while ppc users would set this to '~ppc'. This is an incremental variable. Only define a ~arch. Defaults to the value of $ARCH.", + "type": "string" + }, + "ACCEPT_LICENSE": { + "description": "```sh\nACCEPT_LICENSE = [space delimited list of licenses or groups]\n```\nThis variable is used to mask packages based on licensing restrictions. It may contain both license and group names, where group names are prefixed with the '@' symbol. License groups are defined in the license_groups file (see portage(5)). In addition to license and group names, the * and -* wildcard tokens are also supported. Refer to GLEP 23 for further information: https://www.gentoo.org/glep/glep-0023.html. Defaults to the value defined in the profile. Examples:", + "type": "string" + }, + "ACCEPT_PROPERTIES": { + "description": "```sh\nACCEPT_PROPERTIES = [space delimited list of properties]\n```\nThis variable is used to mask packages based on PROPERTIES restrictions. In addition to property names, the * and -* wildcard tokens are also supported. This variable can be temporarily overridden using the --accept-properties option of emerge(1). See ebuild(5) for more information about PROPERTIES. Defaults to the value of *. Examples:", + "type": "string" + }, + "ACCEPT_RESTRICT": { + "description": "```sh\nACCEPT_RESTRICT = [space delimited list of RESTRICT tokens]\n```\nThis variable is used to mask packages based on RESTRICT tokens. In addition to RESTRICT tokens, the * and -* wildcard tokens are also supported. This variable can be temporarily overridden using the --accept-restrict option of emerge(1). See ebuild(5) for more information about RESTRICT. Defaults to the value of *. Examples:", + "type": "string" + }, + "BINPKG_FORMAT": { + "description": "This variable sets the format used for tar binary packages. Possible values are xpak or gpkg. If BINPKG_FORMAT is set to xpak, packages will have the file extension .tbz2 for any compression type for historical reasons. If BINPKG_FORMAT is set to xpak, and FEATURES=\"binpkg-multi-instance\" is set, packages will have the file extension .xpak. If BINPKG_FORMAT is set to gpkg, packages will have the file extension .gpkg.", + "type": "string" + }, + "BINPKG_COMPRESS": { + "description": "```sh\nBINPKG_COMPRESS = \"compression\"\n```\nThis variable is used to determine the compression used for binary packages. Supported settings and compression algorithms are: bzip2, gzip, lz4, lzip, lzop, xz, zstd. See note for BINPKG_FORMAT on file suffix. Defaults to \"zstd\". Example:", + "type": "string" + }, + "BINPKG_COMPRESS_FLAGS": { + "description": "```sh\nBINPKG_COMPRESS_FLAGS = \"arguments for compression command\"\n```\nThis variable is used to add additional arguments to the compression command selected by BINPKG_COMPRESS. Defaults to \"\". Example:", + "type": "string" + }, + "BINPKG_GPG_SIGNING_BASE_COMMAND": { + "description": "```sh\nBINPKG_GPG_SIGNING_BASE_COMMAND = \"GPG command and arguments [PORTAGE_CONFIG]\"\n```\nThe base command will be used for all signing operations. Portage will replace [PORTAGE_CONFIG] under different operations. Please do not add arguments that can be configured independently. Defaults to \"/usr/bin/flock /run/lock/portage-binpkg-gpg.lock /usr/bin/gpg --sign --armor [PORTAGE_CONFIG]\".", + "type": "string" + }, + "BINPKG_GPG_SIGNING_DIGEST=": { + "description": "```sh\nBINPKG_GPG_SIGNING_DIGEST= = \"GPG supported digest\"\n```\nThe digest that will be used for signature. Defaults to \"SHA512\"", + "type": "string" + }, + "BINPKG_GPG_SIGNING_GPG_HOME": { + "description": "```sh\nBINPKG_GPG_SIGNING_GPG_HOME = [path]\n```\nThe GPG home where the signing private key located. Defaults to \"/root/.gnupg\"", + "type": "string" + }, + "BINPKG_GPG_SIGNING_KEY": { + "description": "```sh\nBINPKG_GPG_SIGNING_KEY = \"GPG key ID\"\n```\nGPG key ID used to sign binary packages, must exists in BINPKG_GPG_SIGNING_GPG_HOME. Defaults to \"\" Example: \"0x40DCF18E97150795!\"", + "type": "string" + }, + "BINPKG_GPG_VERIFY_BASE_COMMAND=": { + "description": "```sh\nBINPKG_GPG_VERIFY_BASE_COMMAND= = \"GPG command and arguments\"\n```\nThe base command will be used for all verify operations. Portage will replace [PORTAGE_CONFIG] and [SIGNATURE] under different operations. Please do not add arguments that can be configured independently. Defaults to \"/usr/bin/gpg --verify --batch --no-tty --no-auto-check-trustdb --status-fd 2 [PORTAGE_CONFIG] [SIGNATURE]\"", + "type": "string" + }, + "BINPKG_GPG_VERIFY_GPG_HOME": { + "description": "```sh\nBINPKG_GPG_VERIFY_GPG_HOME = [path]\n```\nThe GPG home where the trusted keys located. Please make sure the target directory is globally readable, as the user will be dropped to nobody during verification. Defaults to \"/etc/portage/gnupg\"", + "type": "string" + }, + "CBUILD": { + "description": "This variable is passed by the ebuild scripts to the configure as --build=${CBUILD} only if it is defined. Do not set this yourself unless you know what you are doing.", + "type": "string" + }, + "CCACHE_DIR": { + "description": "```sh\nCCACHE_DIR = [path]\n```\nDefines the location of the ccache working directory. See the ccache(1) man page for more information.", + "type": "string" + }, + "CCACHE_SIZE": { + "description": "```sh\nCCACHE_SIZE = \"size\"\n```\nThis controls the space use limitations for ccache. See the -M flag in the ccache(1) man page for more information.", + "type": "string" + }, + "CFLAGS": { + "description": "```sh\nCFLAGS CXXFLAGS\n```\nUse these variables to set the desired optimization/CPU instruction settings for applications that you compile. These two variables are passed to the C and C++ compilers, respectively. (CXX is used to refer to the C++ compiler within many buildsystems.) Nearly all ebuild files will take advantage of your custom settings, resulting in a Gentoo Linux that is fully customized to your specifications. Please use sane settings as some packages will fail to compile/run if the optimizations are too extreme.", + "type": "string" + }, + "CHOST": { + "description": "This variable is passed by the ebuild scripts to the configure step as --host=${CHOST}. This way you can force the build-host.", + "type": "string" + }, + "CLEAN_DELAY": { + "description": "```sh\nCLEAN_DELAY = integer\n```\nDetermines how long the countdown delay will be after running `emerge --unmerge`. Defaults to 5 seconds.", + "type": "string" + }, + "COLLISION_IGNORE": { + "description": "```sh\nCOLLISION_IGNORE = [space delimited list of fnmatch patterns]\n```\nThis variable allows the user to disable collision-protect and protect-owned for specific fnmatch(3) patterns. For backward compatibility, directories that are listed without a fnmatch pattern will automatically have /* appended to them. Defaults to \"/lib/modules/* *.py[co]\".", + "type": "string" + }, + "CONFIG_PROTECT": { + "description": "```sh\nCONFIG_PROTECT = [space delimited list of files and/or directories]\n```\nAll files and/or directories that are defined here will have \"config file protection\" enabled for them. See the CONFIGURATION FILES section of emerge(1) for more information.", + "type": "string" + }, + "CONFIG_PROTECT_MASK": { + "description": "```sh\nCONFIG_PROTECT_MASK = [space delimited list of files and/or directories]\n```\nAll files and/or directories that are defined here will have \"config file protection\" disabled for them. See the CONFIGURATION FILES section of emerge(1) for more information.", + "type": "string" + }, + "CTARGET": { + "description": "This variable is passed by the ebuild scripts to the configure as --target=${CTARGET} only if it is defined.", + "type": "string" + }, + "DISTDIR": { + "description": "```sh\nDISTDIR = [path]\n```\nDefines the location of your local source file repository. After packages are built, it is safe to remove any and all files from this directory since they will be automatically fetched on demand for a given build. If you would like to selectively prune obsolete files from this directory, see eclean(1) from the gentoolkit package.", + "type": "string" + }, + "DOC_SYMLINKS_DIR": { + "description": "If this variable contains a directory then symlinks to html documentation will be installed into it.", + "type": "string" + }, + "EBEEP_IGNORE": { + "description": "Defines whether or not to ignore audible beeps when displaying important informational messages. This variable is unset by default.", + "type": "string" + }, + "EMERGE_DEFAULT_OPTS": { + "description": "Options to append to the end of the emerge(1) command line on every invocation. These options will not be appended to the command line if --ignore-default-opts is specified.", + "type": "string" + }, + "EMERGE_LOG_DIR": { + "description": "Controls the location of emerge.log and emerge-fetch.log. Defaults to /var/log.", + "type": "string" + }, + "EMERGE_WARNING_DELAY": { + "description": "```sh\nEMERGE_WARNING_DELAY = integer\n```\nDetermines how long the countdown delay will be after running `emerge --unmerge` for a system package. Defaults to 10 seconds.", + "type": "string" + }, + "EPAUSE_IGNORE": { + "description": "Defines whether or not to ignore short pauses that occur when displaying important informational messages. This variable is unset by default. If it is set to any value pauses are ignored.", + "type": "string" + }, + "EXTRA_ECONF": { + "description": "```sh\nEXTRA_ECONF = [configure options string]\n```\nContains additional options that econf will append to configure script arguments (see ebuild(5)).", + "type": "string" + }, + "FEATURES": { + "description": "```sh\nFEATURES = \"sandbox\"\n```\nDefines actions portage takes by default. This is an incremental variable. Most of these settings are for developer use, but some are available to non-developers as well. The sandbox feature is very important and should not be disabled by default. assume-digests When commiting work to cvs with repoman(1), assume that all existing SRC_URI digests are correct. This feature also affects digest generation via ebuild(1) and emerge(1) (emerge generates digests only when the digest feature is enabled). Existing digests for files that do not exist in ${DISTDIR} will be automatically assumed even when assume-digests is not enabled. If a file exists in ${DISTDIR} but its size does not match the existing digest, the digest will be regenerated regardless of whether or not assume-digests is enabled. The ebuild(1) digest command has a --force option that can be used to force regeneration of digests. binpkg-docompress Perform docompress (controllable file compression) before creating binary package. When this option is enabled (the default), documentation files are already compressed inside binary packages. When it is disabled, binary packages contain uncompressed documentation and Portage compresses it before installing. binpkg-dostrip Perform file stripping before creating binary package. When this option is enabled (the default), executables are already stripped inside binary packages. When it is disabled, binary packages contain unstripped executables and Portage strips (or splits) them before installing. binpkg-dostrip must be enabled for installsources to work. binpkg-ignore-signature This will disable GPG signature check for all binary packages. Enable this could be dangerous if you get binary packages from remote site or use third party packages. binpkg-logs Keep logs from successful binary package merges. This is relevant only when PORTAGE_LOGDIR is set. binpkg-multi-instance Enable support for multiple binary package instances per ebuild. Having multiple instances is useful for a number of purposes, such as retaining builds that were built with different USE flags or linked against different versions of libraries. The location of any particular package within PKGDIR can be expressed as follows: ${PKGDIR}/${CATEGORY}/${PN}/${PF}-${BUILD_ID}.xpak The build-id starts at 1 for the first build of a particular ebuild, and is incremented by 1 for each new build. It is possible to share a writable PKGDIR over NFS, and locking ensures that each package added to PKGDIR will have a unique build-id. It is not necessary to migrate an existing PKGDIR to the new layout, since portage is capable of working with a mixed PKGDIR layout, where packages using the old layout are allowed to remain in place. The new PKGDIR layout is backward-compatible with binhost clients running older portage, since the file format is identical, the per-package PATH attribute in the 'Packages' index directs them to download the file from the correct URI, and they automatically use BUILD_TIME metadata to select the latest builds. The eclean-pkg command can be used to prune old builds from PKGDIR. It is also possible to remove packages manually, and then run 'emaint --fix binhost' to update the ${PKGDIR}/Packages index. This feature is enabled by default. binpkg-request-signature Binary packages are requested to be signed by trusted GPG signature. Portage will reject to process any binary package without a valid GPG signature. The verify command is defined in BINPKG_GPG_VERIFY_COMMAND variable. binpkg-signing Binary packages will be signed by given GPG command. The signing command is defined in BINPKG_GPG_SIGNING_COMMAND variable. buildpkg Binary packages will be created for all packages that are merged. Also see quickpkg(1) and emerge(1) --buildpkg and --buildpkgonly options. buildpkg-live When this option is enabled (the default), buildpkg will exhibit the default behavior of building binary cache for all packages. When it is disabled, binary packages will not be created for live ebuilds. buildsyspkg Build binary packages for just packages in the system set. candy Enable a special progress indicator when emerge(1) is calculating dependencies. case-insensitive-fs Use case-insensitive file name comparisions when merging and unmerging files. Most users should not enable this feature, since most filesystems are case-sensitive. You should only enable this feature if you are using portage to install files to a case-insensitive filesystem. ccache Enable portage support for the ccache package. If the ccache dir is not present in the user's environment, then portage will default to ${PORTAGE_TMPDIR}/ccache. Warning: This feature is known to cause numerous compilation failures. Sometimes ccache will retain stale code objects or corrupted files, which can lead to packages that cannot be emerged. If this happens (if you receive errors like \"File not recognized: File truncated\"), try recompiling the application with ccache disabled before reporting a bug. Unless you are doing development work, do not enable ccache. clean-logs Enable automatic execution of the command specified by the PORTAGE_LOGDIR_CLEAN variable. The default PORTAGE_LOGDIR_CLEAN setting will remove all files from PORTAGE_LOGDIR that were last modified at least 7 days ago. collision-protect A QA-feature to ensure that a package doesn't overwrite files it doesn't own. The COLLISION_IGNORE variable can be used to selectively disable this feature. Also see the related protect-owned feature. compress-build-logs The causes all build logs to be compressed while they are being written. Log file names have an extension that is appropriate for the compression type. Currently, only gzip(1) compression is supported, so build logs will have a '.gz' extension when this feature is enabled. compress-index If set then a compressed copy of 'Packages' index file will be written. This feature is intended for Gentoo binhosts using certain webservers (such as, but not limited to, Nginx with gzip_static module) to avoid redundant on-the-fly compression. The resulting file will be called 'Packages.gz' and its modification time will match that of 'Packages'. compressdebug Compress the debug sections in the split debug files with zlib to save space. See splitdebug for general split debug information (upon which this feature depends). config-protect-if-modified This causes the CONFIG_PROTECT behavior to be skipped for files that have not been modified since they were installed. This feature is enabled by default. digest Autogenerate digests for packages when running the emerge(1) or ebuild(1) commands. If the assume-digests feature is also enabled then existing SRC_URI digests will be reused whenever they are available. distcc Enable portage support for the distcc package. distlocks Portage uses lockfiles to ensure competing instances don't clobber each other's files. It covers saving distfiles to ${DISTDIR} and binpkgs to ${PKGDIR}. This feature is enabled by default but may cause heartache on less intelligent remote filesystems like NFSv2 and some strangely configured Samba servers (oplocks off, NFS re-export). /usr/lib/portage/bin/clean_locks exists to help handle lock issues when a problem arises (normally due to a crash or disconnect). downgrade-backup When a package is downgraded to a lower version, call quickpkg(1) in order to create a backup of the installed version before it is unmerged (if a binary package of the same version does not already exist). Also see the related unmerge-backup feature. ebuild-locks Use locks to ensure that unsandboxed ebuild phases never execute concurrently. Also see parallel-install. fail-clean Clean up temporary files after a build failure. This is particularly useful if you have PORTAGE_TMPDIR on tmpfs. If this feature is enabled, you probably also want to enable PORTAGE_LOGDIR in order to save the build log. Both the ebuild(1) command and the noclean feature cause the fail-clean feature to be automatically disabled. fakeroot Enable fakeroot for the install and package phases when a non-root user runs the ebuild(1) command. fixlafiles Modifies .la files to not include other .la files and some other fixes (order of flags, duplicated entries, ...) force-mirror Only fetch files from configured mirrors, ignoring SRC_URI, except when mirror is in the ebuild(5) RESTRICT variable. getbinpkg Force emerges to always try to fetch files from the PORTAGE_BINHOST. See make.conf(5) for more information. gpg-keepalive Run GPG unlock command every 5 mins to avoid the passphrase expired. If your GPG is auto unlocked on login, you do not need this. icecream Enable portage support for the icecream package. installsources Install source code into /usr/src/debug/${CATEGORY}/${PF} (also see splitdebug). This feature works only if debugedit is installed, CFLAGS is set to include debug information (such as with the -ggdb flag) and binpkg-dostrip is enabled. ipc-sandbox Isolate the ebuild phase functions from host IPC namespace. Supported only on Linux. Requires IPC namespace support in kernel. keeptemp Do not delete the ${T} directory after the merge process. keepwork Do not delete the ${WORKDIR} directory after the merge process. ${WORKDIR} can then be reused since this feature disables most of the clean phase that runs prior to each build. Due to lack of proper cleanup, this feature can interfere with normal emerge operation and therefore it should not be left enabled for more than a short period of time. lmirror When mirror is enabled in FEATURES, fetch files even when mirror is also in the ebuild(5) RESTRICT variable. Do NOT use lmirror for clients that need to override RESTRICT when fetching from a local mirror, but instead use a \"local\" mirror setting in /etc/portage/mirrors, as described in portage(5). merge-sync After a package is merged or unmerged, sync relevant files to disk in order to avoid data-loss in the event of a power failure. This feature is enabled by default. metadata-transfer Automatically perform a metadata transfer when `emerge --sync` is run. In versions of portage >=2.1.5, this feature is disabled by default. When metadata-transfer is disabled, metadata cache from the ${repository_location}/metadata/md5-cache/ directory will be used directly (if available). mirror Fetch everything in SRC_URI regardless of USE settings, except do not fetch anything when mirror is in RESTRICT. mount-sandbox Isolate the ebuild phase functions from host mount namespace. This makes it possible for ebuild to alter mountpoints without affecting the host system. Supported only on Linux. Requires mount namespace support in kernel. multilib-strict Many Makefiles assume that their libraries should go to /usr/lib, or $(prefix)/lib. This assumption can cause a serious mess if /usr/lib isn't a symlink to /usr/lib64. To find the bad packages, we have a portage feature called multilib-strict. It will prevent emerge from putting 64bit libraries into anything other than (/usr)/lib64. network-sandbox Isolate the ebuild phase functions from host network interfaces. Supported only on Linux. Requires network namespace support in kernel. network-sandbox-proxy Enable escaping network-sandbox through SOCKSv5 proxy. Enabling distcc feature also enables the proxy. If asyncio Python module is available (requires Python 3.3, built-in since Python 3.4) Portage will additionally spawn an isolated SOCKSv5 proxy on UNIX socket. The socket address will be exported as PORTAGE_SOCKS5_PROXY and the processes running inside the sandbox can use it to access host's network when desired. Portage automatically configures new enough distcc to use the proxy. news Enable GLEP 42 news support. See https://www.gentoo.org/glep/glep-0042.html. noauto When utilizing ebuild(1), only run the function requested. Also, forces the corresponding ebuild and eclasses to be sourced again for each phase, in order to account for modifications. noclean Do not delete the source and temporary files after the merge process. nodoc Do not install doc files (/usr/share/doc). noinfo Do not install info pages. noman Do not install manpages. nostrip Prevents the stripping of binaries that are merged to the live filesystem. notitles Disables xterm titlebar updates (which contains status info). parallel-fetch Fetch in the background while compiling. Run `tail -f /var/log/emerge-fetch.log` in a terminal to view parallel-fetch progress. parallel-install Use finer-grained locks when installing packages, allowing for greater parallelization. For additional parallelization, disable ebuild-locks. pid-sandbox Isolate the process space for the ebuild processes. This makes it possible to cleanly kill all processes spawned by the ebuild. Supported only on Linux. Requires PID and mount namespace support in kernel. /proc is remounted inside the mount namespace to account for new PID namespace. pkgdir-index-trusted Trust that the PKGDIR index file is valid, meaning that no packages have been manually added or removed since the last call to emaint --fix binhost. This feature eliminates overhead involved with detection of packages that have been manually added or removed, which significantly improves performance in some cases, such as when PKGDIR resides on a high-latency network file system. prelink-checksums If prelink(8) is installed then use it to undo any prelinks on files before computing checksums for merge and unmerge. This feature is useful only if prelink(8) is installed and accurate checksums (despite prelinking) are needed for some reason such as for checking the integrity of installed files or because the unmerge-orphans feature is disabled. Note that normal emerging of packages from source computes the checksums before things will be prelinked, so in such cases, this feature isn't required either. Undoing prelinking while merging is only required when using tools like quickpkg(1) which can cause already prelinked files to be merged. preserve-libs Preserve libraries when the sonames change during upgrade or downgrade. Libraries are preserved only if consumers of those libraries are detected. Preserved libraries are automatically removed when there are no remaining consumers. Run `emerge @preserved-rebuild` in order to rebuild all consumers of preserved libraries. protect-owned This is identical to the collision-protect feature except that files may be overwritten if they are not explicitly listed in the contents of a currently installed package. This is particularly useful on systems that have lots of orphan files that have been left behind by older versions of portage that did not support the unmerge-orphans feature. Like collision-protect, the COLLISION_IGNORE variable can be used to selectively disable this feature. It is recommended to leave either protect-owned or collision-protect enabled at all times, since otherwise file collisions between packages may result in files being overwritten or uninstalled at inappropriate times. If collision-protect is enabled then it takes precedence over protect-owned. python-trace Output a verbose trace of python execution to stderr when a command's --debug option is enabled. qa-unresolved-soname-deps Trigger a QA warning when a package installs files with unresolved soname dependencies. sandbox Enable sandbox-ing when running emerge(1) and ebuild(1). sesandbox Enable SELinux sandbox-ing. Do not toggle this FEATURE yourself. sfperms Stands for Smart Filesystem Permissions. Before merging packages to the live filesystem, automatically search for and set permissions on setuid and setgid files. Files that are setuid have the group and other read bits removed while files that are setgid have the other read bit removed. See also suidctl below. sign When commiting work to cvs with repoman(1), sign the Manifest with a GPG key. Read about the PORTAGE_GPG_KEY variable in make.conf(5). skiprocheck Skip write access checks on DISTDIR when fetching files. This is useful when FETCHCOMMAND and RESUMECOMMAND are used to forward fetch requests to a server that exposes DISTDIR as a read-only NFS share. A read-only DISTDIR is not compatible with the distlocks, so it is recommended to also add \"-distlocks\" to FEATURES in order to avoid warning messages that are triggered by this incompatibility. split-elog Store logs created by PORTAGE_ELOG_SYSTEM=\"save\" in category subdirectories of PORTAGE_LOGDIR/elog, instead of using PORTAGE_LOGDIR/elog directly. split-log Store build logs in category subdirectories of PORTAGE_LOGDIR/build, instead of using PORTAGE_LOGDIR directly. splitdebug Prior to stripping ELF etdyn and etexec files, the debugging info is stored for later use by various debuggers. This feature is disabled by nostrip. You should also consider setting compressdebug so the files don't suck up a lot of space. For installation of source code, see installsources. strict Have portage react strongly to conditions that have the potential to be dangerous (like missing or incorrect digests for ebuilds). strict-keepdir Have portage strictly require keepdir calls in ebuilds. Empty directories installed without explicit keepdir will be removed. This feature is automatically enabled for EAPI 8 and later. stricter Have portage react strongly to conditions that may conflict with system security provisions (for example textrels, executable stack). Read about the QA_STRICT_* variables in make.conf(5). suidctl Before merging packages to the live filesystem, automatically strip setuid bits from any file that is not listed in /etc/portage/suidctl.conf. test Run package-specific tests during each merge to help make sure the package compiled properly. See test in ebuild(1) and src_test() in ebuild(5). This feature implies the \"test\" USE flag if it is a member of IUSE, either explicitly or implicitly (see ebuild(5) for more information about IUSE). The \"test\" USE flag is also automatically disabled when the \"test\" feature is disabled. test-fail-continue If \"test\" is enabled FEATURES and the test phase of an ebuild fails, continue to execute the remaining phases as if the failure had not occurred. Note that the test phase for a specific package may be disabled by masking the \"test\" USE flag in package.use.mask (see portage(5)). unknown-features-filter Filter out any unknown values that the FEATURES variable contains. unknown-features-warn Warn if FEATURES contains one or more unknown values. unmerge-backup Call quickpkg(1) to create a backup of each package before it is unmerged (if a binary package of the same version does not already exist). Also see the related downgrade-backup feature. unmerge-logs Keep logs from successful unmerge phases. This is relevant only when PORTAGE_LOGDIR is set. unmerge-orphans If a file is not claimed by another package in the same slot and it is not protected by CONFIG_PROTECT, unmerge it even if the modification time or checksum differs from the file that was originally installed. userfetch When portage is run as root, drop privileges to portage:portage during the fetching of package sources. userpriv Allow portage to drop root privileges and compile packages as portage:portage without a sandbox (unless usersandbox is also used). usersandbox Enable the sandbox in the compile phase, when running without root privs (userpriv). usersync Drop privileges to the owner of ${repository_location} for emerge(1) --sync operations. Note that this feature assumes that all subdirectories of ${repository_location} have the same ownership as ${repository_location} itself. It is the user's responsibility to ensure correct ownership, since otherwise Portage would have to waste time validating ownership for each and every sync operation. warn-on-large-env Warn if portage is about to execute a child process with a large environment. webrsync-gpg Enable GPG verification when using emerge-webrsync. This feature is deprecated and has been replaced by the repos.conf sync-webrsync-verify-signature setting, see portage(5). xattr Preserve extended attributes (filesystem-stored metadata) when installing files (see attr(1)). The PORTAGE_XATTR_EXCLUDE variable may be used to exclude specific attributes from being preserved.", + "type": "string" + }, + "FETCHCOMMAND": { + "description": "This variable contains the command used for fetching package sources from the internet. It must contain the full path to the executable as well as the place-holders \\${DISTDIR}, \\${FILE} and \\${URI}. The command should be written to place the fetched file at \\${DISTDIR}/\\${FILE}. Also see RESUMECOMMAND. Optional FETCHCOMMAND Placeholders Placeholder Meaning Example \\${DIGESTS} Space separated list of file digests blake2b: sha512:", + "type": "string" + }, + "FFLAGS": { + "description": "```sh\nFFLAGS FCFLAGS\n```\nUse these variables to set the desired optimization/CPU instruction settings for applications that you compile with a FORTRAN compiler. FFLAGS is usually passed to the FORTRAN 77 compiler, and FCFLAGS to any FORTRAN compiler in more modern build systems.", + "type": "string" + }, + "GENTOO_MIRRORS": { + "description": "```sh\nGENTOO_MIRRORS = [URIs]\n```\nInsert your space-separated list of local mirrors here. These locations are used to download files before the ones listed in the ebuild scripts. Merging 'mirrorselect' can help. Entries in this variable that have no protocol and simply start with a '/' path separator may be used to specify mounted filesystem mirrors.", + "type": "string" + }, + "GPG_VERIFY_GROUP_DROP": { + "description": "```sh\nGPG_VERIFY_GROUP_DROP = [group]\n```\nThe group name used to drop root privileges during verification. Defaults to \"nogroup\"", + "type": "string" + }, + "GPG_VERIFY_USER_DROP": { + "description": "```sh\nGPG_VERIFY_USER_DROP = [user]\n```\nThe user name used to drop root privileges during verification. Defaults to \"nobody\"", + "type": "string" + }, + "INSTALL_MASK": { + "description": "```sh\nINSTALL_MASK = [space delimited list of filename patterns (globs)]\n```\nUse this variable if you want to selectively prevent certain files from being copied into your file system tree. This does not work on symlinks, but only on actual files (including directories). Useful if you wish to filter out files like HACKING.gz and TODO.gz.", + "type": "string" + }, + "LDFLAGS": { + "description": "A list of flags to pass to the compiler when the linker will be called. See ld(1) for linker flags, but don't forget that these flags will be passed directly to the compiler. Thus, you must use '-Wl' to escape the flags which only the linker understands (see gcc(1)).", + "type": "string" + }, + "MAKEOPTS": { + "description": "Use this variable if you want to use parallel make. For example, if you have a dual-processor system, set this variable to \"-j2\" or \"-j3\" for enhanced build performance with many packages. It is suggested that the jobs value used be the minimum of: available RAM divided by 2GB, or the number of threads on the system. In order to avoid excess load, the --load-average option is recommended. For more information, see make(1). Also see emerge(1) for information about analogous --jobs and --load-average options. If unset, defaults to using the number of processors to limit jobs (and load average via GNUMAKEFLAGS).", + "type": "string" + }, + "NO_COLOR": { + "description": "```sh\nNO_COLOR = [any string]\n```\nSet to any nonempty string (e.g. \"1\") to disable color by default. Defaults to unset.", + "type": "string" + }, + "NOCOLOR": { + "description": "```sh\nNOCOLOR = [\"true\" | \"false\"]\n```\nDefines if color should be disabled by default. Deprecated in favor of NO_COLOR. Defaults to false.", + "type": "string" + }, + "PKGDIR": { + "description": "```sh\nPKGDIR = [path]\n```\nDefines the location where created .tbz2 or .gpkg binary packages will be stored when the emerge(1) --buildpkg option is enabled. By default, a given package is stored in a subdirectory corresponding to its category. However, for backward compatibility with the layout used by older versions of portage, if the ${PKGDIR}/All directory exists then all packages will be stored inside of it and symlinks to the packages will be created in the category subdirectories.", + "type": "string" + }, + "PORT_LOGDIR": { + "description": "See PORTAGE_LOGDIR below. Deprecated.", + "type": "string" + }, + "PORT_LOGDIR_CLEAN": { + "description": "See PORTAGE_LOGDIR_CLEAN below. Deprecated.", + "type": "string" + }, + "PORTAGE_BINHOST": { + "description": "```sh\nPORTAGE_BINHOST = [space delimited URI list]\n```\nThis is a list of hosts from which portage will grab prebuilt-binary packages. Each entry in the list must specify the full address of a directory serving tbz2/gpkgs for your system (this directory must contain a 'Packages' index file). This is only used when running with the get binary pkg options are given to emerge. Review emerge(1) for more information. The PORTAGE_BINHOST variable is deprecated in favor of the binrepos.conf configuration file (see portage(5)).", + "type": "string" + }, + "PORTAGE_BINHOST_HEADER_URI": { + "description": "```sh\nPORTAGE_BINHOST_HEADER_URI = \"ftp://login:pass@grp.mirror.site/pub/grp/i686/athlon-xp/\"\n```\nThis variable only makes sense on a system that will serve as a binhost and build packages for clients. It defines the URI header field for the package index file which is located at ${PKGDIR}/Packages. Clients that have PORTAGE_BINHOST properly configured will be able to fetch the index and use the URI header field as a base URI for fetching binary packages. If the URI header field is not defined then the client will use its ${PORTAGE_BINHOST} setting as the base URI.", + "type": "string" + }, + "PORTAGE_BINPKG_FORMAT": { + "description": "This variable sets default format used for binary packages. Possible values are tar and rpm or both. It is very uncommon to set this and is likely not what you want. You probably want BINPKG_FORMAT instead.", + "type": "string" + }, + "PORTAGE_BINPKG_TAR_OPTS": { + "description": "This variable contains options to be passed to the tar command for creation of binary packages.", + "type": "string" + }, + "PORTAGE_BUNZIP2_COMMAND": { + "description": "```sh\nPORTAGE_BUNZIP2_COMMAND = [bunzip2 command string]\n```\nThis variable should contain a command that is suitable for portage to call for bunzip2 extraction operations.", + "type": "string" + }, + "PORTAGE_BZIP2_COMMAND": { + "description": "```sh\nPORTAGE_BZIP2_COMMAND = [bzip2 command string]\n```\nThis variable should contain a command that is suitable for portage to call for bzip2 compression operations. PORTAGE_BZIP2_COMMAND will also be called for extraction operation, with -d appended, unless the PORTAGE_BUNZIP2_COMMAND variable is set.", + "type": "string" + }, + "PORTAGE_CHECKSUM_FILTER": { + "description": "```sh\nPORTAGE_CHECKSUM_FILTER = [space delimited list of hash names]\n```\nThis variable may be used to filter the hash functions that are used to verify integrity of files. Hash function names are case-insensitive, and the * and -* wildcard tokens are supported. Defaults to the value of *. Examples:", + "type": "string" + }, + "PORTAGE_COMPRESS": { + "description": "```sh\nPORTAGE_COMPRESS = \"bzip2\"\n```\nThis variable contains the command used to compress documentation during the install phase.", + "type": "string" + }, + "PORTAGE_COMPRESS_EXCLUDE_SUFFIXES": { + "description": "```sh\nPORTAGE_COMPRESS_EXCLUDE_SUFFIXES = \"gif htm[l]? jp[e]?g pdf png\"\n```\nThis variable contains a space delimited list of file suffixes for which matching files are excluded when the PORTAGE_COMPRESS command is called. Regular expressions are supported and the match is performed only against the portion of the file name which follows the last period character.", + "type": "string" + }, + "PORTAGE_COMPRESS_FLAGS": { + "description": "```sh\nPORTAGE_COMPRESS_FLAGS = \"-9\"\n```\nThis variable contains flags for the PORTAGE_COMPRESS command.", + "type": "string" + }, + "PORTAGE_ELOG_CLASSES": { + "description": "", + "type": "string" + }, + "PORTAGE_ELOG_COMMAND": { + "description": "", + "type": "string" + }, + "PORTAGE_ELOG_MAILFROM": { + "description": "", + "type": "string" + }, + "PORTAGE_ELOG_MAILSUBJECT": { + "description": "", + "type": "string" + }, + "PORTAGE_ELOG_MAILURI": { + "description": "", + "type": "string" + }, + "PORTAGE_ELOG_SYSTEM": { + "description": "Please see /usr/share/portage/config/make.conf.example for elog documentation.", + "type": "string" + }, + "PORTAGE_FETCH_CHECKSUM_TRY_MIRRORS": { + "description": "```sh\nPORTAGE_FETCH_CHECKSUM_TRY_MIRRORS = 5\n```\nNumber of mirrors to try when a downloaded file has an incorrect checksum.", + "type": "string" + }, + "PORTAGE_FETCH_RESUME_MIN_SIZE": { + "description": "```sh\nPORTAGE_FETCH_RESUME_MIN_SIZE = 350K\n```\nMinimum size of existing file for RESUMECOMMAND to be called. Files smaller than this size will be removed and FETCHCOMMAND will be called to download the file from the beginning. This is useful for helping to ensure that small garbage files such as html 404 pages are properly discarded. The variable should contain an integer number of bytes and may have a suffix such as K, M, or G.", + "type": "string" + }, + "PORTAGE_GPG_DIR": { + "description": "The gpg(1) home directory that is used by repoman(1) when sign is in FEATURES. Defaults to $HOME/.gnupg.", + "type": "string" + }, + "PORTAGE_GPG_KEY": { + "description": "The gpg(1) key used by repoman(1) to sign manifests when sign is in FEATURES. In order to sign commits with git(1), you will need Git >=1.7.9 and your commit key will have to be configured by `git config user.signingkey key_id`.", + "type": "string" + }, + "PORTAGE_GPG_SIGNING_COMMAND": { + "description": "The command used by egencache(1) to sign manifests when sign is in FEATURES.", + "type": "string" + }, + "PORTAGE_GRPNAME": { + "description": "```sh\nPORTAGE_GRPNAME = [group]\n```\nDefines the groupname to use when executing in userpriv/etc... modes (i.e. non-root). Defaults to portage.", + "type": "string" + }, + "PORTAGE_INST_GID": { + "description": "```sh\nPORTAGE_INST_GID = [gid]\n```\nDefines the group id when installing files via dobin/dosbin. Useful when running ebuild as yourself. Defaults to 0.", + "type": "string" + }, + "PORTAGE_INST_UID": { + "description": "```sh\nPORTAGE_INST_UID = [uid]\n```\nDefines the user id when installing files via dobin/dosbin. Useful when running ebuild as yourself. Defaults to 0.", + "type": "string" + }, + "PORTAGE_IONICE_COMMAND": { + "description": "```sh\nPORTAGE_IONICE_COMMAND = [ionice command string]\n```\nThis variable should contain a command for portage to call in order to adjust the io priority of portage and its subprocesses. The command string should contain a \\${PID} place-holder that will be substituted with an integer pid. For example, a value of \"ionice -c 3 -p \\${PID}\" will set idle io priority. For more information about ionice, see ionice(1). This variable is unset by default. Portage will also set the autogroup-nice value (see fBsched(7))), if FEATURES=\"pid-sandbox\" is enabled.", + "type": "string" + }, + "PORTAGE_SCHEDULING_POLICY": { + "description": "```sh\nPORTAGE_SCHEDULING_POLICY = [policy name] Allows changing the\n```\ncurrent scheduling policy. The supported options are other, batch, idle, fifo, round-robin and deadline. When unset, the scheduling policy remains unchanged, by default Linux uses 'other' policy. Users that wish to minimize the Portage's impact on system responsiveness should set scheduling policy to idle, which significantly reduces the disruption to the rest of the system by scheduling Portage as extremely low priority processes. see sched(7) for more information.", + "type": "string" + }, + "PORTAGE_SCHEDULING_PRIORITY": { + "description": "```sh\nPORTAGE_SCHEDULING_PRIORITY = [priority]\n```\nAllows changing the priority (1-99) of the current scheduling policy, only applies if PORTAGE _SCHEDULING_POLICY is set to 'fifo' or 'round-robin', for others the only supported priority is 0, If unset, defaults to lowest priority of the selected scheduling policy. For more information about scheduler, see sched(7). This variable is unset by default.", + "type": "string" + }, + "PORTAGE_LOG_FILTER_FILE_CMD": { + "description": "This variable specifies a command that filters build log output to a log file. In order to filter ANSI escape codes from build logs, ansifilter(1) is a convenient setting for this variable. Generally, PORTAGE_LOG_FILTER_FILE_CMD should include a supervisor that falls back to cat if the real filter command fails after exec. For example, a supervisor is needed for ansifilter, in case it fails after exec due to a problem resolving libstdc++ during a gcc upgrade. Example:", + "type": "string" + }, + "PORTAGE_LOGDIR": { + "description": "This variable defines the directory in which per-ebuild logs are kept. Logs are created only when this is set. They are stored as ${CATEGORY}:${PF}:YYYYMMDD-HHMMSS.log in the directory specified. If the directory does not exist, it will be created automatically and group permissions will be applied to it. If the directory already exists, portage will not modify its permissions.", + "type": "string" + }, + "PORTAGE_LOGDIR_CLEAN": { + "description": "This variable should contain a command for portage to call in order to clean PORTAGE_LOGDIR. The command string should contain a \\${PORTAGE_LOGDIR} place-holder that will be substituted with the value of that variable. This variable will have no effect unless clean-logs is enabled in FEATURES.", + "type": "string" + }, + "PORTAGE_NICENESS": { + "description": "```sh\nPORTAGE_NICENESS = [number]\n```\nThe value of this variable will be added to the current nice level that emerge is running at. In other words, this will not set the nice level, it will increment it. For more information about nice levels and what are acceptable ranges, see nice(1).", + "type": "string" + }, + "PORTAGE_RO_DISTDIRS": { + "description": "```sh\nPORTAGE_RO_DISTDIRS = [space delimited list of directories]\n```\nWhen a given file does not exist in DISTDIR, search for the file in this list of directories. Search order is from left to right. Note that the current implementation works by creating a symlink inside DISTDIR, but that may change in the future.", + "type": "string" + }, + "PORTAGE_RSYNC_EXTRA_OPTS": { + "description": "```sh\nPORTAGE_RSYNC_EXTRA_OPTS = [rsync options string]\n```\nAdditional rsync options to be used by emerge --sync. Defaults to no value.", + "type": "string" + }, + "PORTAGE_RSYNC_INITIAL_TIMEOUT": { + "description": "```sh\nPORTAGE_RSYNC_INITIAL_TIMEOUT = integer\n```\nUsed by emerge --sync as a timeout for the initial connection to an rsync server. Defaults to 15 seconds.", + "type": "string" + }, + "PORTAGE_RSYNC_OPTS": { + "description": "```sh\nPORTAGE_RSYNC_OPTS = [rsync options string]\n```\nDefault rsync options to be used by emerge --sync. Don't change this unless you know exactly what you're doing! Defaults to \"--recursive --links --safe-links --perms --times --compress --force --whole-file --delete --stats --timeout=180 --exclude='/distfiles' --exclude='/local' --exclude='/packages'\"", + "type": "string" + }, + "PORTAGE_RSYNC_RETRIES": { + "description": "```sh\nPORTAGE_RSYNC_RETRIES = [NUMBER]\n```\nThe number of times rsync should retry on failed connections before giving up. If set to a negative number, then retry until all possible addresses are exhausted. Defaults to -1.", + "type": "string" + }, + "PORTAGE_SSH_OPTS": { + "description": "```sh\nPORTAGE_SSH_OPTS = [list of ssh options]\n```\nAdditional ssh options to be used when portage executes ssh or sftp. This variable supports use of embedded quote characters to quote whitespace or special shell characters within arguments (embedded quotes must be escaped in make.conf settings). Defaults to no value.", + "type": "string" + }, + "PORTAGE_SYNC_STALE": { + "description": "```sh\nPORTAGE_SYNC_STALE = [NUMBER]\n```\nDefines the number of days after the last `emerge --sync` that a warning message should be produced. A value of 0 will disable warnings. Defaults to 30.", + "type": "string" + }, + "PORTAGE_TMPDIR": { + "description": "```sh\nPORTAGE_TMPDIR = [path]\n```\nDefines the location of the temporary build directories.", + "type": "string" + }, + "PORTAGE_TRUST_HELPER": { + "description": "```sh\nPORTAGE_TRUST_HELPER = [path]\n```\nDefines an executable file which initializes and maintains /etc/portage/gnupg, installing keys that are trusted for binary package signing, and refreshing these keys from a key server. This helper is called before all operations involving remote binary packages if and only if binpkg-request-signature is in FEATURES. Defaults to \"/usr/bin/getuto\" (provided by app-portage/getuto).", + "type": "string" + }, + "PORTAGE_USERNAME": { + "description": "```sh\nPORTAGE_USERNAME = [user]\n```\nDefines the username to use when executing in userpriv/etc... modes (i.e. non-root). Defaults to portage.", + "type": "string" + }, + "PORTAGE_WORKDIR_MODE": { + "description": "```sh\nPORTAGE_WORKDIR_MODE = \"0700\"\n```\nThis variable controls permissions for WORKDIR (see ebuild(5)).", + "type": "string" + }, + "PORTAGE_XATTR_EXCLUDE": { + "description": "```sh\nPORTAGE_XATTR_EXCLUDE = [space delimited list of fnmatch patterns]\n```\nThis variable may be used to exclude specific attributes from being preserved when xattr is in FEATURES. Defaults to \"security.*\" (security labels are special, see bug #461868).", + "type": "string" + }, + "PORTDIR": { + "description": "```sh\nPORTDIR = [path]\n```\nDefines the location of main repository. This variable is deprecated in favor of settings in repos.conf. If you change this, you must update your /etc/portage/make.profile symlink accordingly. Defaults to /var/db/repos/gentoo. ***Warning*** Data stored inside PORTDIR is in peril of being overwritten or deleted by the emerge --sync command. The default value of PORTAGE_RSYNC_OPTS will protect the default locations of DISTDIR and PKGDIR, but users are warned that any other locations inside PORTDIR are not necessarily safe for data storage. You should not put other data (such as overlays) in your PORTDIR. Portage will walk directory structures and may arbitrarily add invalid categories as packages.", + "type": "string" + }, + "PORTDIR_OVERLAY": { + "description": "```sh\nPORTDIR_OVERLAY = \"[path] [different-path] [etc...]\"\n```\nDefines the locations of other repositories. This variable is deprecated in favor of settings in repos.conf. This variable is a space-delimited list of directories. Defaults to no value.", + "type": "string" + }, + "QA_STRICT_EXECSTACK": { + "description": "```sh\nQA_STRICT_EXECSTACK = \"set\"\n```\nSet this to cause portage to ignore any QA_EXECSTACK override settings from ebuilds. See also ebuild(5).", + "type": "string" + }, + "QA_STRICT_FLAGS_IGNORED": { + "description": "```sh\nQA_STRICT_FLAGS_IGNORED = \"set\"\n```\nSet this to cause portage to ignore any QA_FLAGS_IGNORED override settings from ebuilds. See also ebuild(5).", + "type": "string" + }, + "QA_STRICT_MULTILIB_PATHS": { + "description": "```sh\nQA_STRICT_MULTILIB_PATHS = \"set\"\n```\nSet this to cause portage to ignore any QA_MULTILIB_PATHS override settings from ebuilds. See also ebuild(5).", + "type": "string" + }, + "QA_STRICT_PRESTRIPPED": { + "description": "```sh\nQA_STRICT_PRESTRIPPED = \"set\"\n```\nSet this to cause portage to ignore any QA_PRESTRIPPED override settings from ebuilds. See also ebuild(5).", + "type": "string" + }, + "QA_STRICT_TEXTRELS": { + "description": "```sh\nQA_STRICT_TEXTRELS = \"set\"\n```\nSet this to cause portage to ignore any QA_TEXTREL override settings from ebuilds. See also ebuild(5).", + "type": "string" + }, + "QA_STRICT_WX_LOAD": { + "description": "```sh\nQA_STRICT_WX_LOAD = \"set\"\n```\nSet this to cause portage to ignore any QA_WX_LOAD override settings from ebuilds. See also ebuild(5).", + "type": "string" + }, + "ALLOW_TEST": { + "description": "```sh\nALLOW_TEST = [token]...\n```\nThis variable can be used to select the kinds of additional tests to run, particularly overriding RESTRICT=\"test\". It contains a whitespace-separated list of tokens. The following tokens are currently recognized: all Run tests in all packages, even if they specify RESTRICT=\"test\". This option is certain to cause test failures, it is intended to be used by developers when testing specific packages. network Run tests in packages specifying PROPERTIES=\"test_network\". Note that this will most likely cause Internet access during the test suite which could cause additional costs, privacy concerns and intermittent test failures.", + "type": "string" + }, + "RESUMECOMMAND": { + "description": "This variable contains the command used for resuming package sources that have been partially downloaded. It should be defined using the same format as FETCHCOMMAND, and must include any additional option(s) that may be necessary in order to continue a partially downloaded file located at \\${DISTDIR}/\\${FILE}.", + "type": "string" + }, + "ROOT": { + "description": "```sh\nROOT = [path]\n```\nUse ROOT to specify the target root filesystem to be used for merging packages or ebuilds. Typically, you should set this setting in the environment rather than in make.conf itself. It's commonly used for creating new build images. Make sure you use an absolute path. Refer to the Cross-compilation section of ebuild(5) for information about how dependencies are handled for ROOT. Defaults to /.", + "type": "string" + }, + "RPMDIR": { + "description": "```sh\nRPMDIR = [path]\n```\nDefines the location where created RPM packages will be stored. Defaults to /var/cache/rpm.", + "type": "string" + }, + "SYNC": { + "description": "```sh\nSYNC = [RSYNC]\n```\nInsert your preferred rsync mirror here. This rsync server is used to sync the local ebuild repository when `emerge --sync` is run.", + "type": "string" + }, + "UNINSTALL_IGNORE": { + "description": "```sh\nUNINSTALL_IGNORE = [space delimited list of fnmatch patterns]\n```\nThis variable prevents uninstallation of files that match specific fnmatch(3) patterns. In order to ignore file collisions with these files at install time, the same patterns can be added to the COLLISION_IGNORE variable. Defaults to \"/lib/modules/*\".", + "type": "string" + }, + "USE": { + "description": "```sh\nUSE = [space delimited list of USE items]\n```\nThis variable contains options that control the build behavior of several packages. More information in ebuild(5). Possible USE values can be found in /var/db/repos/gentoo/profiles/use.desc.", + "type": "string" + }, + "USE_ORDER": { + "description": "```sh\nUSE_ORDER = \"env:pkg:conf:defaults:pkginternal:features:repo:env.d\"\n```\nDetermines the precedence of layers in the incremental stacking of the USE variable. Precedence decreases from left to right such that env overrides pkg, pkg overrides conf, and so forth.", + "type": "string" + } + } +} diff --git a/src/termux_language_server/assets/json/makepkg.conf.json b/src/termux_language_server/assets/json/makepkg.conf.json new file mode 100644 index 0000000..db3b42b --- /dev/null +++ b/src/termux_language_server/assets/json/makepkg.conf.json @@ -0,0 +1,288 @@ +{ + "$id": "https://github.com/termux/termux-language-server/blob/main/src/termux_language_server/assets/json/makepkg.conf.json", + "$schema": "http://json-schema.org/draft-07/schema#", + "$comment": "Don't edit this file directly! It is generated by `termux-language-server --generate-schema=makepkg.conf`.", + "type": "object", + "properties": { + "DLAGENTS": { + "description": "```sh\nDLAGENTS=(protocol::/path/to/command [options] ...)\n```\nSets the download agents used to fetch source files specified with a URL in the \nPKGBUILD\n(5) file. Options can be specified for each command as well, and any protocol can have a download agent. Any spaces in option arguments are required to be escaped to avoid being split. Several examples are provided in the default makepkg.conf.\nIf present, %u will be replaced with the download URL. Otherwise, the download URL will be placed on the end of the command. If present, %o will be replaced with the local file name, plus a \u201c.part\u201d extension, which allows makepkg to handle resuming file downloads.", + "type": "array", + "items": { + "type": "string" + }, + "uniqueItems": true + }, + "VCSCLIENTS": { + "description": "```sh\nVCSCLIENTS=(protocol::package ...)\n```\nSets the packages required to fetch version controlled source files. When required, makepkg will check that these packages are installed or are included in the depends or makedepends arrays in the PKGBUILD.", + "type": "array", + "items": { + "type": "string" + }, + "uniqueItems": true + }, + "CARCH": { + "description": "```sh\nCARCH=\"carch\"\n```\nSpecifies your computer architecture; possible values include such things as \u201ci686\u201d, \u201cx86_64\u201d, \u201cppc\u201d, etc. This should be automatically set on installation.", + "type": "string" + }, + "CHOST": { + "description": "```sh\nCHOST=\"chost\"\n```\nA string such as \u201ci686-pc-linux-gnu\u201d; do not touch this unless you know what you are doing. This can be commented out by most users if desired.", + "type": "string" + }, + "CPPFLAGS": { + "description": "```sh\nCPPFLAGS=\"cppflags\"\n```\nFlags used for the C preprocessor; see CFLAGS for more information.", + "type": "string" + }, + "CFLAGS": { + "description": "```sh\nCFLAGS=\"cflags\"\n```\nFlags used for the C compiler. This is a key part to the use of makepkg. Usually several options are specified, and the most common string resembles something like this: \u201c-march=i686 -O2 -pipe\u201d. Another useful option may be -mcpu in place of -march. Read gcc(1) for more details on the wide variety of compiler flags available.", + "type": "string" + }, + "CXXFLAGS": { + "description": "```sh\nCXXFLAGS=\"cxxflags\"\n```\nFlags used for the C++ compiler; see CFLAGS for more info.", + "type": "string" + }, + "RUSTFLAGS": { + "description": "```sh\nRUSTFLAGS=\"rustflags\"\n```\nFlags used for the Rust compiler, similar in spirit to CFLAGS. Read \nrustc\n(1) for more details on the available flags.", + "type": "string" + }, + "LDFLAGS": { + "description": "```sh\nLDFLAGS=\"ldflags\"\n```\nFlags used for the linker. Several options may be specified with common usage resembling \u201c-Wl,--hash-style=gnu\u201d. Read ld(1) for more details on available linker flags.", + "type": "string" + }, + "LTOFLAGS": { + "description": "```sh\nLTOFLAGS=\"ltoflags\"\n```\nAdditional compiler and linker flags appended to CFLAGS, CXXFLAGS and LDFLAGS when building with link time optimization. If empty, \u201c-flto\u201d is used.", + "type": "string" + }, + "MAKEFLAGS": { + "description": "```sh\nMAKEFLAGS=\"makeflags\"\n```\nThis is often used to set the number of jobs used; for example, -j2. Other flags that make accepts can also be passed.", + "type": "string" + }, + "DEBUG_CFLAGS": { + "description": "```sh\nDEBUG_CFLAGS=\"debug_cflags\"\n```\nAdditional compiler flags appended to CFLAGS for use in debugging. Usually this would include: \u201c-g\u201d. Read gcc(1) for more details on the wide variety of compiler flags available.", + "type": "string" + }, + "DEBUG_CXXFLAGS": { + "description": "```sh\nDEBUG_CXXFLAGS=\"debug_cxxflags\"\n```\nDebug flags used for the C++ compiler; see DEBUG_CFLAGS for more info.", + "type": "string" + }, + "DEBUG_RUSTFLAGS": { + "description": "```sh\nDEBUG_RUSTFLAGS=\"debug_rustflags\"\n```\nAdditional compiler flags appended to RUSTFLAGS for use in debugging. Usually this would include: \u201c-C debuginfo=2\u201d. Read \nrustc\n(1) for more details on the available flags.", + "type": "string" + }, + "BUILDENV": { + "description": "```sh\nBUILDENV=(!distcc !color !ccache check !sign)\n```\nThis array contains options that affect the build environment; the defaults are shown here. All options should always be left in the array; to enable or disable an option, simply remove or add an \u201c!\u201d at the front of the option. If an option is specified multiple times, the final value takes precedence. Each option works as follows:\ndistcc\nUse the distributed C/C++/ObjC compiler to spread compilation among multiple machines. If this is enabled, DISTCC_HOSTS must be specified as well.\ncolor\nColorize output messages, making output easier to read.\nccache\nUse ccache to cache compilation by default. This allows for faster compiles if you are continuously recompiling the same packages. It can be disabled for individual packages by placing !ccache in the PKGBUILD options array.\ncheck\nRun the check() function if present in the PKGBUILD. This can be enabled or disabled for individual packages through the use of makepkg\u2019s \n--check\n and \n--nocheck\n options, respectively.\nsign\nGenerate a PGP signature file using GnuPG. This will execute \ngpg --detach-sign --use-agent\n on the built package to generate a detached signature file, using the GPG agent, if it is available. The signature file will be the entire file name of the package with a \u201c.sig\u201d extension.", + "type": "array", + "items": { + "type": "string", + "enum": [ + "distcc", + "!distcc", + "color", + "!color", + "ccache", + "!ccache", + "check", + "!check", + "sign", + "!sign" + ] + }, + "uniqueItems": true + }, + "DISTCC_HOSTS": { + "description": "```sh\nDISTCC_HOSTS=\"host1 ...\"\n```\nIf using DistCC, this is used to specify a space-delimited list of hosts running in the DistCC cluster. In addition, you will want to modify your MAKEFLAGS.", + "type": "string" + }, + "BUILDDIR": { + "description": "```sh\nBUILDDIR=\"/path/to/directory\"\n```\nIf this value is not set, packages will, by default, be built in subdirectories of the directory that makepkg is called from. This option allows setting the build location to another directory. Incorrect use of $startdir in a PKGBUILD may cause building with this option to fail.", + "type": "string" + }, + "GPGKEY": { + "description": "```sh\nGPGKEY=\"\"\n```\nSpecify a key to use for GPG signing instead of the default key in the keyring. Can be overridden with makepkg\u2019s \n--key\n option.", + "type": "string" + }, + "OPTIONS": { + "description": "```sh\nOPTIONS=(!strip docs libtool staticlibs emptydirs !zipman !purge !debug)\n```\nThis array contains options that affect default packaging. They are equivalent to options that can be placed in the PKGBUILD; the defaults are shown here. All options should always be left in the array; to enable or disable an option, simply remove or add an \u201c!\u201d at the front of the option. If an option is specified multiple times, the final value takes precedence. Each option works as follows:\nstrip\nStrip symbols from binaries and libraries. If you frequently use a debugger on programs or libraries, it may be helpful to disable this option.\ndocs\nSave doc directories. If you wish to delete doc directories, specify !docs in the array. The directories affected are specified by the DOC_DIRS variable.\nlibtool\nLeave libtool (.la) files in packages. Specify !libtool to remove them.\nstaticlibs\nLeave static library (.a) files in packages. Specify !staticlibs to remove them, if they have a shared counterpart.\nemptydirs\nLeave empty directories in packages.\nzipman\nCompress manual (man and info) pages with gzip. The directories affected are specified by the MAN_DIRS variable.\npurge\nRemove files specified by the PURGE_TARGETS variable from the package.\ndebug\nAdd the user-specified debug flags as specified in DEBUG_CFLAGS and DEBUG_CXXFLAGS to their counterpart buildflags. Creates a separate package containing the debug symbols when used with \u2018strip\u2019.\nlto\nEnable building packages using link time optimization. Adds the flags specified in LTOFLAGS to CFLAGS, CXXFLAGS and LDFLAGS (or \u201c-flto\u201d if LTOFLAGS is empty).", + "type": "array", + "items": { + "type": "string", + "enum": [ + "strip", + "!strip", + "docs", + "!docs", + "libtool", + "!libtool", + "staticlibs", + "!staticlibs", + "emptydirs", + "!emptydirs", + "zipman", + "!zipman", + "purge", + "!purge", + "debug", + "!debug", + "lto", + "!lto" + ] + }, + "uniqueItems": true + }, + "INTEGRITY_CHECK": { + "description": "```sh\nINTEGRITY_CHECK=(check1 ...)\n```\nFile integrity checks to use. Multiple checks may be specified; this affects both generation and checking. The current valid options are: ck, md5, sha1, sha224, sha256, sha384, sha512, and b2.", + "type": "array", + "items": { + "type": "string" + }, + "uniqueItems": true + }, + "STRIP_BINARIES": { + "description": "```sh\nSTRIP_BINARIES=\"--strip-all\"\n```\nOptions to be used when stripping binaries. See \nstrip\n(1) for details.", + "type": "string" + }, + "STRIP_SHARED": { + "description": "```sh\nSTRIP_SHARED=\"--strip-unneeded\"\n```\nOptions to be used when stripping shared libraries or PIE executables. See \nstrip\n(1) for details.", + "type": "string" + }, + "STRIP_STATIC": { + "description": "```sh\nSTRIP_STATIC=\"--strip-debug\"\n```\nOptions to be used when stripping static libraries. See \nstrip\n(1) for details.", + "type": "string" + }, + "MAN_DIRS": { + "description": "```sh\nMAN_DIRS=({usr{,/local}{,/share},opt/*}/{man,info} ...)\n```\nIf zipman is specified in the OPTIONS array, this variable will instruct makepkg where to look to compress manual (man and info) pages. If you build packages that are located in opt/, you may need to add the directory to this array. \nNOTE:\n Do not add the leading slash to the directory name.", + "type": "array", + "items": { + "type": "string" + }, + "uniqueItems": true + }, + "DOC_DIRS": { + "description": "```sh\nDOC_DIRS=(usr/{,share/}{doc,gtk-doc} ...)\n```\nIf !docs is specified in the OPTIONS array, this variable will instruct makepkg where to look to remove docs. If you build packages that are located in opt/, you may need to add the directory to this array. \nNOTE:\n Do not add the leading slash to the directory name.", + "type": "array", + "items": { + "type": "string" + }, + "uniqueItems": true + }, + "PURGE_TARGETS": { + "description": "```sh\nPURGE_TARGETS=(usr/{,share}/info/dir .podlist *.pod...)\n```\nIf purge is specified in the OPTIONS array, this variable will instruct makepkg which files to remove from the package. This is useful for index files that are added by multiple packages.", + "type": "array", + "items": { + "type": "string" + }, + "uniqueItems": true + }, + "DBGSRCDIR": { + "description": "```sh\nDBGSRCDIR=\"/usr/src/debug\"\n```\nIf strip and debug are specified in the OPTIONS array, this variable will instruct makepkg where to place source files for installed binaries. The binaries will be modified to link this directory for the debugger search path.", + "type": "string" + }, + "PKGDEST": { + "description": "```sh\nPKGDEST=\"/path/to/directory\"\n```\nIf this value is not set, packages will, by default, be placed in the current directory (location of the \nPKGBUILD\n(5)). Many people like to keep all their packages in one place so this option allows for this behavior. A common location is \u201c/home/packages\u201d.", + "type": "string" + }, + "SRCDEST": { + "description": "```sh\nSRCDEST=\"/path/to/directory\"\n```\nIf this value is not set, downloaded source files will only be stored in the current directory. Many people like to keep all source files in a central location for easy cleanup, so this path can be set here.", + "type": "string" + }, + "SRCPKGDEST": { + "description": "```sh\nSRCPKGDEST=\"/path/to/directory\"\n```\nIf this value is not set, source package files will be stored in in the current directory. Many people like to keep all source package files in a central location for easy cleanup, so this path can be set here.", + "type": "string" + }, + "LOGDEST": { + "description": "```sh\nLOGDEST=\"/path/to/directory\"\n```\nIf this value is not set, log files are written to the current directory. This centralizes the log location, facilitating cleanup and compression.", + "type": "string" + }, + "PACKAGER": { + "description": "```sh\nPACKAGER=\"John Doe \"\n```\nThis value is used when querying a package to see who was the builder. The given format is required for PGP key lookup through WKD. It is recommended to change this to your name and email address.", + "type": "string" + }, + "COMPRESSGZ": { + "description": "```sh\nCOMPRESSGZ=\"(gzip -c -f -n)\", \n```\nSets the command and options used when compressing compiled or source packages in the named format.", + "type": "array", + "items": { + "type": "string" + }, + "uniqueItems": true + }, + "COMPRESSBZ2": { + "description": "```sh\nCOMPRESSBZ2=\"(bzip2 -c -f)\", \n```\nSets the command and options used when compressing compiled or source packages in the named format.", + "type": "array", + "items": { + "type": "string" + }, + "uniqueItems": true + }, + "COMPRESSXZ": { + "description": "```sh\nCOMPRESSXZ=\"(xz -c -z -)\", \n```\nSets the command and options used when compressing compiled or source packages in the named format.", + "type": "array", + "items": { + "type": "string" + }, + "uniqueItems": true + }, + "COMPRESSZST": { + "description": "```sh\nCOMPRESSZST=\"(zstd -c -z -)\", \n```\nSets the command and options used when compressing compiled or source packages in the named format.", + "type": "array", + "items": { + "type": "string" + }, + "uniqueItems": true + }, + "COMPRESSLZO": { + "description": "```sh\nCOMPRESSLZO=\"(lzop -q)\", \n```\nSets the command and options used when compressing compiled or source packages in the named format.", + "type": "array", + "items": { + "type": "string" + }, + "uniqueItems": true + }, + "COMPRESSLRZ": { + "description": "```sh\nCOMPRESSLRZ=\"(lrzip -q)\", \n```\nSets the command and options used when compressing compiled or source packages in the named format.", + "type": "array", + "items": { + "type": "string" + }, + "uniqueItems": true + }, + "COMPRESSLZ4": { + "description": "```sh\nCOMPRESSLZ4=\"(lz4 -q)\", \n```\nSets the command and options used when compressing compiled or source packages in the named format.", + "type": "array", + "items": { + "type": "string" + }, + "uniqueItems": true + }, + "COMPRESSZ": { + "description": "```sh\nCOMPRESSZ=\"(compress -c -f)\", \n```\nSets the command and options used when compressing compiled or source packages in the named format.", + "type": "array", + "items": { + "type": "string" + }, + "uniqueItems": true + }, + "COMPRESSLZ": { + "description": "```sh\nCOMPRESSLZ=\"(lzip -c -f)\"\n```\nSets the command and options used when compressing compiled or source packages in the named format.", + "type": "array", + "items": { + "type": "string" + }, + "uniqueItems": true + }, + "PKGEXT": { + "description": "```sh\nPKGEXT=\".pkg.tar.gz\", \n```\nSets the compression used when making compiled or source packages. Valid suffixes are .tar.gz, .tar.bz2, .tar.xz, .tar.zst, .tar.lzo, .tar.lrz, .tar.lz4, .tar.lz and .tar.Z, or simply .tar to disable compression entirely.", + "type": "string" + }, + "SRCEXT": { + "description": "```sh\nSRCEXT=\".src.tar.gz\"\n```\nSets the compression used when making compiled or source packages. Valid suffixes are .tar.gz, .tar.bz2, .tar.xz, .tar.zst, .tar.lzo, .tar.lrz, .tar.lz4, .tar.lz and .tar.Z, or simply .tar to disable compression entirely.", + "type": "string" + }, + "PACMAN_AUTH": { + "description": "```sh\nPACMAN_AUTH=()\n```\nSpecify a command prefix for running pacman as root. If unset, makepkg will check for the presence of sudo(8) and su(1) in turn, and try the first one it finds.\nIf present, %c will be replaced with the shell-quoted form of the command to run. Otherwise, the command to run is appended to the auth command.", + "type": "array", + "items": { + "type": "string" + }, + "uniqueItems": true + } + } +} diff --git a/src/termux_language_server/assets/json/mdd.json b/src/termux_language_server/assets/json/mdd.json new file mode 100644 index 0000000..66eabf6 --- /dev/null +++ b/src/termux_language_server/assets/json/mdd.json @@ -0,0 +1,62 @@ +{ + "$id": "https://github.com/termux/termux-language-server/blob/main/src/termux_language_server/assets/json/mdd.json", + "$schema": "http://json-schema.org/draft-07/schema#", + "$comment": "https://github.com/zsh-users/zsh/blob/57248b88830ce56adc243a40c7773fb3825cab34/Etc/zsh-development-guide#L285-L288", + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "name of the module" + }, + "link": { + "type": "string", + "enum": ["static", "dynamic", "no"], + "description": "as described in INSTALL. In addition, the value `either` is allowed in the .mdd file, which will be converted by configure to `dynamic` if that is available, else `static`. May also be a command string, which will be run within configure and whose output is used to set the value of `link` in config.modules. This allows a system-specific choice of modules. For example, \n```zsh\nlink=`case $host in\n *-hpux*) echo dynamic;\n ;;\n *) echo no;\n ;;\n esac`\n```" + }, + "load": { + "type": "string", + "enum": ["yes", "no"], + "description": "whether the shell should include hooks for loading the module automatically as necessary. (This corresponds to an `L` in xmods.conf in the old mechanism.)" + }, + "moddeps": { + "type": "string", + "description": "modules on which this module depends (default none)" + }, + "nozshdep": { + "type": "string", + "description": "non-empty indicates no dependence on the `zsh/main' pseudo-module" + }, + "alwayslink": { + "type": "string", + "description": "if non-empty, always link the module into the executable" + }, + "autofeatures": { + "type": "string", + "description": "features defined by the module for autoloading, a space-separated list. The syntax for features is as for zmodload -F, e.g. b:mybin refers to the builtin mybin. This replaces the previous mechanism with separate variables for builtins, conditions, math functions and parameters. Note the features are only available in zsh's native mode, not in emulation modes." + }, + "autofeatures_emu": { + "type": "string", + "description": "As autofeatures, but the features so presented are available in modes that are *not* zsh's native mode. The variable autofeatures must also be present." + }, + "objects": { + "type": "string", + "description": ".o files making up this module (*must* be defined)" + }, + "proto": { + "type": "string", + "description": ".syms files for this module (default generated from $objects)" + }, + "headers": { + "type": "string", + "description": "extra headers for this module (default none)" + }, + "hdrdeps": { + "type": "string", + "description": "extra headers on which the .mdh depends (default none)" + }, + "otherincs": { + "type": "string", + "description": "extra headers that are included indirectly (default none)" + } + } +} diff --git a/src/termux_language_server/assets/json/subpackage.sh.json b/src/termux_language_server/assets/json/subpackage.sh.json new file mode 100644 index 0000000..6bc4614 --- /dev/null +++ b/src/termux_language_server/assets/json/subpackage.sh.json @@ -0,0 +1,148 @@ +{ + "$id": "https://github.com/termux/termux-language-server/blob/main/src/termux_language_server/assets/json/subpackage.sh.json", + "$schema": "http://json-schema.org/draft-07/schema#", + "$comment": "Don't edit this file directly! It is generated by `termux-language-server --generate-schema=subpackage.sh`.", + "type": "object", + "required": [ + "TERMUX_SUBPKG_DESCRIPTION", + "TERMUX_SUBPKG_INCLUDE" + ], + "properties": { + "TERMUX_SUBPKG_DESCRIPTION": { + "type": "string", + "description": "Short, one-line description of subpackage." + }, + "TERMUX_SUBPKG_DEPEND_ON_PARENT": { + "type": "string", + "description": "Specifies way how subpackage should depend on parent. See Subpackage dependencies for more information." + }, + "TERMUX_SUBPKG_DEPENDS": { + "type": "string", + "description": "Comma-separated list of subpackage dependencies.", + "pattern": "[a-z][a-z0-9-]*(, [a-z][a-z0-9-]*)*" + }, + "TERMUX_SUBPKG_BREAKS": { + "type": "string", + "description": "Comma-separated list of packages that are incompatible with the current one.", + "pattern": "[a-z][a-z0-9-]*(, [a-z][a-z0-9-]*)*" + }, + "TERMUX_SUBPKG_CONFLICTS": { + "type": "string", + "description": "Comma-separated list of packages which have file name collisions with the current one.", + "pattern": "[a-z][a-z0-9-]*(, [a-z][a-z0-9-]*)*" + }, + "TERMUX_SUBPKG_REPLACES": { + "type": "string", + "description": "Comma-separated list of packages being replaced by current one.", + "pattern": "[a-z][a-z0-9-]*(, [a-z][a-z0-9-]*)*" + }, + "TERMUX_SUBPKG_ESSENTIAL": { + "type": "string", + "description": "Whether to treat subpackage as essential which cannot be uninstalled in usual way. Default is false.", + "default": "false", + "enum": [ + "true", + "false" + ] + }, + "TERMUX_SUBPKG_PLATFORM_INDEPENDENT": { + "type": "string", + "description": "Whether to treat subpackage as platform independent. Default is false.", + "default": "false", + "enum": [ + "true", + "false" + ] + }, + "TERMUX_SUBPKG_INCLUDE": { + "type": "string", + "description": "A space or newline separated list of files to be included in subpackage." + }, + "TERMUX_SUBPKG_CONFFILES": { + "type": "string", + "description": "A space or newline separated list of package configuration files that should not be overwritten on update." + } + }, + "propertyNames": { + "not": { + "anyOf": [ + { + "const": "TERMUX_ON_DEVICE_BUILD", + "description": "If set, assume that building on device." + }, + { + "const": "TERMUX_BUILD_IGNORE_LOCK", + "description": "If set to true, ignore build process lock." + }, + { + "const": "TERMUX_BUILD_LOCK_FILE", + "description": "Path to build process lock file." + }, + { + "const": "TERMUX_HOST_PLATFORM", + "description": "Host platform definition. Usually $TERMUX_ARCH-linux-android." + }, + { + "const": "TERMUX_PKG_BUILDDIR", + "description": "Path to build directory of current package." + }, + { + "const": "TERMUX_PKG_BUILDER_DIR", + "description": "Path to directory where located build.sh of current package." + }, + { + "const": "TERMUX_PKG_BUILDER_SCRIPT", + "description": "Path to build.sh of current package." + }, + { + "const": "TERMUX_PKG_CACHEDIR", + "description": "Path to source cache directory of current package." + }, + { + "const": "TERMUX_PKG_MASSAGEDIR", + "description": "Path to directory where package content will be extracted from $TERMUX_PREFIX." + }, + { + "const": "TERMUX_PKG_PACKAGEDIR", + "description": "Path to directory where components of *.deb archive of current package will be created." + }, + { + "const": "TERMUX_PKG_SRCDIR", + "description": "Path to source directory of current package." + }, + { + "const": "TERMUX_PKG_TMPDIR", + "description": "Path to temporary directory specific for current package." + }, + { + "const": "TERMUX_COMMON_CACHEDIR", + "description": "Path to global cache directory where build tools are stored." + }, + { + "const": "TERMUX_SCRIPTDIR", + "description": "Path to directory with utility scripts." + }, + { + "const": "TERMUX_PKG_NAME", + "description": "Name of current package." + }, + { + "const": "TERMUX_REPO_URL", + "description": "Array of APT repository URLs from which dependencies will be downloaded if ./build-package.sh got option -i or -I." + }, + { + "const": "TERMUX_REPO_DISTRIBUTION", + "description": "Array of distribution names in addition for TERMUX_REPO_URL." + }, + { + "const": "TERMUX_REPO_COMPONENT", + "description": "Array of repository component names in addition for TERMUX_REPO_URL." + }, + { + "const": "TERMUX_PACKAGE_FORMAT", + "description": "Package output format." + } + ] + } + } +} \ No newline at end of file diff --git a/src/termux_language_server/assets/json/termux.json b/src/termux_language_server/assets/json/termux.json deleted file mode 100644 index 5f63358..0000000 --- a/src/termux_language_server/assets/json/termux.json +++ /dev/null @@ -1 +0,0 @@ -[{"termux_error_exit": ["Function to write error message to stderr and exit.", ""], "termux_download": ["Utility function to download any file.", ""], "termux_setup_golang": ["Setup Go Build environment.", ""], "termux_setup_cmake": ["Setup CMake configure system.", ""], "termux_setup_ninja": ["Setup Ninja make system.", ""], "termux_setup_meson": ["Setup Meson configure system.", ""], "termux_setup_protobuf": ["Setup Protobuf compiler.", ""], "termux_setup_rust": ["Setup Cargo Build.", ""], "termux_setup_ghc_cross_compiler": ["Setup ghc cross-compiler targeting Android.", ""], "termux_setup_ghc": ["Setup ghc compiler for host build.", ""], "termux_setup_jailbreak_cabal": ["Setup jailbreak-cabal utility. It is used to remove version constraints from Haskell (with cabal build system)", ""], "termux_step_setup_variables": ["Setup essential variables like directory locations and flags.", ""], "termux_step_handle_buildarch": ["Determine architecture to build for.", ""], "termux_step_setup_build_folders": ["Delete old src and build directories if they exist.", ""], "termux_step_start_build": ["Initialize build environment. Source package's build.sh.", ""], "termux_step_get_dependencies": ["Download or build specified dependencies of the package.", ""], "termux_step_get_repo_files": ["Fetch APT packages information when -i or -I option was supplied.", ""], "termux_extract_dep_info": ["Obtain package architecture and version for downloading.", ""], "termux_step_create_timestamp_file": ["Make timestamp to determine which files have been installed by the build.", ""], "termux_download_deb": ["Download dependency *.deb packages for installation.", ""], "termux_step_get_source()": ["Obtain package source code and put it in $TERMUX_PKG_SRCDIR.", ""], "termux_git_clone_src": ["Obtain source by git clone, is run if $TERMUX_PKG_SRCURL ends with \".git\".", ""], "termux_download_src_archive": ["Download zip or tar archive with package source code.", ""], "termux_unpack_src_archive": ["Extract downloaded archive into $TERMUX_PKG_SRCDIR.", ""], "termux_step_post_get_source()": ["Hook to run commands immediately after obtaining source code.", ""], "termux_step_handle_host_build()": ["Determine whether a host build is required.", ""], "termux_step_host_build()": ["Perform a host build.", ""], "termux_step_setup_toolchain": ["Setup NDK standalone toolchain.", ""], "termux_step_patch_package": ["Apply to source code all *.patch files located in package's directory.", ""], "termux_step_replace_guess_scripts": ["Replace config.sub and config.guess scripts.", ""], "termux_step_pre_configure()": ["Hook to run commands before source configuration.", ""], "termux_step_configure()": ["Configure sources. By default, it determines build system automatically.", ""], "termux_step_configure_haskell_build": ["Haskell packages build configuration.", ""], "termux_step_configure_autotools": ["Autotools build configuration.", ""], "termux_step_configure_cmake": ["CMake build configuration.", ""], "termux_step_configure_meson": ["Meson build configuration.", ""], "termux_step_post_configure()": ["Hook to run commands immediately after configuration.", ""], "termux_step_make()": ["Compile the source code.", ""], "termux_step_make_install()": ["Install the compiled artifacts.", ""], "termux_step_post_make_install()": ["Hook to run commands immediately after installation.", ""], "termux_step_install_service_scripts()": ["Installs scripts for termux-services", ""], "termux_step_install_license()": ["Link or copy package-specific LICENSE to ./share/doc/$TERMUX_PKG_NAME.", ""], "termux_step_extract_into_massagedir": ["Extract files modified in $TERMUX_PREFIX.", ""], "termux_step_massage": ["Strip binaries, remove unneeded files.", ""], "termux_create_debian_subpackages": ["Creates all subpackages (debian format).", ""], "termux_create_pacman_subpackages": ["Creates all subpackages (pacman format).", ""], "termux_step_post_massage()": ["Final hook before creating *.deb file(s).", ""], "termux_step_create_debian_package": ["Create *.deb package.", ""], "termux_step_create_pacman_package": ["Create *.pkg.tar.xz package.", ""], "termux_step_create_debscripts()": ["Create maintainer scripts, e.g. pre/post installation hooks.", ""], "termux_step_create_pacman_install_hook": ["Convert result of termux_step_create_debscripts to pacman-compatible format.", ""], "termux_step_finish_build": ["Notification of finish.", ""], "termux_github_api_get_tag": ["Query GitHub API for: \u2022 latest-release-tag: useful for projects using github's release mechanism. \u2022 newest-tag(sorted by commit date): useful for projects having tags but no releases.", ""], "termux_gitlab_api_get_tag": ["same as above, but for gitlab", ""], "termux_repology_api_get_latest_version": ["Query repology api for latest version.", ""], "termux_pkg_auto_update": ["By default, decide which method (gitlab, github or repology) to use for update, but can be overrided to use custom method (See here).", ""], "termux_github_auto_update": ["Default update method for packages hosted on github.com. It decides which type of tag to fetch based on TERMUX_PKG_SRCURL.", ""], "termux_gitlab_auto_update": ["Default update method for packages hosted on gitlab.com (or host specified by TERMUX_GITLAB_API_HOST). It decides which type of tag to fetch based on TERMUX_PKG_SRCURL.", ""], "termux_pkg_upgrade_version": ["Write the latest version and updated checksum, check whether updated package builds properly and then push changes to repo.", ""], "termux_pkg_is_update_needed": ["Check whether LATEST_VERSION is greater than TERMUX_PKG_VERSION or not. Called if --skip-version-check was not passed to termux_pkg_upgrade_version. NOTE: You should not call it manually otherwise if TERMUX_PKG_UPDATE_VERSION_REGEXP is used, it won't compare versions extracted from it. Version is extracted by termux_pkg_upgrade_version.", ""], "TERMUX_PKG_HOMEPAGE": ["Home page URL.", "build.sh"], "TERMUX_PKG_DESCRIPTION": ["Short, one-line description of package.", "build.sh"], "TERMUX_PKG_LICENSE": ["Package license.", "build.sh"], "TERMUX_PKG_LICENSE_FILE": ["Name of license file, if it is not found automatically.", "build.sh"], "TERMUX_PKG_MAINTAINER": ["Package maintainer.", "build.sh"], "TERMUX_PKG_API_LEVEL": ["Android API level for which package should be compiled.", "build.sh"], "TERMUX_PKG_VERSION": ["Original package version.", "build.sh"], "TERMUX_PKG_REVISION": ["Package revision. Bumped on each package rebuild.", "build.sh"], "TERMUX_PKG_SKIP_SRC_EXTRACT": ["Whether to omit source code downloading and extraction. Default is false.", "build.sh"], "TERMUX_PKG_SRCURL": ["URL from which source archive should be downloaded, either an archive or a git url ending with .git", "build.sh"], "TERMUX_PKG_SHA256": ["SHA-256 checksum of source archive.", "build.sh"], "TERMUX_PKG_GIT_BRANCH": ["Branch to checkout in termux_step_git_clone_src. Default is v$TERMUX_PKG_VERSION.", "build.sh"], "TERMUX_PKG_METAPACKAGE": ["Whether to make package treated as metapackage. Default is false.", "build.sh"], "TERMUX_PKG_DEPENDS": ["Comma-separated list of dependency package names.", "build.sh"], "TERMUX_PKG_BUILD_DEPENDS": ["Comma-separated list of build-time only dependencies.", "build.sh"], "TERMUX_PKG_BREAKS": ["Comma-separated list of packages that are incompatible with the current one.", "build.sh"], "TERMUX_PKG_CONFLICTS": ["Comma-separated list of packages which have file name collisions with the current one.", "build.sh"], "TERMUX_PKG_REPLACES": ["Comma-separated list of packages being replaced by current one.", "build.sh"], "TERMUX_PKG_PROVIDES": ["Comma-separated list of virtual packages being provided by current one.", "build.sh"], "TERMUX_PKG_RECOMMENDS": ["Comma-separated list of non-absolute dependencies - packages usually used with the current one.", "build.sh"], "TERMUX_PKG_SUGGESTS": ["Comma-separated list of packages that are related to or enhance the current one.", "build.sh"], "TERMUX_PKG_ESSENTIAL": ["Whether to treat package as essential which cannot be uninstalled in usual way. Default is false.", "build.sh"], "TERMUX_PKG_NO_STATICSPLIT": ["Whether to split static libraries into a subpackage. Default is false.", "build.sh"], "TERMUX_PKG_STATICSPLIT_EXTRA_PATTERNS": ["Extra patterns to include in static package. It must be relative to $TERMUX_PREFIX. For example: to include *.h files from $TERMUX_PREFIX/lib, specify lib/*.h. You can use bash globstar patterns to recurse sub-directories.", "build.sh"], "TERMUX_PKG_IS_HASKELL_LIB": ["Whether the package is haskell library. Default is false.", "build.sh"], "TERMUX_PKG_BUILD_IN_SRC": ["Whether to perform build in a source code directory. Default is false.", "build.sh"], "TERMUX_PKG_HAS_DEBUG": ["Whether debug builds are possible for package. Default is true.", "build.sh"], "TERMUX_PKG_PLATFORM_INDEPENDENT": ["Whether to treat package as platform independent. Default is false.", "build.sh"], "TERMUX_PKG_BLACKLISTED_ARCHES": ["Comma-separated list of CPU architectures for which package cannot be compiled.", "build.sh"], "TERMUX_PKG_HOSTBUILD": ["Whether package require building for host. Default is false.", "build.sh"], "TERMUX_PKG_FORCE_CMAKE": ["Whether to prefer CMake over Autotools configure script. Default is false.", "build.sh"], "TERMUX_PKG_EXTRA_CONFIGURE_ARGS": ["Extra arguments passed to build system configuration utility.", "build.sh"], "TERMUX_PKG_EXTRA_HOSTBUILD_CONFIGURE_ARGS": ["Extra arguments passed to build system configuration utility when performing host build.", "build.sh"], "TERMUX_PKG_EXTRA_MAKE_ARGS": ["Extra arguments passed to utility make.", "build.sh"], "TERMUX_PKG_MAKE_INSTALL_TARGET": ["Equivalent for install argument passed to utility make in the installation process.", "build.sh"], "TERMUX_PKG_RM_AFTER_INSTALL": ["List of files that should be removed after installation process.", "build.sh"], "TERMUX_PKG_CONFFILES": ["A space or newline separated list of package configuration files that should not be overwritten on update.", "build.sh"], "TERMUX_PKG_SERVICE_SCRIPT": ["Array of even length containing daemon name(s) and script(s) for use with termux-services/runit.", "build.sh"], "TERMUX_PKG_GO_USE_OLDER": ["Use the older supported release of Go (1.19.7). Default is false.", "build.sh"], "TERMUX_PKG_NO_STRIP": ["Disable stripping binaries. Default is false.", "build.sh"], "TERMUX_PKG_NO_SHEBANG_FIX": ["Skip fixing shebang accordingly to $TERMUX_PREFIX. Default is false.", "build.sh"], "TERMUX_PKG_NO_ELF_CLEANER": ["Disable running of termux-elf-cleaner on built binaries. Default is false.", "build.sh"], "TERMUX_SUBPKG_DESCRIPTION": ["Short, one-line description of subpackage.", "subpackage.sh"], "TERMUX_SUBPKG_DEPEND_ON_PARENT": ["Specifies way how subpackage should depend on parent. See Subpackage dependencies for more information.", "subpackage.sh"], "TERMUX_SUBPKG_DEPENDS": ["Comma-separated list of subpackage dependencies.", "subpackage.sh"], "TERMUX_SUBPKG_BREAKS": ["Comma-separated list of packages that are incompatible with the current one.", "subpackage.sh"], "TERMUX_SUBPKG_CONFLICTS": ["Comma-separated list of packages which have file name collisions with the current one.", "subpackage.sh"], "TERMUX_SUBPKG_REPLACES": ["Comma-separated list of packages being replaced by current one.", "subpackage.sh"], "TERMUX_SUBPKG_ESSENTIAL": ["Whether to treat subpackage as essential which cannot be uninstalled in usual way. Default is false.", "subpackage.sh"], "TERMUX_SUBPKG_PLATFORM_INDEPENDENT": ["Whether to treat subpackage as platform independent. Default is false.", "subpackage.sh"], "TERMUX_SUBPKG_INCLUDE": ["A space or newline separated list of files to be included in subpackage.", "subpackage.sh"], "TERMUX_SUBPKG_CONFFILES": ["A space or newline separated list of package configuration files that should not be overwritten on update.", "subpackage.sh"], "TERMUX_PKG_AUTO_UPDATE": ["Whether to enable automatic updates for this package. Currently packages hosted on GitHub, Gitlab or tracked by repology can be auto updated. For using your own method see here. After writing build.sh you can check if package can be auto-updated using script at scripts/bin/check-auto-update.", ""], "TERMUX_PKG_UPDATE_VERSION_REGEXP": ["Regex to extract version from the new computed version. \u2022 grep -P is set, so you can use perl regex.Use case: any api may return new version as Release_8.9.0, but we want only 8.9.0. So, we can extract it using \\d+\\.\\d+\\.\\d+.", ""], "TERMUX_PKG_UPDATE_METHOD": ["Which method to use for auto-update. Can be github, gitlab or repology. By default it is decided on the basis of TERMUX_PKG_SRCURL\n", ""], "TERMUX_PKG_UPDATE_TAG_TYPE": ["Whether to get latest-release-tag or newest-tag (sorted by commit date) if using github or gitlab method for auto-update. By default if TERMUX_PKG_SRCURL ends in .git then newest-tag is fetched otherwise latest-release-tag.", ""], "TERMUX_GITLAB_API_HOST": ["Which host to use for gitlab api. Default gitlab.com\n", ""], "TERMUX_ON_DEVICE_BUILD": ["If set, assume that building on device.", ""], "TERMUX_BUILD_IGNORE_LOCK": ["If set to true, ignore build process lock.", ""], "TERMUX_BUILD_LOCK_FILE": ["Path to build process lock file.", ""], "TERMUX_HOST_PLATFORM": ["Host platform definition. Usually $TERMUX_ARCH-linux-android.", ""], "TERMUX_PKG_BUILDDIR": ["Path to build directory of current package.", ""], "TERMUX_PKG_BUILDER_DIR": ["Path to directory where located build.sh of current package.", ""], "TERMUX_PKG_BUILDER_SCRIPT": ["Path to build.sh of current package.", ""], "TERMUX_PKG_CACHEDIR": ["Path to source cache directory of current package.", ""], "TERMUX_PKG_MASSAGEDIR": ["Path to directory where package content will be extracted from $TERMUX_PREFIX.", ""], "TERMUX_PKG_PACKAGEDIR": ["Path to directory where components of *.deb archive of current package will be created.", ""], "TERMUX_PKG_SRCDIR": ["Path to source directory of current package.", ""], "TERMUX_PKG_TMPDIR": ["Path to temporary directory specific for current package.", ""], "TERMUX_COMMON_CACHEDIR": ["Path to global cache directory where build tools are stored.", ""], "TERMUX_SCRIPTDIR": ["Path to directory with utility scripts.", ""], "TERMUX_PKG_NAME": ["Name of current package.", ""], "TERMUX_REPO_URL": ["Array of APT repository URLs from which dependencies will be downloaded if ./build-package.sh got option -i or -I.", ""], "TERMUX_REPO_DISTRIBUTION": ["Array of distribution names in addition for TERMUX_REPO_URL.", ""], "TERMUX_REPO_COMPONENT": ["Array of repository component names in addition for TERMUX_REPO_URL.", ""], "TERMUX_PACKAGE_FORMAT": ["Package output format.", ""]}, {"build.sh": ["TERMUX_PKG_HOMEPAGE", "TERMUX_PKG_DESCRIPTION", "TERMUX_PKG_LICENSE", "TERMUX_PKG_VERSION", "TERMUX_PKG_AUTO_UPDATE"], "subpackage.sh": ["TERMUX_SUBPKG_DESCRIPTION", "TERMUX_SUBPKG_INCLUDE", "TERMUX_PKG_AUTO_UPDATE"]}, {"build.sh": ["TERMUX_PKG_DEPENDS", "TERMUX_PKG_BUILD_DEPENDS", "TERMUX_PKG_BREAKS", "TERMUX_PKG_CONFLICTS", "TERMUX_PKG_REPLACES", "TERMUX_PKG_PROVIDES", "TERMUX_PKG_RECOMMENDS", "TERMUX_PKG_SUGGESTS", "TERMUX_PKG_BLACKLISTED_ARCHES"], "subpackage.sh": ["TERMUX_SUBPKG_DEPENDS", "TERMUX_SUBPKG_BREAKS", "TERMUX_SUBPKG_CONFLICTS", "TERMUX_SUBPKG_REPLACES"]}] \ No newline at end of file diff --git a/src/termux_language_server/assets/queries/mingw.scm b/src/termux_language_server/assets/queries/mingw.scm new file mode 100644 index 0000000..0e84a35 --- /dev/null +++ b/src/termux_language_server/assets/queries/mingw.scm @@ -0,0 +1,8 @@ +( + (variable_assignment + name: (variable_name) @variable.name + ) + (#match? + @variable.name "^(mingw|msys2)_" + ) + ) diff --git a/src/termux_language_server/assets/queries/package.scm b/src/termux_language_server/assets/queries/package.scm new file mode 100644 index 0000000..dcb6324 --- /dev/null +++ b/src/termux_language_server/assets/queries/package.scm @@ -0,0 +1,9 @@ +( + (variable_assignment + name: (variable_name) @variable.name + value: (array (word) @package) + ) + (#match? + @variable.name "^(depends|optdepends|makedepends|conflicts|provides)$" + ) + ) diff --git a/src/termux_language_server/documents/__init__.py b/src/termux_language_server/documents/__init__.py deleted file mode 100644 index 5016888..0000000 --- a/src/termux_language_server/documents/__init__.py +++ /dev/null @@ -1,73 +0,0 @@ -r"""Documents -============= -""" -import json -import os -from typing import Literal - -from platformdirs import user_cache_dir - - -def get_document( - method: Literal["builtin", "cache", "web"] = "builtin" -) -> tuple[ - dict[str, tuple[str, str]], dict[str, set[str]], dict[str, set[str]] -]: - r"""Get document. ``builtin`` will use builtin termux.json. ``cache`` - will generate a cache from - ``_. ``web`` is same as - ``cache`` except it doesn't generate cache. We use ``builtin`` as default. - If you want to get the latest result from - ``_, you need to - install `beautifulsoup4 ` by - ``pip install 'termux-language-server[web]'``. - - :param method: - :type method: Literal["builtin", "cache", "web"] - :rtype: tuple[dict[str, tuple[str, str]], dict[str, set[str]], dict[str, set[str]]] - """ - if method == "builtin": - file = os.path.join( - os.path.join( - os.path.join( - os.path.dirname(os.path.dirname(__file__)), "assets" - ), - "json", - ), - "termux.json", - ) - with open(file, "r") as f: - document = json.load(f) - elif method == "cache": - from .builtin import init_document - - if not os.path.exists(user_cache_dir("termux.json")): - document = init_document() - with open(user_cache_dir("termux.json"), "w") as f: - json.dump(document, f) - else: - with open(user_cache_dir("termux.json"), "r") as f: - document = json.load(f) - else: - from .builtin import init_document - - document = init_document() - return ( - document[0], - {k: set(v) for k, v in document[1].items()}, - {k: set(v) for k, v in document[2].items()}, - ) - - -def get_filetype(uri: str) -> Literal["build.sh", "subpackage.sh", ""]: - r"""Get filetype. - - :param uri: - :type uri: str - :rtype: Literal["build.sh", "subpackage.sh", ""] - """ - if os.path.basename(uri) == "build.sh": - return "build.sh" - if os.path.basename(uri).endswith(".subpackage.sh"): - return "subpackage.sh" - return "" diff --git a/src/termux_language_server/documents/builtin.py b/src/termux_language_server/documents/builtin.py deleted file mode 100644 index 082843a..0000000 --- a/src/termux_language_server/documents/builtin.py +++ /dev/null @@ -1,97 +0,0 @@ -r"""Builtin -=========== -""" -from copy import deepcopy -from urllib import request - -from bs4 import BeautifulSoup, FeatureNotFound - -URIS = { - "variable": "https://github.com/termux/termux-packages/wiki/Creating-new-package", - "function": "https://github.com/termux/termux-packages/wiki/Building-packages", - "update": "https://github.com/termux/termux-packages/wiki/Auto-updating-packages", -} - - -def get_soup(uri: str) -> BeautifulSoup: - r"""Get soup. - - :param uri: - :type uri: str - :rtype: BeautifulSoup - """ - with request.urlopen(uri) as f: # nosec: B310 - html = f.read() - - try: - soup = BeautifulSoup(html, "lxml") - except FeatureNotFound: - soup = BeautifulSoup(html, "html.parser") - return soup - - -def init_document() -> ( - tuple[ - dict[str, tuple[str, str]], dict[str, list[str]], dict[str, list[str]] - ] -): - r"""Init document. - - :rtype: ( - tuple[dict[str, tuple[str, str]], dict[str, list[str]], dict[str, list[str]]] - ) - """ - items = {} - required = {"build.sh": [], "subpackage.sh": []} - csvs = deepcopy(required) - variable_table, function_table = get_soup(URIS["update"]).find_all("table") - for tr in ( - get_soup(URIS["function"]).find_all("tr")[1:] - + function_table.find_all("tr")[1:] - ): - tds = tr.find_all("td") - # overridable means `termux_step_configure() { ... }` - items[tds[1].text + ("()" if tds[2].text == "yes" else "")] = ( - tds[3].text, - "", - ) - soup = get_soup(URIS["variable"]) - tables = soup.find_all("table") - for tr in tables[0].find_all("tr")[1:]: - tds = tr.find_all("td") - if tds[2].text == "yes": - required["build.sh"] += [tds[1].text] - if tds[3].text.startswith("Comma-separated list of "): - csvs["build.sh"] += [tds[1].text] - items[tds[1].text] = ( - tds[3].text, - "build.sh", - ) - for tr in tables[2].find_all("tr")[1:]: - tds = tr.find_all("td") - if tds[2].text == "yes": - required["subpackage.sh"] += [tds[1].text] - if tds[3].text.startswith("Comma-separated list of "): - csvs["subpackage.sh"] += [tds[1].text] - items[tds[1].text] = ( - tds[3].text, - "subpackage.sh", - ) - for tr in variable_table.find_all("tr")[1:]: - tds = tr.find_all("td") - if tds[2].text == "yes": - required["build.sh"] += [tds[1].text] - required["subpackage.sh"] += [tds[1].text] - if tds[3].text.startswith("Comma-separated list of "): - csvs["build.sh"] += [tds[1].text] - csvs["subpackage.sh"] += [tds[1].text] - items[tds[1].text] = ( - tds[3].text, - "", - ) - for li in soup.find_all("ul")[-2].find_all("li"): - items[li.find("code").text] = ( - li.text.partition("-")[2].strip().replace("\n", " "), - "", - ) - return items, required, csvs diff --git a/src/termux_language_server/finders.py b/src/termux_language_server/finders.py index 99b2e28..810b57e 100644 --- a/src/termux_language_server/finders.py +++ b/src/termux_language_server/finders.py @@ -1,156 +1,151 @@ r"""Finders =========== """ + from copy import deepcopy +from dataclasses import dataclass from jinja2 import Template +from lsp_tree_sitter import UNI, Finder +from lsp_tree_sitter.finders import ( + ErrorFinder, + QueryFinder, + SchemaFinder, + UnFixedOrderFinder, +) from lsprotocol.types import ( - Diagnostic, + CompletionItemKind, DiagnosticSeverity, DocumentLink, Position, Range, TextEdit, ) -from tree_sitter import Tree +from tree_sitter import Node, Tree + +from . import CSV, FILETYPE +from .schema import BashTrie +from .utils import get_query, get_schema + + +@dataclass(init=False) +class BashFinder(SchemaFinder): + r"""Bashfinder.""" + + def __init__(self, filetype: FILETYPE) -> None: + r"""Init. -from .tree_sitter_lsp import UNI, Finder -from .tree_sitter_lsp.finders import RequiresFinder, UnFixedOrderFinder + :param filetype: + :type filetype: FILETYPE + :rtype: None + """ + self.validator = self.schema2validator(get_schema(filetype)) + self.cls = BashTrie -class InvalidKeywordFinder(Finder): - r"""Invalidkeywordfinder.""" +@dataclass(init=False) +class UnsortedKeywordFinder(UnFixedOrderFinder): + r"""Unsortedkeywordfinder.""" def __init__( self, - names: set[str], - message: str = "{{uni.get_text()}}: shouldn't be {{type}}", - severity: DiagnosticSeverity = DiagnosticSeverity.Error, + filetype: FILETYPE, + message: str = "{{uni.text}}: is unsorted due to {{_uni}}", + severity: DiagnosticSeverity = DiagnosticSeverity.Warning, ) -> None: r"""Init. - :param names: - :type names: set[str] + :param filetype: + :type filetype: FILETYPE :param message: :type message: str :param severity: :type severity: DiagnosticSeverity :rtype: None """ - super().__init__(message, severity) - self.names = names + super().__init__( + list(get_schema(filetype).get("properties", [])), message, severity + ) + self.keywords = UnsortedKeywordFinder.get_keywords(filetype) @staticmethod - def is_correct_declaration(uni: UNI) -> bool: - r"""Is correct declaration. + def get_keywords(filetype) -> dict[str, CompletionItemKind]: + r"""Get keywords. - :param uni: - :type uni: UNI - :rtype: bool + :param filetype: + :rtype: dict[str, CompletionItemKind] """ - parent = uni.node.parent - if parent is None: - return False - text = uni.get_text() - return ( - text.isupper() - and uni.node.type == "variable_name" - and parent.type == "variable_assignment" - or text.islower() - and uni.node.type == "word" - and parent.type == "function_definition" - ) + return { + k: ( + CompletionItemKind.Function + if v.get("const") == 0 + else CompletionItemKind.Variable + ) + for k, v in get_schema(filetype).get("properties", {}).items() + } @staticmethod - def is_array(uni: UNI) -> bool: - r"""Is array. + def is_correct_declaration(uni: UNI, _type: CompletionItemKind) -> bool: + r"""Is correct declaration. :param uni: :type uni: UNI + :param _type: + :type _type: CompletionItemKind :rtype: bool """ - text = uni.get_text() parent = uni.node.parent if parent is None: return False - if ( - text.isupper() + return ( + _type == CompletionItemKind.Variable + and uni.node.type == "variable_name" + and parent.type == "variable_assignment" + and parent.children[-1].type != "array" + or _type == CompletionItemKind.Field and uni.node.type == "variable_name" and parent.type == "variable_assignment" and parent.children[-1].type == "array" - ): - return True - return False + or _type == CompletionItemKind.Function + and uni.node.type == "word" + and parent.type == "function_definition" + ) @staticmethod - def is_correct(uni: UNI) -> bool: - r"""Is correct. + def is_correct_reference(uni: UNI, _type: CompletionItemKind) -> bool: + r"""Is correct reference. :param uni: :type uni: UNI + :param _type: + :type _type: CompletionItemKind :rtype: bool """ - text = uni.get_text() parent = uni.node.parent if parent is None: return False return ( - InvalidKeywordFinder.is_correct_declaration(uni) - or text.isupper() + _type in {CompletionItemKind.Variable, CompletionItemKind.Field} and uni.node.type == "variable_name" - or text.islower() + and parent.type in {"expansion", "simple_expansion"} + or _type == CompletionItemKind.Function and uni.node.type == "word" and parent.type == "command_name" ) - def __call__(self, uni: UNI) -> bool: - r"""Call. - - :param uni: - :type uni: UNI - :rtype: bool - """ - text = uni.get_text() - return text in self.names and ( - not self.is_correct(uni) or self.is_array(uni) - ) - - def uni2diagnostic(self, uni: UNI) -> Diagnostic: - r"""Uni2diagnostic. - - :param uni: - :type uni: UNI - :rtype: Diagnostic - """ - parent = uni.node.parent - if parent is None: - raise TypeError - _type = parent.type - if self.is_array(uni): - _type = "array" - return uni.get_diagnostic(self.message, self.severity, type=_type) - - -class RequiredKeywordFinder(RequiresFinder): - r"""Requiredkeywordfinder.""" - - def filter(self, uni: UNI, require: str) -> bool: - r"""Filter. + @staticmethod + def is_correct(uni: UNI, _type: CompletionItemKind) -> bool: + r"""Is correct. :param uni: :type uni: UNI - :param require: - :type require: str + :param _type: + :type _type: CompletionItemKind :rtype: bool """ - text = uni.get_text() - return text == require and InvalidKeywordFinder.is_correct_declaration( - uni - ) - - -class UnsortedKeywordFinder(UnFixedOrderFinder): - r"""Unsortedkeywordfinder.""" + return UnsortedKeywordFinder.is_correct_declaration( + uni, _type + ) or UnsortedKeywordFinder.is_correct_reference(uni, _type) def filter(self, uni: UNI) -> bool: r"""Filter. @@ -159,10 +154,13 @@ def filter(self, uni: UNI) -> bool: :type uni: UNI :rtype: bool """ - text = uni.get_text() + text = uni.text return ( text in self.order - and InvalidKeywordFinder.is_correct_declaration(uni) + and text in self.keywords + and UnsortedKeywordFinder.is_correct_declaration( + uni, self.keywords[text] + ) ) def get_text_edits(self, uri: str, tree: Tree) -> list[TextEdit]: @@ -183,25 +181,26 @@ def get_text_edits(self, uri: str, tree: Tree) -> list[TextEdit]: return [] # swap 2 unis return [ - TextEdit(UNI.node2range(parent), UNI.node2text(_parent)), - TextEdit(UNI.node2range(_parent), UNI.node2text(parent)), + TextEdit(UNI(parent).range, UNI(_parent).text), + TextEdit(UNI(_parent).range, UNI(parent).text), ] return [] +@dataclass(init=False) class UnsortedCSVFinder(Finder): r"""Unsorted comma separated value finder.""" def __init__( self, - csvs: set[str], - message: str = "{{uni.get_text()}}: unsorted", + filetype: FILETYPE, + message: str = "{{uni.text}}: unsorted", severity: DiagnosticSeverity = DiagnosticSeverity.Warning, ) -> None: r"""Init. - :param csvs: - :type csvs: set[str] + :param filetype: + :type filetype: FILETYPE :param message: :type message: str :param severity: @@ -209,7 +208,21 @@ def __init__( :rtype: None """ super().__init__(message, severity) - self.csvs = csvs + self.csvs = self.get_csvs(filetype) + + @staticmethod + def get_csvs(filetype: FILETYPE) -> set[str]: + r"""Get csvs. + + :param filetype: + :type filetype: FILETYPE + :rtype: set[str] + """ + return set( + k + for k, v in get_schema(filetype).get("properties", {}).items() + if v.get("pattern") == CSV + ) def __call__(self, uni: UNI) -> bool: r"""Call. @@ -218,7 +231,7 @@ def __call__(self, uni: UNI) -> bool: :type uni: UNI :rtype: bool """ - return self.is_csv(uni) and self.sort(uni.get_text()) != uni.get_text() + return self.is_csv(uni) and self.sort(uni.text) != uni.text def is_csv(self, uni: UNI) -> bool: r"""Is csv. @@ -234,7 +247,7 @@ def is_csv(self, uni: UNI) -> bool: parent.type == "variable_assignment" and uni.node == parent.children[-1] and (uni.node.type == "word" or uni.node.type == "string") - and UNI.node2text(parent.children[0]) in self.csvs + and UNI(parent.children[0]).text in self.csvs ) @staticmethod @@ -264,23 +277,22 @@ def get_text_edits(self, uri: str, tree: Tree) -> list[TextEdit]: :rtype: list[TextEdit] """ text_edits = [ - TextEdit(uni.get_range(), self.sort(uni.get_text())) + TextEdit(uni.range, self.sort(uni.text)) for uni in self.find_all(uri, tree) ] return text_edits +@dataclass() class CSVFinder(UnsortedCSVFinder): r"""Comma separated value finder.""" - def __init__(self, csvs: set[str]) -> None: - r"""Init. + def __post_init__(self) -> None: + r"""Post init. - :param csvs: - :type csvs: set[str] :rtype: None """ - super().__init__(csvs - {"TERMUX_PKG_BLACKLISTED_ARCHES"}) + self.csvs -= {"TERMUX_PKG_EXCLUDED_ARCHES"} def __call__(self, uni: UNI) -> bool: r"""Call. @@ -292,7 +304,7 @@ def __call__(self, uni: UNI) -> bool: return self.is_csv(uni) def get_document_links( - self, uri: str, tree: Tree, template: str + self, uri: str, tree: Tree, template: str = "" ) -> list[DocumentLink]: r"""Get document links. @@ -307,7 +319,7 @@ def get_document_links( links = [] for uni in self.find_all(uri, tree): start = list(uni.node.start_point) - text = uni.get_text() + text = uni.text if text.startswith('"'): text = text.strip('"') start[1] += 1 @@ -326,3 +338,67 @@ def get_document_links( ] start[1] += len(name) + 1 return links + + +@dataclass(init=False) +class PackageFinder(QueryFinder): + r"""Packagefinder.""" + + def __init__( + self, + message: str = "{{uni.text}}: no such file", + severity: DiagnosticSeverity = DiagnosticSeverity.Error, + ) -> None: + r"""Init. + + :param message: + :type message: str + :param severity: + :type severity: DiagnosticSeverity + :rtype: None + """ + query = get_query("package") + super().__init__(query, message, severity) + + def capture2uni(self, capture: tuple[Node, str], uri: str) -> UNI | None: + r"""Capture2uni. + + :param capture: + :type capture: tuple[Node, str] + :param uri: + :type uri: str + :rtype: UNI | None + """ + node, label = capture + uni = UNI(node, uri) + return uni if label == "package" else None + + +@dataclass(init=False) +class MinGWFinder(QueryFinder): + r"""Mingwfinder.""" + + def __init__( + self, + message: str = "{{uni.text}}: no such file", + severity: DiagnosticSeverity = DiagnosticSeverity.Error, + ) -> None: + r"""Init. + + :param message: + :type message: str + :param severity: + :type severity: DiagnosticSeverity + :rtype: None + """ + query = get_query("mingw") + super().__init__(query, message, severity) + + +DIAGNOSTICS_FINDER_CLASSES = [ + ErrorFinder, + BashFinder, + UnsortedKeywordFinder, + UnsortedCSVFinder, +] +FORMAT_FINDER_CLASSES = [UnsortedKeywordFinder, UnsortedCSVFinder] diff --git a/src/termux_language_server/misc/__init__.py b/src/termux_language_server/misc/__init__.py new file mode 100644 index 0000000..6b74d27 --- /dev/null +++ b/src/termux_language_server/misc/__init__.py @@ -0,0 +1,31 @@ +r"""Misc +======== +""" + +from typing import Any + +from .. import FILETYPE + + +def get_schema(filetype: FILETYPE) -> dict[str, Any]: + r"""Get schema. + + :param filetype: + :type filetype: FILETYPE + :rtype: dict[str, Any] + """ + if filetype in {"build.sh", "subpackage.sh"}: + from .termux import init_schema + elif filetype in {"PKGBUILD", "install"}: + from .pkgbuild import init_schema + elif filetype == "makepkg.conf": + from .makepkg_conf import init_schema + elif filetype == "color.map": + from .color_map import init_schema + elif filetype == "make.conf": + from .make_conf import init_schema + elif filetype == "ebuild": + from .ebuild import init_schema + else: + raise NotImplementedError(filetype) + return init_schema()[filetype] diff --git a/src/termux_language_server/misc/color_map.py b/src/termux_language_server/misc/color_map.py new file mode 100644 index 0000000..2f6122f --- /dev/null +++ b/src/termux_language_server/misc/color_map.py @@ -0,0 +1,45 @@ +r"""Portage's color.map +======================= +""" + +from typing import Any + +from lsp_tree_sitter.misc import get_soup + +from .._metainfo import SOURCE, project + + +def init_schema() -> dict[str, dict[str, Any]]: + r"""Init schema. + + :rtype: dict[str, dict[str, Any]] + """ + filetype = "color.map" + schema = { + "$id": ( + f"{SOURCE}/blob/main/" + f"src/termux_language_server/assets/json/{filetype}.json" + ), + "$schema": "http://json-schema.org/draft-07/schema#", + "$comment": ( + "Don't edit this file directly! It is generated by " + f"`{project} --generate-schema={filetype}`." + ), + "type": "object", + "properties": {}, + } + dl = get_soup("color.map").find_all("dl")[1] + for dt, dd in zip(dl.find_all("dt"), dl.find_all("dd"), strict=False): + name = dt.text.split()[0] + description = dd.text.replace("\n", " ").strip() + example = dt.text.replace("\n", " ") + if name != example: + description = f"""```sh +{example} +``` +{description}""" + schema["properties"][name] = { + "description": description, + "type": "string", + } + return {filetype: schema} diff --git a/src/termux_language_server/misc/ebuild.py b/src/termux_language_server/misc/ebuild.py new file mode 100644 index 0000000..48b36dc --- /dev/null +++ b/src/termux_language_server/misc/ebuild.py @@ -0,0 +1,61 @@ +r"""Portage's ebuild +==================== +""" + +import os +from shlex import split +from subprocess import check_output # nosec: B404 +from typing import Any + +from lsp_tree_sitter.misc import get_soup + +from .._metainfo import SOURCE, project + + +def init_schema() -> dict[str, dict[str, Any]]: + r"""Init schema. + + :rtype: dict[str, dict[str, Any]] + """ + filetype = "ebuild" + schema = { + "$id": ( + f"{SOURCE}/blob/main/" + f"src/termux_language_server/assets/json/{filetype}.json" + ), + "$schema": "http://json-schema.org/draft-07/schema#", + "$comment": ( + "Don't edit this file directly! It is generated by " + f"`{project} --generate-schema={filetype}`." + ), + "type": "object", + "properties": {}, + } + for dl in get_soup("ebuild").find_all("dl")[20:-2]: + for dt, dd in zip(dl.find_all("dt"), dl.find_all("dd"), strict=False): + if dt.strong is None or dt.strong.text.endswith(":"): + continue + name = dt.strong.text.split()[0] + description = dd.text.replace("\n", " ").strip() + example = dt.text.replace("\n", " ") + if name != example: + description = f"""```sh +{example} +``` +{description}""" + schema["properties"][name] = { + "description": description, + } + if name.isupper(): + schema["properties"][name]["type"] = "string" + else: + schema["properties"][name]["const"] = 0 + eprefix = os.path.dirname(os.path.dirname(os.getenv("SHELL", ""))) + path = ( + check_output(split(f"portageq get_repo_path {eprefix} gentoo")) + .decode() + .strip() + ) + atom = f"({'|'.join(os.listdir(path))})" + schema["properties"]["LICENSE"]["pattern"] = rf"{atom}(( |\n){atom})*" + return {filetype: schema} diff --git a/src/termux_language_server/misc/licenses.py b/src/termux_language_server/misc/licenses.py new file mode 100644 index 0000000..24f72bd --- /dev/null +++ b/src/termux_language_server/misc/licenses.py @@ -0,0 +1,13 @@ +r"""Licenses +============ +""" + +from license_expression import get_license_index + +LICENSES = [ + i["spdx_license_key"] + for i in get_license_index() + if i.get("spdx_license_key") + and not i["spdx_license_key"].startswith("LicenseRef-scancode-") +] +ATOM = f"({'|'.join(LICENSES)})" diff --git a/src/termux_language_server/misc/make_conf.py b/src/termux_language_server/misc/make_conf.py new file mode 100644 index 0000000..95b4f3a --- /dev/null +++ b/src/termux_language_server/misc/make_conf.py @@ -0,0 +1,49 @@ +r"""Portage's make.conf +======================= +""" + +from typing import Any + +from lsp_tree_sitter.misc import get_soup + +from .._metainfo import SOURCE, project + + +def init_schema() -> dict[str, dict[str, Any]]: + r"""Init schema. + + :rtype: dict[str, dict[str, Any]] + """ + filetype = "make.conf" + schema = { + "$id": ( + f"{SOURCE}/blob/main/" + f"src/termux_language_server/assets/json/{filetype}.json" + ), + "$schema": "http://json-schema.org/draft-07/schema#", + "$comment": ( + "Don't edit this file directly! It is generated by " + f"`{project} --generate-schema={filetype}`." + ), + "type": "object", + "properties": {}, + } + for dl in get_soup("make.conf").find_all("dl")[:-2]: + for dt, dd in zip(dl.find_all("dt"), dl.find_all("dd"), strict=False): + if dt.strong is None: + continue + name = dt.strong.text.split()[0] + if not name.isupper(): + continue + description = dd.text.replace("\n", " ").strip() + example = dt.text.replace("\n", " ") + if name != example: + description = f"""```sh +{example} +``` +{description}""" + schema["properties"][name] = { + "description": description, + "type": "string", + } + return {filetype: schema} diff --git a/src/termux_language_server/misc/makepkg_conf.py b/src/termux_language_server/misc/makepkg_conf.py new file mode 100644 index 0000000..616fdad --- /dev/null +++ b/src/termux_language_server/misc/makepkg_conf.py @@ -0,0 +1,89 @@ +r"""makepkg.conf +================ +""" + +from typing import Any + +from lsp_tree_sitter.misc import get_soup + +from .._metainfo import SOURCE, project + + +def init_schema() -> dict[str, dict[str, Any]]: + r"""Init schema. + + :rtype: dict[str, dict[str, Any]] + """ + filetype = "makepkg.conf" + schema = { + "$id": ( + f"{SOURCE}/blob/main/" + f"src/termux_language_server/assets/json/{filetype}.json" + ), + "$schema": "http://json-schema.org/draft-07/schema#", + "$comment": ( + "Don't edit this file directly! It is generated by " + f"`{project} --generate-schema={filetype}`." + ), + "type": "object", + "properties": {}, + } + name = "" + for blockquote in get_soup("makepkg.conf").find_all("blockquote"): + if blockquote.find("p").contents == ["."]: + break + p = blockquote.find_previous("p") + if p.find("strong") is None: + continue + if p.text.islower(): + schema["properties"][name]["items"]["enum"] = schema["properties"][ + name + ]["items"].get("enum", []) + [p.text, f"!{p.text}"] + continue + _description = "\n".join( + content.text.replace("\n", " ") + for p in blockquote.find_all("p") + for content in p.contents + ) + last_name = "" + example = "" + text = "" + name = "" + for text in [content.text for content in p.contents]: + # FIXME: typo of makepkg.conf + if "=" in text or text == "COMPRESSLZO": + if text == "COMPRESSLZO": + text += "=" + name = text.split("=")[0] + if last_name != "": + description = f"""```sh +{example} +``` +{_description}""" + schema["properties"][last_name] = { + "description": description, + "type": "array" if "(" in example else "string", + } + if schema["properties"][last_name]["type"] == "array": + schema["properties"][last_name] |= { + "items": {"type": "string"}, + "uniqueItems": True, + } + example = "" + last_name = name + example += text.replace("\n", " ") + else: + description = f"""```sh +{example} +``` +{_description}""" + schema["properties"][name] = { + "description": description, + "type": "array" if "(" in example else "string", + } + if schema["properties"][last_name]["type"] == "array": + schema["properties"][last_name] |= { + "items": {"type": "string"}, + "uniqueItems": True, + } + return {filetype: schema} diff --git a/src/termux_language_server/misc/pkgbuild.py b/src/termux_language_server/misc/pkgbuild.py new file mode 100644 index 0000000..25c02c4 --- /dev/null +++ b/src/termux_language_server/misc/pkgbuild.py @@ -0,0 +1,218 @@ +r"""PKGBUILD +============ +""" + +import os +from typing import Any + +from lsp_tree_sitter.misc import get_md_tokens, get_soup +from markdown_it.token import Token + +from .._metainfo import SOURCE, project +from .licenses import LICENSES + + +def get_content(tokens: list[Token]) -> str: + r"""Get content. + + :param tokens: + :type tokens: list[Token] + :rtype: str + """ + return "\n".join([ + token.content.replace("\n", " ") for token in tokens if token.content + ]) + + +def init_schema() -> dict[str, Any]: + r"""Init schema. + + :rtype: dict[str, dict[str, Any]] + """ + schemas = {} + for filetype in {"PKGBUILD", "install"}: + schemas[filetype] = { + "$id": ( + f"{SOURCE}/blob/main/" + f"src/termux_language_server/assets/json/{filetype}.json" + ), + "$schema": "http://json-schema.org/draft-07/schema#", + "$comment": ( + "Don't edit this file directly! It is generated by " + f"`{project} --generate-schema={filetype}`." + ), + "type": "object", + "patternProperties": {}, + } + # PKGBUILD has variables + schemas["PKGBUILD"]["properties"] = {} + + tokens = get_md_tokens("PKGBUILD") + # **pkgname (array)** + # + # > Either the name of the package or an array of names for split + # > packages. Valid characters for members of this array are + # > alphanumerics, and any of the following characters: "@ . \_ + -". + # > Additionally, names are not allowed to start with hyphens or dots. + indices = [ + index + for index, token in enumerate(tokens) + if token.content.startswith("**") + and token.content.endswith("**") + and token.level == 1 + ] + blockquote_close_indices = [ + index + for index, token in enumerate(tokens) + if token.type == "blockquote_close" + ] + close_indices = [ + min([ + blockquote_close_index + for blockquote_close_index in blockquote_close_indices + if blockquote_close_index > index + ]) + for index in indices + ] + for index, close_index in zip(indices, close_indices, strict=False): + children = tokens[index].children + if children is None: + continue + words = [child.rstrip(",") for child in children[2].content.split()] + # md5sums, ... + if len(words) > 2: + _words = [child for child in children[4].content.split()] + kind = ( + _words[1].lstrip("(").rstrip(")") + if len(words) > 1 + else "string" + ) + names = words + [_words[0]] + else: + names = [words[0].rstrip("()")] + kind = ( + words[1].lstrip("(").rstrip(")") + if len(words) > 1 + else "string" + ) + for name in names: + description = get_content(tokens[index + 1 : close_index]) + if name.startswith("pre_") or name.startswith("post_"): + filetype = "install" + kind = "Function" + else: + filetype = "PKGBUILD" + if kind == "Function": + name = rf"^{name}($|_.*)" + properties_name = "patternProperties" + else: + properties_name = "properties" + schemas[filetype][properties_name][name] = { + "description": description + } + # makepkg supports building multiple packages from a single + # PKGBUILD. This is achieved by assigning an array of package names + # to the pkgname directive. + if name == "pkgname": + schemas[filetype][properties_name][name]["oneOf"] = [ + { + "type": "array", + "items": {"type": "string"}, + "uniqueItems": True, + }, + {"type": "string"}, + ] + elif kind == "string": + schemas[filetype][properties_name][name]["type"] = "string" + elif kind in {"array", "arrays"}: + schemas[filetype][properties_name][name] |= { + "type": "array", + "items": {"type": "string"}, + "uniqueItems": True, + } + elif kind == "Function": + # Each split package uses a corresponding packaging function + # with name package_foo(), where foo is the name of the split + # package. + schemas[filetype][properties_name][name]["const"] = 0 + # https://archlinux32.org/architecture/ + # https://archlinux.org/packages/ + # https://archlinuxarm.org/forum/viewforum.php?f=56 + schemas["PKGBUILD"]["properties"]["arch"]["items"]["enum"] = [ + "any", + "pentium4", + "i486", + "i686", + "x86_64", + "x86_64_v3", + "arm", + "armv6h", + "armv7h", + "armv8", + "aarch64", + ] + schemas["PKGBUILD"]["properties"]["url"]["format"] = "uri" + del schemas["PKGBUILD"]["properties"]["pkgver"]["type"] + for name in schemas["PKGBUILD"]["properties"]: + if name.endswith("sums"): + del schemas["PKGBUILD"]["properties"][name]["uniqueItems"] + schemas["PKGBUILD"]["properties"]["pkgver"] |= { + "oneOf": [{"type": "string"}, {"const": 0}] + } + + soup = get_soup("https://www.msys2.org/dev/pkgbuild/") + for tr in soup.find_all("tr")[1:]: + tds = tr.find_all("td") + name = tds[0].code.text + kind = tds[1].text + kind = {"mapping": "array"}.get(kind, kind) + description = tds[2].text + schemas["PKGBUILD"]["properties"][name] = { + "type": kind, + "description": description, + } + if kind == "array": + schemas["PKGBUILD"]["properties"][name] |= { + "items": {"type": "string"}, + "uniqueItems": True, + } + elif kind == "object": + schemas["PKGBUILD"]["properties"][name] |= {"properties": {}} + elif kind == "string" and name.endswith("_url"): + schemas["PKGBUILD"]["properties"][name]["format"] = "uri" + # https://packages.msys2.org/repos + schemas["PKGBUILD"]["properties"]["mingw_arch"]["items"]["enum"] = [ + "mingw32", + "mingw64", + "ucrt64", + "clang64", + "clang32", + "clangarm64", + ] + names = [] + for li in soup.find_all("li"): + code = li.find("code") + if code is None: + continue + name = code.text + if not li.text.startswith(name): + continue + names += [name] + # text = li.text + # _, _, text = text.partition(name) + # description = text.replace("\n", " ").lstrip("- ") + schemas["PKGBUILD"]["properties"]["msys2_references"]["items"][ + "pattern" + ] = f"({'|'.join(names)})(|: .*)" + schemas["PKGBUILD"]["properties"]["license"]["items"] = { + "oneOf": [ + { + "type": "string", + "enum": LICENSES + + os.listdir("/usr/share/licenses/common") + + ["custom"], + }, + {"type": "string", "pattern": "custom:.+"}, + ] + } + return schemas diff --git a/src/termux_language_server/misc/termux.py b/src/termux_language_server/misc/termux.py new file mode 100644 index 0000000..07bfef9 --- /dev/null +++ b/src/termux_language_server/misc/termux.py @@ -0,0 +1,169 @@ +r"""Termux +========== +""" + +from typing import Any + +from lsp_tree_sitter.misc import get_soup + +from .. import CSV +from .._metainfo import SOURCE, project +from .licenses import ATOM + +URIS = { + "variable": "https://github.com/termux/termux-packages/wiki/Creating-new-package", + "function": "https://github.com/termux/termux-packages/wiki/Building-packages", + "update": "https://github.com/termux/termux-packages/wiki/Auto-updating-packages", +} + + +def init_schema() -> dict[str, dict[str, Any]]: + r"""Init schema. + + :rtype: dict[str, dict[str, Any]] + """ + schemas = {} + for filetype in {"build.sh", "subpackage.sh"}: + schemas[filetype] = { + "$id": ( + f"{SOURCE}/blob/main/" + f"src/termux_language_server/assets/json/{filetype}.json" + ), + "$schema": "http://json-schema.org/draft-07/schema#", + "$comment": ( + "Don't edit this file directly! It is generated by " + f"`{project} --generate-schema={filetype}`." + ), + "type": "object", + # required variables + "required": [], + # all variables and all overridable functions + "properties": {}, + "propertyNames": { + # not overridable functions + # for subpackage.sh, disable all functions + "not": {"anyOf": []} + }, + } + + soup = get_soup(URIS["variable"]) + tables = soup.find_all("table") + for tr in tables[0].find_all("tr")[1:]: + tds = tr.find_all("td") + name = tds[1].text + is_required = tds[2].text == "yes" + description = tds[3].text.strip() + if is_required: + schemas["build.sh"]["required"] += [name] + schemas["build.sh"]["properties"][name] = { + "type": "string", + "description": description, + } + if description.endswith("Default is true."): + schemas["build.sh"]["properties"][name]["default"] = "true" + schemas["build.sh"]["properties"][name]["enum"] = ["true", "false"] + if description.endswith("Default is false."): + schemas["build.sh"]["properties"][name]["default"] = "false" + schemas["build.sh"]["properties"][name]["enum"] = ["true", "false"] + if description.startswith("Comma-separated list of "): + schemas["build.sh"]["properties"][name]["pattern"] = CSV + for tr in tables[2].find_all("tr")[1:]: + tds = tr.find_all("td") + name = tds[1].text + is_required = tds[2].text == "yes" + description = tds[3].text.strip() + if is_required: + schemas["subpackage.sh"]["required"] += [name] + schemas["subpackage.sh"]["properties"][name] = { + "type": "string", + "description": description, + } + if description.endswith("Default is true."): + schemas["subpackage.sh"]["properties"][name]["default"] = "true" + schemas["subpackage.sh"]["properties"][name]["enum"] = [ + "true", + "false", + ] + if description.endswith("Default is false."): + schemas["subpackage.sh"]["properties"][name]["default"] = "false" + schemas["subpackage.sh"]["properties"][name]["enum"] = [ + "true", + "false", + ] + if description.startswith("Comma-separated list of "): + schemas["subpackage.sh"]["properties"][name]["pattern"] = CSV + for li in soup.find_all("ul")[-2].find_all("li"): + name = li.find("code").text + description = ( + li.text.partition("-")[2].strip().replace("\n", " ").strip() + ) + obj = { + "const": name, + "description": description, + } + schemas["build.sh"]["propertyNames"]["not"]["anyOf"] += [obj] + schemas["subpackage.sh"]["propertyNames"]["not"]["anyOf"] += [obj] + + variable_table, function_table = get_soup(URIS["update"]).find_all("table") + for tr in variable_table.find_all("tr")[1:]: + tds = tr.find_all("td") + name = tds[1].text + is_required = tds[2].text == "yes" + description = tds[3].text.strip() + if is_required: + schemas["build.sh"]["required"] += [name] + schemas["build.sh"]["properties"][name] = { + "type": "string", + "description": description, + } + if description.startswith("Comma-separated list of "): + schemas["build.sh"]["properties"][name]["pattern"] = CSV + + for tr in ( + get_soup(URIS["function"]).find_all("tr")[1:] + + function_table.find_all("tr")[1:] + ): + tds = tr.find_all("td") + name = tds[1].text + # NOTE: capital + # use `!= "no"` to allow some conditional yes + is_overrideable = tds[2].text.lower() != "no" + description = tds[3].text.strip() + if is_overrideable: + schemas["build.sh"]["properties"][name] = { + "description": description, + "const": 0, + } + else: + obj = { + "const": name, + "description": description, + } + schemas["build.sh"]["propertyNames"]["not"]["anyOf"] += [obj] + + schemas["build.sh"]["properties"]["TERMUX_PKG_HOMEPAGE"][ + "format" + ] = schemas["build.sh"]["properties"]["TERMUX_PKG_SRCURL"]["format"] = ( + "uri" + ) + schemas["build.sh"]["properties"]["TERMUX_PKG_MAINTAINER"]["default"] = ( + "@termux" + ) + schemas["build.sh"]["properties"]["TERMUX_PKG_UPDATE_METHOD"]["enum"] = [ + "github", + "gitlab", + "repology", + ] + schemas["build.sh"]["properties"]["TERMUX_GITLAB_API_HOST"]["default"] = ( + "gitlab.com" + ) + schemas["build.sh"]["properties"]["TERMUX_GITLAB_API_HOST"]["format"] = ( + "hostname" + ) + schemas["build.sh"]["properties"]["TERMUX_PKG_UPDATE_VERSION_REGEXP"][ + "format" + ] = "regex" + schemas["build.sh"]["properties"]["TERMUX_PKG_LICENSE"]["pattern"] = ( + rf"{ATOM}(,{ATOM})*" + ) + return schemas diff --git a/src/termux_language_server/packages/__init__.py b/src/termux_language_server/packages/__init__.py new file mode 100644 index 0000000..bdc924f --- /dev/null +++ b/src/termux_language_server/packages/__init__.py @@ -0,0 +1,48 @@ +r"""Packages +============ +""" + +from .. import FILETYPE + +PACKAGE_VARIABLES = { + "PKGBUILD": { + "depends", + "makedepends", + "optdepends", + "conflicts", + "provides", + "replaces", + } +} + + +def search_package_document(name: str, filetype: FILETYPE) -> str: + r"""Search package document. + + :param name: + :type name: str + :param filetype: + :type filetype: FILETYPE + :rtype: str + """ + if filetype == "PKGBUILD": + from .pkgbuild import get_package_document + else: + raise NotImplementedError + return get_package_document(name) + + +def search_package_names(name: str, filetype: FILETYPE) -> dict[str, str]: + r"""Search package names. + + :param name: + :type name: str + :param filetype: + :type filetype: FILETYPE + :rtype: dict[str, str] + """ + if filetype == "PKGBUILD": + from .pkgbuild import get_package_names + else: + raise NotImplementedError + return get_package_names(name) diff --git a/src/termux_language_server/packages/pkgbuild.py b/src/termux_language_server/packages/pkgbuild.py new file mode 100644 index 0000000..3e750af --- /dev/null +++ b/src/termux_language_server/packages/pkgbuild.py @@ -0,0 +1,54 @@ +r"""PKGBUILD packages +===================== +""" + +from pathlib import Path + +from jinja2 import Template +from platformdirs import user_config_path +from pyalpm import Handle, Package + +DB = Handle(".", "/var/lib/pacman").get_localdb() +TEMPLATE_NAME = "template.md.j2" +PATH = user_config_path("pacman") / TEMPLATE_NAME +if not PATH.exists(): + PATH = Path(__file__).parent.parent / "assets" / "jinja2" / TEMPLATE_NAME +TEMPLATE = PATH.read_text() + + +def render_document(pkg: Package, template: str = TEMPLATE) -> str: + r"""Render document. + + :param pkg: + :type pkg: Package + :param template: + :type template: str + :rtype: str + """ + return Template(template).render(pkg=pkg) + + +def get_package_document(name: str, template: str = TEMPLATE) -> str: + r"""Get package document. + + :param name: + :type name: str + :param template: + :type template: str + :rtype: str + """ + return render_document(DB.get_pkg(name), template) + + +def get_package_names(name: str) -> dict[str, str]: + r"""Get package names. + + :param name: + :type name: str + :rtype: dict[str, str] + """ + return { + pkg.name: render_document(pkg) + for pkg in DB.search(name) + if pkg.name.startswith(name) + } diff --git a/src/termux_language_server/parser.py b/src/termux_language_server/parser.py deleted file mode 100644 index adeda13..0000000 --- a/src/termux_language_server/parser.py +++ /dev/null @@ -1,43 +0,0 @@ -r"""Parser -========== -""" -import os -from glob import glob - -from platformdirs import user_data_path -from tree_sitter import Language, Parser, Tree - -LIBS = glob( - os.path.join( - os.path.join(os.path.join(os.path.dirname(__file__), "data"), "lib"), - "*", - ) -) -if len(LIBS) > 0: - LIB = LIBS[0] -else: - # https://github.com/nvim-treesitter/nvim-treesitter/issues/5493 - LIB = str( - next( - ( - user_data_path("nvim") - / "repos" - / "github.com" - / "nvim-treesitter" - / "nvim-treesitter" - / "parser" - ).glob("bash.*") - ) - ) -PARSER = Parser() -PARSER.set_language(Language(LIB, "bash")) - - -def parse(source: bytes) -> Tree: - r"""Parse. - - :param source: - :type source: bytes - :rtype: Tree - """ - return PARSER.parse(source) diff --git a/src/termux_language_server/schema.py b/src/termux_language_server/schema.py new file mode 100644 index 0000000..8a66da3 --- /dev/null +++ b/src/termux_language_server/schema.py @@ -0,0 +1,92 @@ +r"""Schema +========== +""" + +from dataclasses import dataclass +from typing import Literal + +from lsp_tree_sitter import UNI +from lsp_tree_sitter.schema import Trie +from lsprotocol.types import Position, Range +from tree_sitter import Node + + +@dataclass +class BashTrie(Trie): + r"""Bashtrie.""" + + value: dict[str, "Trie"] | list["Trie"] | str | Literal[0] = 0 + + @classmethod + def from_string_node(cls, node: Node, parent: "Trie | None") -> "Trie": + r"""From string node. + + ``_ + + :param cls: + :param node: + :type node: Node + :param parent: + :type parent: Trie | None + :rtype: "Trie" + """ + if node.type == "string" and node.children == 3: + node = node.children[1] + text = UNI(node).text + _range = UNI(node).range + if node.type in {"string", "raw_string"} and node.children != 3: + text = text.strip("'\"") + _range.start.character += 1 + _range.end.character -= 1 + return cls(_range, parent, text) + + @classmethod + def from_node(cls, node: Node, parent: "Trie | None") -> "Trie": + r"""From node. + + :param node: + :type node: Node + :param parent: + :type parent: Trie | None + :rtype: "Trie" + """ + string_types = { + "word", + "string", + "raw_string", + "concatenation", + "number", + "simple_expansion", + } + if node.type in string_types: + return cls.from_string_node(node, parent) + if node.type == "function_definition": + return cls(UNI(node).range, parent, 0) + if node.type == "variable_assignment": + if len(node.children) < 3: + return cls(UNI(node).range, parent, "") + node = node.children[2] + if node.type == "array": + trie = cls(UNI(node).range, parent, []) + value: list[Trie] = trie.value # type: ignore + trie.value = [ + cls.from_node(child, trie) + for child in node.children + if child.type in string_types + ] + return trie + if node.type in string_types: + return cls.from_string_node(node, parent) + if node.type == "program": + trie = cls(Range(Position(0, 0), Position(1, 0)), parent, {}) + value: dict[str, Trie] = trie.value # type: ignore + for child in node.children: + if child.type in { + "variable_assignment", + "function_definition", + }: + value[UNI(child.children[0]).text] = cls.from_node( + child, trie + ) + return trie + raise NotImplementedError(node.type) diff --git a/src/termux_language_server/server.py b/src/termux_language_server/server.py index 6e543f2..7454411 100644 --- a/src/termux_language_server/server.py +++ b/src/termux_language_server/server.py @@ -1,16 +1,20 @@ r"""Server ========== """ + import re from typing import Any +from lsp_tree_sitter.complete import get_completion_list_by_enum +from lsp_tree_sitter.diagnose import get_diagnostics +from lsp_tree_sitter.finders import PositionFinder +from lsp_tree_sitter.format import get_text_edits from lsprotocol.types import ( - INITIALIZE, TEXT_DOCUMENT_COMPLETION, TEXT_DOCUMENT_DID_CHANGE, TEXT_DOCUMENT_DID_OPEN, TEXT_DOCUMENT_DOCUMENT_LINK, - TEXT_DOCUMENT_FORMATTING, + # TEXT_DOCUMENT_FORMATTING, TEXT_DOCUMENT_HOVER, CompletionItem, CompletionItemKind, @@ -21,29 +25,27 @@ DocumentLink, DocumentLinkParams, Hover, - InitializeParams, MarkupContent, MarkupKind, - Position, - Range, + PublishDiagnosticsParams, TextDocumentPositionParams, TextEdit, ) -from pygls.server import LanguageServer +from pygls.lsp.server import LanguageServer -from .documents import get_document, get_filetype from .finders import ( + DIAGNOSTICS_FINDER_CLASSES, + FORMAT_FINDER_CLASSES, CSVFinder, - InvalidKeywordFinder, - RequiredKeywordFinder, - UnsortedCSVFinder, - UnsortedKeywordFinder, + MinGWFinder, + PackageFinder, +) +from .packages import ( + PACKAGE_VARIABLES, + search_package_document, + search_package_names, ) -from .parser import parse -from .tree_sitter_lsp.diagnose import get_diagnostics -from .tree_sitter_lsp.finders import PositionFinder -from .tree_sitter_lsp.format import get_text_edits -from .utils import DIAGNOSTICS_FINDERS, get_keywords +from .utils import get_filetype, get_schema, parser class TermuxLanguageServer(LanguageServer): @@ -57,25 +59,8 @@ def __init__(self, *args: Any) -> None: :rtype: None """ super().__init__(*args) - self.document = {} - self.keywords = {} - self.required = {} - self.csvs = {} self.trees = {} - @self.feature(INITIALIZE) - def initialize(params: InitializeParams) -> None: - r"""Initialize. - - :param params: - :type params: InitializeParams - :rtype: None - """ - opts = params.initialization_options - method = getattr(opts, "method", "builtin") - self.document, self.required, self.csvs = get_document(method) # type: ignore - self.keywords = get_keywords(self.document) - @self.feature(TEXT_DOCUMENT_DID_OPEN) @self.feature(TEXT_DOCUMENT_DID_CHANGE) def did_change(params: DidChangeTextDocumentParams) -> None: @@ -88,22 +73,29 @@ def did_change(params: DidChangeTextDocumentParams) -> None: filetype = get_filetype(params.text_document.uri) if filetype == "": return None - document = self.workspace.get_document(params.text_document.uri) - self.trees[document.uri] = parse(document.source.encode()) + document = self.workspace.get_text_document( + params.text_document.uri + ) + self.trees[document.uri] = parser.parse(document.source.encode()) diagnostics = get_diagnostics( - DIAGNOSTICS_FINDERS - + [ - RequiredKeywordFinder(self.required[filetype]), - InvalidKeywordFinder(set(self.keywords[filetype])), - UnsortedKeywordFinder(self.keywords[filetype]), - UnsortedCSVFinder(self.csvs[filetype]), - ], document.uri, self.trees[document.uri], + DIAGNOSTICS_FINDER_CLASSES, + filetype, + ) + if document.path is not None and filetype == "PKGBUILD": + from .tools.namcap import namcap + + diagnostics += namcap(document.path, document.source) + self.text_document_publish_diagnostics( + PublishDiagnosticsParams( + params.text_document.uri, + diagnostics, + ) ) - self.publish_diagnostics(params.text_document.uri, diagnostics) - @self.feature(TEXT_DOCUMENT_FORMATTING) + # https://github.com/termux/termux-language-server/issues/19#issuecomment-2413779969 + # @self.feature(TEXT_DOCUMENT_FORMATTING) def format(params: DocumentFormattingParams) -> list[TextEdit]: r"""Format. @@ -114,14 +106,14 @@ def format(params: DocumentFormattingParams) -> list[TextEdit]: filetype = get_filetype(params.text_document.uri) if filetype == "": return [] - document = self.workspace.get_document(params.text_document.uri) + document = self.workspace.get_text_document( + params.text_document.uri + ) return get_text_edits( - [ - UnsortedKeywordFinder(self.keywords[filetype]), - UnsortedCSVFinder(self.csvs[filetype]), - ], document.uri, self.trees[document.uri], + FORMAT_FINDER_CLASSES, + filetype, ) @self.feature(TEXT_DOCUMENT_DOCUMENT_LINK) @@ -135,12 +127,33 @@ def document_link(params: DocumentLinkParams) -> list[DocumentLink]: filetype = get_filetype(params.text_document.uri) if filetype == "": return [] - document = self.workspace.get_document(params.text_document.uri) - return CSVFinder(self.csvs[filetype]).get_document_links( - document.uri, - self.trees[document.uri], - "https://github.com/termux/termux-packages/tree/master/packages/{{name}}/build.sh", + document = self.workspace.get_text_document( + params.text_document.uri ) + if filetype in {"build.sh", "subpackage.sh"}: + return CSVFinder(filetype).get_document_links( + document.uri, + self.trees[document.uri], + "https://github.com/termux/termux-packages/tree/master/packages/{{name}}/build.sh", + ) + elif filetype in {"PKGBUILD", "install"}: + if ( + len( + MinGWFinder().find_all( + document.uri, self.trees[document.uri] + ) + ) + > 0 + ): + url = "https://packages.msys2.org/base/{{uni.text}}" + else: + url = "https://archlinux.org/packages/{{uni.text}}" + return PackageFinder().get_document_links( + document.uri, + self.trees[document.uri], + url, + ) + raise NotImplementedError @self.feature(TEXT_DOCUMENT_HOVER) def hover(params: TextDocumentPositionParams) -> Hover | None: @@ -153,36 +166,61 @@ def hover(params: TextDocumentPositionParams) -> Hover | None: filetype = get_filetype(params.text_document.uri) if filetype == "": return None - document = self.workspace.get_document(params.text_document.uri) + document = self.workspace.get_text_document( + params.text_document.uri + ) uni = PositionFinder(params.position).find( document.uri, self.trees[document.uri] ) if uni is None: return None - text = uni.get_text() - _range = uni.get_range() parent = uni.node.parent if parent is None: return None - if ( + text = uni.text + _range = uni.range + # we only hover variable names and function names + if not ( uni.node.type == "variable_name" - and text.isupper() or uni.node.type == "word" and parent.type in { "function_definition", "command_name", } - and text.islower() ): + if ( + parent.type == "array" + and parent.parent is not None + and parent.parent.children[0].text is not None + and parent.parent.children[0].text.decode() + in PACKAGE_VARIABLES.get(filetype, set()) + ): + result = search_package_document(text, filetype) + if result is None: + return None + return Hover( + MarkupContent(MarkupKind.Markdown, result), _range + ) return None - result, _filetype = self.document.get(text, ["", ""]) - if result == "" or _filetype != filetype: - return None - return Hover( - MarkupContent(MarkupKind.PlainText, result), - _range, - ) + if description := ( + get_schema(filetype) + .get("properties", {}) + .get(text, {}) + .get("description") + ): + return Hover( + MarkupContent(MarkupKind.Markdown, description), + _range, + ) + for k, v in ( + get_schema(filetype).get("patternProperties", {}).items() + ): + if re.match(k, text): + return Hover( + MarkupContent(MarkupKind.Markdown, v["description"]), + _range, + ) @self.feature(TEXT_DOCUMENT_COMPLETION) def completions(params: CompletionParams) -> CompletionList: @@ -195,68 +233,75 @@ def completions(params: CompletionParams) -> CompletionList: filetype = get_filetype(params.text_document.uri) if filetype == "": return CompletionList(False, []) - word = self._cursor_word( - params.text_document.uri, params.position, False + document = self.workspace.get_text_document( + params.text_document.uri ) - token = "" if word is None else word[0] - items = [ - CompletionItem( - x, - kind=CompletionItemKind.Variable - if x.isupper() - else CompletionItemKind.Function, - documentation=self.document[x][0], - insert_text=x, + uni = PositionFinder(params.position, right_equal=True).find( + document.uri, self.trees[document.uri] + ) + if uni is None: + return CompletionList(False, []) + parent = uni.node.parent + if parent is None: + return CompletionList(False, []) + text = uni.text + if ( + parent.type == "array" + and parent.parent is not None + and parent.parent.children[0].text is not None + and parent.parent.children[0].text.decode() + in PACKAGE_VARIABLES.get(filetype, set()) + ): + return CompletionList( + False, + [ + CompletionItem( + k, + kind=CompletionItemKind.Module, + documentation=MarkupContent( + MarkupKind.Markdown, v + ), + insert_text=k, + ) + for k, v in search_package_names( + text, filetype + ).items() + ], ) - for x in self.document - if x.startswith(token) and self.document[x][1] in filetype - ] - return CompletionList(False, items) - - def _cursor_line(self, uri: str, position: Position) -> str: - r"""Cursor line. - - :param uri: - :type uri: str - :param position: - :type position: Position - :rtype: str - """ - document = self.workspace.get_document(uri) - return document.source.splitlines()[position.line] - - def _cursor_word( - self, - uri: str, - position: Position, - include_all: bool = True, - regex: str = r"\w+", - ) -> tuple[str, Range]: - """Cursor word. - - :param self: - :param uri: - :type uri: str - :param position: - :type position: Position - :param include_all: - :type include_all: bool - :param regex: - :type regex: str - :rtype: tuple[str, Range] - """ - line = self._cursor_line(uri, position) - for m in re.finditer(regex, line): - if m.start() <= position.character <= m.end(): - end = m.end() if include_all else position.character - return ( - line[m.start() : end], - Range( - Position(position.line, m.start()), - Position(position.line, end), - ), + schema = get_schema(filetype) + if ( + parent.type == "array" + and parent.parent is not None + and parent.parent.children[0].text is not None + ): + property = schema["properties"].get( + parent.parent.children[0].text.decode(), {} ) - return ( - "", - Range(Position(position.line, 0), Position(position.line, 0)), - ) + return get_completion_list_by_enum(text, property) + return CompletionList( + False, + [ + CompletionItem( + k, + kind=CompletionItemKind.Function + if v.get("const") == 0 + else CompletionItemKind.Field + if v.get("type") == "array" + else CompletionItemKind.Variable, + documentation=MarkupContent( + MarkupKind.Markdown, v["description"] + ), + insert_text=k, + ) + for k, v in ( + schema.get("properties", {}) + | { + k.lstrip("^").split("(")[0]: v + for k, v in schema.get( + "patternProperties", {} + ).items() + } + ).items() + if k.startswith(text) + ], + ) diff --git a/src/termux_language_server/tools/namcap.py b/src/termux_language_server/tools/namcap.py new file mode 100644 index 0000000..bbe94e1 --- /dev/null +++ b/src/termux_language_server/tools/namcap.py @@ -0,0 +1,39 @@ +r"""Namcap +========== +""" + +from lsprotocol.types import Diagnostic, DiagnosticSeverity, Position, Range + + +def namcap(path: str, source: str) -> list[Diagnostic]: + r"""Namcap. + + :param path: + :type path: str + :param source: + :type source: str + :rtype: list[Diagnostic] + """ + try: + from Namcap.rules import all_rules + except ImportError: + return [] + from Namcap.package import load_from_pkgbuild + from Namcap.ruleclass import PkgbuildRule + from Namcap.tags import format_message + + pkginfo = load_from_pkgbuild(path) + items = {} + for value in all_rules.values(): + rule = value() + if isinstance(rule, PkgbuildRule): + rule.analyze(pkginfo, "PKGBUILD") # type: ignore + for msg in rule.errors: + items[format_message(msg)] = DiagnosticSeverity.Error + for msg in rule.warnings: + items[format_message(msg)] = DiagnosticSeverity.Warning + end = len(source.splitlines()[0]) + return [ + Diagnostic(Range(Position(0, 0), Position(0, end)), msg, severity) + for msg, severity in items.items() + ] diff --git a/src/termux_language_server/tree_sitter_lsp/__init__.py b/src/termux_language_server/tree_sitter_lsp/__init__.py deleted file mode 100644 index a260b6a..0000000 --- a/src/termux_language_server/tree_sitter_lsp/__init__.py +++ /dev/null @@ -1,460 +0,0 @@ -r"""Tree-sitter LSP -=================== -""" -import os -from copy import deepcopy -from typing import Any - -from jinja2 import Template -from lsprotocol.types import ( - Diagnostic, - DiagnosticSeverity, - DocumentLink, - Location, - Position, - Range, - TextEdit, -) -from pygls.uris import to_fs_path -from tree_sitter import Node, Tree, TreeCursor - -# maximum of recursive search -LEVEL = 5 - - -class UNI: - r"""Unified node identifier.""" - - def __init__(self, uri: str, node: Node) -> None: - r"""Init. - - :param uri: - :type uri: str - :param node: - :type node: Node - :rtype: None - """ - self.uri = uri - self.node = node - - def __repr__(self) -> str: - r"""Repr. - - :rtype: str - """ - return f"{self.get_text()}@{self.uri}:{self.node.start_point[0] + 1}:{self.node.start_point[1] + 1}-{self.node.end_point[0] + 1}:{self.node.end_point[1]}" - - def __eq__(self, that: "UNI") -> bool: - r"""Eq. - - :param that: - :type that: UNI - :rtype: bool - """ - return self.node == that.node - - def get_text(self) -> str: - r"""Get text. - - :rtype: str - """ - return self.node2text(self.node) - - @staticmethod - def node2text(node: Node) -> str: - r"""Node2text. - - :param node: - :type node: Node - :rtype: str - """ - return node.text.decode() - - def get_location(self) -> Location: - r"""Get location. - - :rtype: Location - """ - return Location(self.uri, self.get_range()) - - def get_range(self) -> Range: - r"""Get range. - - :rtype: Range - """ - return self.node2range(self.node) - - @staticmethod - def node2range(node: Node) -> Range: - r"""Node2range. - - :param node: - :type node: Node - :rtype: Range - """ - return Range(Position(*node.start_point), Position(*node.end_point)) - - def get_path(self) -> str: - r"""Get path. - - :rtype: str - """ - return self.uri2path(self.uri) - - @staticmethod - def uri2path(uri: str) -> str: - r"""Uri2path. - - :param uri: - :type uri: str - :rtype: str - """ - if path := to_fs_path(uri): - return path - raise TypeError - - def get_diagnostic( - self, - message: str, - severity: DiagnosticSeverity, - **kwargs: Any, - ) -> Diagnostic: - r"""Get diagnostic. - - :param message: - :type message: str - :param severity: - :type severity: DiagnosticSeverity - :param kwargs: - :type kwargs: Any - :rtype: Diagnostic - """ - _range = self.get_range() - _range.end.character -= 1 - return Diagnostic( - _range, - Template(message).render(uni=self, **kwargs), - severity, - ) - - def get_text_edit(self, new_text: str) -> TextEdit: - r"""Get text edit. - - :param new_text: - :type new_text: str - :rtype: TextEdit - """ - return TextEdit(self.get_range(), new_text) - - def get_document_link(self, target: str, **kwargs) -> DocumentLink: - r"""Get document link. - - :param target: - :type target: str - :param kwargs: - :rtype: DocumentLink - """ - return DocumentLink( - self.get_range(), - Template(target).render(uni=self, **kwargs), - ) - - @staticmethod - def join(path, text) -> str: - r"""Join. - - :param path: - :param text: - :rtype: str - """ - return os.path.join(os.path.dirname(path), text) - - -class Finder: - r"""Finder.""" - - def __init__( - self, - message: str = "", - severity: DiagnosticSeverity = DiagnosticSeverity.Error, - ) -> None: - r"""Init. - - :param message: - :type message: str - :param severity: - :type severity: DiagnosticSeverity - :rtype: None - """ - self.level = 0 - self.message = message - self.severity = severity - self.reset() - - def __call__(self, uni: UNI) -> bool: - r"""Call. - - :param uni: - :type uni: UNI - :rtype: bool - """ - return True - - def __and__(self, second: "Finder") -> "Finder": - r"""And. - - :param second: - :type second: Finder - :rtype: "Finder" - """ - finder = deepcopy(self) - finder.__call__ = lambda uni: self(uni) and second(uni) - return finder - - def __or__(self, second: "Finder") -> "Finder": - r"""Or. - - :param second: - :type second: Finder - :rtype: "Finder" - """ - finder = deepcopy(self) - finder.__call__ = lambda uni: self(uni) or second(uni) - return finder - - def __minus__(self, second: "Finder") -> "Finder": - r"""Minus. - - :param second: - :type second: Finder - :rtype: "Finder" - """ - finder = deepcopy(self) - finder.__call__ = lambda uni: self(uni) and not second(uni) - return finder - - def is_include_node(self, node: Node) -> bool: - r"""Is include node. - - :param node: - :type node: Node - :rtype: bool - """ - return False - - def parse(self, code: bytes) -> Tree: - r"""Parse. - - :param code: - :type code: bytes - :rtype: Tree - """ - raise NotImplementedError - - def uri2tree(self, uri: str) -> Tree | None: - r"""Convert URI to tree. - - :param uri: - :type uri: str - :rtype: Tree | None - """ - path = UNI.uri2path(uri) - if not os.path.exists(path): - return None - with open(path, "rb") as f: - code = f.read() - return self.parse(code) - - def uni2uri(self, uni: UNI) -> str: - r"""Convert UNI to URI. - - :param uni: - :type uni: UNI - :rtype: str - """ - return uni.join(uni.uri, uni.get_text()) - - def uni2path(self, uni: UNI) -> str: - r"""Convert UNI to path. - - :param self: - :param uni: - :type uni: UNI - :rtype: str - """ - uri = self.uni2uri(uni) - return UNI.uri2path(uri) - - def move_cursor( - self, uri: str, cursor: TreeCursor, is_all: bool = False - ) -> str | None: - r"""Move cursor. - - :param self: - :param uri: - :type uri: str - :param cursor: - :type cursor: TreeCursor - :param is_all: - :type is_all: bool - :rtype: str | None - """ - while self(UNI(uri, cursor.node)) is False: - if self.is_include_node(cursor.node) and self.level < LEVEL: - self.level += 1 - old_uri = uri - uri = self.uni2uri(UNI(uri, cursor.node)) - tree = self.uri2tree(uri) - if tree is not None: - if is_all: - self.find_all(uri, tree, False) - else: - result = self.find(uri, tree) - if result is not None: - return - uri = old_uri - self.level -= 1 - if cursor.node.child_count > 0: - cursor.goto_first_child() - continue - while cursor.node.next_sibling is None: - cursor.goto_parent() - # when cannot find new nodes, return - if cursor.node.parent is None: - return None - cursor.goto_next_sibling() - return uri - - def reset(self) -> None: - r"""Reset. - - :rtype: None - """ - self.unis = [] - - def prepare( - self, uri: str, tree: Tree | None = None, reset: bool = True - ) -> TreeCursor: - r"""Prepare. - - :param uri: - :type uri: str - :param tree: - :type tree: Tree | None - :param reset: - :type reset: bool - :rtype: TreeCursor - """ - if reset: - self.reset() - if tree is None: - tree = self.uri2tree(uri) - if tree is None: - raise TypeError - return tree.walk() - - def find( - self, uri: str, tree: Tree | None = None, reset: bool = True - ) -> UNI | None: - r"""Find. - - :param uri: - :type uri: str - :param tree: - :type tree: Tree | None - :param reset: - :type reset: bool - :rtype: UNI | None - """ - cursor = self.prepare(uri, tree, reset) - _uri = self.move_cursor(uri, cursor, False) - if _uri is not None: - return UNI(_uri, cursor.node) - else: - return None - - def find_all( - self, uri: str, tree: Tree | None = None, reset: bool = True - ) -> list[UNI]: - r"""Find all. - - :param uri: - :type uri: str - :param tree: - :type tree: Tree | None - :param reset: - :type reset: bool - :rtype: list[UNI] - """ - cursor = self.prepare(uri, tree, reset) - while True: - _uri = self.move_cursor(uri, cursor, True) - if _uri is not None: - self.unis += [UNI(_uri, cursor.node)] - while cursor.node.next_sibling is None: - cursor.goto_parent() - # when cannot find new nodes, return - if cursor.node.parent is None: - return self.unis - cursor.goto_next_sibling() - - def uni2diagnostic(self, uni: UNI) -> Diagnostic: - r"""Uni2diagnostic. - - :param uni: - :type uni: UNI - :rtype: Diagnostic - """ - return uni.get_diagnostic(self.message, self.severity) - - def unis2diagnostics(self, unis: list[UNI]) -> list[Diagnostic]: - r"""Unis2diagnostics. - - :param unis: - :type unis: list[UNI] - :rtype: list[Diagnostic] - """ - return [self.uni2diagnostic(uni) for uni in unis] - - def get_diagnostics(self, uri: str, tree: Tree) -> list[Diagnostic]: - r"""Get diagnostics. - - :param self: - :param uri: - :type uri: str - :param tree: - :type tree: Tree - :rtype: list[Diagnostic] - """ - return self.unis2diagnostics(self.find_all(uri, tree)) - - def get_text_edits(self, uri: str, tree: Tree) -> list[TextEdit]: - r"""Get text edits. - - :param self: - :param uri: - :type uri: str - :param tree: - :type tree: Tree - :rtype: list[TextEdit] - """ - self.find_all(uri, tree) - return [] - - def get_document_links( - self, uri: str, tree: Tree, template: str - ) -> list[DocumentLink]: - r"""Get document links. - - :param uri: - :type uri: str - :param tree: - :type tree: Tree - :param template: - :type template: str - :rtype: list[DocumentLink] - """ - self.find_all(uri, tree) - return [ - uni.get_document_link(template) for uni in self.find_all(uri, tree) - ] diff --git a/src/termux_language_server/tree_sitter_lsp/complete.py b/src/termux_language_server/tree_sitter_lsp/complete.py deleted file mode 100644 index f7731a9..0000000 --- a/src/termux_language_server/tree_sitter_lsp/complete.py +++ /dev/null @@ -1,48 +0,0 @@ -r"""Complete -============ -""" -import os -from glob import glob -from pathlib import Path - -from lsprotocol.types import CompletionItem, CompletionItemKind, CompletionList - -from . import UNI - - -def get_completion_list_by_uri( - uri: str, text: str = "", expr: str = "*" -) -> CompletionList: - r"""Get completion list by uri. - - :param uri: - :type uri: str - :param text: - :type text: str - :param expr: - :type expr: str - :rtype: CompletionList - """ - dirname = os.path.dirname(UNI.uri2path(uri)) - return CompletionList( - False, - [ - CompletionItem( - x.rpartition(dirname + os.path.sep)[-1], - kind=CompletionItemKind.File - if os.path.isfile(x) - else CompletionItemKind.Folder, - documentation=Path(x).read_text() - if os.path.isfile(x) - else "\n".join(os.listdir(x)), - insert_text=x.rpartition(dirname + os.path.sep)[-1], - ) - for x in [ - file + ("" if os.path.isfile(file) else os.path.sep) - for file in glob( - os.path.join(dirname, text + f"**{os.path.sep}" + expr), - recursive=True, - ) - ] - ], - ) diff --git a/src/termux_language_server/tree_sitter_lsp/diagnose.py b/src/termux_language_server/tree_sitter_lsp/diagnose.py deleted file mode 100644 index 7b521a9..0000000 --- a/src/termux_language_server/tree_sitter_lsp/diagnose.py +++ /dev/null @@ -1,126 +0,0 @@ -r"""Diagnose -============ -""" -import sys -from typing import Callable, Literal - -from lsprotocol.types import Diagnostic, DiagnosticSeverity -from tree_sitter import Tree - -from . import Finder - - -def get_diagnostics( - finders: list[Finder], uri: str, tree: Tree -) -> list[Diagnostic]: - r"""Get diagnostics. - - :param finders: - :type finders: list[Finder] - :param uri: - :type uri: str - :param tree: - :type tree: Tree - :rtype: list[Diagnostic] - """ - return [ - diagnostic - for finder in finders - for diagnostic in finder.get_diagnostics(uri, tree) - ] - - -def count_level( - diagnostics: list[Diagnostic], - level: DiagnosticSeverity = DiagnosticSeverity.Warning, -) -> int: - r"""Count level. - - :param diagnostics: - :type diagnostics: list[Diagnostic] - :param level: - :type level: DiagnosticSeverity - :rtype: int - """ - return len( - [ - diagnostic - for diagnostic in diagnostics - if diagnostic.severity and diagnostic.severity <= level - ] - ) - - -class _Colorama: - """Colorama.""" - - def __getattribute__(self, _: str) -> str: - """Getattribute. - - :param _: - :type _: str - :rtype: str - """ - return "" - - -def diagnostics2linter_messages( - path: str, - diagnostics: list[Diagnostic], - color: Literal["auto", "always", "never"] = "auto", - colors: list[str] | None = None, -) -> list[str]: - r"""Diagnostics2linter messages. - - :param path: - :type path: str - :param diagnostics: - :type diagnostics: list[Diagnostic] - :param color: - :type color: Literal["auto", "always", "never"] - :param colors: - :type colors: list[str] | None - :rtype: list[str] - """ - from colorama import Fore, init - - init() - if not sys.stdout.isatty() and color == "auto" or color == "never": - Fore = _Colorama() - if colors is None: - colors = [Fore.RESET, Fore.RED, Fore.YELLOW, Fore.BLUE, Fore.GREEN] - return [ - f"{Fore.MAGENTA}{path}{Fore.RESET}:{Fore.CYAN}{diagnostic.range.start.line + 1}:{diagnostic.range.start.character + 1}{Fore.RESET}-{Fore.CYAN}{diagnostic.range.end.line + 1}:{diagnostic.range.end.character + 1}{Fore.RESET}:{colors[diagnostic.severity if diagnostic.severity else 0]}{str(diagnostic.severity).split('.')[-1].lower()}{Fore.RESET}: {diagnostic.message}" - for diagnostic in diagnostics - ] - - -def check( - paths: list[str], - finders: list[Finder], - parse: Callable[[bytes], Tree], - color: Literal["auto", "always", "never"] = "auto", -) -> int: - r"""Check. - - :param paths: - :type paths: list[str] - :param finders: - :type finders: list[Finder] - :param parse: - :type parse: Callable[[bytes], Tree] - :param color: - :type color: Literal["auto", "always", "never"] - :rtype: int - """ - count = 0 - lines = [] - for path in paths: - with open(path, "rb") as f: - src = f.read() - tree = parse(src) - diagnostics = get_diagnostics(finders, path, tree) - count += count_level(diagnostics) - lines += diagnostics2linter_messages(path, diagnostics, color) - print("\n".join(lines)) - return count diff --git a/src/termux_language_server/tree_sitter_lsp/finders.py b/src/termux_language_server/tree_sitter_lsp/finders.py deleted file mode 100644 index ebe18c5..0000000 --- a/src/termux_language_server/tree_sitter_lsp/finders.py +++ /dev/null @@ -1,517 +0,0 @@ -r"""Finders -=========== -""" -import os -from copy import deepcopy -from typing import Any - -from jinja2 import Template -from lsprotocol.types import ( - Diagnostic, - DiagnosticSeverity, - Location, - Position, - Range, - TextEdit, -) -from tree_sitter import Node, Tree - -from . import UNI, Finder - - -class MissingFinder(Finder): - r"""Missingfinder.""" - - def __init__( - self, - message: str = "{{uni.get_text()}}: missing", - severity: DiagnosticSeverity = DiagnosticSeverity.Error, - ) -> None: - r"""Init. - - :param message: - :type message: str - :param severity: - :type severity: DiagnosticSeverity - :rtype: None - """ - super().__init__(message, severity) - - def __call__(self, uni: UNI) -> bool: - r"""Call. - - :param uni: - :type uni: UNI - :rtype: bool - """ - node = uni.node - return node.is_missing and not ( - any(child.is_missing for child in node.children) - ) - - -class ErrorFinder(Finder): - r"""Errorfinder.""" - - def __init__( - self, - message: str = "{{uni.get_text()}}: error", - severity: DiagnosticSeverity = DiagnosticSeverity.Error, - ) -> None: - r"""Init. - - :param message: - :type message: str - :param severity: - :type severity: DiagnosticSeverity - :rtype: None - """ - super().__init__(message, severity) - - def __call__(self, uni: UNI) -> bool: - r"""Call. - - :param uni: - :type uni: UNI - :rtype: bool - """ - node = uni.node - return node.has_error and not ( - any(child.has_error for child in node.children) - ) - - -class NotFileFinder(Finder): - r"""NotFilefinder.""" - - def __init__( - self, - message: str = "{{uni.get_text()}}: no such file or directory", - severity: DiagnosticSeverity = DiagnosticSeverity.Error, - ) -> None: - r"""Init. - - :param message: - :type message: str - :param severity: - :type severity: DiagnosticSeverity - :rtype: None - """ - super().__init__(message, severity) - - def __call__(self, uni: UNI) -> bool: - r"""Call. - - :param uni: - :type uni: UNI - :rtype: bool - """ - path = self.uni2path(uni) - return not (os.path.isfile(path) or os.path.isdir(path)) - - -class RepeatedFinder(Finder): - r"""Repeatedfinder.""" - - def __init__( - self, - message: str = "{{uni.get_text()}}: is repeated on {{_uni}}", - severity: DiagnosticSeverity = DiagnosticSeverity.Warning, - ) -> None: - r"""Init. - - :param message: - :type message: str - :param severity: - :type severity: DiagnosticSeverity - :rtype: None - """ - super().__init__(message, severity) - - def reset(self) -> None: - r"""Reset. - - :rtype: None - """ - self.unis = [] - self._unis = [] - self.uni_pairs = [] - - def filter(self, uni: UNI) -> bool: - r"""Filter. - - :param uni: - :type uni: UNI - :rtype: bool - """ - return True - - def compare(self, uni: UNI, _uni: UNI) -> bool: - r"""Compare. - - :param uni: - :type uni: UNI - :param _uni: - :type _uni: UNI - :rtype: bool - """ - return uni.node.text == _uni.node.text - - def __call__(self, uni: UNI) -> bool: - r"""Call. - - :param uni: - :type uni: UNI - :rtype: bool - """ - if self.filter(uni) is False: - return False - for _uni in self._unis: - if self.compare(uni, _uni): - self.uni_pairs += [[uni, _uni]] - return True - self._unis += [uni] - return False - - def get_definitions(self, uni: UNI) -> list[Location]: - r"""Get definitions. - - :param uni: - :type uni: UNI - :rtype: list[Location] - """ - for uni_, _uni in self.uni_pairs: - # cache hit - if uni == uni_: - return [_uni.get_location()] - return [] - - def get_references(self, uni: UNI) -> list[Location]: - r"""Get references. - - :param uni: - :type uni: UNI - :rtype: list[Location] - """ - locations = [] - for uni_, _uni in self.uni_pairs: - # cache hit - if uni == _uni: - locations += [uni_.get_location()] - return locations - - def get_text_edits(self, uri: str, tree: Tree) -> list[TextEdit]: - r"""Get text edits. Only return two to avoid `Overlapping edit` - - :param self: - :param uri: - :type uri: str - :param tree: - :type tree: Tree - :rtype: list[TextEdit] - """ - self.find_all(uri, tree) - for uni, _uni in self.uni_pairs: - # swap 2 unis - return [ - uni.get_text_edit(_uni.get_text()), - _uni.get_text_edit(uni.get_text()), - ] - return [] - - def uni2diagnostic(self, uni: UNI) -> Diagnostic: - r"""Uni2diagnostic. - - :param uni: - :type uni: UNI - :rtype: Diagnostic - """ - for uni_, _uni in self.uni_pairs: - if uni == uni_: - return uni.get_diagnostic( - self.message, self.severity, _uni=_uni - ) - return uni.get_diagnostic(self.message, self.severity) - - -class UnsortedFinder(RepeatedFinder): - r"""Unsortedfinder.""" - - def __init__( - self, - message: str = "{{uni.get_text()}}: is unsorted due to {{_uni}}", - severity: DiagnosticSeverity = DiagnosticSeverity.Warning, - ) -> None: - r"""Init. - - :param message: - :type message: str - :param severity: - :type severity: DiagnosticSeverity - :rtype: None - """ - super().__init__(message, severity) - - def compare(self, uni: UNI, _uni: UNI) -> bool: - r"""Compare. - - :param uni: - :type uni: UNI - :param _uni: - :type _uni: UNI - :rtype: bool - """ - return uni.node.text < _uni.node.text - - -class UnFixedOrderFinder(RepeatedFinder): - r"""Unfixedorderfinder.""" - - def __init__( - self, - order: list[Any], - message: str = "{{uni.get_text()}}: is unsorted due to {{_uni}}", - severity: DiagnosticSeverity = DiagnosticSeverity.Warning, - ) -> None: - r"""Init. - - :param order: - :type order: list[Any] - :param message: - :type message: str - :param severity: - :type severity: DiagnosticSeverity - :rtype: None - """ - super().__init__(message, severity) - self.order = order - - def filter(self, uni: UNI) -> bool: - r"""Filter. - - :param uni: - :type uni: UNI - :rtype: bool - """ - return uni.get_text() in self.order - - def compare(self, uni: UNI, _uni: UNI) -> bool: - r"""Compare. - - :param uni: - :type uni: UNI - :param _uni: - :type _uni: UNI - :rtype: bool - """ - return self.order.index(uni.get_text()) < self.order.index( - _uni.get_text() - ) - - -class TypeFinder(Finder): - r"""Typefinder.""" - - def __init__( - self, - _type: str, - message: str = "", - severity: DiagnosticSeverity = DiagnosticSeverity.Information, - ) -> None: - r"""Init. - - :param self: - :param _type: - :type _type: str - :param message: - :type message: str - :param severity: - :type severity: DiagnosticSeverity - :rtype: None - """ - super().__init__(message, severity) - self.type = _type - - def __call__(self, uni: UNI) -> bool: - r"""Call. - - :param uni: - :type uni: UNI - :rtype: bool - """ - node = uni.node - return node.type == self.type - - -class PositionFinder(Finder): - r"""Positionfinder.""" - - def __init__(self, position: Position) -> None: - r"""Init. - - :param position: - :type position: Position - :rtype: None - """ - super().__init__() - self.position = position - - @staticmethod - def belong(position: Position, node: Node) -> bool: - r"""Belong. - - :param position: - :type position: Position - :param node: - :type node: Node - :rtype: bool - """ - return ( - Position(*node.start_point) <= position < Position(*node.end_point) - ) - - def __call__(self, uni: UNI) -> bool: - r"""Call. - - :param uni: - :type uni: UNI - :rtype: bool - """ - node = uni.node - return node.child_count == 0 and self.belong(self.position, node) - - -class RangeFinder(Finder): - r"""Rangefinder.""" - - def __init__(self, _range: Range) -> None: - r"""Init. - - :param _range: - :type _range: Range - :rtype: None - """ - super().__init__() - self.range = _range - - @staticmethod - def equal(_range: Range, node: Node) -> bool: - r"""Equal. - - :param _range: - :type _range: Range - :param node: - :type node: Node - :rtype: bool - """ - return _range.start == Position( - *node.start_point - ) and _range.end == Position(*node.end_point) - - def __call__(self, uni: UNI) -> bool: - r"""Call. - - :param uni: - :type uni: UNI - :rtype: bool - """ - node = uni.node - return self.equal(self.range, node) - - -class RequiresFinder(Finder): - r"""Requiresfinder.""" - - def __init__( - self, - requires: set[Any], - message: str = "{{require}}: required", - severity: DiagnosticSeverity = DiagnosticSeverity.Error, - ) -> None: - r"""Init. - - :param requires: - :type requires: set[Any] - :param message: - :type message: str - :param severity: - :type severity: DiagnosticSeverity - :rtype: None - """ - self.requires = requires - super().__init__(message, severity) - - def reset(self) -> None: - r"""Reset. - - :rtype: None - """ - self.unis = [] - self._requires = deepcopy(self.requires) - - def filter(self, uni: UNI, require: Any) -> bool: - r"""Filter. - - :param uni: - :type uni: UNI - :param require: - :type require: Any - :rtype: bool - """ - return False - - def __call__(self, uni: UNI) -> bool: - r"""Call. - - :param uni: - :type uni: UNI - :rtype: bool - """ - found = set() - for require in self._requires: - if self.filter(uni, require): - found |= {require} - self._requires -= found - return False - - def require2message(self, require: Any, **kwargs: Any) -> str: - r"""Require2message. - - :param require: - :type require: Any - :param kwargs: - :type kwargs: Any - :rtype: str - """ - return Template(self.message).render( - uni=self, require=require, **kwargs - ) - - def get_end(self, tree: Tree) -> int: - r"""Get end. - - :param tree: - :type tree: Tree - :rtype: int - """ - return len(UNI.node2text(tree.root_node).splitlines()[0]) - 1 - - def get_diagnostics(self, uri: str, tree: Tree) -> list[Diagnostic]: - r"""Get diagnostics. - - :param uri: - :type uri: str - :param tree: - :type tree: Tree - :rtype: list[Diagnostic] - """ - self.find_all(uri, tree) - end = self.get_end(tree) - return [ - Diagnostic( - Range(Position(0, 0), Position(0, end)), - self.require2message(i), - self.severity, - ) - for i in self._requires - ] diff --git a/src/termux_language_server/tree_sitter_lsp/format.py b/src/termux_language_server/tree_sitter_lsp/format.py deleted file mode 100644 index ce02b08..0000000 --- a/src/termux_language_server/tree_sitter_lsp/format.py +++ /dev/null @@ -1,103 +0,0 @@ -r"""Format -========== -""" -from typing import Callable - -from lsprotocol.types import Position, Range, TextEdit -from tree_sitter import Tree - -from . import Finder - - -def position_2d_to_1d(source: str, position: Position) -> int: - r"""Position 2d to 1d. - - :param source: - :type source: str - :param position: - :type position: Position - :rtype: int - """ - return ( - sum(len(line) + 1 for line in source.splitlines()[: position.line]) - + position.character - ) - - -def range_2d_to_1d(source: str, region: Range) -> range: - r"""Range 2d to 1d. - - :param source: - :type source: str - :param region: - :type region: Range - :rtype: range - """ - return range( - position_2d_to_1d(source, region.start), - position_2d_to_1d(source, region.end), - ) - - -def apply_text_edits(text_edits: list[TextEdit], source: str) -> str: - r"""Apply text edits. - - :param text_edits: - :type text_edits: list[TextEdit] - :param source: - :type source: str - :rtype: str - """ - for text_edit in text_edits: - region = range_2d_to_1d(source, text_edit.range) - source = ( - source[: region.start] + text_edit.new_text + source[region.stop :] - ) - return source - - -def format( - paths: list[str], finders: list[Finder], parse: Callable[[bytes], Tree] -) -> None: - r"""Format. - - :param paths: - :type paths: list[str] - :param finders: - :type finders: list[Finder] - :param parse: - :type parse: Callable[[bytes], Tree] - :rtype: None - """ - for path in paths: - with open(path, "rb") as f: - src = f.read() - tree = parse(src) - text_edits = [ - text_edit - for finder in finders - for text_edit in finder.get_text_edits(path, tree) - ] - src = apply_text_edits(text_edits, src.decode()) - with open(path, "w") as f: - f.write(src) - - -def get_text_edits( - finders: list[Finder], uri: str, tree: Tree -) -> list[TextEdit]: - r"""Get text edits. - - :param finders: - :type finders: list[Finder] - :param uri: - :type uri: str - :param tree: - :type tree: Tree - :rtype: list[TextEdit] - """ - return [ - text_edit - for finder in finders - for text_edit in finder.get_text_edits(uri, tree) - ] diff --git a/src/termux_language_server/utils.py b/src/termux_language_server/utils.py index d467019..00f9b01 100644 --- a/src/termux_language_server/utils.py +++ b/src/termux_language_server/utils.py @@ -1,118 +1,95 @@ r"""Utils ========= """ -from typing import Callable, Literal -from tree_sitter import Tree +import json +import os +from typing import Any, Literal -from .documents import get_document, get_filetype -from .finders import ( - InvalidKeywordFinder, - RequiredKeywordFinder, - UnsortedCSVFinder, - UnsortedKeywordFinder, -) -from .tree_sitter_lsp.diagnose import check as _check -from .tree_sitter_lsp.finders import ErrorFinder, MissingFinder -from .tree_sitter_lsp.format import format as _format +from tree_sitter import Language, Parser, Query +from tree_sitter_bash import language as get_language_ptr -DIAGNOSTICS_FINDERS = [ - ErrorFinder(), - MissingFinder(), -] +from . import FILETYPE +SCHEMAS = {} +QUERIES = {} +parser = Parser() +parser.language = Language(get_language_ptr()) -def get_keywords(document: dict[str, tuple[str, str]]) -> dict[str, list[str]]: - r"""Get keywords. - - :param document: - :type document: dict[str, tuple[str, str]] - :rtype: dict[str, list[str]] - """ - keywords = {"build.sh": [], "subpackage.sh": []} - for k, v in document.items(): - if v[1] == "build.sh": - keywords["build.sh"] += [k] - if v[1] == "subpackage.sh": - keywords["subpackage.sh"] += [k] - return keywords +def get_query(name: str, filetype: str = "bash") -> Query: + r"""Get query. -def get_paths(paths: list[str]) -> dict[str, list[str]]: - r"""Get paths. - - :param paths: - :type paths: list[str] - :rtype: dict[str, list[str]] + :param name: + :type name: str + :param filetype: + :type filetype: str + :rtype: Query """ - _paths = {"build.sh": [], "subpackage.sh": []} - for path in paths: - filetype = get_filetype(path) - if filetype == "build.sh": - _paths["build.sh"] += [path] - elif filetype == "subpackage.sh": - _paths["subpackage.sh"] += [path] + if name not in QUERIES: + with open( + os.path.join( + os.path.dirname(__file__), + "assets", + "queries", + f"{name}{os.path.extsep}scm", + ) + ) as f: + text = f.read() + if parser.language: + QUERIES[name] = Query(parser.language, text) else: raise NotImplementedError - return _paths + return QUERIES[name] -def check( - paths: list[str], - parse: Callable[[bytes], Tree], - color: Literal["auto", "always", "never"] = "auto", -) -> int: - r"""Check. +def get_schema(filetype: FILETYPE) -> dict[str, Any]: + r"""Get schema. - :param paths: - :type paths: list[str] - :param parse: - :type parse: Callable[[bytes], Tree] - :param color: - :type color: Literal["auto", "always", "never"] - :rtype: int + :param filetype: + :type filetype: FILETYPE + :rtype: dict[str, Any] """ - document, required, csvs = get_document() - keywords = get_keywords(document) - _paths = get_paths(paths) - return sum( - _check( - _paths[filetype], - DIAGNOSTICS_FINDERS - + [ - RequiredKeywordFinder(required[filetype]), - InvalidKeywordFinder(set(keywords[filetype])), - UnsortedKeywordFinder(keywords[filetype]), - UnsortedCSVFinder(csvs[filetype]), - ], - parse, - color, + if filetype not in SCHEMAS: + file = os.path.join( + os.path.dirname(__file__), + "assets", + "json", + f"{filetype}.json", ) - for filetype in ["build.sh", "subpackage.sh"] - ) + with open(file) as f: + SCHEMAS[filetype] = json.load(f) + return SCHEMAS[filetype] -def format( - paths: list[str], - parse: Callable[[bytes], Tree], -) -> None: - r"""Format. +def get_filetype(uri: str) -> FILETYPE | Literal[""]: + r"""Get filetype. - :param paths: - :type paths: list[str] - :param parse: - :type parse: Callable[[bytes], Tree] - :rtype: None + :param uri: + :type uri: str + :rtype: FILETYPE | Literal[""] """ - document, _, csvs = get_document() - keywords = get_keywords(document) - _paths = get_paths(paths) - for filetype in ["build.sh", "subpackage.sh"]: - _format( - _paths[filetype], - [ - UnsortedKeywordFinder(keywords[filetype]), - UnsortedCSVFinder(csvs[filetype]), - ], - parse, - ) + dirname = os.path.basename(os.path.dirname(uri)) + basename = os.path.basename(uri) + ext = uri.split(os.path.extsep)[-1] + if basename == "build.sh" and dirname != "scripts" and dirname != "recipe": + return "build.sh" + if basename.endswith(".subpackage.sh"): + return "subpackage.sh" + if ext == "install": + return "install" + if basename == "PKGBUILD": + return "PKGBUILD" + if basename == "makepkg.conf": + return "makepkg.conf" + if ext in {"ebuild", "eclass"}: + return "ebuild" + if basename == "make.conf": + return "make.conf" + if basename == "color.map": + return "color.map" + if ext == "mdd": + return "mdd" + if basename in {"devscripts.conf", ".devscripts"}: + return "devscripts.conf" + return "" diff --git a/templates/metainfo.py b/templates/metainfo.py deleted file mode 100644 index c82bc16..0000000 --- a/templates/metainfo.py +++ /dev/null @@ -1,18 +0,0 @@ -"""This file is generated by scikit-build.generate. -The information comes from pyproject.toml. -It provide some metainfo for docs/conf.py to build documents and -help2man to build man pages. -""" -from datetime import datetime - -# For docs/conf.py -project = "$name" -author = "\n".join(f"{a[0]} <{a[1]}>" for a in $authors) -copyright = datetime.now().year - -# For help2man -DESCRIPTION = "$description" -EPILOG = "Report bugs to " + $urls["Bug Report"] -VERSION = f"""$name $version -Copyright (C) {copyright} -Written by {author}""" diff --git a/templates/metainfo.py.j2 b/templates/metainfo.py.j2 new file mode 100644 index 0000000..bfe7fd5 --- /dev/null +++ b/templates/metainfo.py.j2 @@ -0,0 +1,22 @@ +"""This file is generated by setuptools-generate. +The information comes from pyproject.toml. +It provide some metainfo for docs/conf.py to build documents and +help2man to build man pages. +""" + +# For docs/conf.py +project = "{{ data['project']['name'] }}" +author = """{% for author in data['project']['authors'] -%} +{{ author['name'] }} <{{ author['email'] }}> {% endfor -%} +""" +copyright = "{{ year }}" + +# For help2man +DESCRIPTION = "{{ data['project']['description'] }}" +EPILOG = "Report bugs to {{ data['project']['urls']['Bug Report'] }}" +# format __version__ by yourself +VERSION = """{{ data['project']['name'] }} {__version__} +Copyright (C) {{ year }} +Written by {% for author in data['project']['authors'] -%} +{{ author['name'] }} <{{ author['email'] }}> {% endfor %}""" +SOURCE = "{{ data['project']['urls']['Source'] }}" diff --git a/tests/PKGBUILD b/tests/PKGBUILD new file mode 100644 index 0000000..db17068 --- /dev/null +++ b/tests/PKGBUILD @@ -0,0 +1,19 @@ +# Updated by https://github.com/Freed-Wu/pkgbuild-language-server/blob/main/.github/workflows/main.yml +pkgname=pkgbuild-language-server +pkgver=0.0.6 +pkgrel=1 +pkgdesc="Archlinux and Windows Msys2's PKGBUILD language server" +arch=("any") +mingw_arch=(wrong_arch) +url=https://github.com/Freed-Wu/pkgbuild-language-server +depends=(python-colorama python-jinja python-platformdirs python-pygls python-tree-sitter) +optdepends=(python-pypandoc python-markdown-it-py pacman pyalpm namcap) +makedepends=python-installer +license=('GPL3') +_py=py3 +source=("https://files.pythonhosted.org/packages/$_py/${pkgname::1}/${pkgname//-/_}/${pkgname//-/_}-$pkgver-$_py-none-any.whl") +sha256sums=('db062b5028e93aa9304d2783cd73017320587ac64fc4d8c01f514ae1015a4bf0') + +package() { + python -m installer -d "$pkgdir" ./*.whl +} diff --git a/tests/build.sh b/tests/build.sh index 8af3e6e..1f8c1e4 100644 --- a/tests/build.sh +++ b/tests/build.sh @@ -1,4 +1,3 @@ -# shellcheck disable=SC2034 # https://github.com/termux/termux-packages/pull/17457/files TERMUX_PKG_LICENSE=GPL-3.0 TERMUX_PKG_HOMEPAGE=https://github.com/ggerganov/llama.cpp @@ -6,7 +5,6 @@ TERMUX_PKG_DESCRIPTION="Port of Facebook's LLaMA model in C/C++" TERMUX_PKG_MAINTAINER=@termux TERMUX_PKG_SRCURL=https://github.com/ggerganov/llama.cpp/archive/refs/tags/${TERMUX_PKG_VERSION#*-}.tar.gz TERMUX_PKG_SHA256=315071e1034846e8ed448008cda35da481f056d6495696cb862ef8b94aaae0f6 -TERMUX_PKG_AUTO_UPDATE=true TERMUX_PKG_DEPENDS="libc++, libopenblas, openmpi" TERMUX_PKG_RECOMMENDS="python-sentencepiece, python-numpy" TERMUX_PKG_EXTRA_CONFIGURE_ARGS=" @@ -15,10 +13,11 @@ TERMUX_PKG_EXTRA_CONFIGURE_ARGS=" -DLLAMA_BLAS=ON -DLLAMA_BLAS_VENDOR=OpenBLAS " +TERMUX_PKG_AUTO_UPDATE=true # XXX: llama.cpp uses `int64_t`, but on 32-bit Android `size_t` is `int32_t`. # XXX: I don't think it will work if we simply casting it. -TERMUX_PKG_BLACKLISTED_ARCHES=(arm i686) +TERMUX_PKG_EXCLUDED_ARCHES=(arm i686) termux_pkg_auto_update() { local latest_tag @@ -26,7 +25,7 @@ termux_pkg_auto_update() { termux_github_api_get_tag "${TERMUX_PKG_SRCURL}" "${TERMUX_PKG_UPDATE_TAG_TYPE}" )" - if [[ -z "${latest_tag}" ]]; then + if [[ -z ${latest_tag} ]]; then termux_error_exit "ERROR: Unable to get tag from ${TERMUX_PKG_SRCURL}" fi termux_pkg_upgrade_version "0.0.0-${latest_tag}" diff --git a/tests/neovim-0.9.4.ebuild b/tests/neovim-0.9.4.ebuild new file mode 100644 index 0000000..ec45d50 --- /dev/null +++ b/tests/neovim-0.9.4.ebuild @@ -0,0 +1,119 @@ +# Copyright 1999-2023 Gentoo Authors +# Distributed under the terms of the GNU General Public License v2 + +EAPI=8 + +# RelWithDebInfo sets -Og -g +CMAKE_BUILD_TYPE=Release +LUA_COMPAT=( lua5-{1..2} luajit ) +inherit cmake lua-single optfeature xdg + +DESCRIPTION="Vim-fork focused on extensibility and agility" +HOMEPAGE="https://neovim.io" + +if [[ ${PV} == 9999 ]]; then + inherit git-r3 + EGIT_REPO_URI="https://github.com/neovim/neovim.git" +else + SRC_URI="https://github.com/neovim/neovim/archive/v${PV}.tar.gz -> ${P}.tar.gz" + KEYWORDS="~amd64 ~arm ~arm64 ~ppc64 ~riscv ~x86 ~x64-macos" +fi + +LICENSE="Apache-2.0 vim" +SLOT="0" +IUSE="+lto +nvimpager test" + +# Upstream say the test library needs LuaJIT +# https://github.com/neovim/neovim/blob/91109ffda23d0ce61cec245b1f4ffb99e7591b62/CMakeLists.txt#L377 +REQUIRED_USE="${LUA_REQUIRED_USE} test? ( lua_single_target_luajit )" +# TODO: Get tests running +RESTRICT="!test? ( test ) test" + +# Upstream build scripts invoke the Lua interpreter +BDEPEND="${LUA_DEPS} + >=dev-util/gperf-3.1 + >=sys-devel/gettext-0.20.1 + virtual/libiconv + virtual/libintl + virtual/pkgconfig +" +# Check https://github.com/neovim/neovim/blob/master/third-party/CMakeLists.txt for +# new dependency bounds and so on on bumps (obviously adjust for right branch/tag). +DEPEND="${LUA_DEPS} + >=dev-lua/luv-1.45.0[${LUA_SINGLE_USEDEP}] + $(lua_gen_cond_dep ' + dev-lua/lpeg[${LUA_USEDEP}] + dev-lua/mpack[${LUA_USEDEP}] + ') + $(lua_gen_cond_dep ' + dev-lua/LuaBitOp[${LUA_USEDEP}] + ' lua5-{1,2}) + >=dev-libs/libuv-1.46.0:= + >=dev-libs/libvterm-0.3.3 + >=dev-libs/msgpack-3.0.0:= + >=dev-libs/tree-sitter-0.20.8:= + >=dev-libs/libtermkey-0.22 + >=dev-libs/unibilium-2.0.0:0= +" +RDEPEND=" + ${DEPEND} + app-eselect/eselect-vi +" +BDEPEND+=" + test? ( + $(lua_gen_cond_dep 'dev-lua/busted[${LUA_USEDEP}]') + ) +" + +PATCHES=( + "${FILESDIR}/${PN}-0.9.0-cmake_lua_version.patch" + "${FILESDIR}/${PN}-0.9.1-cmake-darwin.patch" + "${FILESDIR}/${PN}-0.9.0-cmake-release-type.patch" +) + +src_prepare() { + # Use our system vim dir + sed -e "/^# define SYS_VIMRC_FILE/s|\$VIM|${EPREFIX}/etc/vim|" \ + -i src/nvim/globals.h || die + + # https://forums.gentoo.org/viewtopic-p-8750050.html + xdg_environment_reset + cmake_src_prepare +} + +src_configure() { + # Upstream default to LTO on non-debug builds + # Let's expose it as a USE flag because upstream + # have preferences for how we should use LTO + # if we want it on (not just -flto) + # ... but allow turning it off. + # TODO: Investigate USE_BUNDLED, doesn't seem to be needed right now + local mycmakeargs=( + -DENABLE_LTO=$(usex lto) + -DPREFER_LUA=$(usex lua_single_target_luajit no "$(lua_get_version)") + -DLUA_PRG="${ELUA}" + ) + cmake_src_configure +} + +src_install() { + cmake_src_install + + # install a default configuration file + insinto /etc/vim + doins "${FILESDIR}"/sysinit.vim + + # conditionally install a symlink for nvimpager + if use nvimpager; then + dosym ../share/nvim/runtime/macros/less.sh /usr/bin/nvimpager + fi +} + +pkg_postinst() { + xdg_pkg_postinst + + optfeature "clipboard support" x11-misc/xsel x11-misc/xclip gui-apps/wl-clipboard + optfeature "Python plugin support" dev-python/pynvim + optfeature "Ruby plugin support" dev-ruby/neovim-ruby-client + optfeature "remote/nvr support" dev-python/neovim-remote +} diff --git a/tests/test_documents.py b/tests/test_documents.py deleted file mode 100644 index 6582834..0000000 --- a/tests/test_documents.py +++ /dev/null @@ -1,16 +0,0 @@ -r"""Test documents""" -from termux_language_server.documents import get_document - - -class Test: - r"""Test.""" - - @staticmethod - def test_get_document() -> None: - r"""Test get document. - - :rtype: None - """ - assert len( - get_document()[0].get("TERMUX_PKG_NAME", "")[0].splitlines() - ) diff --git a/tests/test_schema.py b/tests/test_schema.py new file mode 100644 index 0000000..4298d9e --- /dev/null +++ b/tests/test_schema.py @@ -0,0 +1,29 @@ +r"""Test schema.""" + +import os + +from lsp_tree_sitter.finders import SchemaFinder +from termux_language_server.schema import BashTrie +from termux_language_server.utils import get_filetype, get_schema, parser + +PATH = os.path.dirname(__file__) + + +class Test: + r"""Test.""" + + @staticmethod + def test_SchemaFinder() -> None: + r"""Test schemafinder. + + :rtype: None + """ + path = os.path.join(PATH, "build.sh") + filetype = get_filetype(path) + assert filetype == "build.sh" + with open(path, "rb") as f: + text = f.read() + tree = parser.parse(text) + finder = SchemaFinder(get_schema(filetype), BashTrie) + diagnostics = finder.get_diagnostics(path, tree) + assert len(diagnostics) > 0 diff --git a/tests/test_utils.py b/tests/test_utils.py new file mode 100644 index 0000000..fd88b8c --- /dev/null +++ b/tests/test_utils.py @@ -0,0 +1,21 @@ +r"""Test utils.""" + +from termux_language_server.utils import get_schema + + +class Test: + r"""Test.""" + + @staticmethod + def test_get_schema() -> None: + r"""Test get schema. + + :rtype: None + """ + assert len( + get_schema("build.sh") + .get("properties", {}) + .get("TERMUX_PKG_VERSION", {}) + .get("description", "") + .splitlines() + )