Pin Emacs buffers to windows (for cscope) - emacs

For my day job, I live in Emacs. Utterly. I also have become pretty dependent on CScope to help me find things in the code.
Normally, I have 2 windows in a split (C-x 3):
alt text http://bitthicket.com/files/emacs-2split.JPG
And I use the right window for code buffers and the left window for the CScope search buffer. When you do a CScope search and select a result, it automatically updates the right-side window to show the buffer referred to by the result. This is all well and good, except that it causes me to lose my place in some other buffer that I was studying. Sometimes this is no biggie, because [C-s u] gets me back to where I was.
What would be better, though, is to have 3 split windows like this ([C-x 2] in the left window):
alt text http://bitthicket.com/files/emacs-3split.jpg
And have the bottom left window contain the CScope search buffer, and the top left window be the only buffer that CScope ever updates. That way, I can see my CScope searches and navigate around the code without losing the buffer I'm focused on.
Anyone know how I can do that?

Put this in your .emacs file:
;; Toggle window dedication
(defun toggle-window-dedicated ()
"Toggle whether the current active window is dedicated or not"
(interactive)
(message
(if (let (window (get-buffer-window (current-buffer)))
(set-window-dedicated-p window
(not (window-dedicated-p window))))
"Window '%s' is dedicated"
"Window '%s' is normal")
(current-buffer)))
Then bind it to some key - I use the Pause key:
(global-set-key [pause] 'toggle-window-dedicated)
And then use it to "dedicate" the window you want locked. then cscope can only open files from its result window in some OTHER window. Works a charm. I specifically use it for exactly this purpose - keeping one source file always on screen, while using cscope in a second buffer/window, and looking at cscope results in a third.

Well, I decided to not be a reputation-whore and find the answer myself. I looked in cscope.el as shown on the Emacs wiki, as well as the xcscope.el that comes with the cscope RPM package on RHEL.
Neither appear to give a way to do what I'm wanting. The way is probably to edit the ELisp by adding a package variable like *browse-buffer* or something and just initialize that variable if not already initialized the first time the user does [C-c C-s g] or whatever, and always have the resulting code shown in *browse-buffer*. Then the user can put the *browse-buffer* wherever he wants it.

Related

Emacs sr-speedbar

I am currently trying to learn Emacs more in depth so that I can do more with my Emacs than just simple editing stuff...
I am making good progress and at the moment I am trying to configure the 'sr-speedbar' module to my liking, but some details I can't figure out myself:
Say that I've 2 open buffer windows A and B plus the speedbar window. If I open a file by pressing Enter in the speedbar window, then the new file always get opened in the same buffer window B (which I opened last). Can I somehow specify that the new content should be opened in buffer window A?
Currently the speedbar window refreshes itself automatically to the new location whenever I open a new file using 'C-x C-f'. This is actually pretty useful, but sometimes I don't want this when I am quickly trying things out in a tmp file. And the refresh also "destroys" my "tree-view" of the speedbar, where I expanded the directory contents rather than opening them directly. The question is, how can I suppress this "refreshing behaviour"? Can I somehow disable the automatic mode and trigger it manually if I need it?
And do you guys have more useful tips regarding speedbar navigation? How does a Emacs guru use speedbar or are there better alternatives?
Thx in advance for your help!
You can turn off the auto-refresh in your init file like this -
(require 'sr-speedbar)
(setq sr-speedbar-auto-refresh nil)
and/or turn it on and off later with the function sr-speedbar-refresh-toggle.
The defaults it (and speedbar) comes with are a bit odd though - it also doesn't show files that it doesn't recognize, uses images for buttons, and is set on the right side - so you can set these if you'd like -
(setq speedbar-show-unknown-files t) ; show all files
(setq speedbar-use-images nil) ; use text for buttons
(setq sr-speedbar-right-side nil) ; put on left side
I do use sr-speedbar for projects that have enough of a directory structure - otherwise I use the usual switch-to-buffer (C-x b), ibuffer (C-x C-b), and dired (C-x d), and another function that switches to the previous buffer. Also bound to single keys because they get used so much.
But... I'm still learning Emacs - I haven't tried helm, projectile, or project-explorer yet - they look interesting also.

How to control which window to be used for new contents in Emacs?

Often I have multiples windows carefully arranged within a frame.
However, certain command, say M-x man RET will grab one of the visible windows to display its own content. Sometimes this is annoying because the window that was taken away is one that I need to keep it visible.
e.g. I have 3 windows on screen, one useful source-code window and two useless windows. I want to keep the soure-code window visible while checking the man page. But very often Emacs just take away the code-window for the newly opened man page.
One way I can think of is to display the (chronological) open order of each window, so that I can focus point on n-th window and be confident that Emacs will grab (n+1)-th window for new content.
Is there a way to display such order, e.g. in the mode-line of each window?
Or is there another way for better control for displaying new window?
A little late to the party but as discussed in the comments, using dedicated windows is a good way to control where new content is displayed (+1 to #lawlist for bringing it up and to #phils for mentioning toggling!).
I'm pretty sure you'd be able to implement a command that toggles dedicatedness yourself at this point, but since I have the code for this handy I'll share it anyway:
(defun toggle-window-dedicated ()
"Control whether or not Emacs is allowed to display another
buffer in current window."
(interactive)
(message
(if (let (window (get-buffer-window (current-buffer)))
; set-window-dedicated-p returns FLAG that was passed as
; second argument, thus can be used as COND for if:
(set-window-dedicated-p window (not (window-dedicated-p window))))
"%s: Can't touch this!"
"%s is up for grabs.")
(current-buffer)))
(global-set-key (kbd "C-c d") 'toggle-window-dedicated)
Now, in a multi-window setup you can simply press C-c d in each window you would like to "protect".
I'll throw this example usage of display-buffer-alist into the mix, given that it was mentioned in the comments, and is indeed a general mechanism for controlling how and where buffers are displayed (even though, as Drew indicates, it is far from trivial).
Start with the help for the variable itself:
C-hv display-buffer-alist RET
From there you'll get to the help for display-buffer, and no doubt acquire some idea of the complexities involved :)
In any case, the following is an example of using a custom function to decide how to display buffers named *Buffer List*.
You can easily see that if you can write a function which can figure out how to display a buffer where you want it to, then you can use display-buffer-alist to make it happen.
(defun my-display-buffer-pop-up-same-width-window (buffer alist)
"A `display-buffer' ACTION forcing a vertical window split.
See `split-window-sensibly' and `display-buffer-pop-up-window'."
(let ((split-width-threshold nil)
(split-height-threshold 0))
(display-buffer-pop-up-window buffer alist)))
(add-to-list 'display-buffer-alist
'("\\*Buffer List\\*" my-display-buffer-pop-up-same-width-window))
A key quote regarding the ACTION functions is:
Each such FUNCTION should accept two arguments: the buffer to
display and an alist. Based on those arguments, it should
display the buffer and return the window.

Is there any way to get Ediff to not open its navigation interface in an external window?

Not being using Emacs all that long (v23, windows) and just discovered M-x ediff. Fantastic.
Although I'm not to keen on the fact it opens its help/navigation in a separate frame/window, meaning that if I lose focus to that window, the single key shortcuts don't work.
For example as soon as I press ? to expand the window, it shifts over top of my current window, so I have to pick up my mouse and move it to another screen. Then if I lose focus to that window and press p / n / j or any other key to work with the diff, it inserts it into my document. So i have to undo, grab mouse, focus to other window, and repeat.
Is there any way to configure these options to show in a split instead?
I didn't know how to do it but it is usually easy to learn with Emacs. First I asked about ediff customizations:
M-x customize-apropos
ediff
I saw there is something called Ediff Window Setup Function which takes the values Multi Frame, Single Frame, or Other Function. Mine was set to Multi Frame and changed it to Single Frame and saved it for future sessions. And Voila! as they say somewhere.
Simply:
(setq ediff-window-setup-function 'ediff-setup-windows-plain)
M-x describe-variable ediff-window-setup-function will enlighten you
further.
For reference my ediff customisation is fairly simple:
(if (locate-library "ediff")
(progn
(autoload 'ediff-files "ediff")
(autoload 'ediff-buffers "ediff")
(eval-after-load "ediff" '(progn
(message "doing ediff customisation")
(setq diff-switches "-u"
ediff-custom-diff-options "-U3"
ediff-split-window-function 'split-window-horizontally
ediff-window-setup-function 'ediff-setup-windows-plain)
(add-hook 'ediff-startup-hook 'ediff-toggle-wide-display)
(add-hook 'ediff-cleanup-hook 'ediff-toggle-wide-display)
(add-hook 'ediff-suspend-hook 'ediff-toggle-wide-display)))))
From chapter Window and Frame Configuration in Ediff User's Manual:
The following variable controls how
windows are set up:
ediff-window-setup-function
The multiframe setup is done by the ediff-setup-windows-multiframe
function, which is the default on
windowing displays. The plain setup,
one where all windows are always in
one frame, is done by
ediff-setup-windows-plain, which is
the default on a non-windowing display
(or in an xterm window). In fact,
under Emacs, you can switch freely
between these two setups by executing
the command ediff-toggle-multiframe
using the Minibuffer of the Menubar.
(custom-set-variables
...
'(ediff-window-setup-function (quote ediff-setup-windows-plain))
...)
Not that you would set the variable this way, but it allows you to know these things:
The variable you are interested in is ediff-window-setup-function
The value it needs to be set to is ediff-setup-windows-plain
You can configure the variable from customize: M-x customize-group RET ediff-window
Ediff Window Setup Function: Menu Single Frame
Note: you can avoid using the mouse to go back to the ediff control window by using M-x other-frame. Also found on C-x 5 o.
This no longer works in 2017 gnu emacs (24.5, 25.2, 2017) on windows
(setq ediff-window-setup-function 'ediff-setup-windows-plain) ; stopped working
Even
ediff-toggle-multiframe ; no longer has any effect now.
It works in emacs22.3 on windows, so I have use older emacs from 2008!

How do I close an automatically opened window in Emacs?

This is probably a very naive Emacs question - I'm new to it.
When I'm evaluating a lisp expression, if there's an error the debugger automatically comes up in another window. If I have *scratch* and *info* open (the former for trying out lisp and the latter for reading about it), then the debugger opens up in the window that *info* was in. At the moment, I have to switch to that window, then change it back to *info*, before returning to *scratch*. (The same thing happens if I do C-x C-b for a list of buffers.) I'm guessing there has to be a way to just close that window without this long sequence of commands. Can anyone enlighten me?
At least here on my emacs (22.3), when the debugger pops up, its window becomes the active one. There, pressing q just quits the debugger, if that's what you want. At that point, it also gets out of recursive editing.
From what I understand, you want to close the buffer in the other window without moving your cursor from the current window.
I don't any existing function does that, so I rolled my own.
(defun other-window-kill-buffer ()
"Kill the buffer in the other window"
(interactive)
;; Window selection is used because point goes to a different window
;; if more than 2 windows are present
(let ((win-curr (selected-window))
(win-other (next-window)))
(select-window win-other)
(kill-this-buffer)
(select-window win-curr)))
You can bind it to something like "C-x K" or some other somewhat difficult-to-press key so you won't press it by mistake.
(global-set-key (kbd "C-x K") 'other-window-kill-buffer)
I use this a LOT! (for Help buffers, Compilation buffers, Grep buffers, and just plain old buffers I want to close now, without moving the point)
I'm usually using the delete-other-windows command. C-x 1.
It's so regullar, that I rebinded to F4.
Official docs: https://www.gnu.org/software/emacs/manual/html_node/emacs/Change-Window.html#Change-Window
HTH
Using winner mode, you can use the keybinding C-C left arrow to return to the previous window configuration. Of course, this doesn't actually kill the new buffer, but it does hide it.
I think you're looking for C-x 4 C-o, which displays a buffer in the "other" window without switching to it.
As mentioned above, in the case of the backtrace buffer you probably want to exit from it with q, to get out of the recursive edit.
Try to use popwin-mode. It is really good about closing windows automatically.
I want to describe how mechanism work|
You open undo-tree-visualize than you find your correct branch, after that when you change your active window which has cursor via switch-window undo-tree related buffer will close other window automatically.
One possible solution is to use a window management package. Store your "preferred" window arrangement, and after the debugger/buffer window pops up and you're done with it, revert to your preferred arrangement.
There are a bunch of packages to choose from, see: switching window configurations on the wiki.
Additionally, you might want to figure out the actions you commonly do that trigger the extra (unwanted) window popping up, and use that to trigger saving your window configuration just before the window pops up.
If you want to roll your own (it's pretty easy), you can just save off the window configuration, and restore it like so:
(setq the-window-configuration-i-want (current-window-configuration))
(global-set-key (kbd "<f7>")
(lambda () (interactive)
(set-window-configuration the-window-configuration-i-want)))
The trick is figuring out where to put the setting of the-window-configuration-i-want.
Thanks go to #spk for a nice function. I merely modified it to also close the window too and bound it to the already nice set of window control functions found in evil-windows (via "C-w"):
(use-package evil
:bind (:map evil-window-map ("O" . delete-most-recent-window))
:preface
(defun delete-most-recent-window ()
"Kill the buffer in the most recent window."
(interactive)
;; Window selection is used because point goes to a different window
;; if more than 2 windows are present
(let ((win-curr (selected-window))
(win-other (next-window)))
(select-window win-other)
(kill-this-buffer)
(delete-window) ; <-- Added this
(select-window win-curr))))

How to remove directory window and add a cscope window in Emacs ECB?

Yesterday I installed ECB on my Emacs, and I find method window and history window quite useful. But directory tree window and source window less useful, if I can hide them I will save more space for method window and history.
Another problem is that I use cscope to search through the project for definitions and callers, the result of cscope is shown by splitting the main window into two. I'd like to know is it possible to make cscope result window fixed in ECB window, just like method window and history window?
Many thanks.
===============
Thanks to sanityinc and ecb documents, finally I create a layout with cscope fixed in it. I'll post code here in case it will help others.
(require 'ecb)
(ecb-layout-define "my-cscope-layout" left nil
(ecb-set-methods-buffer)
(ecb-split-ver 0.5 t)
(other-window 1)
(ecb-set-history-buffer)
(ecb-split-ver 0.25 t)
(other-window 1)
(ecb-set-cscope-buffer))
(defecb-window-dedicator ecb-set-cscope-buffer " *ECB cscope-buf*"
(switch-to-buffer "*cscope*"))
(setq ecb-layout-name "my-cscope-layout")
;; Disable buckets so that history buffer can display more entries
(setq ecb-history-make-buckets 'never)
There are a bunch of layout presets, listed here, one of which might work for you. Also, you can create a custom layout following the directions here, which can even be done interactively using the ecb-create-new-layout command.
The latter page also describes how to add a new fixed window, of the type you want for cscope.