-
Notifications
You must be signed in to change notification settings - Fork 38
/
gt-text-utility.el
124 lines (99 loc) · 5.18 KB
/
gt-text-utility.el
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
;;; gt-text-utility.el --- Text utilities base on the translator -*- lexical-binding: t -*-
;; Copyright (C) 2024 lorniu <[email protected]>
;; Author: lorniu <[email protected]>
;; SPDX-License-Identifier: GPL-3.0-or-later
;; 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/>.
;; This file is NOT part of GNU Emacs.
;;; Commentary:
;; Integrate md5, sha1, base64, qrcode and others into this translation framework.
;;
;; Shows that this framework is more than just translation purposes.
;;
;; Use like this:
;;
;; \\=(gt-start (gt-text-utility :render (gt-buffer-render)))
;;
;; To avoid be prompted, specify the targets like this:
;;
;; \\=(gt-start (gt-text-utility :taker (gt-taker :langs '(md5 sha1)) :render (gt-insert-render)))
;;; Code:
(require 'gt-extension)
(defvar gt-text-utilities `(base64 rot13 qrcode speak ,@(secure-hash-algorithms))
"List of available targets for `gt-text-utility-engine'.")
(defclass gt-text-utility (gt-translator) ())
(defclass gt-text-utility-engine (gt-engine)
((tag :initform 'Text-Utility)
(cache :initform nil)
(delimiter :initform nil)))
(cl-defmethod gt-reset :after ((translator gt-text-utility) &rest _)
(with-slots (_engines) translator
(unless _engines (setf _engines (gt-text-utility-engine)))
(setf _engines (ensure-list _engines))
(unless (and (not (cdr _engines)) (cl-typep (car _engines) 'gt-text-utility-engine))
(user-error "%s should use only one gt-text-utility-engine as engine" (gt-desc translator)))))
(cl-defmethod gt-target ((taker gt-taker) (_ gt-text-utility) &rest _)
(let ((tgts (if (slot-boundp taker 'langs)
(ensure-list (oref taker langs))
(mapcar #'intern
(completing-read-multiple
"Utilities (can choose multiple): " gt-text-utilities
nil t nil 'gt-text-utility-hist)))))
(unless tgts (user-error "No targets found"))
(cons nil (cl-delete-duplicates tgts))))
(cl-defmethod gt-translate ((_ gt-text-utility-engine) task _)
"Translate and render the result directly, skip parse and other steps."
(with-slots (text tgt res translator) task
(setf res (mapcar (lambda (c) (gt-text-util tgt (encode-coding-string c 'utf-8))) text))
(gt-update-state translator)
(gt-output (oref translator render) translator)))
(cl-defmethod gt-keybinds ((_buffer gt-buffer-render) (_ gt-text-utility))
(gt-buffer-render-key ("t" "Cycle Next") #'gt-buffer-render--cycle-next)
(gt-buffer-render-key ("g" "Refresh") #'gt-buffer-render--refresh)
(gt-buffer-render-key ("q" "Quit") #'kill-buffer-and-window)
(gt-buffer-render-key ("C-x C-q") #'gt-buffer-render--toggle-readonly)
(gt-buffer-render-key ("?") #'gt-buffer-render--show-tips))
(cl-defgeneric gt-text-util (target text)
"Dispatch to different TEXT utility methods for different TARGET."
(:method ((_ (eql 'base64)) text) (base64-encode-string text t))
(:method ((_ (eql 'rot13)) text) (rot13 text))
(:method ((_ (eql 'qrcode)) text) (gt-qrcode text))
(:method ((_ (eql 'speak)) text) (gt-text-speak-button text))
(if (member target (secure-hash-algorithms))
(secure-hash target text)
(user-error "Unimplemented")))
(defun gt-text-speak-button (str)
(propertize str
'display " click to speak... "
'pointer 'hand
'keymap (gt-simple-keymap [mouse-1] (lambda () (interactive) (gt-speak 'interact str t)))
'face '(:box t)
'mouse-face '(:reverse-video t :inherit font-lock-warning-face)))
(declare-function qrencode "ext:qrencode.el" t t)
;;;###autoload
(defun gt-qrcode (str)
"Genrate QR Code for STR."
(interactive (list (read-string "String to generate QRCode: ")))
(let ((code (if (executable-find "qrencode")
(with-temp-buffer
(let ((coding-system-for-read 'raw-text))
(set-buffer-multibyte nil)
(insert str)
(shell-command-on-region (point-min) (point-max) "qrencode -t PNG -o -" (current-buffer))
(if (string-match-p "PNG" (buffer-substring 1 (min (point-max) 8)))
(propertize " " 'display `(image :type png :data ,(buffer-string) :width 200))
(user-error (buffer-string)))))
(if (require 'qrencode nil t)
(qrencode str)
(user-error "Install program `qrencode' or package `qrencode.el' first to generate QR Code")))))
(if (called-interactively-p 'any) (message "%s" code) code)))
(provide 'gt-text-utility)
;;; gt-text-utility.el ends here