update packages

This commit is contained in:
2021-01-08 19:32:30 +01:00
parent ce8f24d28a
commit f5649dceab
467 changed files with 26642 additions and 22487 deletions

View File

@@ -44,8 +44,8 @@
"Ask for server password everytime a CRDT server is to be started."
:type 'boolean)
(defcustom crdt-confirm-stop-session t
"Ask for confirmation when a CRDT server with some client connected is to be stopped."
(defcustom crdt-confirm-disconnect t
"Ask for confirmation when a CRDT server is to stop the connection from some client."
:type 'boolean)
(defvar crdt--log-network-traffic nil
@@ -191,7 +191,7 @@ and HIGH-OFFSET. (to save two copying from using CRDT--ID-REPLACE-OFFSET)"
(get-text-property pos 'crdt-id obj))
(defsubst crdt--get-starting-id (pos &optional obj)
"Get the CRDT-ID at POS in OBJ."
"Get the CRDT-ID object at POS in OBJ."
(car (crdt--get-crdt-id-pair pos obj)))
(defsubst crdt--end-of-block-p (pos &optional obj)
@@ -295,12 +295,19 @@ Must be used inside CRDT--WITH-INSERTION-INFORMATION."
This is useful for functions that apply remote change to local buffer,
to avoid recusive calling of CRDT synchronization functions.")
(crdt--defvar-permanent-local crdt--changed-string nil)
(crdt--defvar-permanent-local crdt--changed-string nil
"Save changed substring in CRDT--BEFORE-CHANGE.")
(crdt--defvar-permanent-local crdt--changed-start nil
"Save start character address of changes in CRDT--BEFORE-CHANGE,
to recover the portion being overwritten in CRDT--AFTER-CHANGE.")
(crdt--defvar-permanent-local crdt--last-point nil)
(crdt--defvar-permanent-local crdt--last-mark nil)
(crdt--defvar-permanent-local crdt--last-process-mark-id nil)
(crdt--defvar-permanent-local crdt--pseudo-cursor-table nil
"A hash table that maps SITE-ID to CONSes of the form (CURSOR-OVERLAY . REGION-OVERLAY).")
@@ -326,6 +333,8 @@ to avoid recusive calling of CRDT synchronization functions.")
(crdt--defvar-permanent-local crdt--buffer-sync-callback)
(crdt--defvar-permanent-local crdt--buffer-pseudo-process)
;;; Global variables
(defvar crdt--session-list nil)
@@ -364,8 +373,10 @@ Also set CRDT--PSEUDO-CURSOR-TABLE to NIL."
"CRDT mode" nil " CRDT" nil
(if crdt-mode
(progn
(setq crdt--pseudo-cursor-table (make-hash-table))
(setq crdt--overlay-table (make-hash-table :test 'equal))
(unless crdt--pseudo-cursor-table
(setq crdt--pseudo-cursor-table (make-hash-table)))
(unless crdt--overlay-table
(setq crdt--overlay-table (make-hash-table :test 'equal)))
(crdt--install-hooks))
(crdt--uninstall-hooks)
(crdt--clear-pseudo-cursor-table)
@@ -383,13 +394,18 @@ If SESSION is nil, use current CRDT--SESSION."
(defmacro crdt--with-buffer-name (name &rest body)
"Find CRDT shared buffer associated with NAME and evaluate BODY in it.
Also, try to recover from synchronization error if any error happens in BODY.
Must be called when CURRENT-BUFFER is a CRDT status buffer.
If such buffer doesn't exist yet, do nothing."
`(let (crdt-buffer)
(setq crdt-buffer (gethash ,name (crdt--session-buffer-table crdt--session)))
(when (and crdt-buffer (buffer-live-p crdt-buffer))
(with-current-buffer crdt-buffer
,@body))))
(condition-case err
,(cons 'progn body)
(error (if (crdt--server-p)
(signal (car err) (cdr err)) ; didn't implement server side recovery yet
(crdt--client-recover))))))))
(defmacro crdt--with-buffer-name-pull (name &rest body)
"Find CRDT shared buffer associated with NAME and evaluate BODY in it.
@@ -412,7 +428,8 @@ after synchronization is completed."
(crdt-mode)
(crdt--broadcast-maybe (crdt--format-message `(get ,,name)))
(let ((crdt--inhibit-update t))
(insert "Synchronizing with server..."))
(insert "Synchronizing with server...")
(read-only-mode))
(setq crdt--buffer-sync-callback
(lambda ()
,@body))))))))
@@ -587,9 +604,26 @@ Otherwise use a dedicated buffer for displaying active users on CRDT-BUFFER."
t)))
(message "Doesn't have position information for this user yet.")))))
(defun crdt--user-menu-kill ()
"Disconnect the user under point in CRDT user menu.
Only server can perform this action."
(interactive)
(if (crdt--server-p)
(let ((site-id (tabulated-list-get-id)))
(if site-id
(if (eq site-id (crdt--session-local-id crdt--session))
(message "Suicide is not allowed.")
(dolist (p (process-list))
(when (eq (process-get p 'client-id) site-id)
(delete-process p))))
(message "We somehow don't have the SITE-ID for this user.
Please submit a bug report to crdt.el maintainer.")))
(message "Only server can disconnect a user.")))
(defvar crdt-user-menu-mode-map
(let ((map (make-sparse-keymap)))
(define-key map (kbd "RET") #'crdt--user-menu-goto)
(define-key map (kbd "k") #'crdt--user-menu-kill)
map))
(define-derived-mode crdt-user-menu-mode tabulated-list-mode
@@ -599,9 +633,10 @@ Otherwise use a dedicated buffer for displaying active users on CRDT-BUFFER."
("Address" 15 t)]))
(defun crdt-list-users (&optional crdt-buffer display-buffer)
"Display a list of active users working on a CRDT-shared buffer CRDT-BUFFER.
"Display a list of active users working on a CRDT-shared session.
Find the session in CRDT-BUFFER if non NIL, or current buffer.
If DISPLAY-BUFFER is provided, display the output there.
Otherwise use a dedicated buffer for displaying active users on CRDT-BUFFER."
Otherwise create a dedicated buffer."
(interactive)
(with-current-buffer (or crdt-buffer (current-buffer))
(unless crdt--session
@@ -787,10 +822,11 @@ Start the search around POSITION-HINT."
;; (crdt--verify-buffer)
)
(defun crdt--local-delete (beg end)
(defun crdt--local-delete (beg end length)
"Handle local deletion event and return a message to be sent to other peers.
The deletion happens between BEG and END."
(let ((outer-end end))
The deletion happens between BEG and END, and have LENGTH."
(let ((outer-end end)
(crdt--changed-string (crdt--changed-string beg length)))
(crdt--with-insertion-information
(beg 0 nil crdt--changed-string nil (length crdt--changed-string))
(when (crdt--split-maybe)
@@ -801,10 +837,10 @@ The deletion happens between BEG and END."
(crdt--id-replace-offset ending-id (+ 1 left-offset (length crdt--changed-string))))))))
(crdt--with-insertion-information
((length crdt--changed-string) outer-end crdt--changed-string nil 0 nil)
(crdt--split-maybe)))
;; (crdt--verify-buffer)
`(delete ,crdt--buffer-network-name
,beg ,@ (crdt--dump-ids 0 (length crdt--changed-string) crdt--changed-string t)))
(crdt--split-maybe))
;; (crdt--verify-buffer)
`(delete ,crdt--buffer-network-name
,beg ,@ (crdt--dump-ids 0 (length crdt--changed-string) crdt--changed-string t))))
(defun crdt--remote-delete (position-hint id-items)
"Handle remote deletion message of ID-ITEMS.
@@ -837,7 +873,13 @@ Start the search for those ID-ITEMs around POSITION-HINT."
"Before change hook used by CRDT-MODE.
It saves the content to be changed (between BEG and END) into CRDT--CHANGED-STRING."
(unless crdt--inhibit-update
(setq crdt--changed-string (buffer-substring beg end))))
(setq crdt--changed-string (buffer-substring beg end))
(setq crdt--changed-start beg)))
(defsubst crdt--changed-string (beg length)
"Retrieve part of CRDT--CHANGED-STRING starting at BEG with LENGTH before change."
(let ((from (- beg crdt--changed-start)))
(substring crdt--changed-string from (+ from length))))
(defsubst crdt--crdt-id-assimilate (template beg &optional object)
"Make the CRDT-ID property after BEG in OBJECT the same as TEMPLATE.
@@ -854,11 +896,9 @@ TEMPLATE should be a string. If OBJECT is NIL, use current buffer."
(defun crdt--after-change (beg end length)
"After change hook used by CRDT-MODE.
It examine CRDT--CHANGED-STRING (should be saved by
CRDT--BEFORE-STRING and whose length shall equal to LENGTH)
and current content between BEG and END,
update the CRDT-ID for any newly inserted text,
and send message to other peers if needed."
It examine (CRDT--CHANGED-STRING) (should be saved by CRDT--BEFORE-STRING)
and current content between BEG and END with LENGTH,
update the CRDT-ID for any newly inserted text, and send message to other peers if needed."
(when (markerp beg)
(setq beg (marker-position beg)))
(when (markerp end)
@@ -875,18 +915,25 @@ and send message to other peers if needed."
(save-excursion
(goto-char beg)
(if (and (= length (- end beg))
(string-equal crdt--changed-string
(string-equal (crdt--changed-string beg length)
(buffer-substring-no-properties beg end)))
(crdt--crdt-id-assimilate crdt--changed-string beg)
(crdt--crdt-id-assimilate (crdt--changed-string beg length) beg)
(widen)
(with-silent-modifications
(unless (= length 0)
(crdt--broadcast-maybe
(crdt--format-message (crdt--local-delete beg end))))
(crdt--format-message (crdt--local-delete beg end length))))
(unless (= beg end)
(dolist (message (crdt--local-insert beg end))
(crdt--broadcast-maybe
(crdt--format-message message)))))))))))
(crdt--format-message message)))))))
;; process-mark synchronization is dependent on correct CRDT-ID
;; therefore we must do it after the insert/change stuff is done
(crdt--send-process-mark-maybe)
;; see if region stuff changed
(let ((cursor-message (crdt--local-cursor)))
(when cursor-message
(crdt--broadcast-maybe (crdt--format-message cursor-message))))))))
;;; CRDT point/mark synchronization
@@ -957,7 +1004,8 @@ Send message to other peers about any changes."
(unless (eq crdt--buffer-network-name (crdt--session-focused-buffer-name crdt--session))
(crdt--broadcast-maybe
(crdt--format-message `(focus ,(crdt--session-local-id crdt--session) ,crdt--buffer-network-name)))
(setf (crdt--session-focused-buffer-name crdt--session) crdt--buffer-network-name))
(setf (crdt--session-focused-buffer-name crdt--session) crdt--buffer-network-name)
(crdt--refresh-users-maybe))
(let ((cursor-message (crdt--local-cursor)))
(when cursor-message
(crdt--broadcast-maybe (crdt--format-message cursor-message)))))
@@ -1016,6 +1064,17 @@ Verify that CRDT IDs in a document follows ascending order."
(setq pos next-pos)
(setq id next-id))))))
;;; Recovery
(defun crdt--client-recover ()
"Try to recover from a synchronization failure from a client.
Current buffer is assmuned to be the one with synchronization error."
(ding)
(read-only-mode)
(message "Synchronization error detected, try recovering...")
(crdt--broadcast-maybe
(crdt--format-message `(get ,crdt--buffer-network-name))))
;;; Network protocol
(defun crdt--format-message (args)
@@ -1031,7 +1090,7 @@ If (CRDT--SESSION-NETWORK-PROCESS CRDT--SESSION) is a server process,
broadcast MESSAGE-STRING to clients except the one of which CLIENT-ID
property is EQ to WITHOUT.
If (CRDT--SESSION-NETWORK-PROCESS CRDT--SESSION) is a client process,
send MESSAGE-STRING to server when WITHOUT is T."
send MESSAGE-STRING to server when WITHOUT is non-nil."
(when crdt--log-network-traffic
(message "Send %s" message-string))
(if (process-contact (crdt--session-network-process crdt--session) :server)
@@ -1061,7 +1120,7 @@ The overlay is FRONT-ADVANCE and REAR-ADVANCE, and lies between BEG and END."
(base64-encode-string (crdt--get-id end))
(crdt--base64-encode-maybe (crdt--get-id (1- end))))))
(defun crdt--generate-challenge ()
(defsubst crdt--generate-challenge ()
"Generate a challenge string for authentication."
(apply #'unibyte-string (cl-loop for i below 32 collect (random 256))))
@@ -1069,9 +1128,11 @@ The overlay is FRONT-ADVANCE and REAR-ADVANCE, and lies between BEG and END."
"Send messages to a client about the full state of BUFFER.
The network process for the client connection is PROCESS."
(with-current-buffer buffer
(process-send-string process (crdt--format-message `(sync
,crdt--buffer-network-name
,@ (crdt--dump-ids (point-min) (point-max) nil nil t))))
(process-send-string process
(crdt--format-message
`(sync
,crdt--buffer-network-name
,@ (crdt--dump-ids (point-min) (point-max) nil nil t))))
;; synchronize cursor
(maphash (lambda (site-id ov-pair)
(cl-destructuring-bind (cursor-ov . region-ov) ov-pair
@@ -1109,6 +1170,15 @@ The network process for the client connection is PROCESS."
,(car k) ,(cdr k) ,prop ,value))))))
crdt--overlay-table)
;; synchronize process marker if there's any
(let ((buffer-process (get-buffer-process buffer)))
(when buffer-process
(let ((mark-pos (marker-position (process-mark buffer-process))))
(process-send-string process
(crdt--format-message
`(process-mark ,crdt--buffer-network-name
,(crdt--get-id mark-pos) ,mark-pos))))))
(process-send-string process (crdt--format-message `(ready ,crdt--buffer-network-name ,major-mode)))))
(defun crdt--greet-client (process)
@@ -1132,19 +1202,23 @@ The network process for the client connection is PROCESS."
(cons 'add (hash-table-keys (crdt--session-buffer-table crdt--session)))))
;; synchronize contact
(maphash (lambda (k v)
(process-send-string
process (crdt--format-message `(contact ,k ,(crdt--contact-metadata-display-name v)
,(crdt--contact-metadata-host v)
,(crdt--contact-metadata-service v))))
(process-send-string
process (crdt--format-message `(focus ,k ,(crdt--contact-metadata-focused-buffer-name v)))))
(process-send-string process
(crdt--format-message
`(contact ,k ,(crdt--contact-metadata-display-name v)
,(crdt--contact-metadata-host v)
,(crdt--contact-metadata-service v))))
(process-send-string process
(crdt--format-message
`(focus ,k ,(crdt--contact-metadata-focused-buffer-name v)))))
(crdt--session-contact-table crdt--session))
(process-send-string process
(crdt--format-message `(contact ,(crdt--session-local-id crdt--session)
,(crdt--session-local-name crdt--session))))
(crdt--format-message
`(contact ,(crdt--session-local-id crdt--session)
,(crdt--session-local-name crdt--session))))
(process-send-string process
(crdt--format-message `(focus ,(crdt--session-local-id crdt--session)
,(crdt--session-focused-buffer-name crdt--session))))
(crdt--format-message
`(focus ,(crdt--session-local-id crdt--session)
,(crdt--session-focused-buffer-name crdt--session))))
(let ((contact-message `(contact ,client-id ,(process-get process 'client-name)
,(process-contact process :host)
,(process-contact process :service))))
@@ -1195,6 +1269,7 @@ The network process for the client connection is PROCESS."
(cl-destructuring-bind (buffer-name . ids) (cdr message)
(crdt--with-buffer-name
buffer-name
(read-only-mode -1)
(let ((crdt--inhibit-update t))
(unless crdt--buffer-sync-callback
;; try to get to the same position after sync,
@@ -1301,7 +1376,8 @@ Handle received STRING from PROCESS."
(unless (and (process-buffer process)
(buffer-live-p (process-buffer process)))
(set-process-buffer process (generate-new-buffer "*crdt-server*"))
(set-marker (process-mark process) 1))
(with-current-buffer (process-buffer process)
(set-marker (process-mark process) 1)))
(with-current-buffer (process-buffer process)
(unless crdt--session
(setq crdt--session (process-get process 'crdt-session)))
@@ -1336,7 +1412,8 @@ Handle received STRING from PROCESS."
(error (message "%s error when processing message from %s:%s, disconnecting." err
(process-contact process :host) (process-contact process :service))
(if (crdt--server-p)
(delete-process process)
(progn
(delete-process process))
(crdt--stop-session crdt--session))))))
(delete-region (point-min) (point))
(goto-char (point-min)))))))
@@ -1365,6 +1442,7 @@ Handle received STRING from PROCESS."
(unless (eq (process-status process) 'open)
(when (process-get process 'tuntox-process)
(process-send-string process (crdt--format-message '(leave))))
(ding)
(crdt--stop-session (process-get process 'crdt-session))))
;;; UI commands
@@ -1417,10 +1495,12 @@ Otherwise, return the list of names for client sessions."
(cl-find name crdt--session-list
:test 'equal :key #'crdt--session-name))
(defun crdt-share-buffer (session-name)
(defun crdt-share-buffer (session-name &optional port)
"Share the current buffer in the CRDT session with name SESSION-NAME.
Create a new one if such a CRDT session doesn't exist.
If SESSION-NAME is empty, use the buffer name of the current buffer."
Create a new one if such a CRDT session doesn't exist. When PORT
is non-NIL use when creating a new session, otherwise prompt
from minibuffer. If SESSION-NAME is empty, use the buffer name
of the current buffer."
(interactive
(progn
(when (and crdt-mode crdt--session)
@@ -1438,7 +1518,7 @@ If SESSION-NAME is empty, use the buffer name of the current buffer."
(let ((session (crdt--get-session session-name)))
(if session
(crdt--share-buffer (current-buffer) session)
(let ((port (read-from-minibuffer "Create new session on port (default 6530): " nil nil t nil "6530")))
(let ((port (or port (read-from-minibuffer "Create new session on port (default 6530): " nil nil t nil "6530"))))
(when (not (numberp port))
(error "Port must be a number"))
(crdt--share-buffer (current-buffer) (crdt-new-session port session-name))))))
@@ -1504,7 +1584,7 @@ Setup up the server with PASSWORD and assign this Emacs DISPLAY-NAME."
(defun crdt--stop-session (session)
"Kill the CRDT SESSION.
Disconnect if it's a client session, or stop serving if it's a server session."
(when (if (and crdt-confirm-stop-session
(when (if (and crdt-confirm-disconnect
(crdt--server-p session)
(crdt--session-network-clients session))
(yes-or-no-p "There are yet connected clients. Stop session? ")
@@ -1528,10 +1608,14 @@ Disconnect if it's a client session, or stop serving if it's a server session."
(setq crdt--session-list
(delq session crdt--session-list))
(crdt--refresh-sessions-maybe)
(let ((proxy-process (process-get (crdt--session-network-process session) 'tuntox-process)))
(let* ((process (crdt--session-network-process session))
(proxy-process (process-get process 'tuntox-process))
(process-buffer (process-buffer process)))
(delete-process (crdt--session-network-process session))
(when (and process-buffer (buffer-live-p process-buffer))
(kill-buffer process-buffer))
(when (and proxy-process (process-live-p proxy-process))
(interrupt-process proxy-process)))
(delete-process (crdt--session-network-process session))
(message "Disconnected.")))
(defun crdt-stop-session (&optional session-name)
@@ -1761,7 +1845,7 @@ Join with DISPLAY-NAME."
(crdt--base64-encode-maybe (crdt--get-id (1- end))))))))))))
(apply orig-fun ov beg end args))
(cl-defmethod crdt-process-message ((message (head overlay-move)) process)
(cl-defmethod crdt-process-message ((message (head overlay-move)) _process)
(cl-destructuring-bind (buffer-name site-id logical-clock
start-hint start-id-base64 end-hint end-id-base64)
(cdr message)
@@ -1777,7 +1861,7 @@ Join with DISPLAY-NAME."
(end (crdt--find-id (base64-decode-string end-id-base64) end-hint rear-advance)))
(let ((crdt--inhibit-overlay-advices t))
(move-overlay ov start end)))))))
(crdt--broadcast-maybe (crdt--format-message message) (process-get process 'client-id)))
(crdt--broadcast-maybe (crdt--format-message message) nil))
(defun crdt--delete-overlay-advice (orig-fun ov)
(unless crdt--inhibit-overlay-advices
@@ -1832,7 +1916,7 @@ Join with DISPLAY-NAME."
(when (memq (crdt--overlay-metadata-species meta) crdt--enabled-overlay-species)
(let ((crdt--inhibit-overlay-advices t))
(overlay-put ov prop value))))))))
(crdt--broadcast-maybe (crdt--format-message message) (process-get process 'client-id)))
(crdt--broadcast-maybe (crdt--format-message message) nil))
(advice-add 'make-overlay :around #'crdt--make-overlay-advice)
@@ -1867,5 +1951,126 @@ Join with DISPLAY-NAME."
(cl-loop for command in '(org-cycle org-shifttab)
do (advice-add command :around #'crdt--org-overlay-advice))
;;; pseudo process
(cl-defstruct (crdt--pseudo-process (:constructor crdt--make-pseudo-process))
buffer
mark)
(defun crdt--pseudo-process-send-string (pseudo-process string)
(with-current-buffer (crdt--pseudo-process-buffer pseudo-process)
(crdt--broadcast-maybe (crdt--format-message
`(process ,crdt--buffer-network-name ,string)))))
(defun crdt--process-send-string-advice (orig-func process string)
(if (crdt--pseudo-process-p process)
(crdt--pseudo-process-send-string process string)
(funcall orig-func process string)))
(defun crdt--process-send-region-advice (orig-func process start end)
(if (crdt--pseudo-process-p process)
(crdt--pseudo-process-send-string process (buffer-substring-no-properties start end))
(funcall orig-func process start end)))
(defun crdt--get-buffer-process-advice (orig-func buffer)
(and buffer
(setq buffer (get-buffer buffer))
(with-current-buffer buffer
(if (and crdt--session (not (crdt--server-p)))
crdt--buffer-pseudo-process
(funcall orig-func buffer)))))
(defun crdt--get-process-advice (orig-func name)
(if (crdt--pseudo-process-p name)
name
(funcall orig-func name)))
(defun crdt--process-mark-advice (orig-func process)
(if (crdt--pseudo-process-p process)
(crdt--pseudo-process-mark process)
(funcall orig-func process)))
(defun crdt--process-name-advice (orig-func process)
(if (crdt--pseudo-process-p process)
process
(funcall orig-func process)))
(cl-defmethod crdt-process-message ((message (head process-mark)) process)
(cl-destructuring-bind (buffer-name crdt-id position-hint) (cdr message)
(crdt--with-buffer-name
buffer-name
(save-excursion
(goto-char (crdt--id-to-pos crdt-id position-hint))
(let ((buffer-process (get-buffer-process (current-buffer))))
(if buffer-process
(progn (set-marker (process-mark buffer-process) (point))
(setq crdt--last-process-mark-id crdt-id)
(crdt--broadcast-maybe (crdt--format-message message) nil))
(unless (crdt--server-p)
(setq crdt--buffer-pseudo-process
(crdt--make-pseudo-process :buffer (current-buffer) :mark (point-marker)))
(setq crdt--last-process-mark-id crdt-id))))))))
(defun crdt--send-process-mark-maybe ()
(let ((buffer-process (get-buffer-process (current-buffer))))
(when buffer-process
(let* ((mark-pos (marker-position (process-mark buffer-process)))
(current-id (crdt--get-id mark-pos)))
(unless (string-equal crdt--last-process-mark-id current-id)
(setq crdt--last-process-mark-id current-id)
(crdt--broadcast-maybe
(crdt--format-message
`(process-mark ,crdt--buffer-network-name
,current-id ,mark-pos))))))))
(defun crdt--process-status-advice (orig-func process)
(if (crdt--pseudo-process-p process)
'run
(funcall orig-func process)))
(defun crdt--delete-process-advice (orig-func process)
(unless (crdt--pseudo-process-p process)
(funcall orig-func process)))
(defun crdt--process-buffer-advice (orig-func process)
(if (crdt--pseudo-process-p process)
(crdt--pseudo-process-buffer process)
(funcall orig-func process)))
(defun crdt--processp-advice (orig-func object)
(or (crdt--pseudo-process-p object) (funcall orig-func object)))
(defun crdt--dummy () nil)
(defun crdt--process-sentinel/filter-advice (orig-func process)
(if (crdt--pseudo-process-p process)
#'crdt--dummy
(funcall orig-func process)))
(defun crdt--set-process-sentinel/filter-advice (orig-func process func)
(if (crdt--pseudo-process-p process)
nil
(funcall orig-func process func)))
(advice-add 'process-send-string :around #'crdt--process-send-string-advice)
(advice-add 'process-send-region :around #'crdt--process-send-region-advice)
(advice-add 'processp :around #'crdt--processp-advice)
(advice-add 'get-buffer-process :around #'crdt--get-buffer-process-advice)
(advice-add 'get-process :around #'crdt--get-process-advice)
(advice-add 'process-status :around #'crdt--process-status-advice)
(advice-add 'process-buffer :around #'crdt--process-buffer-advice)
(advice-add 'process-mark :around #'crdt--process-mark-advice)
(advice-add 'delete-process :around #'crdt--delete-process-advice)
(advice-add 'process-name :around #'crdt--process-name-advice)
(advice-add 'process-sentinel :around #'crdt--process-sentinel/filter-advice)
(advice-add 'process-filter :around #'crdt--process-sentinel/filter-advice)
(advice-add 'set-process-sentinel :around #'crdt--set-process-sentinel/filter-advice)
(advice-add 'set-process-filter :around #'crdt--set-process-sentinel/filter-advice)
(cl-defmethod crdt-process-message ((message (head process)) process)
(cl-destructuring-bind (buffer-name string) (cdr message)
(crdt--with-buffer-name
buffer-name
(process-send-string (get-buffer-process (current-buffer)) string))))
(provide 'crdt)
;;; crdt.el ends here