Como substituir um char no cursor no emacs lisp

4

Eu quero criar um modo secundário que ajude a inserir o caractere de tom tailandês. Isto é o que eu escrevi:

(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)

Claro que preciso implementar mais detalhes, mas já tenho problemas. Em primeiro lugar, a função replace-string não funciona mesmo se houver o em um buffer. Em segundo lugar, não consegui descobrir como substituir apenas um caractere que está no cursor.

Como posso escrever para implementar esse tipo de função?

Editar

Seguindo o conselho de Gilles, escrevi assim:

(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)

Mas recebo assoc: Symbol's function definition is void: thai-tone-conversion-list error, quando coloco 2 em thai-input-mode .

    
por ironsand 20.07.2014 / 01:20

1 resposta

2

(replace-string "o" "ô") substitui a próxima ocorrência de o após o cursor¹, exceto no modo de marca transitória com uma marca ativa, caso em que substitui a primeira ocorrência na região marcada.

Isso funciona para substituir o caractere após o cursor, mas, claro, se isso não for um o , ele poderá substituir um caractere adicional. Você poderia usar os argumentos START e END para replace-string para limitar a extensão da substituição, mas isso não será escalável. Use char-after para recuperar o caractere após o cursor e char-before para recuperar o caractere antes do cursor. Esta função parece destinada a ser usada depois de digitar um o , então acho que char-before é o que você está procurando.

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

Uma abordagem alternativa é fazer um teste (ou uma série de testes) com looking-at (para texto que começa no cursor) ou looking-back (para o texto que termina no cursor). Você pode, então, chamar replace-match para substitua o texto; isso permite alguma automação, por exemplo, o Emacs pode cuidar da substituição de letras minúsculas por letras minúsculas e maiúsculas por letras maiúsculas.

(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 que o Emacs já tem algum suporte para o tailandês, pode ser mais fácil construir sobre ele do que reinventar a roda. Você pode selecionar um dos dois métodos de entrada tailandeses com set-input-method ( C-x RET C-\ ). Não parece haver nenhuma documentação em inglês além do código-fonte .

¹ Na terminologia do Emacs, o “cursor” como na posição em que as edições são feitas é chamado de ponto . A palavra cursor é reservada para o artefato visual na tela que marca a posição do ponto.

    
por 20.07.2014 / 04:19

Tags