[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[elpa] externals/crdt dfc98d3525 38/44: add crdt-goto-{next, prev}-user
From: |
ELPA Syncer |
Subject: |
[elpa] externals/crdt dfc98d3525 38/44: add crdt-goto-{next, prev}-user |
Date: |
Sat, 2 Jul 2022 22:57:35 -0400 (EDT) |
branch: externals/crdt
commit dfc98d35257e812922da103a0a54e96fb155490d
Author: Qiantan Hong <qhong@alum.mit.edu>
Commit: Qiantan Hong <qhong@alum.mit.edu>
add crdt-goto-{next,prev}-user
---
README.org | 123 ++++++++++++++++++++++++++++++++++++-------------------------
crdt.el | 72 ++++++++++++++++++++++++++++++------
2 files changed, 134 insertions(+), 61 deletions(-)
diff --git a/README.org b/README.org
index 1dcd4edca5..5d07211b38 100644
--- a/README.org
+++ b/README.org
@@ -1,9 +1,11 @@
* Introduction
-~crdt.el~ is a real-time collaborative editing environment for Emacs using
Conflict-free Replicated Data Types.
+~crdt.el~ is a real-time collaborative editing environment for Emacs
+using Conflict-free Replicated Data Types.
Highlights:
-- [[https://en.wikipedia.org/wiki/Conflict-free_replicated_data_type][CRDT]],
darling child of collaborative editing researches...
+- [[https://en.wikipedia.org/wiki/Conflict-free_replicated_data_type][CRDT]],
+ darling child of collaborative editing researches...
- Share multiple buffer in one session
- See other users' cursor and region
- Synchronize Org mode folding status
@@ -16,26 +18,30 @@ Highlights:
~crdt.el~ is now on GNU ELPA! Just =M-x package-install crdt=.
-*Caution!!!* Please make sure that you and your peers are on the same
~crdt.el~ version!
-It turns out to be one of the most common causes of ~crdt.el~ not working.
-Because currently the network protocol is not stablized, behavior when using
mismatched versions is unexpectable.
+*Caution!!!* Please make sure that you and your peers are on the same
+~crdt.el~ version! It turns out to be one of the most common causes
+of ~crdt.el~ not working. Because currently the network protocol is
+not stablized, behavior when using mismatched versions is
+unexpectable.
- Strictly speaking, it should works when =crdt-protocol-version= are defined
and the same on all peers.
But why not save some hassle and keep everyone on the latest version.
- To upgrade, just =M-x package-reinstall crdt=, then preferably restart Emacs.
** Start a shared session
-A shared session is a place that can contains multiple buffers (or files),
-and multiple users can join to collaboratively edit those buffers (or files).
-Think about a meeting room with some people working together on some papers.
+A shared session is a place that can contains multiple buffers (or
+files), and multiple users can join to collaboratively edit those
+buffers (or files). Think about a meeting room with some people
+working together on some papers.
In some buffer, =M-x crdt-share-buffer=. Then enter session name.
This add the current buffer to the existing session with that name.
-If no such exists, it creates a new session with the provided session name,
-and initially contains the current buffer as a shared buffer.
+If no such exists, it creates a new session with the provided session
+name, and initially contains the current buffer as a shared buffer.
-If a new session is to be created, you need to enter port (default to 6530),
-optional password and your display name (default to your current
=(user-full-name)=).
+If a new session is to be created, you need to enter port (default to
+6530), optional password and your display name (default to your
+current =(user-full-name)=).
** Join a session
@@ -43,10 +49,16 @@ optional password and your display name (default to your
current =(user-full-nam
** List active users
-In a CRDT shared buffer (either server or client), =M-x crdt-list-users=.
+In a CRDT shared buffer (either server or client), =M-x
+crdt-list-users=.
-In the displayed user list, press ~RET~ on an entry to goto that user's cursor
position.
-Press ~f~ to follow that user, and press ~f~ again or =M-x crdt-stop-follow=
to stop following.
+In the displayed user list, press ~RET~ on an entry to goto that
+user's cursor position. Press ~f~ to follow that user, and press ~f~
+again or =M-x crdt-stop-follow= to stop following.
+
+You can also use =M-x crdt-goto-next-user= and =M-x
+crdt-goto-prev-user= to cycle through users' cursor positions from any
+CRDT shared buffer (don't need to be in the user list buffer).
** List all sessions, and buffer in current session
@@ -57,10 +69,12 @@ press ~RET~ in the session list to see buffers in the
selected session.
** Stop sharing
-=M-x crdt-stop-session= stops a session you've started and disconnect all
other users from it.
-This will ask for your confirmation, customize =crdt-confirm-stop-session= if
you want to disable it.
+=M-x crdt-stop-session= stops a session you've started and disconnect
+all other users from it. This will ask for your confirmation,
+customize =crdt-confirm-stop-session= if you want to disable it.
-You can also press ~k~ or ~d~ in the session list (show it by =M-x
crdt-list-sessions=).
+You can also press ~k~ or ~d~ in the session list (show it by =M-x
+crdt-list-sessions=).
=M-x crdt-stop-share-buffer= removes current buffer from its CRDT
session (this operation is only allowed at server side). You can also
@@ -70,66 +84,75 @@ press ~k~ or ~d~ in the buffer list.
=M-x crdt-disconnect=, then choose a session to disconnect from.
-You can also press ~k~ or ~d~ in the session list (show it by =M-x
crdt-list-sessions=).
+You can also press ~k~ or ~d~ in the session list (show it by =M-x
+crdt-list-sessions=).
-The server Emacs has the privilege to disconnect a user from a session.
-To do so, press ~k~ or ~d~ on an entry in the user list (show it by =M-x
crdt-list-users=).
+The server Emacs has the privilege to disconnect a user from a
+session. To do so, press ~k~ or ~d~ on an entry in the user list
+(show it by =M-x crdt-list-users=).
** Visualizing author of parts of the document
-Turn on =crdt-visualize-author-mode=. Colored underlines are added to each
part of the document,
-based on which user authored it.
+
+Turn on =crdt-visualize-author-mode=. Colored underlines are added to
+each part of the document, based on which user authored it.
** Synchronizing Org folding status
-Turn on =crdt-org-sync-overlay-mode=. All peers that have this enabled have
their
-folding status synchronized. Peers without enabling this minor mode are
unaffected.
+Turn on =crdt-org-sync-overlay-mode=. All peers that have this enabled
+have their folding status synchronized. Peers without enabling this
+minor mode are unaffected.
** Comint integration
-Just go ahead and share you comint REPL buffer! Tested: ~shell~ and
~cmuscheme~.
-By default, when sharing a comint buffer, ~crdt.el~ temporarily reset input
history (as in =M-n= =M-p=)
-so others don't spy into your =.bash_history= and alike.
-You can customize this behavior using variable
=crdt-comint-share-input-history=.
+Just go ahead and share you comint REPL buffer! Tested: ~shell~ and
+~cmuscheme~. By default, when sharing a comint buffer, ~crdt.el~
+temporarily reset input history (as in =M-n= =M-p=) so others don't
+spy into your =.bash_history= and alike. You can customize this
+behavior using variable =crdt-comint-share-input-history=.
** What if we don't have a public IP?
There're various workaround.
-- You can use [[https://gitlab.com/gjedeer/tuntox][tuntox]] to proxy your
connection over the [[https://tox.chat][Tox]] protocol.
- =crdt.el= has experimental built-in integration for =tuntox=.
- To enable it, you need to install =tuntox=,
- set up the custom variable =crdt-tuntox-executable= accordingly (the path to
your =tuntox= binary),
- and set the custom variable =crdt-use-tuntox=.
- Setting it to =t= make =crdt.el= always create =tuntox= proxy for new server
sessions,
- and setting it to ='confirm= make =crdt.el= ask you every time when creating
new sessions.
- After starting a session with =tuntox= proxy,
- you can =M-x crdt-copy-url= to copy a URL recognizable by =M-x crdt-connect=
and share it to your friends.
- Be aware that according to my experience, =tuntox= takes significant time to
establish a connection (sometimes up to half a minute),
+- You can use [[https://gitlab.com/gjedeer/tuntox][tuntox]] to proxy
+ your connection over the [[https://tox.chat][Tox]] protocol.
+ =crdt.el= has experimental built-in integration for =tuntox=. To
+ enable it, you need to install =tuntox=, set up the custom variable
+ =crdt-tuntox-executable= accordingly (the path to your =tuntox=
+ binary), and set the custom variable =crdt-use-tuntox=. Setting it
+ to =t= make =crdt.el= always create =tuntox= proxy for new server
+ sessions, and setting it to ='confirm= make =crdt.el= ask you every
+ time when creating new sessions. After starting a session with
+ =tuntox= proxy, you can =M-x crdt-copy-url= to copy a URL
+ recognizable by =M-x crdt-connect= and share it to your friends. Be
+ aware that according to my experience, =tuntox= takes significant
+ time to establish a connection (sometimes up to half a minute),
however it gets much faster after the connection is established.
-- You can use Teredo to get a public routable IPv6 address.
- One free software implementation is Miredo. Get it from your
- favorite package manager or from [[https://www.remlab.net/miredo/][their
website]].
+- You can use Teredo to get a public routable IPv6 address. One free
+ software implementation is Miredo. Get it from your favorite package
+ manager or from [[https://www.remlab.net/miredo/][their website]].
A typical usage is (run as root)
#+BEGIN_SRC
# /usr/local/sbin/miredo
# ifconfig teredo
#+END_SRC
- The =ifconfig= command should print the information of your IPv6 address.
- Now your traffic go through IPv6, and once you start a =crdt.el= session,
- your friends should be able to join using the IPv6 address.
- For more information, see the user guide on the Miredo website.
+ The =ifconfig= command should print the information of your IPv6
+ address. Now your traffic go through IPv6, and once you start a
+ =crdt.el= session, your friends should be able to join using the
+ IPv6 address. For more information, see the user guide on the
+ Miredo website.
- You can use SSH port forwarding if you have a VPS with public IP.
Example usage:
#+BEGIN_SRC
$ ssh -R EXAMPLE.COM:6530:127.0.0.1:6530 EXAMPLE.COM
#+END_SRC
- This make your =crdt.el= session on local port =6530= accessible from
- =EXAMPLE.COM:6530=.
+ This make your =crdt.el= session on local port =6530= accessible
+ from =EXAMPLE.COM:6530=.
- Note that you need to set the following =/etc/ssh/sshd_config= option on
- your VPS
+ Note that you need to set the following =/etc/ssh/sshd_config=
+ option on your VPS
#+BEGIN_SRC
GatewayPorts yes
#+END_SRC
diff --git a/crdt.el b/crdt.el
index d3768a481d..cfedcc59f3 100644
--- a/crdt.el
+++ b/crdt.el
@@ -370,6 +370,7 @@ Must be used inside CRDT--WITH-INSERTION-INFORMATION."
next-user-id
(buffer-table (make-hash-table :test 'equal)) ; maps buffer network name to
buffer
follow-user-id
+ my-location-marker ; used to store my location temporarily when
crdt-goto-{next,prev}-user
permissions
(local-fcap-table (make-hash-table))
(remote-fcap-table (make-hash-table)))
@@ -916,26 +917,78 @@ Directly return the user name under point if in the user
menu."
(crdt--read-user session)
(signal 'quit nil)))
-(defun crdt-goto-user (session user-id)
- "Goto the cursor location of user with USER-ID in SESSION."
+(defun crdt-goto-user (session user-id &optional noswitch)
+ "Goto the cursor location of user with USER-ID in SESSION.
+If NOSWITCH is non-nil, don't switch window."
(interactive (let ((session (crdt--read-session-maybe)))
(list session (crdt--read-user-maybe session))))
(let ((crdt--session session))
(if (eq user-id (crdt--session-local-id crdt--session))
- (funcall (if (eq major-mode 'crdt-user-menu-mode)
- #'switch-to-buffer-other-window
- #'switch-to-buffer)
- (gethash (crdt--session-focused-buffer-name crdt--session)
(crdt--session-buffer-table crdt--session)))
+ (unless noswitch
+ (funcall (if (eq major-mode 'crdt-user-menu-mode)
+ #'switch-to-buffer-other-window
+ #'switch-to-buffer)
+ (gethash (crdt--session-focused-buffer-name crdt--session)
(crdt--session-buffer-table crdt--session))))
(unless
(cl-block nil
(let* ((metadata (or (gethash user-id (crdt--session-contact-table
crdt--session)) (cl-return)))
(buffer-name (or (crdt--contact-metadata-focus metadata)
(cl-return))))
(crdt--with-buffer-name-pull (buffer-name)
- (switch-to-buffer-other-window (current-buffer))
+ (unless noswitch
+ (switch-to-buffer-other-window (current-buffer)))
(ignore-errors (goto-char (overlay-start (car (gethash user-id
crdt--pseudo-cursor-table)))))
t)))
(message "Doesn't have position information for this user yet.")))))
+(defun crdt--session-ensure-user-menu-buffer (session)
+ (unless (and (crdt--session-user-menu-buffer session)
+ (buffer-live-p (crdt--session-user-menu-buffer session)))
+ (setf (crdt--session-user-menu-buffer session)
+ (generate-new-buffer (format "*CRDT Users %s*" (crdt--session-urlstr
session))))
+ (crdt--assimilate-session (crdt--session-user-menu-buffer session))))
+
+(defun crdt--cycle-user (&optional prev)
+ "Move point in user menu buffer and goto its cursor position.
+If user menu buffer does not exist yet, create it.
+If PREV is non-nil, move backward, otherwise move forward.
+When moving into/out of ourselves, push/pop a global marker instead."
+ (unless crdt--session
+ (error "Not a CRDT shared buffer"))
+ (crdt--session-ensure-user-menu-buffer crdt--session)
+ (let ((mark (point-marker)))
+ (with-current-buffer (crdt--session-user-menu-buffer crdt--session)
+ (when (= (point) (point-max))
+ (forward-line -1))
+ (when (eq (tabulated-list-get-id) (crdt--session-local-id crdt--session))
+ (setf (crdt--session-my-location-marker crdt--session) mark)
+ (add-to-history 'global-mark-ring mark global-mark-ring-max t))
+ (if prev
+ (unless (= (forward-line -1) 0)
+ (goto-char (point-max))
+ (forward-line -1))
+ (forward-line)
+ (when (= (point) (point-max))
+ (goto-char (point-min))))
+ (let ((window (get-buffer-window (current-buffer) t)))
+ (when window (set-window-point window (point))))
+ (if (eq (tabulated-list-get-id) (crdt--session-local-id crdt--session))
+ (if (eq (car global-mark-ring) (crdt--session-my-location-marker
crdt--session))
+ (pop-global-mark)
+ (goto-char (crdt--session-my-location-marker crdt--session)))
+ (crdt-goto-user crdt--session (tabulated-list-get-id) t)))))
+
+(defun crdt-goto-next-user ()
+ "Move point in user menu buffer to next user and goto its cursor position.
+If user menu buffer does not exist yet, create it."
+ (interactive)
+ (crdt--cycle-user))
+
+(defun crdt-goto-prev-user ()
+ "Move point in user menu buffer to previous user and goto its cursor
position.
+If user menu buffer does not exist yet, create it."
+ (interactive)
+ (crdt--cycle-user t))
+
(defun crdt-kill-user (session user-id)
"Disconnect the user with USER-ID in SESSION.
Only server can perform this action."
@@ -974,10 +1027,7 @@ Only server can perform this action."
(with-current-buffer (current-buffer)
(unless crdt--session
(error "Not a CRDT shared buffer"))
- (unless (and (crdt--session-user-menu-buffer crdt--session)
(buffer-live-p (crdt--session-user-menu-buffer crdt--session)))
- (setf (crdt--session-user-menu-buffer crdt--session)
- (generate-new-buffer (format "*CRDT Users %s*"
(crdt--session-urlstr crdt--session))))
- (crdt--assimilate-session (crdt--session-user-menu-buffer
crdt--session)))
+ (crdt--session-ensure-user-menu-buffer crdt--session)
(let ((display-buffer (crdt--session-user-menu-buffer crdt--session)))
(crdt-refresh-users display-buffer)
(switch-to-buffer-other-window display-buffer)))))
- [elpa] externals/crdt 10f423bbef 15/44: Merge branch 'fix' into development, (continued)
- [elpa] externals/crdt 10f423bbef 15/44: Merge branch 'fix' into development, ELPA Syncer, 2022/07/02
- [elpa] externals/crdt 900abacbdd 16/44: Use the term "user-command-functions" instead of proxy, ELPA Syncer, 2022/07/02
- [elpa] externals/crdt 38fdfc5557 07/44: semver, and various fixes, ELPA Syncer, 2022/07/02
- [elpa] externals/crdt 270a4099bb 14/44: return -> cl-return, ELPA Syncer, 2022/07/02
- [elpa] externals/crdt d46be72920 05/44: remove base64 mangling and fix a stupid bug, ELPA Syncer, 2022/07/02
- [elpa] externals/crdt 3a78c8a615 24/44: Improve settings form when CRDT-USE-STUNNEL is nil, ELPA Syncer, 2022/07/02
- [elpa] externals/crdt 569486e6c6 25/44: Lots of changes, ELPA Syncer, 2022/07/02
- [elpa] externals/crdt 6726c7f2d0 30/44: Add special cases for completions when there are 0 or 1 candidates, ELPA Syncer, 2022/07/02
- [elpa] externals/crdt 0a351b4ce2 35/44: Add crdt-default-tls. Don't use tls by default, ELPA Syncer, 2022/07/02
- [elpa] externals/crdt 39c308368e 36/44: Also add (kbd "d") binding for *-kill-*, ELPA Syncer, 2022/07/02
- [elpa] externals/crdt dfc98d3525 38/44: add crdt-goto-{next, prev}-user,
ELPA Syncer <=
- [elpa] externals/crdt dc9ec07fbd 43/44: Revise README, ELPA Syncer, 2022/07/02
- [elpa] externals/crdt 5d90bf0ce2 03/44: generate uninteresting process buffers instead, ELPA Syncer, 2022/07/02
- [elpa] externals/crdt 1dfa6f7c30 02/44: many changes, ELPA Syncer, 2022/07/02
- [elpa] externals/crdt 2c68377c15 01/44: Merge branch 'master' into development, ELPA Syncer, 2022/07/02
- [elpa] externals/crdt 102498e84f 12/44: remove tramp for now, keep it simple, ELPA Syncer, 2022/07/02
- [elpa] externals/crdt 357f4b7174 18/44: more sensible version message, ELPA Syncer, 2022/07/02
- [elpa] externals/crdt b222966674 19/44: fix DEL key in forms mode, ELPA Syncer, 2022/07/02
- [elpa] externals/crdt 5e67684793 20/44: fix bug of hanging data buffer when CRDT--READ-SETTINGS errors, ELPA Syncer, 2022/07/02
- [elpa] externals/crdt e06e6e7236 21/44: add history support for CRDT-READ-SETTINGS, ELPA Syncer, 2022/07/02
- [elpa] externals/crdt fae016ba25 08/44: Preliminary url support, ELPA Syncer, 2022/07/02