Regenerate nvim config
This commit is contained in:
89
config/neovim/store/lazy-plugins/noice.nvim/.github/ISSUE_TEMPLATE/bug_report.yml
vendored
Normal file
89
config/neovim/store/lazy-plugins/noice.nvim/.github/ISSUE_TEMPLATE/bug_report.yml
vendored
Normal file
@ -0,0 +1,89 @@
|
||||
name: Bug Report
|
||||
description: File a bug/issue
|
||||
title: "bug: "
|
||||
labels: [bug]
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
**Before** reporting an issue, make sure to read the [documentation](https://github.com/folke/noice.nvim) and search [existing issues](https://github.com/folke/noice.nvim/issues). Usage questions such as ***"How do I...?"*** belong in [Discussions](https://github.com/folke/noice.nvim/discussions) and will be closed.
|
||||
- type: checkboxes
|
||||
attributes:
|
||||
label: Did you check docs and existing issues?
|
||||
description: Make sure you checked all of the below before submitting an issue
|
||||
options:
|
||||
- label: I have read all the noice.nvim docs
|
||||
required: true
|
||||
- label: I have searched the existing issues of noice.nvim
|
||||
required: true
|
||||
- label: I have searched the existing issues of plugins related to this issue
|
||||
required: true
|
||||
- type: input
|
||||
attributes:
|
||||
label: "Neovim version (nvim -v)"
|
||||
placeholder: "0.8.0 commit db1b0ee3b30f"
|
||||
validations:
|
||||
required: true
|
||||
- type: input
|
||||
attributes:
|
||||
label: "Operating system/version"
|
||||
placeholder: "MacOS 11.5"
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Describe the bug
|
||||
description: A clear and concise description of what the bug is. Please include any related errors you see in Neovim.
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Steps To Reproduce
|
||||
description: Steps to reproduce the behavior.
|
||||
placeholder: |
|
||||
1.
|
||||
2.
|
||||
3.
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Expected Behavior
|
||||
description: A concise description of what you expected to happen.
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Repro
|
||||
description: Minimal `init.lua` to reproduce this issue. Save as `repro.lua` and run with `nvim -u repro.lua`
|
||||
value: |
|
||||
-- DO NOT change the paths and don't remove the colorscheme
|
||||
local root = vim.fn.fnamemodify("./.repro", ":p")
|
||||
|
||||
-- set stdpaths to use .repro
|
||||
for _, name in ipairs({ "config", "data", "state", "cache" }) do
|
||||
vim.env[("XDG_%s_HOME"):format(name:upper())] = root .. "/" .. name
|
||||
end
|
||||
|
||||
-- bootstrap lazy
|
||||
local lazypath = root .. "/plugins/lazy.nvim"
|
||||
if not vim.loop.fs_stat(lazypath) then
|
||||
vim.fn.system({ "git", "clone", "--filter=blob:none", "https://github.com/folke/lazy.nvim.git", lazypath, })
|
||||
end
|
||||
vim.opt.runtimepath:prepend(lazypath)
|
||||
|
||||
-- install plugins
|
||||
local plugins = {
|
||||
"folke/tokyonight.nvim",
|
||||
"folke/noice.nvim",
|
||||
-- add any other plugins here
|
||||
}
|
||||
require("lazy").setup(plugins, {
|
||||
root = root .. "/plugins",
|
||||
})
|
||||
|
||||
vim.cmd.colorscheme("tokyonight")
|
||||
-- add anything else here
|
||||
render: Lua
|
||||
validations:
|
||||
required: false
|
||||
36
config/neovim/store/lazy-plugins/noice.nvim/.github/ISSUE_TEMPLATE/feature_request.yml
vendored
Normal file
36
config/neovim/store/lazy-plugins/noice.nvim/.github/ISSUE_TEMPLATE/feature_request.yml
vendored
Normal file
@ -0,0 +1,36 @@
|
||||
name: Feature Request
|
||||
description: Suggest a new feature
|
||||
title: "feature: "
|
||||
labels: [enhancement]
|
||||
body:
|
||||
- type: checkboxes
|
||||
attributes:
|
||||
label: Did you check the docs?
|
||||
description: Make sure you read all the docs before submitting a feature request
|
||||
options:
|
||||
- label: I have read all the noice.nvim docs
|
||||
required: true
|
||||
- type: textarea
|
||||
validations:
|
||||
required: true
|
||||
attributes:
|
||||
label: Is your feature request related to a problem? Please describe.
|
||||
description: A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
|
||||
- type: textarea
|
||||
validations:
|
||||
required: true
|
||||
attributes:
|
||||
label: Describe the solution you'd like
|
||||
description: A clear and concise description of what you want to happen.
|
||||
- type: textarea
|
||||
validations:
|
||||
required: true
|
||||
attributes:
|
||||
label: Describe alternatives you've considered
|
||||
description: A clear and concise description of any alternative solutions or features you've considered.
|
||||
- type: textarea
|
||||
validations:
|
||||
required: false
|
||||
attributes:
|
||||
label: Additional context
|
||||
description: Add any other context or screenshots about the feature request here.
|
||||
72
config/neovim/store/lazy-plugins/noice.nvim/.github/workflows/ci.yml
vendored
Normal file
72
config/neovim/store/lazy-plugins/noice.nvim/.github/workflows/ci.yml
vendored
Normal file
@ -0,0 +1,72 @@
|
||||
name: CI
|
||||
on:
|
||||
push:
|
||||
pull_request:
|
||||
|
||||
jobs:
|
||||
tests:
|
||||
strategy:
|
||||
matrix:
|
||||
# os: [ubuntu-latest, windows-latest]
|
||||
os: [ubuntu-latest]
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Install Neovim
|
||||
shell: bash
|
||||
run: |
|
||||
mkdir -p /tmp/nvim
|
||||
wget -q https://github.com/neovim/neovim/releases/download/nightly/nvim.appimage -O /tmp/nvim/nvim.appimage
|
||||
cd /tmp/nvim
|
||||
chmod a+x ./nvim.appimage
|
||||
./nvim.appimage --appimage-extract
|
||||
echo "/tmp/nvim/squashfs-root/usr/bin/" >> $GITHUB_PATH
|
||||
- name: Run Tests
|
||||
run: |
|
||||
nvim --version
|
||||
[ ! -d tests ] && exit 0
|
||||
nvim --headless -u tests/init.lua -c "PlenaryBustedDirectory tests/ {minimal_init = 'tests/init.lua', sequential = true}"
|
||||
docs:
|
||||
runs-on: ubuntu-latest
|
||||
needs: tests
|
||||
if: ${{ github.ref == 'refs/heads/main' }}
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: panvimdoc
|
||||
uses: kdheepak/panvimdoc@main
|
||||
with:
|
||||
vimdoc: noice.nvim
|
||||
version: "Neovim >= 0.8.0"
|
||||
demojify: true
|
||||
treesitter: true
|
||||
- name: Push changes
|
||||
uses: stefanzweifel/git-auto-commit-action@v4
|
||||
with:
|
||||
commit_message: "chore(build): auto-generate vimdoc"
|
||||
commit_user_name: "github-actions[bot]"
|
||||
commit_user_email: "github-actions[bot]@users.noreply.github.com"
|
||||
commit_author: "github-actions[bot] <github-actions[bot]@users.noreply.github.com>"
|
||||
release:
|
||||
name: release
|
||||
if: ${{ github.ref == 'refs/heads/main' }}
|
||||
needs:
|
||||
- docs
|
||||
- tests
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: google-github-actions/release-please-action@v3
|
||||
id: release
|
||||
with:
|
||||
release-type: simple
|
||||
package-name: noice.nvim
|
||||
- uses: actions/checkout@v3
|
||||
- name: tag stable versions
|
||||
if: ${{ steps.release.outputs.release_created }}
|
||||
run: |
|
||||
git config user.name github-actions[bot]
|
||||
git config user.email github-actions[bot]@users.noreply.github.com
|
||||
git remote add gh-token "https://${{ secrets.GITHUB_TOKEN }}@github.com/google-github-actions/release-please-action.git"
|
||||
git tag -d stable || true
|
||||
git push origin :stable || true
|
||||
git tag -a stable -m "Last Stable Release"
|
||||
git push origin stable
|
||||
8
config/neovim/store/lazy-plugins/noice.nvim/.gitignore
vendored
Normal file
8
config/neovim/store/lazy-plugins/noice.nvim/.gitignore
vendored
Normal file
@ -0,0 +1,8 @@
|
||||
tt.*
|
||||
.tests
|
||||
doc/tags
|
||||
debug
|
||||
.repro
|
||||
foo.*
|
||||
*.log
|
||||
data
|
||||
@ -0,0 +1,12 @@
|
||||
MD013:
|
||||
line_length: 120
|
||||
tables: false
|
||||
MD033:
|
||||
allowed_elements:
|
||||
- "details"
|
||||
- "summary"
|
||||
- "b"
|
||||
- "table"
|
||||
- "tr"
|
||||
- "td"
|
||||
- "a"
|
||||
19
config/neovim/store/lazy-plugins/noice.nvim/.neoconf.json
Normal file
19
config/neovim/store/lazy-plugins/noice.nvim/.neoconf.json
Normal file
@ -0,0 +1,19 @@
|
||||
{
|
||||
"neodev": {
|
||||
"library": {
|
||||
"plugins": [
|
||||
"nui.nvim",
|
||||
"nvim-cmp",
|
||||
"nvim-notify",
|
||||
"telescope.nvim",
|
||||
"plenary.nvim"
|
||||
]
|
||||
}
|
||||
},
|
||||
"lspconfig": {
|
||||
"sumneko_lua": {
|
||||
"Lua.runtime.version": "LuaJIT",
|
||||
"Lua.workspace.checkThirdParty": false
|
||||
}
|
||||
}
|
||||
}
|
||||
873
config/neovim/store/lazy-plugins/noice.nvim/CHANGELOG.md
Normal file
873
config/neovim/store/lazy-plugins/noice.nvim/CHANGELOG.md
Normal file
@ -0,0 +1,873 @@
|
||||
# Changelog
|
||||
|
||||
## [3.0.2](https://github.com/folke/noice.nvim/compare/v3.0.1...v3.0.2) (2024-05-22)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **markdown:** keys when buf is invalid ([0dc97cb](https://github.com/folke/noice.nvim/commit/0dc97cb21edac79a1d575541c57a31a3e3bd5b88))
|
||||
|
||||
## [3.0.1](https://github.com/folke/noice.nvim/compare/v3.0.0...v3.0.1) (2024-05-18)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* typo with hist messages. Fixes [#815](https://github.com/folke/noice.nvim/issues/815) ([a0a40d3](https://github.com/folke/noice.nvim/commit/a0a40d3e5fdb2eab005e2ee08c4af09c99fcb9a4))
|
||||
|
||||
## [3.0.0](https://github.com/folke/noice.nvim/compare/v2.1.1...v3.0.0) (2024-05-18)
|
||||
|
||||
|
||||
### ⚠ BREAKING CHANGES
|
||||
|
||||
* bump required Neovim version to >= 0.9
|
||||
|
||||
### Features
|
||||
|
||||
* bump required Neovim version to >= 0.9 ([6c5290a](https://github.com/folke/noice.nvim/commit/6c5290ad947a97c34889debe59bafe771a9f9578))
|
||||
* **util:** better debug log ([217c684](https://github.com/folke/noice.nvim/commit/217c6848a6656c5e187d66a2b3caed9a9676d448))
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **cmdline:** use other work-around for cmdpreview ([6a3721b](https://github.com/folke/noice.nvim/commit/6a3721b03dbeb10c3b1c47f63fdc2d77bb550550))
|
||||
* **msg:** add historical messages as a msg_show instead of history so it doesnt popup ([b9b4818](https://github.com/folke/noice.nvim/commit/b9b481864d0d91c7df539ecebb30a2235a3678da))
|
||||
* **ui:** dont try updating the ui during textlock ([4ef75a3](https://github.com/folke/noice.nvim/commit/4ef75a3c3893f9efcaf078e60280a9247b9876ff))
|
||||
|
||||
## [2.1.1](https://github.com/folke/noice.nvim/compare/v2.1.0...v2.1.1) (2024-05-16)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* fixed check on get_clients. Fixes [#806](https://github.com/folke/noice.nvim/issues/806) ([588471b](https://github.com/folke/noice.nvim/commit/588471bdf26d8fde3fa1672339339a18e1b8568a))
|
||||
|
||||
## [2.1.0](https://github.com/folke/noice.nvim/compare/v2.0.3...v2.1.0) (2024-05-16)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **config:** added `Noice all` to show ALL messages captured by Noice. See [#769](https://github.com/folke/noice.nvim/issues/769) ([72f72d3](https://github.com/folke/noice.nvim/commit/72f72d3271109ea37128681766de068b62947647))
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **cmdline:** yet another work-around that no longer temporarily changes the cmdline ([68b9c53](https://github.com/folke/noice.nvim/commit/68b9c5395a5e0f4462b4f38791018a48e6929cd9))
|
||||
* depraction warnings on Neovim 0.11 ([9946087](https://github.com/folke/noice.nvim/commit/9946087bb51a5bfb99efcd1527ef7fe46574cf2f))
|
||||
* **format:** config.format doesn't work ([#772](https://github.com/folke/noice.nvim/issues/772)) ([09708be](https://github.com/folke/noice.nvim/commit/09708be5668762062d619fddf6cb2b68d165a9c2))
|
||||
* **messages:** include any messages before Noice was started as one history_show message. Fixes [#799](https://github.com/folke/noice.nvim/issues/799) ([61947de](https://github.com/folke/noice.nvim/commit/61947de3d5904375ea94e0c13db2537488ad9829))
|
||||
* **messages:** only add previous messages once when Noice starts. Fixes [#804](https://github.com/folke/noice.nvim/issues/804) ([269de18](https://github.com/folke/noice.nvim/commit/269de18e0c4682c8964f278b4fbb9f6ef9a52cd3))
|
||||
* **msg:** update router when blocking ([ee433a7](https://github.com/folke/noice.nvim/commit/ee433a724c31858537a7d8c80d09c7686810da4a))
|
||||
* **router:** add additional updates on `SafeState` when available ([fff989f](https://github.com/folke/noice.nvim/commit/fff989f7e5fd3c1e307ac8b92de26be837b18c81))
|
||||
* **router:** don't use `SafeState` since apparently this is a nightly thing and seems to work without. Fixes [#805](https://github.com/folke/noice.nvim/issues/805) ([ef085e9](https://github.com/folke/noice.nvim/commit/ef085e9cf9ab15a679a403dcfbafba08b9c6cbec))
|
||||
* **router:** remove SafeState again, since it breaks incsearch ([3c3a8f3](https://github.com/folke/noice.nvim/commit/3c3a8f30061bfbb73308e221d760a3c7c6526473))
|
||||
|
||||
|
||||
### Performance Improvements
|
||||
|
||||
* **cmdline:** prevent unneeded redraws during cmdline preview (substitute). Fixes [#803](https://github.com/folke/noice.nvim/issues/803) ([8d924eb](https://github.com/folke/noice.nvim/commit/8d924ebc8e5c28ee30793c30b57d9670884bf05b))
|
||||
* **ui_attach:** router now only queues messages in `vim.ui_attach`. Use `SafeState` to execute queue when needed. ([4c26991](https://github.com/folke/noice.nvim/commit/4c2699111730a14144224d7b193bede6b707b1bc))
|
||||
|
||||
## [2.0.3](https://github.com/folke/noice.nvim/compare/v2.0.2...v2.0.3) (2024-05-15)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **hacks:** use feedkeys instead of input to force redraw ([dbf8d70](https://github.com/folke/noice.nvim/commit/dbf8d708a46c9d5a6c79f8fc77ac4ffa04d3f0d9))
|
||||
* **nui:** safely destroy any create window/buffers during E565 errors. Fixes command preview ([a0c6203](https://github.com/folke/noice.nvim/commit/a0c6203d551242322ac7995b26d4e320140e05b1))
|
||||
|
||||
## [2.0.2](https://github.com/folke/noice.nvim/compare/v2.0.1...v2.0.2) (2024-05-09)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **cmdpreview:** read the variable `cmdpreview` in nvim-0.9+ on windows ([#774](https://github.com/folke/noice.nvim/issues/774)) ([a35003d](https://github.com/folke/noice.nvim/commit/a35003dbdd9c8d6d05aa47064de2b76ace872ec4))
|
||||
* disable incsearch hack for nightly (no longer needed) ([02d698a](https://github.com/folke/noice.nvim/commit/02d698ac0d294e2195429662d0d1cae6cd9a5621))
|
||||
* **progress:** Change LspProgress data field `result` to `params` ([#785](https://github.com/folke/noice.nvim/issues/785)) ([89de3b5](https://github.com/folke/noice.nvim/commit/89de3b56abee53783dca3500115891fb827669d6))
|
||||
* retry rendering only once to prevent rendering loops ([f4decbc](https://github.com/folke/noice.nvim/commit/f4decbc7a80229ccc9f86026b74bdcf0c39e38a7))
|
||||
* **router:** make sure we retry views that could not render due to E565. Fixes [#783](https://github.com/folke/noice.nvim/issues/783) ([6df3d8a](https://github.com/folke/noice.nvim/commit/6df3d8acea83b531deca29e18c64783a3eac106d))
|
||||
* use `vim.api.nvim__redraw` to update cursor on nightly instead of ffi. Fixes [#781](https://github.com/folke/noice.nvim/issues/781) ([37c8124](https://github.com/folke/noice.nvim/commit/37c8124ee8aac0614a7221c335a97db9ed5e40f3))
|
||||
|
||||
## [2.0.1](https://github.com/folke/noice.nvim/compare/v2.0.0...v2.0.1) (2024-03-26)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **input:** don't filter ^M and <cr> for the command line ([#734](https://github.com/folke/noice.nvim/issues/734)) ([d29b26c](https://github.com/folke/noice.nvim/commit/d29b26c329558ee4bb2e7f3cc25078929ef89b2f))
|
||||
* lsp message view not effective ([#747](https://github.com/folke/noice.nvim/issues/747)) ([2640d39](https://github.com/folke/noice.nvim/commit/2640d3975d47156c412db6e974a1b1280ff46aab))
|
||||
* **popup:** don't make the window column go below negative 1 ([#737](https://github.com/folke/noice.nvim/issues/737)) ([01b2b53](https://github.com/folke/noice.nvim/commit/01b2b5316eb6986cc763e7b4f0f0e0f60d2a344b))
|
||||
|
||||
|
||||
### Performance Improvements
|
||||
|
||||
* ignore events when setting buf options during render. Fixes [#694](https://github.com/folke/noice.nvim/issues/694) ([bf67d70](https://github.com/folke/noice.nvim/commit/bf67d70bd7265d075191e7812d8eb42b9791f737))
|
||||
* **lsp:** update lsp progress messages at most every 100ms ([9a9756d](https://github.com/folke/noice.nvim/commit/9a9756d6999abc016c087b9d3fcea3c9de99be98))
|
||||
|
||||
## [2.0.0](https://github.com/folke/noice.nvim/compare/v1.16.3...v2.0.0) (2023-10-25)
|
||||
|
||||
|
||||
### ⚠ BREAKING CHANGES
|
||||
|
||||
* command redirection! Redirect messages generated by a command or function to a different view
|
||||
* lsp hover/signatureHelp and message are now enabled by default. Disable in the config if you don't want this.
|
||||
|
||||
### Features
|
||||
|
||||
* :Noice now has subcommands, full commands and a lua api require("noice").cmd("last") ([88767a6](https://github.com/folke/noice.nvim/commit/88767a64c6b6665b8eca09271d6e0a7b9f53ccaa))
|
||||
* add `circleFull` spinner ([#495](https://github.com/folke/noice.nvim/issues/495)) ([5427398](https://github.com/folke/noice.nvim/commit/54273980749ceb4396501300bf4c86f3bb818f75))
|
||||
* add scrollbar to all nui views ([0630e94](https://github.com/folke/noice.nvim/commit/0630e94375c53ecdb64b4d53e1013a0897625d25))
|
||||
* added `Filter.cond` to conditionally use a route ([29a2e05](https://github.com/folke/noice.nvim/commit/29a2e052d2653443716a8eece89300e9b36b5f2a))
|
||||
* added `Noice dismiss` to hide all visible messages. Fixes [#417](https://github.com/folke/noice.nvim/issues/417) ([a32bc89](https://github.com/folke/noice.nvim/commit/a32bc892aadb26668fd0161962ae4eccb1bf5854))
|
||||
* added cmdline formatter help ([7f0ecd8](https://github.com/folke/noice.nvim/commit/7f0ecd88ee3e3ac3d11a8646f1e9a209b4579715))
|
||||
* added config options for input() cmdline. Fixes [#115](https://github.com/folke/noice.nvim/issues/115) ([b645e30](https://github.com/folke/noice.nvim/commit/b645e30dc228e75b64b28374aa72b6c8ebbbe977))
|
||||
* added config.lsp.hover. Undocumented for now and disabled by default. ([c2f37ed](https://github.com/folke/noice.nvim/commit/c2f37ed040238573e7a2542e14a814b2c19164bd))
|
||||
* added configurable commands ([e9ccf78](https://github.com/folke/noice.nvim/commit/e9ccf782c0b4e9f7df47cc30972185e048e0ea67))
|
||||
* added custom handlers for markdown links and help tags ([37e7203](https://github.com/folke/noice.nvim/commit/37e72034cf336bb4748e15585ab805b3ec2752f4))
|
||||
* added deactivate ([bf216e0](https://github.com/folke/noice.nvim/commit/bf216e017979f8be712b1ada62736a58e75b0fe3))
|
||||
* added different closing and focusing ways to lsp hover ([0402182](https://github.com/folke/noice.nvim/commit/04021821b74a8588e20764beb222b71a5fce037c))
|
||||
* added health check for GUI's with multigrid enabled ([0fdedab](https://github.com/folke/noice.nvim/commit/0fdedab33ac84b133b9c93c0e4d12a51f18d6981))
|
||||
* added health checks to see if other plugins have overwritten Noice handlers ([906c6c8](https://github.com/folke/noice.nvim/commit/906c6c827dd36176baf9521a0653ca9f29410683))
|
||||
* added markdown to treesitter health checks ([7c955cc](https://github.com/folke/noice.nvim/commit/7c955cced94bd4eb78d689eddd6528012dcc4bdb))
|
||||
* added methods that can be mapped for scrolling the hover/signatureHelp windows ([a6ad24e](https://github.com/folke/noice.nvim/commit/a6ad24ed8b9d0b6b0dcde311865547a48cea21da))
|
||||
* added notify.timeout. Set it on a view to change the deafault timeout ([feaf5c4](https://github.com/folke/noice.nvim/commit/feaf5c43c22a14f5405e7dabd0112974589a6998))
|
||||
* added option to disable smart_move ([8600a03](https://github.com/folke/noice.nvim/commit/8600a03bf88a2bd817d71829344a8100deaed8b1))
|
||||
* added option to disable the health checker ([a2f6e4c](https://github.com/folke/noice.nvim/commit/a2f6e4cd831c1c72e92d0f6dc778f68635e82855))
|
||||
* added optional col to start highlighting with treesitter/syntax ([ccb7e56](https://github.com/folke/noice.nvim/commit/ccb7e561248aab93f67b2b6ab31d75e621b4211c))
|
||||
* added overrides for default lsp and cmp formatters :) Enable with config.lsp.override ([6d9fb12](https://github.com/folke/noice.nvim/commit/6d9fb1242cd782edfb77ac06b12d72ed24e3888f))
|
||||
* added preset to set hover docs and signature help border ([e34db67](https://github.com/folke/noice.nvim/commit/e34db671490ebfdc4268fb83602e1a7e06b91e69))
|
||||
* added routing of LSP window/showMessage ([75730f4](https://github.com/folke/noice.nvim/commit/75730f4b660af682d376c218a16822c782451241))
|
||||
* added suport for Luasnip jump targets to signature help ([c09d197](https://github.com/folke/noice.nvim/commit/c09d1973e7542ca0201464e053c857e15a2b9f22))
|
||||
* added support for <pre>{lang} code blocks used in the Neovim codebase ([de48a45](https://github.com/folke/noice.nvim/commit/de48a4528aad5c7b50cf4b4ec1b419762a95934d))
|
||||
* added support for filtering messages generated by a command on the commandline ([b3ee385](https://github.com/folke/noice.nvim/commit/b3ee38584609d6bf63aceca04fe5463d5ed080ed))
|
||||
* added support for negative positions. Fixes [#179](https://github.com/folke/noice.nvim/issues/179) ([8d7a63c](https://github.com/folke/noice.nvim/commit/8d7a63c8f003d92c1484045ebe667a62d7625594))
|
||||
* added title option to cmdline format ([42d771a](https://github.com/folke/noice.nvim/commit/42d771a32ddeb20866907d88d2e95a4730c34807))
|
||||
* always use the global notify instance and set animate=false when blocking ([edc8df6](https://github.com/folke/noice.nvim/commit/edc8df60a16bb0f2709110b29fef98c6cc616d42))
|
||||
* automatically move out of the way of existing floating windows. Fixes [#117](https://github.com/folke/noice.nvim/issues/117) ([a810700](https://github.com/folke/noice.nvim/commit/a810700bb8189fe7fb699f388fda6fdb9869fac8))
|
||||
* better defaults for history and last ([cdb25b8](https://github.com/folke/noice.nvim/commit/cdb25b8a398dae6d72fea3e5721a7c367b2a19f1))
|
||||
* **cmdline:** added cmdline support for `:lua=` and `:=` ([acfa513](https://github.com/folke/noice.nvim/commit/acfa5133da31a35ec24fca0757ad1c85edc4c585))
|
||||
* **cmdline:** added support for FloatTitle and added proper default ([79c7059](https://github.com/folke/noice.nvim/commit/79c70594aefb4efecbce4528174fdd0227baaf3e))
|
||||
* **cmp:** incude item.detail when it's not part of item.documentation ([c2a745a](https://github.com/folke/noice.nvim/commit/c2a745a26ae562f1faecbf6177ac53377d2658d5))
|
||||
* command redirection! Redirect messages generated by a command or function to a different view ([a8b3117](https://github.com/folke/noice.nvim/commit/a8b3117f22e49dcb44853ca9df84feaa663077bb))
|
||||
* conceal markdown escape characters. Fixes [#170](https://github.com/folke/noice.nvim/issues/170) ([6824794](https://github.com/folke/noice.nvim/commit/6824794d01fb27e428f642440517fe066bf47105))
|
||||
* **config:** add calculator to cmdline formats ([#240](https://github.com/folke/noice.nvim/issues/240)) ([fa21685](https://github.com/folke/noice.nvim/commit/fa21685e23cbb72bb573eecf48dd3644bc1513ba))
|
||||
* don't hide mini messages when blocking [#112](https://github.com/folke/noice.nvim/issues/112) ([6b9144d](https://github.com/folke/noice.nvim/commit/6b9144d3f9873e1651d783c6b862177d5647bd20))
|
||||
* don't process events that are disabled in config & disable ext that are enabled in the attached GUI ([abb5721](https://github.com/folke/noice.nvim/commit/abb5721129b3f54bb6f38713f45029c61c0e5f64))
|
||||
* dont show lsp doc when empty ([a61a07f](https://github.com/folke/noice.nvim/commit/a61a07f51398defd6a922e457eabf272ff15ccf3))
|
||||
* **format:** allow `config.format.level.icons` to be false. Fixes [#274](https://github.com/folke/noice.nvim/issues/274) ([aa68eb6](https://github.com/folke/noice.nvim/commit/aa68eb6f83c48df41bab8ae36623e5af3f224c66))
|
||||
* **health:** added check for vim-sleuth ([2d11c5b](https://github.com/folke/noice.nvim/commit/2d11c5bfe77c7b93ab5ad7e156e239b8279cc5ee))
|
||||
* **health:** added markdown_inline to treesitter checks ([d525285](https://github.com/folke/noice.nvim/commit/d5252857db3b295d1b34150531f58f3cc6251192))
|
||||
* **health:** show what other plugin is overriding a Noice handler ([84dcdf3](https://github.com/folke/noice.nvim/commit/84dcdf3bf453ae1bc4d05a2110e3202e1eb4eafa))
|
||||
* improved smart move. Added filetype exclusions and only move out when overlap > 30%. Fixes [#130](https://github.com/folke/noice.nvim/issues/130) ([c63267d](https://github.com/folke/noice.nvim/commit/c63267d3649d3b9c5992a4db96a954c8f581cd73))
|
||||
* keep track of where messages are displayed ([13097dc](https://github.com/folke/noice.nvim/commit/13097dccc8228f07b2aa9191081cc8fa3944af98))
|
||||
* lsp hover/signatureHelp and message are now enabled by default. Disable in the config if you don't want this. ([9130fd1](https://github.com/folke/noice.nvim/commit/9130fd17a19f95b55ca9362919fef31ab54ef841))
|
||||
* lsp signature help ([2a19f32](https://github.com/folke/noice.nvim/commit/2a19f32b3d22b0b31812fab76e576e04f06cd2e9))
|
||||
* **lsp:** added config.lsp.hover.silent. Fixes [#412](https://github.com/folke/noice.nvim/issues/412) ([e2a53cf](https://github.com/folke/noice.nvim/commit/e2a53cf946d88d87cd0123711afce5ddad047b7b))
|
||||
* **lsp:** added custom formatters for lsp hover and made :help work in hover text ([63c70a9](https://github.com/folke/noice.nvim/commit/63c70a90b033dbd17016bf7e254f7427596dbc3b))
|
||||
* **lsp:** fallback to buffer filetype for code blocks without lang. Fixes [#378](https://github.com/folke/noice.nvim/issues/378) ([cab2c80](https://github.com/folke/noice.nvim/commit/cab2c80497388735c9795f496a36e76bc5c7c4bf))
|
||||
* manage message state without `msg_clear` ([#209](https://github.com/folke/noice.nvim/issues/209)) ([fb0e3b0](https://github.com/folke/noice.nvim/commit/fb0e3b0bb3028050b61a45e53809af03b15a24bc))
|
||||
* markdown formatter ([6ea06c9](https://github.com/folke/noice.nvim/commit/6ea06c926fc3bc495e07ab5a1b51bcb19628d771))
|
||||
* new markdown renderer without empty lines around code blocks. Fixes [#158](https://github.com/folke/noice.nvim/issues/158) ([111fe5e](https://github.com/folke/noice.nvim/commit/111fe5eaa9d1c5f77ccd427c0139676917c9c162))
|
||||
* noice presets ([c43d82b](https://github.com/folke/noice.nvim/commit/c43d82b3344e73e85c1af8c994a3dd7a3b4849b5))
|
||||
* **notify:** added plain renderer ([345fccc](https://github.com/folke/noice.nvim/commit/345fccc9e17bc4fd74361fb0a953d0e87195a657))
|
||||
* open :messages and history in a split with enter=true ([7beef93](https://github.com/folke/noice.nvim/commit/7beef93fabceefb028a42998150ccd3b5c9b4ea5))
|
||||
* **popupmenu:** allow different views for regular/cmdline popupmenu ([af706c4](https://github.com/folke/noice.nvim/commit/af706c4b443cf1c416ef7288ec3434f3f1ab6cf1))
|
||||
* preset for inc_rename ([91c79a0](https://github.com/folke/noice.nvim/commit/91c79a0c51ebb070163668c1156d5cc20c02af3a))
|
||||
* properly calculate buf height taking wrap into account ([add20ee](https://github.com/folke/noice.nvim/commit/add20ee9ffabc80b34e1b80a53ef68df9969d02e))
|
||||
* properly calculate layout in case of max_width and wrap ([83c837e](https://github.com/folke/noice.nvim/commit/83c837e1cf39820f275d347e5d65c11e8398e102))
|
||||
* removed default `<esc>` handler from `split` view ([fb10fa2](https://github.com/folke/noice.nvim/commit/fb10fa2ef7d78953ffb8b9c5fd0f42c389cbedaf))
|
||||
* replace html entities. Fixes [#168](https://github.com/folke/noice.nvim/issues/168) ([7e3e958](https://github.com/folke/noice.nvim/commit/7e3e9584601a216069f92ab3a33dd2a1af30283f))
|
||||
* set default view for hover to hover ([dafcddd](https://github.com/folke/noice.nvim/commit/dafcddd583e34444ba4f893d3bece1c12f3a739a))
|
||||
* set default zindex for hover to 45. Lower than cmp and notify ([0bf5f9e](https://github.com/folke/noice.nvim/commit/0bf5f9e447c5ede0fe7b5c42583e206ed7073b48))
|
||||
* show warning when running with TUI rework ([cf2231b](https://github.com/folke/noice.nvim/commit/cf2231bfb691b3b58d2685f48da11596cec1cfa3))
|
||||
* **signature:** added signature param docs. Fixes [#421](https://github.com/folke/noice.nvim/issues/421) ([e76ae13](https://github.com/folke/noice.nvim/commit/e76ae13dd272dc23d0154b93172d445aeabad8f1))
|
||||
* smart positioning of the hover window. Make sure to update Nui as well to use this. ([5bd6e30](https://github.com/folke/noice.nvim/commit/5bd6e308a10324e0c3d8a320aae234d9ce0a9610))
|
||||
* Support hide scrollbar for view ([#603](https://github.com/folke/noice.nvim/issues/603)) ([f700175](https://github.com/folke/noice.nvim/commit/f700175b91948e4f71cf73872cea364247cf2dbd))
|
||||
* **ui:** added hybrid messages functionality, but not needed for now ([addc0a2](https://github.com/folke/noice.nvim/commit/addc0a2521ce666a1f546f9a04574a63a858c6a5))
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* accept preset as a table ([#582](https://github.com/folke/noice.nvim/issues/582)) ([53d613c](https://github.com/folke/noice.nvim/commit/53d613cd0031e83987964947b1bad8b5047c9d0e))
|
||||
* activate vim-sleuth hack. See [#139](https://github.com/folke/noice.nvim/issues/139) ([e99990f](https://github.com/folke/noice.nvim/commit/e99990ffdbf6b65275dd6f51089352d45e7197bc))
|
||||
* added debugging info for [#220](https://github.com/folke/noice.nvim/issues/220) ([6de461b](https://github.com/folke/noice.nvim/commit/6de461b8475c4f56bc5b8ed93c819c8b15f3e067))
|
||||
* Allow mapping <esc> ([#329](https://github.com/folke/noice.nvim/issues/329)) ([b7e9054](https://github.com/folke/noice.nvim/commit/b7e9054b02b5958db8bb5ad7675e92bfb5a8e903))
|
||||
* always show cursorline and reset to line for popupmenu. Fixes [#239](https://github.com/folke/noice.nvim/issues/239) ([c7f666c](https://github.com/folke/noice.nvim/commit/c7f666cff4160a9f9f31e5de112429d6db7956d2))
|
||||
* anchor popupmenu to SW for bottom cmdline. Fixes [#134](https://github.com/folke/noice.nvim/issues/134) ([9102aef](https://github.com/folke/noice.nvim/commit/9102aef70431cd9959add7bc50d507c18f0089de))
|
||||
* better handling of splitkeep for nui splits ([84d1904](https://github.com/folke/noice.nvim/commit/84d1904c64759a82149e003bd83442572d588769))
|
||||
* better way of showing/hiding cursor ([10a97a0](https://github.com/folke/noice.nvim/commit/10a97a0fadfc8929c8aecd9b69dda67b7b2f7a33))
|
||||
* **block:** better deal with carriage return characters (take 2) ([ee24b36](https://github.com/folke/noice.nvim/commit/ee24b36743b18e53bdc6b49bbfa426fc18ea337a))
|
||||
* calculate negative offsets based off minmax. Fixes [#179](https://github.com/folke/noice.nvim/issues/179) ([cf2912d](https://github.com/folke/noice.nvim/commit/cf2912d08eb7442c52347d3427a61557e0783f02))
|
||||
* call update_screen during cmdpreview to fix cursor movement. Fixes [#131](https://github.com/folke/noice.nvim/issues/131) ([23da4ed](https://github.com/folke/noice.nvim/commit/23da4eddea9b78ab0846c5b2a1cda5a10f49b4a4))
|
||||
* check for nil on zindex. Fixes [#129](https://github.com/folke/noice.nvim/issues/129) ([07465b3](https://github.com/folke/noice.nvim/commit/07465b3486508a233701e32c948c589985d9cd48))
|
||||
* check if loader returned a function before loading ([66946c7](https://github.com/folke/noice.nvim/commit/66946c72f0a36f37e480b5eae97aac3cdcd5961d))
|
||||
* check if plugin is noice ([7b62ccf](https://github.com/folke/noice.nvim/commit/7b62ccfc236e51e78e5b2fc7d3068eacd65e4590))
|
||||
* check item.detail is type of table ([#595](https://github.com/folke/noice.nvim/issues/595)) ([3670766](https://github.com/folke/noice.nvim/commit/3670766b10fded979fcb00606801edc585a65f2a))
|
||||
* cleanup progress messages from lsp clients that died. Fixes [#175](https://github.com/folke/noice.nvim/issues/175) ([e084d3b](https://github.com/folke/noice.nvim/commit/e084d3bed43ad1372b6a638218e19c83330af403))
|
||||
* **cmdline:** better and safer way to trigger redraw during cmdpreview ([02ed6d4](https://github.com/folke/noice.nvim/commit/02ed6d4c0c1e4d21fc4e79bbe54961023ee9badb))
|
||||
* **cmdline:** dont use normal commands so ModeChanged will trigger correctly. Fixes [#390](https://github.com/folke/noice.nvim/issues/390) ([fa7b6a1](https://github.com/folke/noice.nvim/commit/fa7b6a18c5cdc23961038bc56b93495efcd0f5c7))
|
||||
* **cmdline:** fixed a byte offset issue with the new virtual inline text ([a13a88f](https://github.com/folke/noice.nvim/commit/a13a88fb2016b6cfea8f56238566b345f537e47a))
|
||||
* **cmdline:** make sure cursor is always visible ([2f0a427](https://github.com/folke/noice.nvim/commit/2f0a42701b4aa65b55fff8f32878d9adc7e7ac77))
|
||||
* cmp popupmenu position ([#183](https://github.com/folke/noice.nvim/issues/183)) ([8db0420](https://github.com/folke/noice.nvim/commit/8db0420c55ea813d721f3c08c6d61ad68fb366e5))
|
||||
* config.cmdline.opts now overrides any option from the cmdline formats ([2851fc2](https://github.com/folke/noice.nvim/commit/2851fc23a15a3651402ce6adfde92d0d35990e32))
|
||||
* **config:** allow overriding options set by presets ([5a1bf17](https://github.com/folke/noice.nvim/commit/5a1bf1707f592fefff4cb3da903b17369e088cc1))
|
||||
* **config:** correctly set the presets ([e5cb84f](https://github.com/folke/noice.nvim/commit/e5cb84f1ed524f850fa92e3a256e830ed07fadee))
|
||||
* **config:** properly deal with preset routes. Fixes [#517](https://github.com/folke/noice.nvim/issues/517) ([fea7f1c](https://github.com/folke/noice.nvim/commit/fea7f1cf15b04ec9b8dd071aa3510f693156ce59))
|
||||
* **confirm:** keep newlines in confirm message. Fixes [#422](https://github.com/folke/noice.nvim/issues/422) ([051111f](https://github.com/folke/noice.nvim/commit/051111f98d7128c833eaa32423426829981b2aa3))
|
||||
* correctly apply padding based on four numbers ([c9c1fbd](https://github.com/folke/noice.nvim/commit/c9c1fbd605388badcfa62c0b7f58d184f19e1484))
|
||||
* correctly calculate popupmenu width based on border and padding. Fixes [#122](https://github.com/folke/noice.nvim/issues/122) ([b152bf5](https://github.com/folke/noice.nvim/commit/b152bf5281a0e974b53ce1011b0938134573760e))
|
||||
* **debug:** calculate stacktrace outisde of vim schedule to make it useful ([a5de1ca](https://github.com/folke/noice.nvim/commit/a5de1ca0eaecd21fd33a0a191d1a0b9dd97cb54a))
|
||||
* **debug:** only concat debug info that is a string ([78ec5c6](https://github.com/folke/noice.nvim/commit/78ec5c6eefb9b61056a8545ded33b99f7a9a9f72))
|
||||
* disable all signature help when signature is disabled. Fixes [#104](https://github.com/folke/noice.nvim/issues/104) ([58f52e3](https://github.com/folke/noice.nvim/commit/58f52e345d8a2fe4d9b56829986a6c5b3661fdf6))
|
||||
* disable vim-sleuth for Noice buffers ([d148e1a](https://github.com/folke/noice.nvim/commit/d148e1ab5844eb0b9efa09f77772feb20cd4b660))
|
||||
* disable winbar on Noice windows ([1b37f74](https://github.com/folke/noice.nvim/commit/1b37f74423bb6b2e8bf4ad3ec7f1545960f142a7))
|
||||
* do render after mount Fixes [#150](https://github.com/folke/noice.nvim/issues/150) ([7e2e449](https://github.com/folke/noice.nvim/commit/7e2e4491afb02422b26c241f9fb7f8960b51fe05))
|
||||
* don't try smart move between noice windows ([4a46ba3](https://github.com/folke/noice.nvim/commit/4a46ba33d8b2309d2cbcfb725e958d2e0bdc77d6))
|
||||
* dont check cmdpreview on windows. Fixes [#229](https://github.com/folke/noice.nvim/issues/229) ([b10bbbb](https://github.com/folke/noice.nvim/commit/b10bbbb91215d0324d7d7f4cd0d8de3d1332648f))
|
||||
* dont check lazyredraw when Noice is running ([a202a22](https://github.com/folke/noice.nvim/commit/a202a2226e91f62706ebff63a5b0d4fdf2d2e370))
|
||||
* dont error if cmp not loaded when overriding ([4bae487](https://github.com/folke/noice.nvim/commit/4bae48798424d300e204cce2eb73b087854472d5))
|
||||
* dont error in checkhealth if nvim-treesitter is not installed ([044767a](https://github.com/folke/noice.nvim/commit/044767a01d38208c32d97b0214cce66c41e8f7c8))
|
||||
* dont hide cursor on input. Fixes [#585](https://github.com/folke/noice.nvim/issues/585). Fixes [#566](https://github.com/folke/noice.nvim/issues/566) ([819a5bf](https://github.com/folke/noice.nvim/commit/819a5bf62fa31c893c9d0c6da17ef93a810a1e8c))
|
||||
* dont make scrollbars focusable ([e226401](https://github.com/folke/noice.nvim/commit/e226401ba577808528e76861edc6a04c36ccbce1))
|
||||
* dont render views when not running. Fixes [#200](https://github.com/folke/noice.nvim/issues/200) ([9dc2508](https://github.com/folke/noice.nvim/commit/9dc250851eff005fe94f37c12c05bfddf2cedca8))
|
||||
* dont restore cursor when exiting. Fixes [#230](https://github.com/folke/noice.nvim/issues/230) ([0115097](https://github.com/folke/noice.nvim/commit/0115097e5008bae01e512f30cea66e2d7182f19b))
|
||||
* dont show if window is closed while showing. Fixes [#208](https://github.com/folke/noice.nvim/issues/208) ([a8402e8](https://github.com/folke/noice.nvim/commit/a8402e84c1923885896ee83eefb0f492a9f9b620))
|
||||
* export scroll in noice.lsp. See [#161](https://github.com/folke/noice.nvim/issues/161) ([0fe5a1e](https://github.com/folke/noice.nvim/commit/0fe5a1ea053ee086327eab386594c5f2e7f15e77))
|
||||
* fallback to syntax if treesitter parser is not available ([882e58c](https://github.com/folke/noice.nvim/commit/882e58c2dccce0adba30a7d483af15fbe40dd70b))
|
||||
* fix lsp showMessage. Fixes [#220](https://github.com/folke/noice.nvim/issues/220) ([5ff75a5](https://github.com/folke/noice.nvim/commit/5ff75a5196d3ebe3148ca0c8c20ac750664ddfb6))
|
||||
* fixed flickering during substitute & cmdpreview ([1702772](https://github.com/folke/noice.nvim/commit/170277257a976e2f669351676974a7bc51e88b5a))
|
||||
* force cmdline redraw only when pum is not visible. Fixes [#188](https://github.com/folke/noice.nvim/issues/188). Closes [#189](https://github.com/folke/noice.nvim/issues/189) ([412594c](https://github.com/folke/noice.nvim/commit/412594c23090b107aeb839b49e23fc508a4e3b8b))
|
||||
* guicursor behaves weird, when resetting too fast. Delay by 100ms. Fixes [#114](https://github.com/folke/noice.nvim/issues/114) ([3710528](https://github.com/folke/noice.nvim/commit/37105289ac5a4fd7b977a9c307c1a95f3e38acf6))
|
||||
* **hacks:** make sure the cursor is properly updated before getchar ([0cca940](https://github.com/folke/noice.nvim/commit/0cca940561d4b723cb52ba9e4ec239fceb36f146))
|
||||
* handle vim.notify nil messages for nvim-notify. Fixes [#109](https://github.com/folke/noice.nvim/issues/109) ([83b60f2](https://github.com/folke/noice.nvim/commit/83b60f2cced7428419fa41cfc30cda53082739ee))
|
||||
* **health:** added info on how to disable overwritten by other plugins ([a4c3d48](https://github.com/folke/noice.nvim/commit/a4c3d484dcf925de7d27110f198c45d06cf062ac))
|
||||
* **health:** allow running in GUIs with multigrid ([71a7591](https://github.com/folke/noice.nvim/commit/71a75913d680af9f1f26a2886518e390cd8f73e1))
|
||||
* **health:** correctly check if lsp.message is enabled ([#381](https://github.com/folke/noice.nvim/issues/381)) ([1ff6b10](https://github.com/folke/noice.nvim/commit/1ff6b10471590331cc1585ad64f084f19cd4bcb7))
|
||||
* **health:** dont use nvim-treesitter to check if a lang exists ([585d24e](https://github.com/folke/noice.nvim/commit/585d24ec6e3fb4288414f864cfe2de7d025e8216))
|
||||
* **health:** fix deprecated health checks healthcheck ([#438](https://github.com/folke/noice.nvim/issues/438)) ([0f12ed3](https://github.com/folke/noice.nvim/commit/0f12ed399e79aa49f283aa954468b92be65e03ed))
|
||||
* **health:** only check for lazyredraw during startup ([46a40bd](https://github.com/folke/noice.nvim/commit/46a40bde471a15d4c5bdd959327bd35aafe0030f))
|
||||
* hide cursor with vim.schedule to keep Neovide from crashing ([c4ba29d](https://github.com/folke/noice.nvim/commit/c4ba29d90e15eef3603f5acb7c8526fad5092969))
|
||||
* hide scroll if it was shown before. Fixes [#216](https://github.com/folke/noice.nvim/issues/216) ([f5ac589](https://github.com/folke/noice.nvim/commit/f5ac589abf503a2033e1c5b4fad40f326ccab2b4))
|
||||
* **icons:** removed all obsolete icons thanks to nerdfix ([cf6a194](https://github.com/folke/noice.nvim/commit/cf6a194f9280cda1fdcc36d271fccd4a24082df3))
|
||||
* improved markdown empty line handling ([8cd47e0](https://github.com/folke/noice.nvim/commit/8cd47e0080cb095f00765ef3a73e3b4e6c8fe627))
|
||||
* incorrect active param for some lsp. Fixes [#162](https://github.com/folke/noice.nvim/issues/162) ([c7f1fca](https://github.com/folke/noice.nvim/commit/c7f1fca4e1a940f6964d732dfa85ac7ff0942c2d))
|
||||
* keep correct case for prefix match in popupmenu ([4757fd9](https://github.com/folke/noice.nvim/commit/4757fd93160815adec33e17b8c04c762c2b12ff3))
|
||||
* keep signature help open as long as the last non-whitespace character is a trigger character ([5f4544f](https://github.com/folke/noice.nvim/commit/5f4544f4e9d6481e6187d665654bcaaa19573a2e))
|
||||
* let all the cmdline hl groups fallback to the default one ([040fca5](https://github.com/folke/noice.nvim/commit/040fca50b477a2eda9033860f46a5661a00ed340))
|
||||
* load defaults as function to prevent require loops on older neovim versions ([48ffb9b](https://github.com/folke/noice.nvim/commit/48ffb9bfd5db6208a015b09e93472b47eabb2f08))
|
||||
* **lsp:** add non-nil guard to setup function ([#454](https://github.com/folke/noice.nvim/issues/454)) ([4524216](https://github.com/folke/noice.nvim/commit/4524216d7484c7b183ca1f654d8e66dff28a5680))
|
||||
* **lsp:** allow whitespace info string in markdown ([#535](https://github.com/folke/noice.nvim/issues/535)) ([1343acc](https://github.com/folke/noice.nvim/commit/1343acc592c3f138d7ffb88f9b8be1c4969b30d3))
|
||||
* **lsp:** dont show lsp progress for lsp clients that died. Fixes [#207](https://github.com/folke/noice.nvim/issues/207) ([6afc974](https://github.com/folke/noice.nvim/commit/6afc9741808fb03c938afcdc5a355243ba15066b))
|
||||
* **lsp:** return true if scrolling succeeded ([5750c09](https://github.com/folke/noice.nvim/commit/5750c097e7b9563ee07b83d7933f7954945f9397))
|
||||
* make ffi behave with plugin reloaders ([7e78236](https://github.com/folke/noice.nvim/commit/7e782362a85132e32803bfbce77a99032abc54fd))
|
||||
* make help match :help as well. Fixes [#135](https://github.com/folke/noice.nvim/issues/135) ([dc33efa](https://github.com/folke/noice.nvim/commit/dc33efa6e840eac71055d1066e54095e5c196178))
|
||||
* make nui views nomodifiable ([f674f03](https://github.com/folke/noice.nvim/commit/f674f030acad42f5afd3059198fc7ad1e5e2b598))
|
||||
* make search_count work with nohlsearch. Fixes [#217](https://github.com/folke/noice.nvim/issues/217) ([80ec5b8](https://github.com/folke/noice.nvim/commit/80ec5b8c5838e8583081a0bdeec5e7151c4f46d3))
|
||||
* make split views behave with splitkeep and restore cursor position after re-render ([0b1fb33](https://github.com/folke/noice.nvim/commit/0b1fb33327de070f702912362578f7734ba6b5d6))
|
||||
* make sure we always have an encoding for getting signatureHelp ([ba36767](https://github.com/folke/noice.nvim/commit/ba367673b3728ba2dc0672775421d13a94357dca))
|
||||
* **markdown:** better check to see if a ts parser is available. Fixes [#397](https://github.com/folke/noice.nvim/issues/397) ([d60bee1](https://github.com/folke/noice.nvim/commit/d60bee1b85af1882768af80385bc2500d495feba))
|
||||
* **markdown:** code block, rule, codeblock should only render one rule ([feb8e4d](https://github.com/folke/noice.nvim/commit/feb8e4d19ea6ef2a99248d608bda873e3a7d2707))
|
||||
* **markdown:** conceal escaping forward slashes. Fixes [#455](https://github.com/folke/noice.nvim/issues/455) ([a7246aa](https://github.com/folke/noice.nvim/commit/a7246aa99fde34fb9d5e13c62c83ac7226514d67))
|
||||
* **markdown:** replace `<code>`. Fixes [#424](https://github.com/folke/noice.nvim/issues/424) ([38fb652](https://github.com/folke/noice.nvim/commit/38fb652d0a95780d20a551a6ec44b01226476c99))
|
||||
* **markdown:** replace additional html entities ([#448](https://github.com/folke/noice.nvim/issues/448)) ([d31fe94](https://github.com/folke/noice.nvim/commit/d31fe940e0866686718822aaac45527412c45134)), closes [#447](https://github.com/folke/noice.nvim/issues/447)
|
||||
* **markdown:** revert ([d767be9](https://github.com/folke/noice.nvim/commit/d767be960e8660b19595ccff2dad6abd7aae2d4a))
|
||||
* **markdown:** strip "\r" chars ([4d2801b](https://github.com/folke/noice.nvim/commit/4d2801babc4026229c58f0c77a20ff5b7b4c0d07))
|
||||
* mini focusable=false by default ([04794f6](https://github.com/folke/noice.nvim/commit/04794f6d1ea2be83bcc5617c78aa7b7fab46fcdd))
|
||||
* noautocmd for ze in cmdline. Fixes [#206](https://github.com/folke/noice.nvim/issues/206) ([8d088aa](https://github.com/folke/noice.nvim/commit/8d088aa6083d0332ced778aab0e1fa2f2533902c))
|
||||
* **notify_send:** properly close file descriptors from spwaning notifysend ([f5132fa](https://github.com/folke/noice.nvim/commit/f5132fa6eb71e96d9f0cd7148b186b324b142d15))
|
||||
* **notify:** better way of finding rendering offset. Fixes [#181](https://github.com/folke/noice.nvim/issues/181) ([dbadd10](https://github.com/folke/noice.nvim/commit/dbadd106e42b6344243405614ae3583fb5b17efe))
|
||||
* **notify:** nvim-notify replace can be an id or a record ([a9cc87b](https://github.com/folke/noice.nvim/commit/a9cc87b14e18bc3717746b45d79157c0adb43a4d))
|
||||
* **notify:** take col offsets into account for nvim-notify renderers. Fixes [#375](https://github.com/folke/noice.nvim/issues/375) ([20596d9](https://github.com/folke/noice.nvim/commit/20596d96551605f7462f5722198b188e4047b605))
|
||||
* nui windows must have nowrap by default. See [#196](https://github.com/folke/noice.nvim/issues/196) ([48003c5](https://github.com/folke/noice.nvim/commit/48003c550a03bd15169b35c5b3dc066f0e8f541d))
|
||||
* nui.menu._tree -> nui.menu.tree ([ab151eb](https://github.com/folke/noice.nvim/commit/ab151eb85b15d13176d1b2a4c37113530637a058))
|
||||
* **nui:** dont trigger autocmds when doing zt ([d176765](https://github.com/folke/noice.nvim/commit/d176765ceabae9a12bf09a5c785d3dcb3859e1b6))
|
||||
* **nui:** make sure nui recreates buffer and window when needed ([3e6dfd8](https://github.com/folke/noice.nvim/commit/3e6dfd8bb00d98399704a020ab7892234ce80fdb))
|
||||
* **nui:** mount if buffer is no longer valid ([71d7b5c](https://github.com/folke/noice.nvim/commit/71d7b5cf8f24b9bdc425934c36cfda784fcd10f2))
|
||||
* **nui:** nui broke noice. added a temporary work-around till the problem is solved ([4db3c8f](https://github.com/folke/noice.nvim/commit/4db3c8f14302273b842f73a8facf1999169c1e41))
|
||||
* **nui:** remove border text when style is `nil`, `"none"`, or `"shadow"` ([d85a4d0](https://github.com/folke/noice.nvim/commit/d85a4d01774b5649dbcda8526a26f201dff5ade4))
|
||||
* **nui:** remove padding when border is `shadow` ([1515007](https://github.com/folke/noice.nvim/commit/151500759722c12fb6a3931c5243d68f01af007a))
|
||||
* **nui:** removed work-around for padding and border style shadow ([4f34d33](https://github.com/folke/noice.nvim/commit/4f34d33fc3dc0d6f4da9b4b8c63b9714fd4eea79))
|
||||
* **nui:** reset close events on remount ([1558c48](https://github.com/folke/noice.nvim/commit/1558c48257e6d1c99edd15fd12fbd1dbc4fa22c1))
|
||||
* **nui:** set mounted=false if buffer is no longer valid ([3353a7a](https://github.com/folke/noice.nvim/commit/3353a7ab4bae6c22f61fd646c10e336b4582f0ea))
|
||||
* **nui:** umount on hide, to fix rendering issue while blocking ([119682b](https://github.com/folke/noice.nvim/commit/119682b44f6b5303e141fdbdbdd25c261a89d306))
|
||||
* one-off error for highlighting with treesitter/syntax ([1602ce8](https://github.com/folke/noice.nvim/commit/1602ce897e66672c43da95c9175d103f1a69e2aa))
|
||||
* only relayout with real width and height ([2462809](https://github.com/folke/noice.nvim/commit/24628097307e5e8453e691192bed45ec6da1bebd))
|
||||
* only set noice buffer names if debug. Fixes [#197](https://github.com/folke/noice.nvim/issues/197) ([ea1079d](https://github.com/folke/noice.nvim/commit/ea1079deb6ffdc326b3da0dc2e84371b330dfdae))
|
||||
* only show/hide scrollbar when needed ([d01cd10](https://github.com/folke/noice.nvim/commit/d01cd1052a865588bbebbd4015ad778b81312fe9))
|
||||
* **overrides:** noice was leaking extmarks for stylize_markdown ([9b148a1](https://github.com/folke/noice.nvim/commit/9b148a141df7fefc66705e2e7219d11536b99288))
|
||||
* popupmenu default relative=editor ([7ef41aa](https://github.com/folke/noice.nvim/commit/7ef41aa92e2ca0bdfe972bc6a68350c8be06044e))
|
||||
* **popupmenu:** always show the regular (non-cmdline) popupmenu near the cursor ([e3936cc](https://github.com/folke/noice.nvim/commit/e3936ccbbd32f6ce4a4f55a77ec556b116c0b928))
|
||||
* **popupmenu:** only use popupmenu hl group for known item kinds. Fixes [#453](https://github.com/folke/noice.nvim/issues/453) ([0b86a7b](https://github.com/folke/noice.nvim/commit/0b86a7bfbf84927909ed81e9616a5e24602fe6fb))
|
||||
* **popupmenu:** properly close pmenu when cmdline window is open. Fixes [#542](https://github.com/folke/noice.nvim/issues/542) ([d19e5cb](https://github.com/folke/noice.nvim/commit/d19e5cb58e33c6d74e9005d1965d6e8ebd6b057b))
|
||||
* **popupmenu:** replace any newlines by space. Fixes [#265](https://github.com/folke/noice.nvim/issues/265) ([5199089](https://github.com/folke/noice.nvim/commit/51990892e1dd5ee1a1444b1cf3ccf0aca377e0c4))
|
||||
* potential endless loop in markdown key handlers ([078cbd9](https://github.com/folke/noice.nvim/commit/078cbd9087fd358df8de54072253c0e2ae7c89c9))
|
||||
* **preset:** palette now configures cmdline_popupmenu instead of popupmenu ([294097a](https://github.com/folke/noice.nvim/commit/294097a239ec943587e5707b678142c52a9b318e))
|
||||
* progress use vim.lsp.get_client_by_id ([#529](https://github.com/folke/noice.nvim/issues/529)) ([397619d](https://github.com/folke/noice.nvim/commit/397619d5351d650e9879d18c9312a5add5729815))
|
||||
* properly handle carriage returns. Fixes [#190](https://github.com/folke/noice.nvim/issues/190) ([c14b064](https://github.com/folke/noice.nvim/commit/c14b0649c2356a4e86aeea63449859ee0b39ef6d))
|
||||
* properly handle MarkedString[] mix. Fixes [#178](https://github.com/folke/noice.nvim/issues/178) ([14cff19](https://github.com/folke/noice.nvim/commit/14cff1957fe00ec8f6d2d0951369bbccad74c7c2))
|
||||
* re-use existing views with same backend and opts ([1d1e9ed](https://github.com/folke/noice.nvim/commit/1d1e9ed9ce34895c7dfb80d44aa5b7a90863ef06))
|
||||
* read conceal setting after sort ([#558](https://github.com/folke/noice.nvim/issues/558)) ([24c09cc](https://github.com/folke/noice.nvim/commit/24c09cc0263054cb3d8dedf2c54b570e655850f5))
|
||||
* reduce some flickering when updating views ([f39b657](https://github.com/folke/noice.nvim/commit/f39b657bff3d224b41fbe6b21fd3ce24e6b9b4e2))
|
||||
* remove old neovide compatibility warning ([#545](https://github.com/folke/noice.nvim/issues/545)) ([dfbe27c](https://github.com/folke/noice.nvim/commit/dfbe27cfafd6bcb5605dc6c6b82174c33fc9b09e))
|
||||
* reopen scrollbar windows if they were deleted somehow. Fixes [#235](https://github.com/folke/noice.nvim/issues/235) ([74c7e29](https://github.com/folke/noice.nvim/commit/74c7e29aba2cc32e5a51fa1828813e08f327ef3a))
|
||||
* reset preloader before trying to load the module ([08655e9](https://github.com/folke/noice.nvim/commit/08655e9f1bed638f9871d76b05928da74d1eeb68))
|
||||
* reset view when update_layout fails. Fixes [#155](https://github.com/folke/noice.nvim/issues/155) ([7d08ed5](https://github.com/folke/noice.nvim/commit/7d08ed5bcc2d4a5fc540f096dd1d8fa800faed42))
|
||||
* restore cursor with vim.schedule to be safe ([973659e](https://github.com/folke/noice.nvim/commit/973659e01fafa5b8e5808dce443bfddb63e5eb54))
|
||||
* return lines in stylize_markdown ([f9bf77d](https://github.com/folke/noice.nvim/commit/f9bf77ddd5d6d78c37391696e05ba6e7d0c9830f))
|
||||
* return message id in vim.notify, so it can be used for replace if the view supports it. Fixes [#109](https://github.com/folke/noice.nvim/issues/109) ([0b0e8cf](https://github.com/folke/noice.nvim/commit/0b0e8cf85ab5fcb891b7cfd44c0c4908c0e1ef46))
|
||||
* return nil when Noice is not running for statusline ([289ce14](https://github.com/folke/noice.nvim/commit/289ce145dca5300f9a30684221b9ebe375bb4aae))
|
||||
* **router:** properly disable updater when disabling Noice. Fixes [#423](https://github.com/folke/noice.nvim/issues/423) ([3bed83b](https://github.com/folke/noice.nvim/commit/3bed83b4d2e4fce03a27071c39be0d9e04313332))
|
||||
* scroll cmdline to make sure cursor is always visible. Fixes [#196](https://github.com/folke/noice.nvim/issues/196) ([e023c5f](https://github.com/folke/noice.nvim/commit/e023c5f005807e8bbcab2d1f614e75a9f62edc59))
|
||||
* scrollbar destructs itself, so make a copy to see if there are any remnants left ([8d80a69](https://github.com/folke/noice.nvim/commit/8d80a692d5a045a3ec995536782f2b4c2b8d901b))
|
||||
* scrollbar for popups was off if there was padding on the window ([deda89a](https://github.com/folke/noice.nvim/commit/deda89a17c1e9dc1d4886b4c1d3704dfddefb1f2))
|
||||
* **scrollbar:** zindex + 1 + 2 for bar and thumb ([0daa539](https://github.com/folke/noice.nvim/commit/0daa5390eb14e0c19ac64debaea638bcf5fb70aa))
|
||||
* set conceallevel local. Fixes [#634](https://github.com/folke/noice.nvim/issues/634) ([c1591df](https://github.com/folke/noice.nvim/commit/c1591dfc8e2177402eff82be5c9cddc72de28c16))
|
||||
* set cursor to top when opening view. Fixes [#165](https://github.com/folke/noice.nvim/issues/165) ([c20f38e](https://github.com/folke/noice.nvim/commit/c20f38e7c1b6d368af2bb599667b473879316c89))
|
||||
* show unstable message after loading noice ([2613a16](https://github.com/folke/noice.nvim/commit/2613a16b5009acbf2adabb34b029b1c4c57101e3))
|
||||
* showMessage error with kinds. Fixes [#222](https://github.com/folke/noice.nvim/issues/222) ([d4d653a](https://github.com/folke/noice.nvim/commit/d4d653a894d1f1fbc422db1f8351d86fdb1f16f8))
|
||||
* **signature:** nil check for parameter label. Fixes [#435](https://github.com/folke/noice.nvim/issues/435) ([9d778e7](https://github.com/folke/noice.nvim/commit/9d778e7ce29c519ca0285b054e7c3b679bc9d3b9))
|
||||
* **signature:** nil check on lsp signature.parameters. Fixes [#162](https://github.com/folke/noice.nvim/issues/162) ([1dc7f26](https://github.com/folke/noice.nvim/commit/1dc7f26a68efbd5f0da081d98d938c587de0ba25))
|
||||
* **signature:** safer lsp signature parameters ([#449](https://github.com/folke/noice.nvim/issues/449)) ([e33c346](https://github.com/folke/noice.nvim/commit/e33c34642a7b02db3db03bfc2bec7799bbc2034e))
|
||||
* **signature:** show signature in correct window. Fixes [#593](https://github.com/folke/noice.nvim/issues/593) ([2f0993e](https://github.com/folke/noice.nvim/commit/2f0993ee97f98cacde179a1f431881b2758e2138))
|
||||
* **signature:** support label offsets ([9649d9f](https://github.com/folke/noice.nvim/commit/9649d9fd4d8fa8a8654e1e9c293718ae8d62e73b))
|
||||
* **signature:** when loading, attach to existing lsp clients. Fixes [#342](https://github.com/folke/noice.nvim/issues/342) ([f69f1a5](https://github.com/folke/noice.nvim/commit/f69f1a577615a5a6527f133df0aa40e596bd1707))
|
||||
* silence treesitter errors of invalid langs. Covered by checkhealth ([db1628f](https://github.com/folke/noice.nvim/commit/db1628fc81cf2029eea9dfe2e8e121143b6b35dc))
|
||||
* **smart_move:** Dont move `cmdline` view ([#123](https://github.com/folke/noice.nvim/issues/123)) ([3da3f6d](https://github.com/folke/noice.nvim/commit/3da3f6d5be613ff7eb590c3e7f31c4e0cddf75d8))
|
||||
* statusline messages no longer need active state. Fixes [#211](https://github.com/folke/noice.nvim/issues/211) ([e5092c2](https://github.com/folke/noice.nvim/commit/e5092c284a6ffd44e8d09f5efbe29395190c77f9))
|
||||
* stop processing messages when Neovim is exiting. Fixes [#237](https://github.com/folke/noice.nvim/issues/237) ([8c8acf7](https://github.com/folke/noice.nvim/commit/8c8acf74c09374e48a8fa1835560c3913d57243f))
|
||||
* support older Neovim versions ([4a1ec5e](https://github.com/folke/noice.nvim/commit/4a1ec5ec0b163a365d7593d93450676b9cbcbebd))
|
||||
* **swap:** additionally check for updates when a swap file was found ([1165d3e](https://github.com/folke/noice.nvim/commit/1165d3e727bdd226eefffcc801d563bcb30e71c4))
|
||||
* tag popupmenu border ([d2064a5](https://github.com/folke/noice.nvim/commit/d2064a50495f21f14ce52419660672f1e7c489bf))
|
||||
* tag scrollbar and popupmenu ([13bed57](https://github.com/folke/noice.nvim/commit/13bed5763abd9a0c4c84abd794f26772cb850fe8))
|
||||
* **telescope:** Correct index for finder ([#136](https://github.com/folke/noice.nvim/issues/136)) ([99bbfe7](https://github.com/folke/noice.nvim/commit/99bbfe7ee49263577f6a941ad61677199a02eaf7))
|
||||
* **telescope:** wrap text in telescope's previewer ([#514](https://github.com/folke/noice.nvim/issues/514)) ([a7f611e](https://github.com/folke/noice.nvim/commit/a7f611ef740a45b995d4a8e6d237643ac6ad0093))
|
||||
* **text:** better (correct) way of dealing with `\r` characters. Fixes [#483](https://github.com/folke/noice.nvim/issues/483) ([520a737](https://github.com/folke/noice.nvim/commit/520a73760030f1293bbee41b0dcd041f47d1ecae))
|
||||
* **text:** temp fixup for CRLF handling ([3e1400f](https://github.com/folke/noice.nvim/commit/3e1400f172cf67041f6845d86413de56fb90e685))
|
||||
* **treesitter:** deprecated call. Fixes [#408](https://github.com/folke/noice.nvim/issues/408) ([1ded575](https://github.com/folke/noice.nvim/commit/1ded575928752861558a729fcbbd1e6e53c76652))
|
||||
* **treesitter:** dont allow recursive injections. Fixes [#286](https://github.com/folke/noice.nvim/issues/286) ([a31b41a](https://github.com/folke/noice.nvim/commit/a31b41a739731988fc30a48a3099586a884bdf61))
|
||||
* **treesitter:** fixed treesitter.query.get. Fixes [#539](https://github.com/folke/noice.nvim/issues/539) ([e91a31c](https://github.com/folke/noice.nvim/commit/e91a31c32c0eef6a338030ac51eaed14ac49ce2e))
|
||||
* **treesitter:** ignore weird invalid end_col errors. Fixes [#473](https://github.com/folke/noice.nvim/issues/473) ([7e2692b](https://github.com/folke/noice.nvim/commit/7e2692b0c461da182a54ff2af4a35aea2bf8ea5c))
|
||||
* **treesitter:** only disable injections for php and html ([0e1bf11](https://github.com/folke/noice.nvim/commit/0e1bf11d46054b8ab04eb62b53c5ac81b44f14df))
|
||||
* **treesitter:** parse injections ([#571](https://github.com/folke/noice.nvim/issues/571)) ([3ec6e42](https://github.com/folke/noice.nvim/commit/3ec6e4221e9b80f914ed6774abb4e82d8f5c3b39))
|
||||
* **treesitter:** use the new treesitter ft to lang API if availble. Fixes [#378](https://github.com/folke/noice.nvim/issues/378) ([36d141b](https://github.com/folke/noice.nvim/commit/36d141bd5852b10e32058e259982182b9e5e8060))
|
||||
* truncate log file if it becomes too big ([79a5262](https://github.com/folke/noice.nvim/commit/79a526210233808e7c73714998f56c9f059c11d8))
|
||||
* **ui_attach:** dont update router during `ext_messages` and disable/enable Noice during confirm. [#298](https://github.com/folke/noice.nvim/issues/298) ([a4cbc0f](https://github.com/folke/noice.nvim/commit/a4cbc0f0cebdaa9529a749f4463aedc5a2cdcf1b))
|
||||
* **ui:** cmdline is always blocking. Fixes [#347](https://github.com/folke/noice.nvim/issues/347) ([6702d97](https://github.com/folke/noice.nvim/commit/6702d97d3c37c3a363ffc7c890578109f82f9f20))
|
||||
* **ui:** disable debug logging ([bfb0cdb](https://github.com/folke/noice.nvim/commit/bfb0cdb56cc3b2eb5f00b6c1747d04540d76799a))
|
||||
* **ui:** dont propagate events handled by Noice to other uis. Fixes [#17](https://github.com/folke/noice.nvim/issues/17) ([1cff24c](https://github.com/folke/noice.nvim/commit/1cff24cabf1076916be1e83de16514be99827678))
|
||||
* **ui:** dont update on msg_ruler. Fixes [#588](https://github.com/folke/noice.nvim/issues/588) ([ec19fc0](https://github.com/folke/noice.nvim/commit/ec19fc0fd27fcfa8661d71bcfb61f6b84a6b7f98))
|
||||
* **ui:** exclude search_count from realtime updates ([73caffa](https://github.com/folke/noice.nvim/commit/73caffa74550e98ae3f61520a4af526ac593609b))
|
||||
* **ui:** safer adding of winhl ([36b1935](https://github.com/folke/noice.nvim/commit/36b1935660988b4b6034ef9fb8454a1427990675))
|
||||
* **ui:** work-around for segfaults in TUI. Fixes [#298](https://github.com/folke/noice.nvim/issues/298) ([176ec31](https://github.com/folke/noice.nvim/commit/176ec31026ec4baf64638fba1a180701257380f1))
|
||||
* use modeline=false for popupmenu scroll events. Fixes [#572](https://github.com/folke/noice.nvim/issues/572) ([1f087c2](https://github.com/folke/noice.nvim/commit/1f087c2495bbc824b556329eb389dfff8964e5a3))
|
||||
* use vim.F.unpack_len and vim.F.pack_len. Fixes a number of issues... ([51c2179](https://github.com/folke/noice.nvim/commit/51c2179d3535d4c61d0ceb80e2938884fa73181c))
|
||||
* **views:** don't override winbar and foldenable for every view ([a7d60f7](https://github.com/folke/noice.nvim/commit/a7d60f73b1325137b34c630bc0af76fa6598ba1f))
|
||||
* **views:** dont highlight CurSearch for some views. Fixes [#399](https://github.com/folke/noice.nvim/issues/399) ([0c493e5](https://github.com/folke/noice.nvim/commit/0c493e5d243c39adf3d6ce7683a16e610cc44e0a))
|
||||
* **views:** increase zindex for cmdline popup, popupmenu and confirm from 60 to 200 ([d71c1de](https://github.com/folke/noice.nvim/commit/d71c1deabf78db16262f5388fe12930fc16bd93e))
|
||||
* **virtual:** extra check if buffer still valid that has virtual text extmark ([7ed897d](https://github.com/folke/noice.nvim/commit/7ed897d77d13eb4a9f4ab576f58db9bdda9af6ec))
|
||||
* **virtual:** remove extmark from correct buffer where it was set. Fixes [#464](https://github.com/folke/noice.nvim/issues/464) ([e5a4c7a](https://github.com/folke/noice.nvim/commit/e5a4c7a6ac3ef4c32f97a50c0b9b21e21c445c04))
|
||||
* wait to override cmp till it loaded ([712180f](https://github.com/folke/noice.nvim/commit/712180f94684b7ce56957df60d037c81784e69c3))
|
||||
* workaround E36: Not enough room errors ([#522](https://github.com/folke/noice.nvim/issues/522)) ([f43775f](https://github.com/folke/noice.nvim/commit/f43775f0e427b0c7e9d30e6bc51fdebea6979b37))
|
||||
|
||||
|
||||
### Performance Improvements
|
||||
|
||||
* cache highlighter queries ([b4eb215](https://github.com/folke/noice.nvim/commit/b4eb2155f3347377eb0c14458755ce7b7966cdb7))
|
||||
* do redrawstatus before resetting cursor ([5aa862f](https://github.com/folke/noice.nvim/commit/5aa862f380c65fbe2833b2b9e869822e7e9f8257))
|
||||
* don't bufload when highlighting a buffer ([8df4cbd](https://github.com/folke/noice.nvim/commit/8df4cbdae15a915d460828710bf9ff1befb3f12d))
|
||||
* dont update popupmenu state when it hasn't changed ([cafdddb](https://github.com/folke/noice.nvim/commit/cafdddb6eb3105cac1220337f91c21aebe998485))
|
||||
* **lazy:** set package.loaded when real module was loaded ([f6cc07a](https://github.com/folke/noice.nvim/commit/f6cc07af4d9329c48fed9e22044f2a0ed8ac7d31))
|
||||
* make noice a bit more robust when exiting to prevent possible delays on exit ([35e3664](https://github.com/folke/noice.nvim/commit/35e3664297096d8e24ca17f590bc793482f5182d))
|
||||
* **popupmenu:** re-use existing nui menu for rendering the popupmenu ([fdd78c2](https://github.com/folke/noice.nvim/commit/fdd78c25f64482c4c92ca84ba9c5814a5aa2788e))
|
||||
* re-use existing popupmenu instead of unmount/create ([b209e0b](https://github.com/folke/noice.nvim/commit/b209e0bbb1666081eb70cfa919d315d892e73cb7))
|
||||
* shutdown Noice on VimLeave to prevent close delay ([de1d5dc](https://github.com/folke/noice.nvim/commit/de1d5dc1f9446221674cee6b69b81a28b13dfa62))
|
||||
|
||||
## [1.16.3](https://github.com/folke/noice.nvim/compare/v1.16.2...v1.16.3) (2023-10-24)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **hacks:** make sure the cursor is properly updated before getchar ([0cca940](https://github.com/folke/noice.nvim/commit/0cca940561d4b723cb52ba9e4ec239fceb36f146))
|
||||
* use modeline=false for popupmenu scroll events. Fixes [#572](https://github.com/folke/noice.nvim/issues/572) ([1f087c2](https://github.com/folke/noice.nvim/commit/1f087c2495bbc824b556329eb389dfff8964e5a3))
|
||||
|
||||
## [1.16.2](https://github.com/folke/noice.nvim/compare/v1.16.1...v1.16.2) (2023-10-15)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **cmdline:** better and safer way to trigger redraw during cmdpreview ([02ed6d4](https://github.com/folke/noice.nvim/commit/02ed6d4c0c1e4d21fc4e79bbe54961023ee9badb))
|
||||
* **signature:** show signature in correct window. Fixes [#593](https://github.com/folke/noice.nvim/issues/593) ([2f0993e](https://github.com/folke/noice.nvim/commit/2f0993ee97f98cacde179a1f431881b2758e2138))
|
||||
* **virtual:** extra check if buffer still valid that has virtual text extmark ([7ed897d](https://github.com/folke/noice.nvim/commit/7ed897d77d13eb4a9f4ab576f58db9bdda9af6ec))
|
||||
* **virtual:** remove extmark from correct buffer where it was set. Fixes [#464](https://github.com/folke/noice.nvim/issues/464) ([e5a4c7a](https://github.com/folke/noice.nvim/commit/e5a4c7a6ac3ef4c32f97a50c0b9b21e21c445c04))
|
||||
|
||||
## [1.16.1](https://github.com/folke/noice.nvim/compare/v1.16.0...v1.16.1) (2023-10-07)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **ui:** exclude search_count from realtime updates ([73caffa](https://github.com/folke/noice.nvim/commit/73caffa74550e98ae3f61520a4af526ac593609b))
|
||||
|
||||
## [1.16.0](https://github.com/folke/noice.nvim/compare/v1.15.11...v1.16.0) (2023-10-04)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* Support hide scrollbar for view ([#603](https://github.com/folke/noice.nvim/issues/603)) ([f700175](https://github.com/folke/noice.nvim/commit/f700175b91948e4f71cf73872cea364247cf2dbd))
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **ui:** disable debug logging ([bfb0cdb](https://github.com/folke/noice.nvim/commit/bfb0cdb56cc3b2eb5f00b6c1747d04540d76799a))
|
||||
* **ui:** dont update on msg_ruler. Fixes [#588](https://github.com/folke/noice.nvim/issues/588) ([ec19fc0](https://github.com/folke/noice.nvim/commit/ec19fc0fd27fcfa8661d71bcfb61f6b84a6b7f98))
|
||||
|
||||
## [1.15.11](https://github.com/folke/noice.nvim/compare/v1.15.10...v1.15.11) (2023-09-25)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* accept preset as a table ([#582](https://github.com/folke/noice.nvim/issues/582)) ([53d613c](https://github.com/folke/noice.nvim/commit/53d613cd0031e83987964947b1bad8b5047c9d0e))
|
||||
* check item.detail is type of table ([#595](https://github.com/folke/noice.nvim/issues/595)) ([3670766](https://github.com/folke/noice.nvim/commit/3670766b10fded979fcb00606801edc585a65f2a))
|
||||
* dont hide cursor on input. Fixes [#585](https://github.com/folke/noice.nvim/issues/585). Fixes [#566](https://github.com/folke/noice.nvim/issues/566) ([819a5bf](https://github.com/folke/noice.nvim/commit/819a5bf62fa31c893c9d0c6da17ef93a810a1e8c))
|
||||
* read conceal setting after sort ([#558](https://github.com/folke/noice.nvim/issues/558)) ([24c09cc](https://github.com/folke/noice.nvim/commit/24c09cc0263054cb3d8dedf2c54b570e655850f5))
|
||||
|
||||
## [1.15.10](https://github.com/folke/noice.nvim/compare/v1.15.9...v1.15.10) (2023-08-26)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **treesitter:** parse injections ([#571](https://github.com/folke/noice.nvim/issues/571)) ([3ec6e42](https://github.com/folke/noice.nvim/commit/3ec6e4221e9b80f914ed6774abb4e82d8f5c3b39))
|
||||
|
||||
## [1.15.9](https://github.com/folke/noice.nvim/compare/v1.15.8...v1.15.9) (2023-07-25)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **health:** allow running in GUIs with multigrid ([71a7591](https://github.com/folke/noice.nvim/commit/71a75913d680af9f1f26a2886518e390cd8f73e1))
|
||||
|
||||
## [1.15.8](https://github.com/folke/noice.nvim/compare/v1.15.7...v1.15.8) (2023-07-21)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* remove old neovide compatibility warning ([#545](https://github.com/folke/noice.nvim/issues/545)) ([dfbe27c](https://github.com/folke/noice.nvim/commit/dfbe27cfafd6bcb5605dc6c6b82174c33fc9b09e))
|
||||
|
||||
## [1.15.7](https://github.com/folke/noice.nvim/compare/v1.15.6...v1.15.7) (2023-07-20)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **popupmenu:** properly close pmenu when cmdline window is open. Fixes [#542](https://github.com/folke/noice.nvim/issues/542) ([d19e5cb](https://github.com/folke/noice.nvim/commit/d19e5cb58e33c6d74e9005d1965d6e8ebd6b057b))
|
||||
|
||||
## [1.15.6](https://github.com/folke/noice.nvim/compare/v1.15.5...v1.15.6) (2023-07-18)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **treesitter:** fixed treesitter.query.get. Fixes [#539](https://github.com/folke/noice.nvim/issues/539) ([e91a31c](https://github.com/folke/noice.nvim/commit/e91a31c32c0eef6a338030ac51eaed14ac49ce2e))
|
||||
|
||||
## [1.15.5](https://github.com/folke/noice.nvim/compare/v1.15.4...v1.15.5) (2023-07-17)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **lsp:** allow whitespace info string in markdown ([#535](https://github.com/folke/noice.nvim/issues/535)) ([1343acc](https://github.com/folke/noice.nvim/commit/1343acc592c3f138d7ffb88f9b8be1c4969b30d3))
|
||||
* **ui:** dont propagate events handled by Noice to other uis. Fixes [#17](https://github.com/folke/noice.nvim/issues/17) ([1cff24c](https://github.com/folke/noice.nvim/commit/1cff24cabf1076916be1e83de16514be99827678))
|
||||
|
||||
## [1.15.4](https://github.com/folke/noice.nvim/compare/v1.15.3...v1.15.4) (2023-06-30)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* progress use vim.lsp.get_client_by_id ([#529](https://github.com/folke/noice.nvim/issues/529)) ([397619d](https://github.com/folke/noice.nvim/commit/397619d5351d650e9879d18c9312a5add5729815))
|
||||
* workaround E36: Not enough room errors ([#522](https://github.com/folke/noice.nvim/issues/522)) ([f43775f](https://github.com/folke/noice.nvim/commit/f43775f0e427b0c7e9d30e6bc51fdebea6979b37))
|
||||
|
||||
## [1.15.3](https://github.com/folke/noice.nvim/compare/v1.15.2...v1.15.3) (2023-06-24)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **config:** properly deal with preset routes. Fixes [#517](https://github.com/folke/noice.nvim/issues/517) ([fea7f1c](https://github.com/folke/noice.nvim/commit/fea7f1cf15b04ec9b8dd071aa3510f693156ce59))
|
||||
|
||||
## [1.15.2](https://github.com/folke/noice.nvim/compare/v1.15.1...v1.15.2) (2023-06-22)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **telescope:** wrap text in telescope's previewer ([#514](https://github.com/folke/noice.nvim/issues/514)) ([a7f611e](https://github.com/folke/noice.nvim/commit/a7f611ef740a45b995d4a8e6d237643ac6ad0093))
|
||||
* **views:** don't override winbar and foldenable for every view ([a7d60f7](https://github.com/folke/noice.nvim/commit/a7d60f73b1325137b34c630bc0af76fa6598ba1f))
|
||||
* **views:** increase zindex for cmdline popup, popupmenu and confirm from 60 to 200 ([d71c1de](https://github.com/folke/noice.nvim/commit/d71c1deabf78db16262f5388fe12930fc16bd93e))
|
||||
|
||||
## [1.15.1](https://github.com/folke/noice.nvim/compare/v1.15.0...v1.15.1) (2023-06-10)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **nui:** nui broke noice. added a temporary work-around till the problem is solved ([4db3c8f](https://github.com/folke/noice.nvim/commit/4db3c8f14302273b842f73a8facf1999169c1e41))
|
||||
* **ui:** safer adding of winhl ([36b1935](https://github.com/folke/noice.nvim/commit/36b1935660988b4b6034ef9fb8454a1427990675))
|
||||
|
||||
## [1.15.0](https://github.com/folke/noice.nvim/compare/v1.14.2...v1.15.0) (2023-06-06)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* add `circleFull` spinner ([#495](https://github.com/folke/noice.nvim/issues/495)) ([5427398](https://github.com/folke/noice.nvim/commit/54273980749ceb4396501300bf4c86f3bb818f75))
|
||||
* **popupmenu:** allow different views for regular/cmdline popupmenu ([af706c4](https://github.com/folke/noice.nvim/commit/af706c4b443cf1c416ef7288ec3434f3f1ab6cf1))
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **popupmenu:** always show the regular (non-cmdline) popupmenu near the cursor ([e3936cc](https://github.com/folke/noice.nvim/commit/e3936ccbbd32f6ce4a4f55a77ec556b116c0b928))
|
||||
* **preset:** palette now configures cmdline_popupmenu instead of popupmenu ([294097a](https://github.com/folke/noice.nvim/commit/294097a239ec943587e5707b678142c52a9b318e))
|
||||
|
||||
|
||||
### Performance Improvements
|
||||
|
||||
* **popupmenu:** re-use existing nui menu for rendering the popupmenu ([fdd78c2](https://github.com/folke/noice.nvim/commit/fdd78c25f64482c4c92ca84ba9c5814a5aa2788e))
|
||||
|
||||
## [1.14.2](https://github.com/folke/noice.nvim/compare/v1.14.1...v1.14.2) (2023-05-27)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **block:** better deal with carriage return characters (take 2) ([ee24b36](https://github.com/folke/noice.nvim/commit/ee24b36743b18e53bdc6b49bbfa426fc18ea337a))
|
||||
* **text:** temp fixup for CRLF handling ([3e1400f](https://github.com/folke/noice.nvim/commit/3e1400f172cf67041f6845d86413de56fb90e685))
|
||||
|
||||
## [1.14.1](https://github.com/folke/noice.nvim/compare/v1.14.0...v1.14.1) (2023-05-27)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **text:** better (correct) way of dealing with `\r` characters. Fixes [#483](https://github.com/folke/noice.nvim/issues/483) ([520a737](https://github.com/folke/noice.nvim/commit/520a73760030f1293bbee41b0dcd041f47d1ecae))
|
||||
|
||||
## [1.14.0](https://github.com/folke/noice.nvim/compare/v1.13.4...v1.14.0) (2023-05-25)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **cmdline:** added support for FloatTitle and added proper default ([79c7059](https://github.com/folke/noice.nvim/commit/79c70594aefb4efecbce4528174fdd0227baaf3e))
|
||||
|
||||
## [1.13.4](https://github.com/folke/noice.nvim/compare/v1.13.3...v1.13.4) (2023-05-24)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **cmdline:** fixed a byte offset issue with the new virtual inline text ([a13a88f](https://github.com/folke/noice.nvim/commit/a13a88fb2016b6cfea8f56238566b345f537e47a))
|
||||
|
||||
## [1.13.3](https://github.com/folke/noice.nvim/compare/v1.13.2...v1.13.3) (2023-05-24)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **overrides:** noice was leaking extmarks for stylize_markdown ([9b148a1](https://github.com/folke/noice.nvim/commit/9b148a141df7fefc66705e2e7219d11536b99288))
|
||||
|
||||
## [1.13.2](https://github.com/folke/noice.nvim/compare/v1.13.1...v1.13.2) (2023-05-22)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **treesitter:** ignore weird invalid end_col errors. Fixes [#473](https://github.com/folke/noice.nvim/issues/473) ([7e2692b](https://github.com/folke/noice.nvim/commit/7e2692b0c461da182a54ff2af4a35aea2bf8ea5c))
|
||||
|
||||
|
||||
### Performance Improvements
|
||||
|
||||
* don't bufload when highlighting a buffer ([8df4cbd](https://github.com/folke/noice.nvim/commit/8df4cbdae15a915d460828710bf9ff1befb3f12d))
|
||||
|
||||
## [1.13.1](https://github.com/folke/noice.nvim/compare/v1.13.0...v1.13.1) (2023-05-21)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* support older Neovim versions ([4a1ec5e](https://github.com/folke/noice.nvim/commit/4a1ec5ec0b163a365d7593d93450676b9cbcbebd))
|
||||
|
||||
## [1.13.0](https://github.com/folke/noice.nvim/compare/v1.12.4...v1.13.0) (2023-05-21)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **cmp:** incude item.detail when it's not part of item.documentation ([c2a745a](https://github.com/folke/noice.nvim/commit/c2a745a26ae562f1faecbf6177ac53377d2658d5))
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **notify:** nvim-notify replace can be an id or a record ([a9cc87b](https://github.com/folke/noice.nvim/commit/a9cc87b14e18bc3717746b45d79157c0adb43a4d))
|
||||
|
||||
|
||||
### Performance Improvements
|
||||
|
||||
* cache highlighter queries ([b4eb215](https://github.com/folke/noice.nvim/commit/b4eb2155f3347377eb0c14458755ce7b7966cdb7))
|
||||
|
||||
## [1.12.4](https://github.com/folke/noice.nvim/compare/v1.12.3...v1.12.4) (2023-05-07)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **lsp:** add non-nil guard to setup function ([#454](https://github.com/folke/noice.nvim/issues/454)) ([4524216](https://github.com/folke/noice.nvim/commit/4524216d7484c7b183ca1f654d8e66dff28a5680))
|
||||
* **markdown:** conceal escaping forward slashes. Fixes [#455](https://github.com/folke/noice.nvim/issues/455) ([a7246aa](https://github.com/folke/noice.nvim/commit/a7246aa99fde34fb9d5e13c62c83ac7226514d67))
|
||||
|
||||
## [1.12.3](https://github.com/folke/noice.nvim/compare/v1.12.2...v1.12.3) (2023-05-04)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **health:** fix deprecated health checks healthcheck ([#438](https://github.com/folke/noice.nvim/issues/438)) ([0f12ed3](https://github.com/folke/noice.nvim/commit/0f12ed399e79aa49f283aa954468b92be65e03ed))
|
||||
* **markdown:** replace additional html entities ([#448](https://github.com/folke/noice.nvim/issues/448)) ([d31fe94](https://github.com/folke/noice.nvim/commit/d31fe940e0866686718822aaac45527412c45134)), closes [#447](https://github.com/folke/noice.nvim/issues/447)
|
||||
* **popupmenu:** only use popupmenu hl group for known item kinds. Fixes [#453](https://github.com/folke/noice.nvim/issues/453) ([0b86a7b](https://github.com/folke/noice.nvim/commit/0b86a7bfbf84927909ed81e9616a5e24602fe6fb))
|
||||
* **signature:** safer lsp signature parameters ([#449](https://github.com/folke/noice.nvim/issues/449)) ([e33c346](https://github.com/folke/noice.nvim/commit/e33c34642a7b02db3db03bfc2bec7799bbc2034e))
|
||||
|
||||
## [1.12.2](https://github.com/folke/noice.nvim/compare/v1.12.1...v1.12.2) (2023-04-18)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **signature:** nil check for parameter label. Fixes [#435](https://github.com/folke/noice.nvim/issues/435) ([9d778e7](https://github.com/folke/noice.nvim/commit/9d778e7ce29c519ca0285b054e7c3b679bc9d3b9))
|
||||
* **signature:** support label offsets ([9649d9f](https://github.com/folke/noice.nvim/commit/9649d9fd4d8fa8a8654e1e9c293718ae8d62e73b))
|
||||
|
||||
## [1.12.1](https://github.com/folke/noice.nvim/compare/v1.12.0...v1.12.1) (2023-04-17)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **router:** properly disable updater when disabling Noice. Fixes [#423](https://github.com/folke/noice.nvim/issues/423) ([3bed83b](https://github.com/folke/noice.nvim/commit/3bed83b4d2e4fce03a27071c39be0d9e04313332))
|
||||
|
||||
## [1.12.0](https://github.com/folke/noice.nvim/compare/v1.11.0...v1.12.0) (2023-04-16)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* added `Noice dismiss` to hide all visible messages. Fixes [#417](https://github.com/folke/noice.nvim/issues/417) ([a32bc89](https://github.com/folke/noice.nvim/commit/a32bc892aadb26668fd0161962ae4eccb1bf5854))
|
||||
|
||||
## [1.11.0](https://github.com/folke/noice.nvim/compare/v1.10.2...v1.11.0) (2023-04-16)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **lsp:** added config.lsp.hover.silent. Fixes [#412](https://github.com/folke/noice.nvim/issues/412) ([e2a53cf](https://github.com/folke/noice.nvim/commit/e2a53cf946d88d87cd0123711afce5ddad047b7b))
|
||||
* **signature:** added signature param docs. Fixes [#421](https://github.com/folke/noice.nvim/issues/421) ([e76ae13](https://github.com/folke/noice.nvim/commit/e76ae13dd272dc23d0154b93172d445aeabad8f1))
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **confirm:** keep newlines in confirm message. Fixes [#422](https://github.com/folke/noice.nvim/issues/422) ([051111f](https://github.com/folke/noice.nvim/commit/051111f98d7128c833eaa32423426829981b2aa3))
|
||||
* **markdown:** replace `<code>`. Fixes [#424](https://github.com/folke/noice.nvim/issues/424) ([38fb652](https://github.com/folke/noice.nvim/commit/38fb652d0a95780d20a551a6ec44b01226476c99))
|
||||
* **markdown:** revert ([d767be9](https://github.com/folke/noice.nvim/commit/d767be960e8660b19595ccff2dad6abd7aae2d4a))
|
||||
|
||||
## [1.10.2](https://github.com/folke/noice.nvim/compare/v1.10.1...v1.10.2) (2023-03-26)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **icons:** removed all obsolete icons thanks to nerdfix ([cf6a194](https://github.com/folke/noice.nvim/commit/cf6a194f9280cda1fdcc36d271fccd4a24082df3))
|
||||
|
||||
## [1.10.1](https://github.com/folke/noice.nvim/compare/v1.10.0...v1.10.1) (2023-03-24)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **treesitter:** deprecated call. Fixes [#408](https://github.com/folke/noice.nvim/issues/408) ([1ded575](https://github.com/folke/noice.nvim/commit/1ded575928752861558a729fcbbd1e6e53c76652))
|
||||
|
||||
## [1.10.0](https://github.com/folke/noice.nvim/compare/v1.9.5...v1.10.0) (2023-03-23)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **cmdline:** added cmdline support for `:lua=` and `:=` ([acfa513](https://github.com/folke/noice.nvim/commit/acfa5133da31a35ec24fca0757ad1c85edc4c585))
|
||||
|
||||
## [1.9.5](https://github.com/folke/noice.nvim/compare/v1.9.4...v1.9.5) (2023-03-19)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **views:** dont highlight CurSearch for some views. Fixes [#399](https://github.com/folke/noice.nvim/issues/399) ([0c493e5](https://github.com/folke/noice.nvim/commit/0c493e5d243c39adf3d6ce7683a16e610cc44e0a))
|
||||
|
||||
## [1.9.4](https://github.com/folke/noice.nvim/compare/v1.9.3...v1.9.4) (2023-03-15)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **markdown:** better check to see if a ts parser is available. Fixes [#397](https://github.com/folke/noice.nvim/issues/397) ([d60bee1](https://github.com/folke/noice.nvim/commit/d60bee1b85af1882768af80385bc2500d495feba))
|
||||
* **markdown:** strip "\r" chars ([4d2801b](https://github.com/folke/noice.nvim/commit/4d2801babc4026229c58f0c77a20ff5b7b4c0d07))
|
||||
|
||||
## [1.9.3](https://github.com/folke/noice.nvim/compare/v1.9.2...v1.9.3) (2023-03-14)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **cmdline:** dont use normal commands so ModeChanged will trigger correctly. Fixes [#390](https://github.com/folke/noice.nvim/issues/390) ([fa7b6a1](https://github.com/folke/noice.nvim/commit/fa7b6a18c5cdc23961038bc56b93495efcd0f5c7))
|
||||
|
||||
## [1.9.2](https://github.com/folke/noice.nvim/compare/v1.9.1...v1.9.2) (2023-03-12)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **cmdline:** make sure cursor is always visible ([2f0a427](https://github.com/folke/noice.nvim/commit/2f0a42701b4aa65b55fff8f32878d9adc7e7ac77))
|
||||
* **config:** allow overriding options set by presets ([5a1bf17](https://github.com/folke/noice.nvim/commit/5a1bf1707f592fefff4cb3da903b17369e088cc1))
|
||||
* **config:** correctly set the presets ([e5cb84f](https://github.com/folke/noice.nvim/commit/e5cb84f1ed524f850fa92e3a256e830ed07fadee))
|
||||
|
||||
## [1.9.1](https://github.com/folke/noice.nvim/compare/v1.9.0...v1.9.1) (2023-03-03)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **health:** correctly check if lsp.message is enabled ([#381](https://github.com/folke/noice.nvim/issues/381)) ([1ff6b10](https://github.com/folke/noice.nvim/commit/1ff6b10471590331cc1585ad64f084f19cd4bcb7))
|
||||
|
||||
## [1.9.0](https://github.com/folke/noice.nvim/compare/v1.8.3...v1.9.0) (2023-03-03)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **lsp:** fallback to buffer filetype for code blocks without lang. Fixes [#378](https://github.com/folke/noice.nvim/issues/378) ([cab2c80](https://github.com/folke/noice.nvim/commit/cab2c80497388735c9795f496a36e76bc5c7c4bf))
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **treesitter:** use the new treesitter ft to lang API if availble. Fixes [#378](https://github.com/folke/noice.nvim/issues/378) ([36d141b](https://github.com/folke/noice.nvim/commit/36d141bd5852b10e32058e259982182b9e5e8060))
|
||||
|
||||
## [1.8.3](https://github.com/folke/noice.nvim/compare/v1.8.2...v1.8.3) (2023-03-02)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **notify:** take col offsets into account for nvim-notify renderers. Fixes [#375](https://github.com/folke/noice.nvim/issues/375) ([20596d9](https://github.com/folke/noice.nvim/commit/20596d96551605f7462f5722198b188e4047b605))
|
||||
|
||||
## [1.8.2](https://github.com/folke/noice.nvim/compare/v1.8.1...v1.8.2) (2023-02-07)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **signature:** when loading, attach to existing lsp clients. Fixes [#342](https://github.com/folke/noice.nvim/issues/342) ([f69f1a5](https://github.com/folke/noice.nvim/commit/f69f1a577615a5a6527f133df0aa40e596bd1707))
|
||||
|
||||
## [1.8.1](https://github.com/folke/noice.nvim/compare/v1.8.0...v1.8.1) (2023-02-06)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **ui:** cmdline is always blocking. Fixes [#347](https://github.com/folke/noice.nvim/issues/347) ([6702d97](https://github.com/folke/noice.nvim/commit/6702d97d3c37c3a363ffc7c890578109f82f9f20))
|
||||
|
||||
## [1.8.0](https://github.com/folke/noice.nvim/compare/v1.7.1...v1.8.0) (2023-01-24)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* added deactivate ([bf216e0](https://github.com/folke/noice.nvim/commit/bf216e017979f8be712b1ada62736a58e75b0fe3))
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* Allow mapping <esc> ([#329](https://github.com/folke/noice.nvim/issues/329)) ([b7e9054](https://github.com/folke/noice.nvim/commit/b7e9054b02b5958db8bb5ad7675e92bfb5a8e903))
|
||||
|
||||
## [1.7.1](https://github.com/folke/noice.nvim/compare/v1.7.0...v1.7.1) (2023-01-23)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **nui:** make sure nui recreates buffer and window when needed ([3e6dfd8](https://github.com/folke/noice.nvim/commit/3e6dfd8bb00d98399704a020ab7892234ce80fdb))
|
||||
* **nui:** mount if buffer is no longer valid ([71d7b5c](https://github.com/folke/noice.nvim/commit/71d7b5cf8f24b9bdc425934c36cfda784fcd10f2))
|
||||
* **nui:** set mounted=false if buffer is no longer valid ([3353a7a](https://github.com/folke/noice.nvim/commit/3353a7ab4bae6c22f61fd646c10e336b4582f0ea))
|
||||
|
||||
|
||||
### Performance Improvements
|
||||
|
||||
* make noice a bit more robust when exiting to prevent possible delays on exit ([35e3664](https://github.com/folke/noice.nvim/commit/35e3664297096d8e24ca17f590bc793482f5182d))
|
||||
|
||||
## [1.7.0](https://github.com/folke/noice.nvim/compare/v1.6.2...v1.7.0) (2023-01-14)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **ui:** added hybrid messages functionality, but not needed for now ([addc0a2](https://github.com/folke/noice.nvim/commit/addc0a2521ce666a1f546f9a04574a63a858c6a5))
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **swap:** additionally check for updates when a swap file was found ([1165d3e](https://github.com/folke/noice.nvim/commit/1165d3e727bdd226eefffcc801d563bcb30e71c4))
|
||||
* **ui:** work-around for segfaults in TUI. Fixes [#298](https://github.com/folke/noice.nvim/issues/298) ([176ec31](https://github.com/folke/noice.nvim/commit/176ec31026ec4baf64638fba1a180701257380f1))
|
||||
|
||||
## [1.6.2](https://github.com/folke/noice.nvim/compare/v1.6.1...v1.6.2) (2023-01-13)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **ui_attach:** dont update router during `ext_messages` and disable/enable Noice during confirm. [#298](https://github.com/folke/noice.nvim/issues/298) ([a4cbc0f](https://github.com/folke/noice.nvim/commit/a4cbc0f0cebdaa9529a749f4463aedc5a2cdcf1b))
|
||||
|
||||
## [1.6.1](https://github.com/folke/noice.nvim/compare/v1.6.0...v1.6.1) (2023-01-10)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* show unstable message after loading noice ([2613a16](https://github.com/folke/noice.nvim/commit/2613a16b5009acbf2adabb34b029b1c4c57101e3))
|
||||
|
||||
## [1.6.0](https://github.com/folke/noice.nvim/compare/v1.5.2...v1.6.0) (2023-01-10)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* show warning when running with TUI rework ([cf2231b](https://github.com/folke/noice.nvim/commit/cf2231bfb691b3b58d2685f48da11596cec1cfa3))
|
||||
|
||||
## [1.5.2](https://github.com/folke/noice.nvim/compare/v1.5.1...v1.5.2) (2023-01-01)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **treesitter:** only disable injections for php and html ([0e1bf11](https://github.com/folke/noice.nvim/commit/0e1bf11d46054b8ab04eb62b53c5ac81b44f14df))
|
||||
|
||||
## [1.5.1](https://github.com/folke/noice.nvim/compare/v1.5.0...v1.5.1) (2022-12-31)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* dont error in checkhealth if nvim-treesitter is not installed ([044767a](https://github.com/folke/noice.nvim/commit/044767a01d38208c32d97b0214cce66c41e8f7c8))
|
||||
* **health:** dont use nvim-treesitter to check if a lang exists ([585d24e](https://github.com/folke/noice.nvim/commit/585d24ec6e3fb4288414f864cfe2de7d025e8216))
|
||||
* **notify_send:** properly close file descriptors from spwaning notifysend ([f5132fa](https://github.com/folke/noice.nvim/commit/f5132fa6eb71e96d9f0cd7148b186b324b142d15))
|
||||
* **nui:** dont trigger autocmds when doing zt ([d176765](https://github.com/folke/noice.nvim/commit/d176765ceabae9a12bf09a5c785d3dcb3859e1b6))
|
||||
* **popupmenu:** replace any newlines by space. Fixes [#265](https://github.com/folke/noice.nvim/issues/265) ([5199089](https://github.com/folke/noice.nvim/commit/51990892e1dd5ee1a1444b1cf3ccf0aca377e0c4))
|
||||
* **treesitter:** dont allow recursive injections. Fixes [#286](https://github.com/folke/noice.nvim/issues/286) ([a31b41a](https://github.com/folke/noice.nvim/commit/a31b41a739731988fc30a48a3099586a884bdf61))
|
||||
|
||||
## [1.5.0](https://github.com/folke/noice.nvim/compare/v1.4.2...v1.5.0) (2022-12-21)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* added `Filter.cond` to conditionally use a route ([29a2e05](https://github.com/folke/noice.nvim/commit/29a2e052d2653443716a8eece89300e9b36b5f2a))
|
||||
* **format:** allow `config.format.level.icons` to be false. Fixes [#274](https://github.com/folke/noice.nvim/issues/274) ([aa68eb6](https://github.com/folke/noice.nvim/commit/aa68eb6f83c48df41bab8ae36623e5af3f224c66))
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* correctly apply padding based on four numbers ([c9c1fbd](https://github.com/folke/noice.nvim/commit/c9c1fbd605388badcfa62c0b7f58d184f19e1484))
|
||||
* **nui:** removed work-around for padding and border style shadow ([4f34d33](https://github.com/folke/noice.nvim/commit/4f34d33fc3dc0d6f4da9b4b8c63b9714fd4eea79))
|
||||
|
||||
## [1.4.2](https://github.com/folke/noice.nvim/compare/v1.4.1...v1.4.2) (2022-12-16)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **debug:** calculate stacktrace outisde of vim schedule to make it useful ([a5de1ca](https://github.com/folke/noice.nvim/commit/a5de1ca0eaecd21fd33a0a191d1a0b9dd97cb54a))
|
||||
* **debug:** only concat debug info that is a string ([78ec5c6](https://github.com/folke/noice.nvim/commit/78ec5c6eefb9b61056a8545ded33b99f7a9a9f72))
|
||||
* **nui:** remove border text when style is `nil`, `"none"`, or `"shadow"` ([d85a4d0](https://github.com/folke/noice.nvim/commit/d85a4d01774b5649dbcda8526a26f201dff5ade4))
|
||||
* **nui:** remove padding when border is `shadow` ([1515007](https://github.com/folke/noice.nvim/commit/151500759722c12fb6a3931c5243d68f01af007a))
|
||||
|
||||
## [1.4.1](https://github.com/folke/noice.nvim/compare/v1.4.0...v1.4.1) (2022-12-03)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* scrollbar destructs itself, so make a copy to see if there are any remnants left ([8d80a69](https://github.com/folke/noice.nvim/commit/8d80a692d5a045a3ec995536782f2b4c2b8d901b))
|
||||
* stop processing messages when Neovim is exiting. Fixes [#237](https://github.com/folke/noice.nvim/issues/237) ([8c8acf7](https://github.com/folke/noice.nvim/commit/8c8acf74c09374e48a8fa1835560c3913d57243f))
|
||||
|
||||
## [1.4.0](https://github.com/folke/noice.nvim/compare/v1.3.1...v1.4.0) (2022-12-03)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* added support for <pre>{lang} code blocks used in the Neovim codebase ([de48a45](https://github.com/folke/noice.nvim/commit/de48a4528aad5c7b50cf4b4ec1b419762a95934d))
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* check if loader returned a function before loading ([66946c7](https://github.com/folke/noice.nvim/commit/66946c72f0a36f37e480b5eae97aac3cdcd5961d))
|
||||
* reset preloader before trying to load the module ([08655e9](https://github.com/folke/noice.nvim/commit/08655e9f1bed638f9871d76b05928da74d1eeb68))
|
||||
|
||||
## [1.3.1](https://github.com/folke/noice.nvim/compare/v1.3.0...v1.3.1) (2022-12-01)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* dont error if cmp not loaded when overriding ([4bae487](https://github.com/folke/noice.nvim/commit/4bae48798424d300e204cce2eb73b087854472d5))
|
||||
* wait to override cmp till it loaded ([712180f](https://github.com/folke/noice.nvim/commit/712180f94684b7ce56957df60d037c81784e69c3))
|
||||
201
config/neovim/store/lazy-plugins/noice.nvim/LICENSE
Normal file
201
config/neovim/store/lazy-plugins/noice.nvim/LICENSE
Normal file
@ -0,0 +1,201 @@
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
813
config/neovim/store/lazy-plugins/noice.nvim/README.md
Normal file
813
config/neovim/store/lazy-plugins/noice.nvim/README.md
Normal file
@ -0,0 +1,813 @@
|
||||
# 💥 Noice _(Nice, Noise, Notice)_
|
||||
|
||||
Highly experimental plugin that completely replaces the UI for `messages`, `cmdline` and the `popupmenu`.
|
||||
|
||||

|
||||
|
||||
## ✨ Features
|
||||
|
||||
- 🌅 fully **configurable views** like [nvim-notify](https://github.com/rcarriga/nvim-notify),
|
||||
splits, popups, virtual text, ..
|
||||
- 🔍 use **filters** to **route messages** to different views
|
||||
- 🌈 message **highlights** are preserved in the views (like the colors of `:hi`)
|
||||
- 📝 command output like [:messages](https://neovim.io/doc/user/message.html#:messages)
|
||||
is shown in normal buffers, which makes it much easier to work with
|
||||
- 📚 `:Noice` command to show a full message history
|
||||
- ⌨️ no more [:h more-prompt](https://neovim.io/doc/user/message.html#more-prompt)
|
||||
- 💻 fully customizable **cmdline** with icons
|
||||
- 💅 **syntax highlighting** for `vim` and `lua` on the **cmdline**
|
||||
- 🚥 **statusline** components
|
||||
- 🔭 open message history in [telescope.nvim](https://github.com/nvim-telescope/telescope.nvim)
|
||||
|
||||
## 🔥 Status
|
||||
|
||||
**Noice** is using the new experimental `vim.ui_attach` API, so issues are to be expected.
|
||||
It is highly recommended to use Neovim nightly, since a bunch of issues have already been fixed upstream.
|
||||
Check this [tracking issue](https://github.com/folke/noice.nvim/issues/6) for a list of known issues.
|
||||
|
||||
## ⚡️ Requirements
|
||||
|
||||
- Neovim >= 0.9.0 **_(nightly highly recommended)_**
|
||||
- [nui.nvim](https://github.com/MunifTanjim/nui.nvim): used for proper rendering and multiple views
|
||||
- [nvim-notify](https://github.com/rcarriga/nvim-notify): notification view _**(optional)**_
|
||||
- a [Nerd Font](https://www.nerdfonts.com/) **_(optional)_**
|
||||
- [nvim-treesitter](https://github.com/nvim-treesitter/nvim-treesitter/) **_(optional, but highly recommended)_**
|
||||
used for highlighting the cmdline and lsp docs. Make sure to install the parsers for
|
||||
`vim`, `regex`, `lua`, `bash`, `markdown` and `markdown_inline`
|
||||
|
||||
## 📦 Installation
|
||||
|
||||
Install the plugin with your preferred package manager:
|
||||
|
||||
```lua
|
||||
-- lazy.nvim
|
||||
{
|
||||
"folke/noice.nvim",
|
||||
event = "VeryLazy",
|
||||
opts = {
|
||||
-- add any options here
|
||||
},
|
||||
dependencies = {
|
||||
-- if you lazy-load any plugin below, make sure to add proper `module="..."` entries
|
||||
"MunifTanjim/nui.nvim",
|
||||
-- OPTIONAL:
|
||||
-- `nvim-notify` is only needed, if you want to use the notification view.
|
||||
-- If not available, we use `mini` as the fallback
|
||||
"rcarriga/nvim-notify",
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Suggested setup:
|
||||
|
||||
```lua
|
||||
require("noice").setup({
|
||||
lsp = {
|
||||
-- override markdown rendering so that **cmp** and other plugins use **Treesitter**
|
||||
override = {
|
||||
["vim.lsp.util.convert_input_to_markdown_lines"] = true,
|
||||
["vim.lsp.util.stylize_markdown"] = true,
|
||||
["cmp.entry.get_documentation"] = true, -- requires hrsh7th/nvim-cmp
|
||||
},
|
||||
},
|
||||
-- you can enable a preset for easier configuration
|
||||
presets = {
|
||||
bottom_search = true, -- use a classic bottom cmdline for search
|
||||
command_palette = true, -- position the cmdline and popupmenu together
|
||||
long_message_to_split = true, -- long messages will be sent to a split
|
||||
inc_rename = false, -- enables an input dialog for inc-rename.nvim
|
||||
lsp_doc_border = false, -- add a border to hover docs and signature help
|
||||
},
|
||||
})
|
||||
```
|
||||
|
||||
It's a good idea to run `:checkhealth noice` after installing to check for common issues.
|
||||
|
||||
<details><summary>vim-plug</summary>
|
||||
|
||||
```vim
|
||||
" vim-plug
|
||||
call plug#begin()
|
||||
Plug 'folke/noice.nvim'
|
||||
Plug 'MunifTanjim/nui.nvim'
|
||||
call plug#end()
|
||||
|
||||
lua require("noice").setup()
|
||||
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
## ⚙️ Configuration
|
||||
|
||||
**noice.nvim** comes with the following defaults:
|
||||
|
||||
Check the [wiki](https://github.com/folke/noice.nvim/wiki/Configuration-Recipes) for configuration recipes.
|
||||
|
||||
```lua
|
||||
{
|
||||
cmdline = {
|
||||
enabled = true, -- enables the Noice cmdline UI
|
||||
view = "cmdline_popup", -- view for rendering the cmdline. Change to `cmdline` to get a classic cmdline at the bottom
|
||||
opts = {}, -- global options for the cmdline. See section on views
|
||||
---@type table<string, CmdlineFormat>
|
||||
format = {
|
||||
-- conceal: (default=true) This will hide the text in the cmdline that matches the pattern.
|
||||
-- view: (default is cmdline view)
|
||||
-- opts: any options passed to the view
|
||||
-- icon_hl_group: optional hl_group for the icon
|
||||
-- title: set to anything or empty string to hide
|
||||
cmdline = { pattern = "^:", icon = "", lang = "vim" },
|
||||
search_down = { kind = "search", pattern = "^/", icon = " ", lang = "regex" },
|
||||
search_up = { kind = "search", pattern = "^%?", icon = " ", lang = "regex" },
|
||||
filter = { pattern = "^:%s*!", icon = "$", lang = "bash" },
|
||||
lua = { pattern = { "^:%s*lua%s+", "^:%s*lua%s*=%s*", "^:%s*=%s*" }, icon = "", lang = "lua" },
|
||||
help = { pattern = "^:%s*he?l?p?%s+", icon = "" },
|
||||
input = {}, -- Used by input()
|
||||
-- lua = false, -- to disable a format, set to `false`
|
||||
},
|
||||
},
|
||||
messages = {
|
||||
-- NOTE: If you enable messages, then the cmdline is enabled automatically.
|
||||
-- This is a current Neovim limitation.
|
||||
enabled = true, -- enables the Noice messages UI
|
||||
view = "notify", -- default view for messages
|
||||
view_error = "notify", -- view for errors
|
||||
view_warn = "notify", -- view for warnings
|
||||
view_history = "messages", -- view for :messages
|
||||
view_search = "virtualtext", -- view for search count messages. Set to `false` to disable
|
||||
},
|
||||
popupmenu = {
|
||||
enabled = true, -- enables the Noice popupmenu UI
|
||||
---@type 'nui'|'cmp'
|
||||
backend = "nui", -- backend to use to show regular cmdline completions
|
||||
---@type NoicePopupmenuItemKind|false
|
||||
-- Icons for completion item kinds (see defaults at noice.config.icons.kinds)
|
||||
kind_icons = {}, -- set to `false` to disable icons
|
||||
},
|
||||
-- default options for require('noice').redirect
|
||||
-- see the section on Command Redirection
|
||||
---@type NoiceRouteConfig
|
||||
redirect = {
|
||||
view = "popup",
|
||||
filter = { event = "msg_show" },
|
||||
},
|
||||
-- You can add any custom commands below that will be available with `:Noice command`
|
||||
---@type table<string, NoiceCommand>
|
||||
commands = {
|
||||
history = {
|
||||
-- options for the message history that you get with `:Noice`
|
||||
view = "split",
|
||||
opts = { enter = true, format = "details" },
|
||||
filter = {
|
||||
any = {
|
||||
{ event = "notify" },
|
||||
{ error = true },
|
||||
{ warning = true },
|
||||
{ event = "msg_show", kind = { "" } },
|
||||
{ event = "lsp", kind = "message" },
|
||||
},
|
||||
},
|
||||
},
|
||||
-- :Noice last
|
||||
last = {
|
||||
view = "popup",
|
||||
opts = { enter = true, format = "details" },
|
||||
filter = {
|
||||
any = {
|
||||
{ event = "notify" },
|
||||
{ error = true },
|
||||
{ warning = true },
|
||||
{ event = "msg_show", kind = { "" } },
|
||||
{ event = "lsp", kind = "message" },
|
||||
},
|
||||
},
|
||||
filter_opts = { count = 1 },
|
||||
},
|
||||
-- :Noice errors
|
||||
errors = {
|
||||
-- options for the message history that you get with `:Noice`
|
||||
view = "popup",
|
||||
opts = { enter = true, format = "details" },
|
||||
filter = { error = true },
|
||||
filter_opts = { reverse = true },
|
||||
},
|
||||
all = {
|
||||
-- options for the message history that you get with `:Noice`
|
||||
view = "split",
|
||||
opts = { enter = true, format = "details" },
|
||||
filter = {},
|
||||
},
|
||||
},
|
||||
notify = {
|
||||
-- Noice can be used as `vim.notify` so you can route any notification like other messages
|
||||
-- Notification messages have their level and other properties set.
|
||||
-- event is always "notify" and kind can be any log level as a string
|
||||
-- The default routes will forward notifications to nvim-notify
|
||||
-- Benefit of using Noice for this is the routing and consistent history view
|
||||
enabled = true,
|
||||
view = "notify",
|
||||
},
|
||||
lsp = {
|
||||
progress = {
|
||||
enabled = true,
|
||||
-- Lsp Progress is formatted using the builtins for lsp_progress. See config.format.builtin
|
||||
-- See the section on formatting for more details on how to customize.
|
||||
--- @type NoiceFormat|string
|
||||
format = "lsp_progress",
|
||||
--- @type NoiceFormat|string
|
||||
format_done = "lsp_progress_done",
|
||||
throttle = 1000 / 30, -- frequency to update lsp progress message
|
||||
view = "mini",
|
||||
},
|
||||
override = {
|
||||
-- override the default lsp markdown formatter with Noice
|
||||
["vim.lsp.util.convert_input_to_markdown_lines"] = false,
|
||||
-- override the lsp markdown formatter with Noice
|
||||
["vim.lsp.util.stylize_markdown"] = false,
|
||||
-- override cmp documentation with Noice (needs the other options to work)
|
||||
["cmp.entry.get_documentation"] = false,
|
||||
},
|
||||
hover = {
|
||||
enabled = true,
|
||||
silent = false, -- set to true to not show a message if hover is not available
|
||||
view = nil, -- when nil, use defaults from documentation
|
||||
---@type NoiceViewOptions
|
||||
opts = {}, -- merged with defaults from documentation
|
||||
},
|
||||
signature = {
|
||||
enabled = true,
|
||||
auto_open = {
|
||||
enabled = true,
|
||||
trigger = true, -- Automatically show signature help when typing a trigger character from the LSP
|
||||
luasnip = true, -- Will open signature help when jumping to Luasnip insert nodes
|
||||
throttle = 50, -- Debounce lsp signature help request by 50ms
|
||||
},
|
||||
view = nil, -- when nil, use defaults from documentation
|
||||
---@type NoiceViewOptions
|
||||
opts = {}, -- merged with defaults from documentation
|
||||
},
|
||||
message = {
|
||||
-- Messages shown by lsp servers
|
||||
enabled = true,
|
||||
view = "notify",
|
||||
opts = {},
|
||||
},
|
||||
-- defaults for hover and signature help
|
||||
documentation = {
|
||||
view = "hover",
|
||||
---@type NoiceViewOptions
|
||||
opts = {
|
||||
lang = "markdown",
|
||||
replace = true,
|
||||
render = "plain",
|
||||
format = { "{message}" },
|
||||
win_options = { concealcursor = "n", conceallevel = 3 },
|
||||
},
|
||||
},
|
||||
},
|
||||
markdown = {
|
||||
hover = {
|
||||
["|(%S-)|"] = vim.cmd.help, -- vim help links
|
||||
["%[.-%]%((%S-)%)"] = require("noice.util").open, -- markdown links
|
||||
},
|
||||
highlights = {
|
||||
["|%S-|"] = "@text.reference",
|
||||
["@%S+"] = "@parameter",
|
||||
["^%s*(Parameters:)"] = "@text.title",
|
||||
["^%s*(Return:)"] = "@text.title",
|
||||
["^%s*(See also:)"] = "@text.title",
|
||||
["{%S-}"] = "@parameter",
|
||||
},
|
||||
},
|
||||
health = {
|
||||
checker = true, -- Disable if you don't want health checks to run
|
||||
},
|
||||
smart_move = {
|
||||
-- noice tries to move out of the way of existing floating windows.
|
||||
enabled = true, -- you can disable this behaviour here
|
||||
-- add any filetypes here, that shouldn't trigger smart move.
|
||||
excluded_filetypes = { "cmp_menu", "cmp_docs", "notify" },
|
||||
},
|
||||
---@type NoicePresets
|
||||
presets = {
|
||||
-- you can enable a preset by setting it to true, or a table that will override the preset config
|
||||
-- you can also add custom presets that you can enable/disable with enabled=true
|
||||
bottom_search = false, -- use a classic bottom cmdline for search
|
||||
command_palette = false, -- position the cmdline and popupmenu together
|
||||
long_message_to_split = false, -- long messages will be sent to a split
|
||||
inc_rename = false, -- enables an input dialog for inc-rename.nvim
|
||||
lsp_doc_border = false, -- add a border to hover docs and signature help
|
||||
},
|
||||
throttle = 1000 / 30, -- how frequently does Noice need to check for ui updates? This has no effect when in blocking mode.
|
||||
---@type NoiceConfigViews
|
||||
views = {}, ---@see section on views
|
||||
---@type NoiceRouteConfig[]
|
||||
routes = {}, --- @see section on routes
|
||||
---@type table<string, NoiceFilter>
|
||||
status = {}, --- @see section on statusline components
|
||||
---@type NoiceFormatOptions
|
||||
format = {}, --- @see section on formatting
|
||||
}
|
||||
```
|
||||
|
||||
<details>
|
||||
<summary>If you don't want to use a Nerd Font, you can replace the icons with Unicode symbols.</summary>
|
||||
|
||||
```lua
|
||||
require("noice").setup({
|
||||
cmdline = {
|
||||
format = {
|
||||
cmdline = { icon = ">" },
|
||||
search_down = { icon = "🔍⌄" },
|
||||
search_up = { icon = "🔍⌃" },
|
||||
filter = { icon = "$" },
|
||||
lua = { icon = "☾" },
|
||||
help = { icon = "?" },
|
||||
},
|
||||
},
|
||||
format = {
|
||||
level = {
|
||||
icons = {
|
||||
error = "✖",
|
||||
warn = "▼",
|
||||
info = "●",
|
||||
},
|
||||
},
|
||||
},
|
||||
popupmenu = {
|
||||
kind_icons = false,
|
||||
},
|
||||
inc_rename = {
|
||||
cmdline = {
|
||||
format = {
|
||||
IncRename = { icon = "⟳" },
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
## 🔍 Filters
|
||||
|
||||
**Noice** uses filters to route messages to specific views.
|
||||
|
||||
| Name | Type | Description |
|
||||
| -------------- | ---------------------- | ------------------------------------------------------------------------------------------------------------------------ |
|
||||
| **any** | `filter[]` | checks that at least one of the filters matches |
|
||||
| **blocking** | `boolean` | are we in blocking mode? |
|
||||
| **cleared** | `boolean` | checks if the message is cleared, meaning it's in the history |
|
||||
| **cmdline** | `boolean` or `string` | checks if the message was generated by executing a cmdline. When `string`, then it is used as a pattern |
|
||||
| **error** | `boolean` | all error-like kinds from `ext_messages` |
|
||||
| **event** | `string` or `string[]` | any of the events from `ext_messages` or `cmdline`. See [:h ui-messages](https://neovim.io/doc/user/ui.html#ui-messages) |
|
||||
| **find** | `string` | uses lua `string.find` to match the pattern |
|
||||
| **has** | `boolean` | checks if the message is exists, meaning it's in the history |
|
||||
| **kind** | `string` or `string[]` | any of the kinds from `ext_messages`. See [:h ui-messages](https://neovim.io/doc/user/ui.html#ui-messages) |
|
||||
| **max_height** | `number` | maximum height of the message |
|
||||
| **max_length** | `number` | maximum length of the message (total width of all the lines) |
|
||||
| **max_width** | `number` | maximum width of the message |
|
||||
| **min_height** | `number` | minimum height of the message |
|
||||
| **min_length** | `number` | minimum length of the message (total width of all the lines) |
|
||||
| **min_width** | `number` | minimum width of the message |
|
||||
| **mode** | `string` | checks if `vim.api.nvim_get_mode()` contains the given mode |
|
||||
| **not** | `filter` | checks whether the filter matches or not |
|
||||
| **warning** | `boolean` | all warning-like kinds from `ext_messages` |
|
||||
|
||||
<details>
|
||||
<summary>Example:</summary>
|
||||
|
||||
```lua
|
||||
-- all messages over 10 lines, excluding echo and search_count
|
||||
local filter = {
|
||||
event = "msg_show",
|
||||
min_height = 10,
|
||||
["not"] = { kind = { "search_count", "echo" } },
|
||||
}
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
## 🌅 Views
|
||||
|
||||
**Noice** comes with the following built-in backends:
|
||||
|
||||
- **popup**: powered by [nui.nvim](https://github.com/MunifTanjim/nui.nvim)
|
||||
- **split**: powered by [nui.nvim](https://github.com/MunifTanjim/nui.nvim)
|
||||
- **notify**: powered by [nvim-notify](https://github.com/rcarriga/nvim-notify)
|
||||
- **virtualtext**: shows the message as virtualtext (for example for `search_count`)
|
||||
- **mini**: similar to [notifier.nvim](https://github.com/vigoux/notifier.nvim) & [fidget.nvim](https://github.com/j-hui/fidget.nvim)
|
||||
- **notify_send**: generate a desktop notification
|
||||
|
||||
A **View** (`config.views`) is a combination of a `backend` and options.
|
||||
**Noice** comes with the following built-in views with sane defaults:
|
||||
|
||||
| View | Backend | Description |
|
||||
| ------------------ | ---------- | ---------------------------------------------------------------------------------- |
|
||||
| **notify** | `notify` | _nvim-notify_ with `level=nil`, `replace=false`, `merge=false` |
|
||||
| **split** | `split` | horizontal split |
|
||||
| **vsplit** | `split` | vertical split |
|
||||
| **popup** | `popup` | simple popup |
|
||||
| **mini** | `mini` | minimal view, by default bottom right, right-aligned |
|
||||
| **cmdline** | `popup` | bottom line, similar to the classic cmdline |
|
||||
| **cmdline_popup** | `popup` | fancy cmdline popup, with different styles according to the cmdline mode |
|
||||
| **cmdline_output** | `split` | split used by `config.presets.cmdline_output_to_split` |
|
||||
| **messages** | `split` | split used for `:messages` |
|
||||
| **confirm** | `popup` | popup used for `confirm` events |
|
||||
| **hover** | `popup` | popup used for lsp signature help and hover |
|
||||
| **popupmenu** | `nui.menu` | special view with the options used to render the popupmenu when backend is **nui** |
|
||||
|
||||
Please refer to [noice.config.views](https://github.com/folke/noice.nvim/blob/main/lua/noice/config/views.lua)
|
||||
to see the options.
|
||||
Any options passed to existing views in `config.views`, will override those options only.
|
||||
You can configure completely new views and use them in custom routes.
|
||||
|
||||
<details>
|
||||
<summary>Example:</summary>
|
||||
|
||||
```lua
|
||||
-- override the default split view to always enter the split when it opens
|
||||
require("noice").setup({
|
||||
views = {
|
||||
split = {
|
||||
enter = true,
|
||||
},
|
||||
},
|
||||
})
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
> All built-in Noice views have the filetype `noice`
|
||||
|
||||
### Nui Options
|
||||
|
||||
See the Nui documentation for [Popup](https://github.com/MunifTanjim/nui.nvim/tree/main/lua/nui/popup)
|
||||
and [Split](https://github.com/MunifTanjim/nui.nvim/tree/main/lua/nui/split).
|
||||
|
||||
<table>
|
||||
<tr><td>Option</td><td>Description</td></tr>
|
||||
<tr>
|
||||
<td> <b>size, position</b> </td>
|
||||
<td>Size, position and their constituents can additionally be specified as <b>"auto"</b>, to use the message height and width.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><b>win_options.winhighlight</b></td>
|
||||
<td>
|
||||
String or can also be a table like:
|
||||
|
||||
```lua
|
||||
{
|
||||
win_options = {
|
||||
winhighlight = {
|
||||
Normal = "NormalFloat",
|
||||
FloatBorder = "FloatBorder"
|
||||
},
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
<td> <b>scrollbar</b> </td>
|
||||
<td>Set to <code>false</code> to hide the scrollbar.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
</table>
|
||||
|
||||
### Notify Options
|
||||
|
||||
| Option | Type | Default | Description |
|
||||
| ----------- | ---------------- | ---------------- | --------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| **title** | `string` | `"Notification"` | title to be used for the notification. Uses `Message.title` if available. |
|
||||
| **replace** | `boolean` | `false` | when true, messages routing to the same notify instance will replace existing messages instead of pushing a new notification every time |
|
||||
| **merge** | `boolean` | `false` | Merge messages into one Notification or create separate notifications |
|
||||
| **level** | `number\|string` | `nil` | notification level. Uses `Message.level` if available. |
|
||||
|
||||
### Virtual Text Options
|
||||
|
||||
Right now there's only an option to set the `hl_group` used to render the virtual text.
|
||||
|
||||
## 🎨 Formatting
|
||||
|
||||
Formatting options can be specified with `config.format`.
|
||||
For a list of the defaults, please refer to [config.format](https://github.com/folke/noice.nvim/blob/main/lua/noice/config/format.lua)
|
||||
|
||||
**Noice** includes the following formatters:
|
||||
|
||||
- **level**: message level with optional `icon` and `hl_group` per level
|
||||
- **text**: any text with optional `hl_group`
|
||||
- **title**: message title with optional `hl_group`
|
||||
- **event**: message event with optional `hl_group`
|
||||
- **kind**: message kind with optional `hl_group`
|
||||
- **date**: formatted date with optional date format string
|
||||
- **message**: message content itself with optional `hl_group` to override message highlights
|
||||
- **confirm**: only useful for `confirm` messages. Will format the choices as buttons.
|
||||
- **cmdline**: will render the cmdline in the message that generated the message.
|
||||
- **progress**: progress bar used by lsp progress
|
||||
- **spinner**: spinners used by lsp progress
|
||||
- **data**: render any custom data from `Message.opts`. Useful in combination with the opts passed to `vim.notify`
|
||||
|
||||
Formatters are used in `format` definitions. **Noice** includes the following built-in formats:
|
||||
|
||||
```lua
|
||||
{
|
||||
-- default format
|
||||
default = { "{level} ", "{title} ", "{message}" },
|
||||
-- default format for vim.notify views
|
||||
notify = { "{message}" },
|
||||
-- default format for the history
|
||||
details = {
|
||||
"{level} ",
|
||||
"{date} ",
|
||||
"{event}",
|
||||
{ "{kind}", before = { ".", hl_group = "NoiceFormatKind" } },
|
||||
" ",
|
||||
"{title} ",
|
||||
"{cmdline} ",
|
||||
"{message}",
|
||||
},
|
||||
telescope = ..., -- formatter used to display telescope results
|
||||
telescope_preview = ..., -- formatter used to preview telescope results
|
||||
lsp_progress = ..., -- formatter used by lsp progress
|
||||
lsp_progress_done = ..., -- formatter used by lsp progress
|
||||
}
|
||||
```
|
||||
|
||||
Text before/after the formatter or in the before/after options, will only be rendered if the formatter itself rendered something.
|
||||
|
||||
The `format` view option, can be either a `string` (one of the built-in formats), or a table with a custom format definition.
|
||||
|
||||
To align text, you can use the `align` option for a view. Can be `center`, `left` or `right`.
|
||||
|
||||
## 🚗 Routes
|
||||
|
||||
A **route** has a `filter`, `view` and optional `opts` attribute.
|
||||
|
||||
- **view**: one of the views (built-in or custom)
|
||||
- **filter** a filter for messages matching this route
|
||||
- **opts**: options for the view and the route
|
||||
|
||||
Route options can be any of the view options above, or one of:
|
||||
|
||||
| Option | Type | Default | Description |
|
||||
| -------- | --------- | ------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| **skip** | `boolean` | `false` | messages matching this filter will be skipped and not shown in any views |
|
||||
| **stop** | `boolean` | `true` | When `false` and a route matches the filter, then other routes can still process the message too. Useful if you want certain messages to be shown in multiple views. |
|
||||
|
||||
Please refer to [noice.config.routes](https://github.com/folke/noice.nvim/blob/main/lua/noice/config/routes.lua)
|
||||
for an overview of the default routes.
|
||||
**Routes** passed to `setup()` will be prepended to the default routes.
|
||||
|
||||
<details>
|
||||
<summary>Example</summary>
|
||||
|
||||
```lua
|
||||
-- skip search_count messages instead of showing them as virtual text
|
||||
require("noice").setup({
|
||||
routes = {
|
||||
{
|
||||
filter = { event = "msg_show", kind = "search_count" },
|
||||
opts = { skip = true },
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
-- always route any messages with more than 20 lines to the split view
|
||||
require("noice").setup({
|
||||
routes = {
|
||||
{
|
||||
view = "split",
|
||||
filter = { event = "msg_show", min_height = 20 },
|
||||
},
|
||||
},
|
||||
})
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
## 🚥 Statusline Components
|
||||
|
||||
**Noice** comes with the following statusline components:
|
||||
|
||||
- **ruler**
|
||||
- **message**: last line of the last message (`event=show_msg`)
|
||||
- **command**: `showcmd`
|
||||
- **mode**: `showmode` (@recording messages)
|
||||
- **search**: search count messages
|
||||
|
||||
See [noice.config.status](https://github.com/folke/noice.nvim/blob/main/lua/noice/config/status.lua) for the default config.
|
||||
|
||||
You can add custom statusline components in setup under the `status` key.
|
||||
|
||||
Statusline components have the following methods:
|
||||
|
||||
- **get**: gets the content of the message **without** highlights
|
||||
- **get_hl**: gets the content of the message **with** highlights
|
||||
- **has**: checks if the component is available
|
||||
|
||||
<details>
|
||||
<summary>Example of configuring <a href="https://github.com/nvim-lualine/lualine.nvim">lualine.nvim</a></summary>
|
||||
|
||||
```lua
|
||||
require("lualine").setup({
|
||||
sections = {
|
||||
lualine_x = {
|
||||
{
|
||||
require("noice").api.status.message.get_hl,
|
||||
cond = require("noice").api.status.message.has,
|
||||
},
|
||||
{
|
||||
require("noice").api.status.command.get,
|
||||
cond = require("noice").api.status.command.has,
|
||||
color = { fg = "#ff9e64" },
|
||||
},
|
||||
{
|
||||
require("noice").api.status.mode.get,
|
||||
cond = require("noice").api.status.mode.has,
|
||||
color = { fg = "#ff9e64" },
|
||||
},
|
||||
{
|
||||
require("noice").api.status.search.get,
|
||||
cond = require("noice").api.status.search.has,
|
||||
color = { fg = "#ff9e64" },
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
## 🔭 Telescope
|
||||
|
||||
In order to use **Noice** in **Telescope**, you can either do `:Noice telescope`,
|
||||
or register the extension and use `:Telescope noice`.
|
||||
The results panel is formatted using `config.format.formatters.telescope`. The preview is formatted with `config.format.formatters.telescope_preview`
|
||||
|
||||
```lua
|
||||
require("telescope").load_extension("noice")
|
||||
```
|
||||
|
||||
## 🚀 Usage
|
||||
|
||||
- `:Noice` or `:Noice history` shows the message history
|
||||
- `:Noice last` shows the last message in a popup
|
||||
- `:Noice dismiss` dismiss all visible messages
|
||||
- `:Noice errors` shows the error messages in a split. Last errors on top
|
||||
- `:Noice disable` disables **Noice**
|
||||
- `:Noice enable` enables **Noice**
|
||||
- `:Noice stats` shows debugging stats
|
||||
- `:Noice telescope` opens message history in Telescope
|
||||
|
||||
Alternatively, all commands also exist as a full name like `:NoiceLast`, `:NoiceDisable`.
|
||||
|
||||
You can also use `Lua` equivalents.
|
||||
|
||||
```lua
|
||||
vim.keymap.set("n", "<leader>nl", function()
|
||||
require("noice").cmd("last")
|
||||
end)
|
||||
|
||||
vim.keymap.set("n", "<leader>nh", function()
|
||||
require("noice").cmd("history")
|
||||
end)
|
||||
```
|
||||
|
||||
> You can add custom commands with `config.commands`
|
||||
|
||||
### ↪️ Command Redirection
|
||||
|
||||
Sometimes it's useful to redirect the messages generated by a command or function
|
||||
to a different view. That can be easily achieved with command redirection.
|
||||
|
||||
The redirect API can taken an optional `routes` parameter, which defaults to `{config.redirect}`.
|
||||
|
||||
```lua
|
||||
-- redirect ":hi"
|
||||
require("noice").redirect("hi")
|
||||
|
||||
-- redirect some function
|
||||
require("noice").redirect(function()
|
||||
print("test")
|
||||
end)
|
||||
```
|
||||
|
||||
Adding the following keymap, will redirect the active cmdline when pressing `<S-Enter>`.
|
||||
The cmdline stays open, so you can change the command and execute it again.
|
||||
When exiting the cmdline, the popup window will be focused.
|
||||
|
||||
```lua
|
||||
vim.keymap.set("c", "<S-Enter>", function()
|
||||
require("noice").redirect(vim.fn.getcmdline())
|
||||
end, { desc = "Redirect Cmdline" })
|
||||
```
|
||||
|
||||
### Lsp Hover Doc Scrolling
|
||||
|
||||
```lua
|
||||
vim.keymap.set({ "n", "i", "s" }, "<c-f>", function()
|
||||
if not require("noice.lsp").scroll(4) then
|
||||
return "<c-f>"
|
||||
end
|
||||
end, { silent = true, expr = true })
|
||||
|
||||
vim.keymap.set({ "n", "i", "s" }, "<c-b>", function()
|
||||
if not require("noice.lsp").scroll(-4) then
|
||||
return "<c-b>"
|
||||
end
|
||||
end, { silent = true, expr = true })
|
||||
```
|
||||
|
||||
## 🌈 Highlight Groups
|
||||
|
||||
<details>
|
||||
<summary>Click to see all highlight groups</summary>
|
||||
|
||||
<!-- hl_start -->
|
||||
|
||||
| Highlight Group | Default Group | Description |
|
||||
| -------------------------------------- | -------------------------------- | -------------------------------------------------- |
|
||||
| **NoiceCmdline** | _MsgArea_ | Normal for the classic cmdline area at the bottom" |
|
||||
| **NoiceCmdlineIcon** | _DiagnosticSignInfo_ | Cmdline icon |
|
||||
| **NoiceCmdlineIconCalculator** | _NoiceCmdlineIcon_ | |
|
||||
| **NoiceCmdlineIconCmdline** | _NoiceCmdlineIcon_ | |
|
||||
| **NoiceCmdlineIconFilter** | _NoiceCmdlineIcon_ | |
|
||||
| **NoiceCmdlineIconHelp** | _NoiceCmdlineIcon_ | |
|
||||
| **NoiceCmdlineIconIncRename** | _NoiceCmdlineIcon_ | |
|
||||
| **NoiceCmdlineIconInput** | _NoiceCmdlineIcon_ | |
|
||||
| **NoiceCmdlineIconLua** | _NoiceCmdlineIcon_ | |
|
||||
| **NoiceCmdlineIconSearch** | _DiagnosticSignWarn_ | Cmdline search icon (`/` and `?`) |
|
||||
| **NoiceCmdlinePopup** | _Normal_ | Normal for the cmdline popup |
|
||||
| **NoiceCmdlinePopupBorder** | _DiagnosticSignInfo_ | Cmdline popup border |
|
||||
| **NoiceCmdlinePopupBorderCalculator** | _NoiceCmdlinePopupBorder_ | |
|
||||
| **NoiceCmdlinePopupBorderCmdline** | _NoiceCmdlinePopupBorder_ | |
|
||||
| **NoiceCmdlinePopupBorderFilter** | _NoiceCmdlinePopupBorder_ | |
|
||||
| **NoiceCmdlinePopupBorderHelp** | _NoiceCmdlinePopupBorder_ | |
|
||||
| **NoiceCmdlinePopupBorderIncRename** | _NoiceCmdlinePopupBorder_ | |
|
||||
| **NoiceCmdlinePopupBorderInput** | _NoiceCmdlinePopupBorder_ | |
|
||||
| **NoiceCmdlinePopupBorderLua** | _NoiceCmdlinePopupBorder_ | |
|
||||
| **NoiceCmdlinePopupBorderSearch** | _DiagnosticSignWarn_ | Cmdline popup border for search |
|
||||
| **NoiceCmdlinePopupTitle** | _DiagnosticSignInfo_ | Cmdline popup border |
|
||||
| **NoiceCmdlinePrompt** | _Title_ | prompt for input() |
|
||||
| **NoiceCompletionItemKindClass** | _NoiceCompletionItemKindDefault_ | |
|
||||
| **NoiceCompletionItemKindColor** | _NoiceCompletionItemKindDefault_ | |
|
||||
| **NoiceCompletionItemKindConstant** | _NoiceCompletionItemKindDefault_ | |
|
||||
| **NoiceCompletionItemKindConstructor** | _NoiceCompletionItemKindDefault_ | |
|
||||
| **NoiceCompletionItemKindDefault** | _Special_ | |
|
||||
| **NoiceCompletionItemKindEnum** | _NoiceCompletionItemKindDefault_ | |
|
||||
| **NoiceCompletionItemKindEnumMember** | _NoiceCompletionItemKindDefault_ | |
|
||||
| **NoiceCompletionItemKindField** | _NoiceCompletionItemKindDefault_ | |
|
||||
| **NoiceCompletionItemKindFile** | _NoiceCompletionItemKindDefault_ | |
|
||||
| **NoiceCompletionItemKindFolder** | _NoiceCompletionItemKindDefault_ | |
|
||||
| **NoiceCompletionItemKindFunction** | _NoiceCompletionItemKindDefault_ | |
|
||||
| **NoiceCompletionItemKindInterface** | _NoiceCompletionItemKindDefault_ | |
|
||||
| **NoiceCompletionItemKindKeyword** | _NoiceCompletionItemKindDefault_ | |
|
||||
| **NoiceCompletionItemKindMethod** | _NoiceCompletionItemKindDefault_ | |
|
||||
| **NoiceCompletionItemKindModule** | _NoiceCompletionItemKindDefault_ | |
|
||||
| **NoiceCompletionItemKindProperty** | _NoiceCompletionItemKindDefault_ | |
|
||||
| **NoiceCompletionItemKindSnippet** | _NoiceCompletionItemKindDefault_ | |
|
||||
| **NoiceCompletionItemKindStruct** | _NoiceCompletionItemKindDefault_ | |
|
||||
| **NoiceCompletionItemKindText** | _NoiceCompletionItemKindDefault_ | |
|
||||
| **NoiceCompletionItemKindUnit** | _NoiceCompletionItemKindDefault_ | |
|
||||
| **NoiceCompletionItemKindValue** | _NoiceCompletionItemKindDefault_ | |
|
||||
| **NoiceCompletionItemKindVariable** | _NoiceCompletionItemKindDefault_ | |
|
||||
| **NoiceCompletionItemMenu** | _none_ | Normal for the popupmenu |
|
||||
| **NoiceCompletionItemWord** | _none_ | Normal for the popupmenu |
|
||||
| **NoiceConfirm** | _Normal_ | Normal for the confirm view |
|
||||
| **NoiceConfirmBorder** | _DiagnosticSignInfo_ | Border for the confirm view |
|
||||
| **NoiceCursor** | _Cursor_ | Fake Cursor |
|
||||
| **NoiceFormatConfirm** | _CursorLine_ | |
|
||||
| **NoiceFormatConfirmDefault** | _Visual_ | |
|
||||
| **NoiceFormatDate** | _Special_ | |
|
||||
| **NoiceFormatEvent** | _NonText_ | |
|
||||
| **NoiceFormatKind** | _NonText_ | |
|
||||
| **NoiceFormatLevelDebug** | _NonText_ | |
|
||||
| **NoiceFormatLevelError** | _DiagnosticVirtualTextError_ | |
|
||||
| **NoiceFormatLevelInfo** | _DiagnosticVirtualTextInfo_ | |
|
||||
| **NoiceFormatLevelOff** | _NonText_ | |
|
||||
| **NoiceFormatLevelTrace** | _NonText_ | |
|
||||
| **NoiceFormatLevelWarn** | _DiagnosticVirtualTextWarn_ | |
|
||||
| **NoiceFormatProgressDone** | _Search_ | Progress bar done |
|
||||
| **NoiceFormatProgressTodo** | _CursorLine_ | progress bar todo |
|
||||
| **NoiceFormatTitle** | _Title_ | |
|
||||
| **NoiceLspProgressClient** | _Title_ | Lsp progress client name |
|
||||
| **NoiceLspProgressSpinner** | _Constant_ | Lsp progress spinner |
|
||||
| **NoiceLspProgressTitle** | _NonText_ | Lsp progress title |
|
||||
| **NoiceMini** | _MsgArea_ | Normal for mini view |
|
||||
| **NoicePopup** | _NormalFloat_ | Normal for popup views |
|
||||
| **NoicePopupBorder** | _FloatBorder_ | Border for popup views |
|
||||
| **NoicePopupmenu** | _Pmenu_ | Normal for the popupmenu |
|
||||
| **NoicePopupmenuBorder** | _FloatBorder_ | Popupmenu border |
|
||||
| **NoicePopupmenuMatch** | _Special_ | Part of the item that matches the input |
|
||||
| **NoicePopupmenuSelected** | _PmenuSel_ | Selected item in the popupmenu |
|
||||
| **NoiceScrollbar** | _PmenuSbar_ | Normal for scrollbar |
|
||||
| **NoiceScrollbarThumb** | _PmenuThumb_ | Scrollbar thumb |
|
||||
| **NoiceSplit** | _NormalFloat_ | Normal for split views |
|
||||
| **NoiceSplitBorder** | _FloatBorder_ | Border for split views |
|
||||
| **NoiceVirtualText** | _DiagnosticVirtualTextInfo_ | Default hl group for virtualtext views |
|
||||
|
||||
<!-- hl_end -->
|
||||
|
||||
</details>
|
||||
975
config/neovim/store/lazy-plugins/noice.nvim/doc/noice.nvim.txt
Normal file
975
config/neovim/store/lazy-plugins/noice.nvim/doc/noice.nvim.txt
Normal file
@ -0,0 +1,975 @@
|
||||
*noice.nvim.txt* For Neovim >= 0.8.0 Last change: 2024 May 23
|
||||
|
||||
==============================================================================
|
||||
Table of Contents *noice.nvim-table-of-contents*
|
||||
|
||||
1. Noice (Nice, Noise, Notice) |noice.nvim-noice-(nice,-noise,-notice)|
|
||||
- Features |noice.nvim-noice-(nice,-noise,-notice)-features|
|
||||
- Status |noice.nvim-noice-(nice,-noise,-notice)-status|
|
||||
- Requirements |noice.nvim-noice-(nice,-noise,-notice)-requirements|
|
||||
- Installation |noice.nvim-noice-(nice,-noise,-notice)-installation|
|
||||
- Configuration |noice.nvim-noice-(nice,-noise,-notice)-configuration|
|
||||
- Filters |noice.nvim-noice-(nice,-noise,-notice)-filters|
|
||||
- Views |noice.nvim-noice-(nice,-noise,-notice)-views|
|
||||
- Formatting |noice.nvim-noice-(nice,-noise,-notice)-formatting|
|
||||
- Routes |noice.nvim-noice-(nice,-noise,-notice)-routes|
|
||||
- Statusline Components|noice.nvim-noice-(nice,-noise,-notice)-statusline-components|
|
||||
- Telescope |noice.nvim-noice-(nice,-noise,-notice)-telescope|
|
||||
- Usage |noice.nvim-noice-(nice,-noise,-notice)-usage|
|
||||
- Highlight Groups |noice.nvim-noice-(nice,-noise,-notice)-highlight-groups|
|
||||
2. Links |noice.nvim-links|
|
||||
|
||||
==============================================================================
|
||||
1. Noice (Nice, Noise, Notice) *noice.nvim-noice-(nice,-noise,-notice)*
|
||||
|
||||
Highly experimental plugin that completely replaces the UI for `messages`,
|
||||
`cmdline` and the `popupmenu`.
|
||||
|
||||
|
||||
FEATURES *noice.nvim-noice-(nice,-noise,-notice)-features*
|
||||
|
||||
- fully **configurable views** like nvim-notify <https://github.com/rcarriga/nvim-notify>,
|
||||
splits, popups, virtual text, ..
|
||||
- use **filters** to **route messages** to different views
|
||||
- message **highlights** are preserved in the views (like the colors of `:hi`)
|
||||
- command output like |:messages|
|
||||
is shown in normal buffers, which makes it much easier to work with
|
||||
- `:Noice` command to show a full message history
|
||||
- no more |:h more-prompt|
|
||||
- fully customizable **cmdline** with icons
|
||||
- **syntax highlighting** for `vim` and `lua` on the **cmdline**
|
||||
- **statusline** components
|
||||
- open message history in telescope.nvim <https://github.com/nvim-telescope/telescope.nvim>
|
||||
|
||||
|
||||
STATUS *noice.nvim-noice-(nice,-noise,-notice)-status*
|
||||
|
||||
**Noice** is using the new experimental `vim.ui_attach` API, so issues are to
|
||||
be expected. It is highly recommended to use Neovim nightly, since a bunch of
|
||||
issues have already been fixed upstream. Check this tracking issue
|
||||
<https://github.com/folke/noice.nvim/issues/6> for a list of known issues.
|
||||
|
||||
|
||||
REQUIREMENTS *noice.nvim-noice-(nice,-noise,-notice)-requirements*
|
||||
|
||||
- Neovim >= 0.9.0 **(nightly highly recommended)**
|
||||
- nui.nvim <https://github.com/MunifTanjim/nui.nvim>used for proper rendering and multiple views
|
||||
- nvim-notify <https://github.com/rcarriga/nvim-notify>notification view _(optional)_
|
||||
- a Nerd Font <https://www.nerdfonts.com/> **(optional)**
|
||||
- nvim-treesitter <https://github.com/nvim-treesitter/nvim-treesitter/> **(optional, but highly recommended)**
|
||||
used for highlighting the cmdline and lsp docs. Make sure to install the parsers for
|
||||
`vim`, `regex`, `lua`, `bash`, `markdown` and `markdown_inline`
|
||||
|
||||
|
||||
INSTALLATION *noice.nvim-noice-(nice,-noise,-notice)-installation*
|
||||
|
||||
Install the plugin with your preferred package manager:
|
||||
|
||||
>lua
|
||||
-- lazy.nvim
|
||||
{
|
||||
"folke/noice.nvim",
|
||||
event = "VeryLazy",
|
||||
opts = {
|
||||
-- add any options here
|
||||
},
|
||||
dependencies = {
|
||||
-- if you lazy-load any plugin below, make sure to add proper `module="..."` entries
|
||||
"MunifTanjim/nui.nvim",
|
||||
-- OPTIONAL:
|
||||
-- `nvim-notify` is only needed, if you want to use the notification view.
|
||||
-- If not available, we use `mini` as the fallback
|
||||
"rcarriga/nvim-notify",
|
||||
}
|
||||
}
|
||||
<
|
||||
|
||||
Suggested setup:
|
||||
|
||||
>lua
|
||||
require("noice").setup({
|
||||
lsp = {
|
||||
-- override markdown rendering so that **cmp** and other plugins use **Treesitter**
|
||||
override = {
|
||||
["vim.lsp.util.convert_input_to_markdown_lines"] = true,
|
||||
["vim.lsp.util.stylize_markdown"] = true,
|
||||
["cmp.entry.get_documentation"] = true, -- requires hrsh7th/nvim-cmp
|
||||
},
|
||||
},
|
||||
-- you can enable a preset for easier configuration
|
||||
presets = {
|
||||
bottom_search = true, -- use a classic bottom cmdline for search
|
||||
command_palette = true, -- position the cmdline and popupmenu together
|
||||
long_message_to_split = true, -- long messages will be sent to a split
|
||||
inc_rename = false, -- enables an input dialog for inc-rename.nvim
|
||||
lsp_doc_border = false, -- add a border to hover docs and signature help
|
||||
},
|
||||
})
|
||||
<
|
||||
|
||||
It’s a good idea to run `:checkhealth noice` after installing to check for
|
||||
common issues.
|
||||
|
||||
vim-plug ~
|
||||
|
||||
>vim
|
||||
" vim-plug
|
||||
call plug#begin()
|
||||
Plug 'folke/noice.nvim'
|
||||
Plug 'MunifTanjim/nui.nvim'
|
||||
call plug#end()
|
||||
|
||||
lua require("noice").setup()
|
||||
<
|
||||
|
||||
|
||||
CONFIGURATION *noice.nvim-noice-(nice,-noise,-notice)-configuration*
|
||||
|
||||
**noice.nvim** comes with the following defaults:
|
||||
|
||||
Check the wiki <https://github.com/folke/noice.nvim/wiki/Configuration-Recipes>
|
||||
for configuration recipes.
|
||||
|
||||
>lua
|
||||
{
|
||||
cmdline = {
|
||||
enabled = true, -- enables the Noice cmdline UI
|
||||
view = "cmdline_popup", -- view for rendering the cmdline. Change to `cmdline` to get a classic cmdline at the bottom
|
||||
opts = {}, -- global options for the cmdline. See section on views
|
||||
---@type table<string, CmdlineFormat>
|
||||
format = {
|
||||
-- conceal: (default=true) This will hide the text in the cmdline that matches the pattern.
|
||||
-- view: (default is cmdline view)
|
||||
-- opts: any options passed to the view
|
||||
-- icon_hl_group: optional hl_group for the icon
|
||||
-- title: set to anything or empty string to hide
|
||||
cmdline = { pattern = "^:", icon = "", lang = "vim" },
|
||||
search_down = { kind = "search", pattern = "^/", icon = " ", lang = "regex" },
|
||||
search_up = { kind = "search", pattern = "^%?", icon = " ", lang = "regex" },
|
||||
filter = { pattern = "^:%s*!", icon = "$", lang = "bash" },
|
||||
lua = { pattern = { "^:%s*lua%s+", "^:%s*lua%s*=%s*", "^:%s*=%s*" }, icon = "", lang = "lua" },
|
||||
help = { pattern = "^:%s*he?l?p?%s+", icon = "" },
|
||||
input = {}, -- Used by input()
|
||||
-- lua = false, -- to disable a format, set to `false`
|
||||
},
|
||||
},
|
||||
messages = {
|
||||
-- NOTE: If you enable messages, then the cmdline is enabled automatically.
|
||||
-- This is a current Neovim limitation.
|
||||
enabled = true, -- enables the Noice messages UI
|
||||
view = "notify", -- default view for messages
|
||||
view_error = "notify", -- view for errors
|
||||
view_warn = "notify", -- view for warnings
|
||||
view_history = "messages", -- view for :messages
|
||||
view_search = "virtualtext", -- view for search count messages. Set to `false` to disable
|
||||
},
|
||||
popupmenu = {
|
||||
enabled = true, -- enables the Noice popupmenu UI
|
||||
---@type 'nui'|'cmp'
|
||||
backend = "nui", -- backend to use to show regular cmdline completions
|
||||
---@type NoicePopupmenuItemKind|false
|
||||
-- Icons for completion item kinds (see defaults at noice.config.icons.kinds)
|
||||
kind_icons = {}, -- set to `false` to disable icons
|
||||
},
|
||||
-- default options for require('noice').redirect
|
||||
-- see the section on Command Redirection
|
||||
---@type NoiceRouteConfig
|
||||
redirect = {
|
||||
view = "popup",
|
||||
filter = { event = "msg_show" },
|
||||
},
|
||||
-- You can add any custom commands below that will be available with `:Noice command`
|
||||
---@type table<string, NoiceCommand>
|
||||
commands = {
|
||||
history = {
|
||||
-- options for the message history that you get with `:Noice`
|
||||
view = "split",
|
||||
opts = { enter = true, format = "details" },
|
||||
filter = {
|
||||
any = {
|
||||
{ event = "notify" },
|
||||
{ error = true },
|
||||
{ warning = true },
|
||||
{ event = "msg_show", kind = { "" } },
|
||||
{ event = "lsp", kind = "message" },
|
||||
},
|
||||
},
|
||||
},
|
||||
-- :Noice last
|
||||
last = {
|
||||
view = "popup",
|
||||
opts = { enter = true, format = "details" },
|
||||
filter = {
|
||||
any = {
|
||||
{ event = "notify" },
|
||||
{ error = true },
|
||||
{ warning = true },
|
||||
{ event = "msg_show", kind = { "" } },
|
||||
{ event = "lsp", kind = "message" },
|
||||
},
|
||||
},
|
||||
filter_opts = { count = 1 },
|
||||
},
|
||||
-- :Noice errors
|
||||
errors = {
|
||||
-- options for the message history that you get with `:Noice`
|
||||
view = "popup",
|
||||
opts = { enter = true, format = "details" },
|
||||
filter = { error = true },
|
||||
filter_opts = { reverse = true },
|
||||
},
|
||||
all = {
|
||||
-- options for the message history that you get with `:Noice`
|
||||
view = "split",
|
||||
opts = { enter = true, format = "details" },
|
||||
filter = {},
|
||||
},
|
||||
},
|
||||
notify = {
|
||||
-- Noice can be used as `vim.notify` so you can route any notification like other messages
|
||||
-- Notification messages have their level and other properties set.
|
||||
-- event is always "notify" and kind can be any log level as a string
|
||||
-- The default routes will forward notifications to nvim-notify
|
||||
-- Benefit of using Noice for this is the routing and consistent history view
|
||||
enabled = true,
|
||||
view = "notify",
|
||||
},
|
||||
lsp = {
|
||||
progress = {
|
||||
enabled = true,
|
||||
-- Lsp Progress is formatted using the builtins for lsp_progress. See config.format.builtin
|
||||
-- See the section on formatting for more details on how to customize.
|
||||
--- @type NoiceFormat|string
|
||||
format = "lsp_progress",
|
||||
--- @type NoiceFormat|string
|
||||
format_done = "lsp_progress_done",
|
||||
throttle = 1000 / 30, -- frequency to update lsp progress message
|
||||
view = "mini",
|
||||
},
|
||||
override = {
|
||||
-- override the default lsp markdown formatter with Noice
|
||||
["vim.lsp.util.convert_input_to_markdown_lines"] = false,
|
||||
-- override the lsp markdown formatter with Noice
|
||||
["vim.lsp.util.stylize_markdown"] = false,
|
||||
-- override cmp documentation with Noice (needs the other options to work)
|
||||
["cmp.entry.get_documentation"] = false,
|
||||
},
|
||||
hover = {
|
||||
enabled = true,
|
||||
silent = false, -- set to true to not show a message if hover is not available
|
||||
view = nil, -- when nil, use defaults from documentation
|
||||
---@type NoiceViewOptions
|
||||
opts = {}, -- merged with defaults from documentation
|
||||
},
|
||||
signature = {
|
||||
enabled = true,
|
||||
auto_open = {
|
||||
enabled = true,
|
||||
trigger = true, -- Automatically show signature help when typing a trigger character from the LSP
|
||||
luasnip = true, -- Will open signature help when jumping to Luasnip insert nodes
|
||||
throttle = 50, -- Debounce lsp signature help request by 50ms
|
||||
},
|
||||
view = nil, -- when nil, use defaults from documentation
|
||||
---@type NoiceViewOptions
|
||||
opts = {}, -- merged with defaults from documentation
|
||||
},
|
||||
message = {
|
||||
-- Messages shown by lsp servers
|
||||
enabled = true,
|
||||
view = "notify",
|
||||
opts = {},
|
||||
},
|
||||
-- defaults for hover and signature help
|
||||
documentation = {
|
||||
view = "hover",
|
||||
---@type NoiceViewOptions
|
||||
opts = {
|
||||
lang = "markdown",
|
||||
replace = true,
|
||||
render = "plain",
|
||||
format = { "{message}" },
|
||||
win_options = { concealcursor = "n", conceallevel = 3 },
|
||||
},
|
||||
},
|
||||
},
|
||||
markdown = {
|
||||
hover = {
|
||||
["|(%S-)|"] = vim.cmd.help, -- vim help links
|
||||
["%[.-%]%((%S-)%)"] = require("noice.util").open, -- markdown links
|
||||
},
|
||||
highlights = {
|
||||
["|%S-|"] = "@text.reference",
|
||||
["@%S+"] = "@parameter",
|
||||
["^%s*(Parameters:)"] = "@text.title",
|
||||
["^%s*(Return:)"] = "@text.title",
|
||||
["^%s*(See also:)"] = "@text.title",
|
||||
["{%S-}"] = "@parameter",
|
||||
},
|
||||
},
|
||||
health = {
|
||||
checker = true, -- Disable if you don't want health checks to run
|
||||
},
|
||||
smart_move = {
|
||||
-- noice tries to move out of the way of existing floating windows.
|
||||
enabled = true, -- you can disable this behaviour here
|
||||
-- add any filetypes here, that shouldn't trigger smart move.
|
||||
excluded_filetypes = { "cmp_menu", "cmp_docs", "notify" },
|
||||
},
|
||||
---@type NoicePresets
|
||||
presets = {
|
||||
-- you can enable a preset by setting it to true, or a table that will override the preset config
|
||||
-- you can also add custom presets that you can enable/disable with enabled=true
|
||||
bottom_search = false, -- use a classic bottom cmdline for search
|
||||
command_palette = false, -- position the cmdline and popupmenu together
|
||||
long_message_to_split = false, -- long messages will be sent to a split
|
||||
inc_rename = false, -- enables an input dialog for inc-rename.nvim
|
||||
lsp_doc_border = false, -- add a border to hover docs and signature help
|
||||
},
|
||||
throttle = 1000 / 30, -- how frequently does Noice need to check for ui updates? This has no effect when in blocking mode.
|
||||
---@type NoiceConfigViews
|
||||
views = {}, ---@see section on views
|
||||
---@type NoiceRouteConfig[]
|
||||
routes = {}, --- @see section on routes
|
||||
---@type table<string, NoiceFilter>
|
||||
status = {}, --- @see section on statusline components
|
||||
---@type NoiceFormatOptions
|
||||
format = {}, --- @see section on formatting
|
||||
}
|
||||
<
|
||||
|
||||
If you don’t want to use a Nerd Font, you can replace the icons with Unicode symbols. ~
|
||||
|
||||
>lua
|
||||
require("noice").setup({
|
||||
cmdline = {
|
||||
format = {
|
||||
cmdline = { icon = ">" },
|
||||
search_down = { icon = "🔍⌄" },
|
||||
search_up = { icon = "🔍⌃" },
|
||||
filter = { icon = "$" },
|
||||
lua = { icon = "☾" },
|
||||
help = { icon = "?" },
|
||||
},
|
||||
},
|
||||
format = {
|
||||
level = {
|
||||
icons = {
|
||||
error = "✖",
|
||||
warn = "▼",
|
||||
info = "●",
|
||||
},
|
||||
},
|
||||
},
|
||||
popupmenu = {
|
||||
kind_icons = false,
|
||||
},
|
||||
inc_rename = {
|
||||
cmdline = {
|
||||
format = {
|
||||
IncRename = { icon = "⟳" },
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
<
|
||||
|
||||
|
||||
FILTERS *noice.nvim-noice-(nice,-noise,-notice)-filters*
|
||||
|
||||
**Noice** uses filters to route messages to specific views.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
Name Type Description
|
||||
------------ ---------- ------------------------------------------------------
|
||||
any filter[] checks that at least one of the filters matches
|
||||
|
||||
blocking boolean are we in blocking mode?
|
||||
|
||||
cleared boolean checks if the message is cleared, meaning it’s in the
|
||||
history
|
||||
|
||||
cmdline boolean or checks if the message was generated by executing a
|
||||
string cmdline. When string, then it is used as a pattern
|
||||
|
||||
error boolean all error-like kinds from ext_messages
|
||||
|
||||
event string or any of the events from ext_messages or cmdline. See :h
|
||||
string[] ui-messages
|
||||
|
||||
find string uses lua string.find to match the pattern
|
||||
|
||||
has boolean checks if the message is exists, meaning it’s in the
|
||||
history
|
||||
|
||||
kind string or any of the kinds from ext_messages. See :h ui-messages
|
||||
string[]
|
||||
|
||||
max_height number maximum height of the message
|
||||
|
||||
max_length number maximum length of the message (total width of all the
|
||||
lines)
|
||||
|
||||
max_width number maximum width of the message
|
||||
|
||||
min_height number minimum height of the message
|
||||
|
||||
min_length number minimum length of the message (total width of all the
|
||||
lines)
|
||||
|
||||
min_width number minimum width of the message
|
||||
|
||||
mode string checks if vim.api.nvim_get_mode() contains the given
|
||||
mode
|
||||
|
||||
not filter checks whether the filter matches or not
|
||||
|
||||
warning boolean all warning-like kinds from ext_messages
|
||||
------------------------------------------------------------------------------
|
||||
Example: ~
|
||||
|
||||
>lua
|
||||
-- all messages over 10 lines, excluding echo and search_count
|
||||
local filter = {
|
||||
event = "msg_show",
|
||||
min_height = 10,
|
||||
["not"] = { kind = { "search_count", "echo" } },
|
||||
}
|
||||
<
|
||||
|
||||
|
||||
VIEWS *noice.nvim-noice-(nice,-noise,-notice)-views*
|
||||
|
||||
**Noice** comes with the following built-in backends:
|
||||
|
||||
- **popup**powered by nui.nvim <https://github.com/MunifTanjim/nui.nvim>
|
||||
- **split**powered by nui.nvim <https://github.com/MunifTanjim/nui.nvim>
|
||||
- **notify**powered by nvim-notify <https://github.com/rcarriga/nvim-notify>
|
||||
- **virtualtext**shows the message as virtualtext (for example for `search_count`)
|
||||
- **mini**similar to notifier.nvim <https://github.com/vigoux/notifier.nvim> & fidget.nvim <https://github.com/j-hui/fidget.nvim>
|
||||
- **notify_send**generate a desktop notification
|
||||
|
||||
A **View** (`config.views`) is a combination of a `backend` and options.
|
||||
**Noice** comes with the following built-in views with sane defaults:
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
View Backend Description
|
||||
---------------- ---------- ----------------------------------------------------
|
||||
notify notify nvim-notify with level=nil, replace=false,
|
||||
merge=false
|
||||
|
||||
split split horizontal split
|
||||
|
||||
vsplit split vertical split
|
||||
|
||||
popup popup simple popup
|
||||
|
||||
mini mini minimal view, by default bottom right, right-aligned
|
||||
|
||||
cmdline popup bottom line, similar to the classic cmdline
|
||||
|
||||
cmdline_popup popup fancy cmdline popup, with different styles according
|
||||
to the cmdline mode
|
||||
|
||||
cmdline_output split split used by config.presets.cmdline_output_to_split
|
||||
|
||||
messages split split used for :messages
|
||||
|
||||
confirm popup popup used for confirm events
|
||||
|
||||
hover popup popup used for lsp signature help and hover
|
||||
|
||||
popupmenu nui.menu special view with the options used to render the
|
||||
popupmenu when backend is nui
|
||||
--------------------------------------------------------------------------------
|
||||
Please refer to noice.config.views
|
||||
<https://github.com/folke/noice.nvim/blob/main/lua/noice/config/views.lua> to
|
||||
see the options. Any options passed to existing views in `config.views`, will
|
||||
override those options only. You can configure completely new views and use
|
||||
them in custom routes.
|
||||
|
||||
Example: ~
|
||||
|
||||
>lua
|
||||
-- override the default split view to always enter the split when it opens
|
||||
require("noice").setup({
|
||||
views = {
|
||||
split = {
|
||||
enter = true,
|
||||
},
|
||||
},
|
||||
})
|
||||
<
|
||||
|
||||
|
||||
All built-in Noice views have the filetype `noice`
|
||||
|
||||
NUI OPTIONS ~
|
||||
|
||||
See the Nui documentation for Popup
|
||||
<https://github.com/MunifTanjim/nui.nvim/tree/main/lua/nui/popup> and Split
|
||||
<https://github.com/MunifTanjim/nui.nvim/tree/main/lua/nui/split>.
|
||||
|
||||
OptionDescriptionsize, positionSize, position and their constituents can additionally be specified as "auto", to use the message height and width.win_options.winhighlightString or can also be a table like:
|
||||
|
||||
>lua
|
||||
{
|
||||
win_options = {
|
||||
winhighlight = {
|
||||
Normal = "NormalFloat",
|
||||
FloatBorder = "FloatBorder"
|
||||
},
|
||||
}
|
||||
}
|
||||
<
|
||||
|
||||
scrollbarSet to false to hide the scrollbar.
|
||||
NOTIFY OPTIONS ~
|
||||
|
||||
-------------------------------------------------------------------------------------------------
|
||||
Option Type Default Description
|
||||
--------- ---------------- ---------------- -----------------------------------------------------
|
||||
title string "Notification" title to be used for the notification. Uses
|
||||
Message.title if available.
|
||||
|
||||
replace boolean false when true, messages routing to the same notify
|
||||
instance will replace existing messages instead of
|
||||
pushing a new notification every time
|
||||
|
||||
merge boolean false Merge messages into one Notification or create
|
||||
separate notifications
|
||||
|
||||
level number\|string nil notification level. Uses Message.level if available.
|
||||
-------------------------------------------------------------------------------------------------
|
||||
|
||||
VIRTUAL TEXT OPTIONS ~
|
||||
|
||||
Right now there’s only an option to set the `hl_group` used to render the
|
||||
virtual text.
|
||||
|
||||
|
||||
FORMATTING *noice.nvim-noice-(nice,-noise,-notice)-formatting*
|
||||
|
||||
Formatting options can be specified with `config.format`. For a list of the
|
||||
defaults, please refer to config.format
|
||||
<https://github.com/folke/noice.nvim/blob/main/lua/noice/config/format.lua>
|
||||
|
||||
**Noice** includes the following formatters:
|
||||
|
||||
- **level**message level with optional `icon` and `hl_group` per level
|
||||
- **text**any text with optional `hl_group`
|
||||
- **title**message title with optional `hl_group`
|
||||
- **event**message event with optional `hl_group`
|
||||
- **kind**message kind with optional `hl_group`
|
||||
- **date**formatted date with optional date format string
|
||||
- **message**message content itself with optional `hl_group` to override message highlights
|
||||
- **confirm**only useful for `confirm` messages. Will format the choices as buttons.
|
||||
- **cmdline**will render the cmdline in the message that generated the message.
|
||||
- **progress**progress bar used by lsp progress
|
||||
- **spinner**spinners used by lsp progress
|
||||
- **data**render any custom data from `Message.opts`. Useful in combination with the opts passed to `vim.notify`
|
||||
|
||||
Formatters are used in `format` definitions. **Noice** includes the following
|
||||
built-in formats:
|
||||
|
||||
>lua
|
||||
{
|
||||
-- default format
|
||||
default = { "{level} ", "{title} ", "{message}" },
|
||||
-- default format for vim.notify views
|
||||
notify = { "{message}" },
|
||||
-- default format for the history
|
||||
details = {
|
||||
"{level} ",
|
||||
"{date} ",
|
||||
"{event}",
|
||||
{ "{kind}", before = { ".", hl_group = "NoiceFormatKind" } },
|
||||
" ",
|
||||
"{title} ",
|
||||
"{cmdline} ",
|
||||
"{message}",
|
||||
},
|
||||
telescope = ..., -- formatter used to display telescope results
|
||||
telescope_preview = ..., -- formatter used to preview telescope results
|
||||
lsp_progress = ..., -- formatter used by lsp progress
|
||||
lsp_progress_done = ..., -- formatter used by lsp progress
|
||||
}
|
||||
<
|
||||
|
||||
Text before/after the formatter or in the before/after options, will only be
|
||||
rendered if the formatter itself rendered something.
|
||||
|
||||
The `format` view option, can be either a `string` (one of the built-in
|
||||
formats), or a table with a custom format definition.
|
||||
|
||||
To align text, you can use the `align` option for a view. Can be `center`,
|
||||
`left` or `right`.
|
||||
|
||||
|
||||
ROUTES *noice.nvim-noice-(nice,-noise,-notice)-routes*
|
||||
|
||||
A **route** has a `filter`, `view` and optional `opts` attribute.
|
||||
|
||||
- **view**one of the views (built-in or custom)
|
||||
- **filter** a filter for messages matching this route
|
||||
- **opts**options for the view and the route
|
||||
|
||||
Route options can be any of the view options above, or one of:
|
||||
|
||||
------------------------------------------------------------------------------------------
|
||||
Option Type Default Description
|
||||
-------- --------- --------- -------------------------------------------------------------
|
||||
skip boolean false messages matching this filter will be skipped and not shown
|
||||
in any views
|
||||
|
||||
stop boolean true When false and a route matches the filter, then other routes
|
||||
can still process the message too. Useful if you want certain
|
||||
messages to be shown in multiple views.
|
||||
------------------------------------------------------------------------------------------
|
||||
Please refer to noice.config.routes
|
||||
<https://github.com/folke/noice.nvim/blob/main/lua/noice/config/routes.lua> for
|
||||
an overview of the default routes. **Routes** passed to `setup()` will be
|
||||
prepended to the default routes.
|
||||
|
||||
Example ~
|
||||
|
||||
>lua
|
||||
-- skip search_count messages instead of showing them as virtual text
|
||||
require("noice").setup({
|
||||
routes = {
|
||||
{
|
||||
filter = { event = "msg_show", kind = "search_count" },
|
||||
opts = { skip = true },
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
-- always route any messages with more than 20 lines to the split view
|
||||
require("noice").setup({
|
||||
routes = {
|
||||
{
|
||||
view = "split",
|
||||
filter = { event = "msg_show", min_height = 20 },
|
||||
},
|
||||
},
|
||||
})
|
||||
<
|
||||
|
||||
|
||||
STATUSLINE COMPONENTS*noice.nvim-noice-(nice,-noise,-notice)-statusline-components*
|
||||
|
||||
**Noice** comes with the following statusline components:
|
||||
|
||||
- **ruler**
|
||||
- **message**last line of the last message (`event=show_msg`)
|
||||
- **command**`showcmd`
|
||||
- **mode**`showmode` (@recording messages)
|
||||
- **search**search count messages
|
||||
|
||||
See noice.config.status
|
||||
<https://github.com/folke/noice.nvim/blob/main/lua/noice/config/status.lua> for
|
||||
the default config.
|
||||
|
||||
You can add custom statusline components in setup under the `status` key.
|
||||
|
||||
Statusline components have the following methods:
|
||||
|
||||
- **get**gets the content of the message **without** highlights
|
||||
- **get_hl**gets the content of the message **with** highlights
|
||||
- **has**checks if the component is available
|
||||
|
||||
Example of configuring lualine.nvim ~
|
||||
|
||||
>lua
|
||||
require("lualine").setup({
|
||||
sections = {
|
||||
lualine_x = {
|
||||
{
|
||||
require("noice").api.status.message.get_hl,
|
||||
cond = require("noice").api.status.message.has,
|
||||
},
|
||||
{
|
||||
require("noice").api.status.command.get,
|
||||
cond = require("noice").api.status.command.has,
|
||||
color = { fg = "#ff9e64" },
|
||||
},
|
||||
{
|
||||
require("noice").api.status.mode.get,
|
||||
cond = require("noice").api.status.mode.has,
|
||||
color = { fg = "#ff9e64" },
|
||||
},
|
||||
{
|
||||
require("noice").api.status.search.get,
|
||||
cond = require("noice").api.status.search.has,
|
||||
color = { fg = "#ff9e64" },
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
<
|
||||
|
||||
|
||||
TELESCOPE *noice.nvim-noice-(nice,-noise,-notice)-telescope*
|
||||
|
||||
In order to use **Noice** in **Telescope**, you can either do `:Noice
|
||||
telescope`, or register the extension and use `:Telescope noice`. The results
|
||||
panel is formatted using `config.format.formatters.telescope`. The preview is
|
||||
formatted with `config.format.formatters.telescope_preview`
|
||||
|
||||
>lua
|
||||
require("telescope").load_extension("noice")
|
||||
<
|
||||
|
||||
|
||||
USAGE *noice.nvim-noice-(nice,-noise,-notice)-usage*
|
||||
|
||||
- `:Noice` or `:Noice history` shows the message history
|
||||
- `:Noice last` shows the last message in a popup
|
||||
- `:Noice dismiss` dismiss all visible messages
|
||||
- `:Noice errors` shows the error messages in a split. Last errors on top
|
||||
- `:Noice disable` disables **Noice**
|
||||
- `:Noice enable` enables **Noice**
|
||||
- `:Noice stats` shows debugging stats
|
||||
- `:Noice telescope` opens message history in Telescope
|
||||
|
||||
Alternatively, all commands also exist as a full name like `:NoiceLast`,
|
||||
`:NoiceDisable`.
|
||||
|
||||
You can also use `Lua` equivalents.
|
||||
|
||||
>lua
|
||||
vim.keymap.set("n", "<leader>nl", function()
|
||||
require("noice").cmd("last")
|
||||
end)
|
||||
|
||||
vim.keymap.set("n", "<leader>nh", function()
|
||||
require("noice").cmd("history")
|
||||
end)
|
||||
<
|
||||
|
||||
|
||||
You can add custom commands with `config.commands`
|
||||
|
||||
COMMAND REDIRECTION ~
|
||||
|
||||
Sometimes it’s useful to redirect the messages generated by a command or
|
||||
function to a different view. That can be easily achieved with command
|
||||
redirection.
|
||||
|
||||
The redirect API can taken an optional `routes` parameter, which defaults to
|
||||
`{config.redirect}`.
|
||||
|
||||
>lua
|
||||
-- redirect ":hi"
|
||||
require("noice").redirect("hi")
|
||||
|
||||
-- redirect some function
|
||||
require("noice").redirect(function()
|
||||
print("test")
|
||||
end)
|
||||
<
|
||||
|
||||
Adding the following keymap, will redirect the active cmdline when pressing
|
||||
`<S-Enter>`. The cmdline stays open, so you can change the command and execute
|
||||
it again. When exiting the cmdline, the popup window will be focused.
|
||||
|
||||
>lua
|
||||
vim.keymap.set("c", "<S-Enter>", function()
|
||||
require("noice").redirect(vim.fn.getcmdline())
|
||||
end, { desc = "Redirect Cmdline" })
|
||||
<
|
||||
|
||||
|
||||
LSP HOVER DOC SCROLLING ~
|
||||
|
||||
>lua
|
||||
vim.keymap.set({ "n", "i", "s" }, "<c-f>", function()
|
||||
if not require("noice.lsp").scroll(4) then
|
||||
return "<c-f>"
|
||||
end
|
||||
end, { silent = true, expr = true })
|
||||
|
||||
vim.keymap.set({ "n", "i", "s" }, "<c-b>", function()
|
||||
if not require("noice.lsp").scroll(-4) then
|
||||
return "<c-b>"
|
||||
end
|
||||
end, { silent = true, expr = true })
|
||||
<
|
||||
|
||||
|
||||
HIGHLIGHT GROUPS *noice.nvim-noice-(nice,-noise,-notice)-highlight-groups*
|
||||
|
||||
Click to see all highlight groups ~
|
||||
|
||||
---------------------------------------------------------------------------------------------------
|
||||
Highlight Group Default Group Description
|
||||
------------------------------------ -------------------------------- -----------------------------
|
||||
NoiceCmdline MsgArea Normal for the classic
|
||||
cmdline area at the bottom”
|
||||
|
||||
NoiceCmdlineIcon DiagnosticSignInfo Cmdline icon
|
||||
|
||||
NoiceCmdlineIconCalculator NoiceCmdlineIcon
|
||||
|
||||
NoiceCmdlineIconCmdline NoiceCmdlineIcon
|
||||
|
||||
NoiceCmdlineIconFilter NoiceCmdlineIcon
|
||||
|
||||
NoiceCmdlineIconHelp NoiceCmdlineIcon
|
||||
|
||||
NoiceCmdlineIconIncRename NoiceCmdlineIcon
|
||||
|
||||
NoiceCmdlineIconInput NoiceCmdlineIcon
|
||||
|
||||
NoiceCmdlineIconLua NoiceCmdlineIcon
|
||||
|
||||
NoiceCmdlineIconSearch DiagnosticSignWarn Cmdline search icon (/ and ?)
|
||||
|
||||
NoiceCmdlinePopup Normal Normal for the cmdline popup
|
||||
|
||||
NoiceCmdlinePopupBorder DiagnosticSignInfo Cmdline popup border
|
||||
|
||||
NoiceCmdlinePopupBorderCalculator NoiceCmdlinePopupBorder
|
||||
|
||||
NoiceCmdlinePopupBorderCmdline NoiceCmdlinePopupBorder
|
||||
|
||||
NoiceCmdlinePopupBorderFilter NoiceCmdlinePopupBorder
|
||||
|
||||
NoiceCmdlinePopupBorderHelp NoiceCmdlinePopupBorder
|
||||
|
||||
NoiceCmdlinePopupBorderIncRename NoiceCmdlinePopupBorder
|
||||
|
||||
NoiceCmdlinePopupBorderInput NoiceCmdlinePopupBorder
|
||||
|
||||
NoiceCmdlinePopupBorderLua NoiceCmdlinePopupBorder
|
||||
|
||||
NoiceCmdlinePopupBorderSearch DiagnosticSignWarn Cmdline popup border for
|
||||
search
|
||||
|
||||
NoiceCmdlinePopupTitle DiagnosticSignInfo Cmdline popup border
|
||||
|
||||
NoiceCmdlinePrompt Title prompt for input()
|
||||
|
||||
NoiceCompletionItemKindClass NoiceCompletionItemKindDefault
|
||||
|
||||
NoiceCompletionItemKindColor NoiceCompletionItemKindDefault
|
||||
|
||||
NoiceCompletionItemKindConstant NoiceCompletionItemKindDefault
|
||||
|
||||
NoiceCompletionItemKindConstructor NoiceCompletionItemKindDefault
|
||||
|
||||
NoiceCompletionItemKindDefault Special
|
||||
|
||||
NoiceCompletionItemKindEnum NoiceCompletionItemKindDefault
|
||||
|
||||
NoiceCompletionItemKindEnumMember NoiceCompletionItemKindDefault
|
||||
|
||||
NoiceCompletionItemKindField NoiceCompletionItemKindDefault
|
||||
|
||||
NoiceCompletionItemKindFile NoiceCompletionItemKindDefault
|
||||
|
||||
NoiceCompletionItemKindFolder NoiceCompletionItemKindDefault
|
||||
|
||||
NoiceCompletionItemKindFunction NoiceCompletionItemKindDefault
|
||||
|
||||
NoiceCompletionItemKindInterface NoiceCompletionItemKindDefault
|
||||
|
||||
NoiceCompletionItemKindKeyword NoiceCompletionItemKindDefault
|
||||
|
||||
NoiceCompletionItemKindMethod NoiceCompletionItemKindDefault
|
||||
|
||||
NoiceCompletionItemKindModule NoiceCompletionItemKindDefault
|
||||
|
||||
NoiceCompletionItemKindProperty NoiceCompletionItemKindDefault
|
||||
|
||||
NoiceCompletionItemKindSnippet NoiceCompletionItemKindDefault
|
||||
|
||||
NoiceCompletionItemKindStruct NoiceCompletionItemKindDefault
|
||||
|
||||
NoiceCompletionItemKindText NoiceCompletionItemKindDefault
|
||||
|
||||
NoiceCompletionItemKindUnit NoiceCompletionItemKindDefault
|
||||
|
||||
NoiceCompletionItemKindValue NoiceCompletionItemKindDefault
|
||||
|
||||
NoiceCompletionItemKindVariable NoiceCompletionItemKindDefault
|
||||
|
||||
NoiceCompletionItemMenu none Normal for the popupmenu
|
||||
|
||||
NoiceCompletionItemWord none Normal for the popupmenu
|
||||
|
||||
NoiceConfirm Normal Normal for the confirm view
|
||||
|
||||
NoiceConfirmBorder DiagnosticSignInfo Border for the confirm view
|
||||
|
||||
NoiceCursor Cursor Fake Cursor
|
||||
|
||||
NoiceFormatConfirm CursorLine
|
||||
|
||||
NoiceFormatConfirmDefault Visual
|
||||
|
||||
NoiceFormatDate Special
|
||||
|
||||
NoiceFormatEvent NonText
|
||||
|
||||
NoiceFormatKind NonText
|
||||
|
||||
NoiceFormatLevelDebug NonText
|
||||
|
||||
NoiceFormatLevelError DiagnosticVirtualTextError
|
||||
|
||||
NoiceFormatLevelInfo DiagnosticVirtualTextInfo
|
||||
|
||||
NoiceFormatLevelOff NonText
|
||||
|
||||
NoiceFormatLevelTrace NonText
|
||||
|
||||
NoiceFormatLevelWarn DiagnosticVirtualTextWarn
|
||||
|
||||
NoiceFormatProgressDone Search Progress bar done
|
||||
|
||||
NoiceFormatProgressTodo CursorLine progress bar todo
|
||||
|
||||
NoiceFormatTitle Title
|
||||
|
||||
NoiceLspProgressClient Title Lsp progress client name
|
||||
|
||||
NoiceLspProgressSpinner Constant Lsp progress spinner
|
||||
|
||||
NoiceLspProgressTitle NonText Lsp progress title
|
||||
|
||||
NoiceMini MsgArea Normal for mini view
|
||||
|
||||
NoicePopup NormalFloat Normal for popup views
|
||||
|
||||
NoicePopupBorder FloatBorder Border for popup views
|
||||
|
||||
NoicePopupmenu Pmenu Normal for the popupmenu
|
||||
|
||||
NoicePopupmenuBorder FloatBorder Popupmenu border
|
||||
|
||||
NoicePopupmenuMatch Special Part of the item that matches
|
||||
the input
|
||||
|
||||
NoicePopupmenuSelected PmenuSel Selected item in the
|
||||
popupmenu
|
||||
|
||||
NoiceScrollbar PmenuSbar Normal for scrollbar
|
||||
|
||||
NoiceScrollbarThumb PmenuThumb Scrollbar thumb
|
||||
|
||||
NoiceSplit NormalFloat Normal for split views
|
||||
|
||||
NoiceSplitBorder FloatBorder Border for split views
|
||||
|
||||
NoiceVirtualText DiagnosticVirtualTextInfo Default hl group for
|
||||
virtualtext views
|
||||
---------------------------------------------------------------------------------------------------
|
||||
==============================================================================
|
||||
2. Links *noice.nvim-links*
|
||||
|
||||
1. *image*: https://user-images.githubusercontent.com/292349/193263220-791847b2-516c-4f23-9802-31dd6bec5f6a.png
|
||||
2. *@recording*:
|
||||
|
||||
Generated by panvimdoc <https://github.com/kdheepak/panvimdoc>
|
||||
|
||||
vim:tw=78:ts=8:noet:ft=help:norl:
|
||||
@ -0,0 +1,18 @@
|
||||
local require = require("noice.util.lazy")
|
||||
|
||||
local Cmdline = require("noice.ui.cmdline")
|
||||
local Status = require("noice.api.status")
|
||||
|
||||
local M = {}
|
||||
|
||||
M.status = Status
|
||||
|
||||
---@deprecated
|
||||
M.statusline = Status
|
||||
|
||||
---@return CmdlinePosition?
|
||||
function M.get_cmdline_position()
|
||||
return Cmdline.position and vim.deepcopy(Cmdline.position)
|
||||
end
|
||||
|
||||
return M
|
||||
@ -0,0 +1,66 @@
|
||||
local require = require("noice.util.lazy")
|
||||
|
||||
local Manager = require("noice.message.manager")
|
||||
local Config = require("noice.config")
|
||||
|
||||
---@type NoiceFilter
|
||||
local nothing = { ["not"] = {} }
|
||||
|
||||
---@param str string
|
||||
local function escape(str)
|
||||
return str:gsub("%%", "%%%%")
|
||||
end
|
||||
|
||||
---@param name string
|
||||
---@return NoiceStatus
|
||||
local function NoiceStatus(name)
|
||||
local function _get()
|
||||
if not Config.is_running() then
|
||||
return
|
||||
end
|
||||
local filter = Config.options.status[name] or nothing
|
||||
return Manager.get(filter, {
|
||||
count = 1,
|
||||
sort = true,
|
||||
history = true,
|
||||
})[1]
|
||||
end
|
||||
---@class NoiceStatus
|
||||
return {
|
||||
has = function()
|
||||
return _get() ~= nil
|
||||
end,
|
||||
get = function()
|
||||
local message = _get()
|
||||
if message then
|
||||
return escape(vim.trim(message:content()))
|
||||
end
|
||||
end,
|
||||
get_hl = function()
|
||||
local message = _get()
|
||||
if message and message._lines[1] then
|
||||
local ret = ""
|
||||
local line = message._lines[#message._lines]
|
||||
for _, text in ipairs(line._texts) do
|
||||
if text.extmark and text.extmark.hl_group then
|
||||
-- use hl_group
|
||||
ret = ret .. "%#" .. text.extmark.hl_group .. "#" .. escape(text:content())
|
||||
else
|
||||
-- or reset to StatusLine
|
||||
ret = ret .. "%#StatusLine#" .. escape(text:content())
|
||||
end
|
||||
end
|
||||
return ret
|
||||
end
|
||||
end,
|
||||
}
|
||||
end
|
||||
|
||||
---@type table<string, NoiceStatus>
|
||||
local status = {}
|
||||
|
||||
return setmetatable(status, {
|
||||
__index = function(_, key)
|
||||
return NoiceStatus(key)
|
||||
end,
|
||||
})
|
||||
@ -0,0 +1,110 @@
|
||||
local require = require("noice.util.lazy")
|
||||
|
||||
local View = require("noice.view")
|
||||
local Manager = require("noice.message.manager")
|
||||
local Config = require("noice.config")
|
||||
local Util = require("noice.util")
|
||||
local Message = require("noice.message")
|
||||
local Router = require("noice.message.router")
|
||||
|
||||
---@class NoiceCommand: NoiceRouteConfig
|
||||
---@field filter_opts NoiceMessageOpts
|
||||
|
||||
local M = {}
|
||||
|
||||
---@type table<string, fun()>
|
||||
M.commands = {}
|
||||
|
||||
---@param command NoiceCommand
|
||||
function M.command(command)
|
||||
return function()
|
||||
local view = View.get_view(command.view, command.opts)
|
||||
view:set(Manager.get(
|
||||
command.filter,
|
||||
vim.tbl_deep_extend("force", {
|
||||
history = true,
|
||||
sort = true,
|
||||
}, command.filter_opts or {})
|
||||
))
|
||||
view:display()
|
||||
end
|
||||
end
|
||||
|
||||
function M.cmd(cmd)
|
||||
if M.commands[cmd] then
|
||||
M.commands[cmd]()
|
||||
else
|
||||
M.commands.history()
|
||||
end
|
||||
end
|
||||
|
||||
function M.setup()
|
||||
M.commands = {
|
||||
debug = function()
|
||||
Config.options.debug = not Config.options.debug
|
||||
end,
|
||||
dismiss = function()
|
||||
Router.dismiss()
|
||||
end,
|
||||
log = function()
|
||||
vim.cmd.edit(Config.options.log)
|
||||
end,
|
||||
enable = function()
|
||||
require("noice").enable()
|
||||
end,
|
||||
disable = function()
|
||||
require("noice").disable()
|
||||
end,
|
||||
telescope = function()
|
||||
require("telescope").extensions.noice.noice({})
|
||||
end,
|
||||
stats = function()
|
||||
Manager.add(Util.stats.message())
|
||||
end,
|
||||
routes = function()
|
||||
local message = Message("noice", "debug")
|
||||
message:set(vim.inspect(Config.options.routes))
|
||||
Manager.add(message)
|
||||
end,
|
||||
config = function()
|
||||
local message = Message("noice", "debug")
|
||||
message:set(vim.inspect(Config.options))
|
||||
Manager.add(message)
|
||||
end,
|
||||
viewstats = function()
|
||||
local message = Message("noice", "debug")
|
||||
message:set(vim.inspect(require("noice.message.router").view_stats()))
|
||||
Manager.add(message)
|
||||
end,
|
||||
}
|
||||
|
||||
for name, command in pairs(Config.options.commands) do
|
||||
M.commands[name] = M.command(command)
|
||||
end
|
||||
|
||||
vim.api.nvim_create_user_command("Noice", function(args)
|
||||
local cmd = vim.trim(args.args or "")
|
||||
M.cmd(cmd)
|
||||
end, {
|
||||
nargs = "?",
|
||||
desc = "Noice",
|
||||
complete = function(_, line)
|
||||
if line:match("^%s*Noice %w+ ") then
|
||||
return {}
|
||||
end
|
||||
local prefix = line:match("^%s*Noice (%w*)") or ""
|
||||
return vim.tbl_filter(function(key)
|
||||
return key:find(prefix) == 1
|
||||
end, vim.tbl_keys(M.commands))
|
||||
end,
|
||||
})
|
||||
|
||||
for name in pairs(M.commands) do
|
||||
local cmd = "Noice" .. name:sub(1, 1):upper() .. name:sub(2)
|
||||
vim.api.nvim_create_user_command(cmd, function()
|
||||
M.cmd(name)
|
||||
end, { desc = "Noice " .. name })
|
||||
end
|
||||
end
|
||||
|
||||
return M
|
||||
@ -0,0 +1,54 @@
|
||||
local require = require("noice.util.lazy")
|
||||
|
||||
local Config = require("noice.config")
|
||||
local Highlights = require("noice.config.highlights")
|
||||
|
||||
local M = {}
|
||||
|
||||
function M.setup()
|
||||
local formats = Config.options.cmdline.format
|
||||
for name, format in pairs(formats) do
|
||||
if format == false then
|
||||
formats[name] = nil
|
||||
else
|
||||
local kind = format.kind or name
|
||||
local kind_cc = kind:sub(1, 1):upper() .. kind:sub(2)
|
||||
|
||||
local hl_group_icon = "CmdlineIcon" .. kind_cc
|
||||
Highlights.add(hl_group_icon, "NoiceCmdlineIcon")
|
||||
|
||||
local hl_group_border = "CmdlinePopupBorder" .. kind_cc
|
||||
Highlights.add(hl_group_border, "NoiceCmdlinePopupBorder")
|
||||
|
||||
format = vim.tbl_deep_extend("force", {
|
||||
conceal = format.conceal ~= false,
|
||||
kind = kind,
|
||||
icon_hl_group = "Noice" .. hl_group_icon,
|
||||
view = Config.options.cmdline.view,
|
||||
lang = format.lang or format.ft,
|
||||
opts = {
|
||||
---@diagnostic disable-next-line: undefined-field
|
||||
border = {
|
||||
text = {
|
||||
top = format.title or (" " .. kind_cc .. " "),
|
||||
},
|
||||
},
|
||||
win_options = {
|
||||
winhighlight = {
|
||||
FloatBorder = "Noice" .. hl_group_border,
|
||||
},
|
||||
},
|
||||
},
|
||||
}, { opts = vim.deepcopy(Config.options.cmdline.opts) }, format)
|
||||
formats[name] = format
|
||||
|
||||
table.insert(Config.options.routes, {
|
||||
view = format.view,
|
||||
opts = format.opts,
|
||||
filter = { event = "cmdline", kind = format.kind },
|
||||
})
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return M
|
||||
@ -0,0 +1,129 @@
|
||||
local M = {}
|
||||
|
||||
---@type table<string, NoiceFormat>
|
||||
M.builtin = {
|
||||
default = { "{level} ", "{title} ", "{message}" },
|
||||
notify = { "{message}" },
|
||||
details = {
|
||||
"{level} ",
|
||||
"{date} ",
|
||||
"{event}",
|
||||
{ "{kind}", before = { ".", hl_group = "NoiceFormatKind" } },
|
||||
" ",
|
||||
"{title} ",
|
||||
"{cmdline} ",
|
||||
"{message}",
|
||||
},
|
||||
telescope = {
|
||||
"{level} ",
|
||||
"{date} ",
|
||||
"{title} ",
|
||||
"{message}",
|
||||
},
|
||||
telescope_preview = {
|
||||
"{level} ",
|
||||
"{date} ",
|
||||
"{event}",
|
||||
{ "{kind}", before = { ".", hl_group = "NoiceFormatKind" } },
|
||||
"\n",
|
||||
"{title}\n",
|
||||
"\n",
|
||||
"{message}",
|
||||
},
|
||||
lsp_progress = {
|
||||
{
|
||||
"{progress} ",
|
||||
key = "progress.percentage",
|
||||
contents = {
|
||||
{ "{data.progress.message} " },
|
||||
},
|
||||
},
|
||||
"({data.progress.percentage}%) ",
|
||||
{ "{spinner} ", hl_group = "NoiceLspProgressSpinner" },
|
||||
{ "{data.progress.title} ", hl_group = "NoiceLspProgressTitle" },
|
||||
{ "{data.progress.client} ", hl_group = "NoiceLspProgressClient" },
|
||||
},
|
||||
lsp_progress_done = {
|
||||
{ "✔ ", hl_group = "NoiceLspProgressSpinner" },
|
||||
{ "{data.progress.title} ", hl_group = "NoiceLspProgressTitle" },
|
||||
{ "{data.progress.client} ", hl_group = "NoiceLspProgressClient" },
|
||||
},
|
||||
}
|
||||
|
||||
---@class NoiceFormatOptions
|
||||
M.defaults = {
|
||||
---@class NoiceFormatOptions.debug
|
||||
debug = {
|
||||
enabled = true,
|
||||
},
|
||||
---@class NoiceFormatOptions.cmdline
|
||||
cmdline = {},
|
||||
---@class NoiceFormatOptions.level
|
||||
level = {
|
||||
hl_group = {
|
||||
trace = "NoiceFormatLevelTrace",
|
||||
debug = "NoiceFormatLevelDebug",
|
||||
info = "NoiceFormatLevelInfo",
|
||||
warn = "NoiceFormatLevelWarn",
|
||||
error = "NoiceFormatLevelError",
|
||||
off = "NoiceFormatLevelOff",
|
||||
},
|
||||
icons = { error = " ", warn = " ", info = " " },
|
||||
},
|
||||
---@class NoiceFormatOptions.progress
|
||||
progress = {
|
||||
---@type NoiceFormat
|
||||
contents = {},
|
||||
width = 20,
|
||||
align = "right",
|
||||
key = "progress", -- key in message.opts For example: "progress.percentage"
|
||||
hl_group = "NoiceFormatProgressTodo",
|
||||
hl_group_done = "NoiceFormatProgressDone",
|
||||
},
|
||||
---@class NoiceFormatOptions.text
|
||||
text = {
|
||||
text = nil,
|
||||
hl_group = nil,
|
||||
},
|
||||
---@class NoiceFormatOptions.spinner
|
||||
spinner = {
|
||||
---@type Spinner
|
||||
name = "dots",
|
||||
hl_group = nil,
|
||||
},
|
||||
---@class NoiceFormatOptions.data
|
||||
data = {
|
||||
key = nil, -- Key in the message.opts object.
|
||||
hl_group = nil, -- Optional hl_group
|
||||
},
|
||||
---@class NoiceFormatOptions.title
|
||||
title = {
|
||||
hl_group = "NoiceFormatTitle",
|
||||
},
|
||||
---@class NoiceFormatOptions.event
|
||||
event = {
|
||||
hl_group = "NoiceFormatEvent",
|
||||
},
|
||||
---@class NoiceFormatOptions.kind
|
||||
kind = {
|
||||
hl_group = "NoiceFormatKind",
|
||||
},
|
||||
---@class NoiceFormatOptions.date
|
||||
date = {
|
||||
format = "%X", --- @see https://www.lua.org/pil/22.1.html
|
||||
hl_group = "NoiceFormatDate",
|
||||
},
|
||||
---@class NoiceFormatOptions.message
|
||||
message = {
|
||||
hl_group = nil, -- if set, then the hl_group will be used instead of the message highlights
|
||||
},
|
||||
---@class NoiceFormatOptions.confirm
|
||||
confirm = {
|
||||
hl_group = {
|
||||
choice = "NoiceFormatConfirm",
|
||||
default_choice = "NoiceFormatConfirmDefault",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
return M
|
||||
@ -0,0 +1,145 @@
|
||||
local require = require("noice.util.lazy")
|
||||
|
||||
local Util = require("noice.util")
|
||||
|
||||
-- Build docs with:
|
||||
-- lua require("noice.config.highlights").docs()
|
||||
|
||||
local M = {}
|
||||
|
||||
M.defaults = {
|
||||
Cmdline = "MsgArea", -- Normal for the classic cmdline area at the bottom"
|
||||
CmdlineIcon = "DiagnosticSignInfo", -- Cmdline icon
|
||||
CmdlineIconSearch = "DiagnosticSignWarn", -- Cmdline search icon (`/` and `?`)
|
||||
CmdlinePrompt = "Title", -- prompt for input()
|
||||
CmdlinePopup = "Normal", -- Normal for the cmdline popup
|
||||
CmdlinePopupBorder = "DiagnosticSignInfo", -- Cmdline popup border
|
||||
CmdlinePopupTitle = "DiagnosticSignInfo", -- Cmdline popup border
|
||||
CmdlinePopupBorderSearch = "DiagnosticSignWarn", -- Cmdline popup border for search
|
||||
Confirm = "Normal", -- Normal for the confirm view
|
||||
ConfirmBorder = "DiagnosticSignInfo", -- Border for the confirm view
|
||||
Cursor = "Cursor", -- Fake Cursor
|
||||
Mini = "MsgArea", -- Normal for mini view
|
||||
Popup = "NormalFloat", -- Normal for popup views
|
||||
PopupBorder = "FloatBorder", -- Border for popup views
|
||||
Popupmenu = "Pmenu", -- Normal for the popupmenu
|
||||
PopupmenuBorder = "FloatBorder", -- Popupmenu border
|
||||
PopupmenuMatch = "Special", -- Part of the item that matches the input
|
||||
PopupmenuSelected = "PmenuSel", -- Selected item in the popupmenu
|
||||
Scrollbar = "PmenuSbar", -- Normal for scrollbar
|
||||
ScrollbarThumb = "PmenuThumb", -- Scrollbar thumb
|
||||
Split = "NormalFloat", -- Normal for split views
|
||||
SplitBorder = "FloatBorder", -- Border for split views
|
||||
VirtualText = "DiagnosticVirtualTextInfo", -- Default hl group for virtualtext views
|
||||
FormatProgressDone = "Search", -- Progress bar done
|
||||
FormatProgressTodo = "CursorLine", -- progress bar todo
|
||||
FormatEvent = "NonText",
|
||||
FormatKind = "NonText",
|
||||
FormatDate = "Special",
|
||||
FormatConfirm = "CursorLine",
|
||||
FormatConfirmDefault = "Visual",
|
||||
FormatTitle = "Title",
|
||||
FormatLevelDebug = "NonText",
|
||||
FormatLevelTrace = "NonText",
|
||||
FormatLevelOff = "NonText",
|
||||
FormatLevelInfo = "DiagnosticVirtualTextInfo",
|
||||
FormatLevelWarn = "DiagnosticVirtualTextWarn",
|
||||
FormatLevelError = "DiagnosticVirtualTextError",
|
||||
LspProgressSpinner = "Constant", -- Lsp progress spinner
|
||||
LspProgressTitle = "NonText", -- Lsp progress title
|
||||
LspProgressClient = "Title", -- Lsp progress client name
|
||||
CompletionItemMenu = "none", -- Normal for the popupmenu
|
||||
CompletionItemWord = "none", -- Normal for the popupmenu
|
||||
CompletionItemKindDefault = "Special",
|
||||
CompletionItemKindColor = "NoiceCompletionItemKindDefault",
|
||||
CompletionItemKindFunction = "NoiceCompletionItemKindDefault",
|
||||
CompletionItemKindClass = "NoiceCompletionItemKindDefault",
|
||||
CompletionItemKindMethod = "NoiceCompletionItemKindDefault",
|
||||
CompletionItemKindConstructor = "NoiceCompletionItemKindDefault",
|
||||
CompletionItemKindInterface = "NoiceCompletionItemKindDefault",
|
||||
CompletionItemKindModule = "NoiceCompletionItemKindDefault",
|
||||
CompletionItemKindStruct = "NoiceCompletionItemKindDefault",
|
||||
CompletionItemKindKeyword = "NoiceCompletionItemKindDefault",
|
||||
CompletionItemKindValue = "NoiceCompletionItemKindDefault",
|
||||
CompletionItemKindProperty = "NoiceCompletionItemKindDefault",
|
||||
CompletionItemKindConstant = "NoiceCompletionItemKindDefault",
|
||||
CompletionItemKindSnippet = "NoiceCompletionItemKindDefault",
|
||||
CompletionItemKindFolder = "NoiceCompletionItemKindDefault",
|
||||
CompletionItemKindText = "NoiceCompletionItemKindDefault",
|
||||
CompletionItemKindEnumMember = "NoiceCompletionItemKindDefault",
|
||||
CompletionItemKindUnit = "NoiceCompletionItemKindDefault",
|
||||
CompletionItemKindField = "NoiceCompletionItemKindDefault",
|
||||
CompletionItemKindFile = "NoiceCompletionItemKindDefault",
|
||||
CompletionItemKindVariable = "NoiceCompletionItemKindDefault",
|
||||
CompletionItemKindEnum = "NoiceCompletionItemKindDefault",
|
||||
}
|
||||
|
||||
function M.add(hl_group, link)
|
||||
if not M.defaults[hl_group] then
|
||||
M.defaults[hl_group] = link
|
||||
end
|
||||
end
|
||||
|
||||
function M.get_link(hl_group)
|
||||
local ok, opts = pcall(vim.api.nvim_get_hl_by_name, hl_group, true)
|
||||
if opts then
|
||||
opts[vim.type_idx] = nil
|
||||
end
|
||||
if not ok or vim.tbl_isempty(opts) then
|
||||
opts = { link = hl_group }
|
||||
end
|
||||
opts.default = true
|
||||
return opts
|
||||
end
|
||||
|
||||
function M.setup()
|
||||
for hl, link in pairs(M.defaults) do
|
||||
if link ~= "none" then
|
||||
local opts = { link = link, default = true }
|
||||
|
||||
if vim.tbl_contains({ "IncSearch", "Search" }, link) then
|
||||
opts = M.get_link(link)
|
||||
end
|
||||
|
||||
vim.api.nvim_set_hl(0, "Noice" .. hl, opts)
|
||||
end
|
||||
end
|
||||
vim.api.nvim_set_hl(0, "NoiceHiddenCursor", { blend = 100, nocombine = true })
|
||||
end
|
||||
|
||||
function M.docs()
|
||||
local me = debug.getinfo(1, "S").source:sub(2)
|
||||
---@type table<string,string>
|
||||
local docs = {}
|
||||
local lines = io.open(me, "r"):lines()
|
||||
for line in lines do
|
||||
---@type string, string
|
||||
local hl, comment = line:match("%s*([a-zA-Z]+)%s*=.*%-%-%s*(.*)")
|
||||
if hl then
|
||||
docs[hl] = comment
|
||||
end
|
||||
end
|
||||
|
||||
local rows = {}
|
||||
table.insert(rows, { "Highlight Group", "Default Group", "Description" })
|
||||
table.insert(rows, { "---", "---", "---" })
|
||||
|
||||
Util.for_each(M.defaults, function(hl, link)
|
||||
table.insert(rows, { "**Noice" .. hl .. "**", "_" .. link .. "_", docs[hl] or "" })
|
||||
end)
|
||||
|
||||
local text = table.concat(
|
||||
vim.tbl_map(function(row)
|
||||
return "| " .. table.concat(row, " | ") .. " |"
|
||||
end, rows),
|
||||
"\n"
|
||||
)
|
||||
|
||||
text = "<!-- hl_start -->\n" .. text .. "\n<!-- hl_end -->"
|
||||
|
||||
local readme = Util.read_file("README.md")
|
||||
readme = readme:gsub("<%!%-%- hl_start %-%->.*<%!%-%- hl_end %-%->", text)
|
||||
Util.write_file("README.md", readme)
|
||||
end
|
||||
|
||||
return M
|
||||
@ -0,0 +1,28 @@
|
||||
local M = {}
|
||||
|
||||
---@class NoicePopupmenuItemKind
|
||||
M.kinds = {
|
||||
Class = " ",
|
||||
Color = " ",
|
||||
Constant = " ",
|
||||
Constructor = " ",
|
||||
Enum = "了 ",
|
||||
EnumMember = " ",
|
||||
Field = " ",
|
||||
File = " ",
|
||||
Folder = " ",
|
||||
Function = " ",
|
||||
Interface = " ",
|
||||
Keyword = " ",
|
||||
Method = "ƒ ",
|
||||
Module = " ",
|
||||
Property = " ",
|
||||
Snippet = " ",
|
||||
Struct = " ",
|
||||
Text = " ",
|
||||
Unit = " ",
|
||||
Value = " ",
|
||||
Variable = " ",
|
||||
}
|
||||
|
||||
return M
|
||||
@ -0,0 +1,301 @@
|
||||
local require = require("noice.util.lazy")
|
||||
|
||||
local Routes = require("noice.config.routes")
|
||||
|
||||
local M = {}
|
||||
|
||||
M.ns = vim.api.nvim_create_namespace("noice")
|
||||
|
||||
function M.defaults()
|
||||
---@class NoiceConfig
|
||||
local defaults = {
|
||||
cmdline = {
|
||||
enabled = true, -- enables the Noice cmdline UI
|
||||
view = "cmdline_popup", -- view for rendering the cmdline. Change to `cmdline` to get a classic cmdline at the bottom
|
||||
opts = {}, -- global options for the cmdline. See section on views
|
||||
---@type table<string, CmdlineFormat>
|
||||
format = {
|
||||
-- conceal: (default=true) This will hide the text in the cmdline that matches the pattern.
|
||||
-- view: (default is cmdline view)
|
||||
-- opts: any options passed to the view
|
||||
-- icon_hl_group: optional hl_group for the icon
|
||||
-- title: set to anything or empty string to hide
|
||||
cmdline = { pattern = "^:", icon = "", lang = "vim" },
|
||||
search_down = { kind = "search", pattern = "^/", icon = " ", lang = "regex" },
|
||||
search_up = { kind = "search", pattern = "^%?", icon = " ", lang = "regex" },
|
||||
filter = { pattern = "^:%s*!", icon = "$", lang = "bash" },
|
||||
lua = { pattern = { "^:%s*lua%s+", "^:%s*lua%s*=%s*", "^:%s*=%s*" }, icon = "", lang = "lua" },
|
||||
help = { pattern = "^:%s*he?l?p?%s+", icon = "" },
|
||||
calculator = { pattern = "^=", icon = "", lang = "vimnormal" },
|
||||
input = {}, -- Used by input()
|
||||
-- lua = false, -- to disable a format, set to `false`
|
||||
},
|
||||
},
|
||||
messages = {
|
||||
-- NOTE: If you enable messages, then the cmdline is enabled automatically.
|
||||
-- This is a current Neovim limitation.
|
||||
enabled = true, -- enables the Noice messages UI
|
||||
view = "notify", -- default view for messages
|
||||
view_error = "notify", -- view for errors
|
||||
view_warn = "notify", -- view for warnings
|
||||
view_history = "messages", -- view for :messages
|
||||
view_search = "virtualtext", -- view for search count messages. Set to `false` to disable
|
||||
},
|
||||
popupmenu = {
|
||||
enabled = true, -- enables the Noice popupmenu UI
|
||||
---@type 'nui'|'cmp'
|
||||
backend = "nui", -- backend to use to show regular cmdline completions
|
||||
---@type NoicePopupmenuItemKind|false
|
||||
-- Icons for completion item kinds (see defaults at noice.config.icons.kinds)
|
||||
kind_icons = {}, -- set to `false` to disable icons
|
||||
},
|
||||
-- default options for require('noice').redirect
|
||||
-- see the section on Command Redirection
|
||||
---@type NoiceRouteConfig
|
||||
redirect = {
|
||||
view = "popup",
|
||||
filter = { event = "msg_show" },
|
||||
},
|
||||
-- You can add any custom commands below that will be available with `:Noice command`
|
||||
---@type table<string, NoiceCommand>
|
||||
commands = {
|
||||
history = {
|
||||
-- options for the message history that you get with `:Noice`
|
||||
view = "split",
|
||||
opts = { enter = true, format = "details" },
|
||||
filter = {
|
||||
any = {
|
||||
{ event = "notify" },
|
||||
{ error = true },
|
||||
{ warning = true },
|
||||
{ event = "msg_show", kind = { "" } },
|
||||
{ event = "lsp", kind = "message" },
|
||||
},
|
||||
},
|
||||
},
|
||||
-- :Noice last
|
||||
last = {
|
||||
view = "popup",
|
||||
opts = { enter = true, format = "details" },
|
||||
filter = {
|
||||
any = {
|
||||
{ event = "notify" },
|
||||
{ error = true },
|
||||
{ warning = true },
|
||||
{ event = "msg_show", kind = { "" } },
|
||||
{ event = "lsp", kind = "message" },
|
||||
},
|
||||
},
|
||||
filter_opts = { count = 1 },
|
||||
},
|
||||
-- :Noice errors
|
||||
errors = {
|
||||
-- options for the message history that you get with `:Noice`
|
||||
view = "popup",
|
||||
opts = { enter = true, format = "details" },
|
||||
filter = { error = true },
|
||||
filter_opts = { reverse = true },
|
||||
},
|
||||
all = {
|
||||
-- options for the message history that you get with `:Noice`
|
||||
view = "split",
|
||||
opts = { enter = true, format = "details" },
|
||||
filter = {},
|
||||
},
|
||||
},
|
||||
notify = {
|
||||
-- Noice can be used as `vim.notify` so you can route any notification like other messages
|
||||
-- Notification messages have their level and other properties set.
|
||||
-- event is always "notify" and kind can be any log level as a string
|
||||
-- The default routes will forward notifications to nvim-notify
|
||||
-- Benefit of using Noice for this is the routing and consistent history view
|
||||
enabled = true,
|
||||
view = "notify",
|
||||
},
|
||||
lsp = {
|
||||
progress = {
|
||||
enabled = true,
|
||||
-- Lsp Progress is formatted using the builtins for lsp_progress. See config.format.builtin
|
||||
-- See the section on formatting for more details on how to customize.
|
||||
--- @type NoiceFormat|string
|
||||
format = "lsp_progress",
|
||||
--- @type NoiceFormat|string
|
||||
format_done = "lsp_progress_done",
|
||||
throttle = 1000 / 10, -- frequency to update lsp progress message
|
||||
view = "mini",
|
||||
},
|
||||
override = {
|
||||
-- override the default lsp markdown formatter with Noice
|
||||
["vim.lsp.util.convert_input_to_markdown_lines"] = false,
|
||||
-- override the lsp markdown formatter with Noice
|
||||
["vim.lsp.util.stylize_markdown"] = false,
|
||||
-- override cmp documentation with Noice (needs the other options to work)
|
||||
["cmp.entry.get_documentation"] = false,
|
||||
},
|
||||
hover = {
|
||||
enabled = true,
|
||||
silent = false, -- set to true to not show a message if hover is not available
|
||||
view = nil, -- when nil, use defaults from documentation
|
||||
---@type NoiceViewOptions
|
||||
opts = {}, -- merged with defaults from documentation
|
||||
},
|
||||
signature = {
|
||||
enabled = true,
|
||||
auto_open = {
|
||||
enabled = true,
|
||||
trigger = true, -- Automatically show signature help when typing a trigger character from the LSP
|
||||
luasnip = true, -- Will open signature help when jumping to Luasnip insert nodes
|
||||
throttle = 50, -- Debounce lsp signature help request by 50ms
|
||||
},
|
||||
view = nil, -- when nil, use defaults from documentation
|
||||
---@type NoiceViewOptions
|
||||
opts = {}, -- merged with defaults from documentation
|
||||
},
|
||||
message = {
|
||||
-- Messages shown by lsp servers
|
||||
enabled = true,
|
||||
view = "notify",
|
||||
opts = {},
|
||||
},
|
||||
-- defaults for hover and signature help
|
||||
documentation = {
|
||||
view = "hover",
|
||||
---@type NoiceViewOptions
|
||||
opts = {
|
||||
replace = true,
|
||||
render = "plain",
|
||||
format = { "{message}" },
|
||||
win_options = { concealcursor = "n", conceallevel = 3 },
|
||||
},
|
||||
},
|
||||
},
|
||||
markdown = {
|
||||
hover = {
|
||||
["|(%S-)|"] = vim.cmd.help, -- vim help links
|
||||
["%[.-%]%((%S-)%)"] = require("noice.util").open, -- markdown links
|
||||
},
|
||||
highlights = {
|
||||
["|%S-|"] = "@text.reference",
|
||||
["@%S+"] = "@parameter",
|
||||
["^%s*(Parameters:)"] = "@text.title",
|
||||
["^%s*(Return:)"] = "@text.title",
|
||||
["^%s*(See also:)"] = "@text.title",
|
||||
["{%S-}"] = "@parameter",
|
||||
},
|
||||
},
|
||||
health = {
|
||||
checker = true, -- Disable if you don't want health checks to run
|
||||
},
|
||||
smart_move = {
|
||||
-- noice tries to move out of the way of existing floating windows.
|
||||
enabled = true, -- you can disable this behaviour here
|
||||
-- add any filetypes here, that shouldn't trigger smart move.
|
||||
excluded_filetypes = { "cmp_menu", "cmp_docs", "notify" },
|
||||
},
|
||||
---@type NoicePresets
|
||||
presets = {
|
||||
-- you can enable a preset by setting it to true, or a table that will override the preset config
|
||||
-- you can also add custom presets that you can enable/disable with enabled=true
|
||||
bottom_search = false, -- use a classic bottom cmdline for search
|
||||
command_palette = false, -- position the cmdline and popupmenu together
|
||||
long_message_to_split = false, -- long messages will be sent to a split
|
||||
inc_rename = false, -- enables an input dialog for inc-rename.nvim
|
||||
lsp_doc_border = false, -- add a border to hover docs and signature help
|
||||
cmdline_output_to_split = false, -- send the output of a command you executed in the cmdline to a split
|
||||
},
|
||||
throttle = 1000 / 30, -- how frequently does Noice need to check for ui updates? This has no effect when in blocking mode.
|
||||
---@type NoiceConfigViews
|
||||
views = {}, ---@see section on views
|
||||
---@type NoiceRouteConfig[]
|
||||
routes = {}, --- @see section on routes
|
||||
---@type table<string, NoiceFilter>
|
||||
status = {}, --- @see section on statusline components
|
||||
---@type NoiceFormatOptions
|
||||
format = {}, --- @see section on formatting
|
||||
debug = false,
|
||||
log = vim.fn.stdpath("state") .. "/noice.log",
|
||||
log_max_size = 1024 * 1024 * 2, -- 10MB
|
||||
}
|
||||
return defaults
|
||||
end
|
||||
|
||||
--- @type NoiceConfig
|
||||
M.options = {}
|
||||
|
||||
M._running = false
|
||||
function M.is_running()
|
||||
return M._running
|
||||
end
|
||||
|
||||
function M.setup(options)
|
||||
options = options or {}
|
||||
|
||||
M.fix_legacy(options)
|
||||
|
||||
if options.popupmenu and options.popupmenu.kind_icons == true then
|
||||
options.popupmenu.kind_icons = nil
|
||||
end
|
||||
|
||||
M.options = vim.tbl_deep_extend("force", {}, M.defaults(), {
|
||||
views = require("noice.config.views").defaults,
|
||||
status = require("noice.config.status").defaults,
|
||||
format = require("noice.config.format").defaults,
|
||||
popupmenu = {
|
||||
kind_icons = require("noice.config.icons").kinds,
|
||||
},
|
||||
})
|
||||
|
||||
M.truncate_log()
|
||||
|
||||
require("noice.config.preset").setup(options)
|
||||
|
||||
local routes = M.options.routes
|
||||
M.options = vim.tbl_deep_extend("force", M.options, options)
|
||||
vim.list_extend(M.options.routes, routes)
|
||||
|
||||
if M.options.popupmenu.kind_icons == false then
|
||||
M.options.popupmenu.kind_icons = {}
|
||||
end
|
||||
|
||||
require("noice.config.cmdline").setup()
|
||||
|
||||
M.options.routes = Routes.get(M.options.routes)
|
||||
|
||||
require("noice.config.highlights").setup()
|
||||
vim.api.nvim_create_autocmd("ColorScheme", {
|
||||
callback = function()
|
||||
require("noice.config.highlights").setup()
|
||||
end,
|
||||
})
|
||||
|
||||
require("noice.lsp").setup()
|
||||
M._running = true
|
||||
end
|
||||
|
||||
function M.truncate_log()
|
||||
local stat = vim.loop.fs_stat(M.options.log)
|
||||
if stat and stat.size > M.options.log_max_size then
|
||||
io.open(M.options.log, "w+"):close()
|
||||
end
|
||||
end
|
||||
|
||||
---@param opts NoiceConfig
|
||||
function M.fix_legacy(opts)
|
||||
if opts.lsp and opts.lsp.signature and type(opts.lsp.signature.auto_open) == "boolean" then
|
||||
opts.lsp.signature.auto_open = {
|
||||
enabled = opts.lsp.signature.auto_open,
|
||||
}
|
||||
end
|
||||
if opts.lsp_progress then
|
||||
opts.lsp = opts.lsp or {}
|
||||
opts.lsp.progress = opts.lsp_progress
|
||||
opts.lsp_progress = nil
|
||||
end
|
||||
if opts.history then
|
||||
opts.commands = opts.commands or {}
|
||||
opts.commands.history = opts.history
|
||||
opts.history = nil
|
||||
end
|
||||
end
|
||||
|
||||
return M
|
||||
@ -0,0 +1,133 @@
|
||||
local require = require("noice.util.lazy")
|
||||
|
||||
local Util = require("noice.util")
|
||||
local Config = require("noice.config")
|
||||
|
||||
---@class NoicePreset: NoiceConfig
|
||||
---@field enabled? boolean
|
||||
|
||||
local M = {}
|
||||
|
||||
function M.setup(options)
|
||||
for name, preset in pairs(options.presets or {}) do
|
||||
if preset ~= false then
|
||||
M.load(name, preset)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
---@param name string
|
||||
---@param preset NoiceConfig|boolean
|
||||
function M.load(name, preset)
|
||||
if preset == true and not M.presets[name] then
|
||||
return Util.panic("Unknown preset " .. name)
|
||||
end
|
||||
|
||||
preset = vim.tbl_deep_extend("force", {}, M.presets[name] or {}, type(preset) == "table" and preset or {})
|
||||
---@cast preset NoicePreset
|
||||
|
||||
if preset.enabled == false then
|
||||
return
|
||||
end
|
||||
|
||||
local routes = preset.routes
|
||||
preset.routes = nil
|
||||
Config.options = vim.tbl_deep_extend("force", Config.options, preset)
|
||||
if routes then
|
||||
vim.list_extend(Config.options.routes, routes)
|
||||
end
|
||||
end
|
||||
|
||||
---@class NoicePresets: table<string, NoicePreset|boolean>
|
||||
M.presets = {
|
||||
bottom_search = {
|
||||
cmdline = {
|
||||
format = {
|
||||
search_down = {
|
||||
view = "cmdline",
|
||||
},
|
||||
search_up = {
|
||||
view = "cmdline",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
lsp_doc_border = {
|
||||
views = {
|
||||
hover = {
|
||||
border = {
|
||||
style = "rounded",
|
||||
},
|
||||
position = { row = 2, col = 2 },
|
||||
},
|
||||
},
|
||||
},
|
||||
command_palette = {
|
||||
views = {
|
||||
cmdline_popup = {
|
||||
position = {
|
||||
row = 3,
|
||||
col = "50%",
|
||||
},
|
||||
size = {
|
||||
min_width = 60,
|
||||
width = "auto",
|
||||
height = "auto",
|
||||
},
|
||||
},
|
||||
cmdline_popupmenu = {
|
||||
relative = "editor",
|
||||
position = {
|
||||
row = 6,
|
||||
col = "50%",
|
||||
},
|
||||
size = {
|
||||
width = 60,
|
||||
height = "auto",
|
||||
max_height = 15,
|
||||
},
|
||||
border = {
|
||||
style = "rounded",
|
||||
padding = { 0, 1 },
|
||||
},
|
||||
win_options = {
|
||||
winhighlight = { Normal = "Normal", FloatBorder = "NoiceCmdlinePopupBorder" },
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
long_message_to_split = {
|
||||
routes = {
|
||||
{
|
||||
filter = { event = "msg_show", min_height = 20 },
|
||||
view = "cmdline_output",
|
||||
},
|
||||
},
|
||||
},
|
||||
inc_rename = {
|
||||
cmdline = {
|
||||
format = {
|
||||
IncRename = {
|
||||
pattern = "^:%s*IncRename%s+",
|
||||
icon = " ",
|
||||
conceal = true,
|
||||
opts = {
|
||||
relative = "cursor",
|
||||
size = { min_width = 20 },
|
||||
position = { row = -3, col = 0 },
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
cmdline_output_to_split = {
|
||||
routes = {
|
||||
{
|
||||
view = "cmdline_output",
|
||||
filter = { cmdline = "^:" },
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
return M
|
||||
@ -0,0 +1,125 @@
|
||||
local require = require("noice.util.lazy")
|
||||
|
||||
local Config = require("noice.config")
|
||||
|
||||
local M = {}
|
||||
|
||||
---@param routes? NoiceRouteConfig[]
|
||||
function M.get(routes)
|
||||
---@type NoiceRouteConfig[]
|
||||
local ret = {}
|
||||
|
||||
-- add custom routes
|
||||
vim.list_extend(ret, routes or {})
|
||||
|
||||
-- add default routes
|
||||
vim.list_extend(ret, M.defaults())
|
||||
return ret
|
||||
end
|
||||
|
||||
---@return NoiceRouteConfig[]
|
||||
function M.defaults()
|
||||
---@type NoiceRouteConfig[]
|
||||
local ret = {}
|
||||
|
||||
for _, kind in ipairs({ "signature", "hover" }) do
|
||||
table.insert(ret, {
|
||||
view = Config.options.lsp[kind].view or Config.options.lsp.documentation.view,
|
||||
filter = { event = "lsp", kind = kind },
|
||||
opts = vim.tbl_deep_extend(
|
||||
"force",
|
||||
{},
|
||||
Config.options.lsp.documentation.opts,
|
||||
Config.options.lsp[kind].opts or {}
|
||||
),
|
||||
})
|
||||
end
|
||||
|
||||
return vim.list_extend(ret, {
|
||||
{
|
||||
view = Config.options.cmdline.view,
|
||||
opts = Config.options.cmdline.opts,
|
||||
filter = { event = "cmdline" },
|
||||
},
|
||||
{
|
||||
view = "confirm",
|
||||
filter = {
|
||||
any = {
|
||||
{ event = "msg_show", kind = "confirm" },
|
||||
{ event = "msg_show", kind = "confirm_sub" },
|
||||
-- { event = "msg_show", kind = { "echo", "echomsg", "" }, before = true },
|
||||
-- { event = "msg_show", kind = { "echo", "echomsg" }, instant = true },
|
||||
-- { event = "msg_show", find = "E325" },
|
||||
-- { event = "msg_show", find = "Found a swap file" },
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
view = Config.options.messages.view_history,
|
||||
filter = {
|
||||
any = {
|
||||
{ event = "msg_history_show" },
|
||||
-- { min_height = 20 },
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
view = Config.options.messages.view_search,
|
||||
filter = {
|
||||
event = "msg_show",
|
||||
kind = "search_count",
|
||||
},
|
||||
},
|
||||
{
|
||||
filter = {
|
||||
any = {
|
||||
{ event = { "msg_showmode", "msg_showcmd", "msg_ruler" } },
|
||||
{ event = "msg_show", kind = "search_count" },
|
||||
},
|
||||
},
|
||||
opts = { skip = true },
|
||||
},
|
||||
{
|
||||
view = Config.options.messages.view,
|
||||
filter = {
|
||||
event = "msg_show",
|
||||
kind = { "", "echo", "echomsg" },
|
||||
},
|
||||
opts = { replace = true, merge = true, title = "Messages" },
|
||||
},
|
||||
{
|
||||
view = Config.options.messages.view_error,
|
||||
filter = { error = true },
|
||||
opts = { title = "Error" },
|
||||
},
|
||||
{
|
||||
view = Config.options.messages.view_warn,
|
||||
filter = { warning = true },
|
||||
opts = { title = "Warning" },
|
||||
},
|
||||
{
|
||||
view = Config.options.notify.view,
|
||||
filter = { event = "notify" },
|
||||
opts = { title = "Notify" },
|
||||
},
|
||||
{
|
||||
view = Config.options.notify.view,
|
||||
filter = {
|
||||
event = "noice",
|
||||
kind = { "stats", "debug" },
|
||||
},
|
||||
opts = { lang = "lua", replace = true, title = "Noice" },
|
||||
},
|
||||
{
|
||||
view = Config.options.lsp.progress.view,
|
||||
filter = { event = "lsp", kind = "progress" },
|
||||
},
|
||||
{
|
||||
view = Config.options.lsp.message.view,
|
||||
opts = Config.options.lsp.message.opts,
|
||||
filter = { event = "lsp", kind = "message" },
|
||||
},
|
||||
})
|
||||
end
|
||||
|
||||
return M
|
||||
@ -0,0 +1,16 @@
|
||||
local require = require("noice.util.lazy")
|
||||
|
||||
local Msg = require("noice.ui.msg")
|
||||
|
||||
local M = {}
|
||||
|
||||
---@type table<string, NoiceFilter>
|
||||
M.defaults = {
|
||||
ruler = { event = Msg.events.ruler },
|
||||
message = { event = Msg.events.show },
|
||||
command = { event = Msg.events.showcmd },
|
||||
mode = { event = Msg.events.showmode },
|
||||
search = { event = Msg.events.show, kind = Msg.kinds.search_count },
|
||||
}
|
||||
|
||||
return M
|
||||
@ -0,0 +1,259 @@
|
||||
local require = require("noice.util.lazy")
|
||||
|
||||
local Util = require("noice.util")
|
||||
local Config = require("noice.config")
|
||||
|
||||
local M = {}
|
||||
|
||||
---@param view string
|
||||
---@return NoiceViewOptions
|
||||
function M.get_options(view)
|
||||
if not view then
|
||||
Util.panic("View is missing?")
|
||||
end
|
||||
|
||||
local opts = { view = view }
|
||||
|
||||
local done = {}
|
||||
while opts.view and not done[opts.view] do
|
||||
done[opts.view] = true
|
||||
|
||||
local view_opts = vim.deepcopy(Config.options.views[opts.view] or {})
|
||||
opts = vim.tbl_deep_extend("keep", opts, view_opts)
|
||||
opts.view = view_opts.view
|
||||
end
|
||||
|
||||
return opts
|
||||
end
|
||||
|
||||
---@class NoiceConfigViews: table<string, NoiceViewOptions>
|
||||
M.defaults = {
|
||||
popupmenu = {
|
||||
relative = "editor",
|
||||
zindex = 65,
|
||||
position = "auto", -- when auto, then it will be positioned to the cmdline or cursor
|
||||
size = {
|
||||
width = "auto",
|
||||
height = "auto",
|
||||
max_height = 20,
|
||||
-- min_width = 10,
|
||||
},
|
||||
win_options = {
|
||||
winbar = "",
|
||||
foldenable = false,
|
||||
cursorline = true,
|
||||
cursorlineopt = "line",
|
||||
winhighlight = {
|
||||
Normal = "NoicePopupmenu", -- change to NormalFloat to make it look like other floats
|
||||
FloatBorder = "NoicePopupmenuBorder", -- border highlight
|
||||
CursorLine = "NoicePopupmenuSelected", -- used for highlighting the selected item
|
||||
PmenuMatch = "NoicePopupmenuMatch", -- used to highlight the part of the item that matches the input
|
||||
},
|
||||
},
|
||||
border = {
|
||||
padding = { 0, 1 },
|
||||
},
|
||||
},
|
||||
cmdline_popupmenu = {
|
||||
view = "popupmenu",
|
||||
zindex = 200,
|
||||
},
|
||||
virtualtext = {
|
||||
backend = "virtualtext",
|
||||
format = { "{message}" },
|
||||
hl_group = "NoiceVirtualText",
|
||||
},
|
||||
notify = {
|
||||
backend = "notify",
|
||||
fallback = "mini",
|
||||
format = "notify",
|
||||
replace = false,
|
||||
merge = false,
|
||||
},
|
||||
split = {
|
||||
backend = "split",
|
||||
enter = false,
|
||||
relative = "editor",
|
||||
position = "bottom",
|
||||
size = "20%",
|
||||
close = {
|
||||
keys = { "q" },
|
||||
},
|
||||
win_options = {
|
||||
winhighlight = { Normal = "NoiceSplit", FloatBorder = "NoiceSplitBorder" },
|
||||
wrap = true,
|
||||
},
|
||||
},
|
||||
cmdline_output = {
|
||||
format = "details",
|
||||
view = "split",
|
||||
},
|
||||
messages = {
|
||||
view = "split",
|
||||
enter = true,
|
||||
},
|
||||
vsplit = {
|
||||
view = "split",
|
||||
position = "right",
|
||||
},
|
||||
popup = {
|
||||
backend = "popup",
|
||||
relative = "editor",
|
||||
close = {
|
||||
events = { "BufLeave" },
|
||||
keys = { "q" },
|
||||
},
|
||||
enter = true,
|
||||
border = {
|
||||
style = "rounded",
|
||||
},
|
||||
position = "50%",
|
||||
size = {
|
||||
width = "120",
|
||||
height = "20",
|
||||
},
|
||||
win_options = {
|
||||
winhighlight = { Normal = "NoicePopup", FloatBorder = "NoicePopupBorder" },
|
||||
winbar = "",
|
||||
foldenable = false,
|
||||
},
|
||||
},
|
||||
hover = {
|
||||
view = "popup",
|
||||
relative = "cursor",
|
||||
zindex = 45,
|
||||
enter = false,
|
||||
anchor = "auto",
|
||||
size = {
|
||||
width = "auto",
|
||||
height = "auto",
|
||||
max_height = 20,
|
||||
max_width = 120,
|
||||
},
|
||||
border = {
|
||||
style = "none",
|
||||
padding = { 0, 2 },
|
||||
},
|
||||
position = { row = 1, col = 0 },
|
||||
win_options = {
|
||||
wrap = true,
|
||||
linebreak = true,
|
||||
},
|
||||
},
|
||||
cmdline = {
|
||||
backend = "popup",
|
||||
relative = "editor",
|
||||
position = {
|
||||
row = "100%",
|
||||
col = 0,
|
||||
},
|
||||
size = {
|
||||
height = "auto",
|
||||
width = "100%",
|
||||
},
|
||||
border = {
|
||||
style = "none",
|
||||
},
|
||||
win_options = {
|
||||
winhighlight = {
|
||||
Normal = "NoiceCmdline",
|
||||
IncSearch = "",
|
||||
CurSearch = "",
|
||||
Search = "",
|
||||
},
|
||||
},
|
||||
},
|
||||
mini = {
|
||||
backend = "mini",
|
||||
relative = "editor",
|
||||
align = "message-right",
|
||||
timeout = 2000,
|
||||
reverse = true,
|
||||
focusable = false,
|
||||
position = {
|
||||
row = -1,
|
||||
col = "100%",
|
||||
-- col = 0,
|
||||
},
|
||||
size = "auto",
|
||||
border = {
|
||||
style = "none",
|
||||
},
|
||||
zindex = 60,
|
||||
win_options = {
|
||||
winbar = "",
|
||||
foldenable = false,
|
||||
winblend = 30,
|
||||
winhighlight = {
|
||||
Normal = "NoiceMini",
|
||||
IncSearch = "",
|
||||
CurSearch = "",
|
||||
Search = "",
|
||||
},
|
||||
},
|
||||
},
|
||||
cmdline_popup = {
|
||||
backend = "popup",
|
||||
relative = "editor",
|
||||
focusable = false,
|
||||
enter = false,
|
||||
zindex = 200,
|
||||
position = {
|
||||
row = "50%",
|
||||
col = "50%",
|
||||
},
|
||||
size = {
|
||||
min_width = 60,
|
||||
width = "auto",
|
||||
height = "auto",
|
||||
},
|
||||
border = {
|
||||
style = "rounded",
|
||||
padding = { 0, 1 },
|
||||
},
|
||||
win_options = {
|
||||
winhighlight = {
|
||||
Normal = "NoiceCmdlinePopup",
|
||||
FloatTitle = "NoiceCmdlinePopupTitle",
|
||||
FloatBorder = "NoiceCmdlinePopupBorder",
|
||||
IncSearch = "",
|
||||
CurSearch = "",
|
||||
Search = "",
|
||||
},
|
||||
winbar = "",
|
||||
foldenable = false,
|
||||
cursorline = false,
|
||||
},
|
||||
},
|
||||
confirm = {
|
||||
backend = "popup",
|
||||
relative = "editor",
|
||||
focusable = false,
|
||||
align = "center",
|
||||
enter = false,
|
||||
zindex = 210,
|
||||
format = { "{confirm}" },
|
||||
position = {
|
||||
row = "50%",
|
||||
col = "50%",
|
||||
},
|
||||
size = "auto",
|
||||
border = {
|
||||
style = "rounded",
|
||||
padding = { 0, 1 },
|
||||
text = {
|
||||
top = " Confirm ",
|
||||
},
|
||||
},
|
||||
win_options = {
|
||||
winhighlight = {
|
||||
Normal = "NoiceConfirm",
|
||||
FloatBorder = "NoiceConfirmBorder",
|
||||
},
|
||||
winbar = "",
|
||||
foldenable = false,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
return M
|
||||
242
config/neovim/store/lazy-plugins/noice.nvim/lua/noice/health.lua
Normal file
242
config/neovim/store/lazy-plugins/noice.nvim/lua/noice/health.lua
Normal file
@ -0,0 +1,242 @@
|
||||
local require = require("noice.util.lazy")
|
||||
|
||||
local Util = require("noice.util")
|
||||
local Config = require("noice.config")
|
||||
local Lsp = require("noice.lsp")
|
||||
local Treesitter = require("noice.text.treesitter")
|
||||
|
||||
local start = vim.health.start or vim.health.report_start
|
||||
local ok = vim.health.ok or vim.health.report_ok
|
||||
local warn = vim.health.warn or vim.health.report_warn
|
||||
local error = vim.health.error or vim.health.report_error
|
||||
|
||||
local M = {}
|
||||
|
||||
M.checks = {}
|
||||
|
||||
M.log = {
|
||||
---@class NoiceHealthLog
|
||||
checkhealth = {
|
||||
start = function(msg)
|
||||
start(msg or "noice.nvim")
|
||||
end,
|
||||
info = function(msg, ...)
|
||||
info(msg:format(...))
|
||||
end,
|
||||
ok = function(msg, ...)
|
||||
ok(msg:format(...))
|
||||
end,
|
||||
warn = function(msg, ...)
|
||||
warn(msg:format(...))
|
||||
end,
|
||||
error = function(msg, ...)
|
||||
error(msg:format(...))
|
||||
end,
|
||||
},
|
||||
---@type NoiceHealthLog
|
||||
notify = {
|
||||
start = function(msg) end,
|
||||
info = function(msg, ...)
|
||||
Util.info(msg:format(...))
|
||||
end,
|
||||
ok = function(msg, ...) end,
|
||||
warn = function(msg, ...)
|
||||
Util.warn_once(msg:format(...))
|
||||
end,
|
||||
error = function(msg, ...)
|
||||
Util.error_once(msg:format(...))
|
||||
end,
|
||||
},
|
||||
}
|
||||
|
||||
---@param opts? {checkhealth?: boolean}
|
||||
function M.check(opts)
|
||||
opts = opts or {}
|
||||
opts.checkhealth = opts.checkhealth == nil and true or opts.checkhealth
|
||||
|
||||
local log = opts.checkhealth and M.log.checkhealth or M.log.notify
|
||||
|
||||
log.start()
|
||||
|
||||
if vim.fn.has("nvim-0.9.0") ~= 1 then
|
||||
log.error("Noice requires Neovim >= 0.9.0")
|
||||
-- require("noice.util").error("Noice needs Neovim >= 0.9.0 (nightly)")
|
||||
if not opts.checkhealth then
|
||||
return
|
||||
end
|
||||
else
|
||||
log.ok("**Neovim** >= 0.9.0")
|
||||
if opts.checkhealth and vim.fn.has("nvim-0.10.0") ~= 1 then
|
||||
log.warn("**Neovim** >= 0.10 is highly recommended, since it fixes some issues related to `vim.ui_attach`")
|
||||
end
|
||||
end
|
||||
|
||||
local uis = vim.api.nvim_list_uis()
|
||||
for _, ui in ipairs(uis) do
|
||||
local ok = true
|
||||
for _, ext in ipairs({ "ext_cmdline", "ext_popupmenu", "ext_messages" }) do
|
||||
if ui[ext] then
|
||||
ok = false
|
||||
log.error(
|
||||
"You're using a GUI that uses " .. ext .. ". Noice can't work when the GUI has " .. ext .. " enabled."
|
||||
)
|
||||
end
|
||||
end
|
||||
if ok then
|
||||
if ui.chan == 0 then
|
||||
log.ok("You're not using a GUI")
|
||||
else
|
||||
log.ok("You're using a GUI that should work ok")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if vim.go.lazyredraw then
|
||||
if not Config.is_running() then
|
||||
log.warn(
|
||||
"You have enabled 'lazyredraw' (see `:h 'lazyredraw'`)\nThis is only meant to be set temporarily.\nYou'll experience issues using Noice."
|
||||
)
|
||||
end
|
||||
else
|
||||
log.ok("**vim.go.lazyredraw** is not enabled")
|
||||
end
|
||||
|
||||
if opts.checkhealth then
|
||||
if not Util.module_exists("notify") then
|
||||
log.warn("Noice needs nvim-notify for routes using the `notify` view")
|
||||
if not opts.checkhealth then
|
||||
return
|
||||
end
|
||||
else
|
||||
log.ok("**nvim-notify** is installed")
|
||||
end
|
||||
|
||||
if vim.o.shortmess:find("S") then
|
||||
log.warn(
|
||||
"You added `S` to `vim.opt.shortmess`. Search count messages will not be handled by Noice. So no virtual text for search count."
|
||||
)
|
||||
end
|
||||
|
||||
for _, lang in ipairs({ "vim", "regex", "lua", "bash", "markdown", "markdown_inline" }) do
|
||||
if Treesitter.has_lang(lang) then
|
||||
log.ok("**TreeSitter " .. lang .. "** parser is installed")
|
||||
else
|
||||
log.warn(
|
||||
"**TreeSitter "
|
||||
.. lang
|
||||
.. "** parser is not installed. Highlighting of the cmdline for "
|
||||
.. lang
|
||||
.. " might be broken"
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if Config.is_running() then
|
||||
---@type {opt:string[], opt_str?:string, handler:fun(), handler_str:string}
|
||||
local checks = {
|
||||
{
|
||||
opt = "notify",
|
||||
enabled = Config.options.notify.enabled,
|
||||
handler = vim.notify,
|
||||
handler_str = "vim.notify",
|
||||
},
|
||||
{
|
||||
opt = "lsp.hover",
|
||||
enabled = Config.options.lsp.hover.enabled,
|
||||
handler = vim.lsp.handlers["textDocument/hover"],
|
||||
handler_str = 'vim.lsp.handlers["textDocument/hover"]',
|
||||
},
|
||||
{
|
||||
opt = "lsp.signature",
|
||||
enabled = Config.options.lsp.signature.enabled,
|
||||
handler = vim.lsp.handlers["textDocument/signatureHelp"],
|
||||
handler_str = 'vim.lsp.handlers["textDocument/signatureHelp"]',
|
||||
},
|
||||
{
|
||||
opt = "lsp.message",
|
||||
enabled = Config.options.lsp.message.enabled,
|
||||
handler = vim.lsp.handlers["window/showMessage"],
|
||||
handler_str = 'vim.lsp.handlers["window/showMessage"]',
|
||||
},
|
||||
{
|
||||
opt = 'lsp.override["vim.lsp.util.convert_input_to_markdown_lines"]',
|
||||
enabled = Config.options.lsp.override["vim.lsp.util.convert_input_to_markdown_lines"],
|
||||
handler = vim.lsp.util.convert_input_to_markdown_lines,
|
||||
handler_str = "vim.lsp.util.convert_input_to_markdown_lines",
|
||||
},
|
||||
{
|
||||
opt = 'lsp.override["vim.lsp.util.stylize_markdown"]',
|
||||
enabled = Config.options.lsp.override["vim.lsp.util.stylize_markdown"],
|
||||
handler = vim.lsp.util.stylize_markdown,
|
||||
handler_str = "vim.lsp.util.stylize_markdown",
|
||||
},
|
||||
}
|
||||
|
||||
if package.loaded["cmp.entry"] then
|
||||
local mod = package.loaded["cmp.entry"]
|
||||
table.insert(checks, {
|
||||
opt = 'lsp.override["cmp.entry.get_documentation"]',
|
||||
enabled = Config.options.lsp.override["cmp.entry.get_documentation"],
|
||||
handler = mod.get_documentation,
|
||||
handler_str = "cmp.entry.get_documentation",
|
||||
})
|
||||
end
|
||||
|
||||
for _, check in ipairs(checks) do
|
||||
if check.handler then
|
||||
if check.enabled then
|
||||
local source = M.get_source(check.handler)
|
||||
if source.plugin ~= "noice.nvim" then
|
||||
log.error(([[`%s` has been overwritten by another plugin?
|
||||
|
||||
Either disable the other plugin or set `config.%s.enabled = false` in your **Noice** config.
|
||||
- plugin: %s
|
||||
- file: %s
|
||||
- line: %s]]):format(check.handler_str, check.opt, source.plugin, source.source, source.line))
|
||||
else
|
||||
log.ok(("`%s` is set to **Noice**"):format(check.handler_str))
|
||||
end
|
||||
elseif opts.checkhealth then
|
||||
log.warn("`" .. check.handler_str .. "` is not configured to be handled by **Noice**")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
function M.get_source(fn)
|
||||
local info = debug.getinfo(fn, "S")
|
||||
local source = info.source:sub(2)
|
||||
---@class FunSource
|
||||
local ret = {
|
||||
line = info.linedefined,
|
||||
source = source,
|
||||
plugin = "unknown",
|
||||
}
|
||||
if source:find("noice") then
|
||||
ret.plugin = "noice.nvim"
|
||||
elseif source:find("/runtime/lua/") then
|
||||
ret.plugin = "nvim"
|
||||
else
|
||||
local opt = source:match("/pack/[^%/]-/opt/([^%/]-)/")
|
||||
local start = source:match("/pack/[^%/]-/start/([^%/]-)/")
|
||||
ret.plugin = opt or start or "unknown"
|
||||
end
|
||||
return ret
|
||||
end
|
||||
M.check({ checkhealth = false })
|
||||
|
||||
M.checker = Util.interval(1000, function()
|
||||
if Config.is_running() then
|
||||
M.check({ checkhealth = false })
|
||||
end
|
||||
end, {
|
||||
enabled = function()
|
||||
return Config.is_running()
|
||||
end,
|
||||
})
|
||||
|
||||
return M
|
||||
@ -0,0 +1,83 @@
|
||||
local require = require("noice.util.lazy")
|
||||
|
||||
local Health = require("noice.health")
|
||||
local Api = require("noice.api")
|
||||
local Config = require("noice.config")
|
||||
|
||||
local M = {}
|
||||
|
||||
M.api = Api
|
||||
|
||||
---@param opts? NoiceConfig
|
||||
function M.setup(opts)
|
||||
-- run some checks before setting up
|
||||
if not Health.check({ checkhealth = false, loaded = false }) then
|
||||
return
|
||||
end
|
||||
|
||||
local function load()
|
||||
require("noice.util").try(function()
|
||||
require("noice.config").setup(opts)
|
||||
require("noice.commands").setup()
|
||||
require("noice.message.router").setup()
|
||||
M.enable()
|
||||
end)
|
||||
end
|
||||
|
||||
if vim.v.vim_did_enter == 0 then
|
||||
-- Schedule loading after VimEnter. Get the UI up and running first.
|
||||
vim.api.nvim_create_autocmd("VimEnter", {
|
||||
once = true,
|
||||
callback = load,
|
||||
})
|
||||
else
|
||||
-- Schedule on the event loop
|
||||
vim.schedule(load)
|
||||
end
|
||||
end
|
||||
|
||||
function M.disable()
|
||||
Config._running = false
|
||||
if Config.options.notify.enabled then
|
||||
require("noice.source.notify").disable()
|
||||
end
|
||||
require("noice.message.router").disable()
|
||||
require("noice.ui").disable()
|
||||
require("noice.util.hacks").disable()
|
||||
end
|
||||
|
||||
M.deactivate = M.disable
|
||||
|
||||
function M.cmd(name)
|
||||
require("noice.commands").cmd(name)
|
||||
end
|
||||
|
||||
function M.enable()
|
||||
Config._running = true
|
||||
if Config.options.notify.enabled then
|
||||
require("noice.source.notify").enable()
|
||||
end
|
||||
require("noice.util.hacks").enable()
|
||||
require("noice.ui").enable()
|
||||
require("noice.message.router").enable()
|
||||
|
||||
if Config.options.health.checker then
|
||||
Health.checker()
|
||||
end
|
||||
end
|
||||
|
||||
-- Redirect any messages generated by a command or function
|
||||
---@param cmd string|fun() command or function to execute
|
||||
---@param routes? NoiceRouteConfig[] custom routes. Defaults to `config.redirect`
|
||||
function M.redirect(cmd, routes)
|
||||
return require("noice.message.router").redirect(cmd, routes)
|
||||
end
|
||||
|
||||
---@param msg string
|
||||
---@param level number|string
|
||||
---@param opts? table<string, any>
|
||||
function M.notify(msg, level, opts)
|
||||
return require("noice.source.notify").notify(msg, level, opts)
|
||||
end
|
||||
|
||||
return M
|
||||
@ -0,0 +1,82 @@
|
||||
local require = require("noice.util.lazy")
|
||||
|
||||
local Manager = require("noice.message.manager")
|
||||
local Util = require("noice.util")
|
||||
local Message = require("noice.message")
|
||||
|
||||
local M = {}
|
||||
|
||||
---@type table<LspKind, NoiceMessage>
|
||||
M._messages = {}
|
||||
|
||||
---@type number?
|
||||
M._autohide = nil
|
||||
|
||||
function M.autohide()
|
||||
if not M._autohide then
|
||||
M._autohide = vim.api.nvim_create_autocmd({ "CursorMoved", "CursorMovedI", "InsertEnter" }, {
|
||||
group = vim.api.nvim_create_augroup("noice_lsp_docs", { clear = true }),
|
||||
callback = function()
|
||||
vim.defer_fn(M.on_close, 10)
|
||||
end,
|
||||
})
|
||||
end
|
||||
end
|
||||
|
||||
---@param kind LspKind
|
||||
function M.get(kind)
|
||||
if not M._messages[kind] then
|
||||
M._messages[kind] = Message("lsp", kind)
|
||||
M._messages[kind].opts.title = kind
|
||||
end
|
||||
M._messages[kind]:clear()
|
||||
return M._messages[kind]
|
||||
end
|
||||
|
||||
function M.on_close()
|
||||
for _, message in pairs(M._messages) do
|
||||
-- close the message if we're not in it's buffer (focus)
|
||||
local keep = message:on_buf(vim.api.nvim_get_current_buf()) or (message.opts.stay and message.opts.stay())
|
||||
if not keep then
|
||||
M.hide(message)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function M.scroll(delta)
|
||||
for _, kind in ipairs({ "hover", "signature" }) do
|
||||
local message = M.get(kind)
|
||||
local win = message:win()
|
||||
if win then
|
||||
Util.nui.scroll(win, delta)
|
||||
return true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
---@param message NoiceMessage
|
||||
function M.hide(message)
|
||||
message.opts.keep = function()
|
||||
return false
|
||||
end
|
||||
Manager.remove(message)
|
||||
end
|
||||
|
||||
---@param message NoiceMessage
|
||||
---@param stay? fun():boolean
|
||||
function M.show(message, stay)
|
||||
M.autohide()
|
||||
message.opts.timeout = 100
|
||||
message.opts.keep = function()
|
||||
return true
|
||||
end
|
||||
message.opts.stay = stay
|
||||
for _, m in pairs(M._messages) do
|
||||
if m ~= message then
|
||||
M.hide(m)
|
||||
end
|
||||
end
|
||||
Manager.add(message)
|
||||
end
|
||||
|
||||
return M
|
||||
@ -0,0 +1,53 @@
|
||||
local require = require("noice.util.lazy")
|
||||
local Util = require("noice.util")
|
||||
|
||||
local Markdown = require("noice.text.markdown")
|
||||
|
||||
---@alias MarkedString string | { language: string; value: string }
|
||||
---@alias MarkupContent { kind: ('plaintext' | 'markdown'), value: string}
|
||||
---@alias MarkupContents MarkedString | MarkedString[] | MarkupContent
|
||||
|
||||
local M = {}
|
||||
|
||||
-- Formats the content and adds it to the message
|
||||
---@param contents MarkupContents Markup content
|
||||
function M.format_markdown(contents)
|
||||
if type(contents) ~= "table" or not Util.islist(contents) then
|
||||
contents = { contents }
|
||||
end
|
||||
|
||||
local parts = {}
|
||||
|
||||
for _, content in ipairs(contents) do
|
||||
if type(content) == "string" then
|
||||
table.insert(parts, content)
|
||||
elseif content.language then
|
||||
table.insert(parts, ("```%s\n%s\n```"):format(content.language, content.value))
|
||||
elseif content.kind == "markdown" then
|
||||
table.insert(parts, content.value)
|
||||
elseif content.kind == "plaintext" then
|
||||
table.insert(parts, ("```\n%s\n```"):format(content.value))
|
||||
elseif Util.islist(content) then
|
||||
vim.list_extend(parts, M.format_markdown(content))
|
||||
elseif type(content) == "table" and next(content) == nil then
|
||||
goto continue
|
||||
else
|
||||
error("Unknown markup " .. vim.inspect(content))
|
||||
end
|
||||
::continue::
|
||||
end
|
||||
|
||||
return vim.split(table.concat(parts, "\n"), "\n")
|
||||
end
|
||||
|
||||
-- Formats the content and adds it to the message
|
||||
---@param contents MarkupContents Markup content
|
||||
---@param message NoiceMessage Noice message
|
||||
---@param opts? MarkdownFormatOptions
|
||||
function M.format(message, contents, opts)
|
||||
local text = table.concat(M.format_markdown(contents), "\n")
|
||||
Markdown.format(message, text, opts)
|
||||
return message
|
||||
end
|
||||
|
||||
return M
|
||||
@ -0,0 +1,37 @@
|
||||
local require = require("noice.util.lazy")
|
||||
|
||||
local Format = require("noice.lsp.format")
|
||||
local Util = require("noice.util")
|
||||
local Docs = require("noice.lsp.docs")
|
||||
local Config = require("noice.config")
|
||||
|
||||
local M = {}
|
||||
|
||||
function M.setup()
|
||||
vim.lsp.handlers["textDocument/hover"] = M.on_hover
|
||||
end
|
||||
|
||||
function M.on_hover(_, result, ctx)
|
||||
if not (result and result.contents) then
|
||||
if Config.options.lsp.hover.silent ~= true then
|
||||
vim.notify("No information available")
|
||||
end
|
||||
return
|
||||
end
|
||||
|
||||
local message = Docs.get("hover")
|
||||
|
||||
if not message:focus() then
|
||||
Format.format(message, result.contents, { ft = vim.bo[ctx.bufnr].filetype })
|
||||
if message:is_empty() then
|
||||
if Config.options.lsp.hover.silent ~= true then
|
||||
vim.notify("No information available")
|
||||
end
|
||||
return
|
||||
end
|
||||
Docs.show(message)
|
||||
end
|
||||
end
|
||||
M.on_hover = Util.protect(M.on_hover)
|
||||
|
||||
return M
|
||||
@ -0,0 +1,64 @@
|
||||
local require = require("noice.util.lazy")
|
||||
|
||||
local Config = require("noice.config")
|
||||
|
||||
local M = {}
|
||||
|
||||
---@alias LspEvent "lsp"
|
||||
M.event = "lsp"
|
||||
|
||||
---@enum LspKind
|
||||
M.kinds = {
|
||||
progress = "progress",
|
||||
hover = "hover",
|
||||
message = "message",
|
||||
signature = "signature",
|
||||
}
|
||||
|
||||
function M.setup()
|
||||
if Config.options.lsp.hover.enabled then
|
||||
require("noice.lsp.hover").setup()
|
||||
end
|
||||
|
||||
if Config.options.lsp.signature.enabled then
|
||||
require("noice.lsp.signature").setup()
|
||||
end
|
||||
|
||||
if Config.options.lsp.message.enabled then
|
||||
require("noice.lsp.message").setup()
|
||||
end
|
||||
|
||||
if Config.options.lsp.progress.enabled then
|
||||
require("noice.lsp.progress").setup()
|
||||
end
|
||||
|
||||
local overrides = vim.tbl_filter(
|
||||
---@param v boolean
|
||||
function(v)
|
||||
return v
|
||||
end,
|
||||
Config.options.lsp.override
|
||||
)
|
||||
|
||||
if #overrides > 0 then
|
||||
require("noice.lsp.override").setup()
|
||||
end
|
||||
end
|
||||
|
||||
function M.scroll(delta)
|
||||
return require("noice.lsp.docs").scroll(delta)
|
||||
end
|
||||
|
||||
function M.hover()
|
||||
---@diagnostic disable-next-line: missing-parameter
|
||||
local params = vim.lsp.util.make_position_params()
|
||||
vim.lsp.buf_request(0, "textDocument/hover", params, require("noice.lsp.hover").on_hover)
|
||||
end
|
||||
|
||||
function M.signature()
|
||||
---@diagnostic disable-next-line: missing-parameter
|
||||
local params = vim.lsp.util.make_position_params()
|
||||
vim.lsp.buf_request(0, "textDocument/signatureHelp", params, require("noice.lsp.signature").on_signature)
|
||||
end
|
||||
|
||||
return M
|
||||
@ -0,0 +1,40 @@
|
||||
local require = require("noice.util.lazy")
|
||||
|
||||
local Manager = require("noice.message.manager")
|
||||
local Message = require("noice.message")
|
||||
local Util = require("noice.util")
|
||||
|
||||
local M = {}
|
||||
|
||||
---@enum MessageType
|
||||
M.message_type = {
|
||||
error = 1,
|
||||
warn = 2,
|
||||
info = 3,
|
||||
debug = 4,
|
||||
}
|
||||
|
||||
---@alias ShowMessageParams {type:MessageType, message:string}
|
||||
|
||||
function M.setup()
|
||||
vim.lsp.handlers["window/showMessage"] = Util.protect(M.on_message)
|
||||
end
|
||||
|
||||
---@param result ShowMessageParams
|
||||
function M.on_message(_, result, ctx)
|
||||
---@type number
|
||||
local client_id = ctx.client_id
|
||||
local client = vim.lsp.get_client_by_id(client_id)
|
||||
local client_name = client and client.name or string.format("lsp id=%d", client_id)
|
||||
|
||||
local message = Message("lsp", "message", result.message)
|
||||
message.opts.title = "LSP Message (" .. client_name .. ")"
|
||||
for level, type in pairs(M.message_type) do
|
||||
if type == result.type then
|
||||
message.level = level
|
||||
end
|
||||
end
|
||||
Manager.add(message)
|
||||
end
|
||||
|
||||
return M
|
||||
@ -0,0 +1,59 @@
|
||||
local require = require("noice.util.lazy")
|
||||
local Markdown = require("noice.text.markdown")
|
||||
|
||||
local Config = require("noice.config")
|
||||
local Format = require("noice.lsp.format")
|
||||
local Message = require("noice.message")
|
||||
local Hacks = require("noice.util.hacks")
|
||||
|
||||
local M = {}
|
||||
|
||||
function M.setup()
|
||||
if Config.options.lsp.override["cmp.entry.get_documentation"] then
|
||||
Hacks.on_module("cmp.entry", function(mod)
|
||||
mod.get_documentation = function(self)
|
||||
local item = self:get_completion_item()
|
||||
|
||||
local lines = item.documentation and Format.format_markdown(item.documentation) or {}
|
||||
local ret = table.concat(lines, "\n")
|
||||
local detail = item.detail
|
||||
if detail and type(detail) == "table" then
|
||||
detail = table.concat(detail, "\n")
|
||||
end
|
||||
|
||||
if detail and not ret:find(detail, 1, true) then
|
||||
local ft = self.context.filetype
|
||||
local dot_index = string.find(ft, "%.")
|
||||
if dot_index ~= nil then
|
||||
ft = string.sub(ft, 0, dot_index - 1)
|
||||
end
|
||||
ret = ("```%s\n%s\n```\n%s"):format(ft, vim.trim(detail), ret)
|
||||
end
|
||||
return vim.split(ret, "\n")
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
if Config.options.lsp.override["vim.lsp.util.convert_input_to_markdown_lines"] then
|
||||
vim.lsp.util.convert_input_to_markdown_lines = function(input, contents)
|
||||
contents = contents or {}
|
||||
local ret = Format.format_markdown(input)
|
||||
vim.list_extend(contents, ret)
|
||||
return contents
|
||||
end
|
||||
end
|
||||
|
||||
if Config.options.lsp.override["vim.lsp.util.stylize_markdown"] then
|
||||
vim.lsp.util.stylize_markdown = function(buf, contents, _opts)
|
||||
vim.api.nvim_buf_clear_namespace(buf, Config.ns, 0, -1)
|
||||
local text = table.concat(contents, "\n")
|
||||
local message = Message("lsp")
|
||||
Markdown.format(message, text)
|
||||
message:render(buf, Config.ns)
|
||||
Markdown.keys(buf)
|
||||
return vim.api.nvim_buf_get_lines(buf, 0, -1, false)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return M
|
||||
@ -0,0 +1,113 @@
|
||||
local require = require("noice.util.lazy")
|
||||
|
||||
local Message = require("noice.message")
|
||||
local Manager = require("noice.message.manager")
|
||||
local Router = require("noice.message.router")
|
||||
local Format = require("noice.text.format")
|
||||
local Config = require("noice.config")
|
||||
local Util = require("noice.util")
|
||||
|
||||
local M = {}
|
||||
|
||||
---@type table<string, NoiceMessage>
|
||||
M._progress = {}
|
||||
M._running = false
|
||||
|
||||
---@param data {client_id: integer, params: lsp.ProgressParams}
|
||||
function M.progress(data)
|
||||
local client_id = data.client_id
|
||||
local params = data.params or data.result -- TODO: Remove data.result after nvim 0.10 release
|
||||
local id = client_id .. "." .. params.token
|
||||
|
||||
local message = M._progress[id]
|
||||
if not message then
|
||||
local client = vim.lsp.get_client_by_id(client_id)
|
||||
-- should not happen, but it does for some reason
|
||||
if not client then
|
||||
return
|
||||
end
|
||||
message = Message("lsp", "progress")
|
||||
message.opts.progress = {
|
||||
client_id = client_id,
|
||||
---@type string
|
||||
client = client and client.name or ("lsp-" .. client_id),
|
||||
}
|
||||
M._progress[id] = message
|
||||
end
|
||||
|
||||
message.opts.progress = vim.tbl_deep_extend("force", message.opts.progress, params.value)
|
||||
message.opts.progress.id = id
|
||||
|
||||
if params.value.kind == "end" then
|
||||
if message.opts.progress.percentage then
|
||||
message.opts.progress.percentage = 100
|
||||
end
|
||||
vim.defer_fn(function()
|
||||
M.close(id)
|
||||
end, 100)
|
||||
end
|
||||
|
||||
M.update()
|
||||
end
|
||||
|
||||
function M.close(id)
|
||||
local message = M._progress[id]
|
||||
if message then
|
||||
M.update()
|
||||
Router.update()
|
||||
Manager.remove(message)
|
||||
M._progress[id] = nil
|
||||
end
|
||||
end
|
||||
|
||||
function M._update()
|
||||
if not vim.tbl_isempty(M._progress) then
|
||||
for id, message in pairs(M._progress) do
|
||||
local client = vim.lsp.get_client_by_id(message.opts.progress.client_id)
|
||||
if not client then
|
||||
M.close(id)
|
||||
end
|
||||
if message.opts.progress.kind == "end" then
|
||||
Manager.add(Format.format(message, Config.options.lsp.progress.format_done))
|
||||
else
|
||||
Manager.add(Format.format(message, Config.options.lsp.progress.format))
|
||||
end
|
||||
end
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
function M.update()
|
||||
error("should never be called")
|
||||
end
|
||||
|
||||
function M.setup()
|
||||
M.update = Util.interval(Config.options.lsp.progress.throttle, M._update, {
|
||||
enabled = function()
|
||||
return not vim.tbl_isempty(M._progress)
|
||||
end,
|
||||
})
|
||||
|
||||
-- Neovim >= 0.10.0
|
||||
local ok = pcall(vim.api.nvim_create_autocmd, "LspProgress", {
|
||||
group = vim.api.nvim_create_augroup("noice_lsp_progress", { clear = true }),
|
||||
callback = function(event)
|
||||
M.progress(event.data)
|
||||
end,
|
||||
})
|
||||
|
||||
-- Neovim < 0.10.0
|
||||
if not ok then
|
||||
local orig = vim.lsp.handlers["$/progress"]
|
||||
vim.lsp.handlers["$/progress"] = function(...)
|
||||
local params = select(2, ...)
|
||||
local ctx = select(3, ...)
|
||||
Util.try(function()
|
||||
M.progress({ client_id = ctx.client_id, params = params })
|
||||
end)
|
||||
orig(...)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return M
|
||||
@ -0,0 +1,247 @@
|
||||
local require = require("noice.util.lazy")
|
||||
|
||||
local NoiceText = require("noice.text")
|
||||
local Format = require("noice.lsp.format")
|
||||
local Markdown = require("noice.text.markdown")
|
||||
local Config = require("noice.config")
|
||||
local Util = require("noice.util")
|
||||
local Docs = require("noice.lsp.docs")
|
||||
|
||||
---@class SignatureInformation
|
||||
---@field label string
|
||||
---@field documentation? string|MarkupContent
|
||||
---@field parameters? ParameterInformation[]
|
||||
---@field activeParameter? integer
|
||||
|
||||
---@class ParameterInformation
|
||||
---@field label string|{[1]:integer, [2]:integer}
|
||||
---@field documentation? string|MarkupContent
|
||||
|
||||
---@class SignatureHelpContext
|
||||
---@field triggerKind SignatureHelpTriggerKind
|
||||
---@field triggerCharacter? string
|
||||
---@field isRetrigger boolean
|
||||
---@field activeSignatureHelp? SignatureHelp
|
||||
|
||||
---@class SignatureHelp
|
||||
---@field signatures SignatureInformation[]
|
||||
---@field activeSignature? integer
|
||||
---@field activeParameter? integer
|
||||
---@field ft? string
|
||||
---@field message NoiceMessage
|
||||
local M = {}
|
||||
M.__index = M
|
||||
|
||||
---@enum SignatureHelpTriggerKind
|
||||
M.trigger_kind = {
|
||||
invoked = 1,
|
||||
trigger_character = 2,
|
||||
content_change = 3,
|
||||
}
|
||||
|
||||
function M.setup()
|
||||
vim.lsp.handlers["textDocument/signatureHelp"] = M.on_signature
|
||||
|
||||
if Config.options.lsp.signature.auto_open.enabled then
|
||||
-- attach to existing buffers
|
||||
for _, client in ipairs((vim.lsp.get_clients or vim.lsp.get_active_clients)()) do
|
||||
for _, buf in ipairs(vim.lsp.get_buffers_by_client_id(client.id)) do
|
||||
M.on_attach(buf, client)
|
||||
end
|
||||
end
|
||||
|
||||
-- attach to new buffers
|
||||
vim.api.nvim_create_autocmd("LspAttach", {
|
||||
group = vim.api.nvim_create_augroup("noice_lsp_signature", { clear = true }),
|
||||
callback = function(args)
|
||||
if args.data ~= nil then
|
||||
M.on_attach(args.buf, vim.lsp.get_client_by_id(args.data.client_id))
|
||||
end
|
||||
end,
|
||||
})
|
||||
end
|
||||
end
|
||||
|
||||
function M.get_char(buf)
|
||||
local current_win = vim.api.nvim_get_current_win()
|
||||
local win = buf == vim.api.nvim_win_get_buf(current_win) and current_win or vim.fn.bufwinid(buf)
|
||||
local cursor = vim.api.nvim_win_get_cursor(win == -1 and 0 or win)
|
||||
local row = cursor[1] - 1
|
||||
local col = cursor[2]
|
||||
local _, lines = pcall(vim.api.nvim_buf_get_text, buf, row, 0, row, col, {})
|
||||
local line = vim.trim(lines and lines[1] or "")
|
||||
return line:sub(-1, -1)
|
||||
end
|
||||
|
||||
---@param result SignatureHelp
|
||||
function M.on_signature(_, result, ctx, config)
|
||||
config = config or {}
|
||||
if not (result and result.signatures) then
|
||||
if not config.trigger then
|
||||
vim.notify("No signature help available")
|
||||
end
|
||||
return
|
||||
end
|
||||
|
||||
local message = Docs.get("signature")
|
||||
|
||||
if config.trigger or not message:focus() then
|
||||
result.ft = vim.bo[ctx.bufnr].filetype
|
||||
result.message = message
|
||||
M.new(result):format()
|
||||
if message:is_empty() then
|
||||
if not config.trigger then
|
||||
vim.notify("No signature help available")
|
||||
end
|
||||
return
|
||||
end
|
||||
Docs.show(message, config.stay)
|
||||
end
|
||||
end
|
||||
M.on_signature = Util.protect(M.on_signature)
|
||||
|
||||
function M.on_attach(buf, client)
|
||||
if client.server_capabilities.signatureHelpProvider then
|
||||
---@type string[]
|
||||
local chars = client.server_capabilities.signatureHelpProvider.triggerCharacters
|
||||
if chars and #chars > 0 then
|
||||
local callback = M.check(buf, chars, client.offset_encoding)
|
||||
if Config.options.lsp.signature.auto_open.luasnip then
|
||||
vim.api.nvim_create_autocmd("User", {
|
||||
pattern = "LuasnipInsertNodeEnter",
|
||||
callback = callback,
|
||||
})
|
||||
end
|
||||
if Config.options.lsp.signature.auto_open.trigger then
|
||||
vim.api.nvim_create_autocmd({ "TextChangedI", "TextChangedP", "InsertEnter" }, {
|
||||
buffer = buf,
|
||||
callback = callback,
|
||||
})
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function M.check(buf, chars, encoding)
|
||||
encoding = encoding or "utf-16"
|
||||
return Util.debounce(Config.options.lsp.signature.auto_open.throttle, function(_event)
|
||||
if vim.api.nvim_get_current_buf() ~= buf then
|
||||
return
|
||||
end
|
||||
|
||||
if vim.tbl_contains(chars, M.get_char(buf)) then
|
||||
local params = vim.lsp.util.make_position_params(0, encoding)
|
||||
vim.lsp.buf_request(buf, "textDocument/signatureHelp", params, function(err, result, ctx)
|
||||
M.on_signature(err, result, ctx, {
|
||||
trigger = true,
|
||||
stay = function()
|
||||
return vim.tbl_contains(chars, M.get_char(buf))
|
||||
end,
|
||||
})
|
||||
end)
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
---@param help SignatureHelp
|
||||
function M.new(help)
|
||||
return setmetatable(help, M)
|
||||
end
|
||||
|
||||
function M:active_parameter(sig_index)
|
||||
if self.activeSignature and self.signatures[self.activeSignature + 1] and sig_index ~= self.activeSignature + 1 then
|
||||
return
|
||||
end
|
||||
local sig = self.signatures[sig_index]
|
||||
if sig.activeParameter and sig.parameters and sig.parameters[sig.activeParameter + 1] then
|
||||
return sig.parameters[sig.activeParameter + 1]
|
||||
end
|
||||
if self.activeParameter and sig.parameters and sig.parameters[self.activeParameter + 1] then
|
||||
return sig.parameters[self.activeParameter + 1]
|
||||
end
|
||||
return sig.parameters and sig.parameters[1] or nil
|
||||
end
|
||||
|
||||
---@param sig SignatureInformation
|
||||
---@param param ParameterInformation
|
||||
function M:format_active_parameter(sig, param)
|
||||
local label = param.label
|
||||
if type(label) == "string" then
|
||||
local from = sig.label:find(label, 1, true)
|
||||
if from then
|
||||
self.message:append(NoiceText("", {
|
||||
hl_group = "LspSignatureActiveParameter",
|
||||
col = from - 1,
|
||||
length = vim.fn.strlen(label),
|
||||
}))
|
||||
end
|
||||
else
|
||||
self.message:append(NoiceText("", {
|
||||
hl_group = "LspSignatureActiveParameter",
|
||||
col = label[1],
|
||||
length = label[2] - label[1],
|
||||
}))
|
||||
end
|
||||
end
|
||||
|
||||
--- dddd
|
||||
-- function M:format_signature(boo) end
|
||||
|
||||
---@param sig SignatureInformation
|
||||
---@overload fun() # goooo
|
||||
function M:format_signature(sig_index, sig)
|
||||
if sig_index ~= 1 then
|
||||
self.message:newline()
|
||||
self.message:newline()
|
||||
Markdown.horizontal_line(self.message)
|
||||
self.message:newline()
|
||||
end
|
||||
|
||||
local count = self.message:height()
|
||||
self.message:append(sig.label)
|
||||
self.message:append(NoiceText.syntax(self.ft, self.message:height() - count))
|
||||
local param = self:active_parameter(sig_index)
|
||||
if param then
|
||||
self:format_active_parameter(sig, param)
|
||||
end
|
||||
self.message:newline()
|
||||
|
||||
if sig.documentation then
|
||||
Markdown.horizontal_line(self.message)
|
||||
Format.format(self.message, sig.documentation, { ft = self.ft })
|
||||
end
|
||||
|
||||
---@type ParameterInformation[]
|
||||
local params = vim.tbl_filter(function(p)
|
||||
return p.documentation
|
||||
end, sig.parameters or {})
|
||||
|
||||
local lines = {}
|
||||
if #params > 0 then
|
||||
for _, p in ipairs(sig.parameters) do
|
||||
if p.documentation then
|
||||
local pdoc = table.concat(Format.format_markdown(p.documentation or ""), "\n")
|
||||
local line = { "-" }
|
||||
if p.label then
|
||||
local label = p.label
|
||||
if type(label) == "table" then
|
||||
label = sig.label:sub(label[1] + 1, label[2])
|
||||
end
|
||||
|
||||
line[#line + 1] = "`[" .. label .. "]`"
|
||||
end
|
||||
line[#line + 1] = pdoc
|
||||
lines[#lines + 1] = table.concat(line, " ")
|
||||
end
|
||||
end
|
||||
end
|
||||
Format.format(self.message, table.concat(lines, "\n"), { ft = self.ft })
|
||||
end
|
||||
|
||||
function M:format()
|
||||
for s, sig in ipairs(self.signatures) do
|
||||
self:format_signature(s, sig)
|
||||
end
|
||||
end
|
||||
|
||||
return M
|
||||
@ -0,0 +1,183 @@
|
||||
local require = require("noice.util.lazy")
|
||||
|
||||
local Util = require("noice.util")
|
||||
local Manager = require("noice.message.manager")
|
||||
|
||||
local M = {}
|
||||
|
||||
---@alias NoiceFilterFun fun(message: NoiceMessage, ...): boolean
|
||||
|
||||
---@class NoiceFilter
|
||||
---@field any? NoiceFilter[]
|
||||
---@field blocking? boolean
|
||||
---@field cleared? boolean
|
||||
---@field cmdline? string|boolean
|
||||
---@field error? boolean
|
||||
---@field event? NoiceEvent|NoiceEvent[]
|
||||
---@field find? string
|
||||
---@field has? boolean
|
||||
---@field kind? NoiceKind|NoiceKind[]
|
||||
---@field max_height? integer
|
||||
---@field max_length? integer
|
||||
---@field max_width? integer
|
||||
---@field message? NoiceMessage|NoiceMessage[]
|
||||
---@field min_height? integer
|
||||
---@field min_length? integer
|
||||
---@field min_width? integer
|
||||
---@field mode? string
|
||||
---@field not? NoiceFilter
|
||||
---@field warning? boolean
|
||||
---@field cond? fun(message:NoiceMessage):boolean
|
||||
|
||||
-----@type table<string, NoiceFilterFun>
|
||||
M.filters = {
|
||||
cleared = function(message, cleared)
|
||||
---@cast message NoiceMessage
|
||||
return cleared == not Manager.has(message)
|
||||
end,
|
||||
has = function(message, has)
|
||||
---@cast message NoiceMessage
|
||||
return has == Manager.has(message, { history = true })
|
||||
end,
|
||||
cond = function(message, cond)
|
||||
return cond(message)
|
||||
end,
|
||||
mode = function(_, mode)
|
||||
return vim.api.nvim_get_mode().mode:find(mode)
|
||||
end,
|
||||
blocking = function(_, blocking)
|
||||
return blocking == Util.is_blocking()
|
||||
end,
|
||||
event = function(message, event)
|
||||
---@cast message NoiceMessage
|
||||
event = type(event) == "table" and event or { event }
|
||||
return vim.tbl_contains(event, message.event)
|
||||
end,
|
||||
kind = function(message, kind)
|
||||
---@cast message NoiceMessage
|
||||
kind = type(kind) == "table" and kind or { kind }
|
||||
return vim.tbl_contains(kind, message.kind)
|
||||
end,
|
||||
cmdline = function(message, cmdline)
|
||||
---@cast message NoiceMessage
|
||||
---@cast cmdline string|boolean
|
||||
if type(cmdline) == "boolean" then
|
||||
return (message.cmdline ~= nil) == cmdline
|
||||
end
|
||||
if message.cmdline then
|
||||
local str = message.cmdline.state.firstc .. message.cmdline:get()
|
||||
return str:find(cmdline)
|
||||
end
|
||||
return false
|
||||
end,
|
||||
message = function(message, other)
|
||||
---@cast message NoiceMessage
|
||||
other = Util.islist(other) and other or { other }
|
||||
---@cast other NoiceMessage[]
|
||||
for _, m in ipairs(other) do
|
||||
if m.id == message.id then
|
||||
return true
|
||||
end
|
||||
end
|
||||
return false
|
||||
end,
|
||||
error = function(message, error)
|
||||
---@cast message NoiceMessage
|
||||
return error == (message.level == "error")
|
||||
end,
|
||||
warning = function(message, warning)
|
||||
---@cast message NoiceMessage
|
||||
return warning == (message.level == "warn")
|
||||
end,
|
||||
find = function(message, find)
|
||||
---@cast message NoiceMessage
|
||||
return message:content():find(find)
|
||||
end,
|
||||
min_height = function(message, min_height)
|
||||
---@cast message NoiceMessage
|
||||
return message:height() >= min_height
|
||||
end,
|
||||
max_height = function(message, max_height)
|
||||
---@cast message NoiceMessage
|
||||
return message:height() <= max_height
|
||||
end,
|
||||
min_width = function(message, min_width)
|
||||
---@cast message NoiceMessage
|
||||
return message:width() >= min_width
|
||||
end,
|
||||
max_width = function(message, max_width)
|
||||
---@cast message NoiceMessage
|
||||
return message:width() <= max_width
|
||||
end,
|
||||
min_length = function(message, min_length)
|
||||
---@cast message NoiceMessage
|
||||
return message:length() >= min_length
|
||||
end,
|
||||
max_length = function(message, max_length)
|
||||
---@cast message NoiceMessage
|
||||
return message:length() <= max_length
|
||||
end,
|
||||
any = function(message, any)
|
||||
---@cast message NoiceMessage
|
||||
---@cast any NoiceFilter[]
|
||||
for _, f in ipairs(any) do
|
||||
if message:is(f) then
|
||||
return true
|
||||
end
|
||||
end
|
||||
return false
|
||||
end,
|
||||
["not"] = function(message, filter)
|
||||
---@cast message NoiceMessage
|
||||
return not message:is(filter)
|
||||
end,
|
||||
}
|
||||
|
||||
---@type table<string,boolean>
|
||||
M._unknown_notified = {}
|
||||
|
||||
---@param message NoiceMessage
|
||||
---@param filter NoiceFilter
|
||||
function M.is(message, filter)
|
||||
for k, v in pairs(filter) do
|
||||
if M.filters[k] then
|
||||
if not M.filters[k](message, v) then
|
||||
return false
|
||||
end
|
||||
else
|
||||
if not M._unknown_notified[k] then
|
||||
M._unknown_notified[k] = true
|
||||
Util.error("Unknown filter key " .. k .. " for " .. vim.inspect(filter))
|
||||
end
|
||||
return false
|
||||
end
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
---@param messages NoiceMessage[]
|
||||
---@param filter NoiceFilter
|
||||
---@param invert? boolean
|
||||
---@return NoiceMessage[]
|
||||
function M.filter(messages, filter, invert)
|
||||
return vim.tbl_filter(
|
||||
---@param message NoiceMessage
|
||||
function(message)
|
||||
local is = M.is(message, filter)
|
||||
if invert then
|
||||
is = not is
|
||||
end
|
||||
return is
|
||||
end,
|
||||
messages
|
||||
)
|
||||
end
|
||||
|
||||
---@param messages NoiceMessage[]
|
||||
---@param filter NoiceFilter
|
||||
---@param invert? boolean
|
||||
function M.has(messages, filter, invert)
|
||||
return #M.filter(messages, filter, invert) > 0
|
||||
end
|
||||
|
||||
return M
|
||||
@ -0,0 +1,116 @@
|
||||
local require = require("noice.util.lazy")
|
||||
|
||||
local Block = require("noice.text.block")
|
||||
local Filter = require("noice.message.filter")
|
||||
|
||||
local _id = 0
|
||||
|
||||
---@class NoiceMessage: NoiceBlock
|
||||
---@field super NoiceBlock
|
||||
---@field id number
|
||||
---@field event NoiceEvent
|
||||
---@field ctime number
|
||||
---@field mtime number
|
||||
---@field tick number
|
||||
---@field level? NotifyLevel
|
||||
---@field kind? NoiceKind
|
||||
---@field cmdline? NoiceCmdline
|
||||
---@field _debug? boolean
|
||||
---@field opts table<string, any>
|
||||
---@overload fun(event: NoiceEvent, kind?: NoiceKind, content?: NoiceContent|NoiceContent[]): NoiceMessage
|
||||
---@diagnostic disable-next-line: undefined-field
|
||||
local Message = Block:extend("NoiceBlock")
|
||||
|
||||
---@param event NoiceEvent
|
||||
---@param kind? NoiceKind
|
||||
---@param content? NoiceContent|NoiceContent[]
|
||||
function Message:init(event, kind, content)
|
||||
_id = _id + 1
|
||||
self.id = _id
|
||||
self.tick = 1
|
||||
self.ctime = vim.fn.localtime()
|
||||
self.mtime = vim.fn.localtime()
|
||||
self.event = event
|
||||
self.kind = kind
|
||||
self.opts = {}
|
||||
Message.super.init(self, content)
|
||||
end
|
||||
|
||||
-- Returns the first buffer that has rendered the message
|
||||
---@return buffer?
|
||||
function Message:buf()
|
||||
return self:bufs()[1]
|
||||
end
|
||||
|
||||
function Message:bufs()
|
||||
return vim.tbl_filter(function(buf)
|
||||
return vim.api.nvim_buf_is_valid(buf) and self.on_buf(buf)
|
||||
end, vim.api.nvim_list_bufs())
|
||||
end
|
||||
|
||||
function Message:wins()
|
||||
return vim.tbl_filter(function(win)
|
||||
return vim.api.nvim_win_is_valid(win) and self:on_win(win)
|
||||
end, vim.api.nvim_list_wins())
|
||||
end
|
||||
|
||||
-- Returns the first window that displays the message
|
||||
---@return window?
|
||||
function Message:win()
|
||||
return self:wins()[1]
|
||||
end
|
||||
|
||||
function Message:focus()
|
||||
local win = self:win()
|
||||
if win then
|
||||
vim.api.nvim_set_current_win(win)
|
||||
-- switch to normal mode
|
||||
vim.cmd("stopinsert")
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
function Message:on_remove()
|
||||
for _, buf in ipairs(vim.api.nvim_list_bufs()) do
|
||||
if self:on_buf(buf) then
|
||||
vim.b[buf].messages = vim.tbl_filter(function(b)
|
||||
return b ~= buf
|
||||
end, vim.b[buf].messages)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function Message:on_win(win)
|
||||
return self:on_buf(vim.api.nvim_win_get_buf(win))
|
||||
end
|
||||
|
||||
function Message:on_buf(buf)
|
||||
return vim.b[buf].messages and vim.tbl_contains(vim.b[buf].messages, self.id)
|
||||
end
|
||||
|
||||
function Message:_add_buf(buf)
|
||||
local bufs = vim.b[buf].messages or {}
|
||||
table.insert(bufs, self.id)
|
||||
vim.b[buf].messages = bufs
|
||||
end
|
||||
|
||||
---@param bufnr number buffer number
|
||||
---@param ns_id number namespace id
|
||||
---@param linenr_start? number line number (1-indexed)
|
||||
function Message:highlight(bufnr, ns_id, linenr_start)
|
||||
self:_add_buf(bufnr)
|
||||
return Message.super.highlight(self, bufnr, ns_id, linenr_start)
|
||||
end
|
||||
|
||||
---@param bufnr number buffer number
|
||||
---@param ns_id number namespace id
|
||||
---@param linenr_start? number start line number (1-indexed)
|
||||
---@param linenr_end? number end line number (1-indexed)
|
||||
function Message:render(bufnr, ns_id, linenr_start, linenr_end)
|
||||
self:_add_buf(bufnr)
|
||||
return Message.super.render(self, bufnr, ns_id, linenr_start, linenr_end)
|
||||
end
|
||||
|
||||
Message.is = Filter.is
|
||||
|
||||
return Message
|
||||
@ -0,0 +1,129 @@
|
||||
local M = {}
|
||||
|
||||
local _tick = 1
|
||||
|
||||
local function next_tick()
|
||||
_tick = _tick + 1
|
||||
return _tick
|
||||
end
|
||||
|
||||
---@type table<number, NoiceMessage>
|
||||
M._history = {}
|
||||
|
||||
---@type table<number, NoiceMessage>
|
||||
M._messages = {}
|
||||
|
||||
function M.tick()
|
||||
return _tick
|
||||
end
|
||||
|
||||
---@param message NoiceMessage
|
||||
function M.add(message)
|
||||
if not (message:is_empty() and vim.tbl_isempty(message.opts)) then
|
||||
message.tick = next_tick()
|
||||
message.mtime = vim.fn.localtime()
|
||||
M._history[message.id] = message
|
||||
M._messages[message.id] = message
|
||||
end
|
||||
end
|
||||
|
||||
---@param message NoiceMessage
|
||||
---@param opts? { history: boolean } # defaults to `{ history = false }`
|
||||
function M.has(message, opts)
|
||||
opts = opts or {}
|
||||
return (opts.history and M._history or M._messages)[message.id] ~= nil
|
||||
end
|
||||
|
||||
---@param message NoiceMessage
|
||||
function M.remove(message)
|
||||
if M._history[message.id] then
|
||||
M._history[message.id] = nil
|
||||
next_tick()
|
||||
end
|
||||
if M._messages[message.id] then
|
||||
M._messages[message.id] = nil
|
||||
next_tick()
|
||||
end
|
||||
message:on_remove()
|
||||
end
|
||||
|
||||
---@param filter? NoiceFilter
|
||||
function M.clear(filter)
|
||||
M.with(function(message)
|
||||
M._messages[message.id] = nil
|
||||
next_tick()
|
||||
end, filter)
|
||||
end
|
||||
|
||||
---@param max number
|
||||
function M.prune(max)
|
||||
local keep = M.get(nil, { count = max })
|
||||
M._messages = {}
|
||||
for _, message in ipairs(keep) do
|
||||
M._messages[message.id] = message
|
||||
end
|
||||
end
|
||||
|
||||
-- Sorts messages in-place by mtime & id
|
||||
---@param messages NoiceMessage[]
|
||||
function M.sort(messages, reverse)
|
||||
table.sort(
|
||||
messages,
|
||||
---@param a NoiceMessage
|
||||
---@param b NoiceMessage
|
||||
function(a, b)
|
||||
local ret = (a.mtime == b.mtime) and (a.id < b.id) or (a.mtime < b.mtime)
|
||||
if reverse then
|
||||
ret = not ret
|
||||
end
|
||||
return ret
|
||||
end
|
||||
)
|
||||
end
|
||||
|
||||
function M.get_by_id(id)
|
||||
return M._history[id]
|
||||
end
|
||||
|
||||
---@class NoiceMessageOpts
|
||||
---@field history? boolean
|
||||
---@field sort? boolean
|
||||
---@field reverse? boolean
|
||||
---@field count? number
|
||||
---@field messages? NoiceMessage[]
|
||||
|
||||
---@param filter? NoiceFilter
|
||||
---@param opts? NoiceMessageOpts
|
||||
---@return NoiceMessage[]
|
||||
function M.get(filter, opts)
|
||||
opts = opts or {}
|
||||
local messages = opts.messages or opts.history and M._history or M._messages
|
||||
local ret = {}
|
||||
for _, message in pairs(messages) do
|
||||
if not filter or message:is(filter) then
|
||||
table.insert(ret, message)
|
||||
end
|
||||
end
|
||||
if opts.sort then
|
||||
M.sort(ret, opts.reverse)
|
||||
end
|
||||
if opts.count and #ret > opts.count then
|
||||
local last = {}
|
||||
for i = #ret - opts.count + 1, #ret do
|
||||
table.insert(last, ret[i])
|
||||
end
|
||||
ret = last
|
||||
end
|
||||
return ret
|
||||
end
|
||||
|
||||
---@param fn fun(message: NoiceMessage)
|
||||
---@param filter? NoiceFilter
|
||||
---@param opts? { history: boolean, sort: boolean } # defaults to `{ history = false, sort = false }`
|
||||
function M.with(fn, filter, opts)
|
||||
for _, message in ipairs(M.get(filter, opts)) do
|
||||
fn(message)
|
||||
end
|
||||
end
|
||||
|
||||
return M
|
||||
@ -0,0 +1,260 @@
|
||||
local require = require("noice.util.lazy")
|
||||
|
||||
local Config = require("noice.config")
|
||||
local Util = require("noice.util")
|
||||
local View = require("noice.view")
|
||||
local Manager = require("noice.message.manager")
|
||||
|
||||
---@class NoiceRoute
|
||||
---@field view NoiceView
|
||||
---@field filter NoiceFilter
|
||||
---@field opts? NoiceRouteOptions|NoiceViewOptions
|
||||
|
||||
---@class NoiceRouteOptions
|
||||
---@field stop boolean
|
||||
---@field skip boolean
|
||||
|
||||
---@class NoiceRouteConfig
|
||||
---@field view string
|
||||
---@field filter NoiceFilter
|
||||
---@field opts? NoiceRouteOptions|NoiceViewOptions
|
||||
|
||||
local M = {}
|
||||
---@type NoiceRoute[]
|
||||
M._routes = {}
|
||||
M._tick = 0
|
||||
M._need_redraw = false
|
||||
---@type fun()|Interval?
|
||||
M._updater = nil
|
||||
M._updating = false
|
||||
|
||||
function M.enable()
|
||||
if not M._updater then
|
||||
M._updater = Util.interval(Config.options.throttle, Util.protect(M.update))
|
||||
end
|
||||
M._updater()
|
||||
end
|
||||
|
||||
function M.disable()
|
||||
if M._updater then
|
||||
M._updater.stop()
|
||||
M._updater = nil
|
||||
Manager.clear()
|
||||
M.update()
|
||||
end
|
||||
vim.api.nvim_create_augroup("NoiceRouter", { clear = true })
|
||||
end
|
||||
|
||||
---@param route NoiceRouteConfig
|
||||
---@param pos? number
|
||||
function M.add(route, pos)
|
||||
local ret = {
|
||||
filter = route.filter,
|
||||
opts = route.opts or {},
|
||||
view = route.view and View.get_view(route.view, route.opts) or nil,
|
||||
}
|
||||
if ret.view == nil then
|
||||
ret.opts.skip = true
|
||||
end
|
||||
if pos then
|
||||
table.insert(M._routes, pos, ret)
|
||||
else
|
||||
table.insert(M._routes, ret)
|
||||
end
|
||||
return ret
|
||||
end
|
||||
|
||||
-- Redirect any messages generated by a command or function
|
||||
---@param cmd string|fun() command or function to execute
|
||||
---@param routes? NoiceRouteConfig[] custom routes. Defaults to `config.redirect`
|
||||
function M.redirect(cmd, routes)
|
||||
routes = routes or { Config.options.redirect }
|
||||
if type(cmd) == "string" then
|
||||
local cmd_str = cmd
|
||||
cmd = function()
|
||||
vim.cmd(cmd_str)
|
||||
end
|
||||
end
|
||||
-- process any pending messages
|
||||
M.update()
|
||||
|
||||
local added = {}
|
||||
local pos = 1
|
||||
-- add temporary routes
|
||||
for _, route in ipairs(routes) do
|
||||
table.insert(added, M.add(route, pos))
|
||||
pos = pos + 1
|
||||
end
|
||||
|
||||
-- execute callback
|
||||
Util.try(cmd)
|
||||
|
||||
-- force a redraw to make sure we received all msg_show events
|
||||
vim.cmd.redraw()
|
||||
|
||||
-- process messages
|
||||
M.update()
|
||||
|
||||
-- remove temporary routes
|
||||
M._routes = vim.tbl_filter(function(r)
|
||||
return not vim.tbl_contains(added, r)
|
||||
end, M._routes)
|
||||
end
|
||||
|
||||
function M.setup()
|
||||
for _, route in ipairs(Config.options.routes) do
|
||||
M.add(route)
|
||||
end
|
||||
end
|
||||
|
||||
function M.check_redraw()
|
||||
if Util.is_blocking() and M._need_redraw then
|
||||
-- NOTE: set to false before actually calling redraw to prevent a loop with ui
|
||||
M._need_redraw = false
|
||||
Util.redraw()
|
||||
end
|
||||
end
|
||||
|
||||
function M.view_stats()
|
||||
local views = M.get_views()
|
||||
---@type table<string,number>
|
||||
local ret = {}
|
||||
|
||||
-- remove deleted messages and new messages from the views
|
||||
for view, _ in pairs(views) do
|
||||
if #view._messages > 0 then
|
||||
if not ret[view._opts.view] then
|
||||
ret[view._opts.view] = 0
|
||||
end
|
||||
ret[view._opts.view] = ret[view._opts.view] + #view._messages
|
||||
end
|
||||
end
|
||||
return ret
|
||||
end
|
||||
|
||||
function M.get_views()
|
||||
---@type table<NoiceView, boolean>
|
||||
local views = {}
|
||||
for _, route in ipairs(M._routes) do
|
||||
if route.view then
|
||||
views[route.view] = true
|
||||
end
|
||||
end
|
||||
return views
|
||||
end
|
||||
|
||||
function M.dismiss()
|
||||
Manager.clear()
|
||||
local views = M.get_views()
|
||||
for view, _ in pairs(views) do
|
||||
view:dismiss()
|
||||
view:display()
|
||||
end
|
||||
M.update()
|
||||
end
|
||||
|
||||
function M.update()
|
||||
if Util.is_exiting() then
|
||||
return
|
||||
end
|
||||
|
||||
if M._updating then
|
||||
return
|
||||
end
|
||||
|
||||
-- only update on changes
|
||||
if M._tick == Manager.tick() then
|
||||
M.check_redraw()
|
||||
return
|
||||
end
|
||||
|
||||
M._updating = true
|
||||
|
||||
Util.stats.track("router.update")
|
||||
|
||||
---@type table<NoiceView,boolean>
|
||||
local updates = {}
|
||||
|
||||
local messages = Manager.get(nil, { sort = true })
|
||||
local views = M.get_views()
|
||||
|
||||
-- remove deleted messages and new messages from the views
|
||||
for view, _ in pairs(views) do
|
||||
local count = #view._messages
|
||||
view._messages = Manager.get({
|
||||
-- remove any deleted messages
|
||||
has = true,
|
||||
-- remove messages that we are adding
|
||||
["not"] = {
|
||||
message = messages,
|
||||
},
|
||||
}, { messages = view._messages })
|
||||
|
||||
-- retry errors only once
|
||||
if view._errors > 1 then
|
||||
view._errors = 0
|
||||
end
|
||||
|
||||
if #view._messages ~= count or view._errors > 0 then
|
||||
updates[view] = true
|
||||
end
|
||||
end
|
||||
|
||||
-- add messages
|
||||
for _, message in ipairs(messages) do
|
||||
for _, route in ipairs(M._routes) do
|
||||
if message:is(route.filter) then
|
||||
if not route.opts.skip then
|
||||
route.view:push(message)
|
||||
route.view._route_opts = vim.tbl_deep_extend("force", route.view._route_opts or {}, route.opts or {})
|
||||
updates[route.view] = true
|
||||
end
|
||||
if route.opts.stop ~= false then
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
Manager.clear()
|
||||
|
||||
local dirty = false
|
||||
for view, _ in pairs(updates) do
|
||||
view:display()
|
||||
if view._errors > 0 then
|
||||
dirty = true
|
||||
end
|
||||
end
|
||||
|
||||
if not dirty then
|
||||
M._tick = Manager.tick()
|
||||
end
|
||||
|
||||
if not vim.tbl_isempty(updates) then
|
||||
Util.stats.track("router.update.updated")
|
||||
M._need_redraw = true
|
||||
end
|
||||
|
||||
M.check_redraw()
|
||||
M._updating = false
|
||||
end
|
||||
|
||||
function M.echo_pending()
|
||||
local messages = Manager.get({ event = "msg_show" }, { sort = true })
|
||||
local chunks = {}
|
||||
for _, message in ipairs(messages) do
|
||||
for _, line in ipairs(message._lines) do
|
||||
---@param t NuiText
|
||||
local chunk = vim.tbl_map(function(t)
|
||||
return { t:content(), t.extmark.hl_group }
|
||||
end, line._texts)
|
||||
vim.list_extend(chunks, chunk)
|
||||
end
|
||||
end
|
||||
chunks[#chunks + 1] = { "foobar", "Normal" }
|
||||
-- vim.opt.cmdheight = 10
|
||||
-- vim.opt.more = false
|
||||
vim.api.nvim_echo(chunks, true, {})
|
||||
end
|
||||
|
||||
return M
|
||||
@ -0,0 +1,69 @@
|
||||
local require = require("noice.util.lazy")
|
||||
|
||||
local Message = require("noice.message")
|
||||
local Manager = require("noice.message.manager")
|
||||
local Router = require("noice.message.router")
|
||||
local Util = require("noice.util")
|
||||
|
||||
local M = {}
|
||||
|
||||
---@alias NotifyEvent "notify"
|
||||
---@alias NotifyLevel "trace"|"debug"|"info"|"warn"|"error"|"off"
|
||||
|
||||
M._orig = nil
|
||||
|
||||
function M.enable()
|
||||
if vim.notify ~= M.notify then
|
||||
M._orig = vim.notify
|
||||
vim.notify = M.notify
|
||||
end
|
||||
end
|
||||
|
||||
function M.disable()
|
||||
if M._orig then
|
||||
vim.notify = M._orig
|
||||
M._orig = nil
|
||||
end
|
||||
end
|
||||
|
||||
function M.get_level(level)
|
||||
if type(level) == "string" then
|
||||
return level
|
||||
end
|
||||
for k, v in pairs(vim.log.levels) do
|
||||
if v == level then
|
||||
return k:lower()
|
||||
end
|
||||
end
|
||||
return "info"
|
||||
end
|
||||
|
||||
---@param msg string
|
||||
---@param level? number|string
|
||||
---@param opts? table<string, any>
|
||||
function M.notify(msg, level, opts)
|
||||
if vim.in_fast_event() then
|
||||
vim.schedule(function()
|
||||
M.notify(msg, level, opts)
|
||||
end)
|
||||
return
|
||||
end
|
||||
|
||||
level = M.get_level(level)
|
||||
local message = Message("notify", level, msg)
|
||||
message.opts = opts or {}
|
||||
message.level = level
|
||||
|
||||
if msg == nil then
|
||||
-- special case for some destinations like nvim-notify
|
||||
message.opts.is_nil = true
|
||||
end
|
||||
|
||||
Manager.add(message)
|
||||
if Util.is_blocking() then
|
||||
Router.update()
|
||||
end
|
||||
return { id = message.id }
|
||||
end
|
||||
|
||||
return M
|
||||
@ -0,0 +1,216 @@
|
||||
local require = require("noice.util.lazy")
|
||||
|
||||
local Highlight = require("noice.text.highlight")
|
||||
local NuiLine = require("nui.line")
|
||||
local Object = require("nui.object")
|
||||
|
||||
---@alias NoiceChunk { [0]: integer, [1]: string}
|
||||
---@alias NoiceContent string|NoiceChunk|NuiLine|NuiText|NoiceBlock
|
||||
|
||||
---@class NoiceBlock
|
||||
---@field _lines NuiLine[]
|
||||
---@field fix_cr boolean?
|
||||
---@overload fun(content?: NoiceContent|NoiceContent[], highlight?: string|table): NoiceBlock
|
||||
local Block = Object("Block")
|
||||
|
||||
---@param content? NoiceContent|NoiceContent[]
|
||||
---@param highlight? string|table data for highlight
|
||||
function Block:init(content, highlight)
|
||||
self._lines = {}
|
||||
if content then
|
||||
self:append(content, highlight)
|
||||
end
|
||||
end
|
||||
|
||||
function Block:clear()
|
||||
self._lines = {}
|
||||
end
|
||||
|
||||
function Block:content()
|
||||
return table.concat(
|
||||
vim.tbl_map(
|
||||
---@param line NuiLine
|
||||
function(line)
|
||||
return line:content()
|
||||
end,
|
||||
self._lines
|
||||
),
|
||||
"\n"
|
||||
)
|
||||
end
|
||||
|
||||
function Block:width()
|
||||
local ret = 0
|
||||
for _, line in ipairs(self._lines) do
|
||||
ret = math.max(ret, line:width())
|
||||
end
|
||||
return ret
|
||||
end
|
||||
|
||||
function Block:length()
|
||||
local ret = 0
|
||||
for _, line in ipairs(self._lines) do
|
||||
ret = ret + line:width()
|
||||
end
|
||||
return ret
|
||||
end
|
||||
|
||||
function Block:height()
|
||||
return #self._lines
|
||||
end
|
||||
|
||||
function Block:is_empty()
|
||||
return #self._lines == 0
|
||||
end
|
||||
|
||||
---@param bufnr number buffer number
|
||||
---@param ns_id number namespace id
|
||||
---@param linenr_start? number line number (1-indexed)
|
||||
function Block:highlight(bufnr, ns_id, linenr_start)
|
||||
self:_fix_extmarks()
|
||||
linenr_start = linenr_start or 1
|
||||
Highlight.update()
|
||||
for _, line in ipairs(self._lines) do
|
||||
line:highlight(bufnr, ns_id, linenr_start)
|
||||
linenr_start = linenr_start + 1
|
||||
end
|
||||
end
|
||||
|
||||
function Block:_fix_extmarks()
|
||||
for _, line in ipairs(self._lines) do
|
||||
for _, text in ipairs(line._texts) do
|
||||
if text.extmark then
|
||||
text.extmark.id = nil
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
---@param bufnr number buffer number
|
||||
---@param ns_id number namespace id
|
||||
---@param linenr_start? number start line number (1-indexed)
|
||||
---@param linenr_end? number end line number (1-indexed)
|
||||
function Block:render(bufnr, ns_id, linenr_start, linenr_end)
|
||||
self:_fix_extmarks()
|
||||
linenr_start = linenr_start or 1
|
||||
Highlight.update()
|
||||
for _, line in ipairs(self._lines) do
|
||||
line:render(bufnr, ns_id, linenr_start, linenr_end)
|
||||
linenr_start = linenr_start + 1
|
||||
if linenr_end then
|
||||
linenr_end = linenr_end + 1
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
---@param content string|NuiText|NuiLine
|
||||
---@param highlight? string|table data for highlight
|
||||
---@return NuiText|NuiLine
|
||||
function Block:_append(content, highlight)
|
||||
if #self._lines == 0 then
|
||||
table.insert(self._lines, NuiLine())
|
||||
end
|
||||
if type(content) == "string" and self.fix_cr ~= false then
|
||||
-- handle carriage returns. They overwrite the line from the first character
|
||||
local cr = content:match("^.*()[\r]")
|
||||
if cr then
|
||||
table.remove(self._lines)
|
||||
table.insert(self._lines, NuiLine())
|
||||
content = content:sub(cr + 1)
|
||||
end
|
||||
end
|
||||
return self._lines[#self._lines]:append(content, highlight)
|
||||
end
|
||||
|
||||
---@param contents NoiceContent|NoiceContent[]
|
||||
---@param highlight? string|table data for highlight
|
||||
function Block:set(contents, highlight)
|
||||
self:clear()
|
||||
self:append(contents, highlight)
|
||||
end
|
||||
|
||||
---@param contents NoiceContent|NoiceContent[]
|
||||
---@param highlight? string|table data for highlight
|
||||
function Block:append(contents, highlight)
|
||||
if type(contents) == "string" then
|
||||
contents = { { highlight or 0, contents } }
|
||||
end
|
||||
|
||||
if contents._texts or contents._content or contents._lines or type(contents[1]) == "number" then
|
||||
contents = { contents }
|
||||
end
|
||||
|
||||
---@cast contents NoiceContent[]
|
||||
for _, content in ipairs(contents) do
|
||||
if content._texts then
|
||||
---@cast content NuiLine
|
||||
for _, t in ipairs(content._texts) do
|
||||
self:_append(t)
|
||||
end
|
||||
elseif content._content then
|
||||
---@cast content NuiText
|
||||
self:_append(content)
|
||||
elseif content._lines then
|
||||
---@cast content NoiceBlock
|
||||
for l, line in ipairs(content._lines) do
|
||||
if l == 1 then
|
||||
-- first line should be appended to the existing line
|
||||
self:append(line)
|
||||
else
|
||||
-- other lines are appended as new lines
|
||||
table.insert(self._lines, line)
|
||||
end
|
||||
end
|
||||
else
|
||||
---@cast content NoiceChunk
|
||||
-- Handle newlines
|
||||
---@type number|string|table, string
|
||||
local attr_id, text = unpack(content)
|
||||
-- msg_show messages can contain invalid \r characters
|
||||
if self.fix_cr ~= false then
|
||||
text = text:gsub("%^M", "\r")
|
||||
text = text:gsub("\r\n", "\n")
|
||||
end
|
||||
|
||||
---@type string|table|nil
|
||||
local hl_group
|
||||
if type(attr_id) == "number" then
|
||||
hl_group = attr_id ~= 0 and Highlight.get_hl_group(attr_id) or nil
|
||||
else
|
||||
hl_group = attr_id
|
||||
end
|
||||
|
||||
while text ~= "" do
|
||||
local nl = text:find("\n")
|
||||
local line = nl and text:sub(1, nl - 1) or text
|
||||
self:_append(line, hl_group)
|
||||
if nl then
|
||||
self:newline()
|
||||
text = text:sub(nl + 1)
|
||||
else
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function Block:last_line()
|
||||
return self._lines[#self._lines]
|
||||
end
|
||||
|
||||
-- trim empty lines at the beginning and the end of the block
|
||||
function Block:trim_empty_lines()
|
||||
while #self._lines > 0 and vim.trim(self._lines[1]:content()) == "" do
|
||||
table.remove(self._lines, 1)
|
||||
end
|
||||
while #self._lines > 0 and vim.trim(self._lines[#self._lines]:content()) == "" do
|
||||
table.remove(self._lines)
|
||||
end
|
||||
end
|
||||
|
||||
function Block:newline()
|
||||
table.insert(self._lines, NuiLine())
|
||||
end
|
||||
|
||||
return Block
|
||||
@ -0,0 +1,198 @@
|
||||
local require = require("noice.util.lazy")
|
||||
|
||||
local Util = require("noice.util")
|
||||
local NoiceText = require("noice.text")
|
||||
|
||||
local M = {}
|
||||
|
||||
---@param message NoiceMessage
|
||||
---@param input NoiceMessage
|
||||
---@param opts NoiceFormatOptions.message
|
||||
function M.message(message, opts, input)
|
||||
if opts.hl_group then
|
||||
message:append(input:content(), opts.hl_group)
|
||||
else
|
||||
message:append(input)
|
||||
end
|
||||
end
|
||||
|
||||
---@param message NoiceMessage
|
||||
---@param opts NoiceFormatOptions.text
|
||||
function M.text(message, opts)
|
||||
if opts.text and opts.text ~= "" then
|
||||
message:append(opts.text, opts.hl_group)
|
||||
end
|
||||
end
|
||||
|
||||
---@param message NoiceMessage
|
||||
---@param opts NoiceFormatOptions.progress
|
||||
function M.progress(message, opts)
|
||||
local contents = require("noice.text.format").format(message, opts.contents, {
|
||||
debug = { enabled = false },
|
||||
})
|
||||
local value = vim.tbl_get(message.opts, unpack(vim.split(opts.key, ".", { plain = true })))
|
||||
if type(value) == "number" then
|
||||
local width = math.max(opts.width, contents:width() + 2)
|
||||
|
||||
local done_length = math.floor(value / 100 * width + 0.5)
|
||||
local todo_length = width - done_length
|
||||
|
||||
if opts.align == "left" then
|
||||
message:append(contents)
|
||||
end
|
||||
|
||||
if width > contents:width() then
|
||||
message:append(string.rep(" ", width - contents:width()))
|
||||
end
|
||||
|
||||
if opts.align == "right" then
|
||||
message:append(contents)
|
||||
end
|
||||
|
||||
message:append(NoiceText("", {
|
||||
hl_group = opts.hl_group_done,
|
||||
hl_mode = "replace",
|
||||
relative = true,
|
||||
col = -width,
|
||||
length = done_length,
|
||||
}))
|
||||
message:append(NoiceText("", {
|
||||
hl_group = opts.hl_group,
|
||||
hl_mode = "replace",
|
||||
relative = true,
|
||||
col = -width + done_length,
|
||||
length = todo_length,
|
||||
}))
|
||||
else
|
||||
message:append(contents)
|
||||
end
|
||||
end
|
||||
|
||||
---@param message NoiceMessage
|
||||
---@param opts NoiceFormatOptions.level
|
||||
function M.level(message, opts)
|
||||
if message.level then
|
||||
local str = message.level:sub(1, 1):upper() .. message.level:sub(2)
|
||||
if opts.icons and opts.icons[message.level] then
|
||||
str = opts.icons[message.level] .. " " .. str
|
||||
end
|
||||
message:append(" " .. str .. " ", opts.hl_group[message.level])
|
||||
end
|
||||
end
|
||||
|
||||
---@param message NoiceMessage
|
||||
---@param opts NoiceFormatOptions.kind
|
||||
function M.kind(message, opts)
|
||||
if message.kind and message.kind ~= "" then
|
||||
message:append(message.kind, opts.hl_group)
|
||||
end
|
||||
end
|
||||
|
||||
---@param message NoiceMessage
|
||||
---@param opts NoiceFormatOptions.title
|
||||
function M.title(message, opts)
|
||||
if message.opts.title then
|
||||
message:append(message.opts.title, opts.hl_group)
|
||||
end
|
||||
end
|
||||
---@param message NoiceMessage
|
||||
---@param opts NoiceFormatOptions.event
|
||||
function M.event(message, opts)
|
||||
if message.event then
|
||||
message:append(message.event, opts.hl_group)
|
||||
end
|
||||
end
|
||||
|
||||
---@param message NoiceMessage
|
||||
---@param opts NoiceFormatOptions.date
|
||||
function M.date(message, opts)
|
||||
message:append(os.date(opts.format, message.ctime), opts.hl_group)
|
||||
end
|
||||
|
||||
---@param message NoiceMessage
|
||||
---@param opts NoiceFormatOptions.debug
|
||||
function M.debug(message, opts)
|
||||
if not opts.enabled then
|
||||
return
|
||||
end
|
||||
local blocking, reason = Util.is_blocking()
|
||||
local debug = {
|
||||
message:is({ cleared = true }) and " " or " ",
|
||||
"#" .. message.id,
|
||||
message.event .. (message.kind and message.kind ~= "" and ("." .. message.kind) or ""),
|
||||
blocking and "⚡ " .. reason,
|
||||
}
|
||||
message:append(NoiceText.virtual_text(" " .. table.concat(
|
||||
vim.tbl_filter(
|
||||
---@param t string
|
||||
function(t)
|
||||
return type(t) == "string"
|
||||
end,
|
||||
debug
|
||||
),
|
||||
" "
|
||||
) .. " ", "DiagnosticVirtualTextInfo"))
|
||||
if message.event == "cmdline" then
|
||||
message:newline()
|
||||
else
|
||||
message:append(" ")
|
||||
end
|
||||
end
|
||||
|
||||
---@param message NoiceMessage
|
||||
---@param opts NoiceFormatOptions.data
|
||||
function M.data(message, opts)
|
||||
local value = vim.tbl_get(message.opts, unpack(vim.split(opts.key, ".", { plain = true })))
|
||||
if value then
|
||||
message:append("" .. value, opts.hl_group)
|
||||
end
|
||||
end
|
||||
|
||||
---@param message NoiceMessage
|
||||
---@param opts NoiceFormatOptions.spinner
|
||||
function M.spinner(message, opts)
|
||||
message:append(require("noice.util.spinners").spin(opts.name), opts.hl_group)
|
||||
end
|
||||
|
||||
---@param message NoiceMessage
|
||||
---@param _opts NoiceFormatOptions.cmdline
|
||||
function M.cmdline(message, _opts)
|
||||
if message.cmdline then
|
||||
message.cmdline:format(message, true)
|
||||
end
|
||||
end
|
||||
|
||||
---@param message NoiceMessage
|
||||
---@param input NoiceMessage
|
||||
---@param opts NoiceFormatOptions.confirm
|
||||
function M.confirm(message, opts, input)
|
||||
if message.kind ~= "confirm" then
|
||||
return message:append(input)
|
||||
end
|
||||
for l, line in ipairs(input._lines) do
|
||||
if l ~= #input._lines then
|
||||
message:append(line)
|
||||
message:newline()
|
||||
end
|
||||
end
|
||||
message:trim_empty_lines()
|
||||
message:newline()
|
||||
message:newline()
|
||||
local _, _, buttons = input:last_line():content():find("(.*):")
|
||||
if buttons then
|
||||
buttons = vim.split(buttons, ", ")
|
||||
|
||||
for b, button in ipairs(buttons) do
|
||||
local hl_group = button:find("%[") and opts.hl_group.default_choice or opts.hl_group.choice
|
||||
message:append(" " .. button .. " ", hl_group)
|
||||
if b ~= #buttons then
|
||||
message:append(" ")
|
||||
end
|
||||
end
|
||||
|
||||
local padding = math.floor((message:width() - message:last_line():width()) / 2)
|
||||
table.insert(message:last_line()._texts, 1, NoiceText((" "):rep(padding)))
|
||||
end
|
||||
end
|
||||
|
||||
return M
|
||||
@ -0,0 +1,172 @@
|
||||
local require = require("noice.util.lazy")
|
||||
|
||||
local Util = require("noice.util")
|
||||
local Config = require("noice.config")
|
||||
local FormatConfig = require("noice.config.format")
|
||||
local Formatters = require("noice.text.format.formatters")
|
||||
local NuiText = require("nui.text")
|
||||
|
||||
local M = {}
|
||||
|
||||
---@alias NoiceFormatter fun(message:NoiceMessage, opts: table, input: NoiceMessage): boolean
|
||||
---@alias NoiceFormat (string|table)[]
|
||||
|
||||
---@class NoiceFormatEntry
|
||||
---@field formatter string
|
||||
---@field before? NoiceFormatEntry
|
||||
---@field after? NoiceFormatEntry
|
||||
---@field opts table
|
||||
|
||||
---@param entry string|table<string, any>
|
||||
---@return NoiceFormatEntry?
|
||||
function M.parse_entry(entry)
|
||||
if type(entry) == "string" then
|
||||
entry = { entry }
|
||||
end
|
||||
|
||||
if #entry ~= 1 then
|
||||
Util.panic("Invalid format entry %s", vim.inspect(entry))
|
||||
return
|
||||
end
|
||||
|
||||
local text = entry[1]
|
||||
|
||||
---@type NoiceFormatEntry
|
||||
local ret = {
|
||||
formatter = "text",
|
||||
opts = { text = text },
|
||||
}
|
||||
|
||||
local before, name, after = text:match("^(.*){(.-)}(.*)$")
|
||||
if before then
|
||||
ret.formatter = name
|
||||
ret.before = M.parse_entry(before)
|
||||
ret.after = M.parse_entry(after)
|
||||
end
|
||||
|
||||
local opts_key = ret.formatter:match("^data%.(.*)")
|
||||
if opts_key then
|
||||
entry.key = opts_key
|
||||
ret.formatter = "data"
|
||||
end
|
||||
|
||||
if not Formatters[ret.formatter] then
|
||||
Util.panic("Invalid formatter %s", ret.formatter)
|
||||
return
|
||||
end
|
||||
|
||||
for k, v in pairs(entry) do
|
||||
if k == "before" then
|
||||
ret.before = M.parse_entry(v)
|
||||
elseif k == "after" then
|
||||
ret.after = M.parse_entry(v)
|
||||
elseif type(k) ~= "number" then
|
||||
---@diagnostic disable-next-line: no-unknown
|
||||
ret.opts[k] = v
|
||||
end
|
||||
end
|
||||
|
||||
return ret
|
||||
end
|
||||
|
||||
---@param message NoiceMessage
|
||||
---@param format? NoiceFormat|string
|
||||
---@param opts? NoiceFormatOptions
|
||||
---@return NoiceMessage
|
||||
function M.format(message, format, opts)
|
||||
opts = vim.tbl_deep_extend("force", vim.deepcopy(Config.options.format), opts or {})
|
||||
|
||||
format = format or "default"
|
||||
|
||||
if type(format) == "string" then
|
||||
format = vim.deepcopy(opts[format] or FormatConfig.builtin[format])
|
||||
end
|
||||
|
||||
-- use existing message, with a separate _lines array
|
||||
local ret = setmetatable({ _lines = {}, _debug = false }, { __index = message })
|
||||
if Config.options.debug and not message._debug then
|
||||
table.insert(format, 1, "{debug}")
|
||||
ret._debug = true
|
||||
end
|
||||
|
||||
for _, entry in ipairs(format) do
|
||||
entry = M.parse_entry(entry)
|
||||
if entry then
|
||||
entry.opts = vim.tbl_deep_extend("force", vim.deepcopy(opts[entry.formatter] or {}), entry.opts)
|
||||
|
||||
local formatted = setmetatable({ _lines = {} }, { __index = message })
|
||||
Formatters[entry.formatter](formatted, entry.opts, message)
|
||||
|
||||
if not formatted:is_empty() then
|
||||
if entry.before then
|
||||
Formatters[entry.before.formatter](ret, entry.before.opts, message)
|
||||
end
|
||||
|
||||
ret:append(formatted)
|
||||
|
||||
if entry.after then
|
||||
-- Else, add after
|
||||
Formatters[entry.after.formatter](ret, entry.after.opts, message)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return ret
|
||||
end
|
||||
|
||||
---@alias NoiceAlign "center" | "left" | "right" | "message-center" | "message-left" | "message-right" | "line-center" | "line-left" | "line-right"
|
||||
|
||||
---@param messages NoiceMessage[]
|
||||
---@param align? NoiceAlign
|
||||
function M.align(messages, align)
|
||||
local width = 0
|
||||
for _, m in ipairs(messages) do
|
||||
for _, line in ipairs(m._lines) do
|
||||
---@diagnostic disable-next-line: undefined-field
|
||||
if line._texts[1] and line._texts[1].padding then
|
||||
table.remove(line._texts, 1)
|
||||
end
|
||||
end
|
||||
width = math.max(width, m:width())
|
||||
end
|
||||
|
||||
for _, m in ipairs(messages) do
|
||||
M._align(m, width, align)
|
||||
end
|
||||
end
|
||||
|
||||
---@param message NoiceMessage
|
||||
---@param width integer
|
||||
---@param align? NoiceAlign
|
||||
function M._align(message, width, align)
|
||||
if align == nil or align == "left" then
|
||||
return
|
||||
end
|
||||
|
||||
local align_object = "message"
|
||||
|
||||
---@type string, string
|
||||
local ao, a = align:match("^(.-)%-(.-)$")
|
||||
if a then
|
||||
align = a
|
||||
align_object = ao
|
||||
end
|
||||
|
||||
for _, line in ipairs(message._lines) do
|
||||
local w = align_object == "line" and line:width() or message:width()
|
||||
if w < width then
|
||||
if align == "right" then
|
||||
table.insert(line._texts, 1, NuiText(string.rep(" ", width - w)))
|
||||
---@diagnostic disable-next-line: no-unknown
|
||||
line._texts[1].padding = true
|
||||
elseif align == "center" then
|
||||
table.insert(line._texts, 1, NuiText(string.rep(" ", math.floor((width - w) / 2 + 0.5))))
|
||||
---@diagnostic disable-next-line: no-unknown
|
||||
line._texts[1].padding = true
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return M
|
||||
@ -0,0 +1,85 @@
|
||||
local require = require("noice.util.lazy")
|
||||
|
||||
local ffi = require("noice.util.ffi")
|
||||
|
||||
local M = {}
|
||||
|
||||
---@class HLAttrs
|
||||
---@field rgb_ae_attr number
|
||||
---@field rgb_fg_color number
|
||||
---@field rgb_bg_color number
|
||||
---@field rgb_sp_color number
|
||||
---@field hl_blend number
|
||||
|
||||
function M.setup()
|
||||
M.attr2entry = ffi.syn_attr2entry --[[@as fun(attr: number): HLAttrs]]
|
||||
|
||||
vim.api.nvim_create_autocmd("ColorScheme", {
|
||||
pattern = "*",
|
||||
callback = function()
|
||||
M.hl = {}
|
||||
for attr_id, _ in pairs(M.hl_attrs) do
|
||||
M._create_hl(attr_id)
|
||||
end
|
||||
end,
|
||||
})
|
||||
end
|
||||
|
||||
---@param attr_id number
|
||||
function M.attr2entry(attr_id)
|
||||
M.setup()
|
||||
return M.attr2entry(attr_id)
|
||||
end
|
||||
|
||||
---@type table<number, number>
|
||||
M.hl = {}
|
||||
|
||||
---@type table<string, table>
|
||||
M.hl_attrs = {}
|
||||
|
||||
---@type table<number, number>
|
||||
M.queue = {}
|
||||
|
||||
function M.get_hl_group(attr_id)
|
||||
if attr_id == 0 then
|
||||
return "Normal"
|
||||
end
|
||||
M.queue[attr_id] = attr_id
|
||||
return "NoiceAttr" .. tostring(attr_id)
|
||||
end
|
||||
|
||||
function M.update()
|
||||
for attr_id, _ in pairs(M.queue) do
|
||||
M._create_hl(attr_id)
|
||||
end
|
||||
M.queue = {}
|
||||
end
|
||||
|
||||
function M._create_hl(attr_id)
|
||||
if attr_id == 0 then
|
||||
return
|
||||
end
|
||||
if not M.hl_attrs[attr_id] then
|
||||
local attrs = M.attr2entry(attr_id)
|
||||
M.hl_attrs[attr_id] = {
|
||||
fg = attrs.rgb_fg_color,
|
||||
bg = attrs.rgb_bg_color,
|
||||
sp = attrs.rgb_sp_color,
|
||||
bold = bit.band(attrs.rgb_ae_attr, 0x02),
|
||||
standout = bit.band(attrs.rgb_ae_attr, 0x0100),
|
||||
italic = bit.band(attrs.rgb_ae_attr, 0x04),
|
||||
underline = bit.band(attrs.rgb_ae_attr, 0x08),
|
||||
undercurl = bit.band(attrs.rgb_ae_attr, 0x10),
|
||||
nocombine = bit.band(attrs.rgb_ae_attr, 0x0200),
|
||||
reverse = bit.band(attrs.rgb_ae_attr, 0x01),
|
||||
blend = attrs.hl_blend ~= -1 and attrs.hl_blend or nil,
|
||||
}
|
||||
end
|
||||
if not M.hl[attr_id] then
|
||||
local hl_group = M.get_hl_group(attr_id)
|
||||
vim.api.nvim_set_hl(0, hl_group, M.hl_attrs[attr_id])
|
||||
M.hl[attr_id] = attr_id
|
||||
end
|
||||
end
|
||||
|
||||
return M
|
||||
@ -0,0 +1,124 @@
|
||||
local require = require("noice.util.lazy")
|
||||
|
||||
local NuiText = require("nui.text")
|
||||
local Treesitter = require("noice.text.treesitter")
|
||||
local Syntax = require("noice.text.syntax")
|
||||
local Markdown = require("noice.text.markdown")
|
||||
|
||||
---@class NoiceExtmark
|
||||
---@field col? number
|
||||
---@field end_col? number
|
||||
---@field id? number
|
||||
---@field hl_group? string
|
||||
---@field virt_self_win_col? number
|
||||
---@field relative? boolean
|
||||
---@field lang? string
|
||||
---@field lines? number
|
||||
|
||||
---@class NoiceText: NuiText
|
||||
---@field super NuiText
|
||||
---@field on_render? fun(text: NoiceText, buf:number, line: number, byte:number, col:number)
|
||||
---@overload fun(content:string, highlight?:string|NoiceExtmark):NoiceText
|
||||
---@diagnostic disable-next-line: undefined-field
|
||||
local NoiceText = NuiText:extend("NoiceText")
|
||||
|
||||
function NoiceText.virtual_text(text, hl_group)
|
||||
local content = (" "):rep(vim.api.nvim_strwidth(text))
|
||||
return NoiceText(content, {
|
||||
virt_text = { { text, hl_group } },
|
||||
virt_text_win_col = 0,
|
||||
relative = true,
|
||||
})
|
||||
end
|
||||
|
||||
function NoiceText.cursor(col)
|
||||
return NoiceText(" ", {
|
||||
hl_group = "NoiceCursor",
|
||||
col = col,
|
||||
relative = true,
|
||||
})
|
||||
end
|
||||
|
||||
---@param col? number
|
||||
function NoiceText.syntax(lang, lines, col)
|
||||
return NoiceText("", {
|
||||
lang = lang,
|
||||
col = col,
|
||||
lines = lines,
|
||||
})
|
||||
end
|
||||
|
||||
---@param bufnr number buffer number
|
||||
---@param ns_id number namespace id
|
||||
---@param linenr number line number (1-indexed)
|
||||
---@param byte_start number start byte position (0-indexed)
|
||||
---@return nil
|
||||
function NoiceText:highlight(bufnr, ns_id, linenr, byte_start)
|
||||
if not self.extmark then
|
||||
return
|
||||
end
|
||||
|
||||
if self.extmark.lang then
|
||||
local range = { linenr - self.extmark.lines, 0, linenr, byte_start + 1 }
|
||||
if self.extmark.col then
|
||||
range[2] = byte_start + self.extmark.col - 1
|
||||
end
|
||||
if Treesitter.has_lang(self.extmark.lang) then
|
||||
Treesitter.highlight(bufnr, ns_id, range, self.extmark.lang)
|
||||
else
|
||||
Syntax.highlight(bufnr, ns_id, range, self.extmark.lang)
|
||||
end
|
||||
if self.extmark.lang == "markdown" then
|
||||
Markdown.keys(bufnr)
|
||||
Markdown.conceal_escape_characters(bufnr, ns_id, range)
|
||||
end
|
||||
return
|
||||
end
|
||||
|
||||
local byte_start_orig = byte_start
|
||||
|
||||
---@type NoiceExtmark
|
||||
local orig = vim.deepcopy(self.extmark)
|
||||
local extmark = self.extmark
|
||||
|
||||
local col_start = 0
|
||||
|
||||
if extmark.relative or self.on_render then
|
||||
---@type string
|
||||
local line = vim.api.nvim_buf_get_text(bufnr, linenr - 1, 0, linenr - 1, byte_start, {})[1]
|
||||
col_start = vim.api.nvim_strwidth(line)
|
||||
end
|
||||
|
||||
if extmark.relative then
|
||||
if extmark.virt_text_win_col then
|
||||
extmark.virt_text_win_col = extmark.virt_text_win_col + col_start
|
||||
end
|
||||
if extmark.col then
|
||||
extmark.col = extmark.col + byte_start
|
||||
end
|
||||
extmark.relative = nil
|
||||
end
|
||||
|
||||
local length = self._length
|
||||
if extmark.length then
|
||||
self._length = extmark.length
|
||||
extmark.length = nil
|
||||
end
|
||||
|
||||
if extmark.col then
|
||||
---@type number
|
||||
byte_start = extmark.col
|
||||
extmark.col = nil
|
||||
end
|
||||
|
||||
NoiceText.super.highlight(self, bufnr, ns_id, linenr, byte_start)
|
||||
|
||||
if self.on_render then
|
||||
self.on_render(self, bufnr, linenr, byte_start_orig, col_start)
|
||||
end
|
||||
|
||||
self._length = length
|
||||
self.extmark = orig
|
||||
end
|
||||
|
||||
return NoiceText
|
||||
@ -0,0 +1,258 @@
|
||||
local require = require("noice.util.lazy")
|
||||
|
||||
local NoiceText = require("noice.text")
|
||||
local Config = require("noice.config")
|
||||
|
||||
---@alias MarkdownBlock {line:string}
|
||||
---@alias MarkdownCodeBlock {code:string[], lang:string}
|
||||
---@alias Markdown (MarkdownBlock|MarkdownCodeBlock)[]
|
||||
|
||||
local M = {}
|
||||
|
||||
function M.is_rule(line)
|
||||
return line and line:find("^%s*[%*%-_][%*%-_][%*%-_]+%s*$")
|
||||
end
|
||||
|
||||
function M.is_code_block(line)
|
||||
return line and line:find("^%s*```")
|
||||
end
|
||||
|
||||
function M.is_empty(line)
|
||||
return line and line:find("^%s*$")
|
||||
end
|
||||
|
||||
-- TODO:: upstream to treesitter
|
||||
-- ((backslash_escape) @conceal (#set! conceal "_") (#contains? @conceal "\_"))
|
||||
|
||||
---@param text string
|
||||
function M.html_entities(text)
|
||||
local entities = { nbsp = "", lt = "<", gt = ">", amp = "&", quot = '"', apos = "'", ensp = " ", emsp = " " }
|
||||
for entity, char in pairs(entities) do
|
||||
text = text:gsub("&" .. entity .. ";", char)
|
||||
end
|
||||
return text
|
||||
end
|
||||
|
||||
--- test\_foo
|
||||
---@param buf buffer
|
||||
---@param range number[]
|
||||
function M.conceal_escape_characters(buf, ns, range)
|
||||
local chars = "\\`*_{}[]()#+-.!/"
|
||||
local regex = "\\["
|
||||
for i = 1, #chars do
|
||||
regex = regex .. "%" .. chars:sub(i, i)
|
||||
end
|
||||
regex = regex .. "]"
|
||||
|
||||
local lines = vim.api.nvim_buf_get_lines(buf, range[1], range[3] + 1, false)
|
||||
|
||||
for l, line in ipairs(lines) do
|
||||
local c = line:find(regex)
|
||||
while c do
|
||||
vim.api.nvim_buf_set_extmark(buf, ns, range[1] + l - 1, c - 1, {
|
||||
end_col = c,
|
||||
conceal = "",
|
||||
})
|
||||
c = line:find(regex, c + 1)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- This is a <code>test</code> **booo**
|
||||
---@param text string
|
||||
---@param opts? MarkdownFormatOptions
|
||||
function M.parse(text, opts)
|
||||
opts = opts or {}
|
||||
---@type string
|
||||
text = text:gsub("</?pre>", "```"):gsub("\r", "")
|
||||
-- text = text:gsub("</?code>", "`")
|
||||
text = M.html_entities(text)
|
||||
|
||||
---@type Markdown
|
||||
local ret = {}
|
||||
|
||||
local lines = vim.split(text, "\n")
|
||||
|
||||
local l = 1
|
||||
|
||||
local function eat_nl()
|
||||
while M.is_empty(lines[l + 1]) do
|
||||
l = l + 1
|
||||
end
|
||||
end
|
||||
|
||||
while l <= #lines do
|
||||
local line = lines[l]
|
||||
if M.is_empty(line) then
|
||||
local is_start = l == 1
|
||||
eat_nl()
|
||||
local is_end = l == #lines
|
||||
if not (M.is_code_block(lines[l + 1]) or M.is_rule(lines[l + 1]) or is_start or is_end) then
|
||||
table.insert(ret, { line = "" })
|
||||
end
|
||||
elseif M.is_code_block(line) then
|
||||
---@type string
|
||||
local lang = line:match("```%s*(%S+)") or opts.ft or "text"
|
||||
local block = { lang = lang, code = {} }
|
||||
while lines[l + 1] and not M.is_code_block(lines[l + 1]) do
|
||||
table.insert(block.code, lines[l + 1])
|
||||
l = l + 1
|
||||
end
|
||||
|
||||
local prev = ret[#ret]
|
||||
if prev and not M.is_rule(prev.line) then
|
||||
table.insert(ret, { line = "" })
|
||||
end
|
||||
|
||||
table.insert(ret, block)
|
||||
l = l + 1
|
||||
eat_nl()
|
||||
elseif M.is_rule(line) then
|
||||
table.insert(ret, { line = "---" })
|
||||
eat_nl()
|
||||
else
|
||||
local prev = ret[#ret]
|
||||
if prev and prev.code then
|
||||
table.insert(ret, { line = "" })
|
||||
end
|
||||
table.insert(ret, { line = line })
|
||||
end
|
||||
l = l + 1
|
||||
end
|
||||
|
||||
return ret
|
||||
end
|
||||
|
||||
function M.get_highlights(line)
|
||||
---@type NoiceText[]
|
||||
local ret = {}
|
||||
for pattern, hl_group in pairs(Config.options.markdown.highlights) do
|
||||
local from = 1
|
||||
while from do
|
||||
---@type number, string?
|
||||
local to, match
|
||||
---@type number, number, string?
|
||||
from, to, match = line:find(pattern, from)
|
||||
if match then
|
||||
---@type number, number
|
||||
from, to = line:find(match, from)
|
||||
end
|
||||
if from then
|
||||
table.insert(
|
||||
ret,
|
||||
NoiceText("", {
|
||||
hl_group = hl_group,
|
||||
col = from - 1,
|
||||
length = to - from + 1,
|
||||
-- priority = 120,
|
||||
})
|
||||
)
|
||||
end
|
||||
from = to and to + 1 or nil
|
||||
end
|
||||
end
|
||||
return ret
|
||||
end
|
||||
|
||||
---@alias MarkdownFormatOptions {ft?: string}
|
||||
|
||||
---@param message NoiceMessage
|
||||
---@param text string
|
||||
---@param opts? MarkdownFormatOptions
|
||||
--```lua
|
||||
--local a = 1
|
||||
--local b = true
|
||||
--```
|
||||
--foo tex
|
||||
function M.format(message, text, opts)
|
||||
opts = opts or {}
|
||||
|
||||
local blocks = M.parse(text, opts)
|
||||
|
||||
local md_lines = 0
|
||||
|
||||
local function emit_md()
|
||||
if md_lines > 0 then
|
||||
message:append(NoiceText.syntax("markdown", md_lines))
|
||||
md_lines = 0
|
||||
end
|
||||
end
|
||||
|
||||
for l = 1, #blocks do
|
||||
local block = blocks[l]
|
||||
if block.code then
|
||||
emit_md()
|
||||
message:newline()
|
||||
---@cast block MarkdownCodeBlock
|
||||
for c, line in ipairs(block.code) do
|
||||
message:append(line)
|
||||
if c == #block.code then
|
||||
message:append(NoiceText.syntax(block.lang, #block.code))
|
||||
else
|
||||
message:newline()
|
||||
end
|
||||
end
|
||||
else
|
||||
---@cast block MarkdownBlock
|
||||
message:newline()
|
||||
if M.is_rule(block.line) then
|
||||
M.horizontal_line(message)
|
||||
else
|
||||
message:append(block.line)
|
||||
for _, t in ipairs(M.get_highlights(block.line)) do
|
||||
message:append(t)
|
||||
end
|
||||
md_lines = md_lines + 1
|
||||
end
|
||||
end
|
||||
end
|
||||
emit_md()
|
||||
end
|
||||
|
||||
function M.keys(buf)
|
||||
if not vim.api.nvim_buf_is_valid(buf) then
|
||||
return
|
||||
end
|
||||
if vim.b[buf].markdown_keys then
|
||||
return
|
||||
end
|
||||
|
||||
local function map(lhs)
|
||||
vim.keymap.set("n", lhs, function()
|
||||
local line = vim.api.nvim_get_current_line()
|
||||
local pos = vim.api.nvim_win_get_cursor(0)
|
||||
local col = pos[2] + 1
|
||||
|
||||
for pattern, handler in pairs(Config.options.markdown.hover) do
|
||||
local from = 1
|
||||
local to, url
|
||||
while from do
|
||||
from, to, url = line:find(pattern, from)
|
||||
if from and col >= from and col <= to then
|
||||
return handler(url)
|
||||
end
|
||||
if from then
|
||||
from = to + 1
|
||||
end
|
||||
end
|
||||
end
|
||||
vim.api.nvim_feedkeys(lhs, "n", false)
|
||||
end, { buffer = buf, silent = true })
|
||||
end
|
||||
|
||||
map("gx")
|
||||
map("K")
|
||||
|
||||
vim.b[buf].markdown_keys = true
|
||||
end
|
||||
|
||||
---@param message NoiceMessage
|
||||
function M.horizontal_line(message)
|
||||
message:append(NoiceText("", {
|
||||
virt_text_win_col = 0,
|
||||
virt_text = { { string.rep("─", vim.go.columns), "@punctuation.special.markdown" } },
|
||||
priority = 100,
|
||||
}))
|
||||
end
|
||||
|
||||
return M
|
||||
@ -0,0 +1,29 @@
|
||||
local M = {}
|
||||
|
||||
--- Highlights a region of the buffer with a given language
|
||||
---@param buf buffer buffer to highlight. Defaults to the current buffer if 0
|
||||
---@param ns number namespace for the highlights
|
||||
---@param range {[1]:number, [2]:number, [3]: number, [4]: number} (table) Region to highlight {start_row, start_col, end_row, end_col}
|
||||
---@param lang string treesitter language
|
||||
function M.highlight(buf, ns, range, lang)
|
||||
vim.api.nvim_buf_call(buf, function()
|
||||
local group = "@" .. lang:upper()
|
||||
|
||||
-- HACK: reset current_syntax, since some syntax files like markdown won't load if it is already set
|
||||
pcall(vim.api.nvim_buf_del_var, buf, "current_syntax")
|
||||
if not pcall(vim.cmd, string.format("syntax include %s syntax/%s.vim", group, lang)) then
|
||||
return
|
||||
end
|
||||
vim.cmd(
|
||||
string.format(
|
||||
"syntax region %s start=+\\%%%dl+ end=+\\%%%dl+ contains=%s keepend",
|
||||
lang .. range[1],
|
||||
range[1] + 1,
|
||||
range[3] + 1,
|
||||
group
|
||||
)
|
||||
)
|
||||
end)
|
||||
end
|
||||
|
||||
return M
|
||||
@ -0,0 +1,83 @@
|
||||
local M = {}
|
||||
M.queries = {}
|
||||
|
||||
function M.get_query(lang)
|
||||
if not M.queries[lang] then
|
||||
---@diagnostic disable-next-line: deprecated
|
||||
M.queries[lang] = (vim.treesitter.query.get or vim.treesitter.query.get_query)(lang, "highlights")
|
||||
end
|
||||
return M.queries[lang]
|
||||
end
|
||||
|
||||
function M.get_lang(ft)
|
||||
return vim.treesitter.language.get_lang and vim.treesitter.language.get_lang(ft) or ft
|
||||
end
|
||||
|
||||
function M.has_lang(lang)
|
||||
if vim.treesitter.language.get_lang then
|
||||
lang = vim.treesitter.language.get_lang(lang) or lang
|
||||
return pcall(vim.treesitter.language.add, lang)
|
||||
end
|
||||
---@diagnostic disable-next-line: deprecated
|
||||
return vim.treesitter.language.require_language(lang, nil, true)
|
||||
end
|
||||
|
||||
--- Highlights a region of the buffer with a given language
|
||||
---@param buf integer? buffer to highlight. Defaults to the current buffer if 0
|
||||
---@param ns number namespace for the highlights
|
||||
---@param range {[1]:number, [2]:number, [3]: number, [4]: number} (table) Region to highlight {start_row, start_col, end_row, end_col}
|
||||
---@param lang string treesitter language
|
||||
-- luacheck: no redefined
|
||||
function M.highlight(buf, ns, range, lang)
|
||||
lang = M.get_lang(lang)
|
||||
|
||||
buf = (buf == 0 or buf == nil) and vim.api.nvim_get_current_buf() or buf
|
||||
|
||||
-- we can't use a cached parser here since that could interfere with the existing parser of the buffer
|
||||
local LanguageTree = require("vim.treesitter.languagetree")
|
||||
local opts = { injections = { php = "", html = "" } }
|
||||
local parser = LanguageTree.new(buf --[[@as integer]], lang, opts)
|
||||
|
||||
---@diagnostic disable-next-line: invisible
|
||||
parser:set_included_regions({ { range } })
|
||||
parser:parse(true)
|
||||
|
||||
parser:for_each_tree(function(tstree, tree)
|
||||
if not tstree then
|
||||
return
|
||||
end
|
||||
local highlighter_query = M.get_query(tree:lang())
|
||||
|
||||
-- Some injected languages may not have highlight queries.
|
||||
if not highlighter_query then
|
||||
return
|
||||
end
|
||||
|
||||
local iter = highlighter_query:iter_captures(tstree:root(), buf, range[1], range[3])
|
||||
|
||||
for capture, node, metadata in iter do
|
||||
---@type number, number, number, number
|
||||
local start_row, start_col, end_row, end_col = node:range()
|
||||
|
||||
---@type string
|
||||
local name = highlighter_query.captures[capture]
|
||||
local hl = 0
|
||||
if not vim.startswith(name, "_") then
|
||||
hl = vim.api.nvim_get_hl_id_by_name("@" .. name .. "." .. lang)
|
||||
end
|
||||
local is_spell = name == "spell"
|
||||
|
||||
if hl and not is_spell then
|
||||
pcall(vim.api.nvim_buf_set_extmark, buf, ns, start_row, start_col, {
|
||||
end_line = end_row,
|
||||
end_col = end_col,
|
||||
hl_group = hl,
|
||||
priority = (tonumber(metadata.priority) or 100) + 10, -- add 10, so it will be higher than the standard highlighter of the buffer
|
||||
conceal = metadata.conceal,
|
||||
})
|
||||
end
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
return M
|
||||
@ -0,0 +1,54 @@
|
||||
---@class NuiRelative
|
||||
---@field type "'cursor'"|"'editor'"|"'win'"
|
||||
---@field winid? number
|
||||
---@field position? { row: number, col: number }
|
||||
|
||||
---@alias _.NuiBorderStyle "'double'"|"'none'"|"'rounded'"|"'shadow'"|"'single'"|"'solid'"
|
||||
|
||||
---@alias _.NuiBorderPadding {top:number, right:number, bottom:number, left:number}
|
||||
|
||||
---@class _.NuiBorder
|
||||
---@field padding? _.NuiBorderPadding
|
||||
---@field style? _.NuiBorderStyle
|
||||
---@field text? { top: string|boolean, bottom: string|boolean }
|
||||
|
||||
---@class NuiBorder: _.NuiBorder
|
||||
---@field padding? _.NuiBorderPadding|number[]
|
||||
|
||||
---@class _.NuiBaseOptions
|
||||
---@field relative? NuiRelative
|
||||
---@field enter? boolean
|
||||
---@field timeout? number
|
||||
---@field buf_options? vim.bo
|
||||
---@field win_options? vim.wo
|
||||
---@field close? {events?:string[], keys?:string[]}
|
||||
|
||||
---@class NuiBaseOptions: _.NuiBaseOptions
|
||||
---@field relative "'cursor'"|"'editor'"|"'win'"|NuiRelative
|
||||
|
||||
---@alias NuiAnchor "NW"|"NE"|"SW"|"SE"
|
||||
|
||||
---@class _.NuiPopupOptions: _.NuiBaseOptions
|
||||
---@field position { row: number|string, col: number|string}
|
||||
---@field size { width: number|string, height: number|string, max_width:number, max_height:number}
|
||||
---@field border? _.NuiBorder
|
||||
---@field anchor? NuiAnchor|"auto"
|
||||
---@field focusable boolean
|
||||
---@field zindex? number
|
||||
|
||||
---@class NuiPopupOptions: NuiBaseOptions,_.NuiPopupOptions
|
||||
---@field position number|string|{ row: number|string, col: number|string}
|
||||
---@field size number|string|{ row: number|string, col: number|string}
|
||||
---@field border? NuiBorder|_.NuiBorderStyle
|
||||
|
||||
---@class _.NuiSplitOptions: _.NuiBaseOptions
|
||||
---@field position "top"|"right"|"bottom"|"left"
|
||||
---@field scrollbar? boolean
|
||||
---@field min_size? number
|
||||
---@field max_size? number
|
||||
---@field size number|string
|
||||
|
||||
---@class NuiSplitOptions: NuiBaseOptions,_.NuiSplitOptions
|
||||
|
||||
---@alias NoiceNuiOptions NuiSplitOptions|NuiPopupOptions|{type: "split"|"popup"}
|
||||
---@alias _.NoiceNuiOptions _.NuiSplitOptions|_.NuiPopupOptions|{type: "split"|"popup"}
|
||||
@ -0,0 +1,276 @@
|
||||
local require = require("noice.util.lazy")
|
||||
|
||||
local Message = require("noice.message")
|
||||
local Manager = require("noice.message.manager")
|
||||
local Config = require("noice.config")
|
||||
local NoiceText = require("noice.text")
|
||||
local Hacks = require("noice.util.hacks")
|
||||
local Object = require("nui.object")
|
||||
|
||||
local M = {}
|
||||
M.message = Message("cmdline", nil)
|
||||
|
||||
---@enum CmdlineEvent
|
||||
M.events = {
|
||||
cmdline = "cmdline",
|
||||
show = "cmdline_show",
|
||||
hide = "cmdline_hide",
|
||||
pos = "cmdline_pos",
|
||||
special_char = "cmdline_special_char",
|
||||
block_show = "cmdline_block_show",
|
||||
block_append = "cmdline_block_append",
|
||||
block_hide = "cmdline_block_hide",
|
||||
}
|
||||
|
||||
---@type NoiceCmdline?
|
||||
M.active = nil
|
||||
|
||||
---@alias NoiceCmdlineFormatter fun(cmdline: NoiceCmdline): {icon?:string, offset?:number, view?:NoiceViewOptions}
|
||||
|
||||
---@class CmdlineState
|
||||
---@field content {[1]: integer, [2]: string}[]
|
||||
---@field pos number
|
||||
---@field firstc string
|
||||
---@field prompt string
|
||||
---@field indent number
|
||||
---@field level number
|
||||
---@field block table
|
||||
|
||||
---@class CmdlineFormat
|
||||
---@field kind string
|
||||
---@field pattern? string|string[]
|
||||
---@field view string
|
||||
---@field conceal? boolean
|
||||
---@field icon? string
|
||||
---@field icon_hl_group? string
|
||||
---@field opts? NoiceViewOptions
|
||||
---@field title? string
|
||||
---@field lang? string
|
||||
|
||||
---@class NoiceCmdline
|
||||
---@field state CmdlineState
|
||||
---@field offset integer
|
||||
---@overload fun(state:CmdlineState): NoiceCmdline
|
||||
local Cmdline = Object("NoiceCmdline")
|
||||
|
||||
---@param state CmdlineState
|
||||
function Cmdline:init(state)
|
||||
self.state = state or {}
|
||||
self.offset = 0
|
||||
end
|
||||
|
||||
function Cmdline:get()
|
||||
return table.concat(
|
||||
vim.tbl_map(function(c)
|
||||
return c[2]
|
||||
end, self.state.content),
|
||||
""
|
||||
)
|
||||
end
|
||||
|
||||
---@return CmdlineFormat
|
||||
function Cmdline:get_format()
|
||||
if self.state.prompt and self.state.prompt ~= "" then
|
||||
return Config.options.cmdline.format.input
|
||||
end
|
||||
local line = self.state.firstc .. self:get()
|
||||
|
||||
---@type {offset:number, format: CmdlineFormat}[]
|
||||
local ret = {}
|
||||
|
||||
for _, format in pairs(Config.options.cmdline.format) do
|
||||
local patterns = type(format.pattern) == "table" and format.pattern or { format.pattern }
|
||||
---@cast patterns string[]
|
||||
for _, pattern in ipairs(patterns) do
|
||||
local from, to = line:find(pattern)
|
||||
-- if match and cmdline pos is visible
|
||||
if from and self.state.pos >= to - 1 then
|
||||
ret[#ret + 1] = {
|
||||
offset = to or 0,
|
||||
format = format,
|
||||
}
|
||||
end
|
||||
end
|
||||
end
|
||||
table.sort(ret, function(a, b)
|
||||
return a.offset > b.offset
|
||||
end)
|
||||
local format = ret[1]
|
||||
if format then
|
||||
self.offset = format.format.conceal and format.offset or 0
|
||||
return format.format
|
||||
end
|
||||
self.offset = 0
|
||||
return {
|
||||
kind = self.state.firstc,
|
||||
view = "cmdline_popup",
|
||||
}
|
||||
end
|
||||
|
||||
---@param message NoiceMessage
|
||||
---@param text_only? boolean
|
||||
function Cmdline:format(message, text_only)
|
||||
local format = self:get_format()
|
||||
message.fix_cr = false
|
||||
|
||||
if format.icon then
|
||||
message:append(NoiceText.virtual_text(format.icon, format.icon_hl_group))
|
||||
message:append(" ")
|
||||
end
|
||||
|
||||
if not text_only then
|
||||
message.kind = format.kind
|
||||
end
|
||||
|
||||
-- FIXME: prompt
|
||||
if self.state.prompt ~= "" then
|
||||
message:append(self.state.prompt, "NoiceCmdlinePrompt")
|
||||
end
|
||||
|
||||
if not format.conceal then
|
||||
message:append(self.state.firstc)
|
||||
end
|
||||
|
||||
local cmd = self:get():sub(self.offset)
|
||||
|
||||
message:append(cmd)
|
||||
|
||||
if format.lang then
|
||||
message:append(NoiceText.syntax(format.lang, 1, -vim.fn.strlen(cmd)))
|
||||
end
|
||||
|
||||
if not text_only then
|
||||
local cursor = NoiceText.cursor(-self:length() + self.state.pos)
|
||||
cursor.on_render = M.on_render
|
||||
message:append(cursor)
|
||||
end
|
||||
end
|
||||
|
||||
function Cmdline:width()
|
||||
return vim.api.nvim_strwidth(self:get())
|
||||
end
|
||||
|
||||
function Cmdline:length()
|
||||
return vim.fn.strlen(self:get())
|
||||
end
|
||||
|
||||
---@type NoiceCmdline[]
|
||||
M.cmdlines = {}
|
||||
M.skipped = false
|
||||
|
||||
function M.on_show(event, content, pos, firstc, prompt, indent, level)
|
||||
local c = Cmdline({
|
||||
event = event,
|
||||
content = content,
|
||||
pos = pos,
|
||||
firstc = firstc,
|
||||
prompt = prompt,
|
||||
indent = indent,
|
||||
level = level,
|
||||
})
|
||||
|
||||
-- This was triggered by a force redraw, so skip it
|
||||
if c:get():find(Hacks.SPECIAL, 1, true) then
|
||||
M.skipped = true
|
||||
return
|
||||
end
|
||||
M.skipped = false
|
||||
|
||||
local last = M.cmdlines[level] and M.cmdlines[level].state
|
||||
if not vim.deep_equal(c.state, last) then
|
||||
M.active = c
|
||||
M.cmdlines[level] = c
|
||||
M.update()
|
||||
end
|
||||
end
|
||||
|
||||
function M.on_hide(_, level)
|
||||
if M.cmdlines[level] then
|
||||
M.cmdlines[level] = nil
|
||||
local active = M.active
|
||||
vim.defer_fn(function()
|
||||
if M.active == active then
|
||||
M.active = nil
|
||||
end
|
||||
end, 100)
|
||||
M.update()
|
||||
end
|
||||
end
|
||||
|
||||
function M.on_pos(_, pos, level)
|
||||
if M.skipped then
|
||||
return
|
||||
end
|
||||
local c = M.cmdlines[level]
|
||||
if c and c.state.pos ~= pos then
|
||||
M.cmdlines[level].state.pos = pos
|
||||
M.update()
|
||||
end
|
||||
end
|
||||
|
||||
---@class CmdlinePosition
|
||||
---@field win number Window containing the cmdline
|
||||
---@field buf number Buffer containing the cmdline
|
||||
---@field bufpos {row:number, col:number} (1-0)-indexed position of the cmdline in the buffer
|
||||
---@field screenpos {row:number, col:number} (1-0)-indexed screen position of the cmdline
|
||||
M.position = nil
|
||||
|
||||
---@param buf number
|
||||
---@param line number
|
||||
---@param byte number
|
||||
function M.on_render(_, buf, line, byte)
|
||||
Hacks.cmdline_force_redraw()
|
||||
local win = vim.fn.bufwinid(buf)
|
||||
if win ~= -1 then
|
||||
-- FIXME: check with cmp
|
||||
-- FIXME: state.pos?
|
||||
local cmdline_start = byte - (M.last():length() - M.last().offset)
|
||||
|
||||
local cursor = byte - M.last():length() + M.last().state.pos
|
||||
vim.schedule(function()
|
||||
if vim.api.nvim_win_is_valid(win) then
|
||||
vim.api.nvim_win_set_cursor(win, { 1, cursor })
|
||||
vim.api.nvim_win_call(win, function()
|
||||
local width = vim.api.nvim_win_get_width(win)
|
||||
local leftcol = math.max(cursor - width + 1, 0)
|
||||
vim.fn.winrestview({ leftcol = leftcol })
|
||||
end)
|
||||
end
|
||||
end)
|
||||
|
||||
local pos = vim.fn.screenpos(win, line, cmdline_start)
|
||||
M.position = {
|
||||
buf = buf,
|
||||
win = win,
|
||||
bufpos = {
|
||||
row = line,
|
||||
col = cmdline_start,
|
||||
},
|
||||
screenpos = {
|
||||
row = pos.row,
|
||||
col = pos.col - 1,
|
||||
},
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
function M.last()
|
||||
local last = math.max(1, unpack(vim.tbl_keys(M.cmdlines)))
|
||||
return M.cmdlines[last]
|
||||
end
|
||||
|
||||
function M.update()
|
||||
M.message:clear()
|
||||
local cmdline = M.last()
|
||||
|
||||
if cmdline then
|
||||
cmdline:format(M.message)
|
||||
Hacks.hide_cursor()
|
||||
Manager.add(M.message)
|
||||
else
|
||||
Manager.remove(M.message)
|
||||
Hacks.show_cursor()
|
||||
end
|
||||
end
|
||||
|
||||
return M
|
||||
@ -0,0 +1,5 @@
|
||||
local M = {}
|
||||
|
||||
function M.on_destroy() end
|
||||
|
||||
return M
|
||||
@ -0,0 +1,193 @@
|
||||
local require = require("noice.util.lazy")
|
||||
|
||||
local Config = require("noice.config")
|
||||
local Util = require("noice.util")
|
||||
local Router = require("noice.message.router")
|
||||
local Manager = require("noice.message.manager")
|
||||
|
||||
---@alias NoiceEvent MsgEvent|CmdlineEvent|NotifyEvent|LspEvent
|
||||
---@alias NoiceKind MsgKind|NotifyLevel|LspKind
|
||||
|
||||
local M = {}
|
||||
M._attached = false
|
||||
|
||||
---@type table<string, table|false>
|
||||
M._handlers = {}
|
||||
|
||||
function M.setup()
|
||||
local widgets = {
|
||||
messages = "msg",
|
||||
cmdline = "cmdline",
|
||||
popupmenu = "popupmenu",
|
||||
}
|
||||
|
||||
-- Check if we're running inside a GUI that already externalizes some widgets
|
||||
---@type table<string, boolean>
|
||||
local ui_widgets = {}
|
||||
local uis = vim.api.nvim_list_uis()
|
||||
for _, ui in ipairs(uis) do
|
||||
for ext, _ in pairs(widgets) do
|
||||
if ui["ext_" .. ext] then
|
||||
ui_widgets[ext] = true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
M._handlers = {}
|
||||
|
||||
---@type table<string, boolean>
|
||||
local options = {}
|
||||
for ext, widget in pairs(widgets) do
|
||||
-- only enable if configured and not enabled in the GUI
|
||||
if Config.options[ext].enabled and not ui_widgets[ext] then
|
||||
options["ext_" .. ext] = true
|
||||
M._handlers[widget] = _G.require("noice.ui." .. widget)
|
||||
else
|
||||
if ui_widgets[ext] and Config.options.debug then
|
||||
Util.warn("Disabling ext_" .. ext)
|
||||
end
|
||||
M._handlers[widget] = false
|
||||
end
|
||||
end
|
||||
return options
|
||||
end
|
||||
|
||||
function M.enable()
|
||||
local options = M.setup()
|
||||
|
||||
if vim.tbl_isempty(options) then
|
||||
if Config.options.debug then
|
||||
vim.schedule(function()
|
||||
Util.warn("No extensions enabled")
|
||||
end)
|
||||
end
|
||||
return
|
||||
end
|
||||
|
||||
if options.ext_messages then
|
||||
require("noice.ui.msg").setup()
|
||||
end
|
||||
|
||||
local safe_handle = Util.protect(M.handle, { msg = "An error happened while handling a ui event" })
|
||||
M._attached = true
|
||||
|
||||
local stack_level = 0
|
||||
|
||||
---@diagnostic disable-next-line: redundant-parameter
|
||||
vim.ui_attach(Config.ns, options, function(event, kind, ...)
|
||||
if Util.is_exiting() then
|
||||
return true
|
||||
end
|
||||
|
||||
local handler = M.get_handler(event, kind, ...)
|
||||
|
||||
if not handler then
|
||||
return
|
||||
end
|
||||
|
||||
if stack_level > 50 then
|
||||
Util.panic("Event loop detected. Shutting down...")
|
||||
return true
|
||||
end
|
||||
stack_level = stack_level + 1
|
||||
|
||||
local tick = Manager.tick()
|
||||
safe_handle(handler, event, kind, ...)
|
||||
|
||||
-- check if we need to update the ui
|
||||
if Manager.tick() > tick then
|
||||
Util.debug(function()
|
||||
local _, blocking = Util.is_blocking()
|
||||
return { event, "sl:" .. stack_level, "tick:" .. tick, blocking or false, kind }
|
||||
end)
|
||||
if
|
||||
require("noice.util.ffi").textlock == 0
|
||||
and Util.is_blocking()
|
||||
and event ~= "msg_ruler"
|
||||
and kind ~= "search_count"
|
||||
then
|
||||
Util.try(Router.update)
|
||||
end
|
||||
else
|
||||
local widget = M.parse_event(event)
|
||||
Util.stats.track(widget .. ".skipped")
|
||||
end
|
||||
stack_level = stack_level - 1
|
||||
|
||||
-- make sure only Noice handles these events
|
||||
return true
|
||||
end)
|
||||
|
||||
vim.api.nvim_create_autocmd("SwapExists", {
|
||||
group = vim.api.nvim_create_augroup("noice-swap-exists", { clear = true }),
|
||||
callback = function()
|
||||
Util.try(Router.update)
|
||||
end,
|
||||
})
|
||||
end
|
||||
|
||||
function M.redirect()
|
||||
M.disable()
|
||||
Router.echo_pending()
|
||||
vim.schedule(M.enable)
|
||||
end
|
||||
|
||||
function M.disable()
|
||||
if M._attached then
|
||||
M._attached = false
|
||||
vim.ui_detach(Config.ns)
|
||||
end
|
||||
end
|
||||
|
||||
---@return string, string
|
||||
function M.parse_event(event)
|
||||
return event:match("([a-z]+)_(.*)")
|
||||
end
|
||||
|
||||
---@param event string
|
||||
function M.get_handler(event, ...)
|
||||
local event_group, event_type = event:match("([a-z]+)_(.*)")
|
||||
local on = "on_" .. event_type
|
||||
|
||||
local handler = M._handlers[event_group]
|
||||
|
||||
-- false means this is a disabled handler
|
||||
if handler == false then
|
||||
return
|
||||
end
|
||||
|
||||
if not handler then
|
||||
if Config.options.debug then
|
||||
vim.schedule(function()
|
||||
Util.error_once("No ui router for " .. event_group)
|
||||
end)
|
||||
end
|
||||
return
|
||||
end
|
||||
|
||||
if type(handler[on]) ~= "function" then
|
||||
local args = { ... }
|
||||
if Config.options.debug then
|
||||
vim.schedule(function()
|
||||
Util.error_once(
|
||||
"No ui router for **"
|
||||
.. event
|
||||
.. "** events\n```lua\n"
|
||||
.. vim.inspect({ group = event_group, on = on, args = args })
|
||||
.. "\n```"
|
||||
)
|
||||
end)
|
||||
end
|
||||
return
|
||||
end
|
||||
|
||||
return handler[on]
|
||||
end
|
||||
|
||||
---@param handler fun(...)
|
||||
---@param event string
|
||||
function M.handle(handler, event, ...)
|
||||
handler(event, ...)
|
||||
end
|
||||
|
||||
return M
|
||||
182
config/neovim/store/lazy-plugins/noice.nvim/lua/noice/ui/msg.lua
Normal file
182
config/neovim/store/lazy-plugins/noice.nvim/lua/noice/ui/msg.lua
Normal file
@ -0,0 +1,182 @@
|
||||
local require = require("noice.util.lazy")
|
||||
|
||||
local Manager = require("noice.message.manager")
|
||||
local Message = require("noice.message")
|
||||
local Hacks = require("noice.util.hacks")
|
||||
local State = require("noice.ui.state")
|
||||
local Cmdline = require("noice.ui.cmdline")
|
||||
|
||||
local M = {}
|
||||
|
||||
---@enum MsgEvent
|
||||
M.events = {
|
||||
show = "msg_show",
|
||||
clear = "msg_clear",
|
||||
showmode = "msg_showmode",
|
||||
showcmd = "msg_showcmd",
|
||||
ruler = "msg_ruler",
|
||||
history_show = "msg_history_show",
|
||||
history_clear = "msg_history_clear",
|
||||
}
|
||||
|
||||
---@enum MsgKind
|
||||
M.kinds = {
|
||||
-- echo
|
||||
empty = "", -- (empty) Unknown (consider a feature-request: |bugs|)
|
||||
echo = "echo", -- |:echo| message
|
||||
echomsg = "echomsg", -- |:echomsg| message
|
||||
-- input related
|
||||
confirm = "confirm", -- |confirm()| or |:confirm| dialog
|
||||
confirm_sub = "confirm_sub", -- |:substitute| confirm dialog |:s_c|
|
||||
return_prompt = "return_prompt", -- |press-enter| prompt after a multiple messages
|
||||
-- error/warnings
|
||||
emsg = "emsg", -- Error (|errors|, internal error, |:throw|, …)
|
||||
echoerr = "echoerr", -- |:echoerr| message
|
||||
lua_error = "lua_error", -- Error in |:lua| code
|
||||
rpc_error = "rpc_error", -- Error response from |rpcrequest()|
|
||||
wmsg = "wmsg", -- Warning ("search hit BOTTOM", |W10|, …)
|
||||
-- hints
|
||||
quickfix = "quickfix", -- Quickfix navigation message
|
||||
search_count = "search_count", -- Search count message ("S" flag of 'shortmess')
|
||||
}
|
||||
|
||||
---@type NoiceMessage
|
||||
M.last = nil
|
||||
---@type NoiceMessage[]
|
||||
M._messages = {}
|
||||
|
||||
M._did_setup = false
|
||||
|
||||
function M.setup()
|
||||
if M._did_setup then
|
||||
return
|
||||
end
|
||||
M._did_setup = true
|
||||
|
||||
local hist = vim.trim(vim.api.nvim_cmd({ cmd = "messages" }, { output = true }))
|
||||
if hist == "" then
|
||||
return
|
||||
end
|
||||
local message = M.get(M.events.show)
|
||||
message:set(hist)
|
||||
Manager.add(message)
|
||||
end
|
||||
|
||||
function M.is_error(kind)
|
||||
return vim.tbl_contains({ M.kinds.echoerr, M.kinds.lua_error, M.kinds.rpc_error, M.kinds.emsg }, kind)
|
||||
end
|
||||
|
||||
function M.is_warning(kind)
|
||||
return kind == M.kinds.wmsg
|
||||
end
|
||||
|
||||
function M.get(event, kind)
|
||||
local id = event .. "." .. (kind or "")
|
||||
if not M._messages[id] then
|
||||
M._messages[id] = Message(event, kind)
|
||||
end
|
||||
return M._messages[id]
|
||||
end
|
||||
|
||||
---@param kind MsgKind
|
||||
---@param content NoiceContent[]
|
||||
function M.on_show(event, kind, content, replace_last)
|
||||
if kind == M.kinds.return_prompt then
|
||||
return M.on_return_prompt()
|
||||
elseif kind == M.kinds.confirm or kind == M.kinds.confirm_sub then
|
||||
return M.on_confirm(event, kind, content)
|
||||
end
|
||||
|
||||
if State.skip(event, kind, content, replace_last) then
|
||||
return
|
||||
end
|
||||
|
||||
if M.last and replace_last then
|
||||
Manager.clear({ message = M.last })
|
||||
M.last = nil
|
||||
end
|
||||
|
||||
local message
|
||||
if kind == M.kinds.search_count then
|
||||
message = M.get(event, kind)
|
||||
Hacks.fix_nohlsearch()
|
||||
else
|
||||
message = Message(event, kind)
|
||||
message.cmdline = Cmdline.active
|
||||
end
|
||||
|
||||
message:set(content)
|
||||
|
||||
message:trim_empty_lines()
|
||||
if M.is_error(kind) then
|
||||
message.level = "error"
|
||||
elseif M.is_warning(kind) then
|
||||
message.level = "warn"
|
||||
end
|
||||
|
||||
M.last = message
|
||||
|
||||
Manager.add(message)
|
||||
end
|
||||
|
||||
function M.on_clear()
|
||||
State.clear("msg_show")
|
||||
M.last = nil
|
||||
local message = M.get(M.events.show, M.kinds.search_count)
|
||||
Manager.remove(message)
|
||||
end
|
||||
|
||||
-- mode like recording...
|
||||
function M.on_showmode(event, content)
|
||||
if State.skip(event, content) then
|
||||
return
|
||||
end
|
||||
local message = M.get(event)
|
||||
if vim.tbl_isempty(content) then
|
||||
if event == "msg_showmode" then
|
||||
Manager.remove(message)
|
||||
end
|
||||
else
|
||||
message:set(content)
|
||||
Manager.add(message)
|
||||
end
|
||||
end
|
||||
M.on_showcmd = M.on_showmode
|
||||
M.on_ruler = M.on_showmode
|
||||
|
||||
function M.on_return_prompt()
|
||||
return vim.api.nvim_input("<cr>")
|
||||
end
|
||||
|
||||
---@param content NoiceChunk[]
|
||||
function M.on_confirm(event, kind, content)
|
||||
if State.skip(event, kind, content) then
|
||||
return
|
||||
end
|
||||
local message = Message(event, kind, content)
|
||||
if not message:content():find("%s+$") then
|
||||
message:append(" ")
|
||||
end
|
||||
message:append(" ", "NoiceCursor")
|
||||
Manager.add(message)
|
||||
vim.schedule(function()
|
||||
Manager.remove(message)
|
||||
end)
|
||||
end
|
||||
|
||||
---@param entries { [1]: string, [2]: NoiceChunk[]}[]
|
||||
function M.on_history_show(event, entries)
|
||||
local contents = {}
|
||||
for _, e in pairs(entries) do
|
||||
local content = e[2]
|
||||
table.insert(contents, { 0, "\n" })
|
||||
vim.list_extend(contents, content)
|
||||
end
|
||||
local message = M.get(event)
|
||||
message:set(contents)
|
||||
Manager.add(message)
|
||||
end
|
||||
|
||||
function M.on_history_clear() end
|
||||
|
||||
return M
|
||||
@ -0,0 +1,70 @@
|
||||
local require = require("noice.util.lazy")
|
||||
|
||||
local Popupmenu = require("noice.ui.popupmenu")
|
||||
|
||||
local cmp = require("cmp")
|
||||
local cmp_config = require("cmp.config")
|
||||
|
||||
---@class NoiceCmpSource: cmp.Source
|
||||
---@field before_line string
|
||||
---@field items {label: string}[]
|
||||
local source = {}
|
||||
source.new = function()
|
||||
return setmetatable({
|
||||
items = {},
|
||||
}, { __index = source })
|
||||
end
|
||||
|
||||
function source:complete(_params, callback)
|
||||
if not Popupmenu.state.visible then
|
||||
return callback()
|
||||
end
|
||||
|
||||
local items = {}
|
||||
|
||||
for i, item in ipairs(Popupmenu.state.items) do
|
||||
table.insert(items, {
|
||||
label = item.word,
|
||||
kind = cmp.lsp.CompletionItemKind.Variable,
|
||||
preselect = i == (Popupmenu.state.selected + 1),
|
||||
})
|
||||
end
|
||||
|
||||
callback({ items = items, isIncomplete = true })
|
||||
end
|
||||
|
||||
local M = {}
|
||||
|
||||
function M.setup()
|
||||
cmp.register_source("noice_popupmenu", source.new())
|
||||
for _, mode in ipairs({ ":" }) do
|
||||
if not cmp_config.cmdline[mode] then
|
||||
cmp.setup.cmdline(mode, {
|
||||
mapping = cmp.mapping.preset.cmdline(),
|
||||
sources = cmp.config.sources({
|
||||
{ name = "noice_popupmenu" },
|
||||
}),
|
||||
})
|
||||
cmp.core:prepare()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function M.on_show()
|
||||
local config = vim.deepcopy(cmp.get_config())
|
||||
config.sources = cmp.config.sources({ { name = "noice_popupmenu" } })
|
||||
cmp.core:prepare()
|
||||
cmp.complete({
|
||||
config = config,
|
||||
})
|
||||
end
|
||||
|
||||
function M.on_select()
|
||||
M.on_show()
|
||||
end
|
||||
|
||||
function M.on_hide()
|
||||
-- cmp.close()
|
||||
end
|
||||
|
||||
return M
|
||||
@ -0,0 +1,98 @@
|
||||
local require = require("noice.util.lazy")
|
||||
|
||||
local Util = require("noice.util")
|
||||
local Config = require("noice.config")
|
||||
|
||||
local M = {}
|
||||
|
||||
---@class PopupmenuBackend
|
||||
---@field setup fun()
|
||||
---@field on_show fun(state: Popupmenu)
|
||||
---@field on_select fun(state: Popupmenu)
|
||||
---@field on_hide fun()
|
||||
|
||||
---@class CompleteItem
|
||||
---@field word string the text that will be inserted, mandatory
|
||||
---@field abbr? string abbreviation of "word"; when not empty it is used in the menu instead of "word"
|
||||
---@field menu? string extra text for the popup menu, displayed after "word" or "abbr"
|
||||
---@field info? string more information about the item, can be displayed in a preview window
|
||||
---@field kind? string single letter indicating the type of completion
|
||||
---@field icase? boolean when non-zero case is to be ignored when comparing items to be equal; when omitted zero is used, thus items that only differ in case are added
|
||||
---@field equal? boolean when non-zero, always treat this item to be equal when comparing. Which means, "equal=1" disables filtering of this item.
|
||||
---@field dup? boolean when non-zero this match will be added even when an item with the same word is already present.
|
||||
---@field empty? boolean when non-zero this match will be added even when it is an empty string
|
||||
---@field user_data? any custom data which is associated with the item and available in |v:completed_item|; it can be any type; defaults to an empty string
|
||||
---@field text? NuiLine
|
||||
|
||||
---@class Popupmenu
|
||||
---@field selected number
|
||||
---@field col number
|
||||
---@field row number
|
||||
---@field grid number
|
||||
---@field items CompleteItem[]
|
||||
M.state = {
|
||||
visible = false,
|
||||
items = {},
|
||||
}
|
||||
|
||||
---@type PopupmenuBackend
|
||||
M.backend = nil
|
||||
|
||||
function M.setup()
|
||||
if Config.options.popupmenu.backend == "cmp" then
|
||||
M.backend = require("noice.ui.popupmenu.cmp")
|
||||
elseif Config.options.popupmenu.backend == "nui" then
|
||||
M.backend = require("noice.ui.popupmenu.nui")
|
||||
end
|
||||
M.backend.setup()
|
||||
end
|
||||
M.setup = Util.once(M.setup)
|
||||
|
||||
---@param items string[][]
|
||||
function M.on_show(_, items, selected, row, col, grid)
|
||||
local state = {
|
||||
items = vim.tbl_map(
|
||||
---@param item string[]
|
||||
function(item)
|
||||
return {
|
||||
word = item[1],
|
||||
kind = item[2],
|
||||
menu = item[3],
|
||||
info = item[4],
|
||||
}
|
||||
end,
|
||||
items
|
||||
),
|
||||
visible = true,
|
||||
selected = selected,
|
||||
row = row,
|
||||
col = col,
|
||||
grid = grid,
|
||||
}
|
||||
if not vim.deep_equal(state, M.state) then
|
||||
M.state = state
|
||||
M.setup()
|
||||
M.backend.on_show(M.state)
|
||||
end
|
||||
end
|
||||
|
||||
function M.on_select(_, selected)
|
||||
if M.state.selected ~= selected then
|
||||
M.state.selected = selected
|
||||
M.state.visible = true
|
||||
M.backend.on_select(M.state)
|
||||
end
|
||||
end
|
||||
|
||||
function M.on_hide()
|
||||
if M.state.visible then
|
||||
M.state.visible = false
|
||||
vim.schedule(function()
|
||||
if not M.state.visible then
|
||||
M.backend.on_hide()
|
||||
end
|
||||
end)
|
||||
end
|
||||
end
|
||||
|
||||
return M
|
||||
@ -0,0 +1,270 @@
|
||||
local require = require("noice.util.lazy")
|
||||
|
||||
local Util = require("noice.util")
|
||||
local Config = require("noice.config")
|
||||
local Menu = require("nui.menu")
|
||||
local Api = require("noice.api")
|
||||
local NuiLine = require("nui.line")
|
||||
local Scrollbar = require("noice.view.scrollbar")
|
||||
local Highlights = require("noice.config.highlights")
|
||||
|
||||
local M = {}
|
||||
---@type NuiMenu|NuiTree
|
||||
M.menu = nil
|
||||
|
||||
---@type NoiceScrollbar
|
||||
M.scroll = nil
|
||||
|
||||
function M.setup() end
|
||||
|
||||
---@param state Popupmenu
|
||||
function M.align(state)
|
||||
local max_width = 0
|
||||
for _, item in ipairs(state.items) do
|
||||
max_width = math.max(max_width, item.text:width())
|
||||
end
|
||||
for _, item in ipairs(state.items) do
|
||||
local width = item.text:width()
|
||||
if width < max_width then
|
||||
item.text:append(string.rep(" ", max_width - width))
|
||||
end
|
||||
end
|
||||
return max_width
|
||||
end
|
||||
|
||||
---@param item CompleteItem
|
||||
---@param prefix? string
|
||||
function M.format_abbr(item, prefix)
|
||||
local text = item.abbr or item.word
|
||||
if prefix and text:lower():find(prefix:lower(), 1, true) == 1 then
|
||||
item.text:append(text:sub(1, #prefix), "NoicePopupmenuMatch")
|
||||
item.text:append(text:sub(#prefix + 1), "NoiceCompletionItemWord")
|
||||
else
|
||||
item.text:append(text, "NoiceCompletionItemWord")
|
||||
end
|
||||
end
|
||||
|
||||
---@param item CompleteItem
|
||||
function M.format_menu(item)
|
||||
if item.menu and item.menu ~= "" then
|
||||
item.text:append(" ")
|
||||
item.text:append(item.menu, "NoiceCompletionItemMenu")
|
||||
end
|
||||
end
|
||||
|
||||
---@param item CompleteItem
|
||||
function M.format_kind(item)
|
||||
if item.kind and item.kind ~= "" then
|
||||
local hl_group = "CompletionItemKind" .. item.kind
|
||||
hl_group = Highlights.defaults[hl_group] and ("Noice" .. hl_group) or "NoiceCompletionItemKindDefault"
|
||||
local icon = Config.options.popupmenu.kind_icons[item.kind]
|
||||
item.text:append(" ")
|
||||
if icon then
|
||||
item.text:append(vim.trim(icon) .. " ", hl_group)
|
||||
end
|
||||
item.text:append(item.kind, hl_group)
|
||||
end
|
||||
end
|
||||
|
||||
---@param state Popupmenu
|
||||
function M.opts(state)
|
||||
local is_cmdline = state.grid == -1
|
||||
|
||||
local view = require("noice.config.views").get_options(is_cmdline and "cmdline_popupmenu" or "popupmenu")
|
||||
|
||||
local _opts = vim.deepcopy(view or {})
|
||||
_opts.enter = false
|
||||
_opts.type = "popup"
|
||||
|
||||
local opts = Util.nui.normalize(_opts)
|
||||
---@cast opts _.NuiPopupOptions
|
||||
|
||||
local padding = opts.border and opts.border.padding or {
|
||||
left = 0,
|
||||
right = 0,
|
||||
top = 0,
|
||||
bottom = 0,
|
||||
}
|
||||
|
||||
local position_auto = not opts.position or opts.position.col == "auto"
|
||||
if is_cmdline then
|
||||
if position_auto then
|
||||
-- Anchor to the cmdline
|
||||
local pos = Api.get_cmdline_position()
|
||||
if pos then
|
||||
opts.relative = { type = "editor" }
|
||||
opts.position = {
|
||||
row = pos.screenpos.row,
|
||||
col = pos.screenpos.col + state.col - padding.left,
|
||||
}
|
||||
-- the padding might get the window below 0
|
||||
if opts.position.col < 0 then
|
||||
opts.position.col = 0
|
||||
end
|
||||
|
||||
if pos.screenpos.row == vim.go.lines then
|
||||
opts.position.row = opts.position.row - 1
|
||||
opts.anchor = "SW"
|
||||
end
|
||||
end
|
||||
end
|
||||
else
|
||||
opts.relative = { type = "cursor" }
|
||||
local border = vim.tbl_get(opts, "border", "style")
|
||||
local offset = (border == nil or border == "none") and 0 or 1
|
||||
opts.position = {
|
||||
row = 1 + offset,
|
||||
col = -padding.left,
|
||||
}
|
||||
end
|
||||
|
||||
-- manage left/right padding on the line
|
||||
-- otherwise the selected CursorLine does not extend to the edges
|
||||
if opts.border and opts.border.padding then
|
||||
opts.border.padding = vim.tbl_deep_extend("force", {}, padding, { left = 0, right = 0 })
|
||||
if opts.size and type(opts.size.width) == "number" then
|
||||
opts.size.width = opts.size.width + padding.left + padding.right
|
||||
end
|
||||
end
|
||||
|
||||
return opts, padding
|
||||
end
|
||||
|
||||
---@param state Popupmenu
|
||||
function M.show(state)
|
||||
-- M.on_hide()
|
||||
local is_cmdline = state.grid == -1
|
||||
local opts, padding = M.opts(state)
|
||||
|
||||
---@type string?
|
||||
local prefix = nil
|
||||
|
||||
if is_cmdline then
|
||||
prefix = vim.fn.getcmdline():sub(state.col + 1, vim.fn.getcmdpos() - 1)
|
||||
elseif #state.items > 0 then
|
||||
prefix = state.items[1].word
|
||||
for _, item in ipairs(state.items) do
|
||||
for i = 1, #prefix do
|
||||
if prefix:sub(i, i) ~= item.word:sub(i, i) then
|
||||
prefix = prefix:sub(1, i - 1)
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
for _, item in ipairs(state.items) do
|
||||
if type(item) == "string" then
|
||||
item = { word = item }
|
||||
end
|
||||
item.text = NuiLine()
|
||||
if padding.left then
|
||||
item.text:append(string.rep(" ", padding.left))
|
||||
end
|
||||
end
|
||||
|
||||
local max_width = 0
|
||||
for _, format in ipairs({ M.format_abbr, M.format_menu, M.format_kind }) do
|
||||
for _, item in ipairs(state.items) do
|
||||
format(item, prefix)
|
||||
end
|
||||
max_width = M.align(state)
|
||||
end
|
||||
|
||||
for _, item in ipairs(state.items) do
|
||||
if padding.right then
|
||||
item.text:append(string.rep(" ", padding.right))
|
||||
end
|
||||
for _, t in ipairs(item.text._texts) do
|
||||
t._content = t._content:gsub("[\n\r]+", " ")
|
||||
end
|
||||
end
|
||||
|
||||
opts = vim.tbl_deep_extend(
|
||||
"force",
|
||||
opts,
|
||||
Util.nui.get_layout({
|
||||
width = max_width + 1, -- +1 for scrollbar
|
||||
height = #state.items,
|
||||
}, opts)
|
||||
)
|
||||
|
||||
---@type NuiTreeNode[]
|
||||
local items = vim.tbl_map(function(item)
|
||||
return Menu.item(item)
|
||||
end, state.items)
|
||||
for i, item in ipairs(items) do
|
||||
item._index = i
|
||||
end
|
||||
|
||||
if M.menu then
|
||||
M.menu._.items = items
|
||||
M.menu.tree:set_nodes(items)
|
||||
M.menu.tree:render()
|
||||
M.menu:update_layout(opts)
|
||||
else
|
||||
M.create(items, opts)
|
||||
end
|
||||
|
||||
-- redraw is needed when in blocking mode
|
||||
if Util.is_blocking() then
|
||||
Util.redraw()
|
||||
end
|
||||
|
||||
M.on_select(state)
|
||||
end
|
||||
|
||||
---@param opts _.NuiPopupOptions
|
||||
---@param items NuiTreeNode[]
|
||||
function M.create(items, opts)
|
||||
M.menu = Menu(opts, {
|
||||
lines = items,
|
||||
})
|
||||
M.menu:mount()
|
||||
Util.tag(M.menu.bufnr, "popupmenu")
|
||||
if M.menu.border then
|
||||
Util.tag(M.menu.border.bufnr, "popupmenu.border")
|
||||
end
|
||||
|
||||
M.scroll = Scrollbar({
|
||||
winnr = M.menu.winid,
|
||||
padding = Util.nui.normalize_padding(opts.border),
|
||||
})
|
||||
M.scroll:mount()
|
||||
end
|
||||
|
||||
---@param state Popupmenu
|
||||
function M.on_show(state)
|
||||
M.show(state)
|
||||
end
|
||||
|
||||
---@param state Popupmenu
|
||||
function M.on_select(state)
|
||||
if M.menu and state.selected ~= -1 then
|
||||
vim.api.nvim_win_set_cursor(M.menu.winid, { state.selected + 1, 0 })
|
||||
vim.api.nvim_exec_autocmds("WinScrolled", { modeline = false })
|
||||
end
|
||||
end
|
||||
|
||||
function M.on_hide()
|
||||
Util.protect(function()
|
||||
if M.menu then
|
||||
M.menu:unmount()
|
||||
M.menu = nil
|
||||
end
|
||||
if M.scroll then
|
||||
M.scroll:unmount()
|
||||
M.scroll = nil
|
||||
end
|
||||
end, {
|
||||
finally = function()
|
||||
if M.menu then
|
||||
M.menu._.loading = false
|
||||
end
|
||||
end,
|
||||
retry_on_E11 = true,
|
||||
retry_on_E565 = true,
|
||||
})()
|
||||
end
|
||||
|
||||
return M
|
||||
@ -0,0 +1,27 @@
|
||||
local M = {}
|
||||
|
||||
---@type table<string, any>
|
||||
M.state = {}
|
||||
|
||||
function M.set(event, ...)
|
||||
local msg = { event, ... }
|
||||
M.state[event] = msg
|
||||
end
|
||||
|
||||
function M.clear(event)
|
||||
M.state[event] = nil
|
||||
end
|
||||
|
||||
function M.is_equal(event, ...)
|
||||
local msg = { event, ... }
|
||||
return vim.deep_equal(M.state[event], msg)
|
||||
end
|
||||
|
||||
function M.skip(event, ...)
|
||||
if M.is_equal(event, ...) then
|
||||
return true
|
||||
end
|
||||
M.set(event, ...)
|
||||
end
|
||||
|
||||
return M
|
||||
@ -0,0 +1,168 @@
|
||||
local require = require("noice.util.lazy")
|
||||
|
||||
local Config = require("noice.config")
|
||||
local Util = require("noice.util")
|
||||
|
||||
---@class CallOptions
|
||||
---@field catch? fun(err:string)
|
||||
---@field finally? fun()
|
||||
---@field msg? string
|
||||
---@field retry_on_vim_errors? boolean
|
||||
---@field retry_on_E11? boolean Retry on errors due to illegal operations while the cmdline window is open
|
||||
local defaults = {
|
||||
retry_on_vim_errors = true,
|
||||
retry_on_E11 = false,
|
||||
ignore_E565 = true,
|
||||
retry_on_E565 = false,
|
||||
ignore_keyboard_interrupt = true,
|
||||
}
|
||||
|
||||
---@class Call
|
||||
---@field _fn fun()
|
||||
---@field _opts CallOptions
|
||||
---@field _retry boolean
|
||||
---@field _defer_retry boolean
|
||||
local M = {}
|
||||
M.__index = M
|
||||
|
||||
M._errors = 0
|
||||
M._max_errors = 20
|
||||
|
||||
function M.reset()
|
||||
M.reset = Util.debounce(200, function()
|
||||
M._errors = 0
|
||||
end)
|
||||
M.reset()
|
||||
end
|
||||
|
||||
---@generic F: fun()
|
||||
---@param fn F
|
||||
---@param opts? CallOptions
|
||||
---@return F
|
||||
function M.protect(fn, opts)
|
||||
if not fn then
|
||||
local trace = debug.traceback()
|
||||
Util.panic("nil passed to noice.util.call.protect. This should not happen.\n%s", trace)
|
||||
end
|
||||
local self = setmetatable({}, M)
|
||||
self._opts = vim.tbl_deep_extend("force", defaults, opts or {})
|
||||
self._fn = fn
|
||||
self._retry = false
|
||||
return function(...)
|
||||
return self(...)
|
||||
end
|
||||
end
|
||||
|
||||
function M:on_error(err)
|
||||
M._errors = M._errors + 1
|
||||
if M._errors > M._max_errors then
|
||||
Util.panic("Too many errors. Disabling Noice")
|
||||
end
|
||||
M.reset()
|
||||
|
||||
if self._opts.catch then
|
||||
pcall(self._opts.catch, err)
|
||||
end
|
||||
|
||||
if err then
|
||||
if self._opts.ignore_keyboard_interrupt and err:lower():find("keyboard interrupt") then
|
||||
M._errors = M._errors - 1
|
||||
return
|
||||
end
|
||||
|
||||
if self._opts.retry_on_E565 and err:find("E565") then
|
||||
M._errors = M._errors - 1
|
||||
self._defer_retry = true
|
||||
return
|
||||
end
|
||||
|
||||
if self._opts.ignore_E565 and err:find("E565") then
|
||||
M._errors = M._errors - 1
|
||||
return
|
||||
end
|
||||
|
||||
-- catch any Vim Errors and retry once
|
||||
if not self._retry and err:find("Vim:E%d+") and self._opts.retry_on_vim_errors then
|
||||
self._retry = true
|
||||
return
|
||||
end
|
||||
|
||||
if self._opts.retry_on_E11 and err:find("E11:") then
|
||||
M._errors = M._errors - 1
|
||||
self._defer_retry = true
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
pcall(M.log, self, err)
|
||||
self:notify(err)
|
||||
end
|
||||
|
||||
function M:log(data)
|
||||
local file = Config.options.log
|
||||
local fd = io.open(file, "a+")
|
||||
if not fd then
|
||||
error(("Could not open file %s for writing"):format(file))
|
||||
end
|
||||
fd:write("\n\n" .. os.date() .. "\n" .. self:format(data, true))
|
||||
fd:close()
|
||||
end
|
||||
|
||||
function M:format(err, stack)
|
||||
local lines = {}
|
||||
table.insert(lines, self._opts.msg or err)
|
||||
|
||||
if stack then
|
||||
if self._opts.msg then
|
||||
table.insert(lines, err)
|
||||
end
|
||||
table.insert(lines, debug.traceback("", 5))
|
||||
end
|
||||
|
||||
return table.concat(lines, "\n")
|
||||
end
|
||||
|
||||
function M:notify(err)
|
||||
local msg = self:format(err, Config.options.debug)
|
||||
vim.schedule(function()
|
||||
if not pcall(Util.error, msg) then
|
||||
vim.notify(msg, vim.log.levels.ERROR, { title = "noice.nvim" })
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
function M:__call(...)
|
||||
local args = vim.F.pack_len(...)
|
||||
|
||||
-- wrap the function and call with args
|
||||
local wrapped = function()
|
||||
return self._fn(vim.F.unpack_len(args))
|
||||
end
|
||||
|
||||
-- error handler
|
||||
local error_handler = function(err)
|
||||
pcall(self.on_error, self, err)
|
||||
return err
|
||||
end
|
||||
|
||||
---@type boolean, any
|
||||
local ok, result = xpcall(wrapped, error_handler)
|
||||
if self._retry then
|
||||
---@type boolean, any
|
||||
ok, result = xpcall(wrapped, error_handler)
|
||||
end
|
||||
|
||||
if self._opts.finally then
|
||||
pcall(self._opts.finally)
|
||||
end
|
||||
|
||||
if not ok and self._defer_retry then
|
||||
vim.defer_fn(function()
|
||||
self(vim.F.unpack_len(args))
|
||||
end, 100)
|
||||
end
|
||||
|
||||
return ok and result or nil
|
||||
end
|
||||
|
||||
return M
|
||||
@ -0,0 +1,40 @@
|
||||
local M = {}
|
||||
|
||||
---@return ffi.namespace*
|
||||
function M.load()
|
||||
-- Put in a global var to make sure we dont reload
|
||||
-- when plugin reloaders do their thing
|
||||
if not _G.noice_C then
|
||||
local ffi = require("ffi")
|
||||
local ok, err = pcall(
|
||||
ffi.cdef,
|
||||
[[typedef int32_t RgbValue;
|
||||
typedef struct attr_entry {
|
||||
int16_t rgb_ae_attr, cterm_ae_attr;
|
||||
RgbValue rgb_fg_color, rgb_bg_color, rgb_sp_color;
|
||||
int cterm_fg_color, cterm_bg_color;
|
||||
int hl_blend;
|
||||
} HlAttrs;
|
||||
HlAttrs syn_attr2entry(int attr);
|
||||
bool cmdpreview;
|
||||
extern int textlock;
|
||||
void setcursor_mayforce(bool force);
|
||||
]]
|
||||
)
|
||||
---@diagnostic disable-next-line: need-check-nil
|
||||
if not ok then
|
||||
error(err)
|
||||
end
|
||||
_G.noice_C = ffi.C
|
||||
end
|
||||
return _G.noice_C
|
||||
end
|
||||
|
||||
return setmetatable(M, {
|
||||
__index = function(_, key)
|
||||
return M.load()[key]
|
||||
end,
|
||||
__newindex = function(_, k, v)
|
||||
M.load()[k] = v
|
||||
end,
|
||||
})
|
||||
@ -0,0 +1,317 @@
|
||||
local require = require("noice.util.lazy")
|
||||
|
||||
local Util = require("noice.util")
|
||||
local Router = require("noice.message.router")
|
||||
local Api = require("noice.api")
|
||||
local Cmdline = require("noice.ui.cmdline")
|
||||
|
||||
-- HACK: a bunch of hacks to make Noice behave
|
||||
local M = {}
|
||||
|
||||
---@type fun()[]
|
||||
M._disable = {}
|
||||
|
||||
function M.reset_augroup()
|
||||
M.group = vim.api.nvim_create_augroup("noice.hacks", { clear = true })
|
||||
end
|
||||
|
||||
function M.enable()
|
||||
M.reset_augroup()
|
||||
M.fix_input()
|
||||
M.fix_redraw()
|
||||
M.fix_cmp()
|
||||
M.fix_vim_sleuth()
|
||||
-- M.fix_cmdpreview()
|
||||
|
||||
-- Hacks for Neovim < 0.10
|
||||
if vim.fn.has("nvim-0.10") == 0 then
|
||||
M.fix_incsearch()
|
||||
end
|
||||
end
|
||||
|
||||
function M.fix_vim_sleuth()
|
||||
vim.g.sleuth_noice_heuristics = 0
|
||||
end
|
||||
|
||||
function M.disable()
|
||||
M.reset_augroup()
|
||||
for _, fn in pairs(M._disable) do
|
||||
fn()
|
||||
end
|
||||
M._disable = {}
|
||||
end
|
||||
|
||||
-- start a timer that checks for vim.v.hlsearch.
|
||||
-- Clears search count and stops timer when hlsearch==0
|
||||
function M.fix_nohlsearch()
|
||||
M.fix_nohlsearch = Util.interval(30, function()
|
||||
if vim.o.hlsearch and vim.v.hlsearch == 0 then
|
||||
local m = require("noice.ui.msg").get("msg_show", "search_count")
|
||||
require("noice.message.manager").remove(m)
|
||||
end
|
||||
end, {
|
||||
enabled = function()
|
||||
return vim.o.hlsearch and vim.v.hlsearch == 1
|
||||
end,
|
||||
})
|
||||
M.fix_nohlsearch()
|
||||
end
|
||||
|
||||
---@see https://github.com/neovim/neovim/issues/20793
|
||||
function M.draw_cursor()
|
||||
if vim.api.nvim__redraw then
|
||||
vim.api.nvim__redraw({ cursor = true })
|
||||
else
|
||||
require("noice.util.ffi").setcursor_mayforce(true)
|
||||
end
|
||||
end
|
||||
|
||||
---@see https://github.com/neovim/neovim/issues/17810
|
||||
function M.fix_incsearch()
|
||||
---@type integer|nil
|
||||
local conceallevel
|
||||
|
||||
vim.api.nvim_create_autocmd("CmdlineEnter", {
|
||||
group = M.group,
|
||||
callback = function(event)
|
||||
if event.match == "/" or event.match == "?" then
|
||||
conceallevel = vim.wo.conceallevel
|
||||
vim.opt_local.conceallevel = 0
|
||||
end
|
||||
end,
|
||||
})
|
||||
|
||||
vim.api.nvim_create_autocmd("CmdlineLeave", {
|
||||
group = M.group,
|
||||
callback = function(event)
|
||||
if conceallevel and (event.match == "/" or event.match == "?") then
|
||||
vim.opt_local.conceallevel = conceallevel
|
||||
conceallevel = nil
|
||||
end
|
||||
end,
|
||||
})
|
||||
end
|
||||
|
||||
-- we need to intercept redraw so we can safely ignore message triggered by redraw
|
||||
-- This wraps vim.cmd, nvim_cmd, nvim_command and nvim_exec
|
||||
---@see https://github.com/neovim/neovim/issues/20416
|
||||
M.inside_redraw = false
|
||||
function M.fix_redraw()
|
||||
local nvim_cmd = vim.api.nvim_cmd
|
||||
|
||||
local function wrap(fn, ...)
|
||||
local inside_redraw = M.inside_redraw
|
||||
|
||||
M.inside_redraw = true
|
||||
|
||||
---@type boolean, any
|
||||
local ok, ret = pcall(fn, ...)
|
||||
|
||||
-- check if the ui needs updating
|
||||
Util.try(Router.update)
|
||||
|
||||
if not inside_redraw then
|
||||
M.inside_redraw = false
|
||||
end
|
||||
|
||||
if ok then
|
||||
return ret
|
||||
end
|
||||
error(ret)
|
||||
end
|
||||
|
||||
vim.api.nvim_cmd = function(cmd, ...)
|
||||
if type(cmd) == "table" and cmd.cmd and cmd.cmd == "redraw" then
|
||||
return wrap(nvim_cmd, cmd, ...)
|
||||
else
|
||||
return nvim_cmd(cmd, ...)
|
||||
end
|
||||
end
|
||||
|
||||
local nvim_command = vim.api.nvim_command
|
||||
vim.api.nvim_command = function(cmd, ...)
|
||||
if cmd == "redraw" then
|
||||
return wrap(nvim_command, cmd, ...)
|
||||
else
|
||||
return nvim_command(cmd, ...)
|
||||
end
|
||||
end
|
||||
|
||||
local nvim_exec = vim.api.nvim_exec
|
||||
vim.api.nvim_exec = function(cmd, ...)
|
||||
if type(cmd) == "string" and cmd:find("redraw") then
|
||||
-- WARN: this will potentially lose messages before or after the redraw ex command
|
||||
-- example: echo "foo" | redraw | echo "bar"
|
||||
-- the 'foo' message will be lost
|
||||
return wrap(nvim_exec, cmd, ...)
|
||||
else
|
||||
return nvim_exec(cmd, ...)
|
||||
end
|
||||
end
|
||||
|
||||
table.insert(M._disable, function()
|
||||
vim.api.nvim_cmd = nvim_cmd
|
||||
vim.api.nvim_command = nvim_command
|
||||
vim.api.nvim_exec = nvim_exec
|
||||
end)
|
||||
end
|
||||
|
||||
---@see https://github.com/neovim/neovim/issues/20311
|
||||
M.before_input = false
|
||||
function M.fix_input()
|
||||
local function wrap(fn, skip)
|
||||
return function(...)
|
||||
if skip and skip(...) then
|
||||
return fn(...)
|
||||
end
|
||||
|
||||
-- make sure the cursor is drawn before blocking
|
||||
M.draw_cursor()
|
||||
|
||||
local Manager = require("noice.message.manager")
|
||||
|
||||
-- do any updates now before blocking
|
||||
M.before_input = true
|
||||
Router.update()
|
||||
|
||||
---@type boolean, any
|
||||
local ok, ret = pcall(fn, ...)
|
||||
|
||||
-- clear any message right after input
|
||||
Manager.clear({ event = "msg_show", kind = { "echo", "echomsg", "" } })
|
||||
|
||||
M.before_input = false
|
||||
if ok then
|
||||
return ret
|
||||
end
|
||||
error(ret)
|
||||
end
|
||||
end
|
||||
|
||||
local function skip(expr)
|
||||
return expr ~= nil
|
||||
end
|
||||
local getchar = vim.fn.getchar
|
||||
local getcharstr = vim.fn.getcharstr
|
||||
local inputlist = vim.fn.inputlist
|
||||
-- local confirm = vim.fn.confirm
|
||||
|
||||
vim.fn.getchar = wrap(vim.fn.getchar, skip)
|
||||
vim.fn.getcharstr = wrap(vim.fn.getcharstr, skip)
|
||||
vim.fn.inputlist = wrap(vim.fn.inputlist, nil)
|
||||
-- vim.fn.confirm = wrap(vim.fn.confirm, nil)
|
||||
|
||||
table.insert(M._disable, function()
|
||||
vim.fn.getchar = getchar
|
||||
vim.fn.getcharstr = getcharstr
|
||||
vim.fn.inputlist = inputlist
|
||||
-- vim.fn.confirm = confirm
|
||||
end)
|
||||
end
|
||||
|
||||
-- Fixes cmp cmdline position
|
||||
function M.fix_cmp()
|
||||
M.on_module("cmp.utils.api", function(api)
|
||||
local get_cursor = api.get_cursor
|
||||
api.get_cursor = function()
|
||||
if api.is_cmdline_mode() then
|
||||
local pos = Api.get_cmdline_position()
|
||||
if pos then
|
||||
return { pos.bufpos.row, vim.fn.getcmdpos() - 1 }
|
||||
end
|
||||
end
|
||||
return get_cursor()
|
||||
end
|
||||
|
||||
local get_screen_cursor = api.get_screen_cursor
|
||||
api.get_screen_cursor = function()
|
||||
if api.is_cmdline_mode() then
|
||||
local pos = Api.get_cmdline_position()
|
||||
if pos then
|
||||
local col = vim.fn.getcmdpos() - Cmdline.last().offset
|
||||
return { pos.screenpos.row, pos.screenpos.col + col }
|
||||
end
|
||||
end
|
||||
return get_screen_cursor()
|
||||
end
|
||||
|
||||
table.insert(M._disable, function()
|
||||
api.get_cursor = get_cursor
|
||||
api.get_screen_cursor = get_screen_cursor
|
||||
end)
|
||||
end)
|
||||
end
|
||||
|
||||
function M.fix_cmdpreview()
|
||||
vim.api.nvim_create_autocmd("CmdlineChanged", {
|
||||
group = M.group,
|
||||
callback = function()
|
||||
local ffi = require("noice.util.ffi")
|
||||
ffi.cmdpreview = false
|
||||
vim.cmd([[redraw]])
|
||||
Util.try(require("noice.message.router").update)
|
||||
end,
|
||||
})
|
||||
end
|
||||
|
||||
M.SPECIAL = "Þ"
|
||||
function M.cmdline_force_redraw()
|
||||
if not require("noice.util.ffi").cmdpreview then
|
||||
return
|
||||
end
|
||||
|
||||
-- HACK: this will trigger redraw during substitute and cmdpreview
|
||||
vim.api.nvim_feedkeys(M.SPECIAL .. Util.BS, "n", true)
|
||||
end
|
||||
|
||||
---@type string?
|
||||
M._guicursor = nil
|
||||
function M.hide_cursor()
|
||||
if M._guicursor == nil then
|
||||
M._guicursor = vim.go.guicursor
|
||||
end
|
||||
-- schedule this, since otherwise Neovide crashes
|
||||
vim.schedule(function()
|
||||
if M._guicursor then
|
||||
vim.go.guicursor = "a:NoiceHiddenCursor"
|
||||
end
|
||||
end)
|
||||
M._disable.guicursor = M.show_cursor
|
||||
end
|
||||
|
||||
function M.show_cursor()
|
||||
if M._guicursor then
|
||||
if not Util.is_exiting() then
|
||||
vim.schedule(function()
|
||||
if M._guicursor and not Util.is_exiting() then
|
||||
-- we need to reset all first and then wait for some time before resetting the guicursor. See #114
|
||||
vim.go.guicursor = "a:"
|
||||
vim.cmd.redrawstatus()
|
||||
vim.go.guicursor = M._guicursor
|
||||
M._guicursor = nil
|
||||
end
|
||||
end)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
---@param fn fun(mod)
|
||||
function M.on_module(module, fn)
|
||||
if package.loaded[module] then
|
||||
return fn(package.loaded[module])
|
||||
end
|
||||
|
||||
package.preload[module] = function()
|
||||
package.preload[module] = nil
|
||||
for _, loader in pairs(package.loaders) do
|
||||
local ret = loader(module)
|
||||
if type(ret) == "function" then
|
||||
local mod = ret()
|
||||
fn(mod)
|
||||
return mod
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return M
|
||||
@ -0,0 +1,383 @@
|
||||
local require = require("noice.util.lazy")
|
||||
|
||||
local Hacks = require("noice.util.hacks")
|
||||
local Config = require("noice.config")
|
||||
|
||||
local M = {}
|
||||
|
||||
M.islist = vim.islist or vim.tbl_islist
|
||||
|
||||
M.stats = require("noice.util.stats")
|
||||
M.call = require("noice.util.call")
|
||||
M.nui = require("noice.util.nui")
|
||||
|
||||
function M.t(str)
|
||||
return vim.api.nvim_replace_termcodes(str, true, true, true)
|
||||
end
|
||||
|
||||
M.CR = M.t("<cr>")
|
||||
M.ESC = M.t("<esc>")
|
||||
M.BS = M.t("<bs>")
|
||||
M.EXIT = M.t("<C-\\><C-n>")
|
||||
M.LUA_CALLBACK = "\x80\253g"
|
||||
M.RIGHT = M.t("<right>")
|
||||
M.LEFT = M.t("<left>")
|
||||
M.CMD = "\x80\253h"
|
||||
|
||||
---@generic F: fun()
|
||||
---@param fn F
|
||||
---@return F
|
||||
function M.once(fn)
|
||||
local done = false
|
||||
return function(...)
|
||||
if not done then
|
||||
fn(...)
|
||||
done = true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function M.open(uri)
|
||||
local cmd
|
||||
if vim.fn.has("win32") == 1 then
|
||||
cmd = { "cmd.exe", "/c", "start", '""', vim.fn.shellescape(uri) }
|
||||
elseif vim.fn.has("macunix") == 1 then
|
||||
cmd = { "open", uri }
|
||||
else
|
||||
cmd = { "xdg-open", uri }
|
||||
end
|
||||
|
||||
local ret = vim.fn.system(cmd)
|
||||
if vim.v.shell_error ~= 0 then
|
||||
local msg = {
|
||||
"Failed to open uri",
|
||||
ret,
|
||||
vim.inspect(cmd),
|
||||
}
|
||||
vim.notify(table.concat(msg, "\n"), vim.log.levels.ERROR)
|
||||
end
|
||||
end
|
||||
|
||||
---@param fn fun():any
|
||||
function M.ignore_events(fn)
|
||||
local ei = vim.go.eventignore
|
||||
vim.go.eventignore = "all"
|
||||
local ret = fn()
|
||||
vim.go.eventignore = ei
|
||||
return ret
|
||||
end
|
||||
|
||||
function M.tag(buf, tag)
|
||||
local ft = vim.bo[buf].filetype
|
||||
|
||||
if ft == "" then
|
||||
M.ignore_events(function()
|
||||
vim.bo[buf].filetype = "noice"
|
||||
end)
|
||||
end
|
||||
|
||||
if Config.options.debug and vim.api.nvim_buf_get_name(buf) == "" then
|
||||
local path = "noice://" .. buf .. "/" .. tag
|
||||
local params = {}
|
||||
if ft ~= "" and ft ~= "noice" then
|
||||
table.insert(params, "filetype=" .. ft)
|
||||
end
|
||||
if #params > 0 then
|
||||
path = path .. "?" .. table.concat(params, "&")
|
||||
end
|
||||
vim.api.nvim_buf_set_name(buf, path)
|
||||
end
|
||||
end
|
||||
|
||||
---@param win window
|
||||
---@param options table<string, any>
|
||||
function M.wo(win, options)
|
||||
for k, v in pairs(options) do
|
||||
if vim.api.nvim_set_option_value then
|
||||
vim.api.nvim_set_option_value(k, v, { scope = "local", win = win })
|
||||
else
|
||||
vim.wo[win][k] = v
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function M.debounce(ms, fn)
|
||||
local timer = vim.loop.new_timer()
|
||||
return function(...)
|
||||
local argv = vim.F.pack_len(...)
|
||||
timer:start(ms, 0, function()
|
||||
timer:stop()
|
||||
vim.schedule_wrap(fn)(vim.F.unpack_len(argv))
|
||||
end)
|
||||
end
|
||||
end
|
||||
|
||||
---@generic F: fun()
|
||||
---@param fn F
|
||||
---@param ms integer
|
||||
---@param opts? {enabled?:fun():boolean}
|
||||
---@return F|Interval
|
||||
function M.interval(ms, fn, opts)
|
||||
opts = opts or {}
|
||||
---@type vim.loop.Timer?
|
||||
local timer = nil
|
||||
|
||||
---@class Interval
|
||||
local T = {}
|
||||
|
||||
function T.keep()
|
||||
if M.is_exiting() then
|
||||
return false
|
||||
end
|
||||
return opts.enabled == nil or opts.enabled()
|
||||
end
|
||||
|
||||
function T.running()
|
||||
return timer and not timer:is_closing()
|
||||
end
|
||||
|
||||
function T.stop()
|
||||
if timer and T.running() then
|
||||
timer:stop()
|
||||
end
|
||||
end
|
||||
|
||||
function T.fn()
|
||||
pcall(fn)
|
||||
if timer and T.running() and not T.keep() then
|
||||
timer:stop()
|
||||
elseif T.keep() and not T.running() then
|
||||
timer = vim.defer_fn(T.fn, ms)
|
||||
end
|
||||
end
|
||||
|
||||
function T.__call()
|
||||
if not T.running() and T.keep() then
|
||||
timer = vim.defer_fn(T.fn, ms)
|
||||
end
|
||||
end
|
||||
|
||||
return setmetatable(T, T)
|
||||
end
|
||||
|
||||
---@param a table<string, any>
|
||||
---@param b table<string, any>
|
||||
---@return string[]
|
||||
function M.diff_keys(a, b)
|
||||
local diff = {}
|
||||
for k, _ in pairs(a) do
|
||||
if not vim.deep_equal(a[k], b[k]) then
|
||||
diff[k] = true
|
||||
end
|
||||
end
|
||||
for k, _ in pairs(b) do
|
||||
if not vim.deep_equal(a[k], b[k]) then
|
||||
diff[k] = true
|
||||
end
|
||||
end
|
||||
return vim.tbl_keys(diff)
|
||||
end
|
||||
|
||||
function M.module_exists(mod)
|
||||
return pcall(_G.require, mod) == true
|
||||
end
|
||||
|
||||
function M.diff(a, b)
|
||||
a = vim.deepcopy(a)
|
||||
b = vim.deepcopy(b)
|
||||
M._diff(a, b)
|
||||
return { left = a, right = b }
|
||||
end
|
||||
|
||||
function M._diff(a, b)
|
||||
if a == b then
|
||||
return true
|
||||
end
|
||||
if type(a) ~= type(b) then
|
||||
return false
|
||||
end
|
||||
if type(a) == "table" then
|
||||
local equal = true
|
||||
for k, v in pairs(a) do
|
||||
if M._diff(v, b[k]) then
|
||||
a[k] = nil
|
||||
b[k] = nil
|
||||
else
|
||||
equal = false
|
||||
end
|
||||
end
|
||||
for k, _ in pairs(b) do
|
||||
if a[k] == nil then
|
||||
equal = false
|
||||
break
|
||||
end
|
||||
end
|
||||
return equal
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
---@param opts? {blocking:boolean, mode:boolean, input:boolean, redraw:boolean}
|
||||
function M.is_blocking(opts)
|
||||
opts = vim.tbl_deep_extend("force", {
|
||||
blocking = true,
|
||||
mode = true,
|
||||
input = true,
|
||||
redraw = true,
|
||||
}, opts or {})
|
||||
local mode = vim.api.nvim_get_mode()
|
||||
|
||||
local blocking_mode = false
|
||||
for _, m in ipairs({ "ic", "ix", "c", "no", "r%?", "rm" }) do
|
||||
if mode.mode:find(m) == 1 then
|
||||
blocking_mode = true
|
||||
end
|
||||
end
|
||||
|
||||
local reason = opts.blocking and mode.blocking and "blocking"
|
||||
or opts.mode and blocking_mode and ("mode:" .. mode.mode)
|
||||
or opts.input and Hacks.before_input and "input"
|
||||
or opts.redraw and Hacks.inside_redraw and "redraw"
|
||||
or #require("noice.ui.cmdline").cmdlines > 0 and "cmdline"
|
||||
or nil
|
||||
return reason ~= nil, reason
|
||||
end
|
||||
|
||||
function M.redraw()
|
||||
vim.cmd.redraw()
|
||||
M.stats.track("redraw")
|
||||
end
|
||||
|
||||
M.protect = M.call.protect
|
||||
|
||||
function M.try(fn, ...)
|
||||
return M.call.protect(fn)(...)
|
||||
end
|
||||
|
||||
function M.win_apply_config(win, opts)
|
||||
opts = vim.tbl_deep_extend("force", vim.api.nvim_win_get_config(win), opts or {})
|
||||
vim.api.nvim_win_set_config(win, opts)
|
||||
end
|
||||
|
||||
---@param msg string
|
||||
---@param level number
|
||||
---@param ... any
|
||||
function M.notify(msg, level, ...)
|
||||
if M.module_exists("notify") then
|
||||
require("notify").notify(msg:format(...), level, {
|
||||
title = "noice.nvim",
|
||||
on_open = function(win)
|
||||
vim.api.nvim_win_set_option(win, "conceallevel", 3)
|
||||
local buf = vim.api.nvim_win_get_buf(win)
|
||||
vim.api.nvim_buf_set_option(buf, "filetype", "markdown")
|
||||
vim.api.nvim_win_set_option(win, "spell", false)
|
||||
end,
|
||||
})
|
||||
else
|
||||
vim.notify(msg:format(...), level, {
|
||||
title = "noice.nvim",
|
||||
})
|
||||
end
|
||||
end
|
||||
|
||||
---@type table<string, boolean>
|
||||
M._once = {}
|
||||
|
||||
---@param msg string
|
||||
---@param level number
|
||||
---@param ... any
|
||||
function M.notify_once(msg, level, ...)
|
||||
msg = msg:format(...)
|
||||
local once = level .. msg
|
||||
if not M._once[once] then
|
||||
M.notify(msg, level)
|
||||
M._once[once] = true
|
||||
end
|
||||
end
|
||||
|
||||
function M.warn_once(msg, ...)
|
||||
M.notify_once(msg, vim.log.levels.WARN, ...)
|
||||
end
|
||||
|
||||
function M.error_once(msg, ...)
|
||||
M.notify_once(msg, vim.log.levels.ERROR, ...)
|
||||
end
|
||||
|
||||
function M.warn(msg, ...)
|
||||
M.notify(msg, vim.log.levels.WARN, ...)
|
||||
end
|
||||
|
||||
function M.error(msg, ...)
|
||||
M.notify(msg, vim.log.levels.ERROR, ...)
|
||||
end
|
||||
|
||||
--- Will stop Noice and show error
|
||||
function M.panic(msg, ...)
|
||||
require("noice").disable()
|
||||
require("noice.view.backend.notify").dismiss()
|
||||
vim.notify(msg:format(...), vim.log.levels.ERROR)
|
||||
error("Noice was stopped to prevent further errors", 0)
|
||||
end
|
||||
|
||||
function M.info(msg, ...)
|
||||
M.notify(msg, vim.log.levels.INFO, ...)
|
||||
end
|
||||
|
||||
---@param data any
|
||||
function M.debug(data)
|
||||
if not Config.options.debug then
|
||||
return
|
||||
end
|
||||
if type(data) == "function" then
|
||||
data = data()
|
||||
end
|
||||
if type(data) ~= "string" then
|
||||
data = vim.inspect(data)
|
||||
end
|
||||
local file = "./noice.log"
|
||||
local fd = io.open(file, "a+")
|
||||
if not fd then
|
||||
error(("Could not open file %s for writing"):format(file))
|
||||
end
|
||||
fd:write(data .. "\n")
|
||||
fd:close()
|
||||
end
|
||||
|
||||
---@return string
|
||||
function M.read_file(file)
|
||||
local fd = io.open(file, "r")
|
||||
if not fd then
|
||||
error(("Could not open file %s for reading"):format(file))
|
||||
end
|
||||
local data = fd:read("*a")
|
||||
fd:close()
|
||||
return data
|
||||
end
|
||||
|
||||
function M.is_exiting()
|
||||
return vim.v.exiting ~= vim.NIL
|
||||
end
|
||||
|
||||
function M.write_file(file, data)
|
||||
local fd = io.open(file, "w+")
|
||||
if not fd then
|
||||
error(("Could not open file %s for writing"):format(file))
|
||||
end
|
||||
fd:write(data)
|
||||
fd:close()
|
||||
end
|
||||
|
||||
---@generic K
|
||||
---@generic V
|
||||
---@param tbl table<K, V>
|
||||
---@param fn fun(key: K, value: V)
|
||||
---@param sorter? fun(a:V, b:V): boolean
|
||||
function M.for_each(tbl, fn, sorter)
|
||||
local keys = vim.tbl_keys(tbl)
|
||||
table.sort(keys, sorter)
|
||||
for _, key in ipairs(keys) do
|
||||
fn(key, tbl[key])
|
||||
end
|
||||
end
|
||||
|
||||
return M
|
||||
@ -0,0 +1,25 @@
|
||||
return function(module)
|
||||
local mod = nil
|
||||
|
||||
local function load()
|
||||
if not mod then
|
||||
mod = require(module)
|
||||
package.loaded[module] = mod
|
||||
end
|
||||
return mod
|
||||
end
|
||||
-- if already loaded, return the module
|
||||
-- otherwise return a lazy module
|
||||
return type(package.loaded[module]) == "table" and package.loaded[module]
|
||||
or setmetatable({}, {
|
||||
__index = function(_, key)
|
||||
return load()[key]
|
||||
end,
|
||||
__newindex = function(_, key, value)
|
||||
load()[key] = value
|
||||
end,
|
||||
__call = function(_, ...)
|
||||
return load()(...)
|
||||
end,
|
||||
})
|
||||
end
|
||||
@ -0,0 +1,254 @@
|
||||
local require = require("noice.util.lazy")
|
||||
|
||||
local Util = require("noice.util")
|
||||
local _ = require("nui.utils")._
|
||||
|
||||
local M = {}
|
||||
|
||||
---@param opts? NoiceNuiOptions
|
||||
---@return _.NoiceNuiOptions
|
||||
function M.normalize(opts)
|
||||
opts = opts or {}
|
||||
|
||||
M.normalize_win_options(opts)
|
||||
|
||||
if opts.type == "split" then
|
||||
---@cast opts NuiSplitOptions
|
||||
return M.normalize_split_options(opts)
|
||||
elseif opts.type == "popup" then
|
||||
---@cast opts NuiPopupOptions
|
||||
return M.normalize_popup_options(opts)
|
||||
end
|
||||
error("Missing type for " .. vim.inspect(opts))
|
||||
end
|
||||
|
||||
---@param opts? NoiceNuiOptions
|
||||
function M.normalize_win_options(opts)
|
||||
opts = opts or {}
|
||||
if opts.win_options and opts.win_options.winhighlight then
|
||||
opts.win_options.winhighlight = Util.nui.get_win_highlight(opts.win_options.winhighlight)
|
||||
end
|
||||
end
|
||||
|
||||
---@return {xmin:integer, xmax:integer, ymin:integer, ymax:integer}
|
||||
function M.bounds(win)
|
||||
local pos = vim.api.nvim_win_get_position(win)
|
||||
local height = vim.api.nvim_win_get_height(win)
|
||||
local width = vim.api.nvim_win_get_width(win)
|
||||
return {
|
||||
xmin = pos[2],
|
||||
xmax = pos[2] + width,
|
||||
ymin = pos[1],
|
||||
ymax = pos[1] + height,
|
||||
}
|
||||
end
|
||||
|
||||
function M.overlap(win1, win2)
|
||||
local bb1 = M.bounds(win1)
|
||||
local bb2 = M.bounds(win2)
|
||||
|
||||
-- # determine the coordinates of the intersection rectangle
|
||||
local x_left = math.max(bb1["xmin"], bb2["xmin"])
|
||||
local y_top = math.max(bb1["ymin"], bb2["ymin"])
|
||||
local x_right = math.min(bb1["xmax"], bb2["xmax"])
|
||||
local y_bottom = math.min(bb1["ymax"], bb2["ymax"])
|
||||
|
||||
if x_right < x_left or y_bottom < y_top then
|
||||
return 0.0
|
||||
end
|
||||
|
||||
-- # The intersection of two axis-aligned bounding boxes is always an
|
||||
-- # axis-aligned bounding box
|
||||
local intersection_area = math.max(x_right - x_left, 1) * math.max(y_bottom - y_top, 1)
|
||||
|
||||
-- # compute the area of both AABBs
|
||||
local bb1_area = (bb1["xmax"] - bb1["xmin"]) * (bb1["ymax"] - bb1["ymin"])
|
||||
local bb2_area = (bb2["xmax"] - bb2["xmin"]) * (bb2["ymax"] - bb2["ymin"])
|
||||
|
||||
-- # compute the intersection over union by taking the intersection
|
||||
-- # area and dividing it by the sum of prediction + ground-truth
|
||||
-- # areas - the intersection area
|
||||
return intersection_area / (bb1_area + bb2_area - intersection_area)
|
||||
end
|
||||
|
||||
---@param opts? NuiPopupOptions
|
||||
---@return _.NuiPopupOptions
|
||||
function M.normalize_popup_options(opts)
|
||||
opts = vim.deepcopy(opts or {})
|
||||
|
||||
-- relative, position, size
|
||||
_.normalize_layout_options(opts)
|
||||
|
||||
-- border
|
||||
local border = opts.border
|
||||
if type(border) == "string" then
|
||||
opts.border = { style = border }
|
||||
end
|
||||
|
||||
-- border padding
|
||||
if opts.border then
|
||||
opts.border.padding = M.normalize_padding(opts.border)
|
||||
end
|
||||
|
||||
-- fix border text
|
||||
if opts.border and (not opts.border.style or opts.border.style == "none" or opts.border.style == "shadow") then
|
||||
opts.border.text = nil
|
||||
end
|
||||
return opts
|
||||
end
|
||||
|
||||
---@param opts? NuiSplitOptions
|
||||
---@return _.NuiSplitOptions
|
||||
function M.normalize_split_options(opts)
|
||||
opts = vim.deepcopy(opts or {})
|
||||
|
||||
-- relative
|
||||
require("nui.split.utils").normalize_options(opts)
|
||||
|
||||
return opts
|
||||
end
|
||||
|
||||
---@param hl string|table<string,string>
|
||||
function M.get_win_highlight(hl)
|
||||
if type(hl) == "string" then
|
||||
return hl
|
||||
end
|
||||
local ret = {}
|
||||
for key, value in pairs(hl) do
|
||||
table.insert(ret, key .. ":" .. value)
|
||||
end
|
||||
return table.concat(ret, ",")
|
||||
end
|
||||
|
||||
---@param opts? NuiBorder|_.NuiBorderStyle|_.NuiBorder
|
||||
---@return _.NuiBorderPadding
|
||||
function M.normalize_padding(opts)
|
||||
opts = opts or {}
|
||||
if type(opts) == "string" then
|
||||
opts = { style = opts }
|
||||
end
|
||||
|
||||
if Util.islist(opts.padding) then
|
||||
if #opts.padding == 2 then
|
||||
return {
|
||||
top = opts.padding[1],
|
||||
bottom = opts.padding[1],
|
||||
left = opts.padding[2],
|
||||
right = opts.padding[2],
|
||||
}
|
||||
elseif #opts.padding == 4 then
|
||||
return {
|
||||
top = opts.padding[1],
|
||||
right = opts.padding[2],
|
||||
bottom = opts.padding[3],
|
||||
left = opts.padding[4],
|
||||
}
|
||||
end
|
||||
end
|
||||
return vim.tbl_deep_extend("force", {
|
||||
left = 0,
|
||||
right = 0,
|
||||
top = 0,
|
||||
bottom = 0,
|
||||
}, opts.padding or {})
|
||||
end
|
||||
|
||||
function M.win_buf_height(win)
|
||||
local buf = vim.api.nvim_win_get_buf(win)
|
||||
|
||||
if not vim.wo[win].wrap then
|
||||
return vim.api.nvim_buf_line_count(buf)
|
||||
end
|
||||
|
||||
local width = vim.api.nvim_win_get_width(win)
|
||||
|
||||
local lines = vim.api.nvim_buf_get_lines(buf, 0, -1, false)
|
||||
local height = 0
|
||||
for _, l in ipairs(lines) do
|
||||
height = height + math.max(1, (math.ceil(vim.fn.strwidth(l) / width)))
|
||||
end
|
||||
return height
|
||||
end
|
||||
|
||||
---@param dim {width: number, height:number}
|
||||
---@param _opts NoiceNuiOptions
|
||||
---@return _.NoiceNuiOptions
|
||||
function M.get_layout(dim, _opts)
|
||||
---@type _.NoiceNuiOptions
|
||||
local opts = M.normalize(_opts)
|
||||
|
||||
local position = vim.deepcopy(opts.position)
|
||||
local size = vim.deepcopy(opts.size)
|
||||
|
||||
---@return number
|
||||
local function minmax(min, max, value)
|
||||
return math.max(min or 1, math.min(value, max or 1000))
|
||||
end
|
||||
|
||||
if opts.type == "split" then
|
||||
---@cast opts _.NuiSplitOptions
|
||||
if size == "auto" then
|
||||
if position == "top" or position == "bottom" then
|
||||
size = minmax(opts.min_size, opts.max_size, dim.height)
|
||||
else
|
||||
size = minmax(opts.min_size, opts.max_size, dim.width)
|
||||
end
|
||||
end
|
||||
elseif opts.type == "popup" then
|
||||
if size.width == "auto" then
|
||||
size.width = minmax(size.min_width, size.max_width, dim.width)
|
||||
dim.width = size.width
|
||||
end
|
||||
if size.height == "auto" then
|
||||
size.height = minmax(size.min_height, size.max_height, dim.height)
|
||||
dim.height = size.height
|
||||
end
|
||||
if position and not (opts.relative and opts.relative.type == "cursor") then
|
||||
if type(position.col) == "number" and position.col < 0 then
|
||||
position.col = vim.o.columns + position.col - dim.width
|
||||
end
|
||||
if type(position.row) == "number" and position.row < 0 then
|
||||
position.row = vim.o.lines + position.row - dim.height
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return { size = size, position = position, relative = opts.relative }
|
||||
end
|
||||
|
||||
function M.anchor(width, height)
|
||||
local anchor = ""
|
||||
local lines_above = vim.fn.screenrow() - 1
|
||||
local lines_below = vim.fn.winheight(0) - lines_above
|
||||
|
||||
if height < lines_below then
|
||||
anchor = anchor .. "N"
|
||||
else
|
||||
anchor = anchor .. "S"
|
||||
end
|
||||
|
||||
if vim.go.columns - vim.fn.screencol() > width then
|
||||
anchor = anchor .. "W"
|
||||
else
|
||||
anchor = anchor .. "E"
|
||||
end
|
||||
return anchor
|
||||
end
|
||||
|
||||
function M.scroll(win, delta)
|
||||
local info = vim.fn.getwininfo(win)[1] or {}
|
||||
local top = info.topline or 1
|
||||
local buf = vim.api.nvim_win_get_buf(win)
|
||||
top = top + delta
|
||||
top = math.max(top, 1)
|
||||
top = math.min(top, M.win_buf_height(win) - info.height + 1)
|
||||
|
||||
vim.defer_fn(function()
|
||||
vim.api.nvim_buf_call(buf, function()
|
||||
vim.api.nvim_command("noautocmd silent! normal! " .. top .. "zt")
|
||||
vim.api.nvim_exec_autocmds("WinScrolled", { modeline = false })
|
||||
end)
|
||||
end, 0)
|
||||
end
|
||||
|
||||
return M
|
||||
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,38 @@
|
||||
local require = require("noice.util.lazy")
|
||||
|
||||
local Message = require("noice.message")
|
||||
|
||||
local M = {}
|
||||
|
||||
---@class NoiceStat
|
||||
---@field event string
|
||||
---@field count number
|
||||
|
||||
---@type table<string, NoiceStat>
|
||||
M._stats = {}
|
||||
|
||||
function M.reset()
|
||||
M._stats = {}
|
||||
end
|
||||
|
||||
function M.track(event)
|
||||
if not M._stats[event] then
|
||||
M._stats[event] = {
|
||||
event = event,
|
||||
count = 0,
|
||||
}
|
||||
end
|
||||
M._stats[event].count = M._stats[event].count + 1
|
||||
end
|
||||
|
||||
---@type NoiceMessage
|
||||
M._message = nil
|
||||
function M.message()
|
||||
if not M._message then
|
||||
M._message = Message("noice", "stats")
|
||||
end
|
||||
M._message:set(vim.inspect(M._stats))
|
||||
return M._message
|
||||
end
|
||||
|
||||
return M
|
||||
@ -0,0 +1,101 @@
|
||||
local require = require("noice.util.lazy")
|
||||
|
||||
local View = require("noice.view")
|
||||
local NuiView = require("noice.view.nui")
|
||||
local Util = require("noice.util")
|
||||
|
||||
---@class NoiceMiniOptions
|
||||
---@field timeout integer
|
||||
---@field reverse? boolean
|
||||
local defaults = { timeout = 5000 }
|
||||
|
||||
---@class MiniView: NoiceView
|
||||
---@field active table<number, NoiceMessage>
|
||||
---@field super NoiceView
|
||||
---@field view? NuiView
|
||||
---@field timers table<number, vim.loop.Timer>
|
||||
---@diagnostic disable-next-line: undefined-field
|
||||
local MiniView = View:extend("MiniView")
|
||||
|
||||
function MiniView:init(opts)
|
||||
MiniView.super.init(self, opts)
|
||||
self.active = {}
|
||||
self.timers = {}
|
||||
self._instance = "view"
|
||||
local view_opts = vim.deepcopy(self._opts)
|
||||
view_opts.type = "popup"
|
||||
view_opts.format = { "{message}" }
|
||||
view_opts.timeout = nil
|
||||
self.view = NuiView(view_opts)
|
||||
end
|
||||
|
||||
function MiniView:update_options()
|
||||
self._opts = vim.tbl_deep_extend("force", defaults, self._opts)
|
||||
end
|
||||
|
||||
---@param message NoiceMessage
|
||||
function MiniView:can_hide(message)
|
||||
if message.opts.keep and message.opts.keep() then
|
||||
return false
|
||||
end
|
||||
return not Util.is_blocking()
|
||||
end
|
||||
|
||||
function MiniView:autohide(id)
|
||||
if not self.timers[id] then
|
||||
self.timers[id] = vim.loop.new_timer()
|
||||
end
|
||||
self.timers[id]:start(self._opts.timeout, 0, function()
|
||||
if not self.active[id] then
|
||||
return
|
||||
end
|
||||
if not self:can_hide(self.active[id]) then
|
||||
return self:autohide(id)
|
||||
end
|
||||
self.active[id] = nil
|
||||
self.timers[id] = nil
|
||||
vim.schedule(function()
|
||||
self:update()
|
||||
end)
|
||||
end)
|
||||
end
|
||||
|
||||
function MiniView:show()
|
||||
for _, message in ipairs(self._messages) do
|
||||
-- we already have debug info,
|
||||
-- so make sure we dont regen it in the child view
|
||||
message._debug = true
|
||||
self.active[message.id] = message
|
||||
self:autohide(message.id)
|
||||
end
|
||||
self:clear()
|
||||
self:update()
|
||||
end
|
||||
|
||||
function MiniView:dismiss()
|
||||
self:clear()
|
||||
self.active = {}
|
||||
self:update()
|
||||
end
|
||||
|
||||
function MiniView:update()
|
||||
local active = vim.tbl_values(self.active)
|
||||
table.sort(
|
||||
active,
|
||||
---@param a NoiceMessage
|
||||
---@param b NoiceMessage
|
||||
function(a, b)
|
||||
local ret = a.id < b.id
|
||||
if self._opts.reverse then
|
||||
return not ret
|
||||
end
|
||||
return ret
|
||||
end
|
||||
)
|
||||
self.view:set(active)
|
||||
self.view:display()
|
||||
end
|
||||
|
||||
function MiniView:hide() end
|
||||
|
||||
return MiniView
|
||||
@ -0,0 +1,210 @@
|
||||
local require = require("noice.util.lazy")
|
||||
|
||||
local Util = require("noice.util")
|
||||
local View = require("noice.view")
|
||||
local Manager = require("noice.message.manager")
|
||||
local NuiText = require("nui.text")
|
||||
|
||||
---@class NoiceNotifyOptions
|
||||
---@field title string
|
||||
---@field level? string|number Message log level
|
||||
---@field merge boolean Merge messages into one Notification or create separate notifications
|
||||
---@field replace boolean Replace existing notification or create a new one
|
||||
---@field render? notify.RenderFun|string
|
||||
---@field timeout? integer
|
||||
local defaults = {
|
||||
title = "Notification",
|
||||
merge = false,
|
||||
level = nil, -- vim.log.levels.INFO,
|
||||
replace = false,
|
||||
}
|
||||
|
||||
---@class NotifyInstance
|
||||
---@field notify fun(msg:string?, level?:string|number, opts?:table): notify.Record}
|
||||
|
||||
---@alias notify.RenderFun fun(buf:buffer, notif: Notification, hl: NotifyBufHighlights, config: notify.Config)
|
||||
|
||||
---@class NotifyView: NoiceView
|
||||
---@field win? number
|
||||
---@field buf? number
|
||||
---@field notif notify.Record
|
||||
---@field super NoiceView
|
||||
---@diagnostic disable-next-line: undefined-field
|
||||
local NotifyView = View:extend("NotifyView")
|
||||
|
||||
function NotifyView.dismiss()
|
||||
require("notify").dismiss({ pending = true, silent = true })
|
||||
end
|
||||
|
||||
function NotifyView:is_available()
|
||||
return pcall(_G.require, "notify") == true
|
||||
end
|
||||
|
||||
function NotifyView:update_options()
|
||||
self._opts = vim.tbl_deep_extend("force", defaults, self._opts)
|
||||
end
|
||||
|
||||
function NotifyView:plain()
|
||||
return function(bufnr, notif)
|
||||
vim.api.nvim_buf_set_lines(bufnr, 0, -1, false, notif.message)
|
||||
end
|
||||
end
|
||||
|
||||
---@param config notify.Config
|
||||
---@param render? notify.RenderFun|string
|
||||
---@return notify.RenderFun
|
||||
function NotifyView:get_render(config, render)
|
||||
---@type string|notify.RenderFun
|
||||
local ret = render or config.render()
|
||||
if type(ret) == "string" then
|
||||
if ret == "plain" then
|
||||
ret = self:plain()
|
||||
else
|
||||
---@type notify.RenderFun
|
||||
ret = require("notify.render")[ret]
|
||||
end
|
||||
end
|
||||
return ret
|
||||
end
|
||||
|
||||
---@param messages NoiceMessage[]
|
||||
---@param render? notify.RenderFun|string
|
||||
---@param content? string
|
||||
function NotifyView:notify_render(messages, render, content)
|
||||
---@param config notify.Config
|
||||
return function(buf, notif, hl, config)
|
||||
-- run notify view
|
||||
self:get_render(config, render)(buf, notif, hl, config)
|
||||
|
||||
Util.tag(buf, "notify")
|
||||
|
||||
---@type string[]
|
||||
local lines = vim.api.nvim_buf_get_lines(buf, 0, -1, false)
|
||||
|
||||
local text = table.concat(lines, "\n")
|
||||
local idx = content and text:find(content, 1, true) or nil
|
||||
|
||||
if idx then
|
||||
-- we found the offset of the content as a string
|
||||
local before = text:sub(1, idx - 1)
|
||||
local offset = #vim.split(before, "\n")
|
||||
local offset_col = #before:match("[^\n]*$")
|
||||
|
||||
-- in case the content starts in the middle of the line,
|
||||
-- we need to add a fake prefix to the first line of the first message
|
||||
-- see #375
|
||||
if offset_col > 0 then
|
||||
messages = vim.deepcopy(messages)
|
||||
table.insert(messages[1]._lines[1]._texts, 1, NuiText(string.rep(" ", offset_col)))
|
||||
end
|
||||
|
||||
-- do our rendering
|
||||
self:render(buf, { offset = offset, highlight = true, messages = messages })
|
||||
-- in case we didn't find the offset, we won't highlight anything
|
||||
end
|
||||
|
||||
-- resize notification
|
||||
local win = vim.fn.bufwinid(buf)
|
||||
if win ~= -1 then
|
||||
---@type number
|
||||
local width = config.minimum_width()
|
||||
for _, line in pairs(lines) do
|
||||
width = math.max(width, vim.str_utfindex(line))
|
||||
end
|
||||
width = math.min(config.max_width() or 1000, width)
|
||||
local height = math.min(config.max_height() or 1000, #lines)
|
||||
Util.win_apply_config(win, { width = width, height = height })
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
---@alias NotifyMsg {content:string, messages:NoiceMessage[], title?:string, level?:string, opts?: table}
|
||||
|
||||
---@param msg NotifyMsg
|
||||
function NotifyView:_notify(msg)
|
||||
local level = self._opts.level or msg.level
|
||||
|
||||
local opts = {
|
||||
title = msg.title or self._opts.title,
|
||||
animate = not Util.is_blocking(),
|
||||
timeout = self._opts.timeout,
|
||||
replace = self._opts.replace and self.notif,
|
||||
keep = function()
|
||||
return Util.is_blocking()
|
||||
end,
|
||||
on_open = function(win)
|
||||
self:set_win_options(win)
|
||||
if self._opts.merge then
|
||||
self.win = win
|
||||
end
|
||||
end,
|
||||
on_close = function()
|
||||
self.notif = nil
|
||||
for _, m in ipairs(msg.messages) do
|
||||
m.opts.notify_id = nil
|
||||
end
|
||||
self.win = nil
|
||||
end,
|
||||
render = Util.protect(self:notify_render(msg.messages, self._opts.render, msg.content)),
|
||||
}
|
||||
|
||||
if msg.opts then
|
||||
opts = vim.tbl_deep_extend("force", opts, msg.opts)
|
||||
if type(msg.opts.replace) == "table" then
|
||||
local m = Manager.get_by_id(msg.opts.replace.id)
|
||||
opts.replace = m and m.opts.notify_id or nil
|
||||
elseif type(msg.opts.replace) == "number" then
|
||||
local m = Manager.get_by_id(msg.opts.replace)
|
||||
opts.replace = m and m.opts.notify_id or nil
|
||||
end
|
||||
end
|
||||
|
||||
---@type string?
|
||||
local content = msg.content
|
||||
|
||||
if msg.opts and msg.opts.is_nil then
|
||||
content = nil
|
||||
end
|
||||
|
||||
local id = require("notify")(content, level, opts)
|
||||
self.notif = id
|
||||
for _, m in ipairs(msg.messages) do
|
||||
m.opts.notify_id = id
|
||||
end
|
||||
end
|
||||
|
||||
function NotifyView:show()
|
||||
---@type NotifyMsg[]
|
||||
local todo = {}
|
||||
|
||||
if self._opts.merge then
|
||||
table.insert(todo, {
|
||||
content = self:content(),
|
||||
messages = self._messages,
|
||||
})
|
||||
else
|
||||
for _, m in ipairs(self._messages) do
|
||||
table.insert(todo, {
|
||||
content = m:content(),
|
||||
messages = { m },
|
||||
title = m.opts.title,
|
||||
level = m.level,
|
||||
opts = m.opts,
|
||||
})
|
||||
end
|
||||
end
|
||||
self:clear()
|
||||
|
||||
for _, msg in ipairs(todo) do
|
||||
self:_notify(msg)
|
||||
end
|
||||
end
|
||||
|
||||
function NotifyView:hide()
|
||||
if self.win and vim.api.nvim_win_is_valid(self.win) then
|
||||
vim.api.nvim_win_close(self.win, true)
|
||||
self.win = nil
|
||||
end
|
||||
end
|
||||
|
||||
return NotifyView
|
||||
@ -0,0 +1,165 @@
|
||||
local require = require("noice.util.lazy")
|
||||
|
||||
local Util = require("noice.util")
|
||||
local View = require("noice.view")
|
||||
|
||||
---@class NoiceNotifySendOptions
|
||||
---@field title string
|
||||
---@field level? string|number Message log level
|
||||
---@field merge boolean Merge messages into one Notification or create separate notifications
|
||||
---@field replace boolean Replace existing notification or create a new one
|
||||
local defaults = {
|
||||
title = "Notification",
|
||||
merge = false,
|
||||
level = nil, -- vim.log.levels.INFO,
|
||||
replace = false,
|
||||
}
|
||||
|
||||
---@class NotifySendArgs
|
||||
---@field title? string
|
||||
---@field body string
|
||||
---@field app_name? string
|
||||
---@field urgency? string
|
||||
---@field expire_time? integer
|
||||
---@field icon? string
|
||||
---@field category? string
|
||||
---@field hint? string
|
||||
---@field print_id? boolean
|
||||
---@field replace_id? string
|
||||
|
||||
---@class NotifySendView: NoiceView
|
||||
---@field win? number
|
||||
---@field buf? number
|
||||
---@field notif? string
|
||||
---@field super NoiceView
|
||||
---@diagnostic disable-next-line: undefined-field
|
||||
local NotifySendView = View:extend("NotifySendView")
|
||||
|
||||
function NotifySendView:init(opts)
|
||||
NotifySendView.super.init(self, opts)
|
||||
end
|
||||
|
||||
function NotifySendView:is_available()
|
||||
return vim.fn.executable("notify-send") == 1
|
||||
end
|
||||
|
||||
function NotifySendView:update_options()
|
||||
self._opts = vim.tbl_deep_extend("force", defaults, self._opts)
|
||||
end
|
||||
|
||||
---@alias NotifySendMsg {content:string, messages:NoiceMessage[], title?:string, level?:NotifyLevel, opts?: table}
|
||||
|
||||
---@param level? NotifyLevel|number
|
||||
function NotifySendView:get_urgency(level)
|
||||
if level then
|
||||
local l = type(level) == "number" and level or vim.log.levels[level:lower()] or vim.log.levels.INFO
|
||||
if l <= 1 then
|
||||
return "low"
|
||||
end
|
||||
if l >= 4 then
|
||||
return "critical"
|
||||
end
|
||||
end
|
||||
return "normal"
|
||||
end
|
||||
|
||||
---@param msg NotifySendMsg
|
||||
function NotifySendView:_notify(msg)
|
||||
local level = self._opts.level or msg.level
|
||||
|
||||
---@type NotifySendArgs
|
||||
local opts = {
|
||||
app_name = "nvim",
|
||||
icon = "nvim",
|
||||
title = msg.title or self._opts.title,
|
||||
body = msg.content,
|
||||
replace_id = self._opts.replace and self.notif or nil,
|
||||
urgency = self:get_urgency(level),
|
||||
}
|
||||
|
||||
local args = { "--print-id" }
|
||||
for k, v in pairs(opts) do
|
||||
if not (k == "title" or k == "body") then
|
||||
table.insert(args, "--" .. k:gsub("_", "-"))
|
||||
table.insert(args, v)
|
||||
end
|
||||
end
|
||||
if opts.title then
|
||||
table.insert(args, vim.trim(opts.title))
|
||||
end
|
||||
if opts.body then
|
||||
table.insert(args, vim.trim(opts.body))
|
||||
end
|
||||
local stdout = vim.loop.new_pipe()
|
||||
local stderr = vim.loop.new_pipe()
|
||||
|
||||
local out = ""
|
||||
local err = ""
|
||||
|
||||
local proc
|
||||
proc = vim.loop.spawn(
|
||||
"notify-send",
|
||||
{
|
||||
stdio = { nil, stdout, stderr },
|
||||
args = args,
|
||||
},
|
||||
vim.schedule_wrap(function(code, _signal) -- on exit
|
||||
stdout:close()
|
||||
stderr:close()
|
||||
proc:close()
|
||||
|
||||
if code ~= 0 then
|
||||
return Util.error("notify-send failed: %s", err)
|
||||
else
|
||||
self.notif = vim.trim(out)
|
||||
end
|
||||
end)
|
||||
)
|
||||
|
||||
vim.loop.read_start(stdout, function(_, data)
|
||||
if data then
|
||||
out = out .. data
|
||||
end
|
||||
end)
|
||||
vim.loop.read_start(stderr, function(_, data)
|
||||
if data then
|
||||
err = err .. data
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
function NotifySendView:show()
|
||||
---@type NotifySendMsg[]
|
||||
local todo = {}
|
||||
|
||||
if self._opts.merge then
|
||||
table.insert(todo, {
|
||||
content = self:content(),
|
||||
messages = self._messages,
|
||||
})
|
||||
else
|
||||
for _, m in ipairs(self._messages) do
|
||||
table.insert(todo, {
|
||||
content = m:content(),
|
||||
messages = { m },
|
||||
title = m.opts.title,
|
||||
level = m.level,
|
||||
opts = m.opts,
|
||||
})
|
||||
end
|
||||
end
|
||||
self:clear()
|
||||
|
||||
for _, msg in ipairs(todo) do
|
||||
self:_notify(msg)
|
||||
end
|
||||
end
|
||||
|
||||
function NotifySendView:hide()
|
||||
if self.win and vim.api.nvim_win_is_valid(self.win) then
|
||||
vim.api.nvim_win_close(self.win, true)
|
||||
self.win = nil
|
||||
end
|
||||
end
|
||||
|
||||
return NotifySendView
|
||||
@ -0,0 +1,5 @@
|
||||
---@param opts? NoiceViewOptions
|
||||
return function(opts)
|
||||
opts.type = "popup"
|
||||
return require("noice.view.nui")(opts)
|
||||
end
|
||||
@ -0,0 +1,5 @@
|
||||
---@param opts? NoiceViewOptions
|
||||
return function(opts)
|
||||
opts.type = "split"
|
||||
return require("noice.view.nui")(opts)
|
||||
end
|
||||
@ -0,0 +1,35 @@
|
||||
local require = require("noice.util.lazy")
|
||||
|
||||
local Config = require("noice.config")
|
||||
local View = require("noice.view")
|
||||
|
||||
---@class VirtualText: NoiceView
|
||||
---@field extmark? number
|
||||
---@field buf? number
|
||||
---@diagnostic disable-next-line: undefined-field
|
||||
local VirtualText = View:extend("VirtualTextView")
|
||||
|
||||
function VirtualText:show()
|
||||
self:hide()
|
||||
self.buf = vim.api.nvim_get_current_buf()
|
||||
|
||||
---@type number, number
|
||||
local line, col = unpack(vim.api.nvim_win_get_cursor(0))
|
||||
line = line - 1
|
||||
|
||||
if self._messages[1] then
|
||||
self.extmark = vim.api.nvim_buf_set_extmark(self.buf, Config.ns, line, col, {
|
||||
virt_text_pos = "eol",
|
||||
virt_text = { { vim.trim(self._messages[1]:content()), self._opts.hl_group or "DiagnosticVirtualTextInfo" } },
|
||||
hl_mode = "combine",
|
||||
})
|
||||
end
|
||||
end
|
||||
|
||||
function VirtualText:hide()
|
||||
if self.extmark and vim.api.nvim_buf_is_valid(self.buf) then
|
||||
vim.api.nvim_buf_del_extmark(self.buf, Config.ns, self.extmark)
|
||||
end
|
||||
end
|
||||
|
||||
return VirtualText
|
||||
@ -0,0 +1,286 @@
|
||||
local require = require("noice.util.lazy")
|
||||
|
||||
local Config = require("noice.config")
|
||||
local ConfigViews = require("noice.config.views")
|
||||
local Util = require("noice.util")
|
||||
local Object = require("nui.object")
|
||||
local Format = require("noice.text.format")
|
||||
|
||||
---@class NoiceViewBaseOptions
|
||||
---@field buf_options? table<string,any>
|
||||
---@field backend string
|
||||
---@field fallback string Fallback view in case the backend could not be loaded
|
||||
---@field format? NoiceFormat|string
|
||||
---@field align? NoiceAlign
|
||||
---@field lang? string
|
||||
---@field view string
|
||||
|
||||
---@alias NoiceViewOptions NoiceViewBaseOptions|NoiceNuiOptions|NoiceNotifyOptions
|
||||
|
||||
---@class NoiceView
|
||||
---@field _tick number
|
||||
---@field _messages NoiceMessage[]
|
||||
---@field _id integer
|
||||
---@field _opts NoiceViewOptions
|
||||
---@field _view_opts NoiceViewOptions
|
||||
---@field _route_opts NoiceViewOptions
|
||||
---@field _visible boolean
|
||||
---@field _instance "opts" | "view" | "backend"
|
||||
---@field _errors integer
|
||||
---@overload fun(opts?: NoiceViewOptions): NoiceView
|
||||
local View = Object("NoiceView")
|
||||
|
||||
---@type {view:NoiceView, opts:NoiceViewOptions}[]
|
||||
View._views = {}
|
||||
|
||||
---@param view string
|
||||
---@param opts NoiceViewOptions
|
||||
function View.get_view(view, opts)
|
||||
local opts_orig = vim.deepcopy(opts)
|
||||
opts = vim.tbl_deep_extend("force", ConfigViews.get_options(view), opts or {}, { view = view })
|
||||
|
||||
---@diagnostic disable-next-line: undefined-field
|
||||
opts.backend = opts.backend or opts.render or view
|
||||
|
||||
-- check if we already loaded this backend
|
||||
for _, v in ipairs(View._views) do
|
||||
if v.opts.view == opts.view then
|
||||
if v.view._instance == "opts" and vim.deep_equal(opts, v.opts) then
|
||||
return v.view
|
||||
end
|
||||
if v.view._instance == "view" then
|
||||
return v.view
|
||||
end
|
||||
end
|
||||
if v.opts.backend == opts.backend then
|
||||
if v.view._instance == "backend" then
|
||||
return v.view
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
---@type NoiceView
|
||||
local mod = require("noice.view.backend." .. opts.backend)
|
||||
local init_opts = vim.deepcopy(opts)
|
||||
local ret = mod(opts)
|
||||
if not ret:is_available() and opts.fallback then
|
||||
return View.get_view(opts.fallback, opts_orig)
|
||||
end
|
||||
table.insert(View._views, { view = ret, opts = init_opts })
|
||||
return ret
|
||||
end
|
||||
|
||||
local _id = 0
|
||||
---@param opts? NoiceViewOptions
|
||||
function View:init(opts)
|
||||
_id = _id + 1
|
||||
self._id = _id
|
||||
self._tick = 0
|
||||
self._messages = {}
|
||||
self._opts = opts or {}
|
||||
self._visible = false
|
||||
self._view_opts = vim.deepcopy(self._opts)
|
||||
self._instance = "opts"
|
||||
self._errors = 0
|
||||
self:update_options()
|
||||
end
|
||||
|
||||
function View:is_available()
|
||||
return true
|
||||
end
|
||||
|
||||
function View:update_options() end
|
||||
|
||||
---@param messages NoiceMessage|NoiceMessage[]
|
||||
---@param opts? {format?: boolean}
|
||||
function View:push(messages, opts)
|
||||
opts = opts or {}
|
||||
|
||||
messages = Util.islist(messages) and messages or { messages }
|
||||
---@cast messages NoiceMessage[]
|
||||
|
||||
for _, message in ipairs(messages) do
|
||||
if opts.format ~= false then
|
||||
message = Format.format(message, self._opts.format)
|
||||
end
|
||||
table.insert(self._messages, message)
|
||||
end
|
||||
end
|
||||
|
||||
function View:clear()
|
||||
self._messages = {}
|
||||
self._route_opts = {}
|
||||
end
|
||||
|
||||
function View:dismiss()
|
||||
self:clear()
|
||||
end
|
||||
|
||||
function View:check_options()
|
||||
---@type NoiceViewOptions
|
||||
local old = vim.deepcopy(self._opts)
|
||||
self._opts = vim.tbl_deep_extend("force", vim.deepcopy(self._view_opts), self._route_opts or {})
|
||||
self:update_options()
|
||||
if not vim.deep_equal(old, self._opts) then
|
||||
self:reset(old, self._opts)
|
||||
end
|
||||
end
|
||||
|
||||
---@param messages NoiceMessage[]
|
||||
---@param opts? {format?: boolean}
|
||||
function View:set(messages, opts)
|
||||
opts = opts or {}
|
||||
self:clear()
|
||||
self:push(messages, opts)
|
||||
end
|
||||
|
||||
function View:debug(msg)
|
||||
if Config.options.debug then
|
||||
Util.debug(("[%s] %s"):format(self._opts.view, vim.inspect(msg)))
|
||||
Util.debug(debug.traceback())
|
||||
end
|
||||
end
|
||||
|
||||
-- Safely destroys any create windows and buffers.
|
||||
-- This is needed to properly re-create views in case of E565 errors
|
||||
function View:destroy() end
|
||||
|
||||
function View:display()
|
||||
if #self._messages > 0 then
|
||||
Format.align(self._messages, self._opts.align)
|
||||
self:check_options()
|
||||
|
||||
Util.protect(function()
|
||||
self._errors = self._errors + 1
|
||||
self:show()
|
||||
self._errors = 0
|
||||
end, {
|
||||
catch = function(err)
|
||||
self:debug(err)
|
||||
self:destroy()
|
||||
end,
|
||||
})()
|
||||
|
||||
self._visible = true
|
||||
else
|
||||
if self._visible then
|
||||
self:hide()
|
||||
end
|
||||
self._visible = false
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
---@param old NoiceViewOptions
|
||||
---@param new NoiceViewOptions
|
||||
function View:reset(old, new) end
|
||||
|
||||
function View:show()
|
||||
Util.error("Missing implementation `View:show()` for %s", self)
|
||||
end
|
||||
|
||||
function View:hide()
|
||||
Util.error("Missing implementation `View:hide()` for %s", self)
|
||||
end
|
||||
|
||||
---@param messages? NoiceMessage[]
|
||||
function View:height(messages)
|
||||
local ret = 0
|
||||
for _, m in ipairs(messages or self._messages) do
|
||||
ret = ret + m:height()
|
||||
end
|
||||
return ret
|
||||
end
|
||||
|
||||
---@param messages? NoiceMessage[]
|
||||
function View:width(messages)
|
||||
local ret = 0
|
||||
for _, m in ipairs(messages or self._messages) do
|
||||
ret = math.max(ret, m:width())
|
||||
end
|
||||
return ret
|
||||
end
|
||||
|
||||
function View:content()
|
||||
return table.concat(
|
||||
vim.tbl_map(
|
||||
---@param m NoiceMessage
|
||||
function(m)
|
||||
return m:content()
|
||||
end,
|
||||
self._messages
|
||||
),
|
||||
"\n"
|
||||
)
|
||||
end
|
||||
|
||||
function View:set_win_options(win)
|
||||
if self._opts.win_options then
|
||||
Util.wo(win, self._opts.win_options)
|
||||
end
|
||||
-- reset cursor on show
|
||||
vim.api.nvim_win_set_cursor(win, { 1, 0 })
|
||||
if self._opts.type == "split" then
|
||||
vim.schedule(function()
|
||||
-- this is needed to make the nui split behave with vim.go.splitkeep
|
||||
if win and vim.api.nvim_win_is_valid(win) then
|
||||
vim.api.nvim_win_set_cursor(win, { 1, 0 })
|
||||
vim.api.nvim_win_call(win, function()
|
||||
vim.cmd([[noautocmd silent! normal! zt]])
|
||||
end)
|
||||
end
|
||||
end)
|
||||
end
|
||||
end
|
||||
|
||||
---@param buf number buffer number
|
||||
---@param opts? {offset: number, highlight: boolean, messages?: NoiceMessage[]} line number (1-indexed), if `highlight`, then only highlight
|
||||
function View:render(buf, opts)
|
||||
if not Config.is_running() then
|
||||
return
|
||||
end
|
||||
opts = opts or {}
|
||||
local linenr = opts.offset or 1
|
||||
|
||||
if self._opts.buf_options then
|
||||
Util.ignore_events(function()
|
||||
require("nui.utils")._.set_buf_options(buf, self._opts.buf_options)
|
||||
end)
|
||||
end
|
||||
|
||||
if self._opts.lang and not vim.b[buf].ts_highlight then
|
||||
if not pcall(vim.treesitter.start, buf, self._opts.lang) then
|
||||
vim.bo[buf].syntax = self._opts.lang
|
||||
end
|
||||
end
|
||||
|
||||
vim.api.nvim_buf_clear_namespace(buf, Config.ns, linenr - 1, -1)
|
||||
vim.b[buf].messages = {}
|
||||
|
||||
---@type number?
|
||||
local win = vim.fn.bufwinid(buf)
|
||||
if win == -1 then
|
||||
win = nil
|
||||
end
|
||||
local cursor = win and vim.api.nvim_win_get_cursor(win)
|
||||
|
||||
if not opts.highlight then
|
||||
vim.api.nvim_buf_set_lines(buf, linenr - 1, -1, false, {})
|
||||
end
|
||||
|
||||
for _, m in ipairs(opts.messages or self._messages) do
|
||||
if opts.highlight then
|
||||
m:highlight(buf, Config.ns, linenr)
|
||||
else
|
||||
m:render(buf, Config.ns, linenr)
|
||||
end
|
||||
linenr = linenr + m:height()
|
||||
end
|
||||
|
||||
if cursor then
|
||||
-- restore cursor
|
||||
pcall(vim.api.nvim_win_set_cursor, win, cursor)
|
||||
end
|
||||
end
|
||||
|
||||
return View
|
||||
@ -0,0 +1,337 @@
|
||||
local require = require("noice.util.lazy")
|
||||
|
||||
local View = require("noice.view")
|
||||
local Util = require("noice.util")
|
||||
local Scrollbar = require("noice.view.scrollbar")
|
||||
local Config = require("noice.config")
|
||||
|
||||
---@class NuiView: NoiceView
|
||||
---@field _nui? NuiPopup|NuiSplit
|
||||
---@field _loading? boolean
|
||||
---@field super NoiceView
|
||||
---@field _hider fun()
|
||||
---@field _timeout_timer vim.loop.Timer
|
||||
---@field _scroll NoiceScrollbar
|
||||
---@diagnostic disable-next-line: undefined-field
|
||||
local NuiView = View:extend("NuiView")
|
||||
|
||||
function NuiView:init(opts)
|
||||
NuiView.super.init(self, opts)
|
||||
self._timer = vim.loop.new_timer()
|
||||
end
|
||||
|
||||
function NuiView:autohide()
|
||||
if self._opts.timeout then
|
||||
self._timer:start(self._opts.timeout, 0, function()
|
||||
if self._visible then
|
||||
vim.schedule(function()
|
||||
self:hide()
|
||||
end)
|
||||
end
|
||||
self._timer:stop()
|
||||
end)
|
||||
end
|
||||
end
|
||||
|
||||
function NuiView:update_options()
|
||||
self._opts = vim.tbl_deep_extend("force", {}, {
|
||||
buf_options = {
|
||||
buftype = "nofile",
|
||||
filetype = "noice",
|
||||
},
|
||||
win_options = {
|
||||
wrap = false,
|
||||
foldenable = false,
|
||||
scrolloff = 0,
|
||||
sidescrolloff = 0,
|
||||
},
|
||||
}, self._opts, self:get_layout())
|
||||
|
||||
self._opts = Util.nui.normalize(self._opts)
|
||||
if self._opts.anchor == "auto" then
|
||||
if self._opts.type == "popup" and self._opts.size then
|
||||
local width = self._opts.size.width
|
||||
local height = self._opts.size.height
|
||||
if type(width) == "number" and type(height) == "number" then
|
||||
local col = self._opts.position and self._opts.position.col
|
||||
local row = self._opts.position and self._opts.position.row
|
||||
self._opts.anchor = Util.nui.anchor(width, height)
|
||||
if self._opts.anchor:find("S") and row then
|
||||
self._opts.position.row = -row + 1
|
||||
end
|
||||
if self._opts.anchor:find("E") and col then
|
||||
self._opts.position.col = -col
|
||||
end
|
||||
end
|
||||
else
|
||||
self._opts.anchor = "NW"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Check if other floating windows are overlapping and move out of the way
|
||||
function NuiView:smart_move()
|
||||
if not Config.options.smart_move.enabled then
|
||||
return
|
||||
end
|
||||
if not (self._opts.type == "popup" and self._opts.relative and self._opts.relative.type == "editor") then
|
||||
return
|
||||
end
|
||||
if not (self._nui.winid and vim.api.nvim_win_is_valid(self._nui.winid)) then
|
||||
return
|
||||
end
|
||||
if not (self._nui.border.winid and vim.api.nvim_win_is_valid(self._nui.border.winid)) then
|
||||
return
|
||||
end
|
||||
|
||||
local nui_win = self._nui.border._.type == "complex" and self._nui.border.winid or self._nui.winid
|
||||
|
||||
local wins = vim.tbl_filter(function(win)
|
||||
local ft = vim.bo[vim.api.nvim_win_get_buf(win)].filetype
|
||||
return win ~= self._nui.winid
|
||||
and ft ~= "noice"
|
||||
and not vim.tbl_contains(Config.options.smart_move.excluded_filetypes, ft)
|
||||
and not (self._nui.border and self._nui.border.winid == win)
|
||||
and vim.api.nvim_win_is_valid(win)
|
||||
and vim.api.nvim_win_get_config(win).relative == "editor"
|
||||
and Util.nui.overlap(nui_win, win) > 0.3
|
||||
end, vim.api.nvim_list_wins())
|
||||
|
||||
if #wins > 0 then
|
||||
-- local info = vim.tbl_map(function(win)
|
||||
-- local buf = vim.api.nvim_win_get_buf(win)
|
||||
-- return {
|
||||
-- win = win,
|
||||
-- buftype = vim.bo[buf].buftype,
|
||||
-- ft = vim.bo[buf].filetype,
|
||||
-- syntax = vim.bo[buf].syntax,
|
||||
-- text = table.concat(vim.api.nvim_buf_get_lines(buf, 0, -1, false), "\n"),
|
||||
-- name = vim.api.nvim_buf_get_name(buf),
|
||||
-- -- config = vim.api.nvim_win_get_config(win),
|
||||
-- area = Util.nui.overlap(nui_win, win),
|
||||
-- }
|
||||
-- end, wins)
|
||||
-- dumpp(info)
|
||||
local layout = self:get_layout()
|
||||
layout.position.row = 2
|
||||
self._nui:update_layout(layout)
|
||||
end
|
||||
end
|
||||
|
||||
function NuiView:create()
|
||||
if self._loading then
|
||||
return
|
||||
end
|
||||
self._loading = true
|
||||
-- needed, since Nui mutates the options
|
||||
local opts = vim.deepcopy(self._opts)
|
||||
self._nui = self._opts.type == "split" and require("nui.split")(opts) or require("nui.popup")(opts)
|
||||
|
||||
self:mount()
|
||||
self:update_layout()
|
||||
if self._opts.scrollbar ~= false then
|
||||
self._scroll = Scrollbar({
|
||||
winnr = self._nui.winid,
|
||||
padding = Util.nui.normalize_padding(self._opts.border),
|
||||
})
|
||||
self._scroll:mount()
|
||||
end
|
||||
self._loading = false
|
||||
end
|
||||
|
||||
function NuiView:mount()
|
||||
self._nui:mount()
|
||||
if self._opts.close and self._opts.close.events then
|
||||
self._nui:on(self._opts.close.events, function()
|
||||
self:hide()
|
||||
end, { once = false })
|
||||
end
|
||||
|
||||
if self._opts.close and self._opts.close.keys then
|
||||
self._nui:map("n", self._opts.close.keys, function()
|
||||
self:hide()
|
||||
end, { remap = false, nowait = true })
|
||||
end
|
||||
end
|
||||
|
||||
---@param old NoiceNuiOptions
|
||||
---@param new NoiceNuiOptions
|
||||
function NuiView:reset(old, new)
|
||||
self._timer:stop()
|
||||
if self._nui then
|
||||
local layout = false
|
||||
local diff = vim.tbl_filter(function(key)
|
||||
if vim.tbl_contains({ "relative", "size", "position" }, key) then
|
||||
layout = true
|
||||
return false
|
||||
end
|
||||
if key == "timeout" then
|
||||
return false
|
||||
end
|
||||
return true
|
||||
end, Util.diff_keys(old, new))
|
||||
|
||||
if #diff > 0 then
|
||||
self._nui:unmount()
|
||||
self._nui = nil
|
||||
self._visible = false
|
||||
elseif layout then
|
||||
if not pcall(self.update_layout, self) then
|
||||
self._nui:unmount()
|
||||
self._nui = nil
|
||||
self._visible = false
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Destroys any create windows and buffers with vim.schedule
|
||||
-- This is needed to properly re-create views in case of E565 errors
|
||||
function NuiView:destroy()
|
||||
local nui = self._nui
|
||||
local scroll = self._scroll
|
||||
vim.schedule(function()
|
||||
if nui then
|
||||
nui._.loading = false
|
||||
nui._.mounted = true
|
||||
nui:unmount()
|
||||
end
|
||||
if scroll then
|
||||
scroll:hide()
|
||||
end
|
||||
end)
|
||||
self._nui = nil
|
||||
self._scroll = nil
|
||||
self._loading = false
|
||||
end
|
||||
|
||||
function NuiView:hide()
|
||||
self._timer:stop()
|
||||
if self._nui then
|
||||
self._visible = false
|
||||
|
||||
Util.protect(function()
|
||||
if self._nui and not self._visible then
|
||||
self:clear()
|
||||
self._nui:unmount()
|
||||
if self._scroll then
|
||||
self._scroll:hide()
|
||||
end
|
||||
end
|
||||
end, {
|
||||
finally = function()
|
||||
if self._nui then
|
||||
self._nui._.loading = false
|
||||
end
|
||||
end,
|
||||
retry_on_E11 = true,
|
||||
retry_on_E565 = true,
|
||||
})()
|
||||
end
|
||||
end
|
||||
|
||||
function NuiView:get_layout()
|
||||
local layout = Util.nui.get_layout({ width = self:width(), height = self:height() }, self._opts)
|
||||
if self._opts.type == "popup" then
|
||||
---@cast layout _.NuiPopupOptions
|
||||
if
|
||||
layout.size
|
||||
and type(layout.size.width) == "number"
|
||||
and layout.size.width < self:width()
|
||||
and self._opts.win_options
|
||||
and self._opts.win_options.wrap
|
||||
then
|
||||
local height = 0
|
||||
for _, m in ipairs(self._messages) do
|
||||
for _, l in ipairs(m._lines) do
|
||||
height = height + math.max(1, (math.ceil(l:width() / layout.size.width)))
|
||||
end
|
||||
end
|
||||
layout = Util.nui.get_layout({ width = self:width(), height = height }, self._opts)
|
||||
end
|
||||
end
|
||||
return layout
|
||||
end
|
||||
|
||||
function NuiView:tag()
|
||||
Util.tag(self._nui.bufnr, "nui." .. self._opts.type)
|
||||
if self._nui.border and self._nui.border.bufnr then
|
||||
Util.tag(self._nui.border.bufnr, "nui." .. self._opts.type .. ".border")
|
||||
end
|
||||
end
|
||||
|
||||
function NuiView:fix_border()
|
||||
if
|
||||
self._nui
|
||||
and self._nui.border
|
||||
and self._nui.border.winid
|
||||
and vim.api.nvim_win_is_valid(self._nui.border.winid)
|
||||
then
|
||||
local winhl = vim.api.nvim_win_get_option(self._nui.border.winid, "winhighlight") or ""
|
||||
if not winhl:find("IncSearch") then
|
||||
local hl = vim.split(winhl, ",")
|
||||
hl[#hl + 1] = "Search:"
|
||||
hl[#hl + 1] = "IncSearch:"
|
||||
winhl = table.concat(hl, ",")
|
||||
vim.api.nvim_win_set_option(self._nui.border.winid, "winhighlight", winhl)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function NuiView:update_layout()
|
||||
self._nui:update_layout(self:get_layout())
|
||||
end
|
||||
|
||||
function NuiView:is_mounted()
|
||||
if self._nui and self._nui.bufnr and not vim.api.nvim_buf_is_valid(self._nui.bufnr) then
|
||||
self._nui.bufnr = nil
|
||||
end
|
||||
|
||||
if self._nui and self._nui.winid and not vim.api.nvim_win_is_valid(self._nui.winid) then
|
||||
self._nui.winid = nil
|
||||
end
|
||||
|
||||
if self._nui and self._nui._.mounted and not self._nui.bufnr then
|
||||
self._nui._.mounted = false
|
||||
end
|
||||
|
||||
return self._nui and self._nui._.mounted and self._nui.bufnr
|
||||
end
|
||||
|
||||
function NuiView:show()
|
||||
if self._loading then
|
||||
return
|
||||
end
|
||||
|
||||
if not self._nui then
|
||||
self:create()
|
||||
end
|
||||
|
||||
if not self:is_mounted() then
|
||||
self:mount()
|
||||
end
|
||||
|
||||
vim.bo[self._nui.bufnr].modifiable = true
|
||||
self:render(self._nui.bufnr)
|
||||
vim.bo[self._nui.bufnr].modifiable = false
|
||||
|
||||
self._nui:show()
|
||||
if not self._nui.winid then
|
||||
return
|
||||
end
|
||||
self:tag()
|
||||
if not self._visible then
|
||||
self:set_win_options(self._nui.winid)
|
||||
self:update_layout()
|
||||
self:smart_move()
|
||||
end
|
||||
|
||||
if self._scroll then
|
||||
self._scroll.winnr = self._nui.winid
|
||||
self._scroll:show()
|
||||
end
|
||||
self:fix_border()
|
||||
self:autohide()
|
||||
end
|
||||
|
||||
return NuiView
|
||||
@ -0,0 +1,163 @@
|
||||
local require = require("noice.util.lazy")
|
||||
|
||||
local Object = require("nui.object")
|
||||
local Util = require("noice.util")
|
||||
|
||||
---@class NoiceScrollbar
|
||||
---@field winnr integer
|
||||
---@field ns_id integer
|
||||
---@field autocmd_id integer
|
||||
---@field bar {bufnr:integer, winnr:integer}?
|
||||
---@field thumb {bufnr:integer, winnr:integer}?
|
||||
---@field visible boolean
|
||||
---@field opts ScrollbarOptions
|
||||
---@overload fun(opts?:ScrollbarOptions):NoiceScrollbar
|
||||
local Scrollbar = Object("NuiScrollbar")
|
||||
|
||||
---@class ScrollbarOptions
|
||||
local defaults = {
|
||||
winnr = 0,
|
||||
autohide = true,
|
||||
hl_group = {
|
||||
bar = "NoiceScrollbar",
|
||||
thumb = "NoiceScrollbarThumb",
|
||||
},
|
||||
---@type _.NuiBorderPadding
|
||||
padding = {
|
||||
top = 0,
|
||||
right = 0,
|
||||
bottom = 0,
|
||||
left = 0,
|
||||
},
|
||||
}
|
||||
|
||||
---@param opts? ScrollbarOptions
|
||||
function Scrollbar:init(opts)
|
||||
self.opts = vim.tbl_deep_extend("force", defaults, opts or {})
|
||||
self.winnr = self.opts.winnr == 0 and vim.api.nvim_get_current_win() or self.opts.winnr
|
||||
self.visible = false
|
||||
end
|
||||
|
||||
function Scrollbar:mount()
|
||||
self.autocmd_id = vim.api.nvim_create_autocmd({ "WinScrolled", "CursorMoved" }, {
|
||||
callback = function()
|
||||
self:update()
|
||||
end,
|
||||
})
|
||||
self:update()
|
||||
end
|
||||
|
||||
function Scrollbar:unmount()
|
||||
if self.autocmd_id then
|
||||
vim.api.nvim_del_autocmd(self.autocmd_id)
|
||||
self.autocmd_id = nil
|
||||
end
|
||||
self:hide()
|
||||
end
|
||||
|
||||
function Scrollbar:show()
|
||||
if not self.visible then
|
||||
self.visible = true
|
||||
self.bar = self:_open_win({ normal = self.opts.hl_group.bar })
|
||||
self.thumb = self:_open_win({ normal = self.opts.hl_group.thumb })
|
||||
end
|
||||
self:update()
|
||||
end
|
||||
|
||||
function Scrollbar:hide()
|
||||
if self.visible then
|
||||
self.visible = false
|
||||
local bar = self.bar
|
||||
if bar then
|
||||
pcall(vim.api.nvim_buf_delete, bar.bufnr, { force = true })
|
||||
pcall(vim.api.nvim_win_close, bar.winnr, true)
|
||||
self.bar = nil
|
||||
end
|
||||
|
||||
local thumb = self.thumb
|
||||
if thumb then
|
||||
pcall(vim.api.nvim_buf_delete, thumb.bufnr, { force = true })
|
||||
pcall(vim.api.nvim_win_close, thumb.winnr, true)
|
||||
self.thumb = nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function Scrollbar:update()
|
||||
if not vim.api.nvim_win_is_valid(self.winnr) then
|
||||
return self:hide()
|
||||
end
|
||||
|
||||
local pos = vim.api.nvim_win_get_position(self.winnr)
|
||||
|
||||
local dim = {
|
||||
row = pos[1] - self.opts.padding.top,
|
||||
col = pos[2] - self.opts.padding.left,
|
||||
width = vim.api.nvim_win_get_width(self.winnr) + self.opts.padding.left + self.opts.padding.right,
|
||||
height = vim.api.nvim_win_get_height(self.winnr) + self.opts.padding.top + self.opts.padding.bottom,
|
||||
}
|
||||
|
||||
local buf_height = Util.nui.win_buf_height(self.winnr)
|
||||
|
||||
if self.opts.autohide and dim.height >= buf_height then
|
||||
self:hide()
|
||||
return
|
||||
elseif not self.visible then
|
||||
self:show()
|
||||
end
|
||||
|
||||
if not (vim.api.nvim_win_is_valid(self.bar.winnr) and vim.api.nvim_win_is_valid(self.thumb.winnr)) then
|
||||
self:hide()
|
||||
self:show()
|
||||
end
|
||||
|
||||
local zindex = vim.api.nvim_win_get_config(self.winnr).zindex or 50
|
||||
|
||||
Util.win_apply_config(self.bar.winnr, {
|
||||
height = dim.height,
|
||||
width = 1,
|
||||
col = dim.col + dim.width - 1,
|
||||
row = dim.row,
|
||||
zindex = zindex + 1,
|
||||
})
|
||||
|
||||
local thumb_height = math.floor(dim.height * dim.height / buf_height + 0.5)
|
||||
thumb_height = math.max(1, thumb_height)
|
||||
|
||||
local pct = vim.api.nvim_win_get_cursor(self.winnr)[1] / buf_height
|
||||
|
||||
local thumb_offset = math.floor(pct * (dim.height - thumb_height) + 0.5)
|
||||
|
||||
Util.win_apply_config(self.thumb.winnr, {
|
||||
width = 1,
|
||||
height = thumb_height,
|
||||
row = dim.row + thumb_offset,
|
||||
col = dim.col + dim.width - 1, -- info.col was already added scrollbar offset.
|
||||
zindex = zindex + 2,
|
||||
})
|
||||
end
|
||||
|
||||
function Scrollbar:_open_win(opts)
|
||||
local bufnr = vim.api.nvim_create_buf(false, true)
|
||||
Util.tag(bufnr, "scrollbar")
|
||||
local ret = {
|
||||
bufnr = bufnr,
|
||||
winnr = vim.api.nvim_open_win(bufnr, false, {
|
||||
relative = "editor",
|
||||
focusable = false,
|
||||
width = 1,
|
||||
-- HACK: height should be >=2 in case of winbar, which is inherited from the parent window
|
||||
-- Change back to 1 when the upstream issue is fixed.
|
||||
-- See https://github.com/neovim/neovim/issues/19464
|
||||
height = 2,
|
||||
row = 0,
|
||||
col = 0,
|
||||
style = "minimal",
|
||||
noautocmd = true,
|
||||
}),
|
||||
}
|
||||
vim.api.nvim_win_set_option(ret.winnr, "winhighlight", "Normal:" .. opts.normal)
|
||||
return ret
|
||||
end
|
||||
|
||||
return Scrollbar
|
||||
@ -0,0 +1,78 @@
|
||||
local require = require("noice.util.lazy")
|
||||
|
||||
local Config = require("noice.config")
|
||||
local Manager = require("noice.message.manager")
|
||||
local Format = require("noice.text.format")
|
||||
local pickers = require("telescope.pickers")
|
||||
local finders = require("telescope.finders")
|
||||
local conf = require("telescope.config").values
|
||||
local previewers = require("telescope.previewers")
|
||||
|
||||
local M = {}
|
||||
|
||||
---@param message NoiceMessage
|
||||
function M.display(message)
|
||||
message = Format.format(message, "telescope")
|
||||
local line = message._lines[1]
|
||||
local hl = {}
|
||||
local byte = 0
|
||||
for _, text in ipairs(line._texts) do
|
||||
local hl_group = text.extmark and text.extmark.hl_group
|
||||
if hl_group then
|
||||
table.insert(hl, { { byte, byte + text:length() }, hl_group })
|
||||
end
|
||||
byte = byte + text:length()
|
||||
end
|
||||
return line:content(), hl
|
||||
end
|
||||
|
||||
function M.finder()
|
||||
local messages = Manager.get(Config.options.commands.history.filter, {
|
||||
history = true,
|
||||
sort = true,
|
||||
reverse = true,
|
||||
})
|
||||
return finders.new_table({
|
||||
results = messages,
|
||||
entry_maker = function(message)
|
||||
return {
|
||||
message = message,
|
||||
display = function(entry)
|
||||
return M.display(entry.message)
|
||||
end,
|
||||
ordinal = Format.format(message, "telescope"):content(),
|
||||
}
|
||||
end,
|
||||
})
|
||||
end
|
||||
|
||||
function M.previewer()
|
||||
return previewers.new_buffer_previewer({
|
||||
title = "Message",
|
||||
define_preview = function(self, entry, _status)
|
||||
vim.api.nvim_win_set_option(self.state.winid, "wrap", true)
|
||||
|
||||
---@type NoiceMessage
|
||||
local message = Format.format(entry.message, "telescope_preview")
|
||||
message:render(self.state.bufnr, Config.ns)
|
||||
end,
|
||||
})
|
||||
end
|
||||
|
||||
function M.telescope(opts)
|
||||
pickers
|
||||
.new(opts, {
|
||||
results_title = "Noice",
|
||||
prompt_title = "Filter Noice",
|
||||
finder = M.finder(),
|
||||
sorter = conf.generic_sorter(opts),
|
||||
previewer = M.previewer(),
|
||||
})
|
||||
:find()
|
||||
end
|
||||
|
||||
return require("telescope").register_extension({
|
||||
exports = {
|
||||
noice = M.telescope,
|
||||
},
|
||||
})
|
||||
1
config/neovim/store/lazy-plugins/noice.nvim/selene.toml
Normal file
1
config/neovim/store/lazy-plugins/noice.nvim/selene.toml
Normal file
@ -0,0 +1 @@
|
||||
std="vim"
|
||||
3
config/neovim/store/lazy-plugins/noice.nvim/stylua.toml
Normal file
3
config/neovim/store/lazy-plugins/noice.nvim/stylua.toml
Normal file
@ -0,0 +1,3 @@
|
||||
indent_type = "Spaces"
|
||||
indent_width = 2
|
||||
column_width = 120
|
||||
35
config/neovim/store/lazy-plugins/noice.nvim/tests/init.lua
Normal file
35
config/neovim/store/lazy-plugins/noice.nvim/tests/init.lua
Normal file
@ -0,0 +1,35 @@
|
||||
local M = {}
|
||||
|
||||
function M.root(root)
|
||||
local f = debug.getinfo(1, "S").source:sub(2)
|
||||
return vim.fn.fnamemodify(f, ":p:h:h") .. "/" .. (root or "")
|
||||
end
|
||||
|
||||
---@param plugin string
|
||||
function M.load(plugin)
|
||||
local name = plugin:match(".*/(.*)")
|
||||
local package_root = M.root(".tests/site/pack/deps/start/")
|
||||
if not vim.loop.fs_stat(package_root .. name) then
|
||||
print("Installing " .. plugin)
|
||||
vim.fn.mkdir(package_root, "p")
|
||||
vim.fn.system({
|
||||
"git",
|
||||
"clone",
|
||||
"--depth=1",
|
||||
"https://github.com/" .. plugin .. ".git",
|
||||
package_root .. "/" .. name,
|
||||
})
|
||||
end
|
||||
end
|
||||
|
||||
function M.setup()
|
||||
vim.cmd([[set runtimepath=$VIMRUNTIME]])
|
||||
vim.opt.runtimepath:append(M.root())
|
||||
vim.opt.packpath = { M.root(".tests/site") }
|
||||
|
||||
M.load("MunifTanjim/nui.nvim")
|
||||
M.load("nvim-lua/plenary.nvim")
|
||||
M.load("rcarriga/nvim-notify")
|
||||
end
|
||||
|
||||
M.setup()
|
||||
3
config/neovim/store/lazy-plugins/noice.nvim/tests/run
Executable file
3
config/neovim/store/lazy-plugins/noice.nvim/tests/run
Executable file
@ -0,0 +1,3 @@
|
||||
#!/nix/store/306znyj77fv49kwnkpxmb0j2znqpa8bj-bash-5.2p26/bin/sh
|
||||
|
||||
nvim --headless -u tests/init.lua -c "PlenaryBustedDirectory tests/ {minimal_init = 'tests/init.lua', sequential = true}"
|
||||
@ -0,0 +1,213 @@
|
||||
local Markdown = require("noice.text.markdown")
|
||||
|
||||
local M = {}
|
||||
|
||||
local ns = vim.api.nvim_create_namespace("noice_test")
|
||||
|
||||
function M.test()
|
||||
describe("markdown", function()
|
||||
it("parse", function()
|
||||
for _, test in ipairs(M.tests) do
|
||||
assert.same(test.output, Markdown.parse(test.input))
|
||||
end
|
||||
end)
|
||||
|
||||
it("conceal escape characters", function()
|
||||
local chars = "\\`*_{}[]()#+-.!"
|
||||
local buf = vim.api.nvim_create_buf(false, true)
|
||||
|
||||
---@type string[]
|
||||
local lines = {}
|
||||
for i = 1, #chars do
|
||||
local char = chars:sub(i, i)
|
||||
table.insert(lines, "\\" .. char)
|
||||
end
|
||||
vim.api.nvim_buf_set_lines(buf, 0, -1, false, lines)
|
||||
|
||||
Markdown.conceal_escape_characters(buf, ns, { 0, 0, #lines - 1, 1 })
|
||||
local extmarks = vim.api.nvim_buf_get_extmarks(buf, ns, 0, -1, {})
|
||||
assert.equal(chars:len(), #extmarks)
|
||||
end)
|
||||
end)
|
||||
end
|
||||
|
||||
M.tests = {
|
||||
{
|
||||
input = [[
|
||||
|
||||
|
||||
|
||||
foo
|
||||
|
||||
]],
|
||||
output = {
|
||||
{ line = " foo" },
|
||||
},
|
||||
},
|
||||
{
|
||||
input = [[
|
||||
bar
|
||||
|
||||
|
||||
---
|
||||
|
||||
foo
|
||||
|
||||
]],
|
||||
output = {
|
||||
{ line = " bar" },
|
||||
{ line = "---" },
|
||||
{ line = " foo" },
|
||||
},
|
||||
},
|
||||
{
|
||||
input = [[
|
||||
```lua
|
||||
local a
|
||||
```
|
||||
|
||||
foo
|
||||
|
||||
```lua
|
||||
local b
|
||||
```
|
||||
]],
|
||||
output = {
|
||||
{ code = { "local a" }, lang = "lua" },
|
||||
{ line = "" },
|
||||
{ line = "foo" },
|
||||
{ line = "" },
|
||||
{ code = { "local b" }, lang = "lua" },
|
||||
},
|
||||
},
|
||||
{
|
||||
input = [[
|
||||
|
||||
```lua
|
||||
local a
|
||||
```
|
||||
```lua
|
||||
local b
|
||||
```
|
||||
]],
|
||||
output = {
|
||||
{ code = { "local a" }, lang = "lua" },
|
||||
{ line = "" },
|
||||
{ code = { "local b" }, lang = "lua" },
|
||||
},
|
||||
},
|
||||
{
|
||||
input = [[
|
||||
|
||||
<foo
|
||||
]],
|
||||
output = {
|
||||
{ line = "<foo" },
|
||||
},
|
||||
},
|
||||
{
|
||||
input = [[
|
||||
|
||||
```lua
|
||||
local a
|
||||
```
|
||||
|
||||
]],
|
||||
output = {
|
||||
{ code = { "local a" }, lang = "lua" },
|
||||
},
|
||||
},
|
||||
{
|
||||
input = [[
|
||||
|
||||
```lua
|
||||
local a
|
||||
local b
|
||||
]],
|
||||
output = {
|
||||
{ code = { "local a", "local b", "" }, lang = "lua" },
|
||||
},
|
||||
},
|
||||
{
|
||||
input = [[
|
||||
|
||||
***
|
||||
|
||||
```lua
|
||||
local a
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
]],
|
||||
output = {
|
||||
{ line = "---" },
|
||||
{ code = { "local a" }, lang = "lua" },
|
||||
{ line = "---" },
|
||||
},
|
||||
},
|
||||
{
|
||||
input = [[
|
||||
|
||||
***
|
||||
|
||||
``` lua
|
||||
local a
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
]],
|
||||
output = {
|
||||
{ line = "---" },
|
||||
{ code = { "local a" }, lang = "lua" },
|
||||
{ line = "---" },
|
||||
},
|
||||
},
|
||||
{
|
||||
input = [[
|
||||
|
||||
```lua
|
||||
local a
|
||||
```
|
||||
|
||||
foo
|
||||
|
||||
bar
|
||||
|
||||
```
|
||||
local b
|
||||
```
|
||||
|
||||
]],
|
||||
output = {
|
||||
{ code = { "local a" }, lang = "lua" },
|
||||
{ line = "" },
|
||||
{ line = "foo" },
|
||||
{ line = "" },
|
||||
{ line = "bar" },
|
||||
{ line = "" },
|
||||
{ code = { "local b" }, lang = "text" },
|
||||
},
|
||||
},
|
||||
{
|
||||
input = [[
|
||||
|
||||
1 < 2
|
||||
3 > 2
|
||||
"quoted"
|
||||
'apos'
|
||||
  indented
|
||||
&
|
||||
]],
|
||||
output = {
|
||||
{ line = "1 < 2" },
|
||||
{ line = "3 > 2" },
|
||||
{ line = '"quoted"' },
|
||||
{ line = "'apos'" },
|
||||
{ line = " indented" },
|
||||
{ line = "&" },
|
||||
},
|
||||
},
|
||||
}
|
||||
M.test()
|
||||
@ -0,0 +1,7 @@
|
||||
local lazy = require("noice.util.lazy")
|
||||
|
||||
describe("ffi", function()
|
||||
it("cmdpreview is false", function()
|
||||
assert(lazy("noice.util.ffi").cmdpreview == false)
|
||||
end)
|
||||
end)
|
||||
@ -0,0 +1,12 @@
|
||||
local View = require("noice.view")
|
||||
local Config = require("noice.config")
|
||||
Config.setup()
|
||||
|
||||
describe("checking views", function()
|
||||
it("view is loaded only once", function()
|
||||
local opts = { enter = true, format = "details" }
|
||||
local view1 = View.get_view("split", opts)
|
||||
local view2 = View.get_view("split", opts)
|
||||
assert.equal(view1, view2)
|
||||
end)
|
||||
end)
|
||||
46
config/neovim/store/lazy-plugins/noice.nvim/vim.toml
Normal file
46
config/neovim/store/lazy-plugins/noice.nvim/vim.toml
Normal file
@ -0,0 +1,46 @@
|
||||
[selene]
|
||||
base = "lua51"
|
||||
name = "vim"
|
||||
|
||||
[vim]
|
||||
any = true
|
||||
|
||||
[[describe.args]]
|
||||
type = "string"
|
||||
[[describe.args]]
|
||||
type = "function"
|
||||
|
||||
[[it.args]]
|
||||
type = "string"
|
||||
[[it.args]]
|
||||
type = "function"
|
||||
|
||||
[[before_each.args]]
|
||||
type = "function"
|
||||
[[after_each.args]]
|
||||
type = "function"
|
||||
|
||||
[assert.is_not]
|
||||
any = true
|
||||
|
||||
[[assert.equals.args]]
|
||||
type = "any"
|
||||
[[assert.equals.args]]
|
||||
type = "any"
|
||||
[[assert.equals.args]]
|
||||
type = "any"
|
||||
required = false
|
||||
|
||||
[[assert.same.args]]
|
||||
type = "any"
|
||||
[[assert.same.args]]
|
||||
type = "any"
|
||||
|
||||
[[assert.truthy.args]]
|
||||
type = "any"
|
||||
|
||||
[[assert.spy.args]]
|
||||
type = "any"
|
||||
|
||||
[[assert.stub.args]]
|
||||
type = "any"
|
||||
Reference in New Issue
Block a user