Emacs: Replace Straight Quotes to Curly π
Here's a command to convert straight quote to curly quotes.
(defun xah-ascii-to-math-symbol (&optional Begin End) "Replace ASCII less-or-equal etc to unicode chars, on text block or region. Example: <= β β€ >= β β₯ ---> β βΆ --> β βΆ -- β β ~= β β Each of these on the left must have a space around them. URL `http://xahlee.info/emacs/emacs/elisp_straight_curly_quotes.html' Created: 2019-07-25 Version: 2025-12-19" (interactive) (let (xbeg xend) (seq-setq (xbeg xend) (if (and Begin End) (list Begin End) (if (region-active-p) (list (region-beginning) (region-end)) (list (save-excursion (if (re-search-backward "\n[ \t]*\n" nil 1) (match-end 0) (point))) (save-excursion (if (re-search-forward "\n[ \t]*\n" nil 1) (match-beginning 0) (point))))))) (let ((case-fold-search nil)) (save-excursion (save-restriction (narrow-to-region xbeg xend) (goto-char (point-min)) (while (search-forward " <= " nil t) (replace-match " β€ ")) (goto-char (point-min)) (while (search-forward " >= " nil t) (replace-match " β₯ ")) (goto-char (point-min)) (while (search-forward " ---> " nil t) (replace-match " βΆ ")) (goto-char (point-min)) (while (search-forward " --> " nil t) (replace-match " βΆ ")) (goto-char (point-min)) (while (search-forward "--" nil t) (replace-match " β ")) (goto-char (point-min)) (while (search-forward "~=" nil t) (replace-match "β")))))))
(defun xah-prettify-punctuations (&optional Begin End) "Replace ASCII punctuations etc to Unicode symbols. Example: -- β β & β οΌ ... β β¦ :) β π URL `http://xahlee.info/emacs/emacs/elisp_straight_curly_quotes.html' Created: 2019-07-25 Version: 2025-12-19" (interactive) (let (xbeg xend) (seq-setq (xbeg xend) (if (and Begin End) (list Begin End) (if (region-active-p) (list (region-beginning) (region-end)) (list (save-excursion (if (re-search-backward "\n[ \t]*\n" nil 1) (match-end 0) (point))) (save-excursion (if (re-search-forward "\n[ \t]*\n" nil 1) (match-beginning 0) (point))))))) (save-restriction (narrow-to-region xbeg xend) (let ((case-fold-search nil)) (goto-char (point-min)) (while (search-forward "..." nil t) (replace-match "β¦")) (goto-char (point-min)) (while (search-forward " & " nil t) (replace-match " οΌ ")) (goto-char (point-min)) (while (search-forward " :)" nil t) (replace-match " π")) (goto-char (point-min)) (while (search-forward " :(" nil t) (replace-match " βΉ")) (goto-char (point-min)) (while (search-forward " ;)" nil t) (replace-match " π")) (goto-char (point-min)) (while (search-forward " , " nil t) (replace-match ", ")) (goto-char (point-min)) (while (search-forward "β" nil t) (replace-match " β ")) (goto-char (point-min)) (while (search-forward " β " nil t) (replace-match " β "))))))
(defun xah-fix-curly-single-quote-to-apostrophe (&optional Begin End) "Replace RIGHT SINGLE QUOTATION MARK to APOSTROPHE. Example: donβt β don't iβve β i've itβs β it's URL `http://xahlee.info/emacs/emacs/elisp_straight_curly_quotes.html' Created: 2019-07-25 Version: 2025-12-19" (interactive) (let (xbeg xend) (seq-setq (xbeg xend) (if (and Begin End) (list Begin End) (if (region-active-p) (list (region-beginning) (region-end)) (list (save-excursion (if (re-search-backward "\n[ \t]*\n" nil 1) (match-end 0) (point))) (save-excursion (if (re-search-forward "\n[ \t]*\n" nil 1) (match-beginning 0) (point))))))) (save-excursion (save-restriction (narrow-to-region xbeg xend) (let ((case-fold-search t)) (goto-char (point-min)) (while (re-search-forward "\\bcanβt\\b" nil t) (replace-match "can't")) (goto-char (point-min)) (while (re-search-forward "\\bdonβt\\b" nil t) (replace-match "don't")) (goto-char (point-min)) (while (re-search-forward "\\bdoesnβt\\b" nil t) (replace-match "doesn't")) (goto-char (point-min)) (while (re-search-forward "\\bwonβt\\b" nil t) (replace-match "won't")) (goto-char (point-min)) (while (re-search-forward "\\bisnβt\\b" nil t) (replace-match "isn't")) (goto-char (point-min)) (while (re-search-forward "\\barenβt\\b" nil t) (replace-match "aren't")) (goto-char (point-min)) (while (re-search-forward "\\bainβt\\b" nil t) (replace-match "ain't")) (goto-char (point-min)) (while (re-search-forward "\\bdidnβt\\b" nil t) (replace-match "didn't")) (goto-char (point-min)) (while (re-search-forward "\\barenβt\\b" nil t) (replace-match "aren't")) (goto-char (point-min)) (while (re-search-forward "\\bwasnβt\\b" nil t) (replace-match "wasn't")) (goto-char (point-min)) (while (re-search-forward "\\bwerenβt\\b" nil t) (replace-match "weren't")) (goto-char (point-min)) (while (re-search-forward "\\bcouldnβt\\b" nil t) (replace-match "couldn't")) (goto-char (point-min)) (while (re-search-forward "\\bshouldnβt\\b" nil t) (replace-match "shouldn't")) (goto-char (point-min)) (while (re-search-forward "\\bβve\\b" nil t) (replace-match "'ve")) (goto-char (point-min)) (while (re-search-forward "\\bβre\\b" nil t) (replace-match "'re")) (goto-char (point-min)) (while (re-search-forward "\\bβll\\b" nil t) (replace-match "'ll")) (goto-char (point-min)) (while (re-search-forward "\\bβm\\b" nil t) (replace-match "'m")) (goto-char (point-min)) (while (re-search-forward "\\bβd\\b" nil t) (replace-match "'d")) (goto-char (point-min)) (while (re-search-forward "\\bβs\\b" nil t) (replace-match "'s")) (goto-char (point-min)) (while (re-search-forward "sβ " nil t) (replace-match "s' ")) (goto-char (point-min)) (while (re-search-forward "sβ\n" nil t) (replace-match "s'\n")) (goto-char (point-min)) (while (re-search-forward "\\bβem\\b" nil t) (replace-match "'em")))))))
(defun xah-fix-double-quote-to-curly (&optional Begin End) "Change straight double quotes to curly. This is a heuristic based algo, result can be wrong in some places. todo: text inside <something something>, do not change inside Created: 2023-01-04 Version: 2025-03-25" (interactive) (let (xbeg xend) (seq-setq (xbeg xend) (if (and Begin End) (list Begin End) (if (region-active-p) (list (region-beginning) (region-end)) (list (save-excursion (if (re-search-backward "\n[ \t]*\n" nil 1) (match-end 0) (point))) (save-excursion (if (re-search-forward "\n[ \t]*\n" nil 1) (match-beginning 0) (point))))))) (let ((case-fold-search nil)) (save-excursion (save-restriction (narrow-to-region xbeg xend) (xah-replace-regexp-pairs-region (point-min) (point-max) [ ["^\"" "β"] ["\"\\'" "β"] ["\\([0-9]+\\)β \\([0-9]+\\)" "\\1β³ \\2"] ] t ) (xah-replace-pairs-region (point-min) (point-max) [ ["\n\"" "\nβ"] [">\"" ">β"] ["(\"" "(β"] [" \"" " β"] ["\" " "β "] ["\"," "β,"] ["\",\n" "β,\n"] ["\". " "β. "] ["\".\n" "β.\n"] ["\"." "β."] ["\"?" "β?"] ["\";" "β;"] ["\":" "β:"] ["\")" "β)"] ["\"]" "β]"] ;; ["\"[" "\β["] [".\"" ".β"] [",\"" ",β"] ["!\"" "!β"] ["?\"" "?β"] ["\"<" "β<"] ;; ["\"\n" "β\n"] ] t t))))))
(defun xah-fix-double-quote-to-curly (&optional Begin End) "Change straight double quotes to curly. This is a heuristic based algo, result can be wrong in some places. todo: text inside <something something>, do not change inside Created: 2023-01-04 Version: 2025-03-25" (interactive) (let (xbeg xend) (seq-setq (xbeg xend) (if (and Begin End) (list Begin End) (if (region-active-p) (list (region-beginning) (region-end)) (list (save-excursion (if (re-search-backward "\n[ \t]*\n" nil 1) (match-end 0) (point))) (save-excursion (if (re-search-forward "\n[ \t]*\n" nil 1) (match-beginning 0) (point))))))) (let ((case-fold-search nil)) (save-excursion (save-restriction (narrow-to-region xbeg xend) (xah-replace-regexp-pairs-region (point-min) (point-max) [ ["^\"" "β"] ["\"\\'" "β"] ["\\([0-9]+\\)β \\([0-9]+\\)" "\\1β³ \\2"] ] t ) (xah-replace-pairs-region (point-min) (point-max) [ ["\n\"" "\nβ"] [">\"" ">β"] ["(\"" "(β"] [" \"" " β"] ["\" " "β "] ["\"," "β,"] ["\",\n" "β,\n"] ["\". " "β. "] ["\".\n" "β.\n"] ["\"." "β."] ["\"?" "β?"] ["\";" "β;"] ["\":" "β:"] ["\")" "β)"] ["\"]" "β]"] ;; ["\"[" "\β["] [".\"" ".β"] [",\"" ",β"] ["!\"" "!β"] ["?\"" "?β"] ["\"<" "β<"] ;; ["\"\n" "β\n"] ] t t))))))
(defun xah-replace-straight-quotes (&optional Begin End) "Replace straight double quotes to curly ones, and others. Works on current text block or selection. Examples of changes: γ\"β¦\"γ β γββ¦βγ γ...γ β γβ¦γ γIβmγ β γI'mγ γ--γ β γβγ γ~=γ β γβγ When called in lisp code, Begin and End are region begin/end positions. WARNING: this command does not guarantee 100% correct conversion of quotes, because it impossible. You should double check highlighted places after. URL `http://xahlee.info/emacs/emacs/elisp_straight_curly_quotes.html' Created: 2015-04-29 Version: 2025-03-25" ;; some examples for debug ;; do "βem all -- done..." ;; Iβam not ;; said "canβt have it, canβt, just canβt" ;; βIβve canβtβ (interactive) (let (xbeg xend) (seq-setq (xbeg xend) (if (and Begin End) (list Begin End) (if (region-active-p) (list (region-beginning) (region-end)) (list (save-excursion (if (re-search-backward "\n[ \t]*\n" nil 1) (match-end 0) (point))) (save-excursion (if (re-search-forward "\n[ \t]*\n" nil 1) (match-beginning 0) (point))))))) (let ((case-fold-search nil)) (save-excursion (save-restriction (narrow-to-region xbeg xend) (xah-prettify-punctuations (point-min) (point-max)) (xah-ascii-to-math-symbol (point-min) (point-max)) (xah-fix-double-quote-to-curly (point-min) (point-max)) (xah-fix-curly-single-quote-to-apostrophe (point-min) (point-max)))))))
requires package Emacs: xah-replace-pairs.el π¦