Skip to content

Latest commit

 

History

History
893 lines (822 loc) · 39.2 KB

mirror-text.org

File metadata and controls

893 lines (822 loc) · 39.2 KB

SOMEDAY [#A] Another try of mirror-text

  • State “SOMEDAY” from “HOLD” [2021-04-09 Fri 17:54]
  • State “HOLD” from “DOING” [2020-05-03 Sun 18:06]
  • Refiled on [2019-12-23 Mon 11:08]

Prefix: mirror-text-mode A minor mode, which allows to edit text in multiple places at once.

The text properties may be propagated. Edits of the copied text may also be synchronised.

The text chunks are continuous text regions, which should be mirrored.

The idea is to have a master chunk where all the commands on the text are being executed. The changes in the master chunk will propagate to all the slave chunks (in the same or other buffers).

The idea for now is to stick to simple functionality - just make text change in all the places if it is edited in a single place. Then, the editing may be prohibited for some chunks by adding read-only property.

In order to keep the chunks linked, I create a virtual chunk stored in a special buffer. Each chunk can be a part of the virtual chunk, which is implemented using markers. The idea of buffer is really important since it may allow implementing independent fontification and maybe multiple major modes without indirect buffers.

Each chunk is defined as an alist, which always contain :chunk-id - unique id of the chunk, and :virtual-chunk - the buffer containing the virtual chunk. This alist is stored in mirror-text-chunk text property. The virtual buffer stores the list of all the chunks as buffer-local hash table mirror-text-chunk-table, based on the chunk ids. Every chunk is represented as an alist containing at least :virtual-region, :region, and :synchronized-p properties. The :virtual-region property stores cons of the markers of the beginning and the end of the chunk in the virtual buffer. The :region property stores cons of the markers of the beginning and the end of the chunk. The :synchronized-p property indicates whether the chunk is synchronised with the virtual buffer.

The changes in the text are reflected in the virtual chunk by setting insert-behind-hooks, insert-in-front-hooks, and modification-hooks in the chunk text properties (the hooks are not set inside the virtual chunk). The insert-* hooks are called after inserting the text and can directly mirror the insertion in the virtual buffer. Also, they set current chunk’s :synchronized-p to 't to avoid duplicating the changes. Then, buffer-local after-change-functions in the virtual buffer can propagate all the changes to the chunks with :synchronized-p set to nil. Notably, inhibit-modification-hooks variable is used in after-change-functions when propagating changes back to the chunks. The modification-hooks are more tricky - they always run before modification. Hence, the hooks only mark the regions about to be edited in buffer-local mirror-text--modification-list using conses of the region markers. Then, after-change-functions in the chunk buffer process the list (if not empty) to propagate the modifications. It is important that after-change-functions may need to operate on multiple chunks at once. All the chunks in mirror-text-midification-list are marked :synchronized-p before the functions process the list.

SOMEDAY copy overlays from some chunks and propagate them to all other chunks. make sure that not too many overlays are copies over and over (add marker to copied overlays and flush them on update)END
;;; mirror-text.el --- Synchronise changes between text regions -*- lexical-binding: t; -*-

;; Version: 0.1
;; Author: Ihor Radchenko <yantar92@gmail.com>
;; Created: 12 April 2020

;;; Commentary:

;; This packages is a framework to create synchronised text regions.
;; The regions may be in the same buffer or in multiple buffers.
;; The text properties can be also synchronised.
;;
;; !!!!! Important
;; This backage is just a proof of concept and will be a subject of breaking changes
;; !!!!!
;;
;; Usage:
;; The main entry point is `mirror-text-create-chunk', which marks the text in current region to be synchronised in future.
;; The marked text is called a chunk.
;; The function returns virtual-chunk, which is the central unit of synchronisation.
;; Regions from virtual-chunk can be inserted to other positions/buffers via `mirror-text--create-chunk' and automatically marked as new chunks.
;; Changes in all the chunks associated with virtual chunk buffer (or regions in this buffer) will be synchronised.
;; 
;; **The following is untested**
;; The virtual chunk buffer may have an active major mode, which will allow uniform fontification of all the chunks.
;; Moreover, the chunks might (not implemented) have overriding keymap, which redirects commands to the virtual chunk buffer.
;; This, in theory, will effectively create separate major mode for all the chunks regardless of the buffer where the chunks are located.
;;
;; Example usage:
;; 1. Activate region of text and run M-x mirror-text-create-chunk
;; This will create mirror-text--virtual-chunks variable containing the created chunk. 
;; 2. To insert a new chunk, evaluate (mirror-text--create-chunk (car mirror-text--virtual-chunks) (point) (1+ (point))) with point where you want to insert the new chunk.
;;

;;; Code:

(defvar mirror-text--virtual-chunks nil
  "List of all the virtual chunk buffers.")

;; TODO: different settings for light&dark backgrounds
(defface mirror-text-background '((t . (:background "Cornsilk")))
  "Face used to indicate the chunks.")

(defface mirror-text-indicator-face '((t . (:background "Red")))
  "Face used to indicate the beginning/end of chunks.")


(defvar mirror-text-beg-chunk-indicator #("#|- " 0 4 (font-lock-face 'mirror-text-indicator-face))
  "String used to indicate the beginning of a chunk.")

(defvar mirror-text-end-chunk-indicator #(" -|#"  0 4 (font-lock-face 'mirror-text-indicator-face))
  "String used to indicate the end of a chunk.")

;; helper functions

(defmacro mirror-text--swap (a b)
  "Swap A and B."
  `(let ((tmp ,a))
     (setf ,a ,b)
     (setf ,b tmp)))

(defun mirror-text--pos-to-marker (pom &optional buffer insertion-type)
  "Convert POM to marker."
  (if (markerp pom)
      pom
    (let ((marker (make-marker)))
      (set-marker marker pom (or buffer (current-buffer)))
      (set-marker-insertion-type marker insertion-type)
      marker)))

(defun mirror-text--markercons= (a b)
  "Return non-nil when cons A = B. Return nil if A or B is nil."
  (and a
       b
       (seq-every-p (lambda (el) (buffer-live-p (marker-buffer el)))
		    (list (car a) (cdr a)
			  (car b) (cdr b)))
       (= (car a) (car b))
       (= (cdr a) (cdr b))))

(defun mirror-text--intersect-cons (c1 c2)
  "Return intersection of two cons regions or nil."
  (when (<= (max (car c1) (car c2))
	    (min (cdr c1) (cdr c2)))
    (cons (max (car c1) (car c2)) (min (cdr c1) (cdr c2)))))

(defun mirror-text--region<= (a b)
  "Return nil when list A > B."
  (or (<= (car a) (car b))
      (<= (cadr a) (cadr b))))

(defun mirror-text--merge-regions (ra rb)
  "Merge RA and RB regions (beg end len chunk)."
  (let* ((a (if (mirror-text--region<= ra rb) ra rb))
	 (b (if (equal a ra) rb ra)))
    (unless (or (> (car b) (cadr a))
		(not (equal (nth 3 a) (nth 3 b)))) ;; not the same chunks
      (list (min (car a) (car b))
	    (max (cadr a) (cadr b))
            (- (max (cadr a) (cadr b))
               (min (car a) (car b)))
            (nth 3 a)))))

(defun mirror-text--add-or-merge-region (region list)
  "Add REGION in the form of (beg end len chunk) to the ordered LIST of regions merging it with existing list elements if possible."
  (let ((elm))
    (setq elm list)
    (while elm
      (let ((cur (car elm))
	    (next (cadr elm)))
	(when (and (mirror-text--region<= cur region)
		   (or (not next)
		       (not (mirror-text--region<= next region))))
	  (let ((merge (mirror-text--merge-regions cur region)))
	    (if merge
		(setcar elm merge)
	      (setcdr elm (cons region (cdr elm)))
	      (setq elm (cdr elm)))
	    (setq cur elm)
	    (setq elm (cdr elm))
	    (while (and elm
			(mirror-text--merge-regions (car cur) (car elm)))
	      (setcar cur (mirror-text--merge-regions (car cur) (car elm)))
	      (setq elm (cdr elm)))
	    (setcdr cur elm)
	    (setq elm nil))))
      (setq elm (cdr elm))
      ))
  (unless list (setq list (list region)))
  list)

;; core chunk code

(defun mirror-text--chunk-modify-function (beg end)
  "Mark the upcoming modifications in the current chunk to be processed by `mirror-text--chunk-after-change-function'."
  (unless (boundp 'mirror-text--buffer-chunk-modifications)
    (make-local-variable 'mirror-text--buffer-chunk-modifications)
    (setq mirror-text--buffer-chunk-modifications nil))
  (let ((inhibit-modification-hooks t))
    ;;(mirror-text--update-chunk beg)
    (add-to-list 'after-change-functions #'mirror-text--chunk-after-change-function)
    (add-to-list 'mirror-text--buffer-chunk-modifications (get-text-property beg 'mirror-text-chunk))))

(defun mirror-text--chunk-after-change-function (beg end oldlen)
  "Propagate the modifications marked by `mirror-text--chunk-modify-function'."
  (require 'org-macs) ;; org-with-point-at
  (when (boundp 'mirror-text--buffer-chunk-modifications)
    (unwind-protect
	(mapc #'mirror-text--update-chunk (mapcar (lambda (chunk) (car (alist-get :region (mirror-text--chunk-info chunk)))) mirror-text--buffer-chunk-modifications))
      (setq mirror-text--buffer-chunk-modifications nil))))

(defun mirror-text--chunk-insert-function (beg end)
  "Handle insertiion into a chunk."
  (mirror-text--update-chunk beg))

;; TODO: consider flagging the synchronized flag in virtual-chunk on modification/insertion
(defun mirror-text--propertize (beg end chunk)
  "Add text properties and modification hooks to the CHUNK text between BEG and END."
  (unless (> end beg) (mirror-text--swap beg end))
  (require 'org-macs) ;; org-with-point-at
  (org-with-point-at beg
    (remove-text-properties beg end '(mirror-text--begoffset nil mirror-text--endoffset nil))
    (put-text-property beg end 'mirror-text-chunk chunk)
    (put-text-property beg end 'front-sticky t) ;; may not be a good idea
    ;; TODO: remove the advice when buffer does not contain any chunks
    
    (put-text-property beg end 'modification-hooks (list #'mirror-text--chunk-modify-function))
    (put-text-property beg end 'insert-in-front-hooks (list #'mirror-text--chunk-insert-function))
    (put-text-property beg end 'insert-behind-hooks (list #'mirror-text--chunk-insert-function))
    ;; (add-function :around (local 'filter-buffer-substring-function) #'mirror-text--buffer-substring-filter)
    (put-text-property beg end  'font-lock-face 'mirror-text-background)
    ;; (put-text-property beg (1+ beg) 'display (concat mirror-text-beg-chunk-indicator (buffer-substring-no-properties beg (1+ beg))))
    ;; (put-text-property (1- end) end 'display (concat (buffer-substring-no-properties (1- end) end) mirror-text-end-chunk-indicator ))
    ))

(defun mirror-text--virtual-chunk-ingest-chunk (chunk-id)
  "Collect the CHUNK-ID contents into the current virtual chunk."
  (when-let* ((chunk (gethash chunk-id mirror-text-chunk-table))
	      (virtual-region (alist-get :virtual-region chunk))
              (region (alist-get :region chunk)))
    (replace-region-contents (car virtual-region)
			     (cdr virtual-region)
                             `(lambda ()
				(let ((beg ,(car region))
                                      (end ,(cdr region)))
				  (org-with-point-at beg
                                    (if (alist-get :keep-text-properties-p chunk)
					(buffer-substring beg end) ;; may consider calling `filter-buffer-substring' here
				      (buffer-substring-no-properties beg end))))))
    (org-with-point-at (car region)
      (let ((inhibit-modification-hooks t)) ; `mirror-text--virtual-chunk-after-change-function' may update the region as well, do not record it
	(org-with-point-at (car virtual-region)
	  (mirror-text--virtual-chunk-after-change-function (car virtual-region) (cdr virtual-region) nil)))))) ;; here it will be possible to selectively copy properties in future

(defun mirror-text--virtual-chunk-after-change-function (beg end oldlen &optional chunk-id chunk)
  "Propagate the insertion from the current virtual chunk into all the linked chunks (or to CHUNK).
Replace the corresponding region in the chunks instead if REPLACE-P is non nil."
  (if (not chunk)
      (progn
	(mirror-text--cleanup (current-buffer))
	(maphash (apply-partially #'mirror-text--virtual-chunk-after-change-function beg end oldlen) mirror-text-chunk-table))
    (when (mirror-text--intersect-cons (cons (mirror-text--pos-to-marker beg) (mirror-text--pos-to-marker end))
				       (alist-get :virtual-region chunk)) 
      (setq beg (car (alist-get :virtual-region chunk)))
      (setq end (cdr (alist-get :virtual-region chunk))) ;; update the whole chunk to avoid messed up pointers
      (let* ((new-text (buffer-substring beg end)) ;; copying with properties, but may need to be more selective in future
	     (real-beg (car (alist-get :region chunk)))
             (real-end (cdr (alist-get :region chunk)))
	     (real-buffer (marker-buffer real-beg)))
	(org-with-point-at real-beg
          (let ((inhibit-read-only t))
            (combine-change-calls  real-beg real-end
				   (replace-region-contents real-beg real-end (lambda () new-text))
				   (mirror-text--propertize real-beg real-end (list (cons ':chunk-id chunk-id)
										    (cons ':virtual-chunk (marker-buffer beg)))))))))))

(defun mirror-text--create-virtual-chunk (text)
  "Create virtual chunk buffer containing TEXT. Return the buffer."
  (let ((buffer (generate-new-buffer (format " mirror-text-virtual-chunk-%s" (sxhash text)))))
    (with-current-buffer buffer
      (insert text)
      (make-local-variable 'mirror-text-chunk-table)
      (setq mirror-text-chunk-table (make-hash-table :test 'equal))
      (add-to-list 'mirror-text--virtual-chunks buffer)
      (setq-local after-change-functions (list #'mirror-text--virtual-chunk-after-change-function)))
    buffer))

(cl-defun mirror-text--create-chunk (virtual-chunk beg end &key
						   (virtual-region (with-current-buffer virtual-chunk
								     (cons (point-min-marker) (point-max-marker))))
                                                   (synchronized-p t)
                                                   (keep-text-properties-p nil))
  "Create a new chunk in VIRTUAL-CHUNK pointing to :region BEG END.
The text in the region will be replaced by the :virtual-region from VIRTUAL-CHUNK."
  (require 'org-id) ;; org-id-uuid
  (setf (car virtual-region) (mirror-text--pos-to-marker (car virtual-region) virtual-chunk))
  (setf (cdr virtual-region) (mirror-text--pos-to-marker (cdr virtual-region) virtual-chunk))
  (setf beg (mirror-text--pos-to-marker beg))
  (setf end (mirror-text--pos-to-marker end))
  ;; (unless (and (markerp beg) (markerp end)) (error "BEG and END should be markers"))
  (set-marker-insertion-type end 'follow-insertion)
  (set-marker-insertion-type (cdr virtual-region) 'follow-insertion)
  (let ((chunk (list (cons ':virtual-region virtual-region)
		     (cons ':region (cons beg end))
		     (cons ':synchronized-p synchronized-p)
                     (cons ':keep-text-properties-p keep-text-properties-p)))
        (chunk-id (org-id-uuid)))
    (unless (member virtual-chunk mirror-text--virtual-chunks) (error "%s is not a virtual chunk buffer" (buffer-name virtual-chunk)))
    (with-current-buffer virtual-chunk
      (puthash chunk-id chunk mirror-text-chunk-table)
      (let ((text (buffer-substring (car virtual-region) (cdr virtual-region))))
	(org-with-point-at beg
          (let ((inhibit-modification-hooks t)
		(inhibit-read-only t))
	    (replace-region-contents beg end (lambda () text))
	    (mirror-text--propertize beg end (list (cons ':chunk-id chunk-id)
						   (cons ':virtual-chunk virtual-chunk)))))))))

;; (defun mirror-text--find-chunk-region (pom)
;;   "Find a chunk region containing POM."
;;   (require 'org-macs) ;; org-with-point-at
;;   (org-with-point-at pom
;;     (let* ((pos (marker-position (mirror-text--pos-to-marker pom)))
;; 	   (beg (and (get-text-property pos 'mirror-text-chunk) pom))
;; 	   (end beg))
;;       (when beg
;; 	(setq beg (or (previous-single-property-change pos 'mirror-text-chunk)
;; 		      beg))
;; 	(setq end (or (next-single-property-change pos 'mirror-text-chunk)
;; 		      end))
;; 	(setq beg (mirror-text--pos-to-marker beg))
;; 	(setq end (mirror-text--pos-to-marker end nil 'move-after-insert))
;; 	(cons beg end)))))

(defun mirror-text--chunk-info (chunk)
  "Return CHUNK info as it is stored in the virtual-chunk buffer.
Return nil when CHUNK is not a valid chunk."
  (let ((virtual-chunk (alist-get :virtual-chunk chunk))
	(chunk-id (alist-get :chunk-id chunk)))
    (if (and chunk-id (buffer-live-p virtual-chunk))
	(with-current-buffer virtual-chunk
          (when (boundp 'mirror-text-chunk-table)
            (gethash chunk-id mirror-text-chunk-table)))
      (mirror-text--cleanup virtual-chunk)
      nil)))

(defun mirror-text--verify-chunk (chunk-info)
  "Return nil when CHUNK-INFO does not point to a valid chunk."
  (require 'org-macs) ;; org-with-point-at
  (let ((region (alist-get :region chunk-info)))
    (when (and (buffer-live-p (marker-buffer (car region)))
	       ;; (mirror-text--markercons= region (mirror-text--find-chunk-region (car region)))
               )
      (with-current-buffer (marker-buffer (car region))
	(equal chunk-info
               (mirror-text--chunk-info (get-text-property (marker-position (car region)) 'mirror-text-chunk)))))))

(defun mirror-text--cleanup (&optional virtual-chunk)
  "Remove orphan VIRTUAL-CHUNK or all the orphan virtual chunks."
  (if (not virtual-chunk)
      (mapc #'mirror-text--cleanup (-select #'identity mirror-text--virtual-chunks))
    (if (not (buffer-live-p virtual-chunk))
	(setq mirror-text--virtual-chunks (delq virtual-chunk mirror-text--virtual-chunks))
      (with-current-buffer virtual-chunk
	(when (boundp 'mirror-text-chunk-table)
	  (mapc (lambda (elm)
		  (unless (cdr elm)
                    (remhash (car elm) mirror-text-chunk-table)))
		(let ((list))
		  (maphash
		   (lambda (key val)
		     (push (cons key
				 (mirror-text--verify-chunk val))
                           list))
		   mirror-text-chunk-table)
                  list))
          (when (hash-table-empty-p mirror-text-chunk-table)
            (setq mirror-text--virtual-chunks (delq virtual-chunk mirror-text--virtual-chunks))
            (kill-buffer virtual-chunk)))))))

(defun mirror-text--update-chunk (&optional pom)
  "Update chunk at POM."
  (require 'org-macs) ; org-with-point-at
  (let* ((pos (or pom (point)))
	 (chunk (get-text-property pos 'mirror-text-chunk))
	 ;; (chunk-region (mirror-text--find-chunk-region pos));;
         (chunk-region (alist-get :region chunk))
         (begoffset (or (get-text-property pos 'mirror-text--begoffset) 0))
         (endoffset (or (get-text-property pos 'mirror-text--endoffset) 0)))
    (when chunk
      (let ((chunk-info (mirror-text--chunk-info chunk)))
	(if (not chunk-info)
            (remove-text-properties (car chunk-region) (cdr chunk-region) '(mirror-text-chunk nil mirror-text--begoffset nil mirror--text-endoffset nil font-lock-face nil))
	  (if (and
                   ;; (mirror-text--markercons= (alist-get :region chunk-info)
		   ;; 			     chunk-region)
                   (zerop begoffset)
                   (zerop endoffset))
              (with-current-buffer (alist-get :virtual-chunk chunk) (mirror-text--virtual-chunk-ingest-chunk (alist-get :chunk-id chunk)))
	    (with-current-buffer (alist-get :virtual-chunk chunk)
	      (let ((virtual-region (alist-get :virtual-region chunk-info)))
		(if (= (- (cdr chunk-region) (car chunk-region))
		       (- (cdr virtual-region) (car virtual-region))) ; same chunk in a new buffer/place
		    (mirror-text--create-chunk (alist-get :virtual-chunk chunk)
					       (car chunk-region)
					       (cdr chunk-region)
					       :virtual-region (cons (car virtual-region)
								     (cdr virtual-region)))
                  (if (= (- (cdr chunk-region) (car chunk-region))
			 (- (- (cdr virtual-region) endoffset) (+ (car virtual-region) begoffset))) ; truncated chunk in a new buffer/place
		      (mirror-text--create-chunk (alist-get :virtual-chunk chunk)
						 (car chunk-region)
						 (cdr chunk-region)
						 :virtual-region (cons (+ (car virtual-region) begoffset)
								       (- (cdr virtual-region) endoffset)))
                    (remove-text-properties (car chunk-region) (cdr chunk-region) '(mirror-text-chunk nil mirror-text--begoffset nil mirror-text--endoffset nil font-lock-face nil))))))))))))

;; This should be used inside advice to the buffer-substring-filter-function
;; Example:
;; (add-function :around (local 'filter-buffer-substring-function)
;;               #'nameless--filter-string)
;; (defun mirror-text--buffer-substring-filter (oldfun beg end &optional delete)
;;   "Detect copied chunks and handle chunks copied partially.
;; The specification follows `filter-buffer-substring-function' requirements."
;;   (when (< end beg) (mirror-text--swap beg end))
;;   (let* ((begchunk-info (mirror-text--chunk-info (get-text-property beg 'mirror-text-chunk)))
;; 	 (endchunk-info (mirror-text--chunk-info (get-text-property (1- end) 'mirror-text-chunk)))
;;          (begoffset (when begchunk-info (- beg (car (alist-get :region begchunk-info)))))
;;          (endoffset (when endchunk-info (- (cdr (alist-get :region endchunk-info)) end)))
;;          (substring (funcall oldfun beg end delete)))
;;     (when substring
;;       (with-temp-buffer
;;         (let ((inhibit-modification-hooks t))
;;           (insert substring)  
;;           ;; (remove-text-properties (point-min) (point-max) '(font-lock-face nil)) ;; may need to be smarter
;; 	  (when begoffset (put-text-property (point-min) (cdr (mirror-text--find-chunk-region (point-min))) 'mirror-text--begoffset begoffset))
;; 	  (when endoffset (put-text-property (car (mirror-text--find-chunk-region (- (point-max) 1))) (point-max) 'mirror-text--endoffset endoffset)))
;; 	(buffer-string)))))

;; TODO: create the minor mode setting modification functions

;; (define-minor-mode mirror-text-mode
;;   "Sync mirror-text fragments in this buffer."
;;   :init-value nil
;;   :lighter " Mirror")

;; exposed to user

(defun mirror-text-create-chunk (beg end &optional buffer)
  "Create a new virtual chunk from region (BEG. END). Mark the region as a chunk."
  (interactive "r")
  (setq beg (mirror-text--pos-to-marker beg buffer))
  (setq end (mirror-text--pos-to-marker end buffer))
  (when (< end beg) (mirror-text--swap beg end))
  (let ((virtual-chunk (mirror-text--create-virtual-chunk (buffer-substring-no-properties beg end))))
    (mirror-text--create-chunk virtual-chunk beg end)))

(provide 'mirror-text)

SOMEDAY check this for the mirror-text |- (Lenticular Text For Emacs)

consider implementing the idea with transformer/merge functions legalnonsense [Github] org-clones

  • Refiled on [2020-09-04 Fri 11:53]
@misc{80ecc83f1c6bfbdd1227c388ed3fc640dbf77856,
  author =       {legalnonsense},
  howpublished = {Github},
  note =         {Online; accessed 04 September 2020},
  title =        {org-clones},
  url =
                  {https://github.com/legalnonsense/org-clones/issues/1},
}

SOMEDAY [#A] reply |- (Recent Questions - Emacs Stack Exchange: Embed org task list from other subtree)

  • Refiled on [2019-12-17 Tue 23:29]

SOMEDAY [#A] url |- (Is there a way to include an org file in another one and have the contents update in real time? : emacs)

  • Refiled on [2019-12-17 Tue 23:29]
  • Refiled on [2019-12-02 Mon 00:45]

SOMEDAY [#A] consider using |- (How to get feedback on packages before they’re in a repository? : emacs)

  • Refiled on [2020-01-09 Thu 19:16]
  • Refiled on [2019-12-14 Sat 17:28]

[#A] url |- (comments by github-alphapapa: /u/github-alphapapa on Cloning/mirroring a region to some other location)

  • Refiled on [2020-03-29 Sun 11:34]
  • Refiled on [2020-03-21 Sat 14:58]
Interesting, seems like a form of transclusion. Maybe it could be used to implement transclusion in other contexts.

cc: u/justtaft

[#A] url |- (magnars/multifiles.el: Work in progress: View and edit parts of multiple files in one buffer)

  • Refiled on [2020-03-29 Sun 11:34]
  • Refiled on [2020-03-21 Sat 14:58]

WAITING [#A] get a feedback email |- Ihor Radchenko <yantar92@gmail.com>: RE: Request for pointers and advice: displaying several buffers inside a single window

  • State “WAITING” from “NEXT” [2020-04-25 Sat 18:53]
  • Refiled on [2020-04-12 Sun 23:41]

url |- (Recent Questions - Emacs Stack Exchange: Split code across multiple SRC blocks?)

  • Refiled on [2020-04-16 Thu 15:59]
  • Refiled on [2020-04-06 Mon 16:41]
For my current config, I’m tangling an org-mode buffer into my init.el, and I have a few sections where I’d like to insert rich text between segments of Emacs lisp code, like the following:

,#+BEGIN_SRC elisp (use-package exwm :config (exwm-enable) ,#+END_SRC

I find that four workspaces is enough to start out with, and I like being able to use my X windows across workspaces.

,#+BEGIN_SRC elisp :init (setq exwm-workspace-number 4 exwm-workspace-show-all-buffers t exwm-layout-show-all-buffers t) ,#+END_SRC

The issue is, if I C-c ’ to edit the second SRC block, it reindents to the beginning of the line. Smartparens is also unhappy about any unmatched closing parentheses I have in subsequent blocks.

Is there anything in org-mode that would support something like this? Perhaps some marker I can tag each block with as a hint that they should all be pulled into the same Org Src buffer when I C-c ’ on one of them?

reply when I get something with transclusion #email -> $:from Opening multiple files in a single buffer?

  • Refiled on [2020-07-27 Mon 08:55]

SOMEDAY /u/RaidenRiver [reddit] (2020) Anyone tried whacked’s transclusion minor mode? (edit a buffer inside another buffer)

  • Refiled on [2020-07-28 Tue 17:36]
  • Refiled on [2020-07-25 Sat 15:22]
@misc{reddit_/u/raidenriver2020_anyon,
  DATE_ADDED =   {Sat Jul 25 12:05:40 2020},
  author =       {/u/RaidenRiver},
  howpublished = {reddit},
  keywords =     {emacs},
  note =         {Online; accessed 25 July 2020},
  title =        {Anyone tried whacked's transclusion minor mode?
                  (edit a buffer inside another buffer)},
  url =
                  {https://www.reddit.com/r/emacs/comments/hw34g5/anyone_tried_whackeds_transclusion_minor_mode/},
  year =         2020,
}

REVIEW /u/itistheblurstoftimes [Reddit:emacs] (2020) [ANN/RFC] Org-clones – orgmode headings in multiple locations and files

  • Refiled on [2020-09-02 Wed 21:14]
  • Refiled on [2020-09-02 Wed 09:51]
@misc{da4fe70f0ce0ffdc286348dcff666f4064ab11fd,
  author =       {/u/itistheblurstoftimes},
  howpublished = {Reddit:emacs},
  keywords =     {emacs},
  note =         {Online; accessed 02 September 2020},
  title =        {[ANN/RFC] Org-clones -- orgmode headings in multiple
                  locations and files},
  url =
                  {https://www.reddit.com/r/emacs/comments/iks94o/annrfc_orgclones_orgmode_headings_in_multiple/},
  year =         2020,
}

HOLD [#A] anyone followup? email |- Dmitrii Korobeinikov <dim1212k@gmail.com>: Re: bug#35419: [Proposal] Buffer Lenses and the Case of Org-Mode (also, Jupyter)

  • Refiled on [2020-09-20 Sun 15:08]
  • State “HOLD” from “NEXT” [2020-05-25 Mon 11:51]
    Make mirror-text better first
[2019-06-03 Mon 11:04]

HOLD [#A] reply comment |- (www.reddit.com)

  • Refiled on [2020-09-20 Sun 15:08]
  • State “HOLD” from “WAITING” [2020-04-20 Mon 12:48]
    do once I implement this
  • State “WAITING” from “NEXT” [2019-12-18 Wed 11:06]
    Need to implement the idea with dired first
  • Refiled on [2019-11-11 Mon 11:06]

this may be useful for transclusion #email -> $:from buffer name of Org Src…

  • Refiled on [2020-10-13 Tue 22:10]

SOMEDAY /u/nobiot [Reddit:emacs] (2020) Org-transclusion (alpha v0.0.4) Demo #4

  • Refiled on [2020-11-08 Sun 13:49]
  • State “DONE” from “NEXT” [2020-11-08 Sun 13:49]
  • Refiled on [2020-11-02 Mon 11:32]
@misc{fd4e4ad22f27f39fe85d526b7132d00cc20840b8,
  author =       {/u/nobiot},
  howpublished = {Reddit:emacs},
  keywords =     {emacs},
  note =         {Online; accessed 02 November 2020},
  title =        {Org-transclusion (alpha v0.0.4) Demo #4},
  url =
                  {https://www.reddit.com/r/emacs/comments/jm1nv6/orgtransclusion_alpha_v004_demo_4/},
  year =         2020,
}

vspinu [Github] lentic: Create views of the same content in two Emacs buffers

  • Refiled on [2020-12-14 Mon 21:15]
@misc{626a17c6d18ed60250805d402f8a6bd6b0163225,
  author =       {vspinu},
  howpublished = {Github},
  note =         {Online; accessed 14 December 2020},
  title =        {lentic: Create views of the same content in two
                  Emacs buffers},
  url =          {https://github.com/vspinu/lentic},
}

[Reddit:emacs] Possible to embed another org file or entry in an org file

  • Refiled on [2020-12-14 Mon 21:37]
@misc{20b8ca138e44049217c5a28634d4b1473c433627,
  howpublished = {Reddit:emacs},
  note =         {Online; accessed 14 December 2020},
  title =        {Possible to embed another org file or entry in an
                  org file},
  url =
                  {https://reddit.com/r/emacs/comments/debean/possible_to_embed_another_org_file_or_entry_in_an/},
}

legalnonsense [Github] org-clones: Prototype for method of cloning orgmore headers

  • Refiled on [2020-12-14 Mon 21:37]
@misc{91ecf1b6df46a79b14eaa39bf9bad7d99c4b8d3a,
  author =       {legalnonsense},
  howpublished = {Github},
  note =         {Online; accessed 14 December 2020},
  title =        {org-clones: Prototype for method of cloning orgmore
                  headers},
  url =          {https://github.com/legalnonsense/org-clones},
}

SOMEDAY Kinneyzhang [Github] Kinneyzhang/roam-block: An all-purpose block ref and block embed implement in emacs.

  • Refiled on [2021-04-05 Mon 19:30]
  • Refiled on [2021-04-05 Mon 19:21]
  • Following up: clear hanging tasks (just take a short look and maybe mark NEXT!)

SOMEDAY nobiot [Github] org-transclusion: (alpha) Emacs package to enable transclusion with Org Mode

  • Refiled on [2021-05-17 Mon 09:57]
  • Refiled on [2020-12-07 Mon 15:14]
@misc{3a0efed2b80738f5fd34940e0f4fe62bc89a5067,
  author =       {nobiot},
  howpublished = {Github},
  note =         {Online; accessed 07 December 2020},
  title =        {org-transclusion: (alpha) Emacs package to enable
                  transclusion with Org Mode},
  url =          {https://github.com/nobiot/org-transclusion},
}

SOMEDAY #email Léo Ackermann <leo.komba@gmail.com> Large source block causes org-mode to be unusable

  • Refiled on [2021-06-23 Wed 19:09]
  • Refiled on [2021-06-22 Tue 10:22]

SOMEDAY whacked [Github] Whacked/transclusion-Minor-Mode: Emacs Minor Mode for Org-Mode File Transclusion Using Embedded Overlays

  • Refiled on [2021-08-22 Sun 20:42]
  • Refiled on [2021-02-27 Sat 20:46]
  • Refiled on [2020-07-25 Sat 15:22]
@misc{github_whacked_whack_minor_mode_emacs_minor,
  DATE_ADDED =   {Sat Jul 25 13:25:59 2020},
  author =       {whacked},
  howpublished = {Github},
  note =         {Online; accessed 25 July 2020},
  title =        {Whacked/transclusion-Minor-Mode: Emacs Minor Mode
                  for Org-Mode File Transclusion Using Embedded
                  Overlays},
  url =          {https://github.com/whacked/transclusion-minor-mode},
}

SOMEDAY magnars [Github] magnars/multifiles.el: Work in progress: View and edit parts of multiple files in one buffer

  • Refiled on [2021-09-23 Thu 16:19]

SOMEDAY [#A] reply? |- (Org-mode: Clones in org-mode?)

  • Refiled on [2021-12-07 Tue 10:49]
  • State “NEXT” from “TODO” [2019-04-26 Fri 04:58]