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?


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))))

;; 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 ()
  (let ((org-buf (get-org-buffer))
        (c++-buf (get-c++-buffer))

    (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)))

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.