Compare commits
6 Commits
master
...
chore-poc-
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
91e6b978e0 | ||
|
|
006b27dc0a | ||
|
|
63cd226c3e | ||
|
|
f9dc294829 | ||
|
|
2dcf249d49 | ||
|
|
9ac1e05fc8 |
@ -7,9 +7,6 @@ end_of_line = lf
|
|||||||
[nvim-tree-lua.txt]
|
[nvim-tree-lua.txt]
|
||||||
max_line_length = 78
|
max_line_length = 78
|
||||||
|
|
||||||
# keep these in sync with .luarc.json
|
|
||||||
# .editorconfig is used within nvim, overriding .luarc.json
|
|
||||||
# .luarc.json is used by style check
|
|
||||||
[*.lua]
|
[*.lua]
|
||||||
indent_style = space
|
indent_style = space
|
||||||
max_line_length = 140
|
max_line_length = 140
|
||||||
|
|||||||
63
.github/workflows/ci.yml
vendored
63
.github/workflows/ci.yml
vendored
@ -20,25 +20,45 @@ jobs:
|
|||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
lua_version: [ 5.1 ]
|
lua_version: [ 5.1 ]
|
||||||
luacheck_version: [ 1.2.0 ]
|
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: checkout
|
- uses: actions/checkout@v4
|
||||||
uses: actions/checkout@v5
|
|
||||||
|
|
||||||
- name: install lua ${{ matrix.lua_version }}
|
- uses: leafo/gh-actions-lua@v10
|
||||||
uses: leafo/gh-actions-lua@v12
|
|
||||||
with:
|
with:
|
||||||
luaVersion: ${{ matrix.lua_version }}
|
luaVersion: ${{ matrix.lua_version }}
|
||||||
|
|
||||||
- name: install luarocks
|
- uses: leafo/gh-actions-luarocks@v4
|
||||||
uses: leafo/gh-actions-luarocks@v6
|
|
||||||
|
|
||||||
- name: install luacheck ${{ matrix.luacheck_version }}
|
- run: luarocks install luacheck 1.1.1
|
||||||
run: luarocks install luacheck ${{ matrix.luacheck_version }}
|
|
||||||
|
|
||||||
- run: make lint
|
- run: make lint
|
||||||
|
|
||||||
|
style:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
concurrency:
|
||||||
|
group: ${{ github.workflow }}-${{ matrix.emmy_lua_code_style_version }}-${{ github.head_ref || github.ref_name }}
|
||||||
|
cancel-in-progress: true
|
||||||
|
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
emmy_lua_code_style_version: [ 1.5.6 ]
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: install emmy_lua_code_style
|
||||||
|
run: |
|
||||||
|
mkdir -p CodeFormat
|
||||||
|
curl -L "https://github.com/CppCXY/EmmyLuaCodeStyle/releases/download/${{ matrix.emmy_lua_code_style_version }}/linux-x64.tar.gz" | tar zx --directory CodeFormat
|
||||||
|
|
||||||
|
- run: echo "CodeFormat/linux-x64/bin" >> "$GITHUB_PATH"
|
||||||
|
|
||||||
|
- run: make style
|
||||||
|
|
||||||
|
- run: make style-doc
|
||||||
|
|
||||||
check:
|
check:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
@ -49,31 +69,26 @@ jobs:
|
|||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
nvim_version: [ stable, nightly ]
|
nvim_version: [ stable, nightly ]
|
||||||
luals_version: [ 3.15.0 ]
|
luals_version: [ 3.11.0 ]
|
||||||
|
|
||||||
env:
|
|
||||||
VIMRUNTIME: /home/runner/nvim-${{ matrix.nvim_version }}/share/nvim/runtime
|
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: checkout
|
- uses: actions/checkout@v4
|
||||||
uses: actions/checkout@v5
|
|
||||||
|
|
||||||
- name: install nvim ${{ matrix.nvim_version }}
|
- uses: rhysd/action-setup-vim@v1
|
||||||
uses: rhysd/action-setup-vim@v1
|
|
||||||
with:
|
with:
|
||||||
neovim: true
|
neovim: true
|
||||||
version: ${{ matrix.nvim_version }}
|
version: ${{ matrix.nvim_version }}
|
||||||
|
|
||||||
- name: install lua-language-server ${{ matrix.luals_version }}
|
- name: install luals
|
||||||
run: |
|
run: |
|
||||||
mkdir -p luals
|
mkdir -p luals
|
||||||
curl -L "https://github.com/LuaLS/lua-language-server/releases/download/${{ matrix.luals_version }}/lua-language-server-${{ matrix.luals_version }}-linux-x64.tar.gz" | tar zx --directory luals
|
curl -L "https://github.com/LuaLS/lua-language-server/releases/download/${{ matrix.luals_version }}/lua-language-server-${{ matrix.luals_version }}-linux-x64.tar.gz" | tar zx --directory luals
|
||||||
echo "luals/bin" >> "$GITHUB_PATH"
|
|
||||||
|
|
||||||
- run: make check
|
- run: echo "luals/bin" >> "$GITHUB_PATH"
|
||||||
|
|
||||||
|
- name: make check
|
||||||
|
env:
|
||||||
|
VIMRUNTIME: /home/runner/nvim-${{ matrix.nvim_version }}/share/nvim/runtime
|
||||||
|
run: make check
|
||||||
|
|
||||||
- run: make help-check
|
- run: make help-check
|
||||||
|
|
||||||
- run: make style
|
|
||||||
|
|
||||||
- run: make style-doc
|
|
||||||
|
|||||||
6
.github/workflows/luarocks-release.yml
vendored
6
.github/workflows/luarocks-release.yml
vendored
@ -1,16 +1,14 @@
|
|||||||
name: Luarocks Release
|
name: Luarocks Release
|
||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
tags:
|
tags:
|
||||||
- v*
|
- 'v[0-9]+.[0-9]+.[0-9]+'
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
luarocks-upload:
|
luarocks-upload:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v5
|
- uses: actions/checkout@v4
|
||||||
- name: LuaRocks Upload
|
- name: LuaRocks Upload
|
||||||
uses: nvim-neorocks/luarocks-tag-release@v7
|
uses: nvim-neorocks/luarocks-tag-release@v7
|
||||||
env:
|
env:
|
||||||
|
|||||||
2
.github/workflows/release-please.yml
vendored
2
.github/workflows/release-please.yml
vendored
@ -16,7 +16,7 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
- uses: google-github-actions/release-please-action@v4
|
- uses: google-github-actions/release-please-action@v4
|
||||||
id: release
|
id: release
|
||||||
- uses: actions/checkout@v5
|
- uses: actions/checkout@v4
|
||||||
- name: tag major and minor versions
|
- name: tag major and minor versions
|
||||||
if: ${{ steps.release.outputs.release_created }}
|
if: ${{ steps.release.outputs.release_created }}
|
||||||
run: |
|
run: |
|
||||||
|
|||||||
2
.github/workflows/semantic-pr-subject.yml
vendored
2
.github/workflows/semantic-pr-subject.yml
vendored
@ -14,6 +14,6 @@ jobs:
|
|||||||
semantic-pr-subject:
|
semantic-pr-subject:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: amannn/action-semantic-pull-request@v6.1.1
|
- uses: amannn/action-semantic-pull-request@v5.5.3
|
||||||
env:
|
env:
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|||||||
1
.gitignore
vendored
1
.gitignore
vendored
@ -1,4 +1,5 @@
|
|||||||
/luals-out/
|
/luals-out/
|
||||||
/luals/
|
/luals/
|
||||||
|
/plenary.nvim/
|
||||||
# backup vim files
|
# backup vim files
|
||||||
*~
|
*~
|
||||||
|
|||||||
@ -1,3 +1,3 @@
|
|||||||
#!/usr/bin/env sh
|
#!/bin/sh
|
||||||
|
|
||||||
make
|
make
|
||||||
|
|||||||
16
.luarc.json
16
.luarc.json
@ -1,23 +1,13 @@
|
|||||||
{
|
{
|
||||||
"$schema": "https://raw.githubusercontent.com/sumneko/vscode-lua/master/setting/schema.json",
|
"$schema": "https://raw.githubusercontent.com/sumneko/vscode-lua/master/setting/schema.json",
|
||||||
|
"runtime.version.luals-check-only": "Lua 5.1",
|
||||||
"workspace": {
|
"workspace": {
|
||||||
"library": [
|
"library": [
|
||||||
"$VIMRUNTIME/lua/vim",
|
"$VIMRUNTIME/lua/vim",
|
||||||
"${3rd}/luv/library"
|
"${3rd}/luv/library",
|
||||||
|
"plenary.nvim"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"format": {
|
|
||||||
"defaultConfig": {
|
|
||||||
"indent_style": "space",
|
|
||||||
"max_line_length": "140",
|
|
||||||
"indent_size": "2",
|
|
||||||
"continuation_indent": "2",
|
|
||||||
"quote_style": "double",
|
|
||||||
"call_arg_parentheses": "always",
|
|
||||||
"space_before_closure_open_parenthesis": "false",
|
|
||||||
"align_continuous_similar_call_args": "true"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"diagnostics": {
|
"diagnostics": {
|
||||||
"libraryFiles": "Disable",
|
"libraryFiles": "Disable",
|
||||||
"globals": [],
|
"globals": [],
|
||||||
|
|||||||
@ -1,3 +1,3 @@
|
|||||||
{
|
{
|
||||||
".": "1.14.0"
|
".": "1.10.0"
|
||||||
}
|
}
|
||||||
|
|||||||
86
CHANGELOG.md
86
CHANGELOG.md
@ -1,91 +1,5 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
## [1.14.0](https://github.com/nvim-tree/nvim-tree.lua/compare/nvim-tree-v1.13.0...nvim-tree-v1.14.0) (2025-08-12)
|
|
||||||
|
|
||||||
|
|
||||||
### Features
|
|
||||||
|
|
||||||
* **#2685:** highlight git new tracked with NvimTreeGitFileNewHL ([#3176](https://github.com/nvim-tree/nvim-tree.lua/issues/3176)) ([0a52012](https://github.com/nvim-tree/nvim-tree.lua/commit/0a52012d611f3c1492b8d2aba363fabf734de91d))
|
|
||||||
* **#2789:** add optional function expand_until to api.tree.expand_all and api.node.expand ([#3166](https://github.com/nvim-tree/nvim-tree.lua/issues/3166)) ([1b876db](https://github.com/nvim-tree/nvim-tree.lua/commit/1b876db04903b93c78c97fd3f3dd85d59eeef5ff))
|
|
||||||
* **#2826:** allow only one window with nvim-tree buffer per tab ([#3174](https://github.com/nvim-tree/nvim-tree.lua/issues/3174)) ([dd2364d](https://github.com/nvim-tree/nvim-tree.lua/commit/dd2364d6802f7f57a98acb8b545ed484c6697626))
|
|
||||||
* **#3157:** add view.cursorlineopt ([#3158](https://github.com/nvim-tree/nvim-tree.lua/issues/3158)) ([8eb5e0b](https://github.com/nvim-tree/nvim-tree.lua/commit/8eb5e0bfd1c4da6efc03ab0c1ccf463dbaae831e))
|
|
||||||
|
|
||||||
|
|
||||||
### Bug Fixes
|
|
||||||
|
|
||||||
* **#3077:** deleting a directory containing symlinked directory will delete the contents of the linked directory ([#3168](https://github.com/nvim-tree/nvim-tree.lua/issues/3168)) ([10db694](https://github.com/nvim-tree/nvim-tree.lua/commit/10db6943cb40625941a35235eeb385ffdfbf827a))
|
|
||||||
* **#3157:** add view.cursorlineopt ([8eb5e0b](https://github.com/nvim-tree/nvim-tree.lua/commit/8eb5e0bfd1c4da6efc03ab0c1ccf463dbaae831e))
|
|
||||||
* **#3172:** live filter exception ([#3173](https://github.com/nvim-tree/nvim-tree.lua/issues/3173)) ([0a7fcdf](https://github.com/nvim-tree/nvim-tree.lua/commit/0a7fcdf3f8ba208f4260988a198c77ec11748339))
|
|
||||||
* invalid window id for popup info window ([#3147](https://github.com/nvim-tree/nvim-tree.lua/issues/3147)) ([d54a187](https://github.com/nvim-tree/nvim-tree.lua/commit/d54a1875a91e1a705795ea26074795210b92ce7f))
|
|
||||||
* **picker:** exclude full_name window id from the choice ([#3165](https://github.com/nvim-tree/nvim-tree.lua/issues/3165)) ([543ed3c](https://github.com/nvim-tree/nvim-tree.lua/commit/543ed3cac212dc3993ef9f042f6c0812e34ddd43))
|
|
||||||
* window picker ignore hidden window ([#3145](https://github.com/nvim-tree/nvim-tree.lua/issues/3145)) ([d87b41c](https://github.com/nvim-tree/nvim-tree.lua/commit/d87b41ca537e2131622d48a6c25ccf2fbe0e5d62))
|
|
||||||
|
|
||||||
|
|
||||||
### Performance Improvements
|
|
||||||
|
|
||||||
* **#3171:** cache toplevel for untracked ([#3185](https://github.com/nvim-tree/nvim-tree.lua/issues/3185)) ([4425136](https://github.com/nvim-tree/nvim-tree.lua/commit/442513648c6936e754c3308a1c58591a399493e5))
|
|
||||||
* **#3171:** use vim.system() instead of vim.fn.system() to execute git toplevel ([#3175](https://github.com/nvim-tree/nvim-tree.lua/issues/3175)) ([9a05b9e](https://github.com/nvim-tree/nvim-tree.lua/commit/9a05b9e9f928856ca23dbf876fab372003180c3f))
|
|
||||||
|
|
||||||
|
|
||||||
### Reverts
|
|
||||||
|
|
||||||
* **#3180, #3177:** invalid group or tabpage ([#3181](https://github.com/nvim-tree/nvim-tree.lua/issues/3181)) ([9b289ab](https://github.com/nvim-tree/nvim-tree.lua/commit/9b289abd6998e30fd24cbc9919e0b0cbed6364ce))
|
|
||||||
* **#3180, #3177:** resolve live filter failures ([#3183](https://github.com/nvim-tree/nvim-tree.lua/issues/3183)) ([a4699c0](https://github.com/nvim-tree/nvim-tree.lua/commit/a4699c0904103e7767334f6da05f5c2ea5514845))
|
|
||||||
|
|
||||||
## [1.13.0](https://github.com/nvim-tree/nvim-tree.lua/compare/nvim-tree-v1.12.0...nvim-tree-v1.13.0) (2025-06-14)
|
|
||||||
|
|
||||||
|
|
||||||
### Features
|
|
||||||
|
|
||||||
* **#3113:** add renderer.icons.folder_arrow_padding ([#3114](https://github.com/nvim-tree/nvim-tree.lua/issues/3114)) ([ea5097a](https://github.com/nvim-tree/nvim-tree.lua/commit/ea5097a1e2702b4827cb7380e7fa0bd6da87699c))
|
|
||||||
* **#3132:** add api.node.expand and api.node.collapse ([#3133](https://github.com/nvim-tree/nvim-tree.lua/issues/3133)) ([ae59561](https://github.com/nvim-tree/nvim-tree.lua/commit/ae595611fb2225f2041996c042aa4e4b8663b41e))
|
|
||||||
|
|
||||||
|
|
||||||
### Bug Fixes
|
|
||||||
|
|
||||||
* "Invalid buffer id" on closing nvim-tree window ([#3129](https://github.com/nvim-tree/nvim-tree.lua/issues/3129)) ([25d16aa](https://github.com/nvim-tree/nvim-tree.lua/commit/25d16aab7d29ca940a9feb92e6bb734697417009))
|
|
||||||
* **#2746:** background and right aligned icons in floating windows ([#3128](https://github.com/nvim-tree/nvim-tree.lua/issues/3128)) ([cbc3165](https://github.com/nvim-tree/nvim-tree.lua/commit/cbc3165e08893bb499da035c6f6f9d1512b57664))
|
|
||||||
* **#3117:** allow changing filename's casing ([bd54d1d](https://github.com/nvim-tree/nvim-tree.lua/commit/bd54d1d33c20d8630703b9842480291588dbad07))
|
|
||||||
* **#3117:** windows: change file/dir case ([#3135](https://github.com/nvim-tree/nvim-tree.lua/issues/3135)) ([bd54d1d](https://github.com/nvim-tree/nvim-tree.lua/commit/bd54d1d33c20d8630703b9842480291588dbad07))
|
|
||||||
* **#3122:** remove redundant vim.validate ([#3123](https://github.com/nvim-tree/nvim-tree.lua/issues/3123)) ([e7d1b7d](https://github.com/nvim-tree/nvim-tree.lua/commit/e7d1b7dadc62fe2eccc17d814354b0a5688621ce))
|
|
||||||
* **#3124:** fix icon padding for "right_align" placements, notably for dotfiles ([#3125](https://github.com/nvim-tree/nvim-tree.lua/issues/3125)) ([e4cd856](https://github.com/nvim-tree/nvim-tree.lua/commit/e4cd856ebf4fec51db10c69d63e43224b701cbce))
|
|
||||||
* **#3124:** prevent empty icons_right_align response from breaking padding ([e4cd856](https://github.com/nvim-tree/nvim-tree.lua/commit/e4cd856ebf4fec51db10c69d63e43224b701cbce))
|
|
||||||
* **#3134:** setting one glyph to "" no longer disables others ([#3136](https://github.com/nvim-tree/nvim-tree.lua/issues/3136)) ([ebcaccd](https://github.com/nvim-tree/nvim-tree.lua/commit/ebcaccda1c575fa19a8087445276e6671e2b9b37))
|
|
||||||
* **#3143:** actions.open_file.window_picker.exclude applies when not using window picker ([#3144](https://github.com/nvim-tree/nvim-tree.lua/issues/3144)) ([05d8172](https://github.com/nvim-tree/nvim-tree.lua/commit/05d8172ebf9cdb2d140cf25b75625374fbc3df7f))
|
|
||||||
* fixes [#3134](https://github.com/nvim-tree/nvim-tree.lua/issues/3134) ([ebcaccd](https://github.com/nvim-tree/nvim-tree.lua/commit/ebcaccda1c575fa19a8087445276e6671e2b9b37))
|
|
||||||
* invalid buffer issue ([25d16aa](https://github.com/nvim-tree/nvim-tree.lua/commit/25d16aab7d29ca940a9feb92e6bb734697417009))
|
|
||||||
|
|
||||||
## [1.12.0](https://github.com/nvim-tree/nvim-tree.lua/compare/nvim-tree-v1.11.0...nvim-tree-v1.12.0) (2025-04-20)
|
|
||||||
|
|
||||||
|
|
||||||
### Features
|
|
||||||
|
|
||||||
* add TreePreOpen event ([#3105](https://github.com/nvim-tree/nvim-tree.lua/issues/3105)) ([c24c047](https://github.com/nvim-tree/nvim-tree.lua/commit/c24c0470d9de277fbebecd718f33561ed7c90298))
|
|
||||||
|
|
||||||
|
|
||||||
### Bug Fixes
|
|
||||||
|
|
||||||
* **#3101:** when renderer.highlight_opened_files = "none" do not reload on BufUnload and BufReadPost ([#3102](https://github.com/nvim-tree/nvim-tree.lua/issues/3102)) ([5bea2b3](https://github.com/nvim-tree/nvim-tree.lua/commit/5bea2b37523a31288e0fcab42f3be5c1bd4516bb))
|
|
||||||
* explicitly set `border` to `"none"` in full name float ([#3094](https://github.com/nvim-tree/nvim-tree.lua/issues/3094)) ([c3c1935](https://github.com/nvim-tree/nvim-tree.lua/commit/c3c193594213c5e2f89ec5d7729cad805f76b256))
|
|
||||||
* reliably dispatch exactly one TreeOpen and TreeClose events ([#3107](https://github.com/nvim-tree/nvim-tree.lua/issues/3107)) ([3a63717](https://github.com/nvim-tree/nvim-tree.lua/commit/3a63717d3d332d8f39aaf65be7a0e4c2265af021))
|
|
||||||
|
|
||||||
## [1.11.0](https://github.com/nvim-tree/nvim-tree.lua/compare/nvim-tree-v1.10.0...nvim-tree-v1.11.0) (2025-02-22)
|
|
||||||
|
|
||||||
|
|
||||||
### Features
|
|
||||||
|
|
||||||
* **#1984:** add quit_on_open and focus opts to various api.node.open functions ([#3054](https://github.com/nvim-tree/nvim-tree.lua/issues/3054)) ([3281f33](https://github.com/nvim-tree/nvim-tree.lua/commit/3281f331f7f0bef13eb00fb2d5a9d28b2f6155a2))
|
|
||||||
* **#3037:** add API node.buffer.delete, node.buffer.wipe ([#3040](https://github.com/nvim-tree/nvim-tree.lua/issues/3040)) ([fee1da8](https://github.com/nvim-tree/nvim-tree.lua/commit/fee1da88972f5972a8296813f6c00d7598325ebd))
|
|
||||||
|
|
||||||
|
|
||||||
### Bug Fixes
|
|
||||||
|
|
||||||
* **#3045:** wipe scratch buffers for full name and show info popups ([#3050](https://github.com/nvim-tree/nvim-tree.lua/issues/3050)) ([fca0b67](https://github.com/nvim-tree/nvim-tree.lua/commit/fca0b67c0b5a31727fb33addc4d9c100736a2894))
|
|
||||||
* **#3059:** test for presence of new 0.11 API vim.hl.range ([#3060](https://github.com/nvim-tree/nvim-tree.lua/issues/3060)) ([70825f2](https://github.com/nvim-tree/nvim-tree.lua/commit/70825f23db61ecd900c4cfea169bffe931926a9d))
|
|
||||||
* arithmetic on nil value error on first git project open ([#3064](https://github.com/nvim-tree/nvim-tree.lua/issues/3064)) ([8052310](https://github.com/nvim-tree/nvim-tree.lua/commit/80523101f0ae48b7f1990e907b685a3d79776c01))
|
|
||||||
* stl and stlnc fillchars are hidden in window picker ([b699143](https://github.com/nvim-tree/nvim-tree.lua/commit/b69914325a945ee5157f0d21047210b42af5776e))
|
|
||||||
* window picker: hide fillchars: stl and stlnc ([#3066](https://github.com/nvim-tree/nvim-tree.lua/issues/3066)) ([b699143](https://github.com/nvim-tree/nvim-tree.lua/commit/b69914325a945ee5157f0d21047210b42af5776e))
|
|
||||||
|
|
||||||
## [1.10.0](https://github.com/nvim-tree/nvim-tree.lua/compare/nvim-tree-v1.9.0...nvim-tree-v1.10.0) (2025-01-13)
|
## [1.10.0](https://github.com/nvim-tree/nvim-tree.lua/compare/nvim-tree-v1.9.0...nvim-tree-v1.10.0) (2025-01-13)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -4,30 +4,6 @@ Thank you for contributing.
|
|||||||
|
|
||||||
See [wiki: Development](https://github.com/nvim-tree/nvim-tree.lua/wiki/Development) for environment setup, tips and tools.
|
See [wiki: Development](https://github.com/nvim-tree/nvim-tree.lua/wiki/Development) for environment setup, tips and tools.
|
||||||
|
|
||||||
<!--
|
|
||||||
https://github.com/jonschlinkert/markdown-toc
|
|
||||||
markdown-toc --maxdepth=2 -i CONTRIBUTING.md
|
|
||||||
-->
|
|
||||||
|
|
||||||
<!-- toc -->
|
|
||||||
|
|
||||||
- [Tools](#tools)
|
|
||||||
- [Quality](#quality)
|
|
||||||
* [lint](#lint)
|
|
||||||
* [style](#style)
|
|
||||||
* [check](#check)
|
|
||||||
- [Diagnostics](#diagnostics)
|
|
||||||
- [Backwards Compatibility](#backwards-compatibility)
|
|
||||||
- [Adding New Actions](#adding-new-actions)
|
|
||||||
- [Documentation](#documentation)
|
|
||||||
* [Opts](#opts)
|
|
||||||
* [API](#api)
|
|
||||||
- [Windows](#windows)
|
|
||||||
- [Pull Request](#pull-request)
|
|
||||||
* [Subject](#subject)
|
|
||||||
|
|
||||||
<!-- tocstop -->
|
|
||||||
|
|
||||||
# Tools
|
# Tools
|
||||||
|
|
||||||
Following are used during CI and strongly recommended during local development.
|
Following are used during CI and strongly recommended during local development.
|
||||||
@ -36,9 +12,9 @@ Language server: [luals](https://luals.github.io)
|
|||||||
|
|
||||||
Lint: [luacheck](https://github.com/lunarmodules/luacheck/)
|
Lint: [luacheck](https://github.com/lunarmodules/luacheck/)
|
||||||
|
|
||||||
Style Fixing: [EmmyLuaCodeStyle](https://github.com/CppCXY/EmmyLuaCodeStyle): `CodeCheck`
|
Style: [EmmyLuaCodeStyle](https://github.com/CppCXY/EmmyLuaCodeStyle): `CodeCheck`
|
||||||
|
|
||||||
nvim-tree.lua migrated from stylua to EmmyLuaCodeStyle ~2024/10. `vim.lsp.buf.format()` may be used as it is the default formatter for luals, using an embedded [EmmyLuaCodeStyle](https://github.com/CppCXY/EmmyLuaCodeStyle)
|
nvim-tree.lua migrated from stylua to EmmyLuaCodeStyle ~2024/10. `vim.lsp.buf.format()` may be used as it is the default formatter for luals
|
||||||
|
|
||||||
You can install them via you OS package manager e.g. `pacman`, `brew` or other via other package managers such as `cargo` or `luarocks`
|
You can install them via you OS package manager e.g. `pacman`, `brew` or other via other package managers such as `cargo` or `luarocks`
|
||||||
|
|
||||||
@ -60,14 +36,14 @@ make lint
|
|||||||
|
|
||||||
## style
|
## style
|
||||||
|
|
||||||
1. Runs lua language server `codestyle-check` only, using `.luarc.json` settings
|
1. Runs CodeCheck using `.editorconfig` settings
|
||||||
1. Runs `scripts/doc-comments.sh` to validate annotated documentation
|
1. Runs `scripts/doc-comments.sh` to validate annotated documentation
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
make style
|
make style
|
||||||
```
|
```
|
||||||
|
|
||||||
You can automatically fix style issues using `CodeCheck`:
|
You can automatically fix `CodeCheck` issues via:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
make style-fix
|
make style-fix
|
||||||
@ -96,30 +72,6 @@ curl -L "https://github.com/LuaLS/lua-language-server/releases/download/3.9.1/lu
|
|||||||
PATH="luals/bin:${PATH}" make check
|
PATH="luals/bin:${PATH}" make check
|
||||||
```
|
```
|
||||||
|
|
||||||
# Diagnostics
|
|
||||||
|
|
||||||
Diagnostics issues may not be suppressed. See [luals](https://luals.github.io) documentation for details on how to structure the code and comments.
|
|
||||||
|
|
||||||
Suppressions are permitted only in the following cases:
|
|
||||||
|
|
||||||
- Backwards compatibility shims
|
|
||||||
- neovim API metadata incorrect, awaiting upstream fix
|
|
||||||
- classic class framework
|
|
||||||
|
|
||||||
# Backwards Compatibility
|
|
||||||
|
|
||||||
Whenever new neovim API is introduced, please ensure that it is available in older versions. See `:help deprecated.txt` and `$VIMRUNTIME/lua/vim/_meta/api.lua`
|
|
||||||
|
|
||||||
See `nvim-tree.setup` for the oldest supported version of neovim. If the API is not availble in that version, a backwards compatibility shim must be used e.g.
|
|
||||||
|
|
||||||
```lua
|
|
||||||
if vim.fn.has("nvim-0.10") == 1 then
|
|
||||||
modified = vim.api.nvim_get_option_value("modified", { buf = target_bufid })
|
|
||||||
else
|
|
||||||
modified = vim.api.nvim_buf_get_option(target_bufid, "modified") ---@diagnostic disable-line: deprecated
|
|
||||||
end
|
|
||||||
```
|
|
||||||
|
|
||||||
# Adding New Actions
|
# Adding New Actions
|
||||||
|
|
||||||
To add a new action, add a file in `actions/name-of-the-action.lua`. You should export a `setup` function if some configuration is needed.
|
To add a new action, add a file in `actions/name-of-the-action.lua`. You should export a `setup` function if some configuration is needed.
|
||||||
|
|||||||
15
Makefile
15
Makefile
@ -17,7 +17,7 @@ luacheck:
|
|||||||
|
|
||||||
# --diagnosis-as-error does not function for workspace, hence we post-process the output
|
# --diagnosis-as-error does not function for workspace, hence we post-process the output
|
||||||
style-check:
|
style-check:
|
||||||
@scripts/luals-check.sh codestyle-check
|
CodeFormat check --config .editorconfig --diagnosis-as-error --workspace lua
|
||||||
|
|
||||||
style-doc:
|
style-doc:
|
||||||
scripts/doc-comments.sh
|
scripts/doc-comments.sh
|
||||||
@ -43,6 +43,19 @@ help-update:
|
|||||||
help-check: help-update
|
help-check: help-update
|
||||||
git diff --exit-code doc/nvim-tree-lua.txt
|
git diff --exit-code doc/nvim-tree-lua.txt
|
||||||
|
|
||||||
|
#
|
||||||
|
# test
|
||||||
|
#
|
||||||
|
test: plenary.nvim
|
||||||
|
scripts/test.sh
|
||||||
|
|
||||||
|
#
|
||||||
|
# Dependencies
|
||||||
|
#
|
||||||
|
# no plenary tags or releases available
|
||||||
|
plenary.nvim:
|
||||||
|
git clone git@github.com:nvim-lua/plenary.nvim.git
|
||||||
|
|
||||||
|
|
||||||
.PHONY: all lint style check luacheck style-check style-doc luals style-fix help-update help-check
|
.PHONY: all lint style check luacheck style-check style-doc luals style-fix help-update help-check
|
||||||
|
|
||||||
|
|||||||
@ -206,7 +206,7 @@ Show the mappings: `g?`
|
|||||||
`S` Search |nvim-tree-api.tree.search_node()|
|
`S` Search |nvim-tree-api.tree.search_node()|
|
||||||
`u` Rename: Full Path |nvim-tree-api.fs.rename_full()|
|
`u` Rename: Full Path |nvim-tree-api.fs.rename_full()|
|
||||||
`U` Toggle Filter: Hidden |nvim-tree-api.tree.toggle_custom_filter()|
|
`U` Toggle Filter: Hidden |nvim-tree-api.tree.toggle_custom_filter()|
|
||||||
`W` Collapse All |nvim-tree-api.tree.collapse_all()|
|
`W` Collapse |nvim-tree-api.tree.collapse_all()|
|
||||||
`x` Cut |nvim-tree-api.fs.cut()|
|
`x` Cut |nvim-tree-api.fs.cut()|
|
||||||
`y` Copy Name |nvim-tree-api.fs.copy.filename()|
|
`y` Copy Name |nvim-tree-api.fs.copy.filename()|
|
||||||
`Y` Copy Relative Path |nvim-tree-api.fs.copy.relative_path()|
|
`Y` Copy Relative Path |nvim-tree-api.fs.copy.relative_path()|
|
||||||
@ -341,7 +341,7 @@ See |nvim-tree-highlight| for details.
|
|||||||
|
|
||||||
See |nvim-tree-api.tree.collapse_all()|
|
See |nvim-tree-api.tree.collapse_all()|
|
||||||
|
|
||||||
Calls: `api.tree.collapse_all({ keep_buffers = false })`
|
Calls: `api.tree.collapse_all(false)`
|
||||||
|
|
||||||
*:NvimTreeCollapseKeepBuffers*
|
*:NvimTreeCollapseKeepBuffers*
|
||||||
|
|
||||||
@ -350,7 +350,7 @@ See |nvim-tree-highlight| for details.
|
|||||||
|
|
||||||
See |nvim-tree-api.tree.collapse_all()|
|
See |nvim-tree-api.tree.collapse_all()|
|
||||||
|
|
||||||
Calls: `api.tree.collapse_all({ keep_buffers = true })`
|
Calls: `api.tree.collapse_all(true)`
|
||||||
|
|
||||||
*:NvimTreeHiTest*
|
*:NvimTreeHiTest*
|
||||||
|
|
||||||
@ -398,7 +398,6 @@ Following is the default configuration. See |nvim-tree-opts| for details. >lua
|
|||||||
view = {
|
view = {
|
||||||
centralize_selection = false,
|
centralize_selection = false,
|
||||||
cursorline = true,
|
cursorline = true,
|
||||||
cursorlineopt = "both",
|
|
||||||
debounce_delay = 15,
|
debounce_delay = 15,
|
||||||
side = "left",
|
side = "left",
|
||||||
preserve_window_proportions = false,
|
preserve_window_proportions = false,
|
||||||
@ -463,10 +462,7 @@ Following is the default configuration. See |nvim-tree-opts| for details. >lua
|
|||||||
hidden_placement = "after",
|
hidden_placement = "after",
|
||||||
diagnostics_placement = "signcolumn",
|
diagnostics_placement = "signcolumn",
|
||||||
bookmarks_placement = "signcolumn",
|
bookmarks_placement = "signcolumn",
|
||||||
padding = {
|
padding = " ",
|
||||||
icon = " ",
|
|
||||||
folder_arrow = " ",
|
|
||||||
},
|
|
||||||
symlink_arrow = " ➛ ",
|
symlink_arrow = " ➛ ",
|
||||||
show = {
|
show = {
|
||||||
file = true,
|
file = true,
|
||||||
@ -545,7 +541,6 @@ Following is the default configuration. See |nvim-tree-opts| for details. >lua
|
|||||||
warning = "",
|
warning = "",
|
||||||
error = "",
|
error = "",
|
||||||
},
|
},
|
||||||
diagnostic_opts = false,
|
|
||||||
},
|
},
|
||||||
modified = {
|
modified = {
|
||||||
enable = false,
|
enable = false,
|
||||||
@ -772,10 +767,6 @@ initially centralized, see |zz|.
|
|||||||
Enable |cursorline| in the tree window.
|
Enable |cursorline| in the tree window.
|
||||||
Type: `boolean`, Default: `true`
|
Type: `boolean`, Default: `true`
|
||||||
|
|
||||||
*nvim-tree.view.cursorlineopt*
|
|
||||||
Set |cursorlineopt| in the tree window.
|
|
||||||
Type: `string`, Default: `"both"`
|
|
||||||
|
|
||||||
*nvim-tree.view.debounce_delay*
|
*nvim-tree.view.debounce_delay*
|
||||||
Idle milliseconds before some reload / refresh operations.
|
Idle milliseconds before some reload / refresh operations.
|
||||||
Increase if you experience performance issues around screen refresh.
|
Increase if you experience performance issues around screen refresh.
|
||||||
@ -1072,16 +1063,12 @@ Configuration options for icons.
|
|||||||
|
|
||||||
*nvim-tree.renderer.icons.bookmarks_placement*
|
*nvim-tree.renderer.icons.bookmarks_placement*
|
||||||
Bookmark icon placement.
|
Bookmark icon placement.
|
||||||
Type: `string`, Default: `"signcolumn"`
|
Type: `string`, Default: `signcolumn`
|
||||||
|
|
||||||
*nvim-tree.renderer.icons.padding.icon*
|
*nvim-tree.renderer.icons.padding*
|
||||||
Inserted between icon and filename.
|
Inserted between icon and filename.
|
||||||
Type: `string`, Default: `" "`
|
Type: `string`, Default: `" "`
|
||||||
|
|
||||||
*nvim-tree.renderer.icons.padding.folder_arrow*
|
|
||||||
Inserted between folder arrow icon and file/folder icon.
|
|
||||||
Type: `string`, Default: `" "`
|
|
||||||
|
|
||||||
*nvim-tree.renderer.icons.symlink_arrow*
|
*nvim-tree.renderer.icons.symlink_arrow*
|
||||||
Used as a separator between symlinks' source and target.
|
Used as a separator between symlinks' source and target.
|
||||||
Type: `string`, Default: `" ➛ "`
|
Type: `string`, Default: `" ➛ "`
|
||||||
@ -1330,10 +1317,6 @@ Icons for diagnostic severity.
|
|||||||
error = ""
|
error = ""
|
||||||
}
|
}
|
||||||
<
|
<
|
||||||
*nvim-tree.diagnostics.diagnostic_opts*
|
|
||||||
|vim.diagnostic.Opts| overrides |nvim-tree.diagnostics.severity| and
|
|
||||||
|nvim-tree.diagnostics.icons|
|
|
||||||
Type: `boolean`, Default: `false`
|
|
||||||
==============================================================================
|
==============================================================================
|
||||||
5.9 OPTS: MODIFIED *nvim-tree-opts-modified*
|
5.9 OPTS: MODIFIED *nvim-tree-opts-modified*
|
||||||
|
|
||||||
@ -1390,7 +1373,7 @@ delete/wipe. A reload or filesystem event will result in an update.
|
|||||||
Type: `boolean`, Default: `false`
|
Type: `boolean`, Default: `false`
|
||||||
|
|
||||||
*nvim-tree.filters.no_bookmark*
|
*nvim-tree.filters.no_bookmark*
|
||||||
Do not show files that are not bookmarked.
|
Do not show files that are not bookarked.
|
||||||
Toggle via |nvim-tree-api.tree.toggle_no_bookmark_filter()|, default `M`
|
Toggle via |nvim-tree-api.tree.toggle_no_bookmark_filter()|, default `M`
|
||||||
Enabling this is not useful as there is no means yet to persist bookmarks.
|
Enabling this is not useful as there is no means yet to persist bookmarks.
|
||||||
Type: `boolean`, Default: `false`
|
Type: `boolean`, Default: `false`
|
||||||
@ -1480,8 +1463,7 @@ vim |current-directory| behaviour.
|
|||||||
Type: `boolean`, Default: `false`
|
Type: `boolean`, Default: `false`
|
||||||
|
|
||||||
*nvim-tree.actions.expand_all*
|
*nvim-tree.actions.expand_all*
|
||||||
Configuration for |nvim-tree-api.tree.expand_all()| and
|
Configuration for expand_all behaviour.
|
||||||
|nvim-tree-api.node.expand()|
|
|
||||||
|
|
||||||
*nvim-tree.actions.expand_all.max_folder_discovery*
|
*nvim-tree.actions.expand_all.max_folder_discovery*
|
||||||
Limit the number of folders being explored when expanding every folders.
|
Limit the number of folders being explored when expanding every folders.
|
||||||
@ -1524,13 +1506,17 @@ Configuration options for opening a file from nvim-tree.
|
|||||||
Resizes the tree when opening a file.
|
Resizes the tree when opening a file.
|
||||||
Type: `boolean`, Default: `true`
|
Type: `boolean`, Default: `true`
|
||||||
|
|
||||||
|
*nvim-tree.experimental.actions.open_file.relative_path*
|
||||||
|
Buffers opened by nvim-tree will use with relative paths instead of
|
||||||
|
absolute.
|
||||||
|
Type: `boolean`, Default: `true`
|
||||||
|
|
||||||
*nvim-tree.actions.open_file.window_picker*
|
*nvim-tree.actions.open_file.window_picker*
|
||||||
Window picker configuration.
|
Window picker configuration.
|
||||||
|
|
||||||
*nvim-tree.actions.open_file.window_picker.enable*
|
*nvim-tree.actions.open_file.window_picker.enable*
|
||||||
Enable the feature. If the feature is not enabled, files will open in
|
Enable the feature. If the feature is not enabled, files will open in
|
||||||
window from which you last opened the tree, obeying
|
window from which you last opened the tree.
|
||||||
|nvim-tree.actions.open_file.window_picker.exclude|
|
|
||||||
Type: `boolean`, Default: `true`
|
Type: `boolean`, Default: `true`
|
||||||
|
|
||||||
*nvim-tree.actions.open_file.window_picker.picker*
|
*nvim-tree.actions.open_file.window_picker.picker*
|
||||||
@ -1549,10 +1535,9 @@ Configuration options for opening a file from nvim-tree.
|
|||||||
Type: `string`, Default: `"ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890"`
|
Type: `string`, Default: `"ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890"`
|
||||||
|
|
||||||
*nvim-tree.actions.open_file.window_picker.exclude*
|
*nvim-tree.actions.open_file.window_picker.exclude*
|
||||||
Table of buffer option names mapped to a list of option values.
|
Table of buffer option names mapped to a list of option values that
|
||||||
Windows containing matching buffers will not be:
|
indicates to the picker that the buffer's window should not be
|
||||||
- available when using a window picker
|
selectable.
|
||||||
- selected when not using a window picker
|
|
||||||
Type: `table`, Default: >lua
|
Type: `table`, Default: >lua
|
||||||
{
|
{
|
||||||
filetype = {
|
filetype = {
|
||||||
@ -1837,26 +1822,17 @@ tree.find_file({opts}) *nvim-tree-api.tree.find_file()*
|
|||||||
tree.search_node() *nvim-tree-api.tree.search_node()*
|
tree.search_node() *nvim-tree-api.tree.search_node()*
|
||||||
Open the search dialogue as per the search_node action.
|
Open the search dialogue as per the search_node action.
|
||||||
|
|
||||||
tree.collapse_all({opts}) *nvim-tree-api.tree.collapse_all()*
|
tree.collapse_all({keep_buffers}) *nvim-tree-api.tree.collapse_all()*
|
||||||
Collapse the tree.
|
Collapse the tree.
|
||||||
|
|
||||||
Parameters: ~
|
Parameters: ~
|
||||||
• {opts} (table) optional parameters
|
|
||||||
|
|
||||||
Options: ~
|
|
||||||
• {keep_buffers} (boolean) do not collapse nodes with open buffers.
|
• {keep_buffers} (boolean) do not collapse nodes with open buffers.
|
||||||
|
|
||||||
tree.expand_all({node}, {opts}) *nvim-tree-api.tree.expand_all()*
|
tree.expand_all({node}) *nvim-tree-api.tree.expand_all()*
|
||||||
Recursively expand all nodes under the tree root or specified folder.
|
Recursively expand all nodes under the tree root or specified folder.
|
||||||
|
|
||||||
Parameters: ~
|
Parameters: ~
|
||||||
• {node} (Node|nil) folder
|
• {node} (Node|nil) folder
|
||||||
• {opts} (ApiTreeExpandOpts) optional parameters
|
|
||||||
|
|
||||||
Options: ~
|
|
||||||
• {expand_until} ((fun(expansion_count: integer, node: Node?): boolean)?)
|
|
||||||
Return true if {node} should be expanded.
|
|
||||||
{expansion_count} is the total number of folders expanded.
|
|
||||||
|
|
||||||
*nvim-tree-api.tree.toggle_enable_filters()*
|
*nvim-tree-api.tree.toggle_enable_filters()*
|
||||||
tree.toggle_enable_filters()
|
tree.toggle_enable_filters()
|
||||||
@ -2031,99 +2007,43 @@ fs.print_clipboard() *nvim-tree-api.fs.print_clipboard()*
|
|||||||
Parameters: ~
|
Parameters: ~
|
||||||
• {node} (Node|nil) file or folder
|
• {node} (Node|nil) file or folder
|
||||||
|
|
||||||
node.open.edit({node}, {opts}) *nvim-tree-api.node.open.edit()*
|
node.open.edit({node}) *nvim-tree-api.node.open.edit()*
|
||||||
File: open as per |nvim-tree.actions.open_file|
|
File: open as per |nvim-tree.actions.open_file|
|
||||||
Folder: expand or collapse
|
Folder: expand or collapse
|
||||||
Root: change directory up
|
Root: change directory up
|
||||||
|
|
||||||
Parameters: ~
|
|
||||||
• {node} (Node|nil) file or folder
|
|
||||||
• {opts} (table) optional parameters
|
|
||||||
|
|
||||||
Options: ~
|
|
||||||
• {quit_on_open} (boolean) quits the tree when opening the file
|
|
||||||
• {focus} (boolean) keep focus in the tree when opening the file
|
|
||||||
|
|
||||||
*nvim-tree-api.node.open.replace_tree_buffer()*
|
*nvim-tree-api.node.open.replace_tree_buffer()*
|
||||||
node.open.replace_tree_buffer({node})
|
node.open.replace_tree_buffer({node})
|
||||||
|nvim-tree-api.node.edit()|, file will be opened in place: in the
|
|nvim-tree-api.node.edit()|, file will be opened in place: in the
|
||||||
nvim-tree window.
|
nvim-tree window.
|
||||||
|
|
||||||
*nvim-tree-api.node.open.no_window_picker()*
|
*nvim-tree-api.node.open.no_window_picker()*
|
||||||
node.open.no_window_picker({node}, {opts})
|
node.open.no_window_picker({node})
|
||||||
|nvim-tree-api.node.edit()|, window picker will never be used as per
|
|nvim-tree-api.node.edit()|, window picker will never be used as per
|
||||||
|nvim-tree.actions.open_file.window_picker.enable| `false`
|
|nvim-tree.actions.open_file.window_picker.enable| `false`
|
||||||
|
|
||||||
Parameters: ~
|
node.open.vertical({node}) *nvim-tree-api.node.open.vertical()*
|
||||||
• {node} (Node|nil) file or folder
|
|
||||||
• {opts} (table) optional parameters
|
|
||||||
|
|
||||||
Options: ~
|
|
||||||
• {quit_on_open} (boolean) quits the tree when opening the file
|
|
||||||
• {focus} (boolean) keep focus in the tree when opening the file
|
|
||||||
|
|
||||||
node.open.vertical({node}, {opts}) *nvim-tree-api.node.open.vertical()*
|
|
||||||
|nvim-tree-api.node.edit()|, file will be opened in a new vertical split.
|
|nvim-tree-api.node.edit()|, file will be opened in a new vertical split.
|
||||||
|
|
||||||
Parameters: ~
|
|
||||||
• {node} (Node|nil) file or folder
|
|
||||||
• {opts} (table) optional parameters
|
|
||||||
|
|
||||||
Options: ~
|
|
||||||
• {quit_on_open} (boolean) quits the tree when opening the file
|
|
||||||
• {focus} (boolean) keep focus in the tree when opening the file
|
|
||||||
|
|
||||||
*nvim-tree-api.node.open.vertical_no_picker()*
|
*nvim-tree-api.node.open.vertical_no_picker()*
|
||||||
node.open.vertical_no_picker({node}, {opts})
|
node.open.vertical_no_picker({node})
|
||||||
|nvim-tree-api.node.vertical()|, window picker will never be used as per
|
|nvim-tree-api.node.vertical()|, window picker will never be used as per
|
||||||
|nvim-tree.actions.open_file.window_picker.enable| `false`
|
|nvim-tree.actions.open_file.window_picker.enable| `false`
|
||||||
|
|
||||||
Parameters: ~
|
node.open.horizontal({node}) *nvim-tree-api.node.open.horizontal()*
|
||||||
• {node} (Node|nil) file or folder
|
|
||||||
• {opts} (table) optional parameters
|
|
||||||
|
|
||||||
Options: ~
|
|
||||||
• {quit_on_open} (boolean) quits the tree when opening the file
|
|
||||||
• {focus} (boolean) keep focus in the tree when opening the file
|
|
||||||
|
|
||||||
node.open.horizontal({node}, {opts}) *nvim-tree-api.node.open.horizontal()*
|
|
||||||
|nvim-tree-api.node.edit()|, file will be opened in a new horizontal split.
|
|nvim-tree-api.node.edit()|, file will be opened in a new horizontal split.
|
||||||
|
|
||||||
Parameters: ~
|
|
||||||
• {node} (Node|nil) file or folder
|
|
||||||
• {opts} (table) optional parameters
|
|
||||||
|
|
||||||
Options: ~
|
|
||||||
• {quit_on_open} (boolean) quits the tree when opening the file
|
|
||||||
• {focus} (boolean) keep focus in the tree when opening the file
|
|
||||||
|
|
||||||
*nvim-tree-api.node.open.horizontal_no_picker()*
|
*nvim-tree-api.node.open.horizontal_no_picker()*
|
||||||
node.open.horizontal_no_picker({node}, {opts})
|
node.open.horizontal_no_picker({node})
|
||||||
|nvim-tree-api.node.horizontal()|, window picker will never be used as per
|
|nvim-tree-api.node.horizontal()|, window picker will never be used as per
|
||||||
|nvim-tree.actions.open_file.window_picker.enable| `false`
|
|nvim-tree.actions.open_file.window_picker.enable| `false`
|
||||||
|
|
||||||
Parameters: ~
|
|
||||||
• {node} (Node|nil) file or folder
|
|
||||||
• {opts} (table) optional parameters
|
|
||||||
|
|
||||||
Options: ~
|
|
||||||
• {quit_on_open} (boolean) quits the tree when opening the file
|
|
||||||
• {focus} (boolean) keep focus in the tree when opening the file
|
|
||||||
|
|
||||||
*nvim-tree-api.node.open.toggle_group_empty()*
|
*nvim-tree-api.node.open.toggle_group_empty()*
|
||||||
node.open.toggle_group_empty({node}, {opts})
|
node.open.toggle_group_empty({node})
|
||||||
Toggle |nvim-tree.renderer.group_empty| for a specific folder.
|
Toggle |nvim-tree.renderer.group_empty| for a specific folder.
|
||||||
Does nothing on files.
|
Does nothing on files.
|
||||||
Needs |nvim-tree.renderer.group_empty| set.
|
Needs |nvim-tree.renderer.group_empty| set.
|
||||||
|
|
||||||
Parameters: ~
|
|
||||||
• {node} (Node|nil) file or folder
|
|
||||||
• {opts} (table) optional parameters
|
|
||||||
|
|
||||||
Options: ~
|
|
||||||
• {quit_on_open} (boolean) quits the tree when opening the file
|
|
||||||
• {focus} (boolean) keep focus in the tree when opening the file
|
|
||||||
|
|
||||||
node.open.drop({node}) *nvim-tree-api.node.open.drop()*
|
node.open.drop({node}) *nvim-tree-api.node.open.drop()*
|
||||||
Switch to window with selected file if it exists.
|
Switch to window with selected file if it exists.
|
||||||
Open file otherwise.
|
Open file otherwise.
|
||||||
@ -2133,17 +2053,9 @@ node.open.drop({node}) *nvim-tree-api.node.open.drop()*
|
|||||||
Folder: expand or collapse
|
Folder: expand or collapse
|
||||||
Root: change directory up
|
Root: change directory up
|
||||||
|
|
||||||
node.open.tab({node}, {opts}) *nvim-tree-api.node.open.tab()*
|
node.open.tab({node}) *nvim-tree-api.node.open.tab()*
|
||||||
|nvim-tree-api.node.edit()|, file will be opened in a new tab.
|
|nvim-tree-api.node.edit()|, file will be opened in a new tab.
|
||||||
|
|
||||||
Parameters: ~
|
|
||||||
• {node} (Node|nil) file or folder
|
|
||||||
• {opts} (table) optional parameters
|
|
||||||
|
|
||||||
Options: ~
|
|
||||||
• {quit_on_open} (boolean) quits the tree when opening the file
|
|
||||||
• {focus} (boolean) keep focus in the tree when opening the file
|
|
||||||
|
|
||||||
*nvim-tree-api.node.open.tab_drop()*
|
*nvim-tree-api.node.open.tab_drop()*
|
||||||
node.open.tab_drop({node})
|
node.open.tab_drop({node})
|
||||||
Switch to tab containing window with selected file if it exists.
|
Switch to tab containing window with selected file if it exists.
|
||||||
@ -2153,31 +2065,15 @@ node.open.tab_drop({node})
|
|||||||
Folder: expand or collapse
|
Folder: expand or collapse
|
||||||
Root: change directory up
|
Root: change directory up
|
||||||
|
|
||||||
node.open.preview({node}, {opts}) *nvim-tree-api.node.open.preview()*
|
node.open.preview({node}) *nvim-tree-api.node.open.preview()*
|
||||||
|nvim-tree-api.node.edit()|, file buffer will have |bufhidden| set to `delete`.
|
|nvim-tree-api.node.edit()|, file buffer will have |bufhidden| set to `delete`.
|
||||||
|
|
||||||
Parameters: ~
|
|
||||||
• {node} (Node|nil) file or folder
|
|
||||||
• {opts} (table) optional parameters
|
|
||||||
|
|
||||||
Options: ~
|
|
||||||
• {quit_on_open} (boolean) quits the tree when opening the file
|
|
||||||
• {focus} (boolean) keep focus in the tree when opening the file
|
|
||||||
|
|
||||||
*nvim-tree-api.node.open.preview_no_picker()*
|
*nvim-tree-api.node.open.preview_no_picker()*
|
||||||
node.open.preview_no_picker({node}, {opts})
|
node.open.preview_no_picker({node})
|
||||||
|nvim-tree-api.node.edit()|, file buffer will have |bufhidden| set to `delete`.
|
|nvim-tree-api.node.edit()|, file buffer will have |bufhidden| set to `delete`.
|
||||||
window picker will never be used as per
|
window picker will never be used as per
|
||||||
|nvim-tree.actions.open_file.window_picker.enable| `false`
|
|nvim-tree.actions.open_file.window_picker.enable| `false`
|
||||||
|
|
||||||
Parameters: ~
|
|
||||||
• {node} (Node|nil) file or folder
|
|
||||||
• {opts} (table) optional parameters
|
|
||||||
|
|
||||||
Options: ~
|
|
||||||
• {quit_on_open} (boolean) quits the tree when opening the file
|
|
||||||
• {focus} (boolean) keep focus in the tree when opening the file
|
|
||||||
|
|
||||||
node.navigate.git.next({node}) *nvim-tree-api.node.navigate.git.next()*
|
node.navigate.git.next({node}) *nvim-tree-api.node.navigate.git.next()*
|
||||||
Navigate to the next item showing git status.
|
Navigate to the next item showing git status.
|
||||||
|
|
||||||
@ -2290,29 +2186,6 @@ node.buffer.wipe({node}, {opts}) *nvim-tree-api.node.buffer.wipe()*
|
|||||||
Options: ~
|
Options: ~
|
||||||
• {force} (boolean) wipe even if buffer is modified, default false
|
• {force} (boolean) wipe even if buffer is modified, default false
|
||||||
|
|
||||||
node.expand({node}, {opts}) *nvim-tree-api.node.expand()*
|
|
||||||
Recursively expand all nodes under a directory or a file's parent
|
|
||||||
directory.
|
|
||||||
|
|
||||||
Parameters: ~
|
|
||||||
• {node} (Node|nil) file or folder
|
|
||||||
• {opts} (ApiTreeExpandOpts) optional parameters
|
|
||||||
|
|
||||||
Options: ~
|
|
||||||
• {expand_until} ((fun(expansion_count: integer, node: Node?): boolean)?)
|
|
||||||
Return true if {node} should be expanded.
|
|
||||||
{expansion_count} is the total number of folders expanded.
|
|
||||||
|
|
||||||
node.collapse({node}, {opts}) *nvim-tree-api.node.collapse()*
|
|
||||||
Collapse the tree under a directory or a file's parent directory.
|
|
||||||
|
|
||||||
Parameters: ~
|
|
||||||
• {node} (Node|nil) file or folder
|
|
||||||
• {opts} (table) optional parameters
|
|
||||||
|
|
||||||
Options: ~
|
|
||||||
• {keep_buffers} (boolean) do not collapse nodes with open buffers.
|
|
||||||
|
|
||||||
==============================================================================
|
==============================================================================
|
||||||
6.4 API GIT *nvim-tree-api.git*
|
6.4 API GIT *nvim-tree-api.git*
|
||||||
|
|
||||||
@ -2339,7 +2212,6 @@ events.Event *nvim-tree-api.events.Event*
|
|||||||
|
|
||||||
live_filter.start() *nvim-tree-api.live_filter.start()*
|
live_filter.start() *nvim-tree-api.live_filter.start()*
|
||||||
Enter |nvim-tree.live_filter| mode.
|
Enter |nvim-tree.live_filter| mode.
|
||||||
Opens an input window with |filetype| `"NvimTreeFilter"`
|
|
||||||
|
|
||||||
live_filter.clear() *nvim-tree-api.live_filter.clear()*
|
live_filter.clear() *nvim-tree-api.live_filter.clear()*
|
||||||
Exit |nvim-tree.live_filter| mode.
|
Exit |nvim-tree.live_filter| mode.
|
||||||
@ -2568,7 +2440,7 @@ You are encouraged to copy these to your own |nvim-tree.on_attach| function. >lu
|
|||||||
vim.keymap.set("n", "S", api.tree.search_node, opts("Search"))
|
vim.keymap.set("n", "S", api.tree.search_node, opts("Search"))
|
||||||
vim.keymap.set("n", "u", api.fs.rename_full, opts("Rename: Full Path"))
|
vim.keymap.set("n", "u", api.fs.rename_full, opts("Rename: Full Path"))
|
||||||
vim.keymap.set("n", "U", api.tree.toggle_custom_filter, opts("Toggle Filter: Hidden"))
|
vim.keymap.set("n", "U", api.tree.toggle_custom_filter, opts("Toggle Filter: Hidden"))
|
||||||
vim.keymap.set("n", "W", api.tree.collapse_all, opts("Collapse All"))
|
vim.keymap.set("n", "W", api.tree.collapse_all, opts("Collapse"))
|
||||||
vim.keymap.set("n", "x", api.fs.cut, opts("Cut"))
|
vim.keymap.set("n", "x", api.fs.cut, opts("Cut"))
|
||||||
vim.keymap.set("n", "y", api.fs.copy.filename, opts("Copy Name"))
|
vim.keymap.set("n", "y", api.fs.copy.filename, opts("Copy Name"))
|
||||||
vim.keymap.set("n", "Y", api.fs.copy.relative_path, opts("Copy Relative Path"))
|
vim.keymap.set("n", "Y", api.fs.copy.relative_path, opts("Copy Relative Path"))
|
||||||
@ -2817,21 +2689,13 @@ e.g. handler for node renamed: >lua
|
|||||||
|nvim_tree_events_kind|
|
|nvim_tree_events_kind|
|
||||||
|
|
||||||
- Event.Ready
|
- Event.Ready
|
||||||
When NvimTree has been initialized.
|
When NvimTree has been initialized
|
||||||
• Note: Handler takes no parameter.
|
|
||||||
|
|
||||||
- Event.TreePreOpen
|
|
||||||
Invoked before the window and buffer for NvimTree are created
|
|
||||||
or opened. Before |Event.TreeOpen| event.
|
|
||||||
• Note: Handler takes no parameter.
|
• Note: Handler takes no parameter.
|
||||||
|
|
||||||
- Event.TreeOpen
|
- Event.TreeOpen
|
||||||
Invoked after the NvimTree is opened.
|
|
||||||
• Note: Handler takes no parameter.
|
• Note: Handler takes no parameter.
|
||||||
|
|
||||||
- Event.TreeClose
|
- Event.TreeClose
|
||||||
Invoked after the NvimTree is closed, but before the window is
|
|
||||||
closed. Dispatched on |WinClosed| event for NvimTree window.
|
|
||||||
• Note: Handler takes no parameter.
|
• Note: Handler takes no parameter.
|
||||||
|
|
||||||
- Event.Resize - When NvimTree is resized.
|
- Event.Resize - When NvimTree is resized.
|
||||||
@ -2946,71 +2810,43 @@ Decorators may:
|
|||||||
- Set highlight group for the name or icons
|
- Set highlight group for the name or icons
|
||||||
- Override node icon
|
- Override node icon
|
||||||
|
|
||||||
Create a `nvim_tree.api.decorator.UserDecorator` class and register it with
|
Specify decorators and their precedence via |nvim-tree.renderer.decorators|
|
||||||
precedence via |nvim-tree.renderer.decorators|
|
e.g. defaults with a user decorator class being overridden only by Cut: >lua
|
||||||
|
{
|
||||||
See |nvim-tree-decorator-example|
|
"Git",
|
||||||
|
"Open",
|
||||||
See `nvim-tree/_meta/api_decorator.lua` for full class documentation.
|
"Hidden",
|
||||||
|
"Modified",
|
||||||
|
"Bookmark",
|
||||||
|
"Diagnostics",
|
||||||
|
"Copied",
|
||||||
|
MyDecorator,
|
||||||
|
"Cut",
|
||||||
|
}
|
||||||
|
|
||||||
|
See `nvim-tree/_meta/api_decorator.lua` for full
|
||||||
|
`nvim_tree.api.decorator.UserDecorator` class documentation.
|
||||||
|
<
|
||||||
==============================================================================
|
==============================================================================
|
||||||
11.1. DECORATOR EXAMPLE *nvim-tree-decorator-example*
|
11.1. DECORATOR EXAMPLE *nvim-tree-decorator-example*
|
||||||
|
|
||||||
A decorator class for nodes named "example", overridind all builtin decorators
|
|
||||||
except for Cut.
|
|
||||||
|
|
||||||
- Highlights node name with `IncSearch`
|
|
||||||
- Creates two icons `"1"` and `"2"` placed after the node name, highlighted with
|
|
||||||
`DiffAdd` and `DiffText`
|
|
||||||
- Replaces the node icon with `"N"`, highlighted with `Error `
|
|
||||||
|
|
||||||
Create a class file `~/.config/nvim/lua/my-decorator.lua`
|
|
||||||
|
|
||||||
Require and register it during |nvim-tree-setup|:
|
|
||||||
>lua
|
|
||||||
local MyDecorator = require("my-decorator")
|
|
||||||
|
|
||||||
require("nvim-tree").setup({
|
|
||||||
renderer = {
|
|
||||||
decorators = {
|
|
||||||
"Git",
|
|
||||||
"Open",
|
|
||||||
"Hidden",
|
|
||||||
"Modified",
|
|
||||||
"Bookmark",
|
|
||||||
"Diagnostics",
|
|
||||||
"Copied",
|
|
||||||
MyDecorator,
|
|
||||||
"Cut",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
})
|
|
||||||
<
|
|
||||||
Contents of `my-decorator.lua`:
|
|
||||||
>lua
|
>lua
|
||||||
|
---Create your decorator class
|
||||||
---@class (exact) MyDecorator: nvim_tree.api.decorator.UserDecorator
|
---@class (exact) MyDecorator: nvim_tree.api.decorator.UserDecorator
|
||||||
---@field private my_icon1 nvim_tree.api.HighlightedString
|
---@field private my_icon nvim_tree.api.HighlightedString
|
||||||
---@field private my_icon2 nvim_tree.api.HighlightedString
|
|
||||||
---@field private my_icon_node nvim_tree.api.HighlightedString
|
|
||||||
---@field private my_highlight_group string
|
|
||||||
local MyDecorator = require("nvim-tree.api").decorator.UserDecorator:extend()
|
local MyDecorator = require("nvim-tree.api").decorator.UserDecorator:extend()
|
||||||
|
|
||||||
---Mandatory constructor :new() will be called once per tree render, with no arguments.
|
---Mandatory constructor :new() will be called once per tree render, with no arguments.
|
||||||
function MyDecorator:new()
|
function MyDecorator:new()
|
||||||
self.enabled = true
|
self.enabled = true
|
||||||
self.highlight_range = "name"
|
self.highlight_range = "all"
|
||||||
self.icon_placement = "after"
|
self.icon_placement = "signcolumn"
|
||||||
|
|
||||||
-- create your icons and highlights once, applied to every node
|
-- create your icon once, for convenience
|
||||||
self.my_icon1 = { str = "1", hl = { "DiffAdd" } }
|
self.my_icon = { str = "I", hl = { "MyIcon" } }
|
||||||
self.my_icon2 = { str = "2", hl = { "DiffText" } }
|
|
||||||
self.my_icon_node = { str = "N", hl = { "Error" } }
|
|
||||||
self.my_highlight_group = "IncSearch"
|
|
||||||
|
|
||||||
-- Define the icon signs only once
|
-- Define the icon sign only once
|
||||||
-- Only needed if you are using icon_placement = "signcolumn"
|
-- Only needed if you are using icon_placement = "signcolumn"
|
||||||
-- self:define_sign(self.my_icon1)
|
self:define_sign(self.my_icon)
|
||||||
-- self:define_sign(self.my_icon2)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
---Override node icon
|
---Override node icon
|
||||||
@ -3018,35 +2854,33 @@ Contents of `my-decorator.lua`:
|
|||||||
---@return nvim_tree.api.HighlightedString? icon_node
|
---@return nvim_tree.api.HighlightedString? icon_node
|
||||||
function MyDecorator:icon_node(node)
|
function MyDecorator:icon_node(node)
|
||||||
if node.name == "example" then
|
if node.name == "example" then
|
||||||
return self.my_icon_node
|
return self.my_icon
|
||||||
else
|
else
|
||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
---Return two icons for DecoratorIconPlacement "after"
|
---Return one icon for DecoratorIconPlacement
|
||||||
---@param node nvim_tree.api.Node
|
---@param node nvim_tree.api.Node
|
||||||
---@return nvim_tree.api.HighlightedString[]? icons
|
---@return nvim_tree.api.HighlightedString[]? icons
|
||||||
function MyDecorator:icons(node)
|
function MyDecorator:icons(node)
|
||||||
if node.name == "example" then
|
if node.name == "example" then
|
||||||
return { self.my_icon1, self.my_icon2, }
|
return { self.my_icon }
|
||||||
else
|
else
|
||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
---Exactly one highlight group for DecoratorHighlightRange "name"
|
---Exactly one highlight group for DecoratorHighlightRange
|
||||||
---@param node nvim_tree.api.Node
|
---@param node nvim_tree.api.Node
|
||||||
---@return string? highlight_group
|
---@return string? highlight_group
|
||||||
function MyDecorator:highlight_group(node)
|
function MyDecorator:highlight_group(node)
|
||||||
if node.name == "example" then
|
if node.name == "example" then
|
||||||
return self.my_highlight_group
|
return "MyHighlight"
|
||||||
else
|
else
|
||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
return MyDecorator
|
|
||||||
<
|
<
|
||||||
==============================================================================
|
==============================================================================
|
||||||
12. OS SPECIFIC RESTRICTIONS *nvim-tree-os-specific*
|
12. OS SPECIFIC RESTRICTIONS *nvim-tree-os-specific*
|
||||||
@ -3056,6 +2890,9 @@ Windows WSL and PowerShell
|
|||||||
- Executable file detection is disabled as this is non-performant and can
|
- Executable file detection is disabled as this is non-performant and can
|
||||||
freeze nvim
|
freeze nvim
|
||||||
- Some filesystem watcher error related to permissions will not be reported
|
- Some filesystem watcher error related to permissions will not be reported
|
||||||
|
- Some users have reported unspecified issues with
|
||||||
|
|nvim-tree.experimental.actions.open_file.relative_path|. Please report any
|
||||||
|
issues or disable this feature.
|
||||||
|
|
||||||
==============================================================================
|
==============================================================================
|
||||||
13. NETRW *nvim-tree-netrw*
|
13. NETRW *nvim-tree-netrw*
|
||||||
@ -3102,7 +2939,6 @@ needed.
|
|||||||
`sort_by` |nvim-tree.sort.sorter|
|
`sort_by` |nvim-tree.sort.sorter|
|
||||||
`git.ignore` |nvim-tree.filters.git_ignored|
|
`git.ignore` |nvim-tree.filters.git_ignored|
|
||||||
`renderer.icons.webdev_colors` |nvim-tree.renderer.icons.web_devicons.file.color|
|
`renderer.icons.webdev_colors` |nvim-tree.renderer.icons.web_devicons.file.color|
|
||||||
`renderer.icons.padding` |nvim-tree.renderer.icons.padding.icon|
|
|
||||||
|
|
||||||
==============================================================================
|
==============================================================================
|
||||||
14.2 LEGACY: HIGHLIGHT *nvim-tree-legacy-highlight*
|
14.2 LEGACY: HIGHLIGHT *nvim-tree-legacy-highlight*
|
||||||
@ -3181,7 +3017,6 @@ highlight group is not, hard linking as follows: >
|
|||||||
|nvim-tree.actions.use_system_clipboard|
|
|nvim-tree.actions.use_system_clipboard|
|
||||||
|nvim-tree.auto_reload_on_write|
|
|nvim-tree.auto_reload_on_write|
|
||||||
|nvim-tree.diagnostics.debounce_delay|
|
|nvim-tree.diagnostics.debounce_delay|
|
||||||
|nvim-tree.diagnostics.diagnostic_opts|
|
|
||||||
|nvim-tree.diagnostics.enable|
|
|nvim-tree.diagnostics.enable|
|
||||||
|nvim-tree.diagnostics.icons|
|
|nvim-tree.diagnostics.icons|
|
||||||
|nvim-tree.diagnostics.severity|
|
|nvim-tree.diagnostics.severity|
|
||||||
@ -3191,6 +3026,7 @@ highlight group is not, hard linking as follows: >
|
|||||||
|nvim-tree.diagnostics.show_on_open_dirs|
|
|nvim-tree.diagnostics.show_on_open_dirs|
|
||||||
|nvim-tree.disable_netrw|
|
|nvim-tree.disable_netrw|
|
||||||
|nvim-tree.experimental|
|
|nvim-tree.experimental|
|
||||||
|
|nvim-tree.experimental.actions.open_file.relative_path|
|
||||||
|nvim-tree.filesystem_watchers.debounce_delay|
|
|nvim-tree.filesystem_watchers.debounce_delay|
|
||||||
|nvim-tree.filesystem_watchers.enable|
|
|nvim-tree.filesystem_watchers.enable|
|
||||||
|nvim-tree.filesystem_watchers.ignore_dirs|
|
|nvim-tree.filesystem_watchers.ignore_dirs|
|
||||||
@ -3259,8 +3095,7 @@ highlight group is not, hard linking as follows: >
|
|||||||
|nvim-tree.renderer.icons.glyphs.symlink|
|
|nvim-tree.renderer.icons.glyphs.symlink|
|
||||||
|nvim-tree.renderer.icons.hidden_placement|
|
|nvim-tree.renderer.icons.hidden_placement|
|
||||||
|nvim-tree.renderer.icons.modified_placement|
|
|nvim-tree.renderer.icons.modified_placement|
|
||||||
|nvim-tree.renderer.icons.padding.folder_arrow|
|
|nvim-tree.renderer.icons.padding|
|
||||||
|nvim-tree.renderer.icons.padding.icon|
|
|
||||||
|nvim-tree.renderer.icons.show|
|
|nvim-tree.renderer.icons.show|
|
||||||
|nvim-tree.renderer.icons.show.bookmarks|
|
|nvim-tree.renderer.icons.show.bookmarks|
|
||||||
|nvim-tree.renderer.icons.show.diagnostics|
|
|nvim-tree.renderer.icons.show.diagnostics|
|
||||||
@ -3311,7 +3146,6 @@ highlight group is not, hard linking as follows: >
|
|||||||
|nvim-tree.update_focused_file.update_root.ignore_list|
|
|nvim-tree.update_focused_file.update_root.ignore_list|
|
||||||
|nvim-tree.view.centralize_selection|
|
|nvim-tree.view.centralize_selection|
|
||||||
|nvim-tree.view.cursorline|
|
|nvim-tree.view.cursorline|
|
||||||
|nvim-tree.view.cursorlineopt|
|
|
||||||
|nvim-tree.view.debounce_delay|
|
|nvim-tree.view.debounce_delay|
|
||||||
|nvim-tree.view.float|
|
|nvim-tree.view.float|
|
||||||
|nvim-tree.view.float.enable|
|
|nvim-tree.view.float.enable|
|
||||||
@ -3368,8 +3202,6 @@ highlight group is not, hard linking as follows: >
|
|||||||
|nvim-tree-api.marks.toggle()|
|
|nvim-tree-api.marks.toggle()|
|
||||||
|nvim-tree-api.node.buffer.delete()|
|
|nvim-tree-api.node.buffer.delete()|
|
||||||
|nvim-tree-api.node.buffer.wipe()|
|
|nvim-tree-api.node.buffer.wipe()|
|
||||||
|nvim-tree-api.node.collapse()|
|
|
||||||
|nvim-tree-api.node.expand()|
|
|
||||||
|nvim-tree-api.node.navigate.diagnostics.next()|
|
|nvim-tree-api.node.navigate.diagnostics.next()|
|
||||||
|nvim-tree-api.node.navigate.diagnostics.next_recursive()|
|
|nvim-tree-api.node.navigate.diagnostics.next_recursive()|
|
||||||
|nvim-tree-api.node.navigate.diagnostics.prev()|
|
|nvim-tree-api.node.navigate.diagnostics.prev()|
|
||||||
|
|||||||
@ -236,20 +236,6 @@ local function setup_autocommands(opts)
|
|||||||
end,
|
end,
|
||||||
})
|
})
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Handles event dispatch when tree is closed by `:q`
|
|
||||||
create_nvim_tree_autocmd("WinClosed", {
|
|
||||||
pattern = "*",
|
|
||||||
---@param ev vim.api.keyset.create_autocmd.callback_args
|
|
||||||
callback = function(ev)
|
|
||||||
if not vim.api.nvim_buf_is_valid(ev.buf) then
|
|
||||||
return
|
|
||||||
end
|
|
||||||
if vim.api.nvim_get_option_value("filetype", { buf = ev.buf }) == "NvimTree" then
|
|
||||||
require("nvim-tree.events")._dispatch_on_tree_close()
|
|
||||||
end
|
|
||||||
end,
|
|
||||||
})
|
|
||||||
end
|
end
|
||||||
|
|
||||||
local DEFAULT_OPTS = { -- BEGIN_DEFAULT_OPTS
|
local DEFAULT_OPTS = { -- BEGIN_DEFAULT_OPTS
|
||||||
@ -273,7 +259,6 @@ local DEFAULT_OPTS = { -- BEGIN_DEFAULT_OPTS
|
|||||||
view = {
|
view = {
|
||||||
centralize_selection = false,
|
centralize_selection = false,
|
||||||
cursorline = true,
|
cursorline = true,
|
||||||
cursorlineopt = "both",
|
|
||||||
debounce_delay = 15,
|
debounce_delay = 15,
|
||||||
side = "left",
|
side = "left",
|
||||||
preserve_window_proportions = false,
|
preserve_window_proportions = false,
|
||||||
@ -338,10 +323,7 @@ local DEFAULT_OPTS = { -- BEGIN_DEFAULT_OPTS
|
|||||||
hidden_placement = "after",
|
hidden_placement = "after",
|
||||||
diagnostics_placement = "signcolumn",
|
diagnostics_placement = "signcolumn",
|
||||||
bookmarks_placement = "signcolumn",
|
bookmarks_placement = "signcolumn",
|
||||||
padding = {
|
padding = " ",
|
||||||
icon = " ",
|
|
||||||
folder_arrow = " ",
|
|
||||||
},
|
|
||||||
symlink_arrow = " ➛ ",
|
symlink_arrow = " ➛ ",
|
||||||
show = {
|
show = {
|
||||||
file = true,
|
file = true,
|
||||||
@ -420,7 +402,6 @@ local DEFAULT_OPTS = { -- BEGIN_DEFAULT_OPTS
|
|||||||
warning = "",
|
warning = "",
|
||||||
error = "",
|
error = "",
|
||||||
},
|
},
|
||||||
diagnostic_opts = false,
|
|
||||||
},
|
},
|
||||||
modified = {
|
modified = {
|
||||||
enable = false,
|
enable = false,
|
||||||
|
|||||||
@ -32,7 +32,7 @@ function M.fn(path)
|
|||||||
local profile = log.profile_start("find file %s", path_real)
|
local profile = log.profile_start("find file %s", path_real)
|
||||||
|
|
||||||
-- refresh the contents of all parents, expanding groups as needed
|
-- refresh the contents of all parents, expanding groups as needed
|
||||||
if explorer:get_node_from_path(path_real) == nil then
|
if utils.get_node_from_path(path_real) == nil then
|
||||||
explorer:refresh_parent_nodes_for_path(vim.fn.fnamemodify(path_real, ":h"))
|
explorer:refresh_parent_nodes_for_path(vim.fn.fnamemodify(path_real, ":h"))
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@ -69,16 +69,9 @@ local function remove_dir(cwd)
|
|||||||
|
|
||||||
-- Type must come from fs_stat and not fs_scandir_next to maintain sshfs compatibility
|
-- Type must come from fs_stat and not fs_scandir_next to maintain sshfs compatibility
|
||||||
local stat = vim.loop.fs_stat(new_cwd)
|
local stat = vim.loop.fs_stat(new_cwd)
|
||||||
-- TODO remove once 0.12 is the minimum neovim version
|
|
||||||
-- path incorrectly specified as an integer, fixed upstream for neovim 0.12 https://github.com/neovim/neovim/pull/33872
|
|
||||||
---@diagnostic disable-next-line: param-type-mismatch
|
|
||||||
local lstat = vim.loop.fs_lstat(new_cwd)
|
|
||||||
|
|
||||||
local type = stat and stat.type or nil
|
local type = stat and stat.type or nil
|
||||||
-- Checks if file is a link file to ensure deletion of the symlink instead of the file it points to
|
|
||||||
local ltype = lstat and lstat.type or nil
|
|
||||||
|
|
||||||
if type == "directory" and ltype ~= "link" then
|
if type == "directory" then
|
||||||
local success = remove_dir(new_cwd)
|
local success = remove_dir(new_cwd)
|
||||||
if not success then
|
if not success then
|
||||||
return false
|
return false
|
||||||
|
|||||||
@ -1,3 +1,4 @@
|
|||||||
|
local utils = require("nvim-tree.utils")
|
||||||
local view = require("nvim-tree.view")
|
local view = require("nvim-tree.view")
|
||||||
local core = require("nvim-tree.core")
|
local core = require("nvim-tree.core")
|
||||||
local diagnostics = require("nvim-tree.diagnostics")
|
local diagnostics = require("nvim-tree.diagnostics")
|
||||||
@ -35,7 +36,7 @@ end
|
|||||||
---@param skip_gitignored boolean? default false
|
---@param skip_gitignored boolean? default false
|
||||||
local function move(explorer, where, what, skip_gitignored)
|
local function move(explorer, where, what, skip_gitignored)
|
||||||
local first_node_line = core.get_nodes_starting_line()
|
local first_node_line = core.get_nodes_starting_line()
|
||||||
local nodes_by_line = explorer:get_nodes_by_line(first_node_line)
|
local nodes_by_line = utils.get_nodes_by_line(explorer.nodes, first_node_line)
|
||||||
local iter_start, iter_end, iter_step, cur, first, nex
|
local iter_start, iter_end, iter_step, cur, first, nex
|
||||||
|
|
||||||
local cursor = explorer:get_cursor_position()
|
local cursor = explorer:get_cursor_position()
|
||||||
@ -190,7 +191,7 @@ local function move_prev_recursive(explorer, what, skip_gitignored)
|
|||||||
if node_init.name == ".." then -- root node
|
if node_init.name == ".." then -- root node
|
||||||
view.set_cursor({ 1, 0 }) -- move to root node (position 1)
|
view.set_cursor({ 1, 0 }) -- move to root node (position 1)
|
||||||
else
|
else
|
||||||
local node_init_line = explorer:find_node_line(node_init)
|
local node_init_line = utils.find_node_line(node_init)
|
||||||
if node_init_line < 0 then
|
if node_init_line < 0 then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|||||||
@ -1,4 +1,6 @@
|
|||||||
local view = require("nvim-tree.view")
|
local view = require("nvim-tree.view")
|
||||||
|
local utils = require("nvim-tree.utils")
|
||||||
|
|
||||||
local DirectoryNode = require("nvim-tree.node.directory")
|
local DirectoryNode = require("nvim-tree.node.directory")
|
||||||
|
|
||||||
local M = {}
|
local M = {}
|
||||||
@ -27,7 +29,7 @@ function M.fn(should_close)
|
|||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
local _, line = parent.explorer:find_node(function(n)
|
local _, line = utils.find_node(parent.explorer.nodes, function(n)
|
||||||
return n.absolute_path == parent.absolute_path
|
return n.absolute_path == parent.absolute_path
|
||||||
end)
|
end)
|
||||||
|
|
||||||
|
|||||||
@ -1,3 +1,4 @@
|
|||||||
|
local utils = require("nvim-tree.utils")
|
||||||
local core = require("nvim-tree.core")
|
local core = require("nvim-tree.core")
|
||||||
local Iterator = require("nvim-tree.iterators.node-iterator")
|
local Iterator = require("nvim-tree.iterators.node-iterator")
|
||||||
|
|
||||||
@ -11,14 +12,9 @@ function M.fn(direction)
|
|||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
local explorer = core.get_explorer()
|
|
||||||
if not explorer then
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
local first, last, next, prev = nil, nil, nil, nil
|
local first, last, next, prev = nil, nil, nil, nil
|
||||||
local found = false
|
local found = false
|
||||||
local parent = node.parent or explorer
|
local parent = node.parent or core.get_explorer()
|
||||||
Iterator.builder(parent and parent.nodes or {})
|
Iterator.builder(parent and parent.nodes or {})
|
||||||
:recursor(function()
|
:recursor(function()
|
||||||
return nil
|
return nil
|
||||||
@ -49,7 +45,7 @@ function M.fn(direction)
|
|||||||
end
|
end
|
||||||
|
|
||||||
if target_node then
|
if target_node then
|
||||||
explorer:focus_node_or_parent(target_node)
|
utils.focus_file(target_node.absolute_path)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@ -57,9 +57,7 @@ end
|
|||||||
|
|
||||||
function M.close_popup()
|
function M.close_popup()
|
||||||
if current_popup ~= nil then
|
if current_popup ~= nil then
|
||||||
if vim.api.nvim_win_is_valid(current_popup.winnr) then
|
vim.api.nvim_win_close(current_popup.winnr, true)
|
||||||
vim.api.nvim_win_close(current_popup.winnr, true)
|
|
||||||
end
|
|
||||||
vim.cmd("augroup NvimTreeRemoveFilePopup | au! CursorMoved | augroup END")
|
vim.cmd("augroup NvimTreeRemoveFilePopup | au! CursorMoved | augroup END")
|
||||||
|
|
||||||
current_popup = nil
|
current_popup = nil
|
||||||
|
|||||||
@ -2,7 +2,6 @@
|
|||||||
local lib = require("nvim-tree.lib")
|
local lib = require("nvim-tree.lib")
|
||||||
local notify = require("nvim-tree.notify")
|
local notify = require("nvim-tree.notify")
|
||||||
local utils = require("nvim-tree.utils")
|
local utils = require("nvim-tree.utils")
|
||||||
local full_name = require("nvim-tree.renderer.components.full-name")
|
|
||||||
local view = require("nvim-tree.view")
|
local view = require("nvim-tree.view")
|
||||||
|
|
||||||
local M = {}
|
local M = {}
|
||||||
@ -40,15 +39,21 @@ local function usable_win_ids()
|
|||||||
end
|
end
|
||||||
|
|
||||||
local win_config = vim.api.nvim_win_get_config(id)
|
local win_config = vim.api.nvim_win_get_config(id)
|
||||||
return id ~= tree_winid
|
return id ~= tree_winid and win_config.focusable and not win_config.external or false
|
||||||
and id ~= full_name.popup_win
|
|
||||||
and win_config.focusable
|
|
||||||
and not win_config.hide
|
|
||||||
and not win_config.external
|
|
||||||
or false
|
|
||||||
end, win_ids)
|
end, win_ids)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---Find the first window in the tab that is not NvimTree.
|
||||||
|
---@return integer -1 if none available
|
||||||
|
local function first_win_id()
|
||||||
|
local selectable = usable_win_ids()
|
||||||
|
if #selectable > 0 then
|
||||||
|
return selectable[1]
|
||||||
|
else
|
||||||
|
return -1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
---Get user to pick a window in the tab that is not NvimTree.
|
---Get user to pick a window in the tab that is not NvimTree.
|
||||||
---@return integer|nil -- If a valid window was picked, return its id. If an
|
---@return integer|nil -- If a valid window was picked, return its id. If an
|
||||||
--- invalid window was picked / user canceled, return nil. If there are
|
--- invalid window was picked / user canceled, return nil. If there are
|
||||||
@ -75,14 +80,6 @@ local function pick_win_id()
|
|||||||
local win_map = {}
|
local win_map = {}
|
||||||
local laststatus = vim.o.laststatus
|
local laststatus = vim.o.laststatus
|
||||||
vim.o.laststatus = 2
|
vim.o.laststatus = 2
|
||||||
local fillchars = vim.opt.fillchars:get()
|
|
||||||
local stl = fillchars.stl
|
|
||||||
local stlnc = fillchars.stlnc
|
|
||||||
fillchars.stl = nil
|
|
||||||
fillchars.stlnc = nil
|
|
||||||
vim.opt.fillchars = fillchars
|
|
||||||
fillchars.stl = stl
|
|
||||||
fillchars.stlnc = stlnc
|
|
||||||
|
|
||||||
local tabpage = vim.api.nvim_get_current_tabpage()
|
local tabpage = vim.api.nvim_get_current_tabpage()
|
||||||
local win_ids = vim.api.nvim_tabpage_list_wins(tabpage)
|
local win_ids = vim.api.nvim_tabpage_list_wins(tabpage)
|
||||||
@ -182,7 +179,6 @@ local function pick_win_id()
|
|||||||
end
|
end
|
||||||
|
|
||||||
vim.o.laststatus = laststatus
|
vim.o.laststatus = laststatus
|
||||||
vim.opt.fillchars = fillchars
|
|
||||||
|
|
||||||
if not vim.tbl_contains(vim.split(M.window_picker.chars, ""), resp) then
|
if not vim.tbl_contains(vim.split(M.window_picker.chars, ""), resp) then
|
||||||
return
|
return
|
||||||
@ -198,15 +194,7 @@ local function open_file_in_tab(filename)
|
|||||||
if M.relative_path then
|
if M.relative_path then
|
||||||
filename = utils.path_relative(filename, vim.fn.getcwd())
|
filename = utils.path_relative(filename, vim.fn.getcwd())
|
||||||
end
|
end
|
||||||
vim.cmd.tabnew()
|
vim.cmd("tabe " .. vim.fn.fnameescape(filename))
|
||||||
vim.bo.bufhidden = "wipe"
|
|
||||||
-- Following vim.fn.tabnew the # buffer may be set to the tree buffer. There is no way to clear the # buffer via vim.fn.setreg as it requires a valid buffer. Clear # by setting it to a new temporary scratch buffer.
|
|
||||||
if utils.is_nvim_tree_buf(vim.fn.bufnr("#")) then
|
|
||||||
local tmpbuf = vim.api.nvim_create_buf(false, true)
|
|
||||||
vim.fn.setreg("#", tmpbuf)
|
|
||||||
vim.api.nvim_buf_delete(tmpbuf, { force = true })
|
|
||||||
end
|
|
||||||
vim.cmd.edit(vim.fn.fnameescape(filename))
|
|
||||||
end
|
end
|
||||||
|
|
||||||
local function drop(filename)
|
local function drop(filename)
|
||||||
@ -249,14 +237,9 @@ local function get_target_winid(mode)
|
|||||||
local target_winid
|
local target_winid
|
||||||
if not M.window_picker.enable or string.find(mode, "no_picker") then
|
if not M.window_picker.enable or string.find(mode, "no_picker") then
|
||||||
target_winid = lib.target_winid
|
target_winid = lib.target_winid
|
||||||
local usable_wins = usable_win_ids()
|
-- first available window
|
||||||
-- first available usable window
|
if not vim.tbl_contains(vim.api.nvim_tabpage_list_wins(0), target_winid) then
|
||||||
if not vim.tbl_contains(usable_wins, target_winid) then
|
target_winid = first_win_id()
|
||||||
if #usable_wins > 0 then
|
|
||||||
target_winid = usable_wins[1]
|
|
||||||
else
|
|
||||||
target_winid = -1
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
-- pick a window
|
-- pick a window
|
||||||
|
|||||||
@ -2,7 +2,6 @@ local utils = require("nvim-tree.utils")
|
|||||||
local core = require("nvim-tree.core")
|
local core = require("nvim-tree.core")
|
||||||
local Iterator = require("nvim-tree.iterators.node-iterator")
|
local Iterator = require("nvim-tree.iterators.node-iterator")
|
||||||
|
|
||||||
local FileNode = require("nvim-tree.node.file")
|
|
||||||
local DirectoryNode = require("nvim-tree.node.directory")
|
local DirectoryNode = require("nvim-tree.node.directory")
|
||||||
|
|
||||||
local M = {}
|
local M = {}
|
||||||
@ -24,30 +23,26 @@ local function buf_match()
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
---Collapse a node, root if nil
|
---@param keep_buffers boolean
|
||||||
---@param node Node?
|
function M.fn(keep_buffers)
|
||||||
---@param opts ApiCollapseOpts
|
|
||||||
local function collapse(node, opts)
|
|
||||||
local explorer = core.get_explorer()
|
local explorer = core.get_explorer()
|
||||||
if not explorer then
|
if not explorer then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
node = node or explorer
|
local node = explorer:get_node_at_cursor()
|
||||||
|
if not node then
|
||||||
local node_at_cursor = explorer:get_node_at_cursor()
|
|
||||||
if not node_at_cursor then
|
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
local matches = buf_match()
|
local matches = buf_match()
|
||||||
|
|
||||||
Iterator.builder({ node:is(FileNode) and node.parent or node:as(DirectoryNode) })
|
Iterator.builder(explorer.nodes)
|
||||||
:hidden()
|
:hidden()
|
||||||
:applier(function(n)
|
:applier(function(n)
|
||||||
local dir = n:as(DirectoryNode)
|
local dir = n:as(DirectoryNode)
|
||||||
if dir then
|
if dir then
|
||||||
dir.open = opts.keep_buffers == true and matches(dir.absolute_path)
|
dir.open = keep_buffers and matches(dir.absolute_path)
|
||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
:recursor(function(n)
|
:recursor(function(n)
|
||||||
@ -56,26 +51,7 @@ local function collapse(node, opts)
|
|||||||
:iterate()
|
:iterate()
|
||||||
|
|
||||||
explorer.renderer:draw()
|
explorer.renderer:draw()
|
||||||
explorer:focus_node_or_parent(node_at_cursor)
|
utils.focus_node_or_parent(node)
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
---@param opts ApiCollapseOpts|boolean|nil legacy -> opts.keep_buffers
|
|
||||||
function M.all(opts)
|
|
||||||
-- legacy arguments
|
|
||||||
if type(opts) == "boolean" then
|
|
||||||
opts = {
|
|
||||||
keep_buffers = opts,
|
|
||||||
}
|
|
||||||
end
|
|
||||||
|
|
||||||
collapse(nil, opts or {})
|
|
||||||
end
|
|
||||||
|
|
||||||
---@param node Node
|
|
||||||
---@param opts ApiCollapseOpts?
|
|
||||||
function M.node(node, opts)
|
|
||||||
collapse(node, opts or {})
|
|
||||||
end
|
end
|
||||||
|
|
||||||
return M
|
return M
|
||||||
95
lua/nvim-tree/actions/tree/modifiers/expand-all.lua
Normal file
95
lua/nvim-tree/actions/tree/modifiers/expand-all.lua
Normal file
@ -0,0 +1,95 @@
|
|||||||
|
local core = require("nvim-tree.core")
|
||||||
|
local Iterator = require("nvim-tree.iterators.node-iterator")
|
||||||
|
local notify = require("nvim-tree.notify")
|
||||||
|
|
||||||
|
local DirectoryNode = require("nvim-tree.node.directory")
|
||||||
|
|
||||||
|
local M = {}
|
||||||
|
|
||||||
|
---@param list string[]
|
||||||
|
---@return table
|
||||||
|
local function to_lookup_table(list)
|
||||||
|
local table = {}
|
||||||
|
for _, element in ipairs(list) do
|
||||||
|
table[element] = true
|
||||||
|
end
|
||||||
|
|
||||||
|
return table
|
||||||
|
end
|
||||||
|
|
||||||
|
---@param node DirectoryNode
|
||||||
|
local function expand(node)
|
||||||
|
node = node:last_group_node()
|
||||||
|
node.open = true
|
||||||
|
if #node.nodes == 0 then
|
||||||
|
core.get_explorer():expand(node)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
---@param expansion_count integer
|
||||||
|
---@param node Node
|
||||||
|
---@return boolean
|
||||||
|
local function should_expand(expansion_count, node)
|
||||||
|
local dir = node:as(DirectoryNode)
|
||||||
|
if not dir then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
local should_halt = expansion_count >= M.MAX_FOLDER_DISCOVERY
|
||||||
|
local should_exclude = M.EXCLUDE[dir.name]
|
||||||
|
return not should_halt and not dir.open and not should_exclude
|
||||||
|
end
|
||||||
|
|
||||||
|
local function gen_iterator()
|
||||||
|
local expansion_count = 0
|
||||||
|
|
||||||
|
return function(parent)
|
||||||
|
if parent.parent and parent.nodes and not parent.open then
|
||||||
|
expansion_count = expansion_count + 1
|
||||||
|
expand(parent)
|
||||||
|
end
|
||||||
|
|
||||||
|
Iterator.builder(parent.nodes)
|
||||||
|
:hidden()
|
||||||
|
:applier(function(node)
|
||||||
|
if should_expand(expansion_count, node) then
|
||||||
|
expansion_count = expansion_count + 1
|
||||||
|
node = node:as(DirectoryNode)
|
||||||
|
if node then
|
||||||
|
expand(node)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
:recursor(function(node)
|
||||||
|
return expansion_count < M.MAX_FOLDER_DISCOVERY and (node.group_next and { node.group_next } or (node.open and node.nodes))
|
||||||
|
end)
|
||||||
|
:iterate()
|
||||||
|
|
||||||
|
if expansion_count >= M.MAX_FOLDER_DISCOVERY then
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
---Expand the directory node or the root
|
||||||
|
---@param node Node
|
||||||
|
function M.fn(node)
|
||||||
|
local explorer = core.get_explorer()
|
||||||
|
local parent = node:as(DirectoryNode) or explorer
|
||||||
|
if not parent then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
if gen_iterator()(parent) then
|
||||||
|
notify.warn("expansion iteration was halted after " .. M.MAX_FOLDER_DISCOVERY .. " discovered folders")
|
||||||
|
end
|
||||||
|
if explorer then
|
||||||
|
explorer.renderer:draw()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function M.setup(opts)
|
||||||
|
M.MAX_FOLDER_DISCOVERY = opts.actions.expand_all.max_folder_discovery
|
||||||
|
M.EXCLUDE = to_lookup_table(opts.actions.expand_all.exclude)
|
||||||
|
end
|
||||||
|
|
||||||
|
return M
|
||||||
@ -1,166 +0,0 @@
|
|||||||
local core = require("nvim-tree.core")
|
|
||||||
local Iterator = require("nvim-tree.iterators.node-iterator")
|
|
||||||
local notify = require("nvim-tree.notify")
|
|
||||||
|
|
||||||
local FileNode = require("nvim-tree.node.file")
|
|
||||||
local DirectoryNode = require("nvim-tree.node.directory")
|
|
||||||
|
|
||||||
local M = {}
|
|
||||||
|
|
||||||
---@param list string[]
|
|
||||||
---@return table
|
|
||||||
local function to_lookup_table(list)
|
|
||||||
local table = {}
|
|
||||||
for _, element in ipairs(list) do
|
|
||||||
table[element] = true
|
|
||||||
end
|
|
||||||
|
|
||||||
return table
|
|
||||||
end
|
|
||||||
|
|
||||||
---@param node DirectoryNode
|
|
||||||
local function expand(node)
|
|
||||||
node = node:last_group_node()
|
|
||||||
node.open = true
|
|
||||||
if #node.nodes == 0 then
|
|
||||||
core.get_explorer():expand(node)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
---@param should_descend fun(expansion_count: integer, node: Node): boolean
|
|
||||||
---@return fun(expansion_count: integer, node: Node): boolean
|
|
||||||
local function limit_folder_discovery(should_descend)
|
|
||||||
return function(expansion_count, node)
|
|
||||||
local should_halt = expansion_count >= M.MAX_FOLDER_DISCOVERY
|
|
||||||
if should_halt then
|
|
||||||
notify.warn("expansion iteration was halted after " .. M.MAX_FOLDER_DISCOVERY .. " discovered folders")
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
|
|
||||||
return should_descend(expansion_count, node)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
---@param _ integer expansion_count
|
|
||||||
---@param node Node
|
|
||||||
---@return boolean
|
|
||||||
local function descend_until_empty(_, node)
|
|
||||||
|
|
||||||
local dir = node:as(DirectoryNode)
|
|
||||||
if not dir then
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
|
|
||||||
local should_exclude = M.EXCLUDE[dir.name]
|
|
||||||
return not should_exclude
|
|
||||||
end
|
|
||||||
|
|
||||||
---@param expansion_count integer
|
|
||||||
---@param node Node
|
|
||||||
---@param should_descend fun(expansion_count: integer, node: Node): boolean
|
|
||||||
---@return boolean
|
|
||||||
local function should_expand(expansion_count, node, should_descend)
|
|
||||||
local dir = node:as(DirectoryNode)
|
|
||||||
if not dir then
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
|
|
||||||
if not dir.open and should_descend(expansion_count, node) then
|
|
||||||
if #node.nodes == 0 then
|
|
||||||
core.get_explorer():expand(dir) -- populate node.group_next
|
|
||||||
end
|
|
||||||
|
|
||||||
if dir.group_next then
|
|
||||||
local expand_next = should_expand(expansion_count, dir.group_next, should_descend)
|
|
||||||
if expand_next then
|
|
||||||
dir.open = true
|
|
||||||
end
|
|
||||||
return expand_next
|
|
||||||
else
|
|
||||||
return true
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
---@param should_descend fun(expansion_count: integer, node: Node): boolean
|
|
||||||
---@return fun(node): any
|
|
||||||
local function gen_iterator(should_descend)
|
|
||||||
local expansion_count = 0
|
|
||||||
|
|
||||||
return function(parent)
|
|
||||||
if parent.parent and parent.nodes and not parent.open then
|
|
||||||
expansion_count = expansion_count + 1
|
|
||||||
expand(parent)
|
|
||||||
end
|
|
||||||
|
|
||||||
Iterator.builder(parent.nodes)
|
|
||||||
:hidden()
|
|
||||||
:applier(function(node)
|
|
||||||
if should_expand(expansion_count, node, should_descend) then
|
|
||||||
expansion_count = expansion_count + 1
|
|
||||||
node = node:as(DirectoryNode)
|
|
||||||
if node then
|
|
||||||
expand(node)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end)
|
|
||||||
:recursor(function(node)
|
|
||||||
if not should_descend(expansion_count, node) then
|
|
||||||
return nil
|
|
||||||
end
|
|
||||||
|
|
||||||
if node.group_next then
|
|
||||||
return { node.group_next }
|
|
||||||
end
|
|
||||||
|
|
||||||
if node.open and node.nodes then
|
|
||||||
return node.nodes
|
|
||||||
end
|
|
||||||
|
|
||||||
return nil
|
|
||||||
end)
|
|
||||||
:iterate()
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
---@param node Node?
|
|
||||||
---@param expand_opts ApiTreeExpandOpts?
|
|
||||||
local function expand_node(node, expand_opts)
|
|
||||||
if not node then
|
|
||||||
return
|
|
||||||
end
|
|
||||||
local descend_until = limit_folder_discovery((expand_opts and expand_opts.expand_until) or descend_until_empty)
|
|
||||||
gen_iterator(descend_until)(node)
|
|
||||||
|
|
||||||
local explorer = core.get_explorer()
|
|
||||||
if explorer then
|
|
||||||
explorer.renderer:draw()
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
---Expand the directory node or the root
|
|
||||||
---@param node Node
|
|
||||||
---@param expand_opts ApiTreeExpandOpts?
|
|
||||||
function M.all(node, expand_opts)
|
|
||||||
expand_node(node and node:as(DirectoryNode) or core.get_explorer(), expand_opts)
|
|
||||||
end
|
|
||||||
|
|
||||||
---Expand the directory node or parent node
|
|
||||||
---@param node Node
|
|
||||||
---@param expand_opts ApiTreeExpandOpts?
|
|
||||||
function M.node(node, expand_opts)
|
|
||||||
if not node then
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
expand_node(node:is(FileNode) and node.parent or node:as(DirectoryNode), expand_opts)
|
|
||||||
end
|
|
||||||
|
|
||||||
function M.setup(opts)
|
|
||||||
M.MAX_FOLDER_DISCOVERY = opts.actions.expand_all.max_folder_discovery
|
|
||||||
M.EXCLUDE = to_lookup_table(opts.actions.expand_all.exclude)
|
|
||||||
end
|
|
||||||
|
|
||||||
return M
|
|
||||||
@ -1,10 +1,10 @@
|
|||||||
local M = {}
|
local M = {}
|
||||||
|
|
||||||
M.collapse = require("nvim-tree.actions.tree.modifiers.collapse")
|
M.collapse_all = require("nvim-tree.actions.tree.modifiers.collapse-all")
|
||||||
M.expand = require("nvim-tree.actions.tree.modifiers.expand")
|
M.expand_all = require("nvim-tree.actions.tree.modifiers.expand-all")
|
||||||
|
|
||||||
function M.setup(opts)
|
function M.setup(opts)
|
||||||
M.expand.setup(opts)
|
M.expand_all.setup(opts)
|
||||||
end
|
end
|
||||||
|
|
||||||
return M
|
return M
|
||||||
|
|||||||
@ -182,16 +182,8 @@ Api.tree.get_nodes = wrap_explorer("get_nodes")
|
|||||||
|
|
||||||
Api.tree.find_file = wrap(actions.tree.find_file.fn)
|
Api.tree.find_file = wrap(actions.tree.find_file.fn)
|
||||||
Api.tree.search_node = wrap(actions.finders.search_node.fn)
|
Api.tree.search_node = wrap(actions.finders.search_node.fn)
|
||||||
|
Api.tree.collapse_all = wrap(actions.tree.modifiers.collapse_all.fn)
|
||||||
---@class ApiCollapseOpts
|
Api.tree.expand_all = wrap_node(actions.tree.modifiers.expand_all.fn)
|
||||||
---@field keep_buffers boolean|nil default false
|
|
||||||
|
|
||||||
Api.tree.collapse_all = wrap(actions.tree.modifiers.collapse.all)
|
|
||||||
|
|
||||||
---@class ApiTreeExpandOpts
|
|
||||||
---@field expand_until (fun(expansion_count: integer, node: Node): boolean)|nil
|
|
||||||
|
|
||||||
Api.tree.expand_all = wrap_node(actions.tree.modifiers.expand.all)
|
|
||||||
Api.tree.toggle_enable_filters = wrap_explorer_member("filters", "toggle")
|
Api.tree.toggle_enable_filters = wrap_explorer_member("filters", "toggle")
|
||||||
Api.tree.toggle_gitignore_filter = wrap_explorer_member_args("filters", "toggle", "git_ignored")
|
Api.tree.toggle_gitignore_filter = wrap_explorer_member_args("filters", "toggle", "git_ignored")
|
||||||
Api.tree.toggle_git_clean_filter = wrap_explorer_member_args("filters", "toggle", "git_clean")
|
Api.tree.toggle_git_clean_filter = wrap_explorer_member_args("filters", "toggle", "git_clean")
|
||||||
@ -230,46 +222,21 @@ Api.fs.copy.absolute_path = wrap_node(wrap_explorer_member("clipboard", "copy_ab
|
|||||||
Api.fs.copy.filename = wrap_node(wrap_explorer_member("clipboard", "copy_filename"))
|
Api.fs.copy.filename = wrap_node(wrap_explorer_member("clipboard", "copy_filename"))
|
||||||
Api.fs.copy.basename = wrap_node(wrap_explorer_member("clipboard", "copy_basename"))
|
Api.fs.copy.basename = wrap_node(wrap_explorer_member("clipboard", "copy_basename"))
|
||||||
Api.fs.copy.relative_path = wrap_node(wrap_explorer_member("clipboard", "copy_path"))
|
Api.fs.copy.relative_path = wrap_node(wrap_explorer_member("clipboard", "copy_path"))
|
||||||
---
|
|
||||||
---@class NodeEditOpts
|
|
||||||
---@field quit_on_open boolean|nil default false
|
|
||||||
---@field focus boolean|nil default true
|
|
||||||
|
|
||||||
---@param mode string
|
---@param mode string
|
||||||
---@param node Node
|
---@param node Node
|
||||||
---@param edit_opts NodeEditOpts?
|
local function edit(mode, node)
|
||||||
local function edit(mode, node, edit_opts)
|
|
||||||
local file_link = node:as(FileLinkNode)
|
local file_link = node:as(FileLinkNode)
|
||||||
local path = file_link and file_link.link_to or node.absolute_path
|
local path = file_link and file_link.link_to or node.absolute_path
|
||||||
local cur_tabpage = vim.api.nvim_get_current_tabpage()
|
|
||||||
|
|
||||||
actions.node.open_file.fn(mode, path)
|
actions.node.open_file.fn(mode, path)
|
||||||
|
|
||||||
edit_opts = edit_opts or {}
|
|
||||||
|
|
||||||
local mode_unsupported_quit_on_open = mode == "drop" or mode == "tab_drop" or mode == "edit_in_place"
|
|
||||||
if not mode_unsupported_quit_on_open and edit_opts.quit_on_open then
|
|
||||||
view.close(cur_tabpage)
|
|
||||||
end
|
|
||||||
|
|
||||||
local mode_unsupported_focus = mode == "drop" or mode == "tab_drop" or mode == "edit_in_place"
|
|
||||||
local focus = edit_opts.focus == nil or edit_opts.focus == true
|
|
||||||
if not mode_unsupported_focus and not focus then
|
|
||||||
-- if mode == "tabnew" a new tab will be opened and we need to focus back to the previous tab
|
|
||||||
if mode == "tabnew" then
|
|
||||||
vim.cmd(":tabprev")
|
|
||||||
end
|
|
||||||
view.focus()
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
---@param mode string
|
---@param mode string
|
||||||
---@param toggle_group boolean?
|
---@param toggle_group boolean?
|
||||||
---@return fun(node: Node, edit_opts: NodeEditOpts?)
|
---@return fun(node: Node)
|
||||||
local function open_or_expand_or_dir_up(mode, toggle_group)
|
local function open_or_expand_or_dir_up(mode, toggle_group)
|
||||||
---@param node Node
|
---@param node Node
|
||||||
---@param edit_opts NodeEditOpts?
|
return function(node)
|
||||||
return function(node, edit_opts)
|
|
||||||
local root = node:as(RootNode)
|
local root = node:as(RootNode)
|
||||||
local dir = node:as(DirectoryNode)
|
local dir = node:as(DirectoryNode)
|
||||||
|
|
||||||
@ -278,7 +245,7 @@ local function open_or_expand_or_dir_up(mode, toggle_group)
|
|||||||
elseif dir then
|
elseif dir then
|
||||||
dir:expand_or_collapse(toggle_group)
|
dir:expand_or_collapse(toggle_group)
|
||||||
elseif not toggle_group then
|
elseif not toggle_group then
|
||||||
edit(mode, node, edit_opts)
|
edit(mode, node)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -320,9 +287,6 @@ Api.node.navigate.diagnostics.prev_recursive = wrap_node(actions.moves.item.fn({
|
|||||||
Api.node.navigate.opened.next = wrap_node(actions.moves.item.fn({ where = "next", what = "opened" }))
|
Api.node.navigate.opened.next = wrap_node(actions.moves.item.fn({ where = "next", what = "opened" }))
|
||||||
Api.node.navigate.opened.prev = wrap_node(actions.moves.item.fn({ where = "prev", what = "opened" }))
|
Api.node.navigate.opened.prev = wrap_node(actions.moves.item.fn({ where = "prev", what = "opened" }))
|
||||||
|
|
||||||
Api.node.expand = wrap_node(actions.tree.modifiers.expand.node)
|
|
||||||
Api.node.collapse = wrap_node(actions.tree.modifiers.collapse.node)
|
|
||||||
|
|
||||||
---@class ApiNodeDeleteWipeBufferOpts
|
---@class ApiNodeDeleteWipeBufferOpts
|
||||||
---@field force boolean|nil default false
|
---@field force boolean|nil default false
|
||||||
|
|
||||||
|
|||||||
@ -55,7 +55,7 @@ function HighlightDisplay:render(bufnr, fmt, l)
|
|||||||
|
|
||||||
vim.api.nvim_buf_set_lines(bufnr, l, -1, true, { text })
|
vim.api.nvim_buf_set_lines(bufnr, l, -1, true, { text })
|
||||||
|
|
||||||
if vim.fn.has("nvim-0.11") == 1 and vim.hl and vim.hl.range then
|
if vim.fn.has("nvim-0.11") == 1 then
|
||||||
vim.hl.range(bufnr, namespace_hi_test_id, self.group, { l, 0 }, { l, #self.group, }, {})
|
vim.hl.range(bufnr, namespace_hi_test_id, self.group, { l, 0 }, { l, #self.group, }, {})
|
||||||
else
|
else
|
||||||
vim.api.nvim_buf_add_highlight(bufnr, -1, self.group, l, 0, #self.group) ---@diagnostic disable-line: deprecated
|
vim.api.nvim_buf_add_highlight(bufnr, -1, self.group, l, 0, #self.group) ---@diagnostic disable-line: deprecated
|
||||||
|
|||||||
@ -231,10 +231,7 @@ end
|
|||||||
function M.setup(opts)
|
function M.setup(opts)
|
||||||
M.enable = opts.diagnostics.enable
|
M.enable = opts.diagnostics.enable
|
||||||
M.debounce_delay = opts.diagnostics.debounce_delay
|
M.debounce_delay = opts.diagnostics.debounce_delay
|
||||||
M.severity = opts.diagnostics.diagnostic_opts and {
|
M.severity = opts.diagnostics.severity
|
||||||
min = vim.diagnostic.severity.HINT,
|
|
||||||
max = vim.diagnostic.severity.ERROR
|
|
||||||
} or opts.diagnostics.severity
|
|
||||||
|
|
||||||
if M.enable then
|
if M.enable then
|
||||||
log.line("diagnostics", "setup")
|
log.line("diagnostics", "setup")
|
||||||
|
|||||||
@ -8,7 +8,6 @@ M.Event = {
|
|||||||
Ready = "Ready",
|
Ready = "Ready",
|
||||||
WillRenameNode = "WillRenameNode",
|
WillRenameNode = "WillRenameNode",
|
||||||
NodeRenamed = "NodeRenamed",
|
NodeRenamed = "NodeRenamed",
|
||||||
TreePreOpen = "TreePreOpen",
|
|
||||||
TreeOpen = "TreeOpen",
|
TreeOpen = "TreeOpen",
|
||||||
TreeClose = "TreeClose",
|
TreeClose = "TreeClose",
|
||||||
WillCreateFile = "WillCreateFile",
|
WillCreateFile = "WillCreateFile",
|
||||||
@ -92,11 +91,6 @@ function M._dispatch_folder_removed(folder_name)
|
|||||||
dispatch(M.Event.FolderRemoved, { folder_name = folder_name })
|
dispatch(M.Event.FolderRemoved, { folder_name = folder_name })
|
||||||
end
|
end
|
||||||
|
|
||||||
--@private
|
|
||||||
function M._dispatch_on_tree_pre_open()
|
|
||||||
dispatch(M.Event.TreePreOpen, nil)
|
|
||||||
end
|
|
||||||
|
|
||||||
--@private
|
--@private
|
||||||
function M._dispatch_on_tree_open()
|
function M._dispatch_on_tree_open()
|
||||||
dispatch(M.Event.TreeOpen, nil)
|
dispatch(M.Event.TreeOpen, nil)
|
||||||
|
|||||||
@ -280,7 +280,7 @@ function Filters:toggle(type)
|
|||||||
local node = self.explorer:get_node_at_cursor()
|
local node = self.explorer:get_node_at_cursor()
|
||||||
self.explorer:reload_explorer()
|
self.explorer:reload_explorer()
|
||||||
if node then
|
if node then
|
||||||
self.explorer:focus_node_or_parent(node)
|
utils.focus_node_or_parent(node)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@ -101,19 +101,10 @@ function Explorer:create_autocmds()
|
|||||||
vim.api.nvim_create_autocmd("BufReadPost", {
|
vim.api.nvim_create_autocmd("BufReadPost", {
|
||||||
group = self.augroup_id,
|
group = self.augroup_id,
|
||||||
callback = function(data)
|
callback = function(data)
|
||||||
-- only handle normal files
|
if (self.filters.state.no_buffer or self.opts.highlight_opened_files ~= "none") and vim.bo[data.buf].buftype == "" then
|
||||||
if vim.bo[data.buf].buftype ~= "" then
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
if self.filters.state.no_buffer then
|
|
||||||
-- full reload is required to update the filter state
|
|
||||||
utils.debounce("Buf:filter_buffer_" .. self.uid_explorer, self.opts.view.debounce_delay, function()
|
utils.debounce("Buf:filter_buffer_" .. self.uid_explorer, self.opts.view.debounce_delay, function()
|
||||||
self:reload_explorer()
|
self:reload_explorer()
|
||||||
end)
|
end)
|
||||||
elseif self.opts.renderer.highlight_opened_files ~= "none" then
|
|
||||||
-- draw to update opened highlight
|
|
||||||
self.renderer:draw()
|
|
||||||
end
|
end
|
||||||
end,
|
end,
|
||||||
})
|
})
|
||||||
@ -122,21 +113,10 @@ function Explorer:create_autocmds()
|
|||||||
vim.api.nvim_create_autocmd("BufUnload", {
|
vim.api.nvim_create_autocmd("BufUnload", {
|
||||||
group = self.augroup_id,
|
group = self.augroup_id,
|
||||||
callback = function(data)
|
callback = function(data)
|
||||||
-- only handle normal files
|
if (self.filters.state.no_buffer or self.opts.highlight_opened_files ~= "none") and vim.bo[data.buf].buftype == "" then
|
||||||
if vim.bo[data.buf].buftype ~= "" then
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
if self.filters.state.no_buffer then
|
|
||||||
-- full reload is required to update the filter state
|
|
||||||
utils.debounce("Buf:filter_buffer_" .. self.uid_explorer, self.opts.view.debounce_delay, function()
|
utils.debounce("Buf:filter_buffer_" .. self.uid_explorer, self.opts.view.debounce_delay, function()
|
||||||
self:reload_explorer()
|
self:reload_explorer()
|
||||||
end)
|
end)
|
||||||
elseif self.opts.renderer.highlight_opened_files ~= "none" then
|
|
||||||
-- draw to update opened highlight; must be delayed as the buffer is still loaded during BufUnload
|
|
||||||
vim.schedule(function()
|
|
||||||
self.renderer:draw()
|
|
||||||
end)
|
|
||||||
end
|
end
|
||||||
end,
|
end,
|
||||||
})
|
})
|
||||||
@ -234,9 +214,8 @@ function Explorer:reload(node, project)
|
|||||||
end
|
end
|
||||||
|
|
||||||
local abs = utils.path_join({ cwd, name })
|
local abs = utils.path_join({ cwd, name })
|
||||||
|
---@type uv.fs_stat.result|nil
|
||||||
-- path incorrectly specified as an integer
|
local stat = vim.loop.fs_lstat(abs)
|
||||||
local stat = vim.loop.fs_lstat(abs) ---@diagnostic disable-line param-type-mismatch
|
|
||||||
|
|
||||||
local filter_reason = self.filters:should_filter_as_reason(abs, stat, filter_status)
|
local filter_reason = self.filters:should_filter_as_reason(abs, stat, filter_status)
|
||||||
if filter_reason == FILTER_REASON.none then
|
if filter_reason == FILTER_REASON.none then
|
||||||
@ -394,9 +373,8 @@ function Explorer:populate_children(handle, cwd, node, project, parent)
|
|||||||
if Watcher.is_fs_event_capable(abs) then
|
if Watcher.is_fs_event_capable(abs) then
|
||||||
local profile = log.profile_start("populate_children %s", abs)
|
local profile = log.profile_start("populate_children %s", abs)
|
||||||
|
|
||||||
-- path incorrectly specified as an integer
|
---@type uv.fs_stat.result|nil
|
||||||
local stat = vim.loop.fs_lstat(abs) ---@diagnostic disable-line param-type-mismatch
|
local stat = vim.loop.fs_lstat(abs)
|
||||||
|
|
||||||
local filter_reason = parent.filters:should_filter_as_reason(abs, stat, filter_status)
|
local filter_reason = parent.filters:should_filter_as_reason(abs, stat, filter_status)
|
||||||
if filter_reason == FILTER_REASON.none and not nodes_by_path[abs] then
|
if filter_reason == FILTER_REASON.none and not nodes_by_path[abs] then
|
||||||
local child = node_factory.create({
|
local child = node_factory.create({
|
||||||
@ -411,9 +389,9 @@ function Explorer:populate_children(handle, cwd, node, project, parent)
|
|||||||
nodes_by_path[child.absolute_path] = true
|
nodes_by_path[child.absolute_path] = true
|
||||||
child:update_git_status(node_ignored, project)
|
child:update_git_status(node_ignored, project)
|
||||||
end
|
end
|
||||||
elseif node.hidden_stats then
|
else
|
||||||
for reason, value in pairs(FILTER_REASON) do
|
for reason, value in pairs(FILTER_REASON) do
|
||||||
if filter_reason == value and type(node.hidden_stats[reason]) == "number" then
|
if filter_reason == value then
|
||||||
node.hidden_stats[reason] = node.hidden_stats[reason] + 1
|
node.hidden_stats[reason] = node.hidden_stats[reason] + 1
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -527,7 +505,7 @@ function Explorer:get_node_at_cursor()
|
|||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
return self:get_nodes_by_line(core.get_nodes_starting_line())[cursor[1]]
|
return utils.get_nodes_by_line(self.nodes, core.get_nodes_starting_line())[cursor[1]]
|
||||||
end
|
end
|
||||||
|
|
||||||
function Explorer:place_cursor_on_node()
|
function Explorer:place_cursor_on_node()
|
||||||
@ -551,114 +529,6 @@ function Explorer:place_cursor_on_node()
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Find the line number of a node.
|
|
||||||
---@param node Node?
|
|
||||||
---@return integer -1 not found
|
|
||||||
function Explorer:find_node_line(node)
|
|
||||||
if not node then
|
|
||||||
return -1
|
|
||||||
end
|
|
||||||
|
|
||||||
local first_node_line = core.get_nodes_starting_line()
|
|
||||||
local nodes_by_line = self:get_nodes_by_line(first_node_line)
|
|
||||||
local iter_start, iter_end = first_node_line, #nodes_by_line
|
|
||||||
|
|
||||||
for line = iter_start, iter_end, 1 do
|
|
||||||
if nodes_by_line[line] == node then
|
|
||||||
return line
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
return -1
|
|
||||||
end
|
|
||||||
|
|
||||||
-- get the node in the tree state depending on the absolute path of the node
|
|
||||||
-- (grouped or hidden too)
|
|
||||||
---@param path string
|
|
||||||
---@return Node|nil
|
|
||||||
---@return number|nil
|
|
||||||
function Explorer:get_node_from_path(path)
|
|
||||||
if self.absolute_path == path then
|
|
||||||
return self
|
|
||||||
end
|
|
||||||
|
|
||||||
return Iterator.builder(self.nodes)
|
|
||||||
:hidden()
|
|
||||||
:matcher(function(node)
|
|
||||||
return node.absolute_path == path or node.link_to == path
|
|
||||||
end)
|
|
||||||
:recursor(function(node)
|
|
||||||
if node.group_next then
|
|
||||||
return { node.group_next }
|
|
||||||
end
|
|
||||||
if node.nodes then
|
|
||||||
return node.nodes
|
|
||||||
end
|
|
||||||
end)
|
|
||||||
:iterate()
|
|
||||||
end
|
|
||||||
|
|
||||||
---Focus node passed as parameter if visible, otherwise focus first visible parent.
|
|
||||||
---If none of the parents is visible focus root.
|
|
||||||
---If node is nil do nothing.
|
|
||||||
---@param node Node? node to focus
|
|
||||||
function Explorer:focus_node_or_parent(node)
|
|
||||||
while node do
|
|
||||||
local found_node, i = self:find_node(function(node_)
|
|
||||||
return node_.absolute_path == node.absolute_path
|
|
||||||
end)
|
|
||||||
|
|
||||||
if found_node or node.parent == nil then
|
|
||||||
view.set_cursor({ i + 1, 1 })
|
|
||||||
break
|
|
||||||
end
|
|
||||||
|
|
||||||
node = node.parent
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Get the node and index of the node from the tree that matches the predicate.
|
|
||||||
--- The explored nodes are those displayed on the view.
|
|
||||||
---@param fn fun(node: Node): boolean
|
|
||||||
---@return table|nil
|
|
||||||
---@return number
|
|
||||||
function Explorer:find_node(fn)
|
|
||||||
local node, i = Iterator.builder(self.nodes)
|
|
||||||
:matcher(fn)
|
|
||||||
:recursor(function(node)
|
|
||||||
return node.group_next and { node.group_next } or (node.open and #node.nodes > 0 and node.nodes)
|
|
||||||
end)
|
|
||||||
:iterate()
|
|
||||||
i = view.is_root_folder_visible() and i or i - 1
|
|
||||||
if node and node.explorer.live_filter.filter then
|
|
||||||
i = i + 1
|
|
||||||
end
|
|
||||||
return node, i
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Return visible nodes indexed by line
|
|
||||||
---@param line_start number
|
|
||||||
---@return table
|
|
||||||
function Explorer:get_nodes_by_line(line_start)
|
|
||||||
local nodes_by_line = {}
|
|
||||||
local line = line_start
|
|
||||||
|
|
||||||
Iterator.builder(self.nodes)
|
|
||||||
:applier(function(node)
|
|
||||||
if node.group_next then
|
|
||||||
return
|
|
||||||
end
|
|
||||||
nodes_by_line[line] = node
|
|
||||||
line = line + 1
|
|
||||||
end)
|
|
||||||
:recursor(function(node)
|
|
||||||
return node.group_next and { node.group_next } or (node.open and #node.nodes > 0 and node.nodes)
|
|
||||||
end)
|
|
||||||
:iterate()
|
|
||||||
|
|
||||||
return nodes_by_line
|
|
||||||
end
|
|
||||||
|
|
||||||
---Api.tree.get_nodes
|
---Api.tree.get_nodes
|
||||||
---@return nvim_tree.api.Node
|
---@return nvim_tree.api.Node
|
||||||
function Explorer:get_nodes()
|
function Explorer:get_nodes()
|
||||||
|
|||||||
@ -188,10 +188,8 @@ local function create_overlay(self)
|
|||||||
|
|
||||||
if vim.fn.has("nvim-0.10") == 1 then
|
if vim.fn.has("nvim-0.10") == 1 then
|
||||||
vim.api.nvim_set_option_value("modifiable", true, { buf = overlay_bufnr })
|
vim.api.nvim_set_option_value("modifiable", true, { buf = overlay_bufnr })
|
||||||
vim.api.nvim_set_option_value("filetype", "NvimTreeFilter", { buf = overlay_bufnr })
|
|
||||||
else
|
else
|
||||||
vim.api.nvim_buf_set_option(overlay_bufnr, "modifiable", true) ---@diagnostic disable-line: deprecated
|
vim.api.nvim_buf_set_option(overlay_bufnr, "modifiable", true) ---@diagnostic disable-line: deprecated
|
||||||
vim.api.nvim_buf_set_option(overlay_bufnr, "filetype", "NvimTreeFilter") ---@diagnostic disable-line: deprecated
|
|
||||||
end
|
end
|
||||||
|
|
||||||
vim.api.nvim_buf_set_lines(overlay_bufnr, 0, -1, false, { self.filter })
|
vim.api.nvim_buf_set_lines(overlay_bufnr, 0, -1, false, { self.filter })
|
||||||
@ -222,9 +220,9 @@ function LiveFilter:clear_filter()
|
|||||||
self.explorer.renderer:draw()
|
self.explorer.renderer:draw()
|
||||||
|
|
||||||
if node then
|
if node then
|
||||||
self.explorer:focus_node_or_parent(node)
|
utils.focus_file(node.absolute_path)
|
||||||
elseif last_node then
|
elseif last_node then
|
||||||
self.explorer:focus_node_or_parent(last_node)
|
utils.focus_file(last_node.absolute_path)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@ -193,10 +193,9 @@ function M.get_toplevel(path)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- attempt to fetch toplevel, cache if untracked
|
-- attempt to fetch toplevel
|
||||||
local toplevel, git_dir = git_utils.get_toplevel(path)
|
local toplevel, git_dir = git_utils.get_toplevel(path)
|
||||||
if not toplevel or not git_dir then
|
if not toplevel or not git_dir then
|
||||||
M._toplevels_by_path[path] = false
|
|
||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
local toplevel_norm = vim.fn.fnamemodify(toplevel, ":p")
|
local toplevel_norm = vim.fn.fnamemodify(toplevel, ":p")
|
||||||
@ -233,13 +232,7 @@ local function reload_tree_at(toplevel)
|
|||||||
end
|
end
|
||||||
|
|
||||||
log.line("watcher", "git event executing '%s'", toplevel)
|
log.line("watcher", "git event executing '%s'", toplevel)
|
||||||
|
local root_node = utils.get_node_from_path(toplevel)
|
||||||
local explorer = require("nvim-tree.core").get_explorer()
|
|
||||||
if not explorer then
|
|
||||||
return nil
|
|
||||||
end
|
|
||||||
|
|
||||||
local root_node = explorer:get_node_from_path(toplevel)
|
|
||||||
if not root_node then
|
if not root_node then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
@ -258,7 +251,7 @@ local function reload_tree_at(toplevel)
|
|||||||
end)
|
end)
|
||||||
:iterate()
|
:iterate()
|
||||||
|
|
||||||
explorer.renderer:draw()
|
root_node.explorer.renderer:draw()
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@ -5,19 +5,6 @@ local M = {
|
|||||||
use_cygpath = false,
|
use_cygpath = false,
|
||||||
}
|
}
|
||||||
|
|
||||||
--- Execute system command
|
|
||||||
---@param cmd string[]
|
|
||||||
---@return string stdout
|
|
||||||
---@return integer exit code
|
|
||||||
local function system(cmd)
|
|
||||||
if vim.fn.has("nvim-0.10") == 1 then
|
|
||||||
local obj = vim.system(cmd):wait()
|
|
||||||
return obj.stdout or "", obj.code
|
|
||||||
else
|
|
||||||
return vim.fn.system(cmd), vim.v.shell_error
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Retrieve the git toplevel directory
|
--- Retrieve the git toplevel directory
|
||||||
---@param cwd string path
|
---@param cwd string path
|
||||||
---@return string|nil toplevel absolute path
|
---@return string|nil toplevel absolute path
|
||||||
@ -29,12 +16,12 @@ function M.get_toplevel(cwd)
|
|||||||
local cmd = { "git", "-C", cwd, "rev-parse", "--show-toplevel", "--absolute-git-dir" }
|
local cmd = { "git", "-C", cwd, "rev-parse", "--show-toplevel", "--absolute-git-dir" }
|
||||||
log.line("git", "%s", table.concat(cmd, " "))
|
log.line("git", "%s", table.concat(cmd, " "))
|
||||||
|
|
||||||
local out, exitCode = system(cmd)
|
local out = vim.fn.system(cmd)
|
||||||
|
|
||||||
log.raw("git", out)
|
log.raw("git", out)
|
||||||
log.profile_end(profile)
|
log.profile_end(profile)
|
||||||
|
|
||||||
if exitCode ~= 0 or not out or #out == 0 or out:match("fatal") then
|
if vim.v.shell_error ~= 0 or not out or #out == 0 or out:match("fatal") then
|
||||||
return nil, nil
|
return nil, nil
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -86,7 +73,7 @@ function M.should_show_untracked(cwd)
|
|||||||
local cmd = { "git", "-C", cwd, "config", "status.showUntrackedFiles" }
|
local cmd = { "git", "-C", cwd, "config", "status.showUntrackedFiles" }
|
||||||
log.line("git", table.concat(cmd, " "))
|
log.line("git", table.concat(cmd, " "))
|
||||||
|
|
||||||
local has_untracked = system(cmd)
|
local has_untracked = vim.fn.system(cmd)
|
||||||
|
|
||||||
log.raw("git", has_untracked)
|
log.raw("git", has_untracked)
|
||||||
log.profile_end(profile)
|
log.profile_end(profile)
|
||||||
|
|||||||
@ -190,7 +190,7 @@ local function open()
|
|||||||
|
|
||||||
-- highlight it
|
-- highlight it
|
||||||
for _, args in ipairs(hl_range_args) do
|
for _, args in ipairs(hl_range_args) do
|
||||||
if vim.fn.has("nvim-0.11") == 1 and vim.hl and vim.hl.range then
|
if vim.fn.has("nvim-0.11") == 1 then
|
||||||
vim.hl.range(M.bufnr, namespace_help_id, args.higroup, args.start, args.finish, {})
|
vim.hl.range(M.bufnr, namespace_help_id, args.higroup, args.start, args.finish, {})
|
||||||
else
|
else
|
||||||
vim.api.nvim_buf_add_highlight(M.bufnr, -1, args.higroup, args.start[1], args.start[2], args.finish[2]) ---@diagnostic disable-line: deprecated
|
vim.api.nvim_buf_add_highlight(M.bufnr, -1, args.higroup, args.start[1], args.start[2], args.finish[2]) ---@diagnostic disable-line: deprecated
|
||||||
|
|||||||
@ -96,7 +96,7 @@ function M.default_on_attach(bufnr)
|
|||||||
vim.keymap.set("n", "S", api.tree.search_node, opts("Search"))
|
vim.keymap.set("n", "S", api.tree.search_node, opts("Search"))
|
||||||
vim.keymap.set("n", "u", api.fs.rename_full, opts("Rename: Full Path"))
|
vim.keymap.set("n", "u", api.fs.rename_full, opts("Rename: Full Path"))
|
||||||
vim.keymap.set("n", "U", api.tree.toggle_custom_filter, opts("Toggle Filter: Hidden"))
|
vim.keymap.set("n", "U", api.tree.toggle_custom_filter, opts("Toggle Filter: Hidden"))
|
||||||
vim.keymap.set("n", "W", api.tree.collapse_all, opts("Collapse All"))
|
vim.keymap.set("n", "W", api.tree.collapse_all, opts("Collapse"))
|
||||||
vim.keymap.set("n", "x", api.fs.cut, opts("Cut"))
|
vim.keymap.set("n", "x", api.fs.cut, opts("Cut"))
|
||||||
vim.keymap.set("n", "y", api.fs.copy.filename, opts("Copy Name"))
|
vim.keymap.set("n", "y", api.fs.copy.filename, opts("Copy Name"))
|
||||||
vim.keymap.set("n", "Y", api.fs.copy.relative_path, opts("Copy Relative Path"))
|
vim.keymap.set("n", "Y", api.fs.copy.relative_path, opts("Copy Relative Path"))
|
||||||
|
|||||||
@ -1,74 +1,27 @@
|
|||||||
|
local utils = require("nvim-tree.utils")
|
||||||
local notify = require("nvim-tree.notify")
|
local notify = require("nvim-tree.notify")
|
||||||
|
|
||||||
local M = {}
|
local M = {}
|
||||||
|
|
||||||
--- Create empty sub-tables if not present
|
|
||||||
---@param tbl table to create empty inside of
|
|
||||||
---@param path string dot separated string of sub-tables
|
|
||||||
---@return table deepest sub-table
|
|
||||||
local function create(tbl, path)
|
|
||||||
local t = tbl
|
|
||||||
for s in string.gmatch(path, "([^%.]+)%.*") do
|
|
||||||
if t[s] == nil then
|
|
||||||
t[s] = {}
|
|
||||||
end
|
|
||||||
t = t[s]
|
|
||||||
end
|
|
||||||
|
|
||||||
return t
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Move a value from src to dst if value is nil on dst.
|
|
||||||
--- Remove value from src
|
|
||||||
---@param src table to copy from
|
|
||||||
---@param src_path string dot separated string of sub-tables
|
|
||||||
---@param src_pos string value pos
|
|
||||||
---@param dst table to copy to
|
|
||||||
---@param dst_path string dot separated string of sub-tables, created when missing
|
|
||||||
---@param dst_pos string value pos
|
|
||||||
---@param remove boolean
|
|
||||||
local function move(src, src_path, src_pos, dst, dst_path, dst_pos, remove)
|
|
||||||
for pos in string.gmatch(src_path, "([^%.]+)%.*") do
|
|
||||||
if src[pos] and type(src[pos]) == "table" then
|
|
||||||
src = src[pos]
|
|
||||||
else
|
|
||||||
return
|
|
||||||
end
|
|
||||||
end
|
|
||||||
local src_val = src[src_pos]
|
|
||||||
if src_val == nil then
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
dst = create(dst, dst_path)
|
|
||||||
if dst[dst_pos] == nil then
|
|
||||||
dst[dst_pos] = src_val
|
|
||||||
end
|
|
||||||
|
|
||||||
if remove then
|
|
||||||
src[src_pos] = nil
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
-- silently move, please add to help nvim-tree-legacy-opts
|
-- silently move, please add to help nvim-tree-legacy-opts
|
||||||
local function refactored(opts)
|
local function refactored(opts)
|
||||||
-- 2022/06/20
|
-- 2022/06/20
|
||||||
move(opts, "update_focused_file", "update_cwd", opts, "update_focused_file", "update_root", true)
|
utils.move_missing_val(opts, "update_focused_file", "update_cwd", opts, "update_focused_file", "update_root", true)
|
||||||
move(opts, "", "update_cwd", opts, "", "sync_root_with_cwd", true)
|
utils.move_missing_val(opts, "", "update_cwd", opts, "", "sync_root_with_cwd", true)
|
||||||
|
|
||||||
-- 2022/11/07
|
-- 2022/11/07
|
||||||
move(opts, "", "open_on_tab", opts, "tab.sync", "open", false)
|
utils.move_missing_val(opts, "", "open_on_tab", opts, "tab.sync", "open", false)
|
||||||
move(opts, "", "open_on_tab", opts, "tab.sync", "close", true)
|
utils.move_missing_val(opts, "", "open_on_tab", opts, "tab.sync", "close", true)
|
||||||
move(opts, "", "ignore_buf_on_tab_change", opts, "tab.sync", "ignore", true)
|
utils.move_missing_val(opts, "", "ignore_buf_on_tab_change", opts, "tab.sync", "ignore", true)
|
||||||
|
|
||||||
-- 2022/11/22
|
-- 2022/11/22
|
||||||
move(opts, "renderer", "root_folder_modifier", opts, "renderer", "root_folder_label", true)
|
utils.move_missing_val(opts, "renderer", "root_folder_modifier", opts, "renderer", "root_folder_label", true)
|
||||||
|
|
||||||
-- 2023/01/01
|
-- 2023/01/01
|
||||||
move(opts, "update_focused_file", "debounce_delay", opts, "view", "debounce_delay", true)
|
utils.move_missing_val(opts, "update_focused_file", "debounce_delay", opts, "view", "debounce_delay", true)
|
||||||
|
|
||||||
-- 2023/01/08
|
-- 2023/01/08
|
||||||
move(opts, "trash", "require_confirm", opts, "ui.confirm", "trash", true)
|
utils.move_missing_val(opts, "trash", "require_confirm", opts, "ui.confirm", "trash", true)
|
||||||
|
|
||||||
-- 2023/01/15
|
-- 2023/01/15
|
||||||
if type(opts.view) == "table" and opts.view.adaptive_size ~= nil then
|
if type(opts.view) == "table" and opts.view.adaptive_size ~= nil then
|
||||||
@ -82,13 +35,13 @@ local function refactored(opts)
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- 2023/07/15
|
-- 2023/07/15
|
||||||
move(opts, "", "sort_by", opts, "sort", "sorter", true)
|
utils.move_missing_val(opts, "", "sort_by", opts, "sort", "sorter", true)
|
||||||
|
|
||||||
-- 2023/07/16
|
-- 2023/07/16
|
||||||
move(opts, "git", "ignore", opts, "filters", "git_ignored", true)
|
utils.move_missing_val(opts, "git", "ignore", opts, "filters", "git_ignored", true)
|
||||||
|
|
||||||
-- 2023/08/26
|
-- 2023/08/26
|
||||||
move(opts, "renderer.icons", "webdev_colors", opts, "renderer.icons.web_devicons.file", "color", true)
|
utils.move_missing_val(opts, "renderer.icons", "webdev_colors", opts, "renderer.icons.web_devicons.file", "color", true)
|
||||||
|
|
||||||
-- 2023/10/08
|
-- 2023/10/08
|
||||||
if type(opts.renderer) == "table" and type(opts.renderer.highlight_diagnostics) == "boolean" then
|
if type(opts.renderer) == "table" and type(opts.renderer.highlight_diagnostics) == "boolean" then
|
||||||
@ -106,14 +59,7 @@ local function refactored(opts)
|
|||||||
opts.update_focused_file.update_root = { enable = opts.update_focused_file.update_root }
|
opts.update_focused_file.update_root = { enable = opts.update_focused_file.update_root }
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
move(opts, "update_focused_file", "ignore_list", opts, "update_focused_file.update_root", "ignore_list", true)
|
utils.move_missing_val(opts, "update_focused_file", "ignore_list", opts, "update_focused_file.update_root", "ignore_list", true)
|
||||||
|
|
||||||
-- 2025/04/30
|
|
||||||
if opts.renderer and opts.renderer.icons and type(opts.renderer.icons.padding) == "string" then
|
|
||||||
local icons_padding = opts.renderer.icons.padding
|
|
||||||
opts.renderer.icons.padding = {}
|
|
||||||
opts.renderer.icons.padding.icon = icons_padding
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
local function deprecated(opts)
|
local function deprecated(opts)
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
local view = require("nvim-tree.view")
|
local view = require("nvim-tree.view")
|
||||||
local core = require("nvim-tree.core")
|
local core = require("nvim-tree.core")
|
||||||
|
local events = require("nvim-tree.events")
|
||||||
local notify = require("nvim-tree.notify")
|
local notify = require("nvim-tree.notify")
|
||||||
|
|
||||||
---@class LibOpenOpts
|
---@class LibOpenOpts
|
||||||
@ -129,6 +130,7 @@ function M.open(opts)
|
|||||||
open_view_and_draw()
|
open_view_and_draw()
|
||||||
end
|
end
|
||||||
view.restore_tab_state()
|
view.restore_tab_state()
|
||||||
|
events._dispatch_on_tree_open()
|
||||||
end
|
end
|
||||||
|
|
||||||
function M.setup(opts)
|
function M.setup(opts)
|
||||||
|
|||||||
@ -227,9 +227,9 @@ function Marks:navigate(up)
|
|||||||
end
|
end
|
||||||
|
|
||||||
if up then
|
if up then
|
||||||
self.explorer:focus_node_or_parent(prev or last)
|
utils.focus_node_or_parent(prev or last)
|
||||||
else
|
else
|
||||||
self.explorer:focus_node_or_parent(next or first)
|
utils.focus_node_or_parent(next or first)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -263,7 +263,7 @@ function Marks:navigate_select()
|
|||||||
if node and not node:is(DirectoryNode) and not utils.get_win_buf_from_path(node.absolute_path) then
|
if node and not node:is(DirectoryNode) and not utils.get_win_buf_from_path(node.absolute_path) then
|
||||||
open_file.fn("edit", node.absolute_path)
|
open_file.fn("edit", node.absolute_path)
|
||||||
elseif node then
|
elseif node then
|
||||||
self.explorer:focus_node_or_parent(node)
|
utils.focus_file(node.absolute_path)
|
||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
|
|||||||
@ -58,18 +58,18 @@ local Builder = Class:extend()
|
|||||||
---@protected
|
---@protected
|
||||||
---@param args BuilderArgs
|
---@param args BuilderArgs
|
||||||
function Builder:new(args)
|
function Builder:new(args)
|
||||||
self.explorer = args.explorer
|
self.explorer = args.explorer
|
||||||
self.index = 0
|
self.index = 0
|
||||||
self.depth = 0
|
self.depth = 0
|
||||||
self.hl_range_args = {}
|
self.hl_range_args = {}
|
||||||
self.combined_groups = {}
|
self.combined_groups = {}
|
||||||
self.lines = {}
|
self.lines = {}
|
||||||
self.markers = {}
|
self.markers = {}
|
||||||
self.signs = {}
|
self.signs = {}
|
||||||
self.extmarks = {}
|
self.extmarks = {}
|
||||||
self.virtual_lines = {}
|
self.virtual_lines = {}
|
||||||
self.decorators = {}
|
self.decorators = {}
|
||||||
self.hidden_display = Builder:setup_hidden_display_function(self.explorer.opts)
|
self.hidden_display = Builder:setup_hidden_display_function(self.explorer.opts)
|
||||||
|
|
||||||
-- instantiate all the builtin and user decorator instances
|
-- instantiate all the builtin and user decorator instances
|
||||||
local builtin, user
|
local builtin, user
|
||||||
@ -101,7 +101,7 @@ end
|
|||||||
---@param end_ number|nil
|
---@param end_ number|nil
|
||||||
function Builder:insert_highlight(groups, start, end_)
|
function Builder:insert_highlight(groups, start, end_)
|
||||||
for _, higroup in ipairs(groups) do
|
for _, higroup in ipairs(groups) do
|
||||||
table.insert(self.hl_range_args, { higroup = higroup, start = { self.index, start }, finish = { self.index, end_ or -1 } })
|
table.insert(self.hl_range_args, { higroup = higroup, start = { self.index, start, }, finish = { self.index, end_ or -1, } })
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -135,12 +135,12 @@ end
|
|||||||
function Builder:format_line(indent_markers, arrows, icon, name, node)
|
function Builder:format_line(indent_markers, arrows, icon, name, node)
|
||||||
local added_len = 0
|
local added_len = 0
|
||||||
local function add_to_end(t1, t2)
|
local function add_to_end(t1, t2)
|
||||||
if not t2 or vim.tbl_isempty(t2) then
|
if not t2 then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
for _, v in ipairs(t2) do
|
for _, v in ipairs(t2) do
|
||||||
if added_len > 0 then
|
if added_len > 0 then
|
||||||
table.insert(t1, { str = self.explorer.opts.renderer.icons.padding.icon })
|
table.insert(t1, { str = self.explorer.opts.renderer.icons.padding })
|
||||||
end
|
end
|
||||||
table.insert(t1, v)
|
table.insert(t1, v)
|
||||||
end
|
end
|
||||||
@ -321,7 +321,7 @@ function Builder:add_hidden_count_string(node, idx, num_children)
|
|||||||
-- if we change the traversal, we might need to sort by depth before rendering `self.virtual_lines`
|
-- if we change the traversal, we might need to sort by depth before rendering `self.virtual_lines`
|
||||||
-- to maintain proper ordering of parent and child folder hidden count info.
|
-- to maintain proper ordering of parent and child folder hidden count info.
|
||||||
table.insert(self.virtual_lines[line_nr], {
|
table.insert(self.virtual_lines[line_nr], {
|
||||||
{ indent_string, indent_markers.hl },
|
{ indent_string, indent_markers.hl },
|
||||||
{ string.rep(indent_padding, (node.parent == nil and 0 or 1)) .. hidden_count_string, "NvimTreeHiddenDisplay" },
|
{ string.rep(indent_padding, (node.parent == nil and 0 or 1)) .. hidden_count_string, "NvimTreeHiddenDisplay" },
|
||||||
})
|
})
|
||||||
end
|
end
|
||||||
@ -381,28 +381,8 @@ end
|
|||||||
function Builder:build_header()
|
function Builder:build_header()
|
||||||
if view.is_root_folder_visible(self.explorer.absolute_path) then
|
if view.is_root_folder_visible(self.explorer.absolute_path) then
|
||||||
local root_name = self:format_root_name(self.explorer.opts.renderer.root_folder_label)
|
local root_name = self:format_root_name(self.explorer.opts.renderer.root_folder_label)
|
||||||
|
table.insert(self.lines, root_name)
|
||||||
-- Pad to window width so the highlight spans the whole row.
|
self:insert_highlight({ "NvimTreeRootFolder" }, 0, string.len(root_name))
|
||||||
local win = view.get_winnr()
|
|
||||||
local width = 0
|
|
||||||
if win and vim.api.nvim_win_is_valid(win) then
|
|
||||||
width = vim.api.nvim_win_get_width(win)
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Use display width for proper padding with Nerd Font / wide glyphs.
|
|
||||||
local name_display_w = vim.fn.strdisplaywidth(root_name)
|
|
||||||
local pad = 0
|
|
||||||
if width and width > name_display_w then
|
|
||||||
pad = width - name_display_w
|
|
||||||
end
|
|
||||||
|
|
||||||
local padded_root = pad > 0 and (root_name .. string.rep(" ", pad)) or root_name
|
|
||||||
|
|
||||||
table.insert(self.lines, padded_root)
|
|
||||||
-- Highlight the entire padded string (covers the full visible row)
|
|
||||||
self:insert_highlight({ "NvimTreeRootFolder" }, 0, string.len(padded_root))
|
|
||||||
|
|
||||||
-- Keep original indexing behavior
|
|
||||||
self.index = 1
|
self.index = 1
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -410,11 +390,12 @@ function Builder:build_header()
|
|||||||
local filter_line = string.format("%s/%s/", self.explorer.opts.live_filter.prefix, self.explorer.live_filter.filter)
|
local filter_line = string.format("%s/%s/", self.explorer.opts.live_filter.prefix, self.explorer.live_filter.filter)
|
||||||
table.insert(self.lines, filter_line)
|
table.insert(self.lines, filter_line)
|
||||||
local prefix_length = string.len(self.explorer.opts.live_filter.prefix)
|
local prefix_length = string.len(self.explorer.opts.live_filter.prefix)
|
||||||
self:insert_highlight({ "NvimTreeLiveFilterPrefix" }, 0, prefix_length)
|
self:insert_highlight({ "NvimTreeLiveFilterPrefix" }, 0, prefix_length)
|
||||||
self:insert_highlight({ "NvimTreeLiveFilterValue" }, prefix_length, string.len(filter_line))
|
self:insert_highlight({ "NvimTreeLiveFilterValue" }, prefix_length, string.len(filter_line))
|
||||||
self.index = self.index + 1
|
self.index = self.index + 1
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
---Sanitize lines for rendering.
|
---Sanitize lines for rendering.
|
||||||
---Replace newlines with literal \n
|
---Replace newlines with literal \n
|
||||||
---@private
|
---@private
|
||||||
@ -458,18 +439,17 @@ function Builder:setup_hidden_display_function(opts)
|
|||||||
-- In case of missing field such as live_filter we zero it, otherwise keep field as is
|
-- In case of missing field such as live_filter we zero it, otherwise keep field as is
|
||||||
hidden_stats = vim.tbl_deep_extend("force", {
|
hidden_stats = vim.tbl_deep_extend("force", {
|
||||||
live_filter = 0,
|
live_filter = 0,
|
||||||
git = 0,
|
git = 0,
|
||||||
buf = 0,
|
buf = 0,
|
||||||
dotfile = 0,
|
dotfile = 0,
|
||||||
custom = 0,
|
custom = 0,
|
||||||
bookmark = 0,
|
bookmark = 0,
|
||||||
}, hidden_stats or {})
|
}, hidden_stats or {})
|
||||||
|
|
||||||
local ok, result = pcall(hidden_display, hidden_stats)
|
local ok, result = pcall(hidden_display, hidden_stats)
|
||||||
if not ok then
|
if not ok then
|
||||||
notify.warn(
|
notify.warn(
|
||||||
"Problem occurred in the function ``opts.renderer.hidden_display`` see nvim-tree.renderer.hidden_display on :h nvim-tree"
|
"Problem occurred in the function ``opts.renderer.hidden_display`` see nvim-tree.renderer.hidden_display on :h nvim-tree")
|
||||||
)
|
|
||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
return result
|
return result
|
||||||
|
|||||||
@ -1,7 +1,6 @@
|
|||||||
local M = {}
|
local M = {}
|
||||||
|
|
||||||
local utils = require("nvim-tree.utils")
|
local utils = require("nvim-tree.utils")
|
||||||
local view = require("nvim-tree.view")
|
|
||||||
|
|
||||||
local function hide(win)
|
local function hide(win)
|
||||||
if win then
|
if win then
|
||||||
@ -33,7 +32,7 @@ local function effective_win_width()
|
|||||||
return win_width - win_info[1].textoff
|
return win_width - win_info[1].textoff
|
||||||
end
|
end
|
||||||
|
|
||||||
local function show(opts)
|
local function show()
|
||||||
local line_nr = vim.api.nvim_win_get_cursor(0)[1]
|
local line_nr = vim.api.nvim_win_get_cursor(0)[1]
|
||||||
if vim.wo.wrap then
|
if vim.wo.wrap then
|
||||||
return
|
return
|
||||||
@ -53,11 +52,6 @@ local function show(opts)
|
|||||||
local text_width = vim.fn.strdisplaywidth(vim.fn.substitute(line, "[^[:print:]]*$", "", "g"))
|
local text_width = vim.fn.strdisplaywidth(vim.fn.substitute(line, "[^[:print:]]*$", "", "g"))
|
||||||
local win_width = effective_win_width()
|
local win_width = effective_win_width()
|
||||||
|
|
||||||
-- windows width reduced by right aligned icons
|
|
||||||
local icon_ns_id = vim.api.nvim_get_namespaces()["NvimTreeExtmarks"]
|
|
||||||
local icon_extmarks = vim.api.nvim_buf_get_extmarks(0, icon_ns_id, { line_nr - 1, 0 }, { line_nr - 1, -1 }, { details = true })
|
|
||||||
win_width = win_width - utils.extmarks_length(icon_extmarks)
|
|
||||||
|
|
||||||
if text_width < win_width then
|
if text_width < win_width then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
@ -70,9 +64,7 @@ local function show(opts)
|
|||||||
height = 1,
|
height = 1,
|
||||||
noautocmd = true,
|
noautocmd = true,
|
||||||
style = "minimal",
|
style = "minimal",
|
||||||
border = "none"
|
|
||||||
})
|
})
|
||||||
vim.wo[M.popup_win].winhl = view.View.winopts.winhl
|
|
||||||
|
|
||||||
local ns_id = vim.api.nvim_get_namespaces()["NvimTreeHighlights"]
|
local ns_id = vim.api.nvim_get_namespaces()["NvimTreeHighlights"]
|
||||||
local extmarks = vim.api.nvim_buf_get_extmarks(0, ns_id, { line_nr - 1, 0 }, { line_nr - 1, -1 }, { details = true })
|
local extmarks = vim.api.nvim_buf_get_extmarks(0, ns_id, { line_nr - 1, 0 }, { line_nr - 1, -1 }, { details = true })
|
||||||
@ -88,17 +80,14 @@ local function show(opts)
|
|||||||
local details = extmark[4]
|
local details = extmark[4]
|
||||||
|
|
||||||
if type(details) == "table" then
|
if type(details) == "table" then
|
||||||
if vim.fn.has("nvim-0.11") == 1 and vim.hl and vim.hl.range then
|
if vim.fn.has("nvim-0.12") == 1 then
|
||||||
vim.hl.range(0, ns_id, details.hl_group, { 0, col }, { 0, details.end_col, }, {})
|
vim.hl.range(0, ns_id, details.hl_group, { 0, col }, { 0, details.end_col, }, {})
|
||||||
else
|
else
|
||||||
vim.api.nvim_buf_add_highlight(0, ns_id, details.hl_group, 0, col, details.end_col) ---@diagnostic disable-line: deprecated
|
vim.api.nvim_buf_add_highlight(0, ns_id, details.hl_group, 0, col, details.end_col) ---@diagnostic disable-line: deprecated
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
vim.cmd([[ setlocal nowrap noswapfile nobuflisted buftype=nofile bufhidden=wipe ]])
|
vim.cmd([[ setlocal nowrap cursorline noswapfile nobuflisted buftype=nofile bufhidden=wipe ]])
|
||||||
if opts.view.cursorline then
|
|
||||||
vim.cmd([[ setlocal cursorline cursorlineopt=both ]])
|
|
||||||
end
|
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -124,7 +113,7 @@ M.setup = function(opts)
|
|||||||
pattern = { "NvimTree_*" },
|
pattern = { "NvimTree_*" },
|
||||||
callback = function()
|
callback = function()
|
||||||
if utils.is_nvim_tree_buf(0) then
|
if utils.is_nvim_tree_buf(0) then
|
||||||
show(opts)
|
show()
|
||||||
end
|
end
|
||||||
end,
|
end,
|
||||||
})
|
})
|
||||||
|
|||||||
@ -22,8 +22,8 @@ local function check_siblings_for_folder(node, with_arrows)
|
|||||||
end
|
end
|
||||||
|
|
||||||
local function get_padding_indent_markers(depth, idx, nodes_number, markers, with_arrows, inline_arrows, node, early_stop)
|
local function get_padding_indent_markers(depth, idx, nodes_number, markers, with_arrows, inline_arrows, node, early_stop)
|
||||||
local base_padding = with_arrows and (not node.nodes or depth > 0) and " " or " "
|
local base_padding = with_arrows and (not node.nodes or depth > 0) and " " or ""
|
||||||
local padding = (inline_arrows or depth == 0) and base_padding or " "
|
local padding = (inline_arrows or depth == 0) and base_padding or ""
|
||||||
|
|
||||||
if depth > 0 then
|
if depth > 0 then
|
||||||
local has_folder_sibling = check_siblings_for_folder(node, with_arrows)
|
local has_folder_sibling = check_siblings_for_folder(node, with_arrows)
|
||||||
@ -95,15 +95,15 @@ function M.get_arrows(node)
|
|||||||
local dir = node:as(DirectoryNode)
|
local dir = node:as(DirectoryNode)
|
||||||
if dir then
|
if dir then
|
||||||
if dir.open then
|
if dir.open then
|
||||||
str = M.config.icons.glyphs.folder["arrow_open"] .. M.config.icons.padding.folder_arrow
|
str = M.config.icons.glyphs.folder["arrow_open"] .. " "
|
||||||
hl = "NvimTreeFolderArrowOpen"
|
hl = "NvimTreeFolderArrowOpen"
|
||||||
else
|
else
|
||||||
str = M.config.icons.glyphs.folder["arrow_closed"] .. M.config.icons.padding.folder_arrow
|
str = M.config.icons.glyphs.folder["arrow_closed"] .. " "
|
||||||
end
|
end
|
||||||
elseif M.config.indent_markers.enable then
|
elseif M.config.indent_markers.enable then
|
||||||
str = ""
|
str = ""
|
||||||
else
|
else
|
||||||
str = " " .. string.rep(" ", #M.config.icons.padding.folder_arrow)
|
str = " "
|
||||||
end
|
end
|
||||||
|
|
||||||
return { str = str, hl = { hl } }
|
return { str = str, hl = { hl } }
|
||||||
|
|||||||
@ -41,29 +41,17 @@ local DiagnosticsDecorator = Decorator:extend()
|
|||||||
---@protected
|
---@protected
|
||||||
---@param args DecoratorArgs
|
---@param args DecoratorArgs
|
||||||
function DiagnosticsDecorator:new(args)
|
function DiagnosticsDecorator:new(args)
|
||||||
self.explorer = args.explorer
|
self.explorer = args.explorer
|
||||||
|
|
||||||
self.enabled = true
|
self.enabled = true
|
||||||
self.highlight_range = self.explorer.opts.renderer.highlight_diagnostics or "none"
|
self.highlight_range = self.explorer.opts.renderer.highlight_diagnostics or "none"
|
||||||
self.icon_placement = self.explorer.opts.renderer.icons.diagnostics_placement or "none"
|
self.icon_placement = self.explorer.opts.renderer.icons.diagnostics_placement or "none"
|
||||||
|
|
||||||
local vim_diagnostic_icons = {}
|
|
||||||
|
|
||||||
if self.explorer.opts.diagnostics.diagnostic_opts then
|
|
||||||
local vim_diagnostic_config = vim.diagnostic.config() or {}
|
|
||||||
local signs = vim_diagnostic_config.signs or {}
|
|
||||||
if type(signs) == "function" then
|
|
||||||
signs = signs(0, 0)
|
|
||||||
end
|
|
||||||
|
|
||||||
vim_diagnostic_icons = (type(signs) == "table" and signs.text) or {}
|
|
||||||
end
|
|
||||||
|
|
||||||
if self.explorer.opts.renderer.icons.show.diagnostics then
|
if self.explorer.opts.renderer.icons.show.diagnostics then
|
||||||
self.diag_icons = {}
|
self.diag_icons = {}
|
||||||
for name, sev in pairs(ICON_KEYS) do
|
for name, sev in pairs(ICON_KEYS) do
|
||||||
self.diag_icons[sev] = {
|
self.diag_icons[sev] = {
|
||||||
str = vim_diagnostic_icons[sev] or self.explorer.opts.diagnostics.icons[name],
|
str = self.explorer.opts.diagnostics.icons[name],
|
||||||
hl = { HG_ICON[sev] },
|
hl = { HG_ICON[sev] },
|
||||||
}
|
}
|
||||||
self:define_sign(self.diag_icons[sev])
|
self:define_sign(self.diag_icons[sev])
|
||||||
|
|||||||
@ -62,7 +62,7 @@ function GitDecorator:build_icons_by_status(glyphs)
|
|||||||
self.icons_by_status.ignored = { str = glyphs.ignored, hl = { "NvimTreeGitIgnoredIcon" }, ord = 7 }
|
self.icons_by_status.ignored = { str = glyphs.ignored, hl = { "NvimTreeGitIgnoredIcon" }, ord = 7 }
|
||||||
end
|
end
|
||||||
|
|
||||||
---@param icons GitIconsByStatus
|
---@param icons GitIconsByXY
|
||||||
function GitDecorator:build_icons_by_xy(icons)
|
function GitDecorator:build_icons_by_xy(icons)
|
||||||
self.icons_by_xy = {
|
self.icons_by_xy = {
|
||||||
["M "] = { icons.staged },
|
["M "] = { icons.staged },
|
||||||
@ -131,7 +131,7 @@ function GitDecorator:build_file_folder_hl_by_xy()
|
|||||||
["RM"] = "NvimTreeGitFileRenamedHL",
|
["RM"] = "NvimTreeGitFileRenamedHL",
|
||||||
[" R"] = "NvimTreeGitFileRenamedHL",
|
[" R"] = "NvimTreeGitFileRenamedHL",
|
||||||
["!!"] = "NvimTreeGitFileIgnoredHL",
|
["!!"] = "NvimTreeGitFileIgnoredHL",
|
||||||
[" A"] = "NvimTreeGitFileNewHL",
|
[" A"] = "none",
|
||||||
}
|
}
|
||||||
|
|
||||||
self.folder_hl_by_xy = {}
|
self.folder_hl_by_xy = {}
|
||||||
|
|||||||
@ -112,8 +112,9 @@ function Decorator:define_sign(icon)
|
|||||||
vim.fn.sign_undefine(name)
|
vim.fn.sign_undefine(name)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- don't render sign if empty
|
-- don't use sign if not defined
|
||||||
if #icon.str < 1 then
|
if #icon.str < 1 then
|
||||||
|
self.icon_placement = "none"
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@ -87,7 +87,7 @@ function Renderer:render_hl(bufnr, hl_range_args)
|
|||||||
end
|
end
|
||||||
vim.api.nvim_buf_clear_namespace(bufnr, namespace_highlights_id, 0, -1)
|
vim.api.nvim_buf_clear_namespace(bufnr, namespace_highlights_id, 0, -1)
|
||||||
for _, args in ipairs(hl_range_args) do
|
for _, args in ipairs(hl_range_args) do
|
||||||
if vim.fn.has("nvim-0.11") == 1 and vim.hl and vim.hl.range then
|
if vim.fn.has("nvim-0.11") == 1 then
|
||||||
vim.hl.range(bufnr, namespace_highlights_id, args.higroup, args.start, args.finish, {})
|
vim.hl.range(bufnr, namespace_highlights_id, args.higroup, args.start, args.finish, {})
|
||||||
else
|
else
|
||||||
vim.api.nvim_buf_add_highlight(bufnr, namespace_highlights_id, args.higroup, args.start[1], args.start[2], args.finish[2]) ---@diagnostic disable-line: deprecated
|
vim.api.nvim_buf_add_highlight(bufnr, namespace_highlights_id, args.higroup, args.start[1], args.start[2], args.finish[2]) ---@diagnostic disable-line: deprecated
|
||||||
|
|||||||
@ -1,3 +1,6 @@
|
|||||||
|
local Iterator = require("nvim-tree.iterators.node-iterator")
|
||||||
|
local notify = require("nvim-tree.notify")
|
||||||
|
|
||||||
local M = {
|
local M = {
|
||||||
debouncers = {},
|
debouncers = {},
|
||||||
}
|
}
|
||||||
@ -8,6 +11,10 @@ M.is_wsl = vim.fn.has("wsl") == 1
|
|||||||
-- false for WSL
|
-- false for WSL
|
||||||
M.is_windows = vim.fn.has("win32") == 1 or vim.fn.has("win32unix") == 1
|
M.is_windows = vim.fn.has("win32") == 1 or vim.fn.has("win32unix") == 1
|
||||||
|
|
||||||
|
function M._is_windows()
|
||||||
|
return vim.fn.has("win32") == 1 or vim.fn.has("win32unix") == 1
|
||||||
|
end
|
||||||
|
|
||||||
---@param haystack string
|
---@param haystack string
|
||||||
---@param needle string
|
---@param needle string
|
||||||
---@return boolean
|
---@return boolean
|
||||||
@ -15,6 +22,22 @@ function M.str_find(haystack, needle)
|
|||||||
return vim.fn.stridx(haystack, needle) ~= -1
|
return vim.fn.stridx(haystack, needle) ~= -1
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---@param path string
|
||||||
|
---@return string|uv.uv_fs_t
|
||||||
|
function M.read_file(path)
|
||||||
|
local fd = vim.loop.fs_open(path, "r", 438)
|
||||||
|
if not fd then
|
||||||
|
return ""
|
||||||
|
end
|
||||||
|
local stat = vim.loop.fs_fstat(fd)
|
||||||
|
if not stat then
|
||||||
|
return ""
|
||||||
|
end
|
||||||
|
local data = vim.loop.fs_read(fd, stat.size, 0)
|
||||||
|
vim.loop.fs_close(fd)
|
||||||
|
return data or ""
|
||||||
|
end
|
||||||
|
|
||||||
local path_separator = package.config:sub(1, 1)
|
local path_separator = package.config:sub(1, 1)
|
||||||
---@param paths string[]
|
---@param paths string[]
|
||||||
---@return string
|
---@return string
|
||||||
@ -112,19 +135,79 @@ end
|
|||||||
|
|
||||||
M.path_separator = path_separator
|
M.path_separator = path_separator
|
||||||
|
|
||||||
---@param extmarks vim.api.keyset.get_extmark_item[] as per vim.api.nvim_buf_get_extmarks
|
--- Get the node and index of the node from the tree that matches the predicate.
|
||||||
|
--- The explored nodes are those displayed on the view.
|
||||||
|
---@param nodes Node[]
|
||||||
|
---@param fn fun(node: Node): boolean
|
||||||
|
---@return table|nil
|
||||||
---@return number
|
---@return number
|
||||||
function M.extmarks_length(extmarks)
|
function M.find_node(nodes, fn)
|
||||||
local length = 0
|
local node, i = Iterator.builder(nodes)
|
||||||
for _, extmark in ipairs(extmarks) do
|
:matcher(fn)
|
||||||
local details = extmark[4]
|
:recursor(function(node)
|
||||||
if details and details.virt_text then
|
return node.group_next and { node.group_next } or (node.open and #node.nodes > 0 and node.nodes)
|
||||||
for _, text in ipairs(details.virt_text) do
|
end)
|
||||||
length = length + vim.fn.strchars(text[1])
|
:iterate()
|
||||||
end
|
i = require("nvim-tree.view").is_root_folder_visible() and i or i - 1
|
||||||
|
if node and node.explorer.live_filter.filter then
|
||||||
|
i = i + 1
|
||||||
|
end
|
||||||
|
return node, i
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Find the line number of a node.
|
||||||
|
-- Return -1 is node is nil or not found.
|
||||||
|
---@param node Node?
|
||||||
|
---@return integer
|
||||||
|
function M.find_node_line(node)
|
||||||
|
if not node then
|
||||||
|
return -1
|
||||||
|
end
|
||||||
|
|
||||||
|
local first_node_line = require("nvim-tree.core").get_nodes_starting_line()
|
||||||
|
local nodes_by_line = M.get_nodes_by_line(require("nvim-tree.core").get_explorer().nodes, first_node_line)
|
||||||
|
local iter_start, iter_end = first_node_line, #nodes_by_line
|
||||||
|
|
||||||
|
for line = iter_start, iter_end, 1 do
|
||||||
|
if nodes_by_line[line] == node then
|
||||||
|
return line
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
return length
|
|
||||||
|
return -1
|
||||||
|
end
|
||||||
|
|
||||||
|
-- get the node in the tree state depending on the absolute path of the node
|
||||||
|
-- (grouped or hidden too)
|
||||||
|
---@param path string
|
||||||
|
---@return Node|nil
|
||||||
|
---@return number|nil
|
||||||
|
function M.get_node_from_path(path)
|
||||||
|
local explorer = require("nvim-tree.core").get_explorer()
|
||||||
|
|
||||||
|
-- tree may not yet be loaded
|
||||||
|
if not explorer then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
if explorer.absolute_path == path then
|
||||||
|
return explorer
|
||||||
|
end
|
||||||
|
|
||||||
|
return Iterator.builder(explorer.nodes)
|
||||||
|
:hidden()
|
||||||
|
:matcher(function(node)
|
||||||
|
return node.absolute_path == path or node.link_to == path
|
||||||
|
end)
|
||||||
|
:recursor(function(node)
|
||||||
|
if node.group_next then
|
||||||
|
return { node.group_next }
|
||||||
|
end
|
||||||
|
if node.nodes then
|
||||||
|
return node.nodes
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
:iterate()
|
||||||
end
|
end
|
||||||
|
|
||||||
M.default_format_hidden_count = function(hidden_count, simple)
|
M.default_format_hidden_count = function(hidden_count, simple)
|
||||||
@ -147,6 +230,30 @@ M.default_format_hidden_count = function(hidden_count, simple)
|
|||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Return visible nodes indexed by line
|
||||||
|
---@param nodes_all Node[]
|
||||||
|
---@param line_start number
|
||||||
|
---@return table
|
||||||
|
function M.get_nodes_by_line(nodes_all, line_start)
|
||||||
|
local nodes_by_line = {}
|
||||||
|
local line = line_start
|
||||||
|
|
||||||
|
Iterator.builder(nodes_all)
|
||||||
|
:applier(function(node)
|
||||||
|
if node.group_next then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
nodes_by_line[line] = node
|
||||||
|
line = line + 1
|
||||||
|
end)
|
||||||
|
:recursor(function(node)
|
||||||
|
return node.group_next and { node.group_next } or (node.open and #node.nodes > 0 and node.nodes)
|
||||||
|
end)
|
||||||
|
:iterate()
|
||||||
|
|
||||||
|
return nodes_by_line
|
||||||
|
end
|
||||||
|
|
||||||
function M.rename_loaded_buffers(old_path, new_path)
|
function M.rename_loaded_buffers(old_path, new_path)
|
||||||
-- delete new if it exists
|
-- delete new if it exists
|
||||||
for _, buf in pairs(vim.api.nvim_list_bufs()) do
|
for _, buf in pairs(vim.api.nvim_list_bufs()) do
|
||||||
@ -186,57 +293,17 @@ function M.rename_loaded_buffers(old_path, new_path)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
local is_windows_drive = function(path)
|
|
||||||
return (M.is_windows) and (path:match("^%a:\\$") ~= nil)
|
|
||||||
end
|
|
||||||
|
|
||||||
---@param path string path to file or directory
|
---@param path string path to file or directory
|
||||||
---@return boolean
|
---@return boolean
|
||||||
function M.file_exists(path)
|
function M.file_exists(path)
|
||||||
if not (M.is_windows or M.is_wsl) then
|
local _, error = vim.loop.fs_stat(path)
|
||||||
local _, error = vim.loop.fs_stat(path)
|
return error == nil
|
||||||
return error == nil
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Windows is case-insensetive, but case-preserving
|
|
||||||
-- If a file's name is being changed into itself
|
|
||||||
-- with different casing, windows will falsely
|
|
||||||
-- report that file is already existing, so a hand-rolled
|
|
||||||
-- implementation of checking for existance is needed.
|
|
||||||
-- Same holds for WSL, since it can sometimes
|
|
||||||
-- access Windows files directly.
|
|
||||||
-- For more details see (#3117).
|
|
||||||
|
|
||||||
if is_windows_drive(path) then
|
|
||||||
return vim.fn.isdirectory(path) == 1
|
|
||||||
end
|
|
||||||
|
|
||||||
local parent = vim.fn.fnamemodify(path, ":h")
|
|
||||||
local filename = vim.fn.fnamemodify(path, ":t")
|
|
||||||
|
|
||||||
local handle = vim.loop.fs_scandir(parent)
|
|
||||||
if not handle then
|
|
||||||
-- File can not exist if its parent directory does not exist
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
|
|
||||||
while true do
|
|
||||||
local name, _ = vim.loop.fs_scandir_next(handle)
|
|
||||||
if not name then
|
|
||||||
break
|
|
||||||
end
|
|
||||||
if name == filename then
|
|
||||||
return true
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
return false
|
|
||||||
end
|
end
|
||||||
|
|
||||||
---@param path string
|
---@param path string
|
||||||
---@return string
|
---@return string
|
||||||
function M.canonical_path(path)
|
function M.canonical_path(path)
|
||||||
if M.is_windows and path:match("^%a:") then
|
if M._is_windows() and path:match("^%a:") then
|
||||||
return path:sub(1, 1):upper() .. path:sub(2)
|
return path:sub(1, 1):upper() .. path:sub(2)
|
||||||
end
|
end
|
||||||
return path
|
return path
|
||||||
@ -260,6 +327,68 @@ function M.escape_special_chars(path)
|
|||||||
return M.is_windows and escape_special_char_for_windows(path) or path
|
return M.is_windows and escape_special_char_for_windows(path) or path
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Create empty sub-tables if not present
|
||||||
|
---@param tbl table to create empty inside of
|
||||||
|
---@param path string dot separated string of sub-tables
|
||||||
|
---@return table deepest sub-table
|
||||||
|
function M.table_create_missing(tbl, path)
|
||||||
|
local t = tbl
|
||||||
|
for s in string.gmatch(path, "([^%.]+)%.*") do
|
||||||
|
if t[s] == nil then
|
||||||
|
t[s] = {}
|
||||||
|
end
|
||||||
|
t = t[s]
|
||||||
|
end
|
||||||
|
|
||||||
|
return t
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Move a value from src to dst if value is nil on dst.
|
||||||
|
--- Remove value from src
|
||||||
|
---@param src table to copy from
|
||||||
|
---@param src_path string dot separated string of sub-tables
|
||||||
|
---@param src_pos string value pos
|
||||||
|
---@param dst table to copy to
|
||||||
|
---@param dst_path string dot separated string of sub-tables, created when missing
|
||||||
|
---@param dst_pos string value pos
|
||||||
|
---@param remove boolean
|
||||||
|
function M.move_missing_val(src, src_path, src_pos, dst, dst_path, dst_pos, remove)
|
||||||
|
local ok, err = pcall(vim.validate, {
|
||||||
|
src = { src, "table" },
|
||||||
|
src_path = { src_path, "string" },
|
||||||
|
src_pos = { src_pos, "string" },
|
||||||
|
dst = { dst, "table" },
|
||||||
|
dst_path = { dst_path, "string" },
|
||||||
|
dst_pos = { dst_pos, "string" },
|
||||||
|
remove = { remove, "boolean" },
|
||||||
|
})
|
||||||
|
if not ok then
|
||||||
|
notify.warn("move_missing_val: " .. (err or "invalid arguments"))
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
for pos in string.gmatch(src_path, "([^%.]+)%.*") do
|
||||||
|
if src[pos] and type(src[pos]) == "table" then
|
||||||
|
src = src[pos]
|
||||||
|
else
|
||||||
|
return
|
||||||
|
end
|
||||||
|
end
|
||||||
|
local src_val = src[src_pos]
|
||||||
|
if src_val == nil then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
dst = M.table_create_missing(dst, dst_path)
|
||||||
|
if dst[dst_pos] == nil then
|
||||||
|
dst[dst_pos] = src_val
|
||||||
|
end
|
||||||
|
|
||||||
|
if remove then
|
||||||
|
src[src_pos] = nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
local function round(value)
|
local function round(value)
|
||||||
-- Amount of digits to round to after floating point.
|
-- Amount of digits to round to after floating point.
|
||||||
local digits = 2
|
local digits = 2
|
||||||
@ -368,6 +497,38 @@ function M.debounce(context, timeout, callback)
|
|||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function M.focus_file(path)
|
||||||
|
local _, i = M.find_node(require("nvim-tree.core").get_explorer().nodes, function(node)
|
||||||
|
return node.absolute_path == path
|
||||||
|
end)
|
||||||
|
require("nvim-tree.view").set_cursor({ i + 1, 1 })
|
||||||
|
end
|
||||||
|
|
||||||
|
---Focus node passed as parameter if visible, otherwise focus first visible parent.
|
||||||
|
---If none of the parents is visible focus root.
|
||||||
|
---If node is nil do nothing.
|
||||||
|
---@param node Node? node to focus
|
||||||
|
function M.focus_node_or_parent(node)
|
||||||
|
local explorer = require("nvim-tree.core").get_explorer()
|
||||||
|
|
||||||
|
if explorer == nil then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
while node do
|
||||||
|
local found_node, i = M.find_node(explorer.nodes, function(node_)
|
||||||
|
return node_.absolute_path == node.absolute_path
|
||||||
|
end)
|
||||||
|
|
||||||
|
if found_node or node.parent == nil then
|
||||||
|
require("nvim-tree.view").set_cursor({ i + 1, 1 })
|
||||||
|
break
|
||||||
|
end
|
||||||
|
|
||||||
|
node = node.parent
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
---@param path string
|
---@param path string
|
||||||
---@return integer|nil
|
---@return integer|nil
|
||||||
---@return integer|nil
|
---@return integer|nil
|
||||||
|
|||||||
@ -254,6 +254,7 @@ local function close(tabpage)
|
|||||||
return
|
return
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
events._dispatch_on_tree_close()
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -269,12 +270,9 @@ function M.close_all_tabs()
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
---@param tabpage integer|nil
|
function M.close()
|
||||||
function M.close(tabpage)
|
|
||||||
if M.View.tab.sync.close then
|
if M.View.tab.sync.close then
|
||||||
M.close_all_tabs()
|
M.close_all_tabs()
|
||||||
elseif tabpage then
|
|
||||||
close(tabpage)
|
|
||||||
else
|
else
|
||||||
M.close_this_tab_only()
|
M.close_this_tab_only()
|
||||||
end
|
end
|
||||||
@ -288,7 +286,6 @@ function M.open(options)
|
|||||||
|
|
||||||
local profile = log.profile_start("view open")
|
local profile = log.profile_start("view open")
|
||||||
|
|
||||||
events._dispatch_on_tree_pre_open()
|
|
||||||
create_buffer()
|
create_buffer()
|
||||||
open_window()
|
open_window()
|
||||||
M.resize()
|
M.resize()
|
||||||
@ -329,7 +326,14 @@ local function grow()
|
|||||||
local count = vim.fn.strchars(l)
|
local count = vim.fn.strchars(l)
|
||||||
-- also add space for right-aligned icons
|
-- also add space for right-aligned icons
|
||||||
local extmarks = vim.api.nvim_buf_get_extmarks(M.get_bufnr(), ns_id, { line_nr, 0 }, { line_nr, -1 }, { details = true })
|
local extmarks = vim.api.nvim_buf_get_extmarks(M.get_bufnr(), ns_id, { line_nr, 0 }, { line_nr, -1 }, { details = true })
|
||||||
count = count + utils.extmarks_length(extmarks)
|
for _, extmark in ipairs(extmarks) do
|
||||||
|
local virt_texts = extmark[4].virt_text
|
||||||
|
if virt_texts then
|
||||||
|
for _, virt_text in ipairs(virt_texts) do
|
||||||
|
count = count + vim.fn.strchars(virt_text[1])
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
if resizing_width < count then
|
if resizing_width < count then
|
||||||
resizing_width = count
|
resizing_width = count
|
||||||
end
|
end
|
||||||
@ -407,7 +411,6 @@ end
|
|||||||
---@param opts OpenInWinOpts|nil
|
---@param opts OpenInWinOpts|nil
|
||||||
function M.open_in_win(opts)
|
function M.open_in_win(opts)
|
||||||
opts = opts or { hijack_current_buf = true, resize = true }
|
opts = opts or { hijack_current_buf = true, resize = true }
|
||||||
events._dispatch_on_tree_pre_open()
|
|
||||||
if opts.winid and vim.api.nvim_win_is_valid(opts.winid) then
|
if opts.winid and vim.api.nvim_win_is_valid(opts.winid) then
|
||||||
vim.api.nvim_set_current_win(opts.winid)
|
vim.api.nvim_set_current_win(opts.winid)
|
||||||
end
|
end
|
||||||
@ -419,7 +422,6 @@ function M.open_in_win(opts)
|
|||||||
M.reposition_window()
|
M.reposition_window()
|
||||||
M.resize()
|
M.resize()
|
||||||
end
|
end
|
||||||
events._dispatch_on_tree_open()
|
|
||||||
end
|
end
|
||||||
|
|
||||||
function M.abandon_current_window()
|
function M.abandon_current_window()
|
||||||
@ -624,7 +626,6 @@ function M.setup(opts)
|
|||||||
M.View.tab = opts.tab
|
M.View.tab = opts.tab
|
||||||
M.View.preserve_window_proportions = options.preserve_window_proportions
|
M.View.preserve_window_proportions = options.preserve_window_proportions
|
||||||
M.View.winopts.cursorline = options.cursorline
|
M.View.winopts.cursorline = options.cursorline
|
||||||
M.View.winopts.cursorlineopt = options.cursorlineopt
|
|
||||||
M.View.winopts.number = options.number
|
M.View.winopts.number = options.number
|
||||||
M.View.winopts.relativenumber = options.relativenumber
|
M.View.winopts.relativenumber = options.relativenumber
|
||||||
M.View.winopts.signcolumn = options.signcolumn
|
M.View.winopts.signcolumn = options.signcolumn
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
#!/usr/bin/env bash
|
#!/bin/bash
|
||||||
|
|
||||||
out=$(grep -nr "^--- @" lua)
|
out=$(grep -nr "^--- @" lua)
|
||||||
|
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
#!/usr/bin/env sh
|
#!/bin/sh
|
||||||
|
|
||||||
# run after changing nvim-tree.lua DEFAULT_OPTS or keymap.lua M.default_on_attach
|
# run after changing nvim-tree.lua DEFAULT_OPTS or keymap.lua M.default_on_attach
|
||||||
# scrapes and updates nvim-tree-lua.txt
|
# scrapes and updates nvim-tree-lua.txt
|
||||||
|
|||||||
@ -1,11 +1,9 @@
|
|||||||
#!/usr/bin/env sh
|
#!/bin/sh
|
||||||
|
|
||||||
# Performs a lua-language-server check on all files.
|
# Performs a lua-language-server check on all files.
|
||||||
# luals-out/check.json will be produced on any issues, returning 1.
|
# luals-out/check.json will be produced on any issues, returning 1.
|
||||||
# Outputs only check.json to stdout, all other messages to stderr, to allow jq etc.
|
# Outputs only check.json to stdout, all other messages to stderr, to allow jq etc.
|
||||||
# $VIMRUNTIME specifies neovim runtime path, defaults to "/usr/share/nvim/runtime" if unset.
|
# $VIMRUNTIME specifies neovim runtime path, defaults to "/usr/share/nvim/runtime" if unset.
|
||||||
#
|
|
||||||
# Call with codestyle-check param to enable only codestyle-check
|
|
||||||
|
|
||||||
if [ -z "${VIMRUNTIME}" ]; then
|
if [ -z "${VIMRUNTIME}" ]; then
|
||||||
export VIMRUNTIME="/usr/share/nvim/runtime"
|
export VIMRUNTIME="/usr/share/nvim/runtime"
|
||||||
@ -19,24 +17,11 @@ FILE_LUARC="${DIR_OUT}/luarc.json"
|
|||||||
rm -rf "${DIR_OUT}"
|
rm -rf "${DIR_OUT}"
|
||||||
mkdir "${DIR_OUT}"
|
mkdir "${DIR_OUT}"
|
||||||
|
|
||||||
case "${1}" in
|
# Uncomment runtime.version for strict neovim baseline 5.1
|
||||||
"codestyle-check")
|
# It is not set normally, to prevent luals loading 5.1 and 5.x, resulting in both versions being chosen on vim.lsp.buf.definition()
|
||||||
jq \
|
cat "${PWD}/.luarc.json" | sed -E 's/.luals-check-only//g' > "${FILE_LUARC}"
|
||||||
'.diagnostics.neededFileStatus[] = "None" | .diagnostics.neededFileStatus."codestyle-check" = "Any"' \
|
|
||||||
"${PWD}/.luarc.json" > "${FILE_LUARC}"
|
|
||||||
|
|
||||||
;;
|
# execute inside lua to prevent luals itself from being checked
|
||||||
*)
|
|
||||||
# Add runtime.version for strict neovim baseline 5.1
|
|
||||||
# It is not set normally, to prevent luals loading 5.1 and 5.x, resulting in both versions being chosen on vim.lsp.buf.definition
|
|
||||||
jq \
|
|
||||||
'."runtime.version" = "Lua 5.1"' \
|
|
||||||
"${PWD}/.luarc.json" > "${FILE_LUARC}"
|
|
||||||
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
# execute inside lua directory to prevent luals itself from being checked
|
|
||||||
OUT=$(lua-language-server --check="${DIR_SRC}" --configpath="${FILE_LUARC}" --checklevel=Information --logpath="${DIR_OUT}" --loglevel=error)
|
OUT=$(lua-language-server --check="${DIR_SRC}" --configpath="${FILE_LUARC}" --checklevel=Information --logpath="${DIR_OUT}" --loglevel=error)
|
||||||
RC=$?
|
RC=$?
|
||||||
|
|
||||||
|
|||||||
25
scripts/test.sh
Executable file
25
scripts/test.sh
Executable file
@ -0,0 +1,25 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
DIR_REPO="$(git rev-parse --show-toplevel)"
|
||||||
|
export DIR_REPO
|
||||||
|
|
||||||
|
DIR_PLENARY="${DIR_REPO}/plenary.nvim"
|
||||||
|
export DIR_PLENARY
|
||||||
|
|
||||||
|
if [ "${#}" -eq 1 ]; then
|
||||||
|
TEST_NAME="${1}"
|
||||||
|
elif [ -z "${TEST_NAME}" ]; then
|
||||||
|
TEST_NAME="tests"
|
||||||
|
fi
|
||||||
|
export TEST_NAME
|
||||||
|
|
||||||
|
echo "testing: ${TEST_NAME}"
|
||||||
|
|
||||||
|
nvim --headless \
|
||||||
|
--clean \
|
||||||
|
-u "${DIR_REPO}/tests/minimal_init.lua" \
|
||||||
|
-l "${DIR_REPO}/tests/test_init.lua" \
|
||||||
|
-c "qa!"
|
||||||
|
|
||||||
8
tests/minimal_init.lua
Normal file
8
tests/minimal_init.lua
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
-- Prepend these as plenary appends a "." and plenary directory
|
||||||
|
-- The spawned processes don't specify --clean so contain the full ~/.local runtime path
|
||||||
|
vim.o.runtimepath = string.format(
|
||||||
|
"%s,%s,%s",
|
||||||
|
vim.env.DIR_REPO,
|
||||||
|
vim.env.DIR_PLENARY,
|
||||||
|
vim.o.runtimepath
|
||||||
|
)
|
||||||
9
tests/test_init.lua
Normal file
9
tests/test_init.lua
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
local test_harness = require("plenary.test_harness")
|
||||||
|
|
||||||
|
test_harness.test_directory(
|
||||||
|
vim.env.TEST_NAME,
|
||||||
|
{
|
||||||
|
minimal_init = vim.env.DIR_REPO .. "/tests/minimal_init.lua",
|
||||||
|
sequential = true,
|
||||||
|
}
|
||||||
|
)
|
||||||
30
tests/unit/utils_spec.lua
Normal file
30
tests/unit/utils_spec.lua
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
---@type Luassert
|
||||||
|
local assert = require("luassert")
|
||||||
|
local stub = require("luassert.stub")
|
||||||
|
|
||||||
|
local utils = require("nvim-tree.utils")
|
||||||
|
|
||||||
|
describe("utils.path_add_trailing", function()
|
||||||
|
it("trailing added", function()
|
||||||
|
assert.equals("foo/", utils.path_add_trailing("foo"))
|
||||||
|
end)
|
||||||
|
|
||||||
|
it("trailing already present", function()
|
||||||
|
assert.equals("foo/", utils.path_add_trailing("foo/"))
|
||||||
|
end)
|
||||||
|
end)
|
||||||
|
|
||||||
|
describe("utils.canonical_path", function()
|
||||||
|
before_each(function()
|
||||||
|
stub(vim.fn, "has")
|
||||||
|
end)
|
||||||
|
|
||||||
|
it("is windows", function()
|
||||||
|
vim.fn.has.on_call_with("win32unix").returns(1)
|
||||||
|
assert.equals("C:\\foo\\bar", utils.canonical_path("c:\\foo\\bar"), "should be uppercase drive")
|
||||||
|
end)
|
||||||
|
|
||||||
|
it("not windows", function()
|
||||||
|
assert.equals("c:\\foo\\bar", utils.canonical_path("c:\\foo\\bar"))
|
||||||
|
end)
|
||||||
|
end)
|
||||||
Loading…
Reference in New Issue
Block a user