168 lines
6.3 KiB
EmacsLisp
168 lines
6.3 KiB
EmacsLisp
\
|
||
;;; 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" . "0") ("1" . "1") ("2" . "2") ("3" . "3") ("4" . "4")
|
||
("5" . "5") ("6" . "6") ("7" . "7") ("8" . "8") ("9" . "9")
|
||
|
||
;; Fullwidth uppercase letters
|
||
("A" . "A") ("B" . "B") ("C" . "C") ("D" . "D") ("E" . "E")
|
||
("F" . "F") ("G" . "G") ("H" . "H") ("I" . "I") ("J" . "J")
|
||
("K" . "K") ("L" . "L") ("M" . "M") ("N" . "N") ("O" . "O")
|
||
("P" . "P") ("Q" . "Q") ("R" . "R") ("S" . "S") ("T" . "T")
|
||
("U" . "U") ("V" . "V") ("W" . "W") ("X" . "X") ("Y" . "Y")
|
||
("Z" . "Z")
|
||
|
||
;; Fullwidth lowercase letters
|
||
("a" . "a") ("b" . "b") ("c" . "c") ("d" . "d") ("e" . "e")
|
||
("f" . "f") ("g" . "g") ("h" . "h") ("i" . "i") ("j" . "j")
|
||
("k" . "k") ("l" . "l") ("m" . "m") ("n" . "n") ("o" . "o")
|
||
("p" . "p") ("q" . "q") ("r" . "r") ("s" . "s") ("t" . "t")
|
||
("u" . "u") ("v" . "v") ("w" . "w") ("x" . "x") ("y" . "y")
|
||
("z" . "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
|