~zge/kaomoji

ref: 5b5611cf3f3bdb2f91af7cd7e80a79a950f50b9f kaomoji/insert-kaomoji.el -rw-r--r-- 5.1 KiB View raw
5b5611cfPhilip K added link to public inbox 1 year, 2 days ago
                                                                                
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
;;; insert-kaomoji.el --- Easily insert kaomojis -*- lexical-binding: t -*-

;; Author: Philip K. <philip@warpmail.net>
;; Version: 0.1.0
;; Package-Requires: ((emacs "24.4"))
;; Keywords: wp
;; URL: https://git.sr.ht/~zge/kaomoji.el

;; This file is NOT part of Emacs.
;;
;; This file is in the public domain, to the extent possible under law,
;; published under the CC0 1.0 Universal license.
;;
;; For a full copy of the CC0 license see
;; https://creativecommons.org/publicdomain/zero/1.0/legalcode

;;; Commentary:
;; 
;; Kaomojis are eastern/Japanese emoticons, which are usually displayed
;; horizontally, as opposed to the western vertical variants (":^)",
;; ";D", "XP", ...).
;;
;; To achieve this they make much more use of more obscure and often
;; harder to type unicode symbols, which often makes it more difficult
;; to type, or impossible if you don't know the symbols names/numbers.
;;
;; This package tries to make it easier to use kaomojis, by using
;; `completing-read' and different categories. The main user functions
;; are therefore `insert-kaomoji' to insert a kaomoji at point, and
;; `insert-kaomoji-into-kill-ring' to push a kaomoji onto the kill ring.
;;
;; The emoticons aren't stored in this file, but (usually) in the
;; KAOMOJIS file that should be in the same directory as this source
;; file. This file is parsed by `insert-kaomoji--parse-buffer' and then
;; stored in `insert-kaomoji-alist'.
;;
;; The kaomojis in KAOMOJIS have been selected and collected from these
;; sites:
;; - https://wikileaks.org/ciav7p1/cms/page_17760284.html
;; - http://kaomoji.ru/en/
;; - https://en.wikipedia.org/wiki/List_of_emoticons


(require 'ring)

;;; Code:

(defvar insert-kaomoji--last-used (make-ring 32)
  "Ring of last kaomojis inserted.")
(defvar insert-kaomoji--last-category nil
  "Symbol of last category used to insert a kaomoji.")



(defun insert-kaomoji--parse-buffer (buf)
  "Parse a buffer BUF creating a alist.

Categories are delimited by an group separator (ASCII 35), which
are in turn split into tags and kaomojis. These two are kept apart
by a record separator (ASCII 36). Both tags and kaomojis split
their unit components by unit separators (ASCII 37)."
  (with-current-buffer buf
    (let (records end)
      (goto-char (point-min))
      (while (save-excursion (setq end (search-forward "" nil t)))
        (save-restriction
          (narrow-to-region (point) end)
          (let* ((names (split-string (buffer-substring
                                       (point-min)
                                       (1- (search-forward "")))
                                      ""))
                 (kaomojis (split-string (buffer-substring
                                         (point) (point-max)) "")))
            (dolist (name names)
              (push (cons (string-trim-left name) kaomojis)
                    records))))
        (goto-char end))
      records)))

(defun insert-kaomoji-parse-file (filename)
  "Parse FILENAME for a list of Kaomoji categories."
  (with-temp-buffer
    (insert-file-contents filename)
    (insert-kaomoji--parse-buffer (current-buffer))))

(defconst insert-kaomoji-alist
  (let* ((dir (if load-file-name
                  (file-name-directory load-file-name)
                default-directory))
         (file (expand-file-name "KAOMOJIS" dir)))
    (insert-kaomoji-parse-file file))
  "Alist of various kaomojis.")



(defun insert-kaomoji--select-kaomoji (category)
  "General function to interactively select a kaomoji.

Will first query a category from `insert-kaomoji-alist', then a
specific kaomoji within the category. If CATEGORY is non-nil,
don't query the user and just use that category instead."
  (let* ((moods (mapcar #'car insert-kaomoji-alist))
         (category (or category (completing-read "Category: " moods nil t)))
         (list (cdr (assoc category insert-kaomoji-alist)))
         (kaomoji (completing-read (format "Kaomoji (%s): " category) list)))
    (setf insert-kaomoji--last-category category)
    (ring-insert insert-kaomoji--last-used kaomoji)
    kaomoji))

(defun insert-kaomoji--choose-kaomoji (arg)
  "Helper function to choose a kaomoji.

No prefix argument opens a category then kaomoji menu, a single
prefix ARG argument re-opens the last category, and a double prefix
argument lists the last used kaomojis."
  (cond ((and (>= arg 16) (< 0 (ring-size insert-kaomoji--last-used)))
         (completing-read "Last inserted Kaomojis: "
                          (ring-elements insert-kaomoji--last-used)))
        ((>= arg 4) (insert-kaomoji--select-kaomoji insert-kaomoji--last-category))
        (t (insert-kaomoji--select-kaomoji nil))))



;;;###autoload
(defun insert-kaomoji-into-kill-ring (arg)
  "Insert a kaomoji directly into `kill-ring'.

See `insert-kaomoji--choose-kaomoji' in regards to how the prefix argument
ARG is handled."
  (interactive "p")
  (kill-new (insert-kaomoji--choose-kaomoji arg)))

;;;###autoload
(defun insert-kaomoji (arg)
  "Insert a kaomoji directly into the current buffer.

See `insert-kaomoji--choose-kaomoji' in regards to how the prefix argument ARG
is handled."
  (interactive "p")
  (insert (insert-kaomoji--choose-kaomoji arg)))

(provide 'insert-kaomoji)

;;; insert-kaomoji.el ends here