diff options
| author | Craig Jennings <c@cjennings.net> | 2026-04-26 19:40:22 -0500 |
|---|---|---|
| committer | Craig Jennings <c@cjennings.net> | 2026-04-26 19:40:22 -0500 |
| commit | 781b46e4eb7c08a3db01b1c1d89677ba8e21fd98 (patch) | |
| tree | 7cc93086d8f644d861aa1c81d46c13a47e524ae8 | |
| parent | fbca79c1e06b41099c1a4d18b587bc8c4611e777 (diff) | |
| download | dotemacs-781b46e4eb7c08a3db01b1c1d89677ba8e21fd98.tar.gz dotemacs-781b46e4eb7c08a3db01b1c1d89677ba8e21fd98.zip | |
feat(lsp): add common build/cache dirs to file-watch ignore list
Extends `lsp-file-watch-ignored-directories' with thirteen build, cache, and tooling directories: `node_modules', `dist', `coverage', `target', `__pycache__', `.venv', `venv', `.pytest_cache', `.mypy_cache', `.ruff_cache', `test-results', `playwright-report', `tf/.terraform'. Uses `add-to-list', so lsp-mode's own defaults (`.git', `.svn', `.idea', etc.) stay in place.
Setting these in a project's `.dir-locals.el' doesn't work. lsp-mode reads `lsp-file-watch-ignored-directories' once at workspace init, from the global value, so a buffer-local override never reaches the watch list. I confirmed this today: in a Python buffer where dir-locals had applied, `M-: lsp-file-watch-ignored-directories' returned the lsp-mode default, not the project's overrides. Setting it globally is what works.
The goal is to push typical workspaces under `lsp-file-watch-threshold' (1000), so the "watch all files? (y or n)" prompt stops firing on every fresh LSP start.
Also added a forward defvar for `lsp-enable-remote' to silence the matching free-variable warning under `make compile'.
| -rw-r--r-- | modules/prog-lsp.el | 39 | ||||
| -rw-r--r-- | tests/test-prog-lsp--add-file-watch-ignored-extras.el | 87 |
2 files changed, 125 insertions, 1 deletions
diff --git a/modules/prog-lsp.el b/modules/prog-lsp.el index c976a83e..a6037db8 100644 --- a/modules/prog-lsp.el +++ b/modules/prog-lsp.el @@ -8,6 +8,42 @@ ;;; Code: +;; Forward declarations for byte-compile and let-binding under lexical scope. +;; Real definitions are lsp-mode's defcustoms. +(defvar lsp-file-watch-ignored-directories) +(defvar lsp-enable-remote) + +;;;;; --------------------- File-Watch Ignore Patterns --------------------- +;; lsp-mode prompts when a workspace exceeds `lsp-file-watch-threshold' (1000) +;; directories. Real source repos cross that line easily once node_modules, +;; build outputs, and language caches are counted. These patterns extend the +;; lsp-mode defaults (.git, .svn, .idea, ...) instead of replacing them, so the +;; built-in VC/IDE excludes still apply. Buffer-local overrides via +;; `.dir-locals.el' don't work — lsp-mode reads the global value at workspace +;; init, not the buffer-local one. Hence: global defaults here. + +(defvar cj/lsp-file-watch-ignored-extras + '("[/\\\\]node_modules\\'" + "[/\\\\]\\.ruff_cache\\'" + "[/\\\\]dist\\'" + "[/\\\\]coverage\\'" + "[/\\\\]test-results\\'" + "[/\\\\]playwright-report\\'" + "[/\\\\]tf[/\\\\]\\.terraform\\'" + "[/\\\\]__pycache__\\'" + "[/\\\\]\\.venv\\'" + "[/\\\\]venv\\'" + "[/\\\\]\\.pytest_cache\\'" + "[/\\\\]\\.mypy_cache\\'" + "[/\\\\]target\\'") + "Build/cache directory patterns to add to `lsp-file-watch-ignored-directories'. +Each entry is an Emacs regex matching a path ending in the named directory.") + +(defun cj/lsp--add-file-watch-ignored-extras () + "Append `cj/lsp-file-watch-ignored-extras' to lsp-mode's ignore list. +Idempotent — `add-to-list' skips patterns already present." + (dolist (pattern cj/lsp-file-watch-ignored-extras) + (add-to-list 'lsp-file-watch-ignored-directories pattern))) ;;;;; ---------------------------- LSP Mode --------------------------- @@ -38,7 +74,8 @@ (setq lsp-enable-imenu nil) (setq lsp-enable-snippet nil) (setq read-process-output-max (* 1024 1024)) ;; 1MB - (setq lsp-idle-delay 0.5)) + (setq lsp-idle-delay 0.5) + (cj/lsp--add-file-watch-ignored-extras)) ;;;;; ----------------------------- LSP UI ---------------------------- diff --git a/tests/test-prog-lsp--add-file-watch-ignored-extras.el b/tests/test-prog-lsp--add-file-watch-ignored-extras.el new file mode 100644 index 00000000..255832e4 --- /dev/null +++ b/tests/test-prog-lsp--add-file-watch-ignored-extras.el @@ -0,0 +1,87 @@ +;;; test-prog-lsp--add-file-watch-ignored-extras.el --- Tests for cj/lsp--add-file-watch-ignored-extras -*- lexical-binding: t; -*- + +;;; Commentary: +;; Tests for cj/lsp--add-file-watch-ignored-extras in prog-lsp.el. +;; The function adds project-agnostic build/cache directory patterns to +;; `lsp-file-watch-ignored-directories' without replacing lsp-mode's +;; defaults. Patterns are sourced from `cj/lsp-file-watch-ignored-extras'. + +;;; Code: + +(require 'ert) +(require 'cl-lib) + +;; Declare lsp-mode's defcustom as a special variable so `let' binds it +;; dynamically. Real definition is lsp-mode's; loaded only when use-package +;; activates lsp-mode. In the test environment, this stub provides the value +;; cell `add-to-list' needs. +(defvar lsp-file-watch-ignored-directories nil) + +(require 'prog-lsp) + +;;; Normal Cases + +(ert-deftest test-prog-lsp--add-file-watch-ignored-extras-normal-adds-all-patterns () + "Normal: every entry from `cj/lsp-file-watch-ignored-extras' lands in the list." + (let ((lsp-file-watch-ignored-directories nil)) + (cj/lsp--add-file-watch-ignored-extras) + (should (= (length lsp-file-watch-ignored-directories) + (length cj/lsp-file-watch-ignored-extras))) + (dolist (pattern cj/lsp-file-watch-ignored-extras) + (should (member pattern lsp-file-watch-ignored-directories))))) + +(ert-deftest test-prog-lsp--add-file-watch-ignored-extras-normal-extends-not-replaces () + "Normal: pre-existing entries (lsp-mode defaults) are preserved." + (let ((lsp-file-watch-ignored-directories + '("[/\\\\]\\.git\\'" "[/\\\\]\\.svn\\'" "[/\\\\]\\.idea\\'"))) + (cj/lsp--add-file-watch-ignored-extras) + (should (member "[/\\\\]\\.git\\'" lsp-file-watch-ignored-directories)) + (should (member "[/\\\\]\\.svn\\'" lsp-file-watch-ignored-directories)) + (should (member "[/\\\\]\\.idea\\'" lsp-file-watch-ignored-directories)) + (dolist (pattern cj/lsp-file-watch-ignored-extras) + (should (member pattern lsp-file-watch-ignored-directories))))) + +(ert-deftest test-prog-lsp--add-file-watch-ignored-extras-normal-key-patterns-present () + "Normal: specific expected directory names appear in the constant." + (dolist (name '("node_modules" "target" "__pycache__" ".venv" "venv" + "dist" "coverage" "test-results" "playwright-report" + ".terraform" ".ruff_cache" ".pytest_cache" ".mypy_cache")) + (should (cl-some (lambda (p) (string-match-p (regexp-quote name) p)) + cj/lsp-file-watch-ignored-extras)))) + +;;; Boundary Cases + +(ert-deftest test-prog-lsp--add-file-watch-ignored-extras-boundary-idempotent () + "Boundary: calling twice doesn't duplicate entries." + (let ((lsp-file-watch-ignored-directories nil)) + (cj/lsp--add-file-watch-ignored-extras) + (cj/lsp--add-file-watch-ignored-extras) + (should (= (length lsp-file-watch-ignored-directories) + (length cj/lsp-file-watch-ignored-extras))))) + +(ert-deftest test-prog-lsp--add-file-watch-ignored-extras-boundary-all-patterns-non-empty () + "Boundary: every pattern is a non-empty string." + (dolist (pattern cj/lsp-file-watch-ignored-extras) + (should (stringp pattern)) + (should (not (string-empty-p pattern))))) + +(ert-deftest test-prog-lsp--add-file-watch-ignored-extras-boundary-all-patterns-valid-regex () + "Boundary: every pattern compiles as a valid Emacs regex." + (dolist (pattern cj/lsp-file-watch-ignored-extras) + (condition-case err + ;; string-match-p compiles the regex; invalid syntax raises invalid-regexp. + (string-match-p pattern "/some/sample/path") + (invalid-regexp + (ert-fail (format "Invalid regex %S: %s" + pattern (error-message-string err))))))) + +;;; Error Cases + +(ert-deftest test-prog-lsp--add-file-watch-ignored-extras-error-non-list-target () + "Error: non-list target value triggers `add-to-list' wrong-type-argument." + (let ((lsp-file-watch-ignored-directories "not-a-list")) + (should-error (cj/lsp--add-file-watch-ignored-extras) + :type 'wrong-type-argument))) + +(provide 'test-prog-lsp--add-file-watch-ignored-extras) +;;; test-prog-lsp--add-file-watch-ignored-extras.el ends here |
