Skip to content

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

Open
Olyxz16 wants to merge 8 commits into
gokcehan:masterfrom
Olyxz16:master
Open

Add gitignore option for automatic gitignore-aware file hiding#2628
Olyxz16 wants to merge 8 commits into
gokcehan:masterfrom
Olyxz16:master

Conversation

@Olyxz16

@Olyxz16 Olyxz16 commented Jun 25, 2026

Copy link
Copy Markdown

Summary

This PR adds a new boolean option gitignore (default false) that makes lf automatically respect .gitignore rules when displaying directories inside a git worktree.
Links to #2627

Motivation

Implementing gitignore-aware hiding via lfrc configuration (e.g. on-cd hooks calling lf -remote) produces visible blinking/artifacts due to IPC delays. The on-cd hook runs asynchronously, so lf renders the directory with stale hiddenfiles before the remote command arrives and forces a redraw. This cannot be fixed from user configuration alone.

The only clean solution is to query git at directory load time, before the UI ever sees the files.

What changed

File Change
opts.go Add gitignore bool to gOpts struct; default false
eval.go Add toggle handler for gitignore/nogitignore/gitignore!; triggers async directory reloads via app.nav.renew()
nav.go Add getGitIgnored() helper, file.gitIgnored flag, dir.gitWorktree state, and mutually exclusive filter logic in dir.sort()
doc.md Add gitignore to Quick Reference and Settings sections
doc.txt, lf.1 Regenerated via gen/doc.sh

Design details

The two hiding mechanisms are mutually exclusive at the directory level:

  • Inside a git worktree: getGitIgnored() calls git check-ignore --stdin -z once per directory load. Only files returned by git (plus .git) are hidden. Normal dotfiles that are not ignored (e.g. .bashrc) remain visible.
  • Outside a git worktree: Normal hiddenfiles behavior applies unchanged.

When the gitignore option is toggled at runtime, checkDir() detects the change and triggers an async directory reload via the existing reload infrastructure (same pattern used for dircounts changes).

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. Gracefully degrades when git is not installed.

Testing

  • go build . passes
  • go test ./... passes
  • go vet ./... clean
  • go fmt ./... clean
  • gen/doc.sh ran successfully

Usage

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

Olyxz16 added 8 commits June 25, 2026 03:18
Add a new boolean option 'gitignore' (default false). When enabled, lf
queries git check-ignore when loading directory contents inside a git
worktree, and hides those files instead of using the static hiddenfiles
patterns. This avoids the visual blinking caused by lf-remote IPC delays
when trying to implement the same feature via on-cd hooks.

Changes:
- opts.go: add gitignore bool option with default false
- eval.go: add toggle handler that triggers async directory reloads
- nav.go: add getGitIgnored helper, file.gitIgnored flag, dir.gitWorktree
  state, and mutually exclusive filter logic in dir.sort()

The two hiding mechanisms are mutually exclusive at the directory level:
- Inside a git worktree: only gitignored files (plus .git) are hidden
- Outside a git worktree: normal hiddenfiles behavior applies
Add gitignore to the Quick Reference options list and the Settings
section in doc.md. Regenerate doc.txt and lf.1 via gen/doc.sh.
This change allows per-directory hiddenfiles configuration via setlocal,
enabling gitignore-aware hiding through the on-load hook without blinking.

Changes:
- opts.go: add hiddenfiles to gLocalOpts; add getHiddenFiles() helper
- eval.go: add hiddenfiles case to setLocalExpr.eval with sort/redraw
- nav.go: use getHiddenFiles(dir.path) instead of gOpts.hiddenfiles
- app.go: move onLoad() before d.sort() so hooks can affect sort order

The on-load hook now runs synchronously before sorting, allowing it to
set local options (like hiddenfiles) that affect the initial render.
Add hiddenfiles to the setlocal supported options list. Remove the
gitignore documentation that was added in the previous approach.
Regenerate doc.txt and lf.1 via gen/doc.sh.
- Add noSuspend flag to skip terminal suspend/resume during sync
  shell commands (on-load hooks), eliminating flicker and escape
  sequence leakage
- Restructure dirChan handler: cache directory before draining
  server commands so addcustominfo can find files
- Buffer serverChan (32) so readExpr() never blocks waiting for
  the main loop to receive setlocal/addcustominfo responses
- Update onLoad() to toggle noSuspend around cmd.eval()
…ly on-load

- Guard all sort/position/loadFile calls in setLocalExpr.eval() with
  !app.noSuspend to prevent double-preview-loading during the dirChan
  handler's server command drain loop
- Run on-load only for the currently focused directory, skipping parent
  directories. This reduces main-loop blocking from ~110ms to ~22ms
  when cd'ing into deep paths, eliminating preview lag caused by
  blocked event processing
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant