Skip to content

Add gitignore option for automatic gitignore-aware file hiding #2627

Description

@Olyxz16

Feature description

Add a new boolean option gitignore (default false). When enabled, lf automatically hides files ignored by .gitignore when inside a git worktree, and falls back to normal hiddenfiles behavior otherwise.

Why this cannot be done in user configuration

This was the first thing I tried :

cmd on-cd %{{
    if git rev-parse --is-inside-work-tree >/dev/null 2>&1; then
        IGNORED=$(ls -A | git check-ignore --stdin 2>/dev/null | tr '\n' ':')
        lf -remote "send $id set hiddenfiles '.git:${IGNORED}'"
    else
        lf -remote "send $id set hiddenfiles '.*'"
    fi
}}

The problem: on-cd runs in a subprocess that does not block the UI thread. By the time lf -remote delivers the set hiddenfiles command, lf has already rendered the directory using the old patterns. The subsequent remote command forces a re-sort and redraw, producing a visible blink/flash every time you change directories. Caching the value (comparing old vs new) only reduces redundant calls -- it cannot eliminate the IPC delay inherent to the hook architecture.

Proposed implementation

The fix belongs at the directory-loading layer (nav.go), before the UI ever sees the files:

  1. getGitIgnored(dir, names) -- calls git check-ignore --stdin -z once per directory load. Returns a map[string]bool of ignored basenames. If the directory is not inside a git worktree (or git is not installed), returns nil.
  2. readdir -- populates file.gitIgnored for each file when inside a worktree.
  3. dir.sort() -- uses a mutually exclusive filter:
    • Inside a git worktree: hide only gitIgnored files (and .git).
    • Outside a worktree: use normal hiddenfiles patterns.
  4. checkDir -- detects gitignore option toggles and triggers async reloads via the existing directory reload infrastructure (same pattern used for dircounts changes).

Changes

File What changed
opts.go Add gitignore bool to gOpts; default false
eval.go Add toggle handler; uses app.nav.renew() to trigger async reloads
nav.go Add getGitIgnored, file.gitIgnored, dir.gitWorktree, and wire into filter logic
doc.md Add gitignore to Quick Reference and Settings sections

Complexity assessment

  • No new Go dependencies. nav.go already imports os/exec.
  • No new goroutines. The git check runs synchronously inside the existing directory-loading goroutine.
  • Performance: One git check-ignore --stdin -z call per directory load. Negligible overhead when disabled. When enabled, batching via stdin is faster than N individual git check-ignore calls.
  • Platform: Pure Go, works on any platform with git in $PATH.

Usage

set hiddenfiles ".*"
set gitignore
  • Inside a git repo: only gitignored files (plus .git) are hidden. Normal dotfiles (e.g. .bashrc) that are not ignored remain visible.
  • Outside a git repo: normal hiddenfiles behavior applies.
  • Toggle at runtime with :set gitignore!.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions