How do I configure Emacs to dedicate the Calculator window? - emacs

I'm using emacs 24.3 from emacsformacosx.com on OS X 10.9 (Mavericks). The behavior is the same on emacs 23.4.1 on Debian Wheezy.
I want to automate applying set-window-dedicated-p so switching/opening a buffer won't use certain windows. For example, if I'm in the Calculator and manually use Meta-: and enter (set-window-dedicated-p (get-buffer-window) t) then it works great - my Calculator window doesn't get hijacked by other buffers. I want it to work like that automatically.
I put this in my .emacs file:
(add-hook 'calc-mode-hook
(lambda ()
(message "Dedicating %s" (buffer-name))
(set-window-dedicated-p (get-buffer-window) t)
(message "Dedication %s" (window-dedicated-p (get-buffer-window "*Calculator*")))))
Then I start up emacs, switch to the *Messages* window, and Meta-x calc. The *Messages* buffer shows
Dedicating *Calculator*
Dedication t
so I know my hook was called and what buffer it operated on. But the *Calculator* buffer is not dedicated - it doesn't behave properly and Meta-: (window-dedicated-p) returns nil. The *Messages* buffer is dedicated instead.
Why is the *Calculator* window shown as dedicated in the hook but not afterwards? What am I doing wrong here?

Unfortunately the *Calculator* buffer is not displayed in any window at the point your code runs.
Your 'validation' messages were misleading you. (buffer-name) is certainly the buffer you want, but it's not in any window, and so you're actually passing a nil argument for the window in all situations. i.e. You're setting the current window dedicated, and then confirming that it's dedicated (which it should indeed be).
I think after advice to calc is what you need here. e.g.:
(defadvice calc (after my-dedicated-calc-window)
"Make the *Calculator* window dedicated."
(let ((win (get-buffer-window "*Calculator*")))
(when win
(set-window-dedicated-p win t))))
(ad-activate 'calc)
n.b. I'm not sure exactly how the arguments to calc affect the window display, but I think with the test for the window wrapping the call to set-window-dedicated-p this code is probably fine in all cases.

Related

Can emacs window be "partially" dedicated?

I'm using dedicated.el which is very similar to dedicate-windows-manually.el to manually mark certain windows as "dedicated" to their buffer and also inelegible for splitting by various commands that open new buffers (grep, compilation, etc.).
But I really only want the second part.
In other words, I want find-file, kill-buffer, switch-buffer and so on to work as if the current window was not dedicated. But I want other commands (grep, compile) to honor the dedicated status and not split that window.
I made a small attempt at this, but it doesn't work properly and seems like a misguided way to go about it, likely missing many cases.
(One of the problems is that the "dedicated" minor mode is associated with a buffer while set-window-dedicated-p applies to a window; this could be overcome, but I still feel there must be a better way to accomplish what I want...)
(defun with-undedicated (f)
(interactive)
(let ((was-dedicated (bound-and-true-p dedicated-mode)))
(progn
(if was-dedicated (dedicated-mode))
(command-execute f)
(if was-dedicated (dedicated-mode)))))
(defun undedicated-find-file ()
(interactive)
(with-undedicated 'ido-find-file))
(defun undedicated-kill-buffer ()
(interactive)
(with-undedicated 'ido-kill-buffer))
(defun undedicated-switch-buffer ()
(interactive)
(with-undedicated 'ido-switch-buffer))
(global-set-key (kbd "C-x C-f") 'undedicated-find-file)
(global-set-key (kbd "C-x k") 'undedicated-kill-buffer)
(global-set-key (kbd "C-x b") 'undedicated-switch-buffer)
edit
The following was performed to test Drew's answer:
(defun make-weak-dedicated ()
(interactive)
(set-window-dedicated-p (selected-window) "weak"))
(defun dedicated-status ()
(interactive)
(minibuffer-message "window-dedicated-p: %s" (window-dedicated-p (selected-window))))
Making the window "weak"ly dedicated does indeed do what I want: grep and other popup buffers do not replace the buffer in the weakly dedicated window. However, in that weakly dedicated window, find-file seems to reset window-dedicated-p to nil as tested by my dedicated-status function, so I still don't have a technique to prevent popup buffers from using or splitting a window and allowing find-file etc. to work as normal within that window.
clarification
Sorry for not being clear. Here's what I want to happen:
I mark a window as [weakly] dedicated (or whatever equivalent may exist)
I invoke grep, compilation, and so on, and they do not split that window nor replace the buffer in that window (instead splitting some other window that is not marked dedicated)
Within the weakly dedicated window, I invoke find-file, which replaces the buffer in the window but leaves the window weakly dedicated to the now changed buffer
It's that last bit that isn't working how I had hoped: after find-file, the window is no longer weakly dedicated (window-dedicated-p is nil). Since the property in question is associated with the window, I find it surprising that changing the buffer affected that window property, but so it is.
See the Elisp manual, node Dedicated Windows. If you use function set-window-dedicated-p to give a window a non-nil and non-t value then function set-window-buffer will respect it as a weakly dedicated window. That may be what you are looking for.

How to make emacs switch to *scheme* by default when eval / load from the file?

The problem:
I'm in scheme-mode (simple quack)
scheme is already running
eval expression
it sends the expression to scheme buffer
but! doesn't bring that buffer up in 2nd window = no immediate feedback
and I have to manually switch second buffer to scheme which is annoying
Some (more recent) modes like fsharp-mode or tuareg do that automatically. Tried to read quack.el, but didn't find convenient separate function like "pop scheme". It's tangled within run-scheme which also changes focus. Settings also don't help.
I want to stay in my rkt/scm file and see repl buffer pop up if not already popped. Like this simple build logic in sublime-text but with persistent repl.
Maybe I should try geiser, but quack is ok for now. Just missing few obvious conveniences.
Just rungeiser. It's in MELPA now, so it's a quick install.
You can also try lispy (which uses geiser) for in-place scheme eval.
e will eval current expression and display the result in the minibuffer.
E will eval current expression and insert the result in current buffer.
u is bound to undo, so you can either e or Eu if you prefer.
I ended up writing this:
(setq scheme-program-name "guile")
(defun run-scheme-2.0 ()
"Loads your chosen Scheme implementation for interactive development,
and displays that buffer below your main editing buffer, and makes sure that
your cursor will be on your code."
(interactive)
(if (not (get-buffer "*scheme*"))
(progn
(setq starting-buffer (buffer-name))
(run-scheme scheme-program-name)
(split-window-below)
(other-window 1)
(shrink-window-if-larger-than-buffer)
(other-window 1)
(switch-to-buffer starting-buffer))))
(add-hook 'scheme-mode-hook 'run-scheme-2.0)

Emacs shell-mode display is too wide after splitting window

If I run M-x shell in emacs to get a terminal, it knows where to wrap lines automatically. For example, the output of ls is formatted into columns that fit the window properly.
My problem is if I then split the window vertically with C-x 3, shell-mode still thinks the window fills the whole frame. The result is ugly wrapping of command output. Is there a way to let shell-mode know it has to update the screen width?
EDIT:
Using HN's answer below, I came up with this fix:
(defun my-resize-window ()
"Reset the COLUMNS environment variable to the current width of the window."
(interactive)
(let ((proc (get-buffer-process (current-buffer)))
(str (format "export COLUMNS=%s" (window-width))))
(funcall comint-input-sender proc str)))
(defun my-shell-mode-hook ()
(local-set-key "\C-cw" 'my-resize-window))
I'm a bit late to the party, but COLUMNS isn't the way to do this. Here is an excerpt from my .emacs:
(defun comint-fix-window-size ()
"Change process window size."
(when (derived-mode-p 'comint-mode)
(set-process-window-size (get-buffer-process (current-buffer))
(window-height)
(window-width))))
(defun my-shell-mode-hook ()
;; add this hook as buffer local, so it runs once per window.
(add-hook 'window-configuration-change-hook 'comint-fix-window-size nil t))
(add-hook 'shell-mode-hook 'my-shell-mode-hook)
Unlike exporting COLUMNS each time, this method doesn't require you to be in
bash at the moment and it doesn't spam your session with blank prompts. This
code should probably be in comint itself, maybe I will file a bug report.
EDIT: If you modify window-configuration-change-hook in a buffer-local-way
the hook runs once per window, as opposed once per frame.
Here is a slightly improved resize function from #Christopher Monsanto's answer. The original one will cause a problem due to nil process. (e.g exit in shell-mode)
(defun comint-fix-window-size ()
"Change process window size."
(when (derived-mode-p 'comint-mode)
(let ((process (get-buffer-process (current-buffer))))
(unless (eq nil process)
(set-process-window-size process (window-height) (window-width))))))
This display is dictated by the COLUMNS environment variable. In my setup COLUMNS has a value of 202, after a vertical split ls displays correctly on shell-mode if I set columns to 80 via
export COLUMNS=80
There must be a way to code this up but I don't have enough elisp-fu to do that. If you'd rather avoid the hassle multi-term manages this automagically.
http://www.emacswiki.org/emacs/MultiTerm
Try M-x eshell; it doesn't have this problem.

kill the associated buffer when close the emacs-client frame by pressing Alt+F4

I get used to emacsclient for the speedy response like vim, by putting emacs into sever mode with command "emacs --daemon". But I found it quite annoying that lots of buffers kept alive when I viewed some files and then closed them by pressing Alt+F4. I have to kill the buffer explicitly before closing the frame.
I want to know, if there is a way to make emacsclient behave more like a lightweight GUI editor(e.g. vim) in this point?
I think you're asking for trouble, but you you could try this:
(add-hook 'delete-frame-functions
(lambda (frame)
(let* ((window (frame-selected-window frame))
(buffer (and window (window-buffer window))))
(when (and buffer (buffer-file-name buffer))
(kill-buffer buffer)))))
I suggest that you use the command quit-window which does precisely what you want (with the prefix argument); it is already the binding for q in special-mode (i.e., not self-insert) buffers. You can bind it to, say, C-f4, and it will kill the buffer and the frame when you type C-u C-f4.
Do something like the following:
(defun my-kill-buffer-and-frame ()
"kill the current buffer and the current frame"
(interactive)
(when (y-or-n-p "Are you sure you wish to delete the current frame?")
(kill-buffer)
(delete-frame)))
If you're sure you always wnt to do it, you can get rid of the prompt:
(defun my-kill-buffer-and-frame ()
"kill the current buffer and the current frame"
(interactive)
(kill-buffer)
(delete-frame))
Then bind it to a key of your choice, like so:
(global-set-key [(f5)] 'my-kill-buffer-and-frame)
Enjoy!

how do i keep emacs server running when the current window is closed (x) on windows using emacsW32?

I'm using EmacsW32 (patched) on windows. Emacs is running in server mode so that subsequent calls to emacsclientw open files in the same server session.
I have C-x C-c mapped to make the current frame invisible and not kill the emacs server process. I'd like clicking the window's X (close) button to also just hide the frame & not terminate the server process as it currently does.
Any ideas ? Thanks!
Sure, I have a method of doing this. There may be refinements possible, but this is a good starting place.
First, I setup a variable and advise the kill-emacs function
(defvar bnb/really-kill-emacs nil)
(defadvice kill-emacs (around bnb/really-exit activate)
"Only kill emacs if the variable is true"
(if bnb/really-kill-emacs
ad-do-it)
(bnb/exit))
The bnb/exit function just makes the frame invisible like what you have bound to C-x C-c.
I then have an additional function to properly exit emacs if that is ever necessary. That will set the variable and call kill-emacs as follows.
(defun bnb/really-kill-emacs ()
(interactive)
(setq bnb/really-kill-emacs t)
(kill-emacs))