branch: scratch/javaimp-list commit 295c799a9e0132f463761d7f4b4f8a1b5e604186 Author: Filipp Gunbin <fgun...@fastmail.fm> Commit: Filipp Gunbin <fgun...@fastmail.fm>
merge --- javaimp-list.el | 137 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ javaimp-util.el | 38 ++++++++++++++++ javaimp.el | 47 +++---------------- 3 files changed, 182 insertions(+), 40 deletions(-) diff --git a/javaimp-list.el b/javaimp-list.el new file mode 100644 index 0000000..c638753 --- /dev/null +++ b/javaimp-list.el @@ -0,0 +1,137 @@ + +;; Listing projects + +(defun javaimp-list-projects (buffer) + (unless (bufferp buffer) + (setq buffer (get-buffer-create "*Javaimp Projects*"))) + (with-current-buffer buffer + (javaimp-list-mode) + (javaimp-list-projects--refresh) + (tabulated-list-print)) + (display-buffer buffer) + nil) + +(defvar javaimp-list-mode-map + (let ((map (make-sparse-keymap))) + (define-key map (kbd "C-d") 'javaimp-list-forget-project) + (define-key map (kbd "RET") 'javaimp-list-display-project) + (define-key map [?i] 'javaimp-list-display-project) + map)) + +(define-derived-mode javaimp-list-mode tabulated-list-print + "Javaimp Project List" + "Major mode for listing the projects known by Javaimp." + (setq tabulated-list-format [("Artifact" 20 #'javaimp-list--artifact-lessp) + ("Group" 20 #'javaimp-list-group-lessp) + ("Version" 7 #'nil) + ("Build file" (length "build.gradle.kts") nil) + ("Loaded at" 10 t) + ("Directory" 0 nil) + ]) + (setq tabulated-list-sort-key (cons "Artifact" nil)) + (add-hook 'tabulated-list-revert-hook #'javaimp-list--refresh nil t)) + +(defun javaimp-list--artifact-lessp (entry1 entry2) + ;; TODO sort only by roots + nil + ) +(defun javaimp-list--group-lessp (entry1 entry2) + ;; TODO sort only by roots + nil + ) + +(defun javaimp-list--refresh () + "Recompute the list of projects for the Javaimp Project List +buffer." + (setq tabulated-list-entries nil) + + (dolist (node (javaimp--collect-nodes-from-tree javaimp-project-forest)) + (let* ((m (javaimp-node-contents node)) + (pm (and (javaimp-node-parent node) + (javaimp-node-contents (javaimp-node-parent node)))) + (mid (javaimp-module-id m)) + (pmid (and pm (javaimp-module-id pm))) + (root (javaimp--get-root node)) + + (depth (let ((ptr node) + (res 0)) + (while (setq ptr (javaimp-node-parent ptr)) + (setq res (1+ res))) + res)) + (artifact (concat (make-string depth ?-) (javaimp-id-artifact mid))) + + ;; show group and version only if different from parent + (group (if (and pmid + (javaimp-id-group mid) + (javaimp-id-group pmid) + (equal (javaimp-id-group mid) (javaimp-id-group pmid))) + "*" + (javaimp-id-group mid))) + (version (if (and pmid + (javaimp-id-version mid) + (javaimp-id-version pmid) + (equal (javaimp-id-version mid) (javaimp-id-version pmid))) + "*" + (javaimp-id-version mid))) + + ;; buttonize filename only if file exists + (basename (file-name-nondirectory (javaimp-module-file m))) + (file (if (file-exists-p (javaimp-module-file m)) + `(,basename + face link + follow-link t + help-echo "Visit file" + action ,(lambda (_btn) + (find-file (javaimp-module-file m)))) + (propertize basename 'face 'warning))) + + (time-format + (let ((daystart-dec (decode-time))) + (setf (decoded-time-second daystart-dec) 0) + (setf (decoded-time-minute daystart-dec) 0) + (setf (decoded-time-hour daystart-dec) 0) + (if (time-less-p (javaimp-module-load-ts m) + (encode-time daystart-dec)) + "%c" "%X"))) + (load-ts time-format (javaimp-module-load-ts m)) + + (absdir (file-name-directory (javaimp-module-file m))) + ;; show dir relatively to root if have parent + (dir-name + (if pm + (let ((root-dir (file-name-directory + (javaimp-module-file + (javaimp-node-contents root))))) + (file-relative-name dir root-dir)) + absdir)) + (dir `(,dir-name + face link + follow-link t + help-echo "Visit directory" + action ,(lambda (_btn) + (find-file absdir)))) + )) + (push (list mid (vector + artifact (or group "--") (or version "--") + dir file load-ts)) + tabulated-list-entries)) + (tabulated-list-init-header)) + +;; TODO only top-level +(defun javaimp-list--forget-project () + "Forget project tree containing project at point." + (interactive) + + (let ((pos (point))) + (delete-process (tabulated-list-get-id)) + (revert-buffer) + (goto-char (min pos (point-max))) + (if (eobp) + (forward-line -1) + (beginning-of-line)))) + +(defun javaimp-list--display-project () + "Display detailed information for project at point." + ;; TODO detailed, with-output-to-temp-buffer + + ) diff --git a/javaimp-util.el b/javaimp-util.el index f2f4c00..e86a795 100644 --- a/javaimp-util.el +++ b/javaimp-util.el @@ -137,6 +137,10 @@ buffer and returns its result" (concat "[" path-separator "\n]+") t))) + + +;; Tree building & search + (defun javaimp--build-tree (this parent-node all) (message "Building tree for module: %s" (javaimp-print-id (javaimp-module-id this))) (let ((children @@ -209,4 +213,38 @@ buffer and returns its result" (push (mapconcat #'identity curr ".") res))))) (nreverse res)))) +(defun javaimp--find-node (predicate forest) + (catch 'found + (dolist (tree forest) + (javaimp--find-node-in-tree-1 tree predicate)))) + +(defun javaimp--find-node-in-tree-1 (tree predicate) + (when tree + (if (funcall predicate (javaimp-node-contents tree)) + (throw 'found tree)) + (dolist (child (javaimp-node-children tree)) + (javaimp--find-node-in-tree-1 child predicate)))) + + +(defun javaimp--collect-nodes (predicate forest) + (apply #'seq-concatenate 'list + (mapcar (lambda (tree) + (javaimp--collect-nodes-from-tree tree predicate)) + forest))) + +(defun javaimp--collect-nodes-from-tree (tree &optional predicate) + (when tree + (append (when (or (not predicate) + (funcall predicate (javaimp-node-contents tree))) + (list tree)) + (apply #'seq-concatenate 'list + (mapcar (lambda (child) + (javaimp--collect-nodes-from-tree child predicate)) + (javaimp-node-children tree)))))) + +(defun javaimp--get-root (node) + (while (javaimp-node-parent node) + (setq node (javaimp-node-parent node))) + node) + (provide 'javaimp-util) diff --git a/javaimp.el b/javaimp.el index 1ea804d..ce92a4b 100644 --- a/javaimp.el +++ b/javaimp.el @@ -197,7 +197,7 @@ any module file." javaimp-project-forest)) (push (car trees) javaimp-project-forest) (dolist (node (cdr trees)) - (when (y-or-n-p (format "Include additional project tree rooted at %s? " + (when (y-or-n-p (format "Include additional project tree rooted at %S? " (javaimp-module-id (javaimp-node-contents node)))) (push node javaimp-project-forest))) (message "Loaded tree for %s" dir))) @@ -292,52 +292,18 @@ any module file." result)))) -;; Tree search routines - -(defun javaimp--find-node (predicate) - (catch 'found - (dolist (tree javaimp-project-forest) - (javaimp--find-node-in-tree-1 tree predicate)))) - -(defun javaimp--select-nodes (predicate) - (apply #'seq-concatenate 'list - (mapcar (lambda (tree) - (javaimp--select-nodes-from-tree tree predicate)) - javaimp-project-forest))) - -(defun javaimp--find-node-in-tree (tree predicate) - (catch 'found - (javaimp--find-node-in-tree-1 tree predicate))) - -(defun javaimp--find-node-in-tree-1 (tree predicate) - (when tree - (if (funcall predicate (javaimp-node-contents tree)) - (throw 'found tree)) - (dolist (child (javaimp-node-children tree)) - (javaimp--find-node-in-tree-1 child predicate)))) - -(defun javaimp--select-nodes-from-tree (tree predicate) - (when tree - (append (if (funcall predicate (javaimp-node-contents tree)) - (list tree)) - (apply #'seq-concatenate 'list - (mapcar (lambda (child) - (javaimp--select-nodes-from-tree child predicate)) - (javaimp-node-children tree)))))) - - ;; Some API functions - +;; ;; do not expose tree structure, return only modules (defun javaimp-find-module (predicate) - (let ((node (javaimp--find-node predicate))) + (let ((node (javaimp--find-node predicate javaimp-project-forest))) (and node (javaimp-node-contents node)))) -(defun javaimp-select-modules (predicate) +(defun javaimp-collect-modules (predicate) (mapcar #'javaimp-node-contents - (javaimp--select-nodes predicate))) + (javaimp--collect-nodes predicate javaimp-project-forest))) ;;; Adding imports @@ -374,7 +340,8 @@ prefix arg is given, don't do this filtering." (lambda (m) (seq-some (lambda (dir) (string-prefix-p dir file)) - (javaimp-module-source-dirs m))))) + (javaimp-module-source-dirs m))) + javaimp-project-forest)) (module (when node (javaimp--update-module-maybe node) (javaimp-node-contents node)))