4

I want to create a minor mode that helps to input thai tone character. This is what I wrote:

(defvar thai-input-mode-map
  (let ((map (make-sparse-keymap)))
    (define-key map "2" (lambda () (interactive)
              (replace-string "o" "ô")
              ))
    map)
  "Keymap used by `thai-input-mode'.")
(easy-mmode-define-minor-mode thai-input-mode
                              "Input mode for Thai"
                              nil  " TH" thai-input-mode-map)
(global-set-key "\C-x\C-t" 'thai-input-mode)

Of course I must implement more details, but I'm already have problems. First of all the replace-string function doesn't work even if there is o in a buffer. Secondly I couldn't figure out how to replace only a character that is at the cursor.

How can I write to implement that kind of function?

Edit

By following Gilles's advice I wrote like this:

(defvar thai-tone-conversion-list
    '(("o" . "ô") ("u" . "û")))
(defun thai-add-tone ()
  (interactive "*")
  (when (let ((case-fold-search t))
          (looking-back "[ou]"))
    (replace-match (assoc (match-string 0) (thai-tone-conversion-list)))))
(defvar thai-input-mode-map
  (let ((map (make-sparse-keymap)))
    (define-key map "2" 'thai-add-tone)
    map)
  "Keymap used by `thai-input-mode'.")
(easy-mmode-define-minor-mode thai-input-mode
                              "Input mode for Thai"
                              nil  " TH" thai-input-mode-map)
(global-set-key "\C-x\C-t" 'thai-input-mode)

But I get assoc: Symbol's function definition is void: thai-tone-conversion-list error, when I put 2 in thai-input-mode.

2

(replace-string "o" "ô") replaces the next occurrence of o after the cursor¹, except in transient mark mode with an active mark in which case it replaces the first occurrence in the marked region.

This works to replace the character after the cursor, but of course if that isn't an o then it could replace a character further. You could use the START and END arguments to replace-string to limit the extent of the replacement, but this won't scale. Use char-after to retrieve the character after the cursor, and char-before to retrieve the character before the cursor. This function looks like it's meant to be used after typing an o, so I think char-before is what you're looking for.

(require 'cl)
(defun thai-add-tone ()
  (interactive "*")
  (case (char-before)
   ((?o)
    (delete-backward-char 1)
    (insert "ô"))
   ((?u)
    (delete-backward-char 1)
    (insert "û"))))

An alternative approach is to make a test (or a series of tests) with looking-at (for text starting at the cursor) or looking-back (for text ending at the cursor). You can then call replace-match to replace the text; this allows some automation, for example Emacs can take care of replacing lowercase by lowercase and uppercase by uppercase.

(defvar thai-tone-conversion-list
    '(("o" . "ô") ("u" . "û")))
(defun thai-add-tone ()
  (interactive "*")
  (when (let ((case-fold-search t))
          (looking-back "[ou]"))
    (replace-match (cdr (assoc (match-string 0) thai-tone-conversion-list)))))

Note that Emacs already has some support for Thai, it may be easier to build upon it than to reinvent the wheel. You can select one of two Thai input methods with set-input-method (C-x RET C-\). There doesn't appear to be any documentation in English beyond the source code.

¹ In Emacs terminology, the “cursor” as in the position at which edits are made is called point. The word cursor is reserved for the visual artifact on the screen that marks the position of the point.

  • Thanks Gilles! I followed your advice, but there is a error I can't fix. I added the code in my question. Could you help me? – ironsand Jul 20 '14 at 16:37
  • And the lisp/language/thai.el seems to be a input method thai character. I want to input thai pronunciation alphabet. The two are different. – ironsand Jul 20 '14 at 16:40
  • @Tetsu My mistake, remove the parentheses around thai-tone-conversion-list. – Gilles Jul 20 '14 at 20:37
  • I still get a error progn: Wrong type argument: stringp, ("o" . "ô"). I also tried the first method, with the function thai-add-tone I get error like this: cond: Wrong number of arguments: #[(n &optional killflag) "¨. – ironsand Jul 21 '14 at 21:29
  • 1
    @Tetsu See my edit. I tested the code this time. – Gilles Jul 22 '14 at 23:37

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.