Skip to content

[Enhancement] Configure showing hidden files#6041

Merged
nathanlesage merged 34 commits into
Zettlr:developfrom
benniekiss:hidden-files
Feb 11, 2026
Merged

[Enhancement] Configure showing hidden files#6041
nathanlesage merged 34 commits into
Zettlr:developfrom
benniekiss:hidden-files

Conversation

@benniekiss

Copy link
Copy Markdown
Collaborator

Description

This PR allows a user to configure whether hidden files are shown in the sidebar and file manager.

Closes #6040
Closes #5949

Changes

A configuration option was added to the advanced settings pane allowing a user to configure whether hidden files and directories (essentially dot files) are shown in the file manager and sidebar.

Additional extensions configured in the advanced settings pane now show up in the file manager.

Hidden file detection was refactored to be consolidated within the file sorting methods of the TreeItem, FileList, and workspace-store. Now, the FSAL indexing includes all files.

A check was added to the readDirectoryRecursively and readDirectory FSAL methods to check if the directory is a .git dir, in which case parsing is skipped.

ignoreDir handling was consolidated, and the FSAL watchdog was updated to use the ignoreDir function. The regex to ignore dot files was commented out so that changes to dot files are picked up when a user has them visible.

The getFilesystemMetadata function was refactored to be more streamlined and remove references to recursive parsing, which is now no longer handled by this function. The call to fs.stat was changed to fs.lstat to detect symlinks and prevent crashes when they are in the tree. This led to the target being stat'd, but then the subsequent call to readFile would fail because it tries to read the link path, not the target path.

Additional information

Tested on:

@nathanlesage nathanlesage left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay, so, I think I get this PR. In general, I'd argue we should move from hidden files to dot files, just because it's more accurate and won't confuse Windows users, since there "hiding" files involves setting an attribute.

Then, it doesn't seem as if this PR actually ignores .ztr-directory files, or does it?

A few more comments see below.

Comment thread source/app/service-providers/fsal/fsal-directory.ts Outdated
Comment thread source/common/util/ignore-dir.ts Outdated
Comment thread source/common/util/file-extention-checks.ts Outdated
Comment thread source/common/util/file-extention-checks.ts Outdated
@benniekiss

benniekiss commented Dec 7, 2025

Copy link
Copy Markdown
Collaborator Author

Okay, so, I think I get this PR. In general, I'd argue we should move from hidden files to dot files, just because it's more accurate and won't confuse Windows users, since there "hiding" files involves setting an attribute.

I had actually originally had this as dotFiles and moved to hiddenFiles just because there may be other non-dotfile files we would want to hide? But that was just me overthinking the future. I can get all hiddenFiles throughout the PR moved back to dotFiles.

Then, it doesn't seem as if this PR actually ignores .ztr-directory files, or does it?

No, .ztr-directory is not ignored and it is visible when hiddenFiles is enabled. Should it be ignored? I can make that happen.

@nathanlesage

Copy link
Copy Markdown
Member

I would like to separate the logic of detecting dot-files, and whether they are affected by the show/hide section. We should probably add a simple array to hide specific dot-files and folders; see also issue #6061. I believe there could be three "layers" of dot files:

  1. Default: Everything is just hidden.
  2. "Dot-files" are shown except those that users of Zettlr commonly deal with. I strongly believe this should be a hard-coded array of dot-files that should never appear. (".git", ".quarto", ".config", and so on)
  3. User-defined "dot-files" are hidden.

Settings-wise it might make sense to capture it like so:

  • Keep the "show dot files" in the file types matrix as you have already implemented.
  • Add a new setting "Hide common dot-files/folders" (feel free to get creative with the exact wording) that is on by default. If "dot files" are hidden in general, it won't have an effect, but if dot files are shown, this filters a few common dot files and folders; i.e.: "most" dot files are shown, but the hard-coded one are not.

Optionally (but I'd argue we should not implement before we actually need it), we could also add a token list-input (like for the attachment extensions) where users could provide additional dot files that should be hidden in addition.

@benniekiss

Copy link
Copy Markdown
Collaborator Author

I think user defined files are out of scope for this, and I dont really have interest in implementing that here.

Regarding always hidden files (.git, etc), should those always be hidden--i.e, no setting to make them visible, or should there be a separate setting to make them visible?

I can get behind always hidden, but a separate setting in my opinion would only confuse users who have to track down two settings for essentially the same functionality.

@benniekiss

Copy link
Copy Markdown
Collaborator Author

Also, in what layer should the always hidden files be filtered?

Currently, git folders are filtered in the FSAL layer because we dont want to recurse into them, which causes issues when parsing certain "exotic" files within the folder.

However, every other file/folder is filtered at the ui level

@nathanlesage

Copy link
Copy Markdown
Member

I'm fine with no option for that. Again, Zettlr only provides a view over the file system, and Is argue users can also always use the computer file browser to view those hidden folders.

I'd also say all hidden files should be filtered at the FSAL level, that is, not even be parsed. This reduces the memory footprint and avoids potential footguns where hidden folders contain a bazillion plain text files that are of no concern to Zettlr. The less we parse, the better. That was also why I was initially hesitant of such a prominent setting...

@benniekiss

Copy link
Copy Markdown
Collaborator Author

Thats definitely doable!

Do you have a list in mind of files/folders to always ignore? It can start off simple, too

@danieltomasz

Copy link
Copy Markdown

As the author of #6061, I agree that hiding hidden or dot files could be expanded to completely ignore them. Regarding hardcoding the list of files, could it be just a setting for files or regular expressions that Zettlr ships with? These could then be overriden by the user either through the settings interface or by editing a text configuration file (if the settings inteface complexity shouldnt be increased and there is no need for new panel) .

I don’t expect this to be a common occurrence but sometimes someone might want at least some of these files accessible in very rare cases.

@benniekiss

Copy link
Copy Markdown
Collaborator Author

So again, I'm not going to implement user-configured hidden files in this PR. I think there's more discussion to be had on the UI and UX of that feature.

Regarding what kind of files are included in the hardcoded list, I would really only want these to be files and folders users have no business editing regardless -- i.e, people should not be messing around in the .git folder, and theres really no need to give a user access to this in the UI, same with the .ztr-directory file. I think the list should also include other VCS folders (.hg for mercurial), and maybe some other common artifact patterns. I don't think this list will end up being long or that intrusive. Otherwise, it would defeat the purpose imo.

@nathanlesage

Copy link
Copy Markdown
Member

I concur with @benniekiss here. Also, there will be many more releases!

As to a potential starting list of what should always be ignored, we might want to start with common gitignore lists and see what we find that might commonly end up in user directories! I don't think that list will be very long, though. One additional thing would be .DS_Store that we should ignore

@danieltomasz

danieltomasz commented Dec 14, 2025

Copy link
Copy Markdown

if I can add to the list a quite often folders to exclude can be .obsidian and .quarto (.git for sure)

@benniekiss

Copy link
Copy Markdown
Collaborator Author

Last commit is a WIP to implementing the hard-coded list and filtering at the FSAL level. I believe its 90% there, I just haven't tested extensively.

I renamed the ignore-dir file and function to ignore-path, etc. because the function is used to check more than just dirs, but rather every file path. I also moved the isDotFile function into this file. It felt more at home there, and the previous location in the file-extension file was sort of out of place since it was not checking an extension.

Even though we filter at the FSAL level, we still need filtering at the UI level. Since the show dot files config option has two parts -- the file manager and the sidebar -- there may be instances where dotfiles are in the tree but shouldn't be shown in a particular context.

One question I had was how to address watchdog handling. Currently, I re-use the ignorePath function in the chokidar ignore option, and because of that, I believe ztr-directory handling is likely broken ATM. What I was wondering -- do we need to have this ignored option set, or does the watchdog already ignore the files since we filter them in the FSAL layer? It is not complicated to have separate watchdog handling, but it means the paths to ignore needs to be separated out. Another question I had was whether we still need to emit events for changes to a .git directory -- I couldn't find any clear functionality that depended on these events.

@nathanlesage

Copy link
Copy Markdown
Member

Everything that is filtered out at the FSAL level also needs to be ignored in the watchdog, especially since changes to git folders would emit a huge amount of events that can have a performance impact on Zettlr because the main loop is busy sending out events into the void.

I just had another question: do we generally need to distinguish between dot files and dot folders?

@benniekiss

Copy link
Copy Markdown
Collaborator Author

Everything that is filtered out at the FSAL level also needs to be ignored in the watchdog, especially since changes to git folders would emit a huge amount of events that can have a performance impact on Zettlr because the main loop is busy sending out events into the void.

Currently, .git dirs are still watched with special handling here, but that should be removed?

// Specials: .git and .ztr-directory
if (basename === '.git') {
// We basically treat .git as a file, not a directory (see above).
this._logger.info(`[WATCHDOG] Emitting event (.git): change:${dirname}`)
report('change', dirname)
} else if (basename === '.ztr-directory') {
// Even on add or unlink, it's strictly speaking a change for the dir
this._logger.info(`[WATCHDOG] Emitting event (.ztr-directory): change:${dirname}`)
report('change', dirname)
} else {
this._logger.info(`[WATCHDOG] Emitting event: ${event}:${p}`)
report(event, p)
}

I just had another question: do we generally need to distinguish between dot files and dot folders?

I don't think so, and there's no distinction in the code currently.

@nathanlesage

Copy link
Copy Markdown
Member

Currently, .git dirs are still watched with special handling here, but that should be removed?

Given that Zettlr may need to react to those changes, we should leave it. But anything that Zettlr doesn't need should be ignored. If we have to extend the list of exceptions in the future so be it!

@nathanlesage nathanlesage left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We're getting there!

Comment thread source/app/service-providers/fsal/index.ts
Comment thread source/app/service-providers/fsal/index.ts Outdated
Comment thread source/app/service-providers/fsal/index.ts Outdated
Comment thread source/common/util/ignore-path.ts Outdated
Comment thread source/common/util/ignore-path.ts Outdated
Comment thread source/win-main/file-manager/FileList.vue Outdated
Comment thread source/win-main/file-manager/TreeItem.vue Outdated
@benniekiss

Copy link
Copy Markdown
Collaborator Author

Given that Zettlr may need to react to those changes, we should leave it. But anything that Zettlr doesn't need should be ignored. If we have to extend the list of exceptions in the future so be it!

So I did some testing to see what was emitted for git dirs, and I don't think anything relies on those types of event, and I don't think the code actually picks them up anyways. In a separate terminal, I tried doing some git commands on a folder opened as a workspace in Zettlr, and no events were emitted, doing things like touch test.md; git add test.md; git commit -m 'test', etc. did not emit the .git watchdog events. I think it should be safe to remove this special handling, as I don't think its needed, and I'm not sure its functional.

Regarding .ztr-directory, though, that does have events appropriately picked up, and I think it is used by the Zettlr for monitoring, so that should stay in.

@nathanlesage

Copy link
Copy Markdown
Member

Great – yes, changes to the .ztr-directory-file need to be caught by the FSAL so that Zettlr can update its sorting, display and other config settings for the corresponding directory. If the git-changes aren't caught, then we can remove any related code for now. At some point we might want to capture them, but for now it's fine if we don't.

@benniekiss

Copy link
Copy Markdown
Collaborator Author

Last commit builds the regex programmatically, which I think addresses all your points. I believe this is good to go on my end

@nathanlesage

Copy link
Copy Markdown
Member

Great, thank you so much! I will be merging this after 4.0 stable comes out, simply because I don't want to risk any potential delays. I'll release Zettlr 4.0 on Dec 26, so this thing will be merged this year.

FYI: I have taken the liberty of cherrypicking the fix for #5949 from this PR just to get that one bugfix over the bridge, too 👀

@nathanlesage nathanlesage left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I want to finally commit this large PR, and now that the code signing works again I believe we can take some risk with this large PR. A few, exclusively style-related suggestions. The code itself looks good.

(Also, nota bene: I just realized that, especially when it comes to big PRs, it is much easier for me to understand the code flow only when I haven't looked at the Zettlr source code for two weeks, and I have no idea why that is. But this time around I suddenly understood the entire PR!)

Comment thread source/common/util/ignore-path.ts Outdated
Comment thread source/common/util/ignore-path.ts Outdated
Comment thread source/common/util/ignore-path.ts Outdated
Comment thread source/common/util/ignore-path.ts Outdated
Comment thread source/common/util/ignore-path.ts Outdated
try {
dir.isGitRepository = (await fs.lstat(path.join(dir.path, '.git'))).isDirectory()
} catch (err: any) {}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can't we do a simple isDir-check? That would avoid this try/catch contraption.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

isDir is sync, which is why I avoided it here, but otherwise I have no problem using it.

Comment thread source/app/service-providers/fsal/fsal-watchdog.ts

return [ directoryPath, ...(await Promise.all(contents)).flat() ]
const { files } = this._config.get()
const ignoreDotFiles = !(files.dotFiles.showInFilemanager || files.dotFiles.showInSidebar)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Isn't this suggestion equal? Would avoid easy to miss brackets.

Suggested change
const ignoreDotFiles = !(files.dotFiles.showInFilemanager || files.dotFiles.showInSidebar)
const ignoreDotFiles = !files.dotFiles.showInFilemanager && !files.dotFiles.showInSidebar

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The current version short circuits, but otherwise they are the same end result

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Totally glossed over that your suggestion also short circuits, so Im gonna merge the change!


const children = await fs.readdir(absPath)
const { files } = this._config.get()
const ignoreDotFiles = !(files.dotFiles.showInFilemanager || files.dotFiles.showInSidebar)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as above comment?

Comment thread source/common/util/file-extention-checks.ts Outdated
@nathanlesage

Copy link
Copy Markdown
Member

Also, I appreciate that you took the time to fix a bunch of newly introduced any-warnings while you were at it!

benniekiss and others added 7 commits February 10, 2026 13:46
Co-authored-by: Hendrik Erz <hendrik@zettlr.com>
Co-authored-by: Hendrik Erz <hendrik@zettlr.com>
Co-authored-by: Hendrik Erz <hendrik@zettlr.com>
Co-authored-by: Hendrik Erz <hendrik@zettlr.com>
Co-authored-by: Hendrik Erz <hendrik@zettlr.com>
Co-authored-by: Hendrik Erz <hendrik@zettlr.com>
Co-authored-by: Hendrik Erz <hendrik@zettlr.com>
@benniekiss

Copy link
Copy Markdown
Collaborator Author

Just want your final opinions on the isDir and !files.dotFiles.showInFilemanager && !files.dotFiles.showInSidebar changes, otherwise this is good to go from my end!

@nathanlesage

Copy link
Copy Markdown
Member

Thanks a bunch! Looks good now – merging

@nathanlesage nathanlesage merged commit 4583fd5 into Zettlr:develop Feb 11, 2026
1 check passed
@benniekiss benniekiss deleted the hidden-files branch February 11, 2026 13:26
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.

File List shows .git-folder Zettlr Crashes on Start With Symlinks in Directory Tree

3 participants