How can I put DISPLAY name in frame-title of GNU EMACS - emacs

I use GNU EMACS on multiple monitors from a Windoze PC via VNC.
(Currently 5 - 4 big, 1 the small monitor on my tablet PC. Two vertical 1200x1920, two horizontal 1920x1200, plus the small.)
The way I am currently doing this is to run a separate VNC on each monitor. I then open a single emacs, and use make-frame-other-display to open emacs' frames in the other VNC window.
To make things more complicated - I run the VNCs on an up-to-date Ubuntu system, but I run the emacs on a quite out of date machine where the rest of the build tools live. I.e. the VNC displays are not local to the same machine as emacs.
Rather than xhost+, I open an xterm in each of the VNCs, and ssh to the machine running emacs. This creates DISPLAYS of the form localhost:16.0. I then use make-frame-on-display using these localhost DISPLAYs.
This gets confusing.
It helps if I leave an "echo $DISPLAY" in the xterm windows. Or chamnge the xterm's title.
I'd like to similarly change the EMACS' frames' titles, to reflect what each frame things is its current DISPLAY. But doing
(defvar frame-title-specific-ag "emacs"
"title element from frame-title-format that is specific to a particular emacs instance; andy glew")
(setq frame-title-format
(list
"frame=%F "
(format "%s" frame-title-specific-ag)
" " 'system-name
" DISPLAY="
(getenv "DISPLAY")
" %b"
" " (format "pid:%d" (emacs-pid))
" user:"(user-login-name))
)
only gets the DISPLAY variable for the entire emacs.
Q: is there a way to find out the display associated with any particular frame?

To get the display name for the current frame, use
(frame-parameter nil 'display)
or replace nil with a specific frame to get the name of its display instead of the current one. For example, use this to show the display in the title:
(setq frame-title-format
'("DISPLAY=" (:eval (frame-parameter nil 'display))))
Note that it is important that this form is completely quoted, so the list that is used has an :eval which tells Emacs to run the code whenever it renders a frame title. Without that, you might be tempted to write something like:
(setq frame-title-format
(list "DISPLAY=" (frame-parameter nil 'display)))
but this doesn't work. The problem is that the function call happens immediately when this form is evaluated, and the result is a list holding a particular string, which is the name of whatever frame was in effect this evaluation happened, and the string will not change magically.

Eli Barzilay pointed us to
(frame-parameter nil 'display)
which is 90% of the way there.
The following puts the display associated with the currently selected frame in its frame title.
(setq frame-title-format
'(
"DISPLAY="
(:eval (frame-parameter nil 'display))
)
)
Glew: This puts the display of the currently selected frame, at the time the frame is created
(e.g. via make-frame-on-display) in the
title. Since this may be a different frame, in a completely different
display, it is not always what is wanted.
The unquoted, un-:eval'ed, form, puts the display of the currently selected frame,
at the time the setq is evaluated, in the title. This is even less of what is wanted.
Here is what I ended up with:
I set the default frame-title-format as above. But I do bnot really use it because I
hook the following:
(defun ag-set-frame-title (frame)
"set frame-title to glew preference, optional arg FRAME / default nil (currently selected frame)"
(interactive)
;; TBD: make-variable-frame-local is deprecated in more recent versions of emacs
;; than the antiquated version at my work. use modify-frame-parameters instead
(let (x)
(setq x
(concat
(or frame-title-specific-ag "emacs")
" " system-name
" DISPLAY=" (frame-parameter frame 'display)
" " (format "pid:%d" (emacs-pid))
" user:" (user-login-name)
;;" " (buffer-name)
)
)
(modify-frame-parameters frame (list (cons 'title x)))
)
)
;; TBD: this old emacs does not have modern hooks
(setq after-make-frame-functions '(ag-set-frame-title))
For good measure:
(defun ag-fix-frame-titles ()
"run ag-set-frame-title on frame-lits"
(interactive)
(mapc 'ag-set-frame-title (frame-list))
)
(ag-fix-frame-titles)
NOTE: per comment string it is possible that the fix described here is only needed on an old version of emacs, such as 21.4.1. #EliBarzilay says not needed on whatever version of emacs he is using.
Subtract points all you want, folks. Truth.

Related

How to make `C-x b RET` switch to previous buffer even if it's already shown in another frame?

Edit: What the poster calls a "window", Emacs calls a "frame". I fixed the title.
Concisely, the question is: in a window, how do I switch quickly to a buffer previously visited in that window, even if it's already opened in another window?
A more detailed description follows.
Normally, in order to switch window to previous buffer one just types C-x b RET. That is, the default argument to switch-to-buffer (or ido-switch-buffer) is the previous buffer.
This is not, however, the case when that (previous) buffer is already shown in another window. That's exactly what bugs me.
Let's consider an example. Suppose I have three buffers (A, B and C) and two windows showing buffers A and B (C is not visible at this point).
Then I open buffer A in the second window, too. So, now I have buffer A shown in both windows. Then I switch (C-x b RET) to B again. After that, C-x b RET will bring me not to A, but to C because A is already shown in the other window.
How do I make C-x b RET behave more consistently?
Update
After this problem had been solved, I realized I needed more: namely, for point position to be remembered per-window, not per buffer. Luckily, there're ready-made solutions:
winpoint
per-window-point
They're quite similar; for a discussion of differences see here.
I've found a fix for switch-to-buffer. It eventually calls
(other-buffer (current-buffer))
while in order to fix your problem, the call needs to look like this:
(other-buffer (current-buffer) t)
i.e. the visible-ok argument needs to be t.
Here's an advice to have it always at t. Hopefully it won't break other stuff that uses other-buffer:
(defadvice other-buffer (around fix-switch-to-buffer
(&optional buffer visible-ok frame) activate)
(setq visible-ok t)
ad-do-it)
Note that ido-switch-to-buffer uses a different machinery, so a different method is needed to fix it.
update: fix for ido-switch-to-buffer
I needed to re-define ido-make-buffer-list:
(defun ido-make-buffer-list (default)
(let* ((ido-current-buffers (list (buffer-name (current-buffer))))
(ido-temp-list (ido-make-buffer-list-1 (selected-frame) ido-current-buffers)))
(if ido-temp-list
(nconc ido-temp-list ido-current-buffers)
(setq ido-temp-list ido-current-buffers))
(if default
(setq ido-temp-list
(cons default (delete default ido-temp-list))))
(if (bound-and-true-p ido-enable-virtual-buffers)
(ido-add-virtual-buffers-to-list))
(run-hooks 'ido-make-buffer-list-hook)
ido-temp-list))
The diff is just one line, but it's too messy to advice it.
update: use new advice system for other-buffer
The old stuff should still work for quite a while, but here's the new approach:
(defun other-buffer-advice (orig-fun &optional buffer visible-ok frame)
(funcall orig-fun buffer t frame))
(advice-add 'other-buffer :around #'other-buffer-advice)
;; (advice-remove 'other-buffer :around #'other-buffer-advice)
Instead of advising the built-in function other-buffer, you can pre-select visible buffers using a package.
1 Using Ivy
If you're using Ivy, you can use abo-abo's approach to override the lower-use function ivy-switch-buffer.
(defun user/ivy-switch-buffer ()
"Switch to another buffer with visible-ok preselection."
(interactive)
(ivy-read "Switch to buffer: " #'internal-complete-buffer
:keymap ivy-switch-buffer-map
:preselect (buffer-name (other-buffer (current-buffer) t))
:action #'ivy--switch-buffer-action
:matcher #'ivy--switch-buffer-matcher
:caller 'ivy-switch-buffer))
(advice-add 'ivy-switch-buffer :override #'user/ivy-switch-buffer)
2 Using Ido mode
2.1 Switching to a buffer shown in another frame
If by "window" you really mean "frame" (i.e., you'd like to ido-switch-buffer to a buffer that is currently shown in another frame), then ido-mode gives you the behavior you're looking for when you change ido-default-buffer-method from its default value of raise-frame to selected-window:
(setq ido-default-buffer-method 'selected-window)
Emacs constructs an independent buffer list for each frame, so the only thing you have to do is to configure Ido to avoid jumping to another frame when you switch buffers.
2.2 Switching to a buffer that is shown in another window inside the same frame
To get this behavior across windows within the same frame, you should hook a function that reorders the buffer list onto ido-make-buffer-list-hook.
From ido.el:
;; Changing the list of files
;; --------------------------
;; By default, the list of current files is most recent first,
;; oldest last, with the exception that the files visible in the
;; current frame are put at the end of the list. A hook exists to
;; allow other functions to order the list. For example, if you add:
;;
;; (add-hook 'ido-make-buffer-list-hook 'ido-summary-buffers-to-end)
;;
;; then all files matching "Summary" are moved to the end of the
;; list. (I find this handy for keeping the INBOX Summary and so on
;; out of the way.) It also moves files matching "output\*$" to the
;; end of the list (these are created by AUCTeX when compiling.)
;; Other functions could be made available which alter the list of
;; matching files (either deleting or rearranging elements.)

Truncation in Emacs Powerline (mode line)

Is there a way to get some elements truncated in the (excellent) Emacs Powerline? I'm thinking, in particular, at the which-func-mode section in the default mode line. It'd be good to see only the first N characters of a function name or section name (when in Org mode), N to be defined.
A side question is: can we simply get components being disabled (that is, not displayed) if the frame is too narrow (80 chars wide, for example)?
Generally you can customize which-func-format accordingly, e.g.:
(setq which-func-format
`("["
(:propertize (:eval (my-which-func-current))
local-map ,which-func-keymap
face which-func
mouse-face mode-line-highlight
help-echo "mouse-1: go to beginning\n\
mouse-2: toggle rest visibility\n\
mouse-3: go to end")
"]")
)
Where my-which-func-current is a function that truncates the current function name accordingly:
(defun my-which-func-current ()
(let ((current (gethash (selected-window) which-func-table)))
(if current
(truncate-string-to-width current 20 nil nil "…")
which-func-unknown)))
This approach works with the standard mode line, and with any mode line extension package that supports standard mode line data. I know that Smart Mode Line does, but I am not sure of Powerline. I don't use either of these packages.

How to fixate value on the right side of the modeline?

Is there a way to position a value on the the right end of the modeline?
From my understanding currently the modeline "pushes" its values farther right if the values increase in size. I would prefer it if some values would start on the right side and expand into the middle.
I have tried solutions like powerline, but they seem rather distracting and more complicated in setup to display the same amount of informatioon as the standard modeline.
Here is one way to do it. The trick is to add spaces until the end of the line minus the place needed to display your text (extracted from powerline code on the emacs wiki):
(defun mode-line-fill (face reserve)
"Return empty space using FACE and leaving RESERVE space on the right."
(unless reserve
(setq reserve 20))
(when (and window-system (eq 'right (get-scroll-bar-mode)))
(setq reserve (- reserve 3)))
(propertize " "
'display `((space :align-to (- (+ right right-fringe right-margin) ,reserve)))
'face face))
;; Set the modeline to tell me the filename, hostname, etc..
(setq-default mode-line-format (list
" "
mode-line-mule-info
'mode-line-modified
"- "
'mode-line-buffer-identification
" (%l, %c) "
'mode-line-modes
" -- "
`(vc-mode vc-mode)
;; Fill until the end of line but 10 characters
(mode-line-fill 'mode-line 10)
"Some text"
)
)
As far as I'm aware, that isn't possible to do through straightforward customization of the ordinary mode line. You can modify the mode-line-format variable to alter its appearance and contents to some degree, but as far as built-in constructs for text alignment are concerned, I'm fairly certain that you're limited to controlling the width of mode line components via either padding or truncation. It might be feasible to employ some clever hackery within the mode-line-format variable (using the (:eval ...) and/or (list ...) forms) to achieve the desired result, however. You could consult the Emacs Lisp Reference Manual page on the mode-line-format variable for details. Beyond that, you'd have to use some third-party packages.

Rearranging Windows Within Emacs?

Emacs tends to open two horizontally separated windows, one on top of the other (I think windows is the proper emacs term). Since I am working with a wide screen I find it easier and better to work with two vertically separated windows, arranged side by side within the emacs frame.
I know how to open a new vertically separated window using C-x 3 but how do you rearrange windows that emacs opens itself (for example when M-x compile is invoked opening a compilation/debugging window) from horizontal to vertical?
I had the same problem, this is what I currently use. Just drop it into your Emacs init file:
;; The default behaviour of `display-buffer' is to always create a new
;; window. As I normally use a large display sporting a number of
;; side-by-side windows, this is a bit obnoxious.
;;
;; The code below will make Emacs reuse existing windows, with the
;; exception that if have a single window open in a large display, it
;; will be split horisontally.
(setq pop-up-windows nil)
(defun my-display-buffer-function (buf not-this-window)
(if (and (not pop-up-frames)
(one-window-p)
(or not-this-window
(not (eq (window-buffer (selected-window)) buf)))
(> (frame-width) 162))
(split-window-horizontally))
;; Note: Some modules sets `pop-up-windows' to t before calling
;; `display-buffer' -- Why, oh, why!
(let ((display-buffer-function nil)
(pop-up-windows nil))
(display-buffer buf not-this-window)))
(setq display-buffer-function 'my-display-buffer-function)
Take a look at the split-height-threshold and the split-height-threshold variables, both customizable.
For further information on what values they take, C-h f split-window-sensibly RET. This Emacs Lisp touches the topic superficially.
This affects how display-buffer works, which probably compile and many other commands use.
Here's my solution:
(defun split-window-prefer-side-by-side (&optional window)
(let ((split-height-threshold (and (< (window-width window)
split-width-threshold)
split-height-threshold)))
(split-window-sensibly window)))
(setq split-window-preferred-function 'split-window-prefer-side-by-side)
This still consults split-*-threshold variable values, just prefers side-by-side windows when both splitting directions are acceptable.

how to put elscreen tabs on the top only?

I'm using elscreen in my GNU Emacs 24.2.1
Currently, when i split my window, I have a same tab panel in each half:
elscreen http://i.zlowiki.ru/121101_0f30ebba.png/800
Note that the two lower windows have the same tabs as the largest one.
How can I remove these two duplicates, and keep only the top one?
If it is too hard, what another alternative could be used for GNU screen?
Here's something to technically do what you asked:
(setq elscreen-display-tab nil) ; disable tabs display
;; get-alist was removed somewhere along the line
;; You can try substituting all instances of get-alist with assoc-default
;; instead of using defalias and see if that works; I haven't tried.
(defalias 'get-alist 'assoc-default) ; get-alist is gone
;; Put tabs display in your frame title bar instead.
(defun elscreen-frame-title-update ()
(when (elscreen-screen-modified-p 'elscreen-frame-title-update)
(let* ((screen-list (sort (elscreen-get-screen-list) '<))
(screen-to-name-alist (elscreen-get-screen-to-name-alist))
(title (concat "| " (mapconcat
(lambda (screen)
(format "%d%s %s |"
screen (elscreen-status-label screen)
(get-alist screen screen-to-name-alist)))
screen-list " "))))
(if (fboundp 'set-frame-name)
(set-frame-name title)
(setq frame-title-format title)))))
(eval-after-load "elscreen"
'(add-hook 'elscreen-screen-update-hook 'elscreen-frame-title-update))
I'm sure it's not what you had in mind, but hey, it's at the VERY top now and only at the top.
Take a look at http://www.emacswiki.org/emacs/ElscreenSeparateBufferLists modifies the operation of elscreen slightly borrowing from escreen. It allows the list of tabs to differ on each buffer.
How about using elscreen-tab plugin?
This plugins is created to resolve what you are annoyed with.
You can install via melpa.