I want to switch between org-mode and c++-mode on top of a single file. I use org-mode syntax inside c++ comment blocks. In Org-mode I have foldable sections while in c++-mode I use hide/show for blocks. When switching mode the outline overlay is reset and everything is made visible. Is it possible to somehow prevent this and retain the visibility state?
1 Answer
I ended up using https://github.com/ShingoFukuyama/ov.el and syncing org-mode and c++-mode overlays. When switching between modes I replicate the other buffer's invisible
overlays. This is done on every mode switch: (add-hook 'multi-select-mode-hook 'sync-buffer-overlays)
(require 'ov)
(defun get-org-buffer ()
(cdr (assoc 'org-mode multi-indirect-buffers-alist)))
(defun get-c++-buffer ()
(cdr (assoc 'c++-mode multi-indirect-buffers-alist)))
;; exclude the overlays marked with `ismultimode' from overlay list of buffer `buf'
(defun get-real-ov (buf)
(let ((org-ov))
(with-current-buffer buf
(setq org-ov (seq-remove (lambda (x) (ov-val x 'ismultimode )) (ov-all))))
org-ov))
;; remove all overlays marked with `ismultimode' from buffer
(defun clean-intermediate-overlays (buf)
(with-current-buffer buf
(dolist (e (ov-all))
(if (ov-val e 'ismultimode )
(ov-reset e)))))
(defun sync-buffer-overlays ()
(interactive)
(let ((org-buf (get-org-buffer))
(c++-buf (get-c++-buffer))
(org-ov)
(c++-ov)
)
(clean-intermediate-overlays c++-buf)
(clean-intermediate-overlays org-buf)
(setq org-ov (get-real-ov org-buf))
(with-current-buffer c++-buf
(dolist (e org-ov)
(let ((beg (ov-beg e))
(end (ov-end e)))
(ov beg end '(invisible hs ismultimode t)))
))
(setq c++-ov (get-real-ov c++-buf))
(with-current-buffer org-buf
(dolist (e c++-ov)
(let ((beg (ov-beg e))
(end (ov-end e)))
(ov beg end '(invisible outline ismultimode t)))
))
)
)