Menerjemahkan string ke penekanan tombol

8

Diberikan string di elisp, saya ingin mensimulasikan emacs menerima penekanan tombol apa pun yang diperlukan untuk membuat kembali string itu. Jadi mengingat string "Hello" emacs akan bertindak persis sama seperti jika saya telah menekan Shift + H, e, l, l, o. Perhatikan bahwa ini tidak selalu sama dengan memasukkan teks ke dalam buffer - beberapa mode seperti mode-cari mendengarkan acara langsung menekan tombol.

Alasan ini diperlukan adalah karena ada banyak mode dan ekstensi yang membuat asumsi bahwa semua input berasal dari keyboard atau membuat asumsi bahwa setiap penyangga / perubahan jendela / bingkai akan dikaitkan dengan peristiwa input keyboard, dan banyak waktu mereka memeriksa data yang terkait dengan peristiwa itu. Untuk mode pengenalan ucapan yang saya kerjakan agar bekerja mulus dengan tubuh kode yang ada, itu tidak bisa hanya memanggil langsung ke elisp untuk melakukan tindakan, alih-alih itu perlu memberitahu elisp untuk menekan tombol untuk menyebabkan tindakan itu terjadi.

Saya telah menemukan peristiwa-perintah-belum dibaca, tetapi saya tidak mengetahui adanya kode yang akan menerjemahkan string ke urutan kunci yang diperlukan. Apakah sesuatu seperti itu sudah ada?

Joseph Garvin
sumber

Jawaban:

5

Apakah

(execute-kbd-macro (kbd "Hello"))

kebetulan bekerja?

PythonNut
sumber
2
Ini akan berfungsi dalam kasus ini, tetapi tidak dengan string "C-Beams" misalnya. Salah satu cara untuk menghindarinya adalah dengan menambahkan spasi di antara setiap karakter. (let ((string "C-Beams")) (execute-kbd-macro (kbd (mapconcat #'char-to-string string " "))))akan bekerja. Mungkin ada cara yang lebih baik ...
YoungFrog
Hmm, trik mapconcat tidak berfungsi jika string benar-benar berisi spasi, misalnya "C beams" menjadi "Cbeams". (execute-kbd-macro (kbd "SPC"))berfungsi, jadi Anda bisa menulis sesuatu yang sedikit lebih rumit daripada mapconcat untuk melakukan substitusi itu ... ini membuat saya khawatir meskipun mungkin ada kunci lain yang relevan meskipun itu membutuhkan perlakuan khusus ini.
Joseph Garvin
Sepertinya baris baru dan tab juga memiliki masalah ini. Saya dapat menangani penggantian SPC / RET / TAB, meskipun saya bertanya-tanya apakah seluruh pendekatan ini akan memiliki masalah dengan keyboard internasional.
Joseph Garvin
(mapc (lambda (char) (execute-kbd-macro (char-to-string char))) string)tampaknya berfungsi ok. Tapi (tentu saja?) Jika ada karakter tab, itu akan berpura-pura memukul TAB, yang mungkin tidak terikat pada perintah memasukkan tab yang sebenarnya ...
YoungFrog
@YoungFrog: yang tampaknya masih rusak oleh \ n
Joseph Garvin
4

Oke, jadi jawaban pertama saya memiliki sejumlah kekurangan seperti yang terinci dalam komentarnya.

execute-kbd-macro adalah fungsi bawaan di C source code.

(execute-kbd-macro MACRO &optional COUNT LOOPFUNC)

Jalankan MACRO sebagai rangkaian karakter perintah editor. MACRO juga bisa menjadi vektor acara keyboard . Jika MACRO adalah simbol, definisi fungsinya digunakan. COUNT adalah hitungan berulang, atau nil untuk sekali, atau 0 untuk loop tak terbatas.

Argumen ketiga opsional LOOPFUNC dapat berupa fungsi yang dipanggil sebelum setiap iterasi makro. Iterasi berhenti jika LOOPFUNC mengembalikan nol.

(penekanan milikku)

Jadi solusi untuk meneruskan string ke Emacs sebagai penekanan tombol individu adalah:

(defun insert-via-kbd (str)
  (execute-kbd-macro (vconcat str)))

Ini tampaknya bekerja dengan sangat baik (bahkan menangani Jepang!), Tetapi masih ada beberapa keanehan:

  • \nakan memicu C-j(tidak C-m, RETatau <return>)
  • \takan memicu TAB(tidak <tab>)
PythonNut
sumber