Redesign EAF binding, introducing eaf-bind-key, support C-h m (#3)

* Experimenting with bind-keys

* Redesign EAF binding, introducing eaf-bind-key, support C-h m
master
Mingde Zeng 6 years ago committed by GitHub
parent 9fffc00200
commit f8dca287ae
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 304
      eaf.el

304
eaf.el

@ -7,7 +7,7 @@
;; Copyright (C) 2018, Andy Stewart, all rights reserved. ;; Copyright (C) 2018, Andy Stewart, all rights reserved.
;; Created: 2018-06-15 14:10:12 ;; Created: 2018-06-15 14:10:12
;; Version: 0.3 ;; Version: 0.3
;; Last-Updated: Fri Nov 29 08:46:55 2019 (-0500) ;; Last-Updated: Fri Nov 29 21:29:56 2019 (-0500)
;; By: Mingde (Matthew) Zeng ;; By: Mingde (Matthew) Zeng
;; URL: http://www.emacswiki.org/emacs/download/eaf.el ;; URL: http://www.emacswiki.org/emacs/download/eaf.el
;; Keywords: ;; Keywords:
@ -154,78 +154,74 @@ Try not to modify this alist directly. Use `eaf-setq' to modify instead."
:group 'eaf) :group 'eaf)
(defcustom eaf-browser-keybinding (defcustom eaf-browser-keybinding
'(("M-f" . "history_forward") '((history_forward . "M-f")
("M-b" . "history_backward") (history_backward . "M-b")
("M-q" . "clean_all_cookie") (clean_all_cookie . "M-q")
("C--" . "zoom_out") (zoom_out . "C--")
("C-=" . "zoom_in") (zoom_in . "C-=")
("C-0" . "zoom_reset") (zoom_reset . "C-0")
("C-n" . "scroll_up") (scroll_up . "C-n")
("C-p" . "scroll_down") (scroll_down . "C-p")
("C-v" . "scroll_up_page") (scroll_up_page . "C-v")
("M-v" . "scroll_down_page") (scroll_down_page . "M-v")
("M-<" . "scroll_to_begin") (scroll_to_begin . "M-<")
("M->" . "scroll_to_bottom")) (scroll_to_bottom . "M->"))
"The keybinding of browser." "The keybinding of EAF Browser."
:type 'cons :type 'cons
:group 'eaf) :group 'eaf)
(defcustom eaf-browser-key-alias (defcustom eaf-browser-key-alias
'(("C-a" . "<home>") '((<home> . "C-a")
("C-e" . "<end>") (<end> . "C-e"))
) "The key alias of EAF Browser."
"The key alias of browser."
:type 'cons :type 'cons
:group 'eaf) :group 'eaf)
(defcustom eaf-pdfviewer-keybinding (defcustom eaf-pdfviewer-keybinding
'(("j" . "scroll_up") '((scroll_up . "j")
("k" . "scroll_down") (scroll_down . "k")
("SPC" . "scroll_up_page") (scroll_up_page . "SPC")
("b" . "scroll_down_page") (scroll_down_page . "b")
("t" . "switch_to_read_mode") (switch_to_read_mode . "t")
("." . "scroll_to_home") (scroll_to_home . ".")
("," . "scroll_to_end") (scroll_to_end . ",")
("0" . "zoom_reset") (zoom_reset . "0")
("=" . "zoom_in") (zoom_in . "=")
("-" . "zoom_out") (zoom_out . "-")
("g" . "jump_to_page") (jump_to_page . "g")
("p" . "jump_to_percent") (jump_to_percent . "p")
("[" . "remember_current_position") (remember_current_position . "[")
("]" . "remeber_jump") (remeber_jump . "]")
("i" . "toggle_inverted_mode") (toggle_inverted_mode . "i"))
) "The keybinding of EAF PDF Viewer."
"The keybinding of pdf viewer."
:type 'cons :type 'cons
:group 'eaf) :group 'eaf)
(defcustom eaf-videoplayer-keybinding (defcustom eaf-videoplayer-keybinding
'(("SPC" . "toggle_play") '((toggle_play . "SPC")
("h" . "play_backward") (play_backward . "h")
("l" . "play_forward") (play_forward . "l"))
) "The keybinding of EAF Video Player."
"The keybinding of video player."
:type 'cons :type 'cons
:group 'eaf) :group 'eaf)
(defcustom eaf-imageviewer-keybinding (defcustom eaf-imageviewer-keybinding
'(("j" . "load_next_image") '((load_next_image . "j")
("k" . "load_prev_image") (load_prev_image . "k"))
) "The keybinding of EAF Image Viewer."
"The keybinding of image viewer."
:type 'cons :type 'cons
:group 'eaf) :group 'eaf)
(defcustom eaf-terminal-keybinding (defcustom eaf-terminal-keybinding
'(("C--" . "zoom_out") '((zoom_out . "C--")
("C-=" . "zoom_in")) (zoom_in . "C-="))
"The keybinding of terminal." "The keybinding of EAF Terminal."
:type 'cons :type 'cons
:group 'eaf) :group 'eaf)
(defcustom eaf-camera-keybinding (defcustom eaf-camera-keybinding
'(("j" . "take_photo")) '((take_photo . "j"))
"The keybinding of camera" "The keybinding of EAF Camera."
:type 'cons :type 'cons
:group 'eaf) :group 'eaf)
@ -366,13 +362,57 @@ We need calcuate render allocation to make sure no black border around render co
(random (expt 16 4)) (random (expt 16 4))
(random (expt 16 4)))) (random (expt 16 4))))
(defun eaf-create-buffer (input-content) (defun eaf-dummy-function (sym)
"Define an alias from SYM to a dummy function that acts as a placeholder."
(defalias sym (lambda nil
"This will function will be handled on the Python side.
Please ONLY use `eaf-bind-key' to edit EAF keybindings!"
(interactive)
(eaf-monitor-key-event))))
(defun eaf-gen-keybinding-map (keybinding)
"Configure the eaf-mode-map from KEYBINDING, one of the eaf-*-keybinding variables."
(setq eaf-mode-map
(let ((map (make-sparse-keymap)))
(cl-loop for (sym . val) in keybinding
do (eaf-dummy-function sym)
(define-key map (kbd val) sym)) map)))
(defun eaf-create-buffer (input-content app-name)
"Create an EAF buffer given INPUT-CONTENT and APP-NAME."
(cond ((equal app-name "browser")
(eaf-gen-keybinding-map eaf-browser-keybinding))
((equal app-name "pdf-viewer")
(eaf-gen-keybinding-map eaf-pdfviewer-keybinding))
((equal app-name "video-player")
(eaf-gen-keybinding-map eaf-videoplayer-keybinding))
((equal app-name "image-viewer")
(eaf-gen-keybinding-map eaf-imageviewer-keybinding))
((equal app-name "camera")
(eaf-gen-keybinding-map eaf-camera-keybinding))
((equal app-name "terminal")
(eaf-gen-keybinding-map eaf-terminal-keybinding)))
(let* ((file-or-command-name (substring input-content (string-match "[^\/]*\/?$" input-content))) (let* ((file-or-command-name (substring input-content (string-match "[^\/]*\/?$" input-content)))
(eaf-buffer (generate-new-buffer (truncate-string-to-width file-or-command-name eaf-title-length)))) (eaf-buffer (generate-new-buffer (truncate-string-to-width file-or-command-name eaf-title-length))))
(with-current-buffer eaf-buffer (with-current-buffer eaf-buffer
(eaf-mode)) (eaf-mode))
eaf-buffer)) eaf-buffer))
(defun eaf-identify-key-in-app (key-command app-name)
(cond ((equal app-name "browser")
(assoc key-command eaf-browser-keybinding))
((equal app-name "pdf-viewer")
(assoc key-command eaf-pdfviewer-keybinding))
((equal app-name "video-player")
(assoc key-command eaf-videoplayer-keybinding))
((equal app-name "image-viewer")
(assoc key-command eaf-imageviewer-keybinding))
((equal app-name "camera")
(assoc key-command eaf-camera-keybinding))
((equal app-name "terminal")
(assoc key-command eaf-terminal-keybinding))))
(defun eaf-is-support (url) (defun eaf-is-support (url)
(dbus-call-method (dbus-call-method
:session "com.lazycat.eaf" :session "com.lazycat.eaf"
@ -456,81 +496,83 @@ We need calcuate render allocation to make sure no black border around render co
(message (format "export %s to html" (buffer-file-name)))))))) (message (format "export %s to html" (buffer-file-name))))))))
(defun eaf-monitor-key-event () (defun eaf-monitor-key-event ()
"Monitor key events during EAF process."
(unless (unless
(ignore-errors (ignore-errors
(with-current-buffer (buffer-name) (with-current-buffer (buffer-name)
(when (eq major-mode 'eaf-mode) (when (eq major-mode 'eaf-mode)
(let* ((event last-command-event) (let* ((event last-command-event)
(key (make-vector 1 event)) (key (if event
(key-command (format "%s" (key-binding key))) (make-vector 1 event)
(key-desc (key-description key)) (where-is-internal last-command)))
) (key-command (key-binding key))
(key-desc (key-description key)))
;; Uncomment for debug. ;; Uncomment for debug.
;; (message (format "!!!!! %s %s %s %s %s" event key key-command key-desc buffer-app-name)) ;; (message (format "!!!!! %s %s %s %s %s" event key (symbol-name key-command) key-desc buffer-app-name))
(cond (cond
;; Fix #51 , don't handle F11 to make emacs toggle frame fullscreen status successfully. ;; Fix #51 , don't handle F11 to make emacs toggle frame fullscreen status successfully.
((equal key-desc "<f11>") ((equal key-desc "<f11>")
t) t)
;; Just send event when user insert single character. ((and
;; Don't send event 'M' if user press Ctrl + M. (eaf-identify-key-in-app key-command buffer-app-name)
((and (or (string-match "^[CMSs]-.*" key-desc))
(equal key-command "self-insert-command") (message "HI")
(equal key-command "completion-select-if-within-overlay")) (cond ((equal buffer-app-name "browser")
(equal 1 (string-width (this-command-keys)))) (let ((function-name-value (symbol-name (car (rassoc key-desc eaf-browser-keybinding)))))
(cond ((equal buffer-app-name "pdf-viewer") (if function-name-value
(eaf-handle-app-key buffer-id key-desc eaf-pdfviewer-keybinding)) (eaf-call "execute_function" buffer-id function-name-value)
((equal buffer-app-name "video-player") (let ((key-alias-value (symbol-name (car (rassoc key-desc eaf-browser-keybinding)))))
(eaf-handle-app-key buffer-id key-desc eaf-videoplayer-keybinding)) (if key-alias-value
((equal buffer-app-name "image-viewer") (eaf-call "send_key" buffer-id key-alias-value))))))
(eaf-handle-app-key buffer-id key-desc eaf-imageviewer-keybinding)) ((equal buffer-app-name "terminal")
((equal buffer-app-name "camera") (let ((function-name-value (symbol-name (car (rassoc key-desc eaf-browser-keybinding)))))
(eaf-handle-app-key buffer-id key-desc eaf-camera-keybinding)) (when function-name-value
(t (eaf-call "execute_function" buffer-id function-name-value))))))
(eaf-call "send_key" buffer-id key-desc)))) ((and (or
((string-match "^[CMSs]-.*" key-desc) (eaf-identify-key-in-app key-command buffer-app-name)
(cond ((equal buffer-app-name "browser") ;; Just send event when user insert single character.
(let ((function-name-value (assoc key-desc eaf-browser-keybinding))) ;; Don't send event 'M' if user press Ctrl + M.
(if function-name-value (equal (symbol-name key-command) "self-insert-command")
(eaf-call "execute_function" buffer-id (cdr function-name-value)) (equal (symbol-name key-command) "completion-select-if-within-overlay"))
(let ((key-alias-value (assoc key-desc eaf-browser-key-alias))) (equal 1 (string-width (this-command-keys))))
(if key-alias-value (cond ((equal buffer-app-name "pdf-viewer")
(eaf-call "send_key" buffer-id (cdr key-alias-value))))))) (eaf-handle-app-key buffer-id key-desc eaf-pdfviewer-keybinding))
((equal buffer-app-name "terminal") ((equal buffer-app-name "video-player")
(let ((function-name-value (assoc key-desc eaf-terminal-keybinding))) (eaf-handle-app-key buffer-id key-desc eaf-videoplayer-keybinding))
(when function-name-value ((equal buffer-app-name "image-viewer")
(eaf-call "execute_function" buffer-id (cdr function-name-value)))) (eaf-handle-app-key buffer-id key-desc eaf-imageviewer-keybinding))
))) ((equal buffer-app-name "camera")
((or
(equal key-command "nil") (eaf-handle-app-key buffer-id key-desc eaf-camera-keybinding))
(equal key-desc "RET") (t
(equal key-desc "DEL") (eaf-call "send_key" buffer-id key-desc))))
(equal key-desc "TAB") ((or
(equal key-desc "SPC") (equal (symbol-name key-command) "nil")
(equal key-desc "<backtab>") (equal key-desc "RET")
(equal key-desc "<home>") (equal key-desc "DEL")
(equal key-desc "<end>") (equal key-desc "TAB")
(equal key-desc "<left>") (equal key-desc "SPC")
(equal key-desc "<right>") (equal key-desc "<backtab>")
(equal key-desc "<up>") (equal key-desc "<home>")
(equal key-desc "<down>") (equal key-desc "<end>")
(equal key-desc "<prior>") (equal key-desc "<left>")
(equal key-desc "<next>") (equal key-desc "<right>")
) (equal key-desc "<up>")
(eaf-call "send_key" buffer-id key-desc) (equal key-desc "<down>")
) (equal key-desc "<prior>")
(t (equal key-desc "<next>"))
(unless (or (eaf-call "send_key" buffer-id key-desc))
(equal key-command "keyboard-quit") (t
(equal key-command "kill-this-buffer") (unless (or
(equal key-command "eaf-open")) (equal (symbol-name key-command) "keyboard-quit")
(ignore-errors (call-interactively (key-binding key)))) (equal (symbol-name key-command) "kill-this-buffer")
))) (equal (symbol-name key-command) "eaf-open"))
(ignore-errors (call-interactively (key-binding key)))))))
;; Set `last-command-event' with nil, emacs won't notify me buffer is ready-only, ;; Set `last-command-event' with nil, emacs won't notify me buffer is ready-only,
;; because i insert nothing in buffer. ;; because i insert nothing in buffer.
(setq last-command-event nil)) (setq last-command-event nil))))
))
;; If something wrong in `eaf-monitor-key-event', emacs will remove `eaf-monitor-key-event' from `pre-command-hook' hook list. ;; If something wrong in `eaf-monitor-key-event', emacs will remove `eaf-monitor-key-event' from `pre-command-hook' hook list.
;; Then we add `eaf-monitor-key-event' in `pre-command-hook' list again, hahahaha. ;; Then we add `eaf-monitor-key-event' in `pre-command-hook' list again, hahahaha.
(run-with-timer (run-with-timer
@ -541,11 +583,12 @@ We need calcuate render allocation to make sure no black border around render co
(add-hook 'pre-command-hook #'eaf-monitor-key-event)))))) (add-hook 'pre-command-hook #'eaf-monitor-key-event))))))
(defun eaf-handle-app-key (buffer-id key-desc keybinding) (defun eaf-handle-app-key (buffer-id key-desc keybinding)
"Call function if match key in keybinding. "Call function on the Python side if matched key in the keybinding.
Otherwise call send_key message to Python side." Otherwise call send_key message to Python side."
(let ((function-name-value (assoc key-desc keybinding))) (let ((function-name-value (symbol-name (car (rassoc key-desc keybinding)))))
(if function-name-value (if function-name-value
(eaf-call "execute_function" buffer-id (cdr function-name-value)) (eaf-call "execute_function" buffer-id function-name-value)
(eaf-call "send_key" buffer-id key-desc)))) (eaf-call "send_key" buffer-id key-desc))))
(defun eaf-set (sym val) (defun eaf-set (sym val)
@ -561,6 +604,20 @@ For convenience, use the Lisp macro `eaf-setq' instead."
Use it as (eaf-setq var val)" Use it as (eaf-setq var val)"
`(eaf-set ',var ,val)) `(eaf-set ',var ,val))
(defun eaf-bind-key-symbol (sym val eaf-app-bindings)
"Similar to `bind-key', but store SYM with VAL in EAF-APP-BINDINGS list.
This is used to bind key to EAF Python applications.
For convenience, use the Lisp macro `eaf-bind-key' instead."
(map-put eaf-app-bindings sym val))
(defmacro eaf-bind-key (var val eaf-app-bindings)
"Similar to `bind-key', but store SYM with VAL in EAF-APP-BINDINGS list.
This is used to bind key to EAF Python applications.
Use it as (eaf-bind-key var val eaf-app-bindings)"
`(eaf-bind-key-symbol ',var ,val ,eaf-app-bindings))
(defun eaf-focus-buffer (msg) (defun eaf-focus-buffer (msg)
(let* ((coordinate-list (split-string msg ",")) (let* ((coordinate-list (split-string msg ","))
(mouse-press-x (string-to-number (nth 0 coordinate-list))) (mouse-press-x (string-to-number (nth 0 coordinate-list)))
@ -582,9 +639,7 @@ Use it as (eaf-setq var val)"
(> mouse-press-y y) (> mouse-press-y y)
(< mouse-press-y (+ y h))) (< mouse-press-y (+ y h)))
(select-window window) (select-window window)
(throw 'find-window t) (throw 'find-window t))))))))))
)
))))))))
(dbus-register-signal (dbus-register-signal
:session "com.lazycat.eaf" "/com/lazycat/eaf" :session "com.lazycat.eaf" "/com/lazycat/eaf"
@ -685,6 +740,7 @@ Use it as (eaf-setq var val)"
'eaf-input-message) 'eaf-input-message)
(defun eaf-send-var-to-python () (defun eaf-send-var-to-python ()
"Send variables defined in `eaf-var-list' to the Python side."
(message "Sending variables to Python side...") (message "Sending variables to Python side...")
(cl-loop for (sym . val) in eaf-var-list (cl-loop for (sym . val) in eaf-var-list
do (eaf-call "store_emacs_var" (symbol-name sym) val))) do (eaf-call "store_emacs_var" (symbol-name sym) val)))
@ -701,7 +757,7 @@ Use it as (eaf-setq var val)"
(add-hook 'after-save-hook #'eaf-monitor-buffer-save) (add-hook 'after-save-hook #'eaf-monitor-buffer-save)
(defun eaf-open-internal (url app-name arguments) (defun eaf-open-internal (url app-name arguments)
(let* ((buffer (eaf-create-buffer url)) (let* ((buffer (eaf-create-buffer url app-name))
buffer-result) buffer-result)
(with-current-buffer buffer (with-current-buffer buffer
(setq buffer-result (eaf-call "new_buffer" buffer-id url app-name arguments))) (setq buffer-result (eaf-call "new_buffer" buffer-id url app-name arguments)))
@ -718,8 +774,7 @@ Use it as (eaf-setq var val)"
;; Kill buffer and show error message from python server. ;; Kill buffer and show error message from python server.
(kill-buffer buffer) (kill-buffer buffer)
(switch-to-buffer eaf-name) (switch-to-buffer eaf-name)
(message buffer-result)) (message buffer-result))))
))
(defun eaf-open-browser (url &optional arguments) (defun eaf-open-browser (url &optional arguments)
"Open EAF browser application given a URL and ARGUMENTS." "Open EAF browser application given a URL and ARGUMENTS."
@ -845,8 +900,7 @@ When called interactively, URL accepts a file that can be opened by EAF."
(input-string (string-trim (read-string (format "EAF Airshare - Info (%s): " current-symbol))))) (input-string (string-trim (read-string (format "EAF Airshare - Info (%s): " current-symbol)))))
(when (string-empty-p input-string) (when (string-empty-p input-string)
(setq input-string current-symbol)) (setq input-string current-symbol))
(eaf-open input-string "airshare") (eaf-open input-string "airshare")))
))
(defun eaf-file-sender-qrcode (file) (defun eaf-file-sender-qrcode (file)
"Open EAF File Sender application. "Open EAF File Sender application.

Loading…
Cancel
Save