Skip to content

Commit

Permalink
✨ emacs-everywhere-linux-copy-function emacs-everywhere-paste-cmd
Browse files Browse the repository at this point in the history
defcustom for alternative methods of handling the clipboard on linux
also added documentation of the added as well as other customizations

Overlaps with issue tecosaur#28 and maybe also a fix for issue tecosaur#10

The modifications have at least a few weak spots.
  1. emacs-everywhere-paste-cmd should maybe be a function
  2. organization of added functions and vars
  3. (eval `(... ,@Args)) is (apply ...) elsewhere

1. There's a solid argument that it's easier to use as a list:
the intent is clearer and there is little ceremony.
but it is weaker (can't drop into elisp) and inconsistent with
emacs-everywhere-filename-function and emacs-everywhere-linux-copy-function

2. I get the sense things were well organized before I started poking around.
But I'm not deep enough into to understand what should go where.

3. `emacs-everywhere-call` uses
    (apply #'call-process command nil t nil (remq nil args))
  Just saw that. That looks cleaner than using eval. I'm here to
  practice lisp. Got carried away in emacs-everywhere-paste-cmd?
  • Loading branch information
WillForan committed Feb 3, 2022
1 parent ace5339 commit 2c0ec9c
Show file tree
Hide file tree
Showing 2 changed files with 72 additions and 13 deletions.
24 changes: 23 additions & 1 deletion README.org
Original file line number Diff line number Diff line change
Expand Up @@ -51,4 +51,26 @@ C-k= still copies the content to the clipboard, but never pastes.
-----

^{*†*} This requires the Emacs daemon to be running, but that's super easy.
Just call =emacs --daemon= and you're sorted!
Just call =emacs --daemon= or =M-x server-start= and you're sorted!

* Customize

** Example hook
The default simulated key chord pastes into Pidgin as a single line. To preserve newlines, the desired combo is =Control+V= (instead of the default =Shift+Insert=). Here we create a function that temporarily modifies the paste command when emacs-everywhere was launched with Pidgin focused.
#+begin_src elisp
;; "Paste as plaintext" using "Control Shift V" for GTK app Pidgin IM
(defun emacs-everywhere-pidgin-paste ()
(when (eq (emacs-everywhere-app-class emacs-everywhere-current-app) "Pidgin")
(set (make-local-variable 'emacs-everywhere-paste-cmd)
'("xdotool" "key" "--clearmodifiers" "Control+V"))))

(add-hook 'emacs-everywhere-init-hooks 'emacs-everywhere-pidgin-paste)
#+end_src

** Highlights

Window and app names that will open in markdown mode are enumerated in =emacs-everywhere-markdown-windows= and =emacs-everywhere-markdown-apps=.

How the clipboard is handled can be redefined using =emacs-everywhere-linux-copy-function= and =emacs-everywhere-paste-cmd=.

See =M-x customize-groups [RET] emacs-everywhere= for the full list. Or peak at the source.
61 changes: 49 additions & 12 deletions emacs-everywhere.el
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,15 @@
:type 'boolean
:group 'emacs-everywhere)

(defcustom emacs-everywhere-paste-cmd nil
"How to paste back. List like (cmd arg1 arg2). Used with `emacs-everywhere-paste'.
Example: '(\"xdotool\" \"key\" \"--clearmodifiers\" \"Shift+Insert\")
Consider pairing with `make-local-variable' in `emacs-everywhere-init-hooks'"
:type 'sexp
:group 'emacs-everywhere)

(defcustom emacs-everywhere-markdown-windows
'("Stack Exchange" "Stack Overflow" "Reddit" ; Sites
'("Stack Exchange" "Stack Overflow" "Reddit" ; Sites
"Pull Request" "Issue" "Comparing .*\\.\\.\\." ; Github
"Discord")
"For use with `emacs-everywhere-markdown-p'.
Expand Down Expand Up @@ -224,6 +231,45 @@ buffers.")
(org-ctrl-c-ctrl-c)
(emacs-everywhere-finish)))

(defun emacs-everywhere-what-paste-cmd ()
"What command to use to paste."
(cond (emacs-everywhere-paste-cmd
emacs-everywhere-paste-cmd)
((eq system-type 'darwin)
'("osascript"
"-e"
"tell application \"System Events\" to keystroke \"v\" using command down"))
(t
'("xdotool"
"key"
"--clearmodifiers"
"Shift+Insert"))))

(defun emacs-everywhere-paste ()
"Paste with operating system specific program or custom cmd"
(interactive)
(let* ((cmd-list (emacs-everywhere-what-paste-cmd))
(cmd (car cmd-list))
(args (cdr cmd-list)))
(eval `(call-process ,cmd nil nil nil ,@args))))

(defun emacs-everywhere-linux-copy ()
"Put the current buffer onto the clipboard."
(let ((inhibit-message t)
(require-final-newline nil)
write-file-functions)
(write-file buffer-file-name)
(pp (buffer-string))
(call-process "xclip" nil nil nil "-selection" "clipboard" buffer-file-name)))

(defcustom emacs-everywhere-linux-copy-function
#'emacs-everywhere-linux-copy
"A function to populate the clipboard. To be pasted into original app by `emacs-everywhere-paste'"
:type 'function
:group 'emacs-everywhere)



(defun emacs-everywhere-finish (&optional abort)
"Copy buffer content, close emacs-everywhere window, and maybe paste.
Must only be called within a emacs-everywhere buffer.
Expand All @@ -236,12 +282,7 @@ Never paste content when ABORT is non-nil."
(run-hooks 'emacs-everywhere-final-hooks)
(gui-select-text (buffer-string))
(unless (eq system-type 'darwin) ; handle clipboard finicklyness
(let ((inhibit-message t)
(require-final-newline nil)
write-file-functions)
(write-file buffer-file-name)
(pp (buffer-string))
(call-process "xclip" nil nil nil "-selection" "clipboard" buffer-file-name))))
(funcall emacs-everywhere-linux-copy-function)))
(sleep-for 0.01) ; prevents weird multi-second pause, lets clipboard info propagate
(let ((window-id (emacs-everywhere-app-id emacs-everywhere-current-app)))
(if (eq system-type 'darwin)
Expand All @@ -255,11 +296,7 @@ Never paste content when ABORT is non-nil."
(when (and (frame-parameter nil 'emacs-everywhere-app)
emacs-everywhere-paste-p
(not abort))
(if (eq system-type 'darwin)
(call-process "osascript" nil nil nil
"-e" "tell application \"System Events\" to keystroke \"v\" using command down")
(call-process "xdotool" nil nil nil
"key" "--clearmodifiers" "Shift+Insert"))))
(emacs-everywhere-paste)))
;; Clean up after ourselves in case the buffer survives `server-buffer-done'
;; (b/c `server-existing-buffer' is non-nil).
(emacs-everywhere-mode -1)
Expand Down

0 comments on commit 2c0ec9c

Please sign in to comment.