Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

readme.md addition request: add example of is_always_hidden of .gitignore targets and .git folder #92

Closed
1 task done
Arisa-Snowbell opened this issue Apr 27, 2023 · 12 comments
Labels
enhancement New feature or request

Comments

@Arisa-Snowbell
Copy link

Did you check existing requests?

  • I have searched the existing issues

Describe the feature

An example of is_always_hidden function that reads .gitignore and hides the targets in the file with a .git folder.

Provide background

It's very common practice and not everyone is able to create such a function by themselves. I would appreciate that very much.
I tried but failed miserably, it didn't react at all, doesn't matter if I return true or false, it was weird.

Additional details

No response

@Arisa-Snowbell Arisa-Snowbell added the enhancement New feature or request label Apr 27, 2023
@Arisa-Snowbell
Copy link
Author

So it appears my installation just bugged, had to remove it from plugins section and do PackerSync and add it back for the config to work, that was really weird, probably packer problem? I mean the is_always_hidden still doesn't work but other things like columns didn't work before doing this.

@nyngwang
Copy link
Contributor

nyngwang commented Apr 28, 2023

Is this caused by my implementation? #69 I'm busy these days so no immediate reply. You could still take a look at the PR first and tag/ping me when necessary, I will take a look. And sorry in advance if anything I did wrong.

Linked for convenience:

M.should_display = function(entry, bufnr)
local name = entry[FIELD.name]
return not config.view_options.is_always_hidden(name, bufnr)
and (not config.view_options.is_hidden_file(name, bufnr) or config.view_options.show_hidden)
end

@Arisa-Snowbell
Copy link
Author

Hi, I tried it again today and found out that I can't different folder from file in the is_always_hidden.
It always returns the name like it was a file name that's why my things didn't work. I included '/' as it was displayed in the buffer. Without the '/' it does work.

@stevearc
Copy link
Owner

If I understand you correctly, you want all gitignored files to be hidden? That's going to be pretty involved. You'll need to find the .gitignore file and read it, then parse all of the patterns and convert them into vim regexes or lua patterns. Then you'll need to check the file paths in is_always_hidden, make it relative to the nearest gitignore, and see if any of the patterns match. It should be straightforward to get something basic working, but supporting all of the gitignore syntax might be difficult.

@nyngwang
Copy link
Contributor

nyngwang commented Apr 29, 2023

@Arisa-Snowbell I would suggest changing the way we think:

  1. Just let oil.nvim (or any other filetree-like plugin) to show almost all files(since now we have is_always_hidden, etc). This way you can control all of them.
  2. When you want .gitignore file to be respected. I would suggest using a git-integrated plugin(they redirect your command/request from Neovim to git itself), e.g. :FzfLua git_files from fzf-lua, instead. This achieves what you want: those ignored files will not be shown.

That is: use two separate plugins for two different views({file,buf}tree, git). This way we can reduce/remove the burden of maintaining git from the authors of {file,buf}tree-like plugins.

I know that the configuration of fzf-lua might look a little intimidating, but they provided Profiles(probably months ago?) to help you start quick by sane defaults. I have been using it for two years, so I recommend it for you, sincerely.

(I used to be a user of neo-tree and they provide some setup options to hide gitignored-files. This turned out to be cumbersome since I wasn't able to delete these ignored files due to "I had hidden them".)

@stevearc
Copy link
Owner

stevearc commented May 4, 2023

Closing as writing gitignore parsing logic is out of scope. The methodology is laid out, but the implementation is left as an exercise for the reader.

@stevearc stevearc closed this as completed May 4, 2023
@dmelchor-stripe
Copy link

dmelchor-stripe commented Jan 21, 2024

For future readers who wish to git ignore files :). This uses LazyVim

I added a cache to avoid rerunning the git command for each file. You can remove that part and call the function directly, but it's much slower. The cache will run the command once and store the result. Then subsequent runs will just check against the cached result.

-- nvim/lua/plugins/oil.lua

-- @class GitCache
-- @field func function
-- @field results table
local GitCache = {}

-- @param func function
-- @return GitCache
function GitCache:new(func)
  local tbl = {
    func = func,
    results = {}
  }
  self.__index = self
  setmetatable(tbl, self)
  return tbl
end

-- @param dir string
function GitCache:_call(dir)
  local cmd = string.format('git -C %s ls-files --ignored --exclude-standard --others --directory | grep -v \"/.*\\/\"', dir)

  local handle = io.popen(cmd)
  if handle == nil then
    return
  end

  -- Clean the output a bit
  local lines = vim.split(output, '\n')
  local ignored_files = {}
  for _, line in ipairs(lines) do
    -- Remove trailing slash
    line = line:gsub('/$', '')
    table.insert(ignored_files, line)
  end
  table.insert(ignored_files, '.git')
  table.insert(ignored_files, '..')

  self.results[dir] = ignored_files
  self.checked = true
end

-- @param dir string
-- @return table
function GitCache:call(dir)
  if self.results[dir] == nil then
    -- Reset cache, we don't care about old dir results
    self.results = {}

    self:_call(dir)
  end
  return self.results[dir]
end

local cache = GitCache:new(get_ignored)

return {
  'stevearc/oil.nvim',
  dependencies = { "nvim-tree/nvim-web-devicons" },
  config = function()
    local oil = require('oil')
    oil.setup({
      view_options = {
        is_hidden_file = function(name, _)
          local ignored_files = cache:call(oil.get_current_dir())
          return vim.tbl_contains(ignored_files, name)
        end,
      },
    })
  end
}

@IlyasYOY
Copy link

IlyasYOY commented Mar 19, 2024

Hello! Thanks @dmelchor-stripe

I slightly changed your implementation:

local function get_git_ignored_files_in(dir)
    local found = vim.fs.find(".git", {
        upward = true,
        path = dir,
    })
    if #found == 0 then
        return {}
    end

    local cmd = string.format(
        'git -C %s ls-files --ignored --exclude-standard --others --directory | grep -v "/.*\\/"',
        dir
    )

    local handle = io.popen(cmd)
    if handle == nil then
        return
    end

    local ignored_files = {}
    for line in handle:lines "*l" do
        line = line:gsub("/$", "")
        table.insert(ignored_files, line)
    end
    handle:close()

    return ignored_files
end

Here it is in my config: https://github.com/IlyasYOY/dotfiles/blob/419ff681f49372d6b75174c95fa0f17afa021966/config/nvim/lua/plugins/core.lua#L1

Usage of the function:

                view_options = {
                    show_hidden = true,
                    is_hidden_file = function(name, bufnr)
                        local ignored_files =
                            get_git_ignored_files_in(oil.get_current_dir())
                        return vim.tbl_contains(ignored_files, name)
                            or vim.startswith(name, ".")
                    end,
                },

Here it is in my config: https://github.com/IlyasYOY/dotfiles/blob/419ff681f49372d6b75174c95fa0f17afa021966/config/nvim/lua/plugins/core.lua#L74

@Rizhiy
Copy link

Rizhiy commented Mar 19, 2024

Daniel's approach seem most sane. If we want to filter by .gitignore we can expect that git is installed on the system and let it tell us what is ignored or not.

@IlyasYOY
Copy link

IlyasYOY commented Mar 20, 2024

Updated my comment so it now works ourside of .git project.

@Rizhiy you might be interested in it you borrowed the solution

@daoye
Copy link

daoye commented Jun 13, 2024

Great!
I was founding how to respect gitignore, This is my want. thanks!
Can we update this solution to readme?

@stevearc
Copy link
Owner

I've added this as a recipe in the new recipes section of the documentation

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

7 participants