122 lines
4.3 KiB
EmacsLisp
122 lines
4.3 KiB
EmacsLisp
;;;; Imeks: Use Emacs as your Xorg pseudo-IME!
|
||
|
||
;; Copyright © 2024 Jaidyn Ann <jadedctrl@posteo.at>
|
||
;;
|
||
;; This program is free software: you can redistribute it and/or
|
||
;; modify it under the terms of the GNU General Public License as
|
||
;; published by the Free Software Foundation, either version 3 of
|
||
;; the License, or (at your option) any later version.
|
||
;;
|
||
;; This program is distributed in the hope that it will be useful,
|
||
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
;; GNU General Public License for more details.
|
||
;;
|
||
;; You should have received a copy of the GNU General Public License
|
||
;; along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||
|
||
(define-minor-mode imeks-mode
|
||
"A mode for typing the contents of an Emacs buffer into X windows."
|
||
:interactive nil
|
||
:lighter " Imeks"
|
||
:group 'imeks)
|
||
|
||
|
||
;;; Options
|
||
;;; ―――――――――――――――――――――――――――――――――――――
|
||
(defcustom imeks-mode-hook nil
|
||
"Hook called when entering Imeks mode."
|
||
:type 'hook
|
||
:group 'imeks)
|
||
|
||
(defcustom imeks-typing-delay .2
|
||
"How long Imeks will wait before typing, by default.\n
|
||
This gives you time to switch from Emacs' X window to another."
|
||
:type 'number
|
||
:group 'imeks)
|
||
|
||
(defcustom imeks-xdotool-path "xdotool"
|
||
"The path to the program xdotool.
|
||
It is used by Imeks to mimic an X keyboard."
|
||
:type 'file
|
||
:group 'imeks)
|
||
|
||
(defcustom imeks-type-on-frame-delete 't
|
||
"When non-nil, Imeks may type the active buffer on frame-deletion.\n
|
||
This will only happen if the buffer is in `imeks-mode`, and
|
||
is for useful if you use frames dedicated to Imeks."
|
||
:type 'boolean
|
||
:group 'imeks)
|
||
|
||
|
||
|
||
;;; Core
|
||
;;; ―――――――――――――――――――――――――――――――――――――
|
||
(defun imeks ()
|
||
(interactive)
|
||
(switch-to-buffer (generate-new-buffer "*imeks*"))
|
||
(imeks-mode))
|
||
|
||
(defun imeks-type-buffer (&optional buffer delay)
|
||
"Types a buffer's contents, mimicking X keyboard input.\n
|
||
Waits DELAY seconds before beginning to type, by default
|
||
`imeks-typing-delay`."
|
||
(interactive)
|
||
(let ((buffer (or buffer (current-buffer))))
|
||
(with-current-buffer buffer
|
||
(imeks-type-region buffer (point-min) (point-max) delay))))
|
||
|
||
(defun imeks-type-region (&optional buffer start end delay)
|
||
"Types a region's contents, mimicking X keyboard input.\n
|
||
Waits DELAY seconds before beginning to type, by default
|
||
`imeks-typing-delay`."
|
||
(interactive)
|
||
(xdotool-type-string
|
||
(with-current-buffer (or buffer (current-buffer))
|
||
(buffer-substring-no-properties (or start (region-beginning))
|
||
(or end (region-end))))
|
||
(or delay imeks-typing-delay)))
|
||
|
||
|
||
|
||
;;; Private hooks
|
||
;;; ―――――――――――――――――――――――――――――――――――――
|
||
(defun imeks--handle-delete-frame (frame)
|
||
"When a frame is deleted and the current buffer is in
|
||
`imeks-mode`, kill the buffer and type its contents as
|
||
if an X keyboard."
|
||
(when (and imeks-mode imeks-type-on-frame-delete)
|
||
(let ((buffer-contents
|
||
(buffer-substring-no-properties (point-min) (point-max))))
|
||
(kill-buffer)
|
||
(xdotool-type-string buffer-contents .2))))
|
||
|
||
(nconc delete-frame-functions '(imeks--handle-delete-frame))
|
||
|
||
|
||
;;
|
||
;;; Util
|
||
;;; ―――――――――――――――――――――――――――――――――――――
|
||
(defun xdotool-type-string (string &optional delay)
|
||
"Types a STRING to the current X display, using xdotool.\n
|
||
Optionally waits a DELAY in seconds before typing the string."
|
||
(let* ((sleep-cmd
|
||
(format "sleep %f;" (or delay 0)))
|
||
(type-cmds
|
||
(mapcar (lambda (line)
|
||
(format "%s type \"$(cat <<'EOF'\n%s\nEOF\n)\""
|
||
imeks-xdotool-path line))
|
||
(string-lines string)))
|
||
(type-cmd ; Work-around, since not all programs accept a typed newline.
|
||
(seq-reduce (lambda (a b)
|
||
(if a
|
||
(format "%s; %s key return; %s" a imeks-xdotool-path b)
|
||
b))
|
||
type-cmds nil))
|
||
(cmd-string
|
||
(concat sleep-cmd type-cmd)))
|
||
(call-process "bash" nil 0 nil
|
||
"-c" cmd-string)))
|
||
|
||
(provide 'imeks)
|