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
Watch subdirectories #1829
Watch subdirectories #1829
Conversation
1bbab5f
to
4066bd9
Compare
sorry about the git noise. I was accidentally on an old version of master. should be updated and now in a single clean commit. |
4066bd9
to
b546542
Compare
Watching is recursive. When watching a project, it registers a watch on every subdirectory in the project. With node modules and compilation output, this can get enormous, easily hitting the watch count. Setting `lsp-watch-folders` can specify the source files to be watched rather than the every subdirectory of the project. `hack-local-variables` to ensure dir-locals are applied at start without this, on first startup dir local values for `lsp-watch-folders` are not found. They _are_ found on restart. If we hack local variables here they are found on startup. Correctly cleanup watched sub folders Want to avoid watching the root but still want the watches to be registered under the root so the current cleanup apparatus can find it and clean up. Put a top level `lsp-watch-root-folder` which can take subdirectories and put each of these watch subtrees under the top level root. Considered using a defcustom allow-list similar to the `lsp-file-watch-ignored` but don't want to consider these at all levels but solely under the top level directory.
b546542
to
f33755d
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you for contributing.
I was thinking about the implementation - can we have a list of regexes which are used to override the current list of all folders. E. g. you can set ignored filters to .*
(ignore all) and then set the force
watch folders variable to ("foo" "bar")
?
@@ -501,6 +501,14 @@ the server has requested that." | |||
:package-version '(lsp-mode . "6.1")) | |||
;;;###autoload(put 'lsp-enable-file-watchers 'safe-local-variable #'booleanp) | |||
|
|||
(defcustom lsp-watch-folders nil |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can we have a regexp as well?
lsp-mode.el
Outdated
@@ -7191,13 +7217,21 @@ returns the command to execute." | |||
INITIALIZATION-OPTIONS are passed to initialize function. | |||
SESSION is the active session." | |||
(lsp--spinner-start) | |||
(hack-local-variables) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we are not allowed to do that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@kiennq had the same comment inline but i think the UI will obscure it some so i'll paste it here as well:
I'm not sure why its needed but I'll explain the problem it seems to solve. When I would start up emacs fresh and enter a project, the var lsp-watch-folders wasn't picked up. I would then lsp-restart-workspace and it was seen. I did that as a kludge to get it to pick them up but not sure why they weren't in the first place. I'll try again though.
lsp-mode.el
Outdated
;; create watch for each root folder without such | ||
(dolist (folder root-folders) | ||
(let ((watch (make-lsp-watch :root-directory folder))) | ||
(puthash folder watch created-watches) | ||
(lsp-watch-root-folder (file-truename folder) | ||
(when (f-equal? folder workspace-root) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shouldn't this to use lsp-f-same?
?
I don't think we need to follow symlink when compare the workspace-root
here
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
didn't know about that one. looks good to me.
lsp-mode.el
Outdated
@@ -7191,13 +7217,21 @@ returns the command to execute." | |||
INITIALIZATION-OPTIONS are passed to initialize function. | |||
SESSION is the active session." | |||
(lsp--spinner-start) | |||
(hack-local-variables) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why this is needed?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure why its needed but I'll explain the problem it seems to solve. When I would start up emacs fresh and enter a project, the var lsp-watch-folders
wasn't picked up. I would then lsp-restart-workspace
and it was seen. I did that as a kludge to get it to pick them up but not sure why they weren't in the first place. I'll try again though.
I thought about doing regexes similar to the ignore list and i chose this path for two reasons:
I'm not married to this implementation by any means so if the regex version sounds better to you as a maintainer this can be adapted or scrapped as you see fit. My usage would end up being "src|test" anyways. It feels a bit wrong to investigate at arbitrary depth which folders match this grant regex when i just want to set up watches of root source directories rather than the whole project. As an aside, it is quite nice to have both of your eyes on the changes so quickly and makes it quite pleasant to discuss and work on this great project. So thanks much for that! |
I don't think anyone is happy with the update: i ran |
In multi-module project you would like to watch
Can you elaborate? It seems to me that all will narrow down to (or (not (lsp--string-match-any <PATH> ignore-list))
(lsp--string-match-any <PATH> allow-list)) |
At the beginning of the project, we decided not to call |
I never had a good mental model of what multi module projects looked like so i hadn't considered this. The code as it is now considers a project to have a single root and passes the subdirectories along when the root is found but not for other project roots because i didn't really know what they were. (or (not (lsp--string-match-any <PATH> ignore-list))
(lsp--string-match-any <PATH> allow-list)) Doing this brings up strange semantics in my opinion. If a file matches both the ignore and allow regexes, what should happen? If a file matches neither the ignore or allow regexes, what should happen. Its clear from the code that it will be watching in both cases but just reading documentation or the var names might have very different expectations. I like the current implementation because its more clear: rather than watching the root directory, watch these sub directories, with the same ability to use the ignore regex as it currently exists. Having both an ignore and allow regex that don't necessarily partition the set of all files turns the allow regex into an ignore-override regex which is strange. Otherwise the expectation of what to do with files that are neither ignored nor allowed seems a bit strange. Again, not trying to be obstinate, and love the conversation. Thank you both again. |
Does this signal that you are willing to rethink the the current decision not to use |
Spacemacs has a solution for that and it is all good. So, we might investigate how to make all the things easier for the users. The issue here is that the dir locals are not available in major-mode hook.
There is an entry in lsp-mode FAQ explaining what you can do. So, I reread your comments and it seems like you are trying to achieve not exactly what I was thinking in the first place. What you are trying to do is to override the project root, right? If yes, I will spend some time checking the code and see what we can do. Your solution might be working but it looks a bit more complex than it should (at least to me). |
yup. i'll remove the
I'm sorry about that. I should have been more clear with my problem statement. My aim is to provide the source directories i want watched so that i'm not registering 4400 watches in our project. With my change, there are 140 or so watches for source files. Our work project is a cljs project so we have lots of compilation output in development mode all of which are unnecessarily watched. We have migrations, static resources, a vendored js project with 122 subfolders for locales, etc. And the only thing i'm interested in are watching the folders containing the clj and cljs files. (length
(ht-keys
(lsp-watch-descriptors (ht-get (lsp-session-watches)
"/Users/dan/projects/clojure/acl"))))
;; 106 vs 473 and a warning about watching 4400 files without the subdirectories set. |
Create a defcustom
lsp-watch-folders
.At work our project has thousands of directories and many directories at the top level that are not interesting as watch roots. There is a way to ignore files and these are checked at every level. It would be far easier to create an allow list. However, this allow-list should be checked only at the top level rather than everywhere like the ignore list.
This PR creates this functionality. It can be easily set in dir-locals like:
I added some tests but I've found a few relating to the file watchers a) don't run in CI due to the presence of the
:tags '(no-win)
metadata and b) when i specify to run them explicitly, they fail.and on master: