I have a problem explaining what I need, and this is why I can't find it (probably), but I'll try my best.
I need one line of text on top of modeline, kind of a footer in the buffer. It is for displaying help, so with-electric-help gets very close to it except that there's an issue with focus (I can move focus back to the original window, but the key bindings will be of the help buffer - not good).
Ideally it would be just a line of text which stays on top of modeline (doesn't scroll with the buffer).
My issues with creating just a separate buffer: I don't know how to find out that the user removed focus from the buffer which was previously showing the "small buffer", so I don't know when to hide it.
The header line sounds like it would do what you want. It's basically the same as the mode line, except almost nothing uses it and it appears at the top of the window.
(setq header-line-format "some text")
or even fancier, you can eval things on the fly and set faces:
(setq header-line-format '(:eval (propertize (format "%d" (buffer-size)) 'face 'modeline-inactive)))
Related
I am trying to set the line height of text in an Emacs buffer so there is space above and below the letters. From the documentation, I infer that the line-height text property may help me to accomplish this.
There is also a line-spacing variable which I can set like (setq-default line-spacing 0.25). This kind of works, except it does not produce space before text, only after it. I don’t like the way this looks when using modes like show-paren-mode, since it “dips” down:
Undesired current behavior (“hanging”)
Desired behavior mockup (vertically-centered)
I'd like to vertically-center the text.
I have discovered that I can temporarily get the effect I want with the following code:
(add-text-properties (point-min) (point-max)
'(line-spacing 0.25 line-height 1.25))
However, in some modes the properties go away in regions where I start typing. How do I make that top and bottom spacing the default? (Hooks won't work.)
Update
TLDR: I've succumbed to the fact that you can't really reliably achieve this natively with Emacs. You need to patch the font itself to include extra spacing. So, I created this script to take care of that.
Old/Incomplete Answer
TLDR: Add this somewhere in init file:
;; Set the padding between lines
(defvar line-padding 3)
(defun add-line-padding ()
"Add extra padding between lines"
; remove padding overlays if they already exist
(let ((overlays (overlays-at (point-min))))
(while overlays
(let ((overlay (car overlays)))
(if (overlay-get overlay 'is-padding-overlay)
(delete-overlay overlay)))
(setq overlays (cdr overlays))))
; add a new padding overlay
(let ((padding-overlay (make-overlay (point-min) (point-max))))
(overlay-put padding-overlay 'is-padding-overlay t)
(overlay-put padding-overlay 'line-spacing (* .1 line-padding))
(overlay-put padding-overlay 'line-height (+ 1 (* .1 line-padding))))
(setq mark-active nil))
(add-hook 'buffer-list-update-hook 'add-line-padding)
Increase or decrease the line-padding value to your liking.
This answer pretty much just summarizes the information in the above question, answer, and comments, so I suggest reading those first.
I use an overlay instead of text properties because it behaves more nicely when adding new text to the buffer (especially via copy/paste).
The buffer-list-update-hook is used as a means of identifying when a new buffer has been created and thus would need to have the overlay applied.
For performance reasons, to not continuously add overlays, the existing padding overlay is deleted if it aleady existed.
As the doc says, line-height is a text (or an overlay) property. It is not a variable.
Try (setq-default line-spacing 20).
line-spacing is a frame parameter or a buffer-local variable. Its value can be an integer number of pixels or a floating-point number specifying spacing relative to the frame's default line height. The doc says nothing about giving it a list value, such as (32 64).
And if you are using Emacs in terminal mode then none of this applies. As the doc says about that:
On text terminals, the line spacing cannot be altered.
Try "Help => More Manuals => Emacs Lisp Reference" and from there type i text properties RET. This will hopefully clarify the situation. As for your specific request, I don't think there's a simple way to get what you want right now. You might like to M-x report-emacs-bug about the display appearence of the paren-highlighting.
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.
this is my first question, so apologies for breaking any rules.
I've just started writing some functions in elisp to help me navigate certain types of text files more efficiently. To make these accessible, I've added some buttons to the tool-bar. As it's now becoming busy, I'd like to either: 1) move some of these additional buttons to a second line; or 2) instantiate a second tool-bar that could be placed somewhere else in the frame (either under the existing tool-bar, or perhaps vertically along the side where the scrollbar is).
I've searched high and low but am unable to find an existing example of this and, as I don't yet really know what I'm doing, I wonder if somebody has a code snippet from which I might start to hack a solution together.
Many thanks in advance.
System: CentOS 5/6, emacs for linux 23.1
Edit:
Thanks for the comment, William. Here's a simple example representing what my tool-bar code might do:
;
; functions used by the toolbar
;
;
(defun copy-paste-whole-line ()
"copies and pastes the whole of the current into a new line underneath"
(interactive)
(beginning-of-line)
(set-mark (point))
(end-of-line)
(setq temp (buffer-substring (region-beginning) (region-end)))
(message " copying: %s" temp )
(newline)
(insert temp))
;
;
; population of the toolbar:
;
;
(when (find-image '((:type xpm :file "copy_paste_line.xpm")))
(unless tool-bar-mode (tool-bar-mode 1))
; (setq tool-bar-map (make-sparse-keymap)) ; <- uncomment this line to have only this button present
(tool-bar-add-item
"copy_paste_line"
'copy-paste-whole-line
'copy-paste-whole-line
:help "copies and pastes the whole of the current line into a new line underneath"))
so, as you can see (actually, I'm not allowed to post images until I have 10 reputation points, so you won't be able to see), the code adds an extra button to the end of the existing tool-bar buttons. I believe this to be a reasonable way to achieve this, but I'm not an experienced elisp programmer, so if you think it's poorly written, please comment - I'd like to understand why... :)
If I only had 1 button, it would be ok like that, however, I have multiple buttons. I would, thus, like to add them to a second instance of a similar tool-bar (or, perhaps a vertical one placed where the scrollbars are).
Thanks again for any input.
Frame parameter tool-bar-lines is supposed to control this. You can, for instance, customize option default-frames-alist if you want to change the number of tool-bar rows to 2 or 3 everywhere. Or you can do this on a mode-by-mode or frame-by-frame basis. You can, for instance, use M-: (set-frame-parameter nil 'tool-bar-lines 3).
Depending on your platform (and toolkit), the behavior might be variable. See the Elisp manual, node Layout Parameters and node Tool Bars.
I believe you are out of luck. It seems to me that (at least on ubuntu and cygwin) only one row of buttons in the tool-bar is supported.
Here is what I have tried without luck on both systems:
(progn
(set-frame-parameter nil 'tool-bar-lines 3)
(loop for i from 1 upto 20 do
(setcdr tool-bar-map (cons (cadr tool-bar-map) (cdr tool-bar-map)))))
The following picture shows what I get:
The other buttons appear in a pull-down menu if you click on the little triangle at the right end of the toolbar:
You can restore the old tool-bar with the following commands:
(progn
(setq tool-bar-map (make-sparse-keymap))
(tool-bar-setup))
Finally, I have 3 rows of buttons. This is possible with emacs-w32:
So it is the gtk+ / nextstep problem.
It is possible to "scroll past the end of the buffer" in a window. This is useful because Emacs has to somehow use the extra space when the buffer does not fill the whole area available to the window used to display it.
However sometimes when the whole buffer would fit completely into the window the top part still isn't displayed and more space than necessary is wasted below the buffer content to fill the available space. It would be better if the window were automatically scrolled to show the complete buffer or if it is bigger than the window as much as possible.
In other words the only time when a window displays something "below the buffer end" is when the window is to big.
Is there a mode or option to do that?
Edit: So something like this?
(add-hook 'post-command-hook 'my-eob-recenter)
(defun my-eob-recenter ()
(when (pos-visible-in-window-p (point-max))
(save-excursion
(goto-char (point-max))
(recenter -1))))
Original answer:
If you have a window which is larger than its contents and you want to shrink it to fit, there's a binding for that.
C-x- runs shrink-window-if-larger-than-buffer
Personally I suspect this would be annoying if it happened automatically, but you might try this:
(defadvice split-window (after my-split-window-shrink)
"Shrink the selected window after a window split
if it is larger than its contents."
(shrink-window-if-larger-than-buffer))
(ad-activate 'split-window)
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.