emacs-emojify

fork of https://github.com/iqbalansari/emacs-emojify
Log | Files | Refs | LICENSE

commit 8132634a5f766e88971969f995fe13d30cc4da74
parent 7319df22d2ab9665716529ee811dc1d3c8e768e9
Author: Iqbal Ansari <iqbalansari02@yahoo.com>
Date:   Sun, 29 Nov 2015 14:07:41 +0530

Add missing docstrings, minor refactoring

Diffstat:
Memojify.el | 183++++++++++++++++++++++++++++++++++++++++++++++++++++---------------------------
1 file changed, 121 insertions(+), 62 deletions(-)

diff --git a/emojify.el b/emojify.el @@ -98,6 +98,7 @@ Set `emojify-debug-mode' to non-nil to instruct emojify to not silence any errors during operation.") (defmacro emojify-execute-ignoring-errors-unless-debug (&rest forms) + "Execute FORMS ignoring errors unless `emojify-debug-mode' is non-nil." (declare (debug t) (indent 0)) `(if emojify-debug-mode (progn @@ -120,10 +121,10 @@ FORMAT-STRING and ARGS are same as the arguments to `message'." (defun emojify--get-relevant-region () "Try getting region in buffer that completely covers the current window. -This is used instead of directly using `window-start' and `window-end', since they -return the values corresponding buffer in currently selected window, which is -incorrect if the buffer where there are called is not actually the buffer visible -in the selected window." +This is used instead of directly using `window-start' and `window-end', since +they return the values corresponding buffer in currently selected window, which +is incorrect if the buffer where there are called is not actually the buffer +visible in the selected window." (let* ((window-size (- (window-end) (window-start))) (start (max (- (point) window-size) (point-min))) (end (min (+ (point) window-size) (point-max)))) @@ -508,9 +509,6 @@ To understand WINDOW, STRING and POS see the function documentation for ;; Core functions and macros -(defvar emojify-region-beg nil) -(defvar emojify-region-end nil) - (defvar emojify-emoji-keymap (let ((map (make-sparse-keymap))) (define-key map [remap delete-char] #'emojify-delete-emoji-forward) (define-key map [remap delete-forward-char] #'emojify-delete-emoji-forward) @@ -530,30 +528,26 @@ mark the start and end of region containing the text." (< new-point match-beginning))) (emojify-redisplay-emojis-in-region match-beginning match-end)))) -(defun emojify--find-key-binding-ignoring-emojify-keymap (key) - "Find the binding for given KEY ignoring the text properties at point. - -This is needed since `key-binding' looks up in keymap text property as well -which is not what we want when falling back in `emojify-delete-emoji'" - (let* ((key-binding (or (minor-mode-key-binding key) - (local-key-binding key) - (global-key-binding key)))) - (when key-binding - (or (command-remapping key-binding - nil - (seq-filter (lambda (keymap) - (not (equal keymap emojify-emoji-keymap))) - (current-active-maps))) - key-binding)))) - (defun emojify--get-point-col-and-line (point) "Return a cons of containing the column number and line at POINT." (save-excursion (goto-char point) (cons (current-column) (line-number-at-pos)))) +;; These should be bound dynamically by functions calling +;; `emojify--inside-rectangle-selection-p' and +;; `emojify--inside-non-rectangle-selection-p' to region-beginning and +;; region-end respectively. This is needed mark the original region which is +;; impossible to get after point moves during processing. +(defvar emojify-region-beg nil) +(defvar emojify-region-end nil) + (defun emojify--inside-rectangle-selection-p (beg end) - "Check if region marked by BEG and END is inside a rectangular selection." + "Check if region marked by BEG and END is inside a rectangular selection. + +In addition to explicit the parameters BEG and END, calling functions should +also dynamically bind `emojify-region-beg' and `emojify-region-end' to beginning +and end of region respectively." (when (and emojify-region-beg (bound-and-true-p rectangle-mark-mode)) (let ((rect-beg (emojify--get-point-col-and-line emojify-region-beg)) @@ -566,7 +560,11 @@ which is not what we want when falling back in `emojify-delete-emoji'" (<= (cdr rect-beg) (cdr emoji-end-pos) (cdr rect-end))))))) (defun emojify--inside-non-rectangle-selection-p (beg end) - "Check if region marked by BEG and END is inside a regular selection." + "Check if region marked by BEG and END is inside a regular selection. + +In addition to the explicit parameters BEG and END, calling functions should +also dynamically bind `emojify-region-beg' and `emojify-region-end' to beginning +and end of region respectively." (when (and emojify-region-beg (region-active-p) (not (bound-and-true-p rectangle-mark-mode))) @@ -574,14 +572,16 @@ which is not what we want when falling back in `emojify-delete-emoji'" (<= emojify-region-beg end emojify-region-end)))) (defun emojify--get-image-background (beg end) - "Get the color to be used as background for emoji in region" + "Get the color to be used as background for emoji between BEG and END." (when (or (emojify--inside-non-rectangle-selection-p beg end) (emojify--inside-rectangle-selection-p beg end)) (face-background 'region))) (defun emojify--get-image-display (data beg end) - "Get the display text property to display the emoji specified in DATA as an image -in region delimited by BEG and END." + "Get the display text property to display the emoji as an image. + +DATA holds the emoji data, BEG and END delimit the region where emoji will +be displayed." (let* ((image-file (expand-file-name (ht-get data "image") emojify-image-dir)) (image-type (intern (upcase (file-name-extension image-file))))) @@ -601,8 +601,10 @@ in region delimited by BEG and END." :height (emojify-default-font-height))))) (defun emojify--get-unicode-display (data _beg _end) - "Get the display text property to display the emoji specified in DATA as unicode characters. -_BEG and _END are ignored." + "Get the display text property to display the emoji as an unicode character. + +DATA holds the emoji data, _BEG and _END delimit the region where emoji will +be displayed." (let* ((unicode (ht-get data "unicode")) (characters (when unicode (string-to-vector unicode)))) @@ -610,21 +612,26 @@ _BEG and _END are ignored." unicode))) (defun emojify--get-ascii-display (data _beg _end) - "Get the display text property to display the emoji specified in DATA as ascii characters. -_BEG and _END are ignored." + "Get the display text property to display the emoji as an ascii characters. + +DATA holds the emoji data, _BEG and _END delimit the region where emoji will +be displayed." (ht-get data "ascii")) -(defun emojify--get-text-display-props (name emoji-start emoji-end) - "The the display property for an emoji named NAME." - (let* ((emoji-data (ht-get emojify-emojis name)) +(defun emojify--get-text-display-props (text beg end) + "Get the display property for an emoji. + +TEXT is the text to be displayed as emoji, BEG and END delimit the +region containing the emoji." + (let* ((emoji-data (ht-get emojify-emojis text)) (display (when emoji-data (funcall (pcase emojify-display-style (`image #'emojify--get-image-display) (`unicode #'emojify--get-unicode-display) (`ascii #'emojify--get-ascii-display)) emoji-data - emoji-start - emoji-end)))) + beg + end)))) (when display (list 'display display)))) @@ -762,6 +769,22 @@ lines ensures that all the possibly affected emojis are redisplayed." ;; Electric delete functionality +(defun emojify--find-key-binding-ignoring-emojify-keymap (key) + "Find the binding for given KEY ignoring the text properties at point. + +This is needed since `key-binding' looks up in keymap text property as well +which is not what we want when falling back in `emojify-delete-emoji'" + (let* ((key-binding (or (minor-mode-key-binding key) + (local-key-binding key) + (global-key-binding key)))) + (when key-binding + (or (command-remapping key-binding + nil + (seq-filter (lambda (keymap) + (not (equal keymap emojify-emoji-keymap))) + (current-active-maps))) + key-binding)))) + (defun emojify-delete-emoji (point) "Delete emoji at POINT." (if (get-text-property point 'emojified) @@ -780,6 +803,8 @@ lines ensures that all the possibly affected emojis are redisplayed." (emojify-delete-emoji (1- (point)))) ;; Integrate with delete-selection-mode +;; Basically instruct delete-selection mode to override our commands +;; if the region is active. (put 'emojify-delete-emoji-forward 'delete-selection 'supersede) (put 'emojify-delete-emoji-backward 'delete-selection 'supersede) @@ -787,7 +812,8 @@ lines ensures that all the possibly affected emojis are redisplayed." ;; Updating background color on selection -(defun emojify-update-emojis-background-in-region (&optional beg end) +(defun emojify--update-emojis-background-in-region (&optional beg end) + "Update the background color for emojis between BEG and END." (when (equal emojify-display-style 'image) (emojify-with-saved-buffer-state (let ((emojify-region-beg (when (region-active-p) (region-beginning))) @@ -802,32 +828,65 @@ lines ensures that all the possibly affected emojis are redisplayed." emoji-end)) (setq beg (1+ emoji-end)))))))) -(defun emojify-record-window-scroll (window display-start) - (let* ((window-start display-start) - (window-end (min (+ window-start (* (window-text-height) - (window-text-width))) +(defun emojify--update-emojis-background-in-region-starting-at (point) + "Update background color for emojis in buffer starting at POINT. + +This updates the emojis in the region starting from POINT, the end of region is +determined by product of `frame-height' and `frame-width' which roughly +corresponds to the visible area. POINT usually corresponds to the starting +position of the window, see +`emojify-update-visible-emojis-background-after-command' and +`emojify-update-visible-emojis-background-after-window-scroll' + +NOTE: `window-text-height' and `window-text-width' would have been more +appropriate here however they were not defined in Emacs v24.3 and below." + (let* ((region-beginning point) + (region-end (min (+ region-beginning (* (frame-height) + (frame-width))) (point-max)))) - (emojify-message "Updating emoji backgrounds in %d %d " window-start window-end) - (emojify-update-emojis-background-in-region window-start window-end))) + (emojify--update-emojis-background-in-region region-beginning + region-end))) (defun emojify-update-visible-emojis-background-after-command () - ;; The function window-end is not reliable in post-command hook - (let* ((window-start (window-start)) - (window-end (min (+ window-start (* (window-text-height) - (window-text-width))) - (point-max)))) - (emojify-message "Updating emoji backgrounds in %d %d" window-start window-end) - (emojify-update-emojis-background-in-region window-start window-end))) + "Function added to `post-command-hook' when region is active. + +This function updates the backgrounds of the emojis in the region changed after +the command. -(defun emojify-setup-emoji-update-on-selection-change () +Ideally this would have been good enough to update emoji backgounds after region +changes, unfortunately this does not work well with commands that scroll the +window specifically `window-start' and `window-end' (sometimes only `window-end') +report incorrect values. + +To work around this +`emojify-update-visible-emojis-background-after-window-scroll' is added to +`window-scroll-functions' to update emojis on window scroll." + (emojify--update-emojis-background-in-region-starting-at (window-start))) + +(defun emojify-update-visible-emojis-background-after-window-scroll (_window display-start) + "Function added to `window-scroll-functions' when region is active. + +This function updates the backgrounds of the emojis in the newly displayed area +of the window. DISPLAY-START corresponds to the new start of the window." + (emojify--update-emojis-background-in-region-starting-at display-start)) + +(defun emojify-update-emojis-on-mark-activation () + "Executed in `activate-mark-hook'. + +Updates emoji backgrounds on activation of mark as well setup update of emojis +when region changes." (emojify-update-visible-emojis-background-after-command) - (add-hook 'post-command-hook #'emojify-update-visible-emojis-background-after-command) - (add-hook 'window-scroll-functions #'emojify-record-window-scroll)) + (add-hook 'post-command-hook #'emojify-update-visible-emojis-background-after-command t t) + (add-hook 'window-scroll-functions #'emojify-update-visible-emojis-background-after-window-scroll t t)) + +(defun emojify-update-emojis-on-mark-deactivation () + "Executed in `deactivate-mark-hook'. -(defun emojify-teardown-emoji-update-on-selection-change () - (emojify-update-emojis-background-in-region (point-min) (point-max)) - (remove-hook 'post-command-hook #'emojify-update-visible-emojis-background-after-command) - (remove-hook 'window-scroll-functions #'emojify-record-window-scroll)) +Updates emoji backgrounds of emojis in buffer on deactivation of mark as well +disables update of emojis when region changes." + (emojify--update-emojis-background-in-region (point-min) (point-max)) + (remove-hook 'post-command-hook #'emojify-update-visible-emojis-background-after-command t) + (remove-hook 'window-scroll-functions #'emojify-update-visible-emojis-background-after-window-scroll t)) @@ -844,8 +903,8 @@ lines ensures that all the possibly affected emojis are redisplayed." (add-hook 'jit-lock-after-change-extend-region-functions #'emojify-after-change-extend-region-function t t) ;; Update emoji backgrounds when region is selected - (add-hook 'activate-mark-hook #'emojify-setup-emoji-update-on-selection-change t t) - (add-hook 'deactivate-mark-hook #'emojify-teardown-emoji-update-on-selection-change t t) + (add-hook 'activate-mark-hook #'emojify-update-emojis-on-mark-activation t t) + (add-hook 'deactivate-mark-hook #'emojify-update-emojis-on-mark-deactivation t t) ;; Redisplay visible emojis when emoji style changes (add-hook 'emojify-emoji-style-change-hooks #'emojify-redisplay-emojis-in-region))) @@ -862,8 +921,8 @@ lines ensures that all the possibly affected emojis are redisplayed." (remove-hook 'jit-lock-after-change-extend-region-functions #'emojify-after-change-extend-region-function t) ;; Update emoji backgrounds when region is selected - (remove-hook 'activate-mark-hook #'emojify-setup-emoji-update-on-selection-change t) - (remove-hook 'deactivate-mark-hook #'emojify-teardown-emoji-update-on-selection-change t) + (remove-hook 'activate-mark-hook #'emojify-update-emojis-on-mark-activation t) + (remove-hook 'deactivate-mark-hook #'emojify-update-emojis-on-mark-deactivation t) ;; Remove style change hooks (remove-hook 'emojify-emoji-style-change-hooks #'emojify-redisplay-emojis-in-region))