From 9245a347a4c2e11341eedef2e62ab23510131305 Mon Sep 17 00:00:00 2001 From: Jonathan Ming Date: Mon, 24 Jul 2023 10:29:46 -0700 Subject: [PATCH] module: add :tools collab Add a collaborative editing module, powered by crdt.el. Ref: https://code.librehq.com/qhong/crdt.el Co-authored-by: Arte Ebrahimi --- modules/config/default/+evil-bindings.el | 24 ++++ modules/tools/collab/README.org | 138 +++++++++++++++++++++++ modules/tools/collab/config.el | 8 ++ modules/tools/collab/doctor.el | 4 + modules/tools/collab/packages.el | 6 + templates/init.example.el | 1 + 6 files changed, 181 insertions(+) create mode 100644 modules/tools/collab/README.org create mode 100644 modules/tools/collab/config.el create mode 100644 modules/tools/collab/doctor.el create mode 100644 modules/tools/collab/packages.el diff --git a/modules/config/default/+evil-bindings.el b/modules/config/default/+evil-bindings.el index 5cd3be659..1f3278636 100644 --- a/modules/config/default/+evil-bindings.el +++ b/modules/config/default/+evil-bindings.el @@ -505,6 +505,30 @@ :desc "Unicode" "u" #'insert-char :desc "From clipboard" "y" #'+default/yank-pop) + ;;; l --- live share/collab + ;;; TODO Do you like this location for this map? This was the best idea we + ;;; could come up with, but we're happy to move it if there's a better + ;;; place! Also not sure if we're allowed to say "live share" since that's + ;;; a blatant ripoff of VS Code's name for this feature + (:when (modulep! :tools collab) + (:prefix-map ("l" . "live share/collab") + :desc "Switch to a shared buffer" "b" #'crdt-switch-to-buffer + :desc "Connect to a session" "c" #'crdt-connect + :desc "Disconnect from session" "d" #'crdt-disconnect + :desc "Toggle following user's cursor" "f" #'crdt-follow-user + :desc "Stop following user if any" "F" #'crdt-stop-follow + :desc "Goto another user's cursor" "g" #'crdt-goto-user + :desc "List shared buffers" "i" #'crdt-list-buffers + :desc "Kick a user (host only)" "k" #'crdt-kill-user + :desc "List sessions" "l" #'crdt-list-sessions + :desc "Share current buffer" "s" #'crdt-share-buffer + :desc "Stop sharing current buffer" "S" #'crdt-stop-share-buffer + :desc "List connected users" "u" #'crdt-list-users + :desc "Stop a session (host only)" "x" #'crdt-stop-session + :desc "Copy URL of current session" "y" #'crdt-copy-url + :desc "Goto next user's cursor" "]" #'crdt-goto-next-user + :desc "Goto previous user's cursor" "[" #'crdt-goto-prev-user)) + ;;; n --- notes (:prefix-map ("n" . "notes") :desc "Search notes for symbol" "*" #'+default/search-notes-for-symbol-at-point diff --git a/modules/tools/collab/README.org b/modules/tools/collab/README.org new file mode 100644 index 000000000..f951a0fa8 --- /dev/null +++ b/modules/tools/collab/README.org @@ -0,0 +1,138 @@ +#+TITLE: tools/collab +#+DATE: September 2, 2022 +#+SINCE: v3.0.0 +#+STARTUP: inlineimage nofold + +* Table of Contents :TOC_3:noexport: +- [[#description][Description]] + - [[#maintainers][Maintainers]] + - [[#module-flags][Module Flags]] + - [[#plugins][Plugins]] +- [[#prerequisites][Prerequisites]] + - [[#with-tunnel][With =+tunnel=]] + - [[#macos][macOS]] + - [[#linux][Linux]] + - [[#windows][Windows]] +- [[#features][Features]] + - [[#keybindings][Keybindings]] +- [[#configuration][Configuration]] +- [[#troubleshooting][Troubleshooting]] + - [[#people-outside-my-lan-cant-connect-to-the-collab-session-im-hosting][People outside my LAN can't connect to the collab session I'm hosting]] + - [[#i-got-an-error-saying-something-including-crdtel-protocol][I got an error saying something including "crdt.el protocol"]] + +* Description +This module adds collaborative editing via the [[https://code.librehq.com/qhong/crdt.el][crdt]] plugin. + +** Maintainers ++ [[https://github.com/artenator][@artenator]] ++ [[https://github.com/jming422][@jming422]] + +** Module Flags ++ =+tunnel= Enables TCP forwarding over the [[https://tox.chat/][Tox]] protocol so that a collaborative + editing session can be established between machines that are behind a NAT. + +** Plugins ++ [[https://code.librehq.com/qhong/crdt.el][crdt]] + +* Prerequisites +With no flags, this module requires nothing else to work. The =+tunnel= flag has one dependency: + +** With =+tunnel= +Tunneling requires the [[https://github.com/gjedeer/tuntox][tuntox]] program, which is used to establish TCP +connections to your collaborators over the Tox peer-to-peer networking protocol. + +*** macOS +tuntox can be installed from Homebrew: +#+BEGIN_SRC bash +brew install tuntox +#+END_SRC + +*** Linux +You can download the tuntox binary for most architectures from its [[https://github.com/gjedeer/tuntox/releases][Releases]] page +on GitHub, and it can be found in some [[https://repology.org/project/tuntox/versions][package manager repositories]] as well. + +*** Windows +Tuntox is currently not supported on Windows, so Windows users cannot use the +=+tunnel= flag and must choose another networking solution, such as a VPN. For +more options, see [[*People outside my LAN can't connect to the collab session I'm hosting][this Troubleshooting entry]]. + +* Features ++ Start a collaborative editing session in one of your buffers with =M-x + crdt-share-buffer= and following the prompts. ++ If you're using =+tunnel=, get the sharable URL of your session using =M-x + crdt-copy-url=. If not using =+tunnel=, then instead of a URL, others can + connect using your public IP address and chosen TCP port number (default port + is 6530) ++ Others can connect to your session using =M-x crdt-connect= and following the + prompts to pass in your tunnel URL or IP address and port ++ Once connected, some commands you can use are: + + =crdt-list-buffers= to list shared buffers. Use this after =crdt-connect= to + open shared buffers for editing! + + =crdt-share-buffer= Start a new collaboration session, or add more buffers + to an existing session. Once a session has started, both the host and + clients can use this function to share buffers! + + =crdt-goto-user= to jump to another collaborator + + =crdt-follow-user= / =crdt-stop-follow= to toggle following another + collaborator + + =crdt-visualize-author-mode= to add colors to regions of the buffer, + visualizing who most recently edited each part of the buffer + + =crdt-stop-session= (host) / =crdt-disconnect= (client) to exit the collab + session + +** Keybindings +When this module is enabled, the `SPC l` leader keymap becomes available, making most of the above functions and more available under that prefix: + +| Binding | Description | +|-----------+---------------------------------------------------------| +| =SPC l b= | Switch to a shared buffer | +| =SPC l c= | Connect to a session | +| =SPC l d= | Disconnect from session | +| =SPC l f= | Toggle following another user's cursor | +| =SPC l F= | Stop following user if any | +| =SPC l g= | Goto another user's cursor | +| =SPC l i= | List shared buffers | +| =SPC l k= | Kick a user (host only) | +| =SPC l l= | List sessions | +| =SPC l s= | Share current buffer, optionally starting a new session | +| =SPC l S= | Stop sharing current buffer | +| =SPC l u= | List connected users | +| =SPC l x= | Stop a session (host only) | +| =SPC l y= | Copy URL of current session | +| =SPC l ]= | Goto next user's cursor | +| =SPC l [= | Goto previous user's cursor | + + +* Configuration + +This list is not exhaustive; for the full list of config options, type =SPC h V +crdt-= after loading the module. + +| Custom variable | Default | Function | +|-----------------------------+--------------------------+-------------------------------------------------------------------------------------------| +| crdt-ask-for-name | t | Set to nil to always use =crdt-default-name= as your name without asking | +| crdt-default-name | ~(user-full-name)~ | Your display name in collaboration sessions | +| crdt-tuntox-executable | "tuntox" | Path to the tuntox binary | +| crdt-tuntox-password-in-url | t if =+tunnel=, else nil | Set to t to put your session password (in plaintext) into the URL made by =crdt-copy-url= | + + +* Troubleshooting + +** People outside my LAN can't connect to the collab session I'm hosting +Without =+tunnel= enabled, on most home/work networks you will be unable to have +others join you from across the Internet unless you set something up to +facilitate the connection between collaborators. +You have a lot of options here, but some of the most common are: ++ Enable the =+tunnel= flag to tunnel your traffic using the [[https://tox.chat/][Tox]] peer-to-peer + networking protocol ++ Use a VPN ++ Use a non-peer-to-peer tunneling method, such as Teredo. One free software + implementation of this method is called [[https://www.remlab.net/miredo/][Miredo]] ++ Use a TCP reverse proxy server, such as [[https://ngrok.com/][ngrok]] ++ Use SSH port forwarding, if you have access to a server with a public network + address + +** I got an error saying something including "crdt.el protocol" +All collaborators must be using the same version of the crdt package in order to +guarantee stability & support for all features. These types of errors should not +occur if everyone is up to date, so ensure that all collaborators have upgraded +Doom Emacs to the latest version and have not pinned =crdt=. diff --git a/modules/tools/collab/config.el b/modules/tools/collab/config.el new file mode 100644 index 000000000..32dc2ebfe --- /dev/null +++ b/modules/tools/collab/config.el @@ -0,0 +1,8 @@ +;;; tools/collab/config.el -*- lexical-binding: t; -*- + +(use-package! crdt + :commands (crdt-share-buffer crdt-connect) + :init + (when (featurep! +tunnel) + (setq crdt-use-tuntox t) + (setq crdt-tuntox-password-in-url t))) diff --git a/modules/tools/collab/doctor.el b/modules/tools/collab/doctor.el new file mode 100644 index 000000000..8d5caacb9 --- /dev/null +++ b/modules/tools/collab/doctor.el @@ -0,0 +1,4 @@ +;;; tools/collab/doctor.el -*- lexical-binding: t; -*- + +(when (and (featurep! +tunnel) (not (executable-find "tuntox"))) + (warn! "Couldn't find tuntox command. This needs to be on your path for the +tunnel flag to work properly.")) diff --git a/modules/tools/collab/packages.el b/modules/tools/collab/packages.el new file mode 100644 index 000000000..326af8b39 --- /dev/null +++ b/modules/tools/collab/packages.el @@ -0,0 +1,6 @@ +;; -*- no-byte-compile: t; -*- +;;; tools/collab/packages.el + +(package! crdt + :recipe (:host nil :repo "https://code.librehq.com/qhong/crdt.el") + :pin "3ba890658d657db5d6aaedd5c2a78b6f93a5f139") diff --git a/templates/init.example.el b/templates/init.example.el index bff0c70a2..a55152d26 100644 --- a/templates/init.example.el +++ b/templates/init.example.el @@ -87,6 +87,7 @@ :tools ;;ansible ;;biblio ; Writes a PhD for you (citation needed) + ;;collab ; buffers with friends ;;debugger ; FIXME stepping through code, to help you add bugs ;;direnv ;;docker