Files
my-lisp/my-replace-zen-to-ascii.el
T

167 lines
6.3 KiB
EmacsLisp
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
;;; my-replace-zen-to-ascii.el --- Convert fullwidth/superscript/subscript chars to ASCII -*- lexical-binding: t; -*-
;; This library converts selected fullwidth ASCII-like characters,
;; Unicode superscript/subscript digits, and common typographic symbols
;; into plain ASCII characters.
;;
;; Main commands:
;;
;; M-x replace-zen-to-ascii-region
;; M-x replace-zen-to-ascii-buffer
;; M-x replace-zen-to-ascii-region-copy
;; M-x replace-zen-to-ascii-buffer-copy
;;
;; The original command name `replace-zen-to-ascii-region' is kept
;; for compatibility with existing init.el settings.
(require 'subr-x)
(defgroup my-replace-zen-to-ascii nil
"Convert selected fullwidth and Unicode compatibility characters to ASCII."
:group 'editing
:prefix "my-replace-zen-to-ascii-")
(defcustom my-replace-zen-to-ascii-convert-scientific-symbols nil
"If non-nil, also convert selected scientific symbols to ASCII.
For example, μ/µ -> u, Å/Å -> A, × -> x, ° -> deg.
This is disabled by default because these symbols may be meaningful
in manuscripts."
:type 'boolean
:group 'my-replace-zen-to-ascii)
(defconst my-replace-zen-to-ascii--basic-table
'((" " . " ")
;; Fullwidth digits
("" . "0") ("" . "1") ("" . "2") ("" . "3") ("" . "4")
("" . "5") ("" . "6") ("" . "7") ("" . "8") ("" . "9")
;; Fullwidth uppercase letters
("" . "A") ("" . "B") ("" . "C") ("" . "D") ("" . "E")
("" . "F") ("" . "G") ("" . "H") ("" . "I") ("" . "J")
("" . "K") ("" . "L") ("" . "M") ("" . "N") ("" . "O")
("" . "P") ("" . "Q") ("" . "R") ("" . "S") ("" . "T")
("" . "U") ("" . "V") ("" . "W") ("" . "X") ("" . "Y")
("" . "Z")
;; Fullwidth lowercase letters
("" . "a") ("" . "b") ("" . "c") ("" . "d") ("" . "e")
("" . "f") ("" . "g") ("" . "h") ("" . "i") ("" . "j")
("" . "k") ("" . "l") ("" . "m") ("" . "n") ("" . "o")
("" . "p") ("" . "q") ("" . "r") ("" . "s") ("" . "t")
("" . "u") ("" . "v") ("" . "w") ("" . "x") ("" . "y")
("" . "z")
;; Fullwidth ASCII punctuation
("" . "!") ("" . "\"") ("" . "#") ("" . "$")
("" . "%") ("" . "&") ("" . "'") ("" . "(")
("" . ")") ("" . "*") ("" . "+") ("" . ",")
("" . "-") ("" . ".") ("" . "/") ("" . ":")
("" . ";") ("" . "<") ("" . "=") ("" . ">")
("" . "?") ("" . "@") ("" . "[") ("" . "\\")
("" . "]") ("" . "^") ("_" . "_") ("" . "`")
("" . "{") ("" . "|") ("" . "}") ("" . "~")
;; Curly quotes and common dash/minus variants
("“" . "\"") ("”" . "\"")
("„" . "\"") ("‟" . "\"")
("" . "'") ("" . "'")
("" . "'") ("" . "'")
("" . "-") ("" . "-") ("—" . "-") ("―" . "-")
;; Superscript digits
("⁰" . "0") ("¹" . "1") ("²" . "2") ("³" . "3") ("⁴" . "4")
("⁵" . "5") ("⁶" . "6") ("⁷" . "7") ("⁸" . "8") ("⁹" . "9")
;; Subscript digits
("₀" . "0") ("₁" . "1") ("₂" . "2") ("₃" . "3") ("₄" . "4")
("₅" . "5") ("₆" . "6") ("₇" . "7") ("₈" . "8") ("₉" . "9")
;; Superscript signs and parentheses
("⁺" . "+") ("⁻" . "-") ("⁼" . "=")
("⁽" . "(") ("⁾" . ")")
;; Subscript signs and parentheses
("₊" . "+") ("₋" . "-") ("₌" . "=")
("₍" . "(") ("₎" . ")"))
"Basic conversion table.")
(defconst my-replace-zen-to-ascii--scientific-table
'(("μ" . "u")
("µ" . "u")
("Å" . "A")
("Å" . "A")
("×" . "x")
("°" . " deg"))
"Optional scientific-symbol conversion table.")
(defun my-replace-zen-to-ascii--table ()
"Return active conversion table."
(if my-replace-zen-to-ascii-convert-scientific-symbols
(append my-replace-zen-to-ascii--basic-table
my-replace-zen-to-ascii--scientific-table)
my-replace-zen-to-ascii--basic-table))
(defun my-replace-zen-to-ascii--regexp ()
"Return regexp for active conversion table."
(regexp-opt (mapcar #'car (my-replace-zen-to-ascii--table))))
(defun my-replace-zen-to-ascii--replace-region (start end)
"Convert selected characters in region START END."
(let* ((table (my-replace-zen-to-ascii--table))
(regexp (regexp-opt (mapcar #'car table))))
(save-excursion
(goto-char start)
(while (re-search-forward regexp end t)
(let* ((from (match-string 0))
(to (cdr (assoc from table))))
(when to
(replace-match to t t)))))))
;;;###autoload
(defun replace-zen-to-ascii-region (start end)
"Convert fullwidth ASCII-like and super/subscript characters in region to ASCII."
(interactive "r")
(my-replace-zen-to-ascii--replace-region start end)
(message "Converted selected characters to ASCII."))
;;;###autoload
(defun replace-zen-to-ascii-buffer ()
"Convert fullwidth ASCII-like and super/subscript characters in the whole buffer."
(interactive)
(replace-zen-to-ascii-region (point-min) (point-max)))
;;;###autoload
(defun replace-zen-to-ascii-region-copy (start end)
"Copy converted region to kill-ring without modifying current buffer."
(interactive "r")
(let ((text (buffer-substring-no-properties start end))
(buf (generate-new-buffer " *replace-zen-to-ascii-copy*")))
(unwind-protect
(with-current-buffer buf
(insert text)
(replace-zen-to-ascii-region (point-min) (point-max))
(kill-new (buffer-string)))
(kill-buffer buf))
(message "Converted text copied to kill-ring.")))
;;;###autoload
(defun replace-zen-to-ascii-buffer-copy ()
"Copy converted whole buffer to kill-ring without modifying current buffer."
(interactive)
(replace-zen-to-ascii-region-copy (point-min) (point-max)))
;;;###autoload
(defun replace-zen-to-ascii-toggle-scientific-symbols ()
"Toggle optional scientific-symbol conversion."
(interactive)
(setq my-replace-zen-to-ascii-convert-scientific-symbols
(not my-replace-zen-to-ascii-convert-scientific-symbols))
(message "Scientific-symbol conversion: %s"
(if my-replace-zen-to-ascii-convert-scientific-symbols
"ON"
"OFF")))
(provide 'my-replace-zen-to-ascii)
;;; my-replace-zen-to-ascii.el ends here