121 lines
4.2 KiB
EmacsLisp
121 lines
4.2 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.
|
|||
|
(reduce (lambda (a b)
|
|||
|
(format "%s; %s key return; %s" a imeks-xdotool-path b))
|
|||
|
type-cmds))
|
|||
|
(cmd-string
|
|||
|
(concat sleep-cmd type-cmd)))
|
|||
|
(call-process "bash" nil 0 nil
|
|||
|
"-c" cmd-string)))
|
|||
|
|
|||
|
|
|||
|
(provide 'imeks)
|