I've got a snippet I want to bind to a key:
(define-key (lisp-interaction-mode-map) (kdb "C-c e")
(let ((result (eval (read (buffer-substring
(point-at-bol) (point-at-eol))))))
(goto-char (point-at-eol))
(insert (format " ; %s" result))))
however, when C-c v that in *scratch*, I get
define-key: Symbol's function definition is void: lisp-interaction-mode-map
You have parentheses around lisp-interaction-mode-map, which Lisp interprets to mean that you want to call the function named lisp-interaction-mode-map. Instead, you want to use it as variable.
I also did some other edits you'll need to get what you have to work. I assumed you wrote read in order to prompt for a user-inputted string:
(define-key lisp-interaction-mode-map (kbd "C-c C-e")
(lambda (result)
(interactive (list (read-from-minibuffer (buffer-substring (point-at-bol) (point-at-eol)))))
(goto-char (point-at-eol))
(insert (format " ; %s" result))))
What's wrong with the normal form?
(define-key lisp-interaction-mode-map [(control e)] 'eval-defun)
Related
I have buffers named *terminal<1>*, *terminal<2>*, *terminal<3>*, etc. Is there a way to bind a key combination that will take an argument for the number? That is, I want to bind C-c 1 to switch to *terminal<1>* and C-c 2 to switch to *terminal<2>*, and so on. If I can't do this directly, is it possible to do metaprogramming in Elisp that will define all the functions for me?
In this suggestion, the interactive switch-to-terminal will take either a prefix argument C-u 2 for example, or prompt the user.
The macro then makes setting up the key bindings a little easier.
Finally I bind C-c 1 to C-c 4 to switch to *terminal<1>* to *terminal<4>*.
(defun switch-to-terminal (buf-num)
(interactive "NNumber of buffer to visist: ")
(let* ((buf-name (format "*terminal<%d>*" buf-num))
(buf (get-buffer buf-name)))
(unless buf
(error "No buffer %s" buf-name))
(switch-to-buffer buf)))
(defmacro bind-switch-to-terminal (num)
`(global-set-key
,(kbd (format "C-c %d" num))
(lambda ()
(interactive)
(switch-to-terminal ,num))))
(bind-switch-to-terminal 1)
(bind-switch-to-terminal 2)
(bind-switch-to-terminal 3)
(bind-switch-to-terminal 4)
This change uses the same switch-to-terminal function, but replaces bind-switch-to-terminal with a function. The lexical-let* allows for the creation of a closure to create unique terminal switching functions, the dotimes loop then binds for C-c 1 to C-c 9.
(defun bind-switch-to-terminal (num)
(lexical-let* ((buf-num num)
(switch-func
(lambda ()
(interactive)
(switch-to-terminal buf-num))))
(global-set-key
(kbd (format "C-c %d" buf-num))
switch-func)))
(dotimes (num 9)
(bind-switch-to-terminal (1+ num)))
You can bind keys as usual:
(global-set-key (kbd "C-c 1") (lambda ()
(interactive)
(switch-to-buffer "*terminal<1>*")))
To create all the shortcuts from 1 to 9 we would use macros.
edit: This buggy version may put you on tracks. I give up :(
(defmacro gototerminal (count)
`(global-set-key (kbd ,(concat "C-c " (number-to-string count)))
;; with the comma I want to evaluate what is inside concat
(lambda () (interactive)
(switch-to-buffer (concat "*terminal<" ,count ">*"))))
)
(progn (setq count 1)
(while (< count 10)
(gototerminal count)
(setq count (1+ count))
))
ps: an elisp debugger is edebug. Set it with C-u C-M-x
I would write a function that calls interactive with an n argument which indicates that the function reads a number from the mini buffer:
(defun test (x)
(interactive "nNumber of buffer to visit: ")
(message (concat "received number: " (number-to-string x))))
Binding this to a key will let you enter a number in the mini buffer.
Another way is to use a numerical argument:
(defun test (x)
(interactive "P")
(message (concat "received number: " (number-to-string x))))
Say you bind this function to C-c c, you can then pass it the number 2 as an argument by pressing C-u 2 C-c c.
If you avoid the usage of an existing prefix key like C-c you can trigger a command with one keypress e.g. F9.
This command can have a single key as input.
Example:
(defun test (k)
(interactive "K")
(message "Pressed key: %d" (- (aref k 0) ?0)))
(local-set-key [f9] 'test)
Emacs' Bookmarks are great, as is navigating the list of buffers. But I find it nice to have shorter chords to get directly to where I want to go. So I have been accruing a repetitive set of functions and keybindings for all my favorite files and folders.
I wondered if I could use a dolist to handle this repetitiveness, but am no good programmer.
Here is one of the (seven and rising) repetitively defined functions, and a feeble attempt at writing the dolist following:
(defun jump-to-main ()
(interactive)
(find-file main))
(global-set-key (kbd "C-c m") 'jump-to-main)
This might barely qualify as pseudocode:
(dolist (x '(("m" main)
("t" tech))
(defun (concat 'jump-to- (cdr x)) ()
(interactive)
(find-file (cdr x)))
(global-set-key (kbd (concat "C-c " (car x)))
'(concat 'jump-to- (cdr x)))
))
The payoff in an elegant init file, versus how fast I am at solving at Lisp problems... hoping the Stackoverflow can save me.
Other strategies and approaches are appreciated.
EDIT:
With lawlist's suggestion, my question may reduce and be more clear presented the following way. I would like to reduce the repetition in the following series of keybindings.
(global-set-key (kbd "C-c A")
(lambda ()
(interactive)
(find-file fileA)))
(global-set-key (kbd "C-c B")
(lambda ()
(interactive)
(find-file fileB)))
...
(global-set-key (kbd "C-c Z")
(lambda ()
(interactive)
(find-file fileZ)))
fileK for example expands to something like "~/fileK.txt".
EDIT:
So here is another try:
(dolist (x '(("m" main)
("t" tech))
(global-set-key (kbd (concat "C-c " (car x)))
(lambda ()
(interactive)
(find-file (cdr x))
))))
The keybinding part seems okay, but (find-file (cdr x)) isn't doing what I need, and I couldn't fix it in a small amount of googling lisp.
Here are the expressions I'm using to focus on the broken parts:
(setq somefile "~/somefile.txt")
(setq x '("s" . somefile))
(concat "C-c " (car x))
(find-file (cdr x))
The last line is the one that doesn't work, as (cdr x) apparently evaluates to (main). I tried slipping in an eval to expand the main variable, but it doesn't seem...
Reading Phil's answer now, this may take me a while.
FWIW, a fairly direct translation of your pseudo-code is:
(defvar my-file-main (expand-file-name "~/main") "My main file")
(defvar my-file-tech (expand-file-name "~/tech") "My tech file")
(dolist (x '(("m" . my-file-main)
("t" . my-file-tech)))
(let* ((sym (cdr x))
(func (intern (concat "jump-to-" (symbol-name sym)))))
(defalias func `(lambda ()
,(format "Jump to file `%s'." (symbol-name sym))
(interactive)
(find-file ,sym)))
(global-set-key (kbd (concat "C-c " (car x))) func)))
I'm used to regex in Ruby, so i'm a lisp noob.
(global-set-key (kbd "C-c t")
(lambda()
(interactive)
(if string-match-p file-name-directory "spec"
(shell-command (concat "rspec " (file-name-directory (buffer-file-name))))
)
)
)
Basically i want to only run this line (or an else for 'test') if the file-name-directory has the word spec in it.
Example: /user/me/app/spec/test.rb
How does one get the if statement to work?
so far i get: Symbol's value as variable is void: string-match-p in the mini buffer. Thanks.
I assume you want this to act on the current buffer, if so, try this:
(global-set-key (kbd "C-c t")
(lambda()
(interactive)
(let* ((full-name (buffer-file-name))
(path (when full-name
(file-name-directory full-name))))
(when (and path (string-match "spec" path))
(shell-command (concat "rspec " path))))))
I've got this snippet of code:
(define-key lisp-interaction-mode-map (kbd "C-c C-e")
(lambda ()
(let ((result (eval (read (buffer-substring
(point-at-bol) (point-at-eol)))))
(goto-char (point-at-eol))))
(insert (format " ; => %s" result))))
but it doesn't work, as in
Wrong type argument: commandp, (lambda nil (let ((result (eval (read (buffer-substring (point-at-bol) (point-at-eol))))) (goto-char (point-at-eol)))) (insert (format " ; => %s" result)))
This command shouldn't function on a per-line basis. Move point by sexp instead.
Here is a library I made that does basically this, but works with mult-line
results, and is reentrant. So you can change some stuff, and re-run the
command to update results.
EDIT: correct link to package mentioned.
Solved.
(define-key lisp-interaction-mode-map (kbd "C-c C-e")
(lambda ()
(interactive)
(let ((result (eval (read (buffer-substring
(point-at-bol) (point-at-eol))))))
(goto-char (point-at-eol))
(insert (format " ; ⇒ %s" result)))))
I want to execute a lisp function while pressing prefix key C-h and then let Emacs continue the normal processing of C-h.
How can I do it?
Thank you!
Evaluating
(key-binding [(control h)])
I found out the command bound is help-command. You can use an "around" defadvice to run your code. See manual.
(defvar smart-ime--state 'normal)
(defvar smart-ime--debug nil)
(defvar smart-ime--ena-prefix-override-keymap nil)
(defvar smart-ime--prefix-override-keymap (make-sparse-keymap))
(defvar smart-ime--keymaps-initialized nil)
(defvar smart-ime--keymap-alist
`(
(smart-ime--ena-prefix-override-keymap . ,smart-ime--prefix-override-keymap)
)
)
(defun smart-ime--init-keymaps ()
(define-key smart-ime--prefix-override-keymap [(control x)] 'smart-ime--prefix-override-handler)
(define-key smart-ime--prefix-override-keymap [(control c)] 'smart-ime--prefix-override-handler)
(define-key smart-ime--prefix-override-keymap [(control h)] 'smart-ime--prefix-override-handler)
)
(defun smart-ime--prefix-override-handler (arg)
(interactive "P")
(smart-ime--prefix-override-replay arg))
;; the most important part
(defun smart-ime--prefix-override-replay (arg)
(let* ((keys (this-command-keys))
(i (length keys))
(key (aref keys (1- i))))
(ime-save-and-set-status 0)
(add-hook 'post-command-hook 'smart-ime--post-command-handler)
(setq smart-ime--state 'prefix)
(setq smart-ime--ena-prefix-override-keymap nil)
;; Don't record this command
(setq this-command last-command)
;; Restore the prefix arg
(setq prefix-arg arg)
(reset-this-command-lengths)
;; Push the key back on the event queue
(setq unread-command-events (cons key unread-command-events))))
(defun smart-ime--post-command-handler-1 ()
(cond ((eq smart-ime--state 'prefix)
(setq smart-ime--state 'sequence))
((eq smart-ime--state 'sequence)
(ime-restore-status)
(setq smart-ime--ena-prefix-override-keymap t)
(setq smart-ime--state 'normal)
(remove-hook 'post-command-hook 'smart-ime--post-command-handler)))
(t
(error "error state")))
(defun smart-ime--post-command-handler ()
(when smart-ime-mode
(condition-case nil
(smart-ime--post-command-handler-1)
(error nil))))
(define-minor-mode smart-ime-mode
"Toggle Smart IME mode."
:init-value nil
:lighter " SmartIME"
:global t
(unless smart-ime--keymaps-initialized
(smart-ime--init-keymaps)
(setq smart-ime--keymaps-initialized t))
(unless smart-ime-mode
(remove-hook 'post-command-hook 'smart-ime--post-command-handler))
(if (not smart-ime-mode)
(setq emulation-mode-map-alists (delq 'smart-ime--keymap-alist emulation-mode-map-alists))
(add-to-ordered-list 'emulation-mode-map-alists 'smart-ime--keymap-alist 400)
(setq smart-ime--ena-prefix-override-keymap t))
)
;;; Announce
(provide 'smart-ime)