aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEli Zaretskii2025-03-02 15:25:53 +0200
committerEli Zaretskii2025-03-02 15:25:53 +0200
commit8937dee9e418c64587769dd22bb9683cd3690688 (patch)
treed85f4f34c5f0febfb573eea0daf4d465671c40e7
parente34d7a7c4eb90cde7a2dc55ac5a02fae303e5d0f (diff)
downloademacs-8937dee9e418c64587769dd22bb9683cd3690688.tar.gz
emacs-8937dee9e418c64587769dd22bb9683cd3690688.zip
New commands to convert ASCII to fullwidth characters and back
* lisp/textmodes/text-mode.el (text-mode--fullwidth-table): New variable. (text-mode--get-fullwidth-table): New internal function. (fullwidth-region, halfwidth-region, fullwidth-word) (halfwidth-word): New commands. (Bug#71822) * etc/NEWS: Announce new commands.
-rw-r--r--etc/NEWS11
-rw-r--r--lisp/textmodes/text-mode.el79
2 files changed, 90 insertions, 0 deletions
diff --git a/etc/NEWS b/etc/NEWS
index 6ca36419116..8d8fbbf38b9 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -445,6 +445,17 @@ modal editing packages.
445* Changes in Specialized Modes and Packages in Emacs 31.1 445* Changes in Specialized Modes and Packages in Emacs 31.1
446 446
447--- 447---
448** Text mode
449
450*** New commands to convert between ASCII and full-width characters.
451New commands 'fullwidth-region' and 'fullwidth-word' convert ASCII
452characters in region or in the word at point to the corresponding
453full-width characters, which are customarily used instead of ASCII
454characters in CJK texts. For example, 'A' is converted to 'A', '1' is
455converted to '1', etc. Companion commands 'halfwidth-region' and
456'halfwidth-word' perform the opposite conversion.
457
458---
448** ASM mode 459** ASM mode
449 460
450*** 'asm-mode-set-comment-hook' is obsolete. 461*** 'asm-mode-set-comment-hook' is obsolete.
diff --git a/lisp/textmodes/text-mode.el b/lisp/textmodes/text-mode.el
index d918efa72c6..2d019f54aec 100644
--- a/lisp/textmodes/text-mode.el
+++ b/lisp/textmodes/text-mode.el
@@ -271,6 +271,85 @@ The argument NLINES says how many lines to center."
271 271
272(define-obsolete-function-alias 'indented-text-mode #'text-mode "29.1") 272(define-obsolete-function-alias 'indented-text-mode #'text-mode "29.1")
273 273
274
275
276(defvar text-mode--fullwidth-table nil)
277
278(defun text-mode--get-fullwidth-table ()
279 "Return translation table for converting half-width characters to fullwidth."
280 (or (and (char-table-p text-mode--fullwidth-table)
281 text-mode--fullwidth-table)
282 ;; Create the translation table.
283 (let ((tbl (make-char-table 'translation-table))
284 (rev-tbl (make-char-table 'translation-table))
285 (ch ?!))
286 (while (<= ch ?~)
287 ;; ! -> !, 0 -> 0, A -> A, etc.
288 (aset tbl ch (+ ch #xFEE0))
289 (aset rev-tbl (+ ch #xFEE0) ch)
290 (setq ch (1+ ch)))
291 (set-char-table-extra-slot tbl 0 rev-tbl)
292 (set-char-table-extra-slot tbl 1 1)
293 (set-char-table-extra-slot rev-tbl 1 1)
294 (put 'text-mode--fullwidth-table 'translation-table tbl)
295 (setq text-mode--fullwidth-table tbl)
296 tbl)))
297
298(defun fullwidth-region (from to)
299 "Convert ASCII characters in the region to their fullwidth variants.
300This converts 1 to 1, A to A, etc.
301When called from Lisp, FROM and TO are character positions that define
302the region in which to convert characters."
303 (interactive "r")
304 (translate-region from to
305 (text-mode--get-fullwidth-table)))
306
307(defun halfwidth-region (from to)
308 "Convert fullwidth characters in the region to their ASCII variants.
309This converts 1 to 1, A to A, etc.
310When called from Lisp, FROM and TO are character positions that define
311the region in which to convert characters."
312 (interactive "r")
313 (translate-region from to
314 (char-table-extra-slot (text-mode--get-fullwidth-table)
315 0)))
316
317(defun fullwidth-word (arg)
318 "Convert fullwidth characters in word at point, moving over the word.
319This converts fullwidth characters to their ASCII variants:
3201 to 1, A to A, etc.
321With numerical argument ARG, convert that many words starting from point.
322With negative argument, convert previous words, but do not move point.
323If point is in the middle of a word, the part of that word before point
324is ignored when converting forward, and the part of that word after
325point is ignored when converting backward."
326 (interactive "p")
327 (let* ((pt (point-marker))
328 (beg pt)
329 (end (progn
330 (forward-word arg)
331 (point))))
332 (fullwidth-region beg end)
333 (or (> arg 0) (goto-char pt))))
334
335(defun halfwidth-word (arg)
336 "Convert characters in word at point to fullwidth, moving over the word.
337This converts ASCII characters to their fullwidth variants:
3381 to 1, A to A, etc.
339With numerical argument ARG, convert that many words starting from point.
340With negative argument, convert previous words, but do not move point.
341If point is in the middle of a word, the part of that word before point
342is ignored when converting forward, and the part of that word after
343point is ignored when converting backward."
344 (interactive "p")
345 (let* ((pt (point-marker))
346 (beg pt)
347 (end (progn
348 (forward-word arg)
349 (point))))
350 (halfwidth-region beg end)
351 (or (> arg 0) (goto-char pt))))
352
274(provide 'text-mode) 353(provide 'text-mode)
275 354
276;;; text-mode.el ends here 355;;; text-mode.el ends here