简体   繁体   English

如何将键绑定到“由以下键序列表示的函数”?

[英]How do I bind a key to “the function represented by the following key sequence”?

I'm just starting to learn emacs (woohoo!) and I've been mucking around in my .emacs quite happily. 我刚刚开始学习emacs(哇哇!)而且我一直很喜欢我的.emacs Unfortunately, I don't know Lisp yet, so I'm having issues with the basics. 不幸的是,我还不知道Lisp,所以我遇到了基础问题。

I've already remapped a few keys until I fix my muscle memory: 在修好肌肉记忆之前,我已经重新设计了几个按键:

(global-set-key (kbd "<f9>") 'recompile)

That's fine. 没关系。 But how can I tell a key to 'simulate pressing several keys'? 但是,如何判断“模拟按几个键”键? For instance, I don't know, make <f1> do the same as Cu 2 Cx } (widen buffer by two chars). 例如,我不知道,make <f1>Cu 2 Cx }做同样的事情(用两个字符加宽缓冲区)。

One way is to look up that Cx } calls shrink-window-horizontally , and do some sort of lambda thing. 一种方法是查找Cx }调用shrink-window-horizontally ,并做一些lambda事情。 This is of course the neat and elegant way (how do you do this?). 这当然是整洁而优雅的方式(你怎么做?)。 But surely there's a way to define <f1> to send the keystrokes Cu 2 Cx } ? 但肯定有办法定义<f1>发送击键Cu 2 Cx }

当然有,这是显而易见的方式:

(global-set-key (kbd "<f1>") (kbd "C-u 2 C-x }"))

I'll use shrink-window-horizontally as the example function, but you can generalize the idea to any bindings you'd like to define. 我将使用shrink-window-horizontally作为示例函数,但您可以将该想法概括为您要定义的任何绑定。

If you want to use two as the default amount to shrink the window, rather than one, try the following: 如果要使用两个作为缩小窗口的默认量,而不是一个,请尝试以下操作:

(global-set-key [f9]
  (lambda (&optional n)
    (interactive "P")
    (shrink-window-horizontally (or n 2))))

That binds the F9 key to an interactive function accepting a prefix argument . F9键绑定到接受前缀参数的交互式函数。 If you just press F9 , you'll pass no argument , which summons the default value of 2, as the parameter n will receive nil as an argument. 如果你只按F9你将不传递参数 ,它会传递默认值2,因为参数n将接收nil作为参数。 However, if you press, say, Cu 10 F9 , you'll pass ten as the argument for n . 但是,如果你按下Cu 10 F9 ,你将传递十来作为n的参数。 This allows you to use your binding more flexibly. 这使您可以更灵活地使用绑定。

For anything long-term, I would recommend the approach shown by seh, as that will naturally be more robust in most situations. 对于任何长期的事情,我会推荐seh所示的方法,因为在大多数情况下,这种方法自然会更强大。 It requires a little more work and know-how, of course, but it's all worthwhile :) 当然,它需要更多的工作和技术诀窍,但这一切都值得:)

angus' approach is like a cut-down version of the keyboard macros feature that gives Emacs its name (and slightly simpler to use than macros for the example in question). 安格斯的方法就像是键盘宏功能的简化版本,它为Emacs提供了名称(并且使用的宏比使用宏的宏更简单)。 You should definitely be aware of macros, however -- they can be exceedingly useful, and for anything more complicated it quickly becomes far easier to record one dynamically than to write out all the individual keys manually. 你肯定应该知道宏 - 然而 - 它们非常有用,而且对于任何更复杂的东西,动态记录动态比手动写出所有单独的键要快得多。

Here's the summary I wrote myself of the most important bits: 以下是我自己写的最重要的部分摘要:

;;;; * Keyboard macros
;;   C-x (          or F3  Begin recording.
;;                     F3  Insert counter (if recording has already commenced).
;;   C-u <n> C-x (  or F3  Begin recording with an initial counter value <n>.
;;   C-x )          or F4  End recording.
;;   C-u <n> C-x )  or F4  End recording, then execute the macro <n>-1 times.
;;   C-x e          or F4  Execute the last recorded keyboard macro.
;;       e          or F4  Additional e or F4 presses repeat the macro.
;;   C-u <n> C-x e  or F4  Execute the last recorded keyboard macro <n> times.
;;   C-x C-k r             Apply the last macro to each line of the region.
;;   C-x C-k e             Edit a keyboard macro (RET for most recent).
;;   C-x C-k b             Set a key-binding.
;;
;; If you find yourself using lots of macros, you can even name them
;; for later use, and save them to your init file.
;;   M-x name-last-kbd-macro RET (name) RET
;;   M-x insert-kbd-macro RET (name) RET
;;
;; For more documentation:
;;   C-h k C-x (
;;   M-: (info "(emacs) Keyboard Macros") RET

If we play with the example from the question, you'll see how some of these things tie together... 如果我们使用问题中的示例,您将看到这些事情中的一些如何结合在一起......

To begin with, you can define the macro with F3 Cu 2 Cx } F4 首先,您可以使用F3 Cu 2 Cx } F4定义宏

You could then bind it temporarily to F1 with Cx Ck b F1 (actually that's not true if F1 is currently a prefix key for an existing keymap, as typing it interactively will simply prompt for the remainder. You can circumvent this in code with (global-set-key (kbd "<f1>") ...) , but I would suggest sticking to the reserved bindings ). 然后你可以用Cx Ck b F1暂时将它绑定到F1 (实际上,如果F1当前是现有键映射的前缀键,则不是这样,因为以交互方式键入它将只是提示剩下的。你可以在代码中绕过它(global-set-key (kbd "<f1>") ...) ,但我建议坚持保留绑定 )。

If you then use describe-key ( Ch k ) to examine what is bound to that key, Emacs will show you a (lambda) expression which you could copy to your init file if you so wished. 如果您然后使用describe-keyCh k )来检查绑定到该键的内容,Emacs将显示一个(lambda)表达式,如果您愿意,可以将其复制到init文件中。

Alternatively, you could name the macro and ask Emacs to insert the code into the current buffer: 或者,您可以命名宏并要求Emacs将代码插入当前缓冲区:

Mx name-last-kbd-macro RET (name) RET Mx name-last-kbd-macro RET (名称) RET
Mx insert-kbd-macro RET RET Mx insert-kbd-macro RET RET

This code will look different to the lambda expression shown by describe-key , but if you evaluate the inserted macro, you'll see the equivalence. 此代码看起来与describe-key显示的lambda表达式不同,但如果您评估插入的宏,您将看到等价。 You can likewise show that the (kbd "...") expression also evaluates to the same value, and therefore these are all just alternative ways of doing the same thing. 您同样可以显示(kbd "...")表达式也计算为相同的值,因此这些只是执行相同操作的替代方法。

(You can use the *scratch* buffer to evaluate the code by moving point after the end of the expression, and either typing Cx Ce to show the value in the minibuffer, or Cj to insert the value into the buffer). (您可以使用* scratch *缓冲区通过在表达式结束后移动点来评估代码,并键入Cx Ce以显示迷你缓冲区中的值,或者键入Cj以将值插入缓冲区)。

Note that the 'inserted' code uses fset to assign the macro to a symbol. 请注意,'inserted'代码使用fset将宏指定给符号。 You could bind the macro to a key either by executing the (fset) and then assigning that symbol to a key with (global-set-key) , or you could ignore the (fset) and simply assign the macro value directly. 您可以通过执行(fset)然后使用(global-set-key)将该符号分配给键来将宏绑定到键,或者可以忽略(fset)并直接分配宏值。 This, of course, is directly equivalent to angus' answer. 当然,这直接等同于安格斯的回答。

Edit: I've just noticed that there's a kmacro-name-last-macro function bound to Cx Ck n which is nearly identical in form to name-last-kbd-macro , but which generates the lambda expression form seen when using kmacro-bind-to-key ( Cx Ck b ) and describe-key . 编辑:我刚才注意到有一个kmacro-name-last-macro函数绑定到Cx Ck n ,它在形式上与name-last-kbd-macro几乎相同,但它生成了使用kmacro-bind-to-key时看到的lambda表达式形式kmacro-bind-to-keyCx Ck b )和describe-key

来自general.el general-simulate-key工作得更好(在我的例子中是弹出窗口和更改键盘的序列,我无法使用宏): https//github.com/noctuid/general.el#simulating-按键

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM