I want to set the outline-minor-mode for init.el file and when TAB key is pressed on the lines starting with ; the function outline-toggle-children should be called in order to fold and expand the sub headings.
Below is the code for hook. But it does not work for the "TAB" key binding as expected.
(add-hook 'emacs-lisp-mode-hook
(lambda ()
(if (equal (buffer-name) "init.el")
(progn
(outline-regexp "^;+")
(outline-minor-mode 1)
(local-set-key (kbd "TAB") ; this does not work
(lambda ()
(if (string-match outline-regexp (thing-at-point 'line))
(outline-toggle-children))))))))
I presume that the error you get is wrong-type-argument commandp. This happens because functions bound to keys must be "interactive" functions. You need to add an (interactive) declaration to the function, so that Emacs knows how to invoke the function in response to an event:
(lambda ()
(interactive)
(if (string-match outline-regexp (thing-at-point 'line))
(outline-toggle-children)))
Related
I am writing some bindings to lambdas in my ~/.emacs and would like to have a description of what the function does appear when I do (for example) C-c ?. I tried to put a string immediately after lambda () but that still does nothing. How do I get something relevant to appear in the binding column?
Example that still functionally works but documentation doesn't:
(global-set-key (kbd "M-p") (lambda ()
"Moves the current line up by one"
(interactive)
(let ((col (current-column)))
(transpose-lines 1)
(forward-line -2)
(forward-char col))))
You should use defun to define your interactive function and bind to that.
(defun my-func ()
"Moves the current line up by one"
(interactive)
(let ((col (current-column)))
(transpose-lines 1)
(forward-line -2)
(forward-char col)))
(global-set-key (kbd "M-p") 'my-func)
I'd like to make a simple change to Emacs so that the next-buffer and previous-buffer commands (which I have bound to C-x <RIGHT> and C-x <LEFT> will skip over the *Messages* buffer.
I'm using Emacs 24 and the Emacs Starter Kit.
I've read the following related questions and answers, but they are not what I want:
Buffer cycling in Emacs: avoiding scratch and Messages buffer
Emacs disable *Messages* buffer
Emacs Lisp Buffer out of focus function?
Here are some of the reasons why they don't work:
I'd like to keep it as simple as possible. Fewer configuration changes are better.
I don't want to kill or prevent *Messages* altogether.
(add-to-list 'ido-ignore-buffers "^\*Messages\*" helps with my C-x b (ido-switch-buffer) but does not change how next-buffer and previous-buffer behave.
This way you can avoid the infinite loop:
(defun next-code-buffer ()
(interactive)
(let (( bread-crumb (buffer-name) ))
(next-buffer)
(while
(and
(string-match-p "^\*" (buffer-name))
(not ( equal bread-crumb (buffer-name) )) )
(next-buffer))))
(global-set-key [remap next-buffer] 'next-code-buffer)
This code loops over non-starred buffers ("^\*"). For your case (only avoid *Messages*) it would be:
(defun next-code-buffer ()
(interactive)
(let (( bread-crumb (buffer-name) ))
(next-buffer)
(while
(and
(equal "*Messages*" (buffer-name))
(not ( equal bread-crumb (buffer-name) )) )
(next-buffer))))
(global-set-key [remap next-buffer] 'next-code-buffer)
You can write previous-code-buffer just replacing every next-buffer with previous-buffer.
The simplest I can think of is defining an advice for both functions. Here it is for next-buffer. Similarly would be for previous-buffer. You can also define a configuration variable to enable/disable the behavior (or activating/deactivating the advice):
(defadvice next-buffer (after avoid-messages-buffer-in-next-buffer)
"Advice around `next-buffer' to avoid going into the *Messages* buffer."
(when (string= "*Messages*" (buffer-name))
(next-buffer)))
;; activate the advice
(ad-activate 'next-buffer)
Maybe you can compare buffers in some other way instead of its string name, but that will work. The code for previous buffer is almost the same. I don't know either if there is a way of calling the original function without triggering the advice once inside the advice itself, but again, the code will work even if the name of the buffer is tested afterwards (will fail if you just have one buffer, and it is the messages buffer; some code can check if there is just one buffer and don't call next-buffer again).
If you want to use a standalone function that does the same thing:
(defun my-next-buffer ()
"next-buffer, only skip *Messages*"
(interactive)
(next-buffer)
(when (string= "*Messages*" (buffer-name))
(next-buffer)))
(global-set-key [remap next-buffer] 'my-next-buffer)
(global-set-key [remap previous-buffer] 'my-next-buffer)
This is what I'm using, based on Diego's answer:
(setq skippable-buffers '("*Messages*" "*scratch*" "*Help*"))
(defun my-next-buffer ()
"next-buffer that skips certain buffers"
(interactive)
(next-buffer)
(while (member (buffer-name) skippable-buffers)
(next-buffer)))
(defun my-previous-buffer ()
"previous-buffer that skips certain buffers"
(interactive)
(previous-buffer)
(while (member (buffer-name) skippable-buffers)
(previous-buffer)))
(global-set-key [remap next-buffer] 'my-next-buffer)
(global-set-key [remap previous-buffer] 'my-previous-buffer)
It is not great yet, because it will hang if there are no buffers other than the skippable-buffers I list. I use C-g to break out of the loop when it happens as a hackaround.
As RubenCaro's answer points out, the other answers can enter infinite loops. I thought David James' approach of a skippable buffers list was a bit nicer, though, so here's a variant of that.
(setq my-skippable-buffers '("*Messages*" "*scratch*" "*Help*"))
(defun my-change-buffer (change-buffer)
"Call CHANGE-BUFFER until current buffer is not in `my-skippable-buffers'."
(let ((initial (current-buffer)))
(funcall change-buffer)
(let ((first-change (current-buffer)))
(catch 'loop
(while (member (buffer-name) my-skippable-buffers)
(funcall change-buffer)
(when (eq (current-buffer) first-change)
(switch-to-buffer initial)
(throw 'loop t)))))))
(defun my-next-buffer ()
"`next-buffer' that skips `my-skippable-buffers'."
(interactive)
(my-change-buffer 'next-buffer))
(defun my-previous-buffer ()
"`previous-buffer' that skips `my-skippable-buffers'."
(interactive)
(my-change-buffer 'previous-buffer))
(global-set-key [remap next-buffer] 'my-next-buffer)
(global-set-key [remap previous-buffer] 'my-previous-buffer)
I have various things set up in my 'before-save-hook. For example, I run 'delete-trailing-whitespace. This is what I want in almost all occasions.
But sometimes, I'm working on files that are shared with other people, and the file already has a bunch of trailing whitespace. If I save the file, I'll get a big diff that's pretty confusing, as my change is buried in dozens or hundreds of meaningless changes. Yes, everyone could just tell their diff tool to not show whitespace changes, but that's something that everyone has to do every time they look at the diff. I'd rather not even have the whitespace change.
Is there anything I can do to save the file without the whitespace changes, short of starting a new instance of Emacs with no init.el file, or with a modified init.el that doesn't have the hook?
Here is how I save without triggering delete-trailing-whitespace:
C-x C-q C-x C-s C-x C-q: read-only, save, revert read-only
A simpler solution I came up with is that my fundamental-mode has no hooks installed, because I want it to be as plain as possible. Thus if I want to save a file without running hooks, I temporarily switch to fundamental-mode.
Based on a comment discussion with #Stefan, here are two possible (untested) solutions:
Use let:
(defun save-buffer-without-dtw ()
(interactive)
(let ((b (current-buffer))) ; memorize the buffer
(with-temp-buffer ; new temp buffer to bind the global value of before-save-hook
(let ((before-save-hook (remove 'delete-trailing-whitespace before-save-hook)))
(with-current-buffer b ; go back to the current buffer, before-save-hook is now buffer-local
(let ((before-save-hook (remove 'delete-trailing-whitespace before-save-hook)))
(save-buffer)))))))
Use unwind-protect:
(defun save-buffer-without-dtw ()
(interactive)
(let ((restore-global
(memq 'delete-trailing-whitespace (default-value before-save-hook)))
(restore-local
(and (local-variable-p 'before-save-hook)
(memq 'delete-trailing-whitespace before-save-hook))))
(unwind-protect
(progn
(when restore-global
(remove-hook 'before-save-hook 'delete-trailing-whitespace))
(when restore-local
(remove-hook 'before-save-hook 'delete-trailing-whitespace t))
(save-buffer))
(when restore-global
(add-hook 'before-save-hook 'delete-trailing-whitespace))
(when restore-local
(add-hook 'before-save-hook 'delete-trailing-whitespace nil t)))))
The problem with the second solution is that the order of functions in the before-save-hook may change.
Here's another solution:
(defvar my-inhibit-dtw nil)
(defun my-delete-trailing-whitespace ()
(unless my-inhibit-dtw (delete-trailing-whitespace)))
(add-hook 'before-save-hook 'my-delete-trailing-whitespace)
and then
(defun my-inhibit-dtw ()
(interactive)
(set (make-local-variable 'my-inhibit-dtw) t))
so you can M-x my-inhibit-dtw RET in the buffers where you don't want to trim whitespace.
I wrote a command inspired by Nicholas Douma's solution.
(defun olav-save-buffer-as-is ()
"Save file \"as is\", that is in read-only-mode."
(interactive)
(if buffer-read-only
(save-buffer)
(read-only-mode 1)
(save-buffer)
(read-only-mode 0)))
What we need to do is remove 'delete-trailing-whitespace from before-save-hook, save the buffer, then add it back.
This code will do that, but only remove and add it if it's there to begin with.
;; save the buffer, removing and readding the 'delete-trailing-whitespace function
;; to 'before-save-hook if it's there
(defun save-buffer-no-delete-trailing-whitespace ()
(interactive)
(let ((normally-should-delete-trailing-whitespace (memq 'delete-trailing-whitespace before-save-hook)))
(when normally-should-delete-trailing-whitespace
(remove-hook 'before-save-hook 'delete-trailing-whitespace))
(save-buffer)
(when normally-should-delete-trailing-whitespace
(add-hook 'before-save-hook 'delete-trailing-whitespace))))
(global-set-key (kbd "C-c C-s") 'save-buffer-no-delete-trailing-whitespace)
It also binds the command to (kbd C-c C-s), for convenience.
I am trying to uniquely identify a window,
so that I can select and delete the window if I press a key over again, though I am having trouble doing this.
(setq split-window-right-toggle-var nil)
(defun split-window-right-toggle ()
(interactive)
(if split-window-right-toggle-var
(progn
(right-split-undo)
(setq split-window-right-toggle-var nil))
(progn
(right-split-do)
(setq split-window-right-toggle-var t))))
(defun right-split-do ()
(interactive)
(split-window-right)
(other-window 1))
(defun right-split-undo ()
(interactive)
(other-window -1)
(delete-window))
The issue with this code is that it heavily depends on which window is active, there for can
change the state of my windows and delete the wrong window, can I uniquely give my window a name then target that window name for deletion ? I am really new at Emacs lisp and would appreciate any help thanks.
You can try out something like this:
(setq window-names (make-hash-table :test 'equal ))
(defun name-window ()
(interactive)
(let ((name (read-input "Name: ")))
(setf (gethash name window-names) (selected-window))))
(defun del-window ()
(interactive)
(let ((name (read-input "Name: ")))
(delete-window (gethash name window-names))))
(selected-window) returns a reference to the current window.
(next-window) returns the next window. Use Emacs' self documenting features
to find out more or refer to the manual.
Here is how I would write your command
(defvar ej-spit-window-saved nil)
(defun ej-split-window-right-toggle ()
"toggle split right"
(interactive)
(setq ej-split-window-saved
(if (and ej-split-window-saved
(frame-visible-p (window-frame ej-split-window-saved)))
(delete-window ej-split-window-saved)
(split-window-right))))
Notes
prefix functions/variables for easier debugging.
it's never too early to document code.
I wrote this below to get to search for the next period in tex mode. It works fine except trying to get it to move forward a char after it finds the period. I am not sure how to do this but here was my attempt.
(add-hook 'text-mode-hook (lambda ()
(local-set-key (kbd "s-p")
(lambda () (interactive) ((search-backward "." nil t) (forward-char))))))
Final solution I combined the functions from ajk solution. I couldn't get the other one working without the add-hook. Someone might know how to get the second one working. The below completely works and searches backward for the previous period unless it is currently at a period.
(add-hook 'text-mode-hook
(lambda ()
(local-set-key (kbd "s-p")
(lambda ()
(interactive)
(if (looking-back "\.")
(backward-char))
(search-backward "." nil t)
(forward-char)))))
Thanks for the help.
You have parentheses around the last two function calls in the anonymous function you're assigning to the key, causing Emacs Lisp to think you want to call a function named (search-backward "." nil t). Try
(add-hook 'text-mode-hook
(lambda ()
(local-set-key (kbd "s-p")
(lambda ()
(interactive)
(search-backward "." nil t)
(forward-char)))))
The problem I would have with this binding is it's not repeatable. If you run it a second time, it finds the same period you just found. You might want to check to see if the previous character is a period and if so, skip it. Also, you can simplify it a bit by using define-key to add the binding explicitly to the text-mode keymap:
(define-key text-mode-map (kbd "s-p")
(lambda ()
(interactive)
(if (looking-back "\.")
(backward-char))
(search-backward "." nil t)
(forward-char)))