Alexander-Miller / treemacs

GNU General Public License v3.0
2.08k stars 152 forks source link

How to do proper DOM manipulation? #801

Closed Townk closed 2 years ago

Townk commented 3 years ago

This is a question / doc request for those, like me, that use Treemacs extension API on their own package.

My first package to use Treemacs is org-ol-tree, which tries to display an Org buffer as an Outline tree on a side window.

The basic tree building, expanding, collapsing, and renaming all work just fine, and I could not be happier.

My problem started when I tried to implement a feature that allow users to "move" headlines around, like they would do on and actual Org file. The org part of the feature works without any problem, but I can't get the Treemacs API to work as I expected!

For instance, when I'm on a headline and I press M-left, my package promotes the headline on the Org buffer, and tries to do the same on the tree. What I tried to do, was to erase the tree buffer, and rebuild the tree with the updated version of the Org buffer. This seams to work as the tree gets updated, but I can't navigate to the correct position, so the tree ultimately stays collapsed.

This is a gif showing the current behavior:

CleanShot 2021-04-11 at 22 57 58

The relevant function on my package is the refresh, which I'm reproducing here:

(defun org-ol-tree-action--refresh (&optional prevent-rebuild target-section-id target-state)
  "Refresh the Outline tree.

If PREVENT-REBUILD is non nil, this function just refresh the buffer content
without refreshing the base data.

If TARGET-SECTION-ID is not nil, uses it instead of the current headline id.

If TARGET-STATE is not nil, use it instead of the one on the current headline."
  (interactive)

  (when org-ol-tree--buffer-p
    (let* ((headline (org-ol-tree-core--current-headline))
           (target-section-id (or target-section-id (when headline
                                                      (org-ol-tree-core--headline-id headline))))
           (target-state (or target-state
                             (org-ol-tree-core--state (org-ol-tree-core--node-get :state)))))

      (unless prevent-rebuild
        (org-ol-tree-ui--build-outline-tree))

      (org-ol-tree-action--goto-root)
      (org-ol-tree-core--collapse)
      (org-ol-tree-action--goto-setion target-section-id target-state)
      (message "Refresh completed"))))

You can see this function on my refactor branch here.

So, my question/request is this:

How to manipulate the tree structure on Treemacs, update it, and save/restore node position correctly?

Townk commented 3 years ago

I forgot to mention, that after I refresh the tree couple times, I start getting errors on Treemacs functions:

Debugger entered--Lisp error: (void-function nil)
  nil(#<marker (moves after insertion) at 59 in *OrgOutlineTree:org-ol-tree/README.org*>)
  treemacs--reopen-node(#<marker (moves after insertion) at 59 in *OrgOutlineTree:org-ol-tree/README.org*> nil)
  treemacs--reentry((:custom root "1"))
  (progn (let* ((key (get-text-property node :path))) (let ((dom-node (gethash key treemacs-dom nil))) (if dom-node (progn (let* ((v dom-node)) (aset v 5 node)) (let ((--dolist-tail-- ...)) (while --dolist-tail-- (let ... ... ...))) (let ((parent-dom-node ...)) (if parent-dom-node (progn ...)))) (setq dom-node (record 'treemacs-dom-node key nil nil nil node nil nil)) (prog1 nil (puthash (progn (progn ...)) dom-node treemacs-dom))))) (treemacs--reentry (get-text-property node :path)) (org-ol-tree-ui--window-resize))
  (let (buffer-read-only) (put-text-property (or (previous-single-property-change (1+ node) 'button) (point-min)) (or (next-single-property-change node 'button) (point-max)) :state 'treemacs-org-ol-parent-section-open-state) (beginning-of-line) (let* ((new-sym (org-ol-tree-ui--section-icon (org-ol-tree-core--node-get :headline node) 'expanded))) (save-excursion (let ((len (length new-sym))) (goto-char (- (let* (...) (or ... ...)) len)) (insert new-sym) (delete-char len)))) (goto-char (or (next-single-property-change node 'button) (point-max))) (progn (insert (apply #'concat (let* ((depth depth) (prefix (concat "\n" ...)) (item (car items)) (strings)) (if item (progn (let ... ...))) (nreverse strings))))) (progn (let* ((key (get-text-property node :path))) (let ((dom-node (gethash key treemacs-dom nil))) (if dom-node (progn (let* (...) (aset v 5 node)) (let (...) (while --dolist-tail-- ...)) (let (...) (if parent-dom-node ...))) (setq dom-node (record 'treemacs-dom-node key nil nil nil node nil nil)) (prog1 nil (puthash (progn ...) dom-node treemacs-dom))))) (treemacs--reentry (get-text-property node :path)) (org-ol-tree-ui--window-resize)))
  (let* ((p (point))) (let (buffer-read-only) (put-text-property (or (previous-single-property-change (1+ node) 'button) (point-min)) (or (next-single-property-change node 'button) (point-max)) :state 'treemacs-org-ol-parent-section-open-state) (beginning-of-line) (let* ((new-sym (org-ol-tree-ui--section-icon (org-ol-tree-core--node-get :headline node) 'expanded))) (save-excursion (let ((len (length new-sym))) (goto-char (- (let* ... ...) len)) (insert new-sym) (delete-char len)))) (goto-char (or (next-single-property-change node 'button) (point-max))) (progn (insert (apply #'concat (let* ((depth depth) (prefix ...) (item ...) (strings)) (if item (progn ...)) (nreverse strings))))) (progn (let* ((key (get-text-property node :path))) (let ((dom-node (gethash key treemacs-dom nil))) (if dom-node (progn (let* ... ...) (let ... ...) (let ... ...)) (setq dom-node (record ... key nil nil nil node nil nil)) (prog1 nil (puthash ... dom-node treemacs-dom))))) (treemacs--reentry (get-text-property node :path)) (org-ol-tree-ui--window-resize))) (count-lines p (point)))
  (save-excursion (let* ((p (point))) (let (buffer-read-only) (put-text-property (or (previous-single-property-change (1+ node) 'button) (point-min)) (or (next-single-property-change node 'button) (point-max)) :state 'treemacs-org-ol-parent-section-open-state) (beginning-of-line) (let* ((new-sym (org-ol-tree-ui--section-icon (org-ol-tree-core--node-get :headline node) 'expanded))) (save-excursion (let ((len ...)) (goto-char (- ... len)) (insert new-sym) (delete-char len)))) (goto-char (or (next-single-property-change node 'button) (point-max))) (progn (insert (apply #'concat (let* (... ... ... ...) (if item ...) (nreverse strings))))) (progn (let* ((key (get-text-property node :path))) (let ((dom-node ...)) (if dom-node (progn ... ... ...) (setq dom-node ...) (prog1 nil ...)))) (treemacs--reentry (get-text-property node :path)) (org-ol-tree-ui--window-resize))) (count-lines p (point))))
  (prog1 (save-excursion (let* ((p (point))) (let (buffer-read-only) (put-text-property (or (previous-single-property-change (1+ node) 'button) (point-min)) (or (next-single-property-change node 'button) (point-max)) :state 'treemacs-org-ol-parent-section-open-state) (beginning-of-line) (let* ((new-sym (org-ol-tree-ui--section-icon ... ...))) (save-excursion (let (...) (goto-char ...) (insert new-sym) (delete-char len)))) (goto-char (or (next-single-property-change node 'button) (point-max))) (progn (insert (apply #'concat (let* ... ... ...)))) (progn (let* ((key ...)) (let (...) (if dom-node ... ... ...))) (treemacs--reentry (get-text-property node :path)) (org-ol-tree-ui--window-resize))) (count-lines p (point)))) (if treemacs-move-forward-on-expand (progn (let* ((parent (let (...) (if result ...))) (child (next-button parent))) (if (equal parent (get-text-property child :parent)) (progn (forward-line 1)))))))
  (let ((items (reverse (org-ol-tree-core--headline-children (org-ol-tree-core--node-get :headline node)))) (depth (1+ (get-text-property node :depth))) (parent-dom-node (let* ((key (get-text-property node :path))) (gethash key treemacs-dom nil)))) (prog1 (save-excursion (let* ((p (point))) (let (buffer-read-only) (put-text-property (or (previous-single-property-change ... ...) (point-min)) (or (next-single-property-change node ...) (point-max)) :state 'treemacs-org-ol-parent-section-open-state) (beginning-of-line) (let* ((new-sym ...)) (save-excursion (let ... ... ... ...))) (goto-char (or (next-single-property-change node ...) (point-max))) (progn (insert (apply ... ...))) (progn (let* (...) (let ... ...)) (treemacs--reentry (get-text-property node :path)) (org-ol-tree-ui--window-resize))) (count-lines p (point)))) (if treemacs-move-forward-on-expand (progn (let* ((parent (let ... ...)) (child (next-button parent))) (if (equal parent (get-text-property child :parent)) (progn (forward-line 1))))))))
  treemacs--do-expand-org-ol-parent-section(#<marker (moves after insertion) at 31 in *OrgOutlineTree:org-ol-tree/README.org*>)
  (let* ((node (let ((result (text-property-not-all (point-at-bol) (point-at-eol) 'button nil))) (if result (progn (copy-marker result t)))))) (if (null node) (progn (throw '--cl-block-__body__-- (treemacs-pulse-on-failure "There is nothing to do here.")))) (if (not (eq 'treemacs-org-ol-parent-section-closed-state (get-text-property node :state))) (progn (throw '--cl-block-__body__-- (treemacs-pulse-on-failure "This function cannot expand a node of type '%s'." (propertize (format "%s" (get-text-property node :state)) 'face 'font-lock-type-face))))) (treemacs--do-expand-org-ol-parent-section node))
  (catch '--cl-block-__body__-- (let* ((node (let ((result (text-property-not-all ... ... ... nil))) (if result (progn (copy-marker result t)))))) (if (null node) (progn (throw '--cl-block-__body__-- (treemacs-pulse-on-failure "There is nothing to do here.")))) (if (not (eq 'treemacs-org-ol-parent-section-closed-state (get-text-property node :state))) (progn (throw '--cl-block-__body__-- (treemacs-pulse-on-failure "This function cannot expand a node of type '%s'." (propertize (format "%s" ...) 'face 'font-lock-type-face))))) (treemacs--do-expand-org-ol-parent-section node)))
  treemacs-expand-org-ol-parent-section(#<marker (moves after insertion) at 31 in *OrgOutlineTree:org-ol-tree/README.org*>)
  treemacs--reopen-node(#<marker (moves after insertion) at 31 in *OrgOutlineTree:org-ol-tree/README.org*> nil)
  treemacs--reentry((:custom root))
  (progn (let* ((key (get-text-property node :path))) (let ((dom-node (gethash key treemacs-dom nil))) (if dom-node (progn (let* ((v dom-node)) (aset v 5 node)) (let ((--dolist-tail-- ...)) (while --dolist-tail-- (let ... ... ...))) (let ((parent-dom-node ...)) (if parent-dom-node (progn ...)))) (setq dom-node (record 'treemacs-dom-node key nil nil nil node nil nil)) (prog1 nil (puthash (progn (progn ...)) dom-node treemacs-dom))))) (treemacs--reentry (get-text-property node :path)) (org-ol-tree-ui--window-resize))
  (let (buffer-read-only) (put-text-property (or (previous-single-property-change (1+ node) 'button) (point-min)) (or (next-single-property-change node 'button) (point-max)) :state 'treemacs-org-ol-doc-open-state) (beginning-of-line) (save-excursion (let ((len (length treemacs-icon-org-ol-doc-open))) (goto-char (- (let* ((button ...)) (or (previous-single-property-change ... ...) (point-min))) len)) (insert treemacs-icon-org-ol-doc-open) (delete-char len))) (goto-char (or (next-single-property-change node 'button) (point-max))) (progn (insert (apply #'concat (let* ((depth depth) (prefix (concat "\n" ...)) (item (car items)) (strings)) (if item (progn (let ... ...))) (nreverse strings))))) (progn (let* ((key (get-text-property node :path))) (let ((dom-node (gethash key treemacs-dom nil))) (if dom-node (progn (let* (...) (aset v 5 node)) (let (...) (while --dolist-tail-- ...)) (let (...) (if parent-dom-node ...))) (setq dom-node (record 'treemacs-dom-node key nil nil nil node nil nil)) (prog1 nil (puthash (progn ...) dom-node treemacs-dom))))) (treemacs--reentry (get-text-property node :path)) (org-ol-tree-ui--window-resize)))
  (let* ((p (point))) (let (buffer-read-only) (put-text-property (or (previous-single-property-change (1+ node) 'button) (point-min)) (or (next-single-property-change node 'button) (point-max)) :state 'treemacs-org-ol-doc-open-state) (beginning-of-line) (save-excursion (let ((len (length treemacs-icon-org-ol-doc-open))) (goto-char (- (let* (...) (or ... ...)) len)) (insert treemacs-icon-org-ol-doc-open) (delete-char len))) (goto-char (or (next-single-property-change node 'button) (point-max))) (progn (insert (apply #'concat (let* ((depth depth) (prefix ...) (item ...) (strings)) (if item (progn ...)) (nreverse strings))))) (progn (let* ((key (get-text-property node :path))) (let ((dom-node (gethash key treemacs-dom nil))) (if dom-node (progn (let* ... ...) (let ... ...) (let ... ...)) (setq dom-node (record ... key nil nil nil node nil nil)) (prog1 nil (puthash ... dom-node treemacs-dom))))) (treemacs--reentry (get-text-property node :path)) (org-ol-tree-ui--window-resize))) (count-lines p (point)))
  (save-excursion (let* ((p (point))) (let (buffer-read-only) (put-text-property (or (previous-single-property-change (1+ node) 'button) (point-min)) (or (next-single-property-change node 'button) (point-max)) :state 'treemacs-org-ol-doc-open-state) (beginning-of-line) (save-excursion (let ((len (length treemacs-icon-org-ol-doc-open))) (goto-char (- (let* ... ...) len)) (insert treemacs-icon-org-ol-doc-open) (delete-char len))) (goto-char (or (next-single-property-change node 'button) (point-max))) (progn (insert (apply #'concat (let* (... ... ... ...) (if item ...) (nreverse strings))))) (progn (let* ((key (get-text-property node :path))) (let ((dom-node ...)) (if dom-node (progn ... ... ...) (setq dom-node ...) (prog1 nil ...)))) (treemacs--reentry (get-text-property node :path)) (org-ol-tree-ui--window-resize))) (count-lines p (point))))
  (prog1 (save-excursion (let* ((p (point))) (let (buffer-read-only) (put-text-property (or (previous-single-property-change (1+ node) 'button) (point-min)) (or (next-single-property-change node 'button) (point-max)) :state 'treemacs-org-ol-doc-open-state) (beginning-of-line) (save-excursion (let ((len ...)) (goto-char (- ... len)) (insert treemacs-icon-org-ol-doc-open) (delete-char len))) (goto-char (or (next-single-property-change node 'button) (point-max))) (progn (insert (apply #'concat (let* ... ... ...)))) (progn (let* ((key ...)) (let (...) (if dom-node ... ... ...))) (treemacs--reentry (get-text-property node :path)) (org-ol-tree-ui--window-resize))) (count-lines p (point)))) (if treemacs-move-forward-on-expand (progn (let* ((parent (let (...) (if result ...))) (child (next-button parent))) (if (equal parent (get-text-property child :parent)) (progn (forward-line 1)))))))
  (let ((items (reverse (org-ol-tree-core--headline-children (org-ol-tree-core--node-get :headline node)))) (depth (1+ (get-text-property node :depth))) (parent-dom-node (let* ((key (get-text-property node :path))) (gethash key treemacs-dom nil)))) (prog1 (save-excursion (let* ((p (point))) (let (buffer-read-only) (put-text-property (or (previous-single-property-change ... ...) (point-min)) (or (next-single-property-change node ...) (point-max)) :state 'treemacs-org-ol-doc-open-state) (beginning-of-line) (save-excursion (let (...) (goto-char ...) (insert treemacs-icon-org-ol-doc-open) (delete-char len))) (goto-char (or (next-single-property-change node ...) (point-max))) (progn (insert (apply ... ...))) (progn (let* (...) (let ... ...)) (treemacs--reentry (get-text-property node :path)) (org-ol-tree-ui--window-resize))) (count-lines p (point)))) (if treemacs-move-forward-on-expand (progn (let* ((parent (let ... ...)) (child (next-button parent))) (if (equal parent (get-text-property child :parent)) (progn (forward-line 1))))))))
  treemacs--do-expand-org-ol-doc(#<marker (moves after insertion) at 5 in *OrgOutlineTree:org-ol-tree/README.org*>)
  (let* ((node (let ((result (text-property-not-all (point-at-bol) (point-at-eol) 'button nil))) (if result (progn (copy-marker result t)))))) (if (null node) (progn (throw '--cl-block-__body__-- (treemacs-pulse-on-failure "There is nothing to do here.")))) (if (not (eq 'treemacs-org-ol-doc-closed-state (get-text-property node :state))) (progn (throw '--cl-block-__body__-- (treemacs-pulse-on-failure "This function cannot expand a node of type '%s'." (propertize (format "%s" (get-text-property node :state)) 'face 'font-lock-type-face))))) (treemacs--do-expand-org-ol-doc node))
  (catch '--cl-block-__body__-- (let* ((node (let ((result (text-property-not-all ... ... ... nil))) (if result (progn (copy-marker result t)))))) (if (null node) (progn (throw '--cl-block-__body__-- (treemacs-pulse-on-failure "There is nothing to do here.")))) (if (not (eq 'treemacs-org-ol-doc-closed-state (get-text-property node :state))) (progn (throw '--cl-block-__body__-- (treemacs-pulse-on-failure "This function cannot expand a node of type '%s'." (propertize (format "%s" ...) 'face 'font-lock-type-face))))) (treemacs--do-expand-org-ol-doc node)))
  treemacs-expand-org-ol-doc()
  (let nil (treemacs-expand-org-ol-doc))
  (cond ((eq val 'treemacs-org-ol-doc-closed-state) (let nil (treemacs-expand-org-ol-doc))) ((eq val 'treemacs-org-ol-parent-section-closed-state) (let nil (treemacs-expand-org-ol-parent-section))))
  (let* ((val (org-ol-tree-core--node-get :state node))) (cond ((eq val 'treemacs-org-ol-doc-closed-state) (let nil (treemacs-expand-org-ol-doc))) ((eq val 'treemacs-org-ol-parent-section-closed-state) (let nil (treemacs-expand-org-ol-parent-section)))))
  org-ol-tree-core--expand()
  (let (buffer-read-only) (erase-buffer) (treemacs-ORG-OL-DOC-extension) (org-ol-tree-core--node-put :headline (org-ol-tree-core--create-dom) (org-ol-tree-core--root-node)) (org-ol-tree-core--expand) (save-excursion (goto-char (point-max)) (insert "\n")))
  (save-current-buffer (set-buffer buffer) (let (buffer-read-only) (erase-buffer) (treemacs-ORG-OL-DOC-extension) (org-ol-tree-core--node-put :headline (org-ol-tree-core--create-dom) (org-ol-tree-core--root-node)) (org-ol-tree-core--expand) (save-excursion (goto-char (point-max)) (insert "\n"))))
  (let ((buffer (if org-ol-tree--buffer-p (current-buffer) org-ol-tree--buffer))) (if buffer nil (user-error "Cannot rebuild the Outline tree from an unrelated ...")) (save-current-buffer (set-buffer buffer) (let (buffer-read-only) (erase-buffer) (treemacs-ORG-OL-DOC-extension) (org-ol-tree-core--node-put :headline (org-ol-tree-core--create-dom) (org-ol-tree-core--root-node)) (org-ol-tree-core--expand) (save-excursion (goto-char (point-max)) (insert "\n")))))
  org-ol-tree-ui--build-outline-tree()
  (if prevent-rebuild nil (org-ol-tree-ui--build-outline-tree))
  (let* ((headline (org-ol-tree-core--current-headline)) (target-section-id (or target-section-id (if headline (progn (org-ol-tree-core--headline-id headline))))) (target-state (or target-state (org-ol-tree-core--state (org-ol-tree-core--node-get :state))))) (if prevent-rebuild nil (org-ol-tree-ui--build-outline-tree)) (org-ol-tree-action--goto-root) (org-ol-tree-core--collapse) (org-ol-tree-action--goto-setion target-section-id target-state) (message "Refresh completed"))
  (progn (let* ((headline (org-ol-tree-core--current-headline)) (target-section-id (or target-section-id (if headline (progn (org-ol-tree-core--headline-id headline))))) (target-state (or target-state (org-ol-tree-core--state (org-ol-tree-core--node-get :state))))) (if prevent-rebuild nil (org-ol-tree-ui--build-outline-tree)) (org-ol-tree-action--goto-root) (org-ol-tree-core--collapse) (org-ol-tree-action--goto-setion target-section-id target-state) (message "Refresh completed")))
  (if org-ol-tree--buffer-p (progn (let* ((headline (org-ol-tree-core--current-headline)) (target-section-id (or target-section-id (if headline (progn ...)))) (target-state (or target-state (org-ol-tree-core--state (org-ol-tree-core--node-get :state))))) (if prevent-rebuild nil (org-ol-tree-ui--build-outline-tree)) (org-ol-tree-action--goto-root) (org-ol-tree-core--collapse) (org-ol-tree-action--goto-setion target-section-id target-state) (message "Refresh completed"))))
  org-ol-tree-action--refresh(nil "2")
  (progn (save-current-buffer (set-buffer org-ol-tree--org-buffer) (save-excursion (goto-char headline-point) (if promote-tree (org-promote-subtree) (org-promote)))) (org-ol-tree-action--refresh nil target-id))
  (if (> headline-level 1) (progn (save-current-buffer (set-buffer org-ol-tree--org-buffer) (save-excursion (goto-char headline-point) (if promote-tree (org-promote-subtree) (org-promote)))) (org-ol-tree-action--refresh nil target-id)))
  (let* ((headline (org-ol-tree-core--current-headline)) (headline-point (org-ol-tree-core--headline-marker headline)) (headline-id (org-ol-tree-core--headline-id headline)) (headline-level (org-ol-tree-core--headline-level headline)) (parent (org-ol-tree-core--headline-parent headline)) (parent-level (if parent (org-ol-tree-core--headline-level parent) 0)) (target-id (org-ol-tree-core--section-string (if (> (- headline-level parent-level) 1) (cdr (org-ol-tree-core--section-from-string headline-id)) (org-ol-tree-core--next-section headline-id (1- headline-level)))))) (if (> headline-level 1) (progn (save-current-buffer (set-buffer org-ol-tree--org-buffer) (save-excursion (goto-char headline-point) (if promote-tree (org-promote-subtree) (org-promote)))) (org-ol-tree-action--refresh nil target-id))))
  (progn (let* ((headline (org-ol-tree-core--current-headline)) (headline-point (org-ol-tree-core--headline-marker headline)) (headline-id (org-ol-tree-core--headline-id headline)) (headline-level (org-ol-tree-core--headline-level headline)) (parent (org-ol-tree-core--headline-parent headline)) (parent-level (if parent (org-ol-tree-core--headline-level parent) 0)) (target-id (org-ol-tree-core--section-string (if (> (- headline-level parent-level) 1) (cdr (org-ol-tree-core--section-from-string headline-id)) (org-ol-tree-core--next-section headline-id (1- headline-level)))))) (if (> headline-level 1) (progn (save-current-buffer (set-buffer org-ol-tree--org-buffer) (save-excursion (goto-char headline-point) (if promote-tree (org-promote-subtree) (org-promote)))) (org-ol-tree-action--refresh nil target-id)))))
  (if org-ol-tree--buffer-p (progn (let* ((headline (org-ol-tree-core--current-headline)) (headline-point (org-ol-tree-core--headline-marker headline)) (headline-id (org-ol-tree-core--headline-id headline)) (headline-level (org-ol-tree-core--headline-level headline)) (parent (org-ol-tree-core--headline-parent headline)) (parent-level (if parent (org-ol-tree-core--headline-level parent) 0)) (target-id (org-ol-tree-core--section-string (if (> ... 1) (cdr ...) (org-ol-tree-core--next-section headline-id ...))))) (if (> headline-level 1) (progn (save-current-buffer (set-buffer org-ol-tree--org-buffer) (save-excursion (goto-char headline-point) (if promote-tree ... ...))) (org-ol-tree-action--refresh nil target-id))))))
  org-ol-tre-action--promote-node(nil)
  org-ol-tre-action--promote-section()
  #<subr funcall-interactively>(org-ol-tre-action--promote-section)
  apply(#<subr funcall-interactively> org-ol-tre-action--promote-section)
  funcall-interactively(org-ol-tre-action--promote-section)
  #<subr call-interactively>(org-ol-tre-action--promote-section nil nil)
  apply(#<subr call-interactively> (org-ol-tre-action--promote-section nil nil))
  explain-pause--wrap-call-interactively(#<subr call-interactively> org-ol-tre-action--promote-section nil nil)
  apply(explain-pause--wrap-call-interactively #<subr call-interactively> (org-ol-tre-action--promote-section nil nil))
  call-interactively(org-ol-tre-action--promote-section nil nil)
  command-execute(org-ol-tre-action--promote-section)
Alexander-Miller commented 3 years ago

Sorry for the late response, I've been busy renovating for the last couple of days.

Now to your question:

Treemacs does not have a dom that can be manipulated. There exists a backing data structure that I call a dom, but it's descriptive, it depicts the current state of the tree and its purpose is to help me to quickly navigate without the need for expensive text searches.

The api for modifying treemacs is quite a bit more simple and high-level. You'll want to use one of

(In fact I just noticed that the last one doesn't work with extensions, so update-node is what you'll want to use. )

How to manipulate the tree structure on Treemacs, update it, and save/restore node position correctly?

As you can see there's not much of an api to manipulate treemacs directly. The assumption is that you change the underlying data source and call a refresh and treemacs handles the rest all on its own. Including the parts of saving and restoring node positions and state.

Before we start digging into the specific troubles you're having I would ask you to have a look at #677 and the treelib branch. I am in the process of a major update of the extensions module with quite a few improvements like a simpler api and support for asynchronicity. It is not quite ready the be officially used yet, but not much is missing.

So if you make the jump now you'll save yourself the trouble of rewriting things in the future. You'll also have an easy time pushing for changes you'd like to see while the new api is not yet released and your POV will be quite valuable for me. I'll also have a much easier time debugging bugs like the one you're seeing because the new api does not use macros to generate entire functions.

Townk commented 3 years ago

Hey Alexander, thanks for the response, and don't worry about taking long to reply. I myself have to deliver a task at work that is keeping me away from my pet project. Anyway, I believe some time next week I will get couple weeks of vacation and will dive deep into my project. I will be more than happy to use the new API. Once I get that started I will update this ticket to let you know the status.

stale[bot] commented 2 years ago

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

Alexander-Miller commented 2 years ago

Stayin alive.

stale[bot] commented 2 years ago

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.