commit a905cb1f557aa9c944668c1dd15fd8ba4766314f
parent 553303dda9e1b68b03cf612efceef7fc88fe6e0b
Author: Iqbal Ansari <iqbalansari02@yahoo.com>
Date: Sun, 22 Nov 2015 21:43:52 +0530
Merge branch 'develop'
Fixes #5
Diffstat:
3 files changed, 131 insertions(+), 2 deletions(-)
diff --git a/.travis.yml b/.travis.yml
@@ -36,7 +36,7 @@ install:
- cask install
script:
- - cask exec ert-runner --reporter ert
+ - cask exec ert-runner
notifications:
email:
diff --git a/emojify.el b/emojify.el
@@ -479,6 +479,14 @@ To understand WINDOW, STRING and POS see the function documentation for
;; Core functions and macros
+(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)
+ (define-key map [remap backward-delete-char] #'emojify-delete-emoji-backward)
+ (define-key map [remap delete-backward-char] #'emojify-delete-emoji-backward)
+ (define-key map [remap backward-delete-char-untabify] #'emojify-delete-emoji-backward)
+ map))
+
(defun emojify--get-point-left-function (buffer match-beginning match-end)
"Create a function that can be executed in point-left hook for emoji text.
@@ -490,6 +498,25 @@ mark the start and end of region containing the text."
(< new-point match-beginning)))
(emojify-redisplay-emojis 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* ((minor-mode-binding (minor-mode-key-binding key))
+ (local-binding (local-key-binding key))
+ (global-binding (global-key-binding key))
+ (key-binding (or minor-mode-binding
+ local-binding
+ global-binding)))
+ (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-image-display (data)
"Get the display text property to display the emoji specified in DATA as an image."
(let* ((image-file (expand-file-name (ht-get data "image")
@@ -593,6 +620,7 @@ TODO: Skip emojifying if region is already emojified."
'emojify-text match
'emojify-start match-beginning
'emojify-end match-end
+ 'keymap emojify-emoji-keymap
'point-entered #'emojify-point-entered-function
'help-echo #'emojify-help-function)))))))))))
@@ -628,10 +656,33 @@ BEG and END are the beginning and end of the region respectively"
'emojify-text t
'emojify-start t
'emojify-end t
- 'help-echo t))))
+ 'keymap t
+ 'help-echo t
+ 'rear-nonsticky t))))
;; Setup the next iteration
(setq beg emoji-end)))))
+(defun emojify-delete-emoji (point)
+ "Delete emoji at POINT."
+ (if (get-text-property point 'emojified)
+ (delete-region (get-text-property point 'emojify-start)
+ (get-text-property point 'emojify-end))
+ (call-interactively (emojify--find-key-binding-ignoring-emojify-keymap (this-command-keys)))))
+
+(defun emojify-delete-emoji-forward ()
+ "Delete emoji after point."
+ (interactive)
+ (emojify-delete-emoji (point)))
+
+(defun emojify-delete-emoji-backward ()
+ "Delete emoji before point."
+ (interactive)
+ (emojify-delete-emoji (1- (point))))
+
+;; Integrate with delete-selection-mode
+(put 'emojify-delete-emoji-forward 'delete-selection 'supersede)
+(put 'emojify-delete-emoji-backward 'delete-selection 'supersede)
+
(defun emojify-redisplay-emojis (&optional beg end)
"Redisplay emojis in region between BEG and END.
diff --git a/test/emojify-test.el b/test/emojify-test.el
@@ -33,6 +33,23 @@
(should (equal (get-text-property (point) 'emojify-end) (point-max)))
(should (equal (get-text-property (point) 'emojify-text) ":smile:"))))
+(ert-deftest emojify-tests-simple-unicode-emoji-test ()
+ :tags '(unicode simple)
+ (emojify-tests-with-emojified-static-buffer "😉"
+ (emojify-tests-should-be-emojified (point-min))
+ (should (equal (get-text-property (point) 'emojify-buffer) (current-buffer)))
+ (should (equal (get-text-property (point-min) 'emojify-start) (point-min)))
+ (should (equal (get-text-property (point) 'emojify-end) (point-max)))
+ (should (equal (get-text-property (point) 'emojify-text) "😉"))))
+
+(ert-deftest emojify-tests-mixed-emoji-test ()
+ :tags '(core mixed)
+ (emojify-tests-with-emojified-static-buffer "😉\n:D\nD:\n:smile:"
+ (emojify-tests-should-be-emojified (point-min))
+ (emojify-tests-should-be-emojified (line-beginning-position 2))
+ (emojify-tests-should-not-be-emojified (line-beginning-position 3))
+ (emojify-tests-should-be-emojified (line-beginning-position 4))))
+
(ert-deftest emojify-tests-emojifying-on-comment-uncomment ()
:tags '(core after-change)
(emojify-tests-with-emojified-buffer ":smile:\n:)"
@@ -213,6 +230,7 @@
(ert-deftest emojify-tests-multiple-emojis-in-sequence ()
"See Github issue #6"
+ :tags '(core contextual)
(emojify-tests-with-emojified-static-buffer ":100::smile:
:100:a:smile:
🎆😃
@@ -340,6 +358,66 @@
(emojify-tests-should-be-emojified first-emoji-pos)
(emojify-tests-should-be-emojified second-emoji-pos)))))
+(ert-deftest emojify-tests-electric-delete ()
+ :tags '(electric-delete)
+ (emojify-tests-with-emojified-buffer "Unicode emoji 😉\nGithub emoji :wink:\nAscii emoji ;)"
+ (goto-char (line-end-position))
+ (let ((final-line-end (get-text-property (1- (point)) 'emojify-start)))
+ (execute-kbd-macro [backspace])
+ (emojify-tests-should-not-be-emojified (line-end-position))
+ (should (equal (line-end-position) final-line-end))))
+
+ (emojify-tests-with-emojified-buffer "Unicode emoji 😉\nGithub emoji :wink:\nAscii emoji ;)"
+ (goto-char (line-end-position 2))
+ (let ((final-line-end (get-text-property (1- (point)) 'emojify-start)))
+ (execute-kbd-macro [backspace])
+ (emojify-tests-should-not-be-emojified (line-end-position))
+ (should (equal (line-end-position) final-line-end))))
+
+ (emojify-tests-with-emojified-buffer "Unicode emoji 😉\nGithub emoji :wink:\nAscii emoji ;)"
+ (goto-char (line-end-position 3))
+ (let ((final-line-end (get-text-property (1- (point)) 'emojify-start)))
+ (execute-kbd-macro [backspace])
+ (emojify-tests-should-not-be-emojified (line-end-position))
+ (should (equal (line-end-position) final-line-end))))
+
+ (emojify-tests-with-emojified-buffer "😉:wink: ;)"
+ (dotimes (_ 4)
+ (execute-kbd-macro (kbd "C-d")))
+ (should (equal (point-min) (point-max))))
+
+ (emojify-tests-with-emojified-buffer "😉:wink: ;)"
+ (goto-char (point-max))
+ (dotimes (_ 4)
+ (execute-kbd-macro [backspace]))
+ (should (equal (point-min) (point-max))))
+
+ (emojify-tests-with-emojified-buffer "😉 :smile:"
+ (goto-char (1+ (point-min)))
+ (dotimes (_ 3)
+ (execute-kbd-macro (kbd "C-d")))
+ (should (equal (1+ (point-min)) (point-max))))
+
+ (emojify-tests-with-emojified-buffer "😉:wink: ;)"
+ "Integration with delsel mode"
+ (with-mock
+ (stub message => nil)
+ (delete-selection-mode +1)
+ (set-mark-command nil)
+ (activate-mark)
+ (goto-char (point-max))
+ (exchange-point-and-mark)
+ (let ((this-command 'emojify-delete-emoji-forward))
+ (delete-selection-pre-hook))
+ (should (equal (point-min) (point-max))))))
+
+(ert-deftest emojify-tests-no-byte-compilation-errors ()
+ :tags '(byte-compilation)
+ (with-mock
+ (stub message => nil)
+ (stub byte-compile-dest-file => "/tmp/emojify.elc")
+ (should (byte-compile-file (locate-library "emojify.el")))))
+
;; So that tests can be run simply by doing `eval-buffer'
(unless noninteractive
(ert "^emojify-"))