first commit

This commit is contained in:
2026-07-03 09:04:08 +09:00
commit 00a581c2ea
6 changed files with 2247 additions and 0 deletions
+167
View File
@@ -0,0 +1,167 @@
\
;;; 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