I'm trying to remap some keys in dired like this:
(add-hook 'dired-mode-hook
(lambda ()
(require 'dired )
(define-key dired-mode-map (kbd "M-o") nil)))
(define-key dired-mode-map (kbd "M-o") 'other-window)
))
Unfortunately this doesn't seem to work, I get this error
Symbol's value as variable is void: dired-mode-map
Which is werid, because I should be loading in dired. What could I be doing wrong?
The original poster has two (2) many [pun intended] closing parentheses at this point: (define-key dired-mode-map (kbd "M-o") nil))) -- i.e., two (2) closing parentheses at the end of that line need to be eliminated. Furthermore, I do not see a reason to set the binding to nil before redefining it.
The following is another way of accomplishing the same goal. Add any additional key bindings after the progn statement as desired.
(eval-after-load "dired" '(progn
(define-key dired-mode-map (kbd "M-o") 'other-window) ))
Related
I'm trying to write a function that will set a shortcut programmatically, as in the MRE below:
(defun my/shortcut-definer (keypress end-message)
(interactive)
(global-set-key
(kbd keypress)
'(lambda () (interactive) (message end-message))))
(my/shortcut-definer "C-x x x" "Hello!")
I am tantalisingly close, but when I enter the chosen keyboard shortcut, I get the error:
Symbol’s value as variable is void: end-message
I think the problem is when defining the shortcut I wanted it to evaluate end-message but instead it included the symbol. How can I make it evaluate end-message in the lambda? (Assuming that is the error).
Looking at this link I found a solution to this problem as follows:
(defun my/shortcut-definer (keypress end-message)
(interactive)
(global-set-key
(kbd keypress)
`(lambda () (interactive) (message ,end-message))))
I'm trying to add completion at point for frame-local variables from backtrace-frames during invocations of read--expression by debugger-eval-expression or edebug-eval-expression.
I constructed the following completion table to add frame-local variables to the already available table for local elisp variables,
;; completion table for locals in current frame
(defvar my-backtrace-locals-completion-table
(completion-table-in-turn
(completion-table-dynamic
(lambda (_string)
(when-let* ((idx (backtrace-get-index)) ;backtrace.el
(frame (nth idx backtrace-frames)))
(backtrace-frame-locals frame)))
'do-switch-buffer)
elisp--local-variables-completion-table)) ;elisp-mode.el
which seems to work fine, eg. to reproduce
(1) evaluate
;; debug-on-error = t
(let ((my-local-var '(1 2))) (mapcan #'car this-local-var))
(2) from debugger's second frame, evaluate with eval-expression
(funcall my-backtrace-locals-completion-table "my-" nil t)
returns expected ("my-local-var").
The problem is following the above steps, but calling instead calling debugger-eval-expression doesn't work. The environment where the table is evaluated isn't finding a backtrace-frame (with or without do-switch-buffer).
How can I define the table to be evaluated in the proper buffer?
emacs v27.0.50
The completion table above doesn't quite return the expected candidates for debugger-eval-expression. The environment where the expression is evaluated has locals from frames higher than, but not including, the one at point in the Backtrace buffer.
So, the available locals should be only those from higher frames, eg.
(eval-when-compile (require 'dash))
(defvar my-backtrace-locals-completion-table
(completion-table-dynamic
(lambda (_string)
(when backtrace-frames
(--mapcat
(-some->> (backtrace-frame-locals it) (--map (car it)))
(nthcdr (1+ (backtrace-get-index)) backtrace-frames))))
'do-switch-buffer))
Then, redefining debugger-eval-expression's interactive spec to use the new locals table in place of the normal elisp table provides the correct completions (passing the 'do-switch-buffer arg completion-table-dynamic to find completions in the original buffer).
(defun my-backtrace#eval (orig-fn exp &optional nframe)
(interactive
(let ((elisp--local-variables-completion-table
my-backtrace-locals-completion-table))
(list (read--expression "[my] Eval in stack frame: "))))
(apply orig-fn (list exp nframe)))
(advice-add 'debugger-eval-expression :around #'my-backtrace#eval)
Can I create a macro so that I can call sequence- functions with a s-? Hence, I should be able to write s-length, s-filter and s-map instead of sequence-length, sequence-filter and sequence-map. Thanks.
You can use filtered-in from racket/require to perform this sort of transformation. Here’s a simple example:
#lang racket
(require racket/require
(filtered-in (λ (name) (regexp-replace #rx"^sequence-" name "s-"))
racket/sequence))
(s-ref '(1 2 3) 1)
If you find yourself using this sort of thing often, it wouldn’t be too hard to write a require transformer that would expand to filtered-in:
#lang racket
(require (for-syntax racket/require-transform
syntax/parse)
racket/require)
(define-syntax reprefix-in
(make-require-transformer
(syntax-parser
[(_ original-prefix:id new-prefix:id require-spec:expr ...)
#:with replacer (string-append "^" (regexp-quote (symbol->string (syntax-e #'original-prefix))))
#:with replacement (symbol->string (syntax-e #'new-prefix))
(expand-import #'(filtered-in (λ (name) (regexp-replace (regexp 'replacer) name 'replacement))
(combine-in require-spec ...)))])))
Then you can use it like this:
(require (reprefix-in sequence- s- racket/sequence))
(s-ref '(1 2 3) 1)
Yes there is. To versing levels of cludgyness.
The way I highly recommend you do, however, is to use rename-in To rename each of these functions on import. So for example, your code would look like:
#lang racket
(require (rename-in racket/sequence
[sequence-length s-length]
[sequence-map s-map]
[sequence-filter s-filter]
...))
There are other more advanced ways to do this that do not require you to explicitly list out each identifier, using module->exports, regexp-match, format-id, and make-require-transformer. But this seems to brittle to me and you're better off being explicit about which names you want to rename.
So I am trying to get a grip on Emacs 24.5 running on Mac Os 10.10.4.
I have a German keyboard and decided to keep the alt -key as Meta. As I still have to use it for some essential characters such as [ , | and } (resembling alt-5, alt-6 and alt-9) it decided to go with this solution:
(global-set-key "\M-5" (lambda () (interactive) (insert “[“)))
(global-set-key "\M-6" (lambda () (interactive) (insert “]”)))
(global-set-key "\M-7" (lambda () (interactive) (insert “|”)))
...
When I am enabling electric pair mode in the init-file with (electric-pair-mode 1) , it works just fine with ( ) and " ", but not with [ ], { } and ' '.
I then tried a different appraoch by using this code to swap the keys:
(defun redefine-key (key char)
(define-key function-key-map key char)
(global-unset-key key))
(redefine-key "\M-5" "[")
(redefine-key "\M-6" "]")
...
Interestingly, the pair feature now works for the square brackets [ ], but not the curly ones { }. Although the ' key on the German keyboard is not even related to the alt-key (it's accessed by the shift-key), it doesn't work at all. Same results for the autopair package, btw.
Please, anyone? Thanks so much!
The way electric-pair-mode works is by installing a callback function ("hook") called electric-pair-post-self-insert-function. As the name suggests, this hook gets invoked by Emacs after the function self-insert-command runs -- which is after you type a key.
And that's your problem here: calling insert is not the same as typing a key. It does not invoke self-insert-command and consequently, the above hook function never gets called. Even worse, you cannot simply invoke self-insert-command programmatically because, unlike insert, it doesn't take a parameter for the character to insert. You have to jump through hoops a bit, but you could try the following:
(global-set-key "\M-5" (lambda (&optional N) (interactive "P") (insert-as-self ?\[ N)))
(global-set-key "\M-6" (lambda (&optional N) (interactive "P") (insert-as-self ?\] N)))
(global-set-key "\M-7" (lambda (&optional N) (interactive "P") (insert-as-self ?\| N)))
(defun insert-as-self (CHAR N)
(let ((last-command-event CHAR)
(repeat (if N N 1)))
(self-insert-command repeat)))
Here, we locally set the special variable last-command-event to "fake" a key stroke before calling self-insert-command.
For curly braces and quotes to work, you have to do two things: First, add the respective (global-set-key ...) definitions to your .emacs file, similar to the ones above. Then let electric-pair-mode know that you want quotes and curlies to be handled by it by adding the following line to your .emacs file:
(setq electric-pair-pairs '((?\' . ?\') (?\" . ?\") (?\{ . ?\}))) –
How do you write an elisp function, that should be bound to a key-press, that works without prompting by default, but when preceeded by Ctrl-u prompts the user for an argument. Something similar to (which is wrong syntax, but I hope you get the idea)?
(defun my-message (&optional (print-message "foo"))
(interactive "P")
(message print-message))
(global-set-key "\C-c\C-m" 'my-message)
The following use a feature of interactive that allows you to use code instead of a string. This code will only be executed when the function is called interactively (which makes this a different answer compared to the earlier answer). The code should evaluate to a list where the elements are mapped to the parameters.
(defun my-test (&optional arg)
(interactive (list (if current-prefix-arg
(read-from-minibuffer "MyPrompt: ")
nil)))
(if arg
(message arg)
(message "NO ARG")))
By using this method, this function can be called from code like (my-test) or (my-test "X") without it prompting the user for input. For most situations, you would like to design functions so that they only prompt for input when called interactively.
Following the same kind of implementation as your example, you could do something like this:
(defun my-message (&optional arg)
(interactive "P")
(let ((msg "foo"))
(when arg
(setq msg (read-from-minibuffer "Message: ")))
(message msg)))
If you just want to use the function as an interactive one, this code is all you need:
(defun my-message (&optional ask)
(interactive "P")
(message (if ask
(read-from-minibuffer "Message: ")
"foo")))