Skip to content

Commit bd0ab70

Browse files
committed
Provide synchronization mechanisms between lsp and treemacs
- now when you add/remove folder(project) in lsp or in treemacs it will be automatically removed from the other. - the synchronization works when editing treemacs workspace via `treemacs-edit-workspaces` or if you switch the workspace with `treemacs-switch-workspace`
1 parent 7a6ef1b commit bd0ab70

File tree

2 files changed

+118
-51
lines changed

2 files changed

+118
-51
lines changed

README.org

+8-3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
* Table of Contents :TOC_4_gh:noexport:
22
- [[#summary][Summary]]
3+
- [[#synchronization][Synchronization]]
34
- [[#views][Views]]
45
- [[#lsp-treemacs-errors-list][lsp-treemacs-errors-list]]
56
- [[#commands][Commands]]
@@ -14,8 +15,12 @@
1415
- [[#screenshot-3][Screenshot]]
1516

1617
* Summary
17-
Integration between [[https://github.com/emacs-lsp/lsp-mode][lsp-mode]] and [[https://github.com/Alexander-Miller/treemacs][treemacs]] .
18-
18+
Integration between [[https://github.com/emacs-lsp/lsp-mode][lsp-mode]] and [[https://github.com/Alexander-Miller/treemacs][treemacs]] and implementation of treeview controls using [[https://github.com/Alexander-Miller/treemacs][treemacs]] as a tree renderer.
19+
* Synchronization
20+
To enable bidirectional synchronization of lsp workspace folders and [[https://github.com/Alexander-Miller/treemacs][treemacs]] projects.
21+
#+begin_src emacs-lisp
22+
(lsp-treemacs-sync-mode 1)
23+
#+end_src
1924
* Views
2025
** lsp-treemacs-errors-list
2126
Displays tree like error list structure.
@@ -36,7 +41,7 @@
3641
[[file:screenshots/dependencies.gif]]
3742
** lsp-metals-treeview
3843
Support for Scala Metals treeview. The treeview is disabled by default in order
39-
to enable the treeview use one of the following configuration approaches.
44+
to enable the treeview use one of the following configuration approaches.
4045
If you are using use-package:
4146
#+BEGIN_SRC elisp
4247

lsp-treemacs.el

+110-48
Original file line numberDiff line numberDiff line change
@@ -659,27 +659,27 @@
659659

660660
(defun lsp-treemacs-deps--get-children (dep)
661661
(lsp-treemacs-deps-with-jdtls
662-
(-let* (((&hash "projectUri" project-uri "rootPath" root-path "path" "kind" "name" "uri") dep)
663-
(project-uri (if (eq kind 2) uri project-uri)))
664-
(unless (or (= kind 6)
665-
(= kind 8))
666-
(->> (lsp-send-execute-command
667-
"java.getPackageData"
668-
(vector (ht ("kind" kind)
669-
("path" (unless (eq kind 2)
670-
(if (= 5 kind)
671-
name
672-
path)))
673-
("rootPath" (unless (eq kind 2)
674-
(or root-path path)))
675-
("projectUri" project-uri))))
676-
(-mapcat (lambda (inner-dep)
677-
(puthash "projectUri" project-uri inner-dep)
678-
(when (= kind 4)
679-
(puthash "rootPath" path inner-dep))
680-
(if (eq (gethash "entryKind" inner-dep) 3)
681-
(lsp-treemacs-deps--get-children inner-dep)
682-
(list inner-dep)))))))))
662+
(-let* (((&hash "projectUri" project-uri "rootPath" root-path "path" "kind" "name" "uri") dep)
663+
(project-uri (if (eq kind 2) uri project-uri)))
664+
(unless (or (= kind 6)
665+
(= kind 8))
666+
(->> (lsp-send-execute-command
667+
"java.getPackageData"
668+
(vector (ht ("kind" kind)
669+
("path" (unless (eq kind 2)
670+
(if (= 5 kind)
671+
name
672+
path)))
673+
("rootPath" (unless (eq kind 2)
674+
(or root-path path)))
675+
("projectUri" project-uri))))
676+
(-mapcat (lambda (inner-dep)
677+
(puthash "projectUri" project-uri inner-dep)
678+
(when (= kind 4)
679+
(puthash "rootPath" path inner-dep))
680+
(if (eq (gethash "entryKind" inner-dep) 3)
681+
(lsp-treemacs-deps--get-children inner-dep)
682+
(list inner-dep)))))))))
683683

684684
(defun lsp-treemacs-deps--java-file? (dep)
685685
(-let [(&hash "kind" "entryKind" entry-kind) dep]
@@ -693,8 +693,8 @@
693693
:query-function (-let (((dep &as &hash "uri") (treemacs-button-get node :dep)))
694694
(if (lsp-treemacs-deps--java-file? dep)
695695
(lsp-treemacs-deps-with-jdtls
696-
(lsp-request "textDocument/documentSymbol"
697-
`(:textDocument (:uri ,uri))))
696+
(lsp-request "textDocument/documentSymbol"
697+
`(:textDocument (:uri ,uri))))
698698
(lsp-treemacs-deps--get-children dep)))
699699
:ret-action 'lsp-treemacs-deps--goto-element
700700
:render-action (if (lsp-treemacs-deps--java-file? (treemacs-button-get node :dep))
@@ -717,12 +717,12 @@
717717

718718
(defun lsp-treemacs-deps--root-folders ()
719719
(lsp-treemacs-deps-with-jdtls
720-
(-mapcat (lambda (root-path)
721-
(let ((project-uri (lsp--path-to-uri root-path)))
722-
(->> project-uri
723-
(lsp-send-execute-command "java.project.list")
724-
(--map (--doto it (puthash "projectUri" project-uri it))))))
725-
(lsp-session-folders (lsp-session)))))
720+
(-mapcat (lambda (root-path)
721+
(let ((project-uri (lsp--path-to-uri root-path)))
722+
(->> project-uri
723+
(lsp-send-execute-command "java.project.list")
724+
(--map (--doto it (puthash "projectUri" project-uri it))))))
725+
(lsp-session-folders (lsp-session)))))
726726

727727
(treemacs-define-variadic-node lsp-treemacs-deps-list
728728
:query-function (lsp-treemacs-deps--root-folders)
@@ -793,25 +793,87 @@
793793
(defun lsp-treemacs-java-deps-follow ()
794794
(interactive)
795795
(lsp-treemacs-deps-with-jdtls
796-
(let ((paths (lsp-send-execute-command "java.resolvePath"
797-
(lsp--buffer-uri))))
798-
(select-window
799-
(with-current-buffer lsp-treemacs-deps-buffer-name
800-
(set-window-point
801-
(get-buffer-window)
802-
(marker-position
803-
(-reduce-from
804-
(-lambda (node (&hash "path" "name" "uri"))
805-
(unless (treemacs-is-node-expanded? node)
806-
(save-excursion
807-
(goto-char (marker-position node))
808-
(funcall (alist-get (treemacs-button-get node :state) treemacs-TAB-actions-config))))
809-
(or (lsp-treemacs--deps-find-children-for-key node (list name uri path))
810-
(user-error "Unable to find %s in the dependency tree." (buffer-name))))
811-
(treemacs-dom-node->position (treemacs-find-in-dom '(:custom LSP-Java-Dependency)))
812-
paths)))
813-
(get-buffer-window)))
814-
(recenter nil))))
796+
(let ((paths (lsp-send-execute-command "java.resolvePath"
797+
(lsp--buffer-uri))))
798+
(select-window
799+
(with-current-buffer lsp-treemacs-deps-buffer-name
800+
(set-window-point
801+
(get-buffer-window)
802+
(marker-position
803+
(-reduce-from
804+
(-lambda (node (&hash "path" "name" "uri"))
805+
(unless (treemacs-is-node-expanded? node)
806+
(save-excursion
807+
(goto-char (marker-position node))
808+
(funcall (alist-get (treemacs-button-get node :state) treemacs-TAB-actions-config))))
809+
(or (lsp-treemacs--deps-find-children-for-key node (list name uri path))
810+
(user-error "Unable to find %s in the dependency tree." (buffer-name))))
811+
(treemacs-dom-node->position (treemacs-find-in-dom '(:custom LSP-Java-Dependency)))
812+
paths)))
813+
(get-buffer-window)))
814+
(recenter nil))))
815+
816+
817+
;; treemacs synchronization
818+
819+
(defun lsp-treemacs--on-folder-remove (project)
820+
(lsp-workspace-folders-remove (treemacs-project->path project)))
821+
822+
(defun lsp-treemacs--on-folder-added (project)
823+
(lsp-workspace-folders-add (treemacs-project->path project)))
824+
825+
(defun lsp-treemacs--treemacs->lsp ()
826+
(let ((lsp-folders (lsp-session-folders (lsp-session)))
827+
(treemacs-folders (->> (treemacs-current-workspace)
828+
(treemacs-workspace->projects)
829+
(-map #'treemacs-project->path)
830+
(-map #'lsp-cannonical-file-name))))
831+
(seq-do #'lsp-workspace-folders-remove (-difference lsp-folders treemacs-folders))
832+
(seq-do #'lsp-workspace-folders-add (-difference treemacs-folders lsp-folders))))
833+
834+
(defun lsp-treemacs--sync-folders (added removed)
835+
(let ((treemacs-create-project-functions (remove #'lsp-treemacs--on-folder-added
836+
treemacs-create-project-functions))
837+
(treemacs-delete-project-functions (remove #'lsp-treemacs--on-folder-remove
838+
treemacs-delete-project-functions)))
839+
(seq-do (lambda (folder)
840+
(when (->> (treemacs-current-workspace)
841+
(treemacs-workspace->projects)
842+
(-none? (lambda (project)
843+
(f-same? (treemacs-project->path project)
844+
folder))))
845+
(treemacs-add-project-to-workspace folder)))
846+
added)
847+
(seq-do (lambda (folder)
848+
(when-let (project (->> (treemacs-current-workspace)
849+
(treemacs-workspace->projects)
850+
(-first (lambda (project)
851+
(f-same? (treemacs-project->path project)
852+
folder)))))
853+
(treemacs-do-remove-project-from-workspace project)))
854+
removed)))
855+
856+
;;;###autoload
857+
(define-minor-mode lsp-treemacs-sync-mode
858+
"Global minor mode for synchronizing lsp-mode workspace folders and treemacs projects."
859+
:init-value nil
860+
:group 'lsp-treemacs
861+
:global t
862+
(cond
863+
(lsp-treemacs-sync-mode
864+
(add-hook 'treemacs-create-project-functions #'lsp-treemacs--on-folder-added)
865+
(add-hook 'treemacs-delete-project-functions #'lsp-treemacs--on-folder-remove)
866+
(add-hook 'lsp-workspace-folders-changed-hook #'lsp-treemacs--sync-folders)
867+
(add-hook 'treemacs-workspace-edit-hook #'lsp-treemacs--treemacs->lsp)
868+
(add-hook 'treemacs-switch-workspace-hook #'lsp-treemacs--treemacs->lsp))
869+
(t
870+
(remove-hook 'treemacs-create-project-functions #'lsp-treemacs--on-folder-added)
871+
(remove-hook 'treemacs-delete-project-functions #'lsp-treemacs--on-folder-remove)
872+
(remove-hook 'lsp-workspace-folders-changed-hook #'lsp-treemacs--sync-folders)
873+
(remove-hook 'treemacs-workspace-edit-hook #'lsp-treemacs--treemacs->lsp)
874+
(remove-hook 'treemacs-switch-workspace-hook #'lsp-treemacs--treemacs->lsp))))
875+
876+
815877

816878
(provide 'lsp-treemacs)
817879
;;; lsp-treemacs.el ends here

0 commit comments

Comments
 (0)