Skip to content

Commit dcc344c

Browse files
feat(view): indicate modified buffers (#1835)
* Outlined new options * highlight_modified is highlight_opened_files * prototype with autocmd * moved modified into glyphs * show_on_dirs and show_on_open_dirs * icon placement before & after * _get_filename_offset * fixed :wq doesn't update modified indicator * highlight_modified, signcolumn modified_placement Refactored to make everything use HighlightedString to remove all the complex `insert_highlight` calculation. Not tested. * updated doc to match the reality of no multi char for glyphs.modified * fixed git signcolumn doesn't show * fixed highlight_modified gets replaced by highlight_opened_files * fixed renderer.icons.show.modified = false crash * updated doc to reflect empty icon not breaking rendering * removed debounce_delay to implement in a later PR * doc nit: order placement * change modified dirs default to be consistent with git * illegal git & modified placement changed to default * don't assume icon exist * nit remove comment * Noted in doc that glyphs can't have more than 2 characters if in signcolumn * Don't sign_define if placement isn't signcolumn Co-authored-by: Alexander Courtis <[email protected]>
1 parent 9ad93b6 commit dcc344c

File tree

10 files changed

+370
-135
lines changed

10 files changed

+370
-135
lines changed

doc/nvim-tree-lua.txt

Lines changed: 56 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,7 @@ Subsequent calls to setup will replace the previous configuration.
224224
highlight_git = false,
225225
full_name = false,
226226
highlight_opened_files = "none",
227+
highlight_modified = "none",
227228
root_folder_label = ":~:s?$?/..?",
228229
indent_width = 2,
229230
indent_markers = {
@@ -240,18 +241,21 @@ Subsequent calls to setup will replace the previous configuration.
240241
icons = {
241242
webdev_colors = true,
242243
git_placement = "before",
244+
modified_placement = "after",
243245
padding = " ",
244246
symlink_arrow = " ➛ ",
245247
show = {
246248
file = true,
247249
folder = true,
248250
folder_arrow = true,
249251
git = true,
252+
modified = true,
250253
},
251254
glyphs = {
252255
default = "",
253256
symlink = "",
254257
bookmark = "",
258+
modified = "●",
255259
folder = {
256260
arrow_closed = "",
257261
arrow_open = "",
@@ -326,6 +330,11 @@ Subsequent calls to setup will replace the previous configuration.
326330
show_on_open_dirs = true,
327331
timeout = 400,
328332
},
333+
modified = {
334+
enable = false,
335+
show_on_dirs = true,
336+
show_on_open_dirs = true,
337+
},
329338
actions = {
330339
use_system_clipboard = true,
331340
change_dir = {
@@ -544,6 +553,7 @@ Configuration options for the system open command.
544553

545554
*nvim-tree.diagnostics*
546555
Show LSP and COC diagnostics in the signcolumn
556+
Note that the modified sign will take precedence over the diagnostics signs.
547557

548558
`NOTE`: it will use the default diagnostic color groups to highlight the signs.
549559
If you wish to customize, you can override these groups:
@@ -619,6 +629,26 @@ Git integration with icons and colors.
619629
milliseconds but a few seconds), it will not render anything until the git
620630
process returned the data.
621631

632+
*nvim-tree.modified*
633+
Indicate which file have unsaved modification.
634+
635+
*nvim-tree.modified.enable*
636+
Enable / disable the feature.
637+
Type: `boolean`, Default: `false`
638+
639+
*nvim-tree.modified.show_on_dirs*
640+
Show modified indication on directory whose children are modified.
641+
Type: `boolean`, Default: `true`
642+
643+
*nvim-tree.modified.show_on_open_dirs*
644+
Show modified indication on open directories.
645+
Only relevant when |modified.show_on_dirs| is `true`.
646+
Type: `boolean`, Default: `true`
647+
648+
You will still need to set |renderer.icons.show.modified| `= true` or
649+
|renderer.highlight_modified| `= true` to be able to see things in the
650+
tree.
651+
622652
*nvim-tree.filesystem_watchers*
623653
Will use file system watcher (libuv fs_event) to watch the filesystem for
624654
changes.
@@ -779,6 +809,13 @@ UI rendering setup
779809
Value can be `"none"`, `"icon"`, `"name"` or `"all"`.
780810
Type: `string`, Default: `"none"`
781811

812+
*nvim-tree.renderer.highlight_modified*
813+
Highlight icons and/or names for modified files using `NvimTreeModified`
814+
highlight groups.
815+
Value can be `"none"`, `"icon"`, `"name"` or `"all"`
816+
This can be used with or without the icons.
817+
Type: `string`, Default `"none"`
818+
782819
*nvim-tree.renderer.root_folder_label* (previously `renderer.root_folder_modifier`)
783820
In what format to show root folder. See `:help filename-modifiers` for
784821
available `string` options.
@@ -821,12 +858,17 @@ UI rendering setup
821858
Place where the git icons will be rendered.
822859
Can be `"after"` or `"before"` filename (after the file/folders icons)
823860
or `"signcolumn"` (requires |nvim-tree.view.signcolumn| enabled).
824-
Note that the diagnostic signs will take precedence over the git signs.
861+
Note that the diagnostic signs and the modified sign will take precedence over the git signs.
825862
Type: `string`, Default: `before`
826863

864+
*nvim-tree.renderer.icons.modified_placement*
865+
Place where the modified icon will be rendered.
866+
Can be `"after"` or `"before"` filename (after the file/folders icons)
867+
or `"signcolumn"` (requires |nvim-tree.view.signcolumn| enabled).
868+
Type: `string`, Default: `after`
869+
827870
*nvim-tree.renderer.icons.padding*
828871
Inserted between icon and filename.
829-
Use with caution, it could break rendering if you set an empty string depending on your font.
830872
Type: `string`, Default: `" "`
831873

832874
*nvim-tree.renderer.icons.symlink_arrow*
@@ -854,8 +896,15 @@ UI rendering setup
854896
Requires |git.enable| `= true`
855897
Type: `boolean`, Default: `true`
856898

899+
*nvim-tree.renderer.icons.show.modified*
900+
Show a modified icon, see |renderer.icons.modified_placement|
901+
Requires |modified.enable| `= true`
902+
Type: `boolean`, Default: `true`
903+
857904
*nvim-tree.renderer.icons.glyphs*
858905
Configuration options for icon glyphs.
906+
NOTE: Do not set any glyphs to more than two characters if it's going
907+
to appear in the signcolumn.
859908

860909
*nvim-tree.renderer.icons.glyphs.default*
861910
Glyph for files. Will be overridden by `nvim-web-devicons` if available.
@@ -865,6 +914,10 @@ UI rendering setup
865914
Glyph for symlinks to files.
866915
Type: `string`, Default: `""`
867916

917+
*nvim-tree.renderer.icons.glyphs.modified*
918+
Icon to display for modified files.
919+
Type: `string`, Default: `""`
920+
868921
*nvim-tree.renderer.icons.glyphs.folder*
869922
Glyphs for directories.
870923
Type: `table`, Default:
@@ -1471,6 +1524,7 @@ NvimTreeEmptyFolderName (Directory)
14711524
NvimTreeOpenedFolderName (Directory)
14721525
NvimTreeExecFile
14731526
NvimTreeOpenedFile
1527+
NvimTreeModifiedFile
14741528
NvimTreeSpecialFile
14751529
NvimTreeImageFile
14761530
NvimTreeIndentMarker

lua/nvim-tree.lua

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ local copy_paste = require "nvim-tree.actions.fs.copy-paste"
1212
local collapse_all = require "nvim-tree.actions.tree-modifiers.collapse-all"
1313
local git = require "nvim-tree.git"
1414
local filters = require "nvim-tree.explorer.filters"
15+
local modified = require "nvim-tree.modified"
1516

1617
local _config = {}
1718

@@ -476,6 +477,15 @@ local function setup_autocommands(opts)
476477
end,
477478
})
478479
end
480+
481+
if opts.modified.enable then
482+
create_nvim_tree_autocmd({ "BufModifiedSet", "BufWritePost" }, {
483+
callback = function()
484+
modified.reload()
485+
reloaders.reload_explorer()
486+
end,
487+
})
488+
end
479489
end
480490

481491
local DEFAULT_OPTS = { -- BEGIN_DEFAULT_OPTS
@@ -532,6 +542,7 @@ local DEFAULT_OPTS = { -- BEGIN_DEFAULT_OPTS
532542
highlight_git = false,
533543
full_name = false,
534544
highlight_opened_files = "none",
545+
highlight_modified = "none",
535546
root_folder_label = ":~:s?$?/..?",
536547
indent_width = 2,
537548
indent_markers = {
@@ -548,18 +559,21 @@ local DEFAULT_OPTS = { -- BEGIN_DEFAULT_OPTS
548559
icons = {
549560
webdev_colors = true,
550561
git_placement = "before",
562+
modified_placement = "after",
551563
padding = " ",
552564
symlink_arrow = "",
553565
show = {
554566
file = true,
555567
folder = true,
556568
folder_arrow = true,
557569
git = true,
570+
modified = true,
558571
},
559572
glyphs = {
560573
default = "",
561574
symlink = "",
562575
bookmark = "",
576+
modified = "",
563577
folder = {
564578
arrow_closed = "",
565579
arrow_open = "",
@@ -634,6 +648,11 @@ local DEFAULT_OPTS = { -- BEGIN_DEFAULT_OPTS
634648
show_on_open_dirs = true,
635649
timeout = 400,
636650
},
651+
modified = {
652+
enable = false,
653+
show_on_dirs = true,
654+
show_on_open_dirs = true,
655+
},
637656
actions = {
638657
use_system_clipboard = true,
639658
change_dir = {
@@ -810,6 +829,7 @@ function M.setup(conf)
810829
require("nvim-tree.renderer").setup(opts)
811830
require("nvim-tree.live-filter").setup(opts)
812831
require("nvim-tree.marks").setup(opts)
832+
require("nvim-tree.modified").setup(opts)
813833
if M.config.renderer.icons.show.file and pcall(require, "nvim-web-devicons") then
814834
require("nvim-web-devicons").setup()
815835
end

lua/nvim-tree/colors.lua

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ local function get_hl_groups()
4040
SpecialFile = { gui = "bold,underline", fg = colors.yellow },
4141
ImageFile = { gui = "bold", fg = colors.purple },
4242
OpenedFile = { gui = "bold", fg = colors.green },
43+
ModifiedFile = { fg = colors.green },
4344

4445
GitDirty = { fg = colors.dark_red },
4546
GitDeleted = { fg = colors.dark_red },

lua/nvim-tree/modified.lua

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
local M = {}
2+
3+
---@type table<string, boolean> record of which file is modified
4+
M._record = {}
5+
6+
---refresh M.record
7+
function M.reload()
8+
M._record = {}
9+
local bufs = vim.fn.getbufinfo { bufmodified = true, buflisted = true }
10+
for _, buf in pairs(bufs) do
11+
local path = buf.name
12+
M._record[path] = true
13+
while path ~= vim.fn.getcwd() and path ~= "/" do
14+
path = vim.fn.fnamemodify(path, ":h")
15+
M._record[path] = true
16+
end
17+
end
18+
end
19+
20+
---@param node table
21+
---@return boolean
22+
function M.is_modified(node)
23+
return M.config.enable
24+
and M._record[node.absolute_path]
25+
and (not node.nodes or M.config.show_on_dirs)
26+
and (not node.open or M.config.show_on_open_dirs)
27+
end
28+
29+
---@param opts table
30+
function M.setup(opts)
31+
M.config = opts.modified
32+
end
33+
34+
return M

0 commit comments

Comments
 (0)