How to force Emacs display of `*Messages*` window - emacs

I'm printing a message like this
(interactive "P")
(message "test")
If the Messages buffer is not visible in the frame, it should appear as a split window. I've seen some softwares do this (maybe tramp) not sure how to do this.
I already read http://www.gnu.org/software/emacs/manual/html_node/elisp/Displaying-Messages.html

I think this works
(defun my-kbd-x-hook (&optional use-generic-p)
"Curl call"
(interactive "P")
(message "hi")
(switch-to-buffer-other-window "*Messages"))

Related

Emacs shell-mode: Prevent RET sending input from anywhere

As the documentation says that RET will comint-send-input anywhere in a shell mode. The issue is that if you by mistake hit enter on any line and you are not at a prompt it will execute the whole random text until the next prompt. How can I prevent this from happening? It would be nice if hitting Enter anywhere out of the prompt will send you to a new prompt at the bottom.
Something like this?
(defun my-comint-send-input-maybe ()
"Only `comint-send-input' when point is after the latest prompt.
Otherwise move to the end of the buffer."
(interactive)
(let ((proc (get-buffer-process (current-buffer))))
(if (and proc (>= (point) (marker-position (process-mark proc))))
(comint-send-input)
(goto-char (point-max)))))
(with-eval-after-load "comint"
(define-key shell-mode-map [remap comint-send-input] 'my-comint-send-input-maybe))
You could replace (goto-char (point-max)) with (comint-copy-old-input) to insert but not send the old input at the new prompt; but that's still liable to cause problems when the inserted input looks like output.
However, also note the comments and link in C-hf comint-send-input regarding comint-get-old-input -- this can be used to implement custom logic for establishing what the "old input" should be when comint-send-input is invoked with point before the process mark.
Bulletproof:
(defun comint-send-input-or-insert-previous-input ()
"Call `comint-send-input' if point is after the process output marker.
Otherwise, move point to the process mark and try to insert a previous input
from `comint-input-ring' (if any) returned by `comint-previous-input-string'
and affected by the current value of `comint-input-ring-index'.
Implementation is synthesized from and inspired by the `comint-after-pmark-p',
`comint-goto-process-mark', and `comint-copy-old-input' functions."
(interactive)
(let ((process (get-buffer-process (current-buffer))))
(if (not process)
(user-error "Current buffer has no process")
(let ((pmark (process-mark process)))
(if (<= (marker-position pmark) (point))
(comint-send-input)
(goto-char pmark)
(when (and (eolp) comint-input-ring)
(let ((input (comint-previous-input-string 0)))
(when (char-or-string-p input)
(insert input)))))))))

Highlight a name throughout an Emacs buffer

I am starting to learn Emacs Lisp, and as a first project I would like to improve the fortran mode in Emacs. I would like to mark the name of a sub routine in the buffer, and then press a shortcut key. To bring up a buffer with all lines in the given source where the name of the subroutine is mentioned.
I found that I can get the marked text using:
(defun get-selected-text (beg end)
(interactive
(if (use-region-p)
(list (region-beginning) (region-end))
(list nil nil)))
(message "%s" (if (and beg end)
(buffer-substring-no-properties beg end) "")))
and can store the line numbers of the subroutines using:
(defun get-line-numbers (str)
(interactive "sEnter string: ")
(save-excursion
(goto-char 0)
(let (( sok 1) (list nil) pp)
(while sok
(setq pp (search-forward str nil t))
(if pp (push (line-number-at-pos pp) list)
(setq sok nil)))
(message "%s" list))))
I would now like to open a new buffer similar to when I use Ctrl-x Ctrl-b to execute list-buffers and then display each line number, together with the text on the line, and the user can select a given line, and press Enter to goto the given line in the original buffer..
Just wanted to show you my version of occur-dwim.
I remember spending some time to find out about the regexp-history variable.
The first function is similar to your get-selected-text.
(defun region-str-or-symbol ()
"Return the contents of region or current symbol."
(if (region-active-p)
(buffer-substring-no-properties
(region-beginning)
(region-end))
(thing-at-point 'symbol)))
(defun occur-dwim ()
"Call `occur' with a sane default."
(interactive)
(push (region-str-or-symbol) regexp-history)
(call-interactively 'occur))
To display the list-buffer you use get-buffer-create and clear it with erase-buffer (it might be that it already extisted).
To output the lines you search in the current buffer save the line in a string and put it into the list buffer via with-current-buffer and insert.
To make return special on the text or to make it clickable put a text-property with a local keymap on it.
With this guide you should be able to find everything you need in the elisp-manual.
Regarding your code, you get the beginning and end of the current region with (interactive "r"). Therewith you also get the error message if there is no active region.

In Emacs, how can I open a buffer/file in "ibuffer/dired mode" in another frame?

When I am working with multiple frames, I want to decide in which frame Emacs should open files/buffers.
You can't do that out of the box.
There are find-buffer-other-frame and the like but they open a new frame.
What you can do is write your own function like this:
(defun find-file-in-frame ()
(interactive)
(call-interactively 'select-frame-by-name)
(call-interactively 'find-file))
This switches frame and then asks for the file, if you want to do it otherwise you have to do more work.
Edit: Here the version that asks in the current frame and opens the file in the other window:
(defun find-file-in-frame (noselect)
(interactive "P")
(let ((current-frame (selected-frame))
(frame (completing-read "Frame: " (make-frame-names-alist)))
(buffer (save-window-excursion
(call-interactively 'find-file))))
(select-frame-set-input-focus (assoc-default frame
(make-frame-names-alist)
nil current-frame))
(switch-to-buffer buffer)
(when noselect
(select-frame-set-input-focus current-frame))))
If you are just referring to find-file, then I would suggest that with the combination of windmove and framemove, switching to the frame in which you wish to open the file is so trivial and fast that you probably don't need anything fancier.
OTOH if you want to be able to select a frame whenever a file is to be opened by any means, this obviously doesn't apply.
Not sure what you're really asking. But as to opening a file from Dired in another frame, just use C-o or M-mouse-2 in Dired+. Those are bound to these commands, in case you do not want to load Dired+ for some reason:
(defun diredp-find-file-other-frame () ; Bound to `C-o'
"In Dired, visit this file or directory in another frame."
(interactive)
(find-file-other-frame (file-name-sans-versions (dired-get-filename nil t) t)))
(defun diredp-mouse-find-file-other-frame (event) ; Bound to `M-mouse-2'
"In Dired, visit file or directory clicked on in another frame."
(interactive "e")
(let ((pop-up-frames t)) (dired-mouse-find-file-other-window event)))

Clickable text in emacs minibuffer

How can I put clickable text in emacs minibuffer?
For example, this code makes clickable text in a text buffer and it works fine for me.
(let ((map (make-sparse-keymap)))
(define-key map (kbd "<down-mouse-1>")
'(lambda() (interactive) (message-box "it works!")))
(add-text-properties 1 5 `(keymap, map
mouse-face highlight)))
However, similar code for minibuffer doesn't work correctly
[...]
(with-current-buffer (window-buffer (minibuffer-window))
(message "link")
(add-text-properties (point-at-bol) (point-at-eol)
`(keymap, map
mouse-face highlight))))
As a result a text is put in a minibuffer without these properties.
I also tried (propertize but result is same.
[...]
(message (propertize "link"
'mouse-face 'highlight
'keymap map)))
What's wrong with this?
Thanks
message writes to the echo area, not the minibuffer.
The minibuffer is not active. Even if you use insert instead of message you will not see the text there.
What is it that you are really trying to do? What is the context where you want to insert such propertized text in the minibuffer? The minibuffer is active when, e.g., input is being read. You can initiate reading and insert the text there when it is active.

Select the previously-selected window in emacs

I need an emacs built-in function or elisp function that can take me to the previously-selected window. I thought that (select-window (get-lru-window)) would do it, but if I run it several times, seems to just cycle between windows instead of swapping back and forth between them, which is what I expect.
Any other ideas?
There doesn't seem to be a way to get the most recently selected window in emacs (as opposed to the least recently used returned by get-lru-window). Internally emacs tracks use_time on windows, and get-lru-window uses that to find the "oldest" window. But unfortunately that is not exposed in elisp.
The window list is ordered in cyclic window ordering which doesn't help in your case.
The buffer-list is however ordered most-to-least recently used buffer (or not really strictly, there is a (bury-buffer) function to move a buffer last).
This means that, if you can transform your problem into something like "how can I switch to the buffer in a different window that was most recently the selected buffer", it should be possible.
One way would be to do something like this:
(defun switch-to-previous-buffer-in-a-different-window ()
(interactive)
(let* ((otherbuf (other-buffer (current-buffer) t))
(otherwin (get-buffer-window otherbuf)))
(if otherwin
(select-window otherwin)
(message "Last buffer (%s) is not currently visible" (buffer-name otherbuf)))))
Or the shorter, and more featureful:
(defun switch-to-previous-buffer-possibly-creating-new-window ()
(interactive)
(pop-to-buffer (other-buffer (current-buffer) t)))
Here other-buffer is used to get the most recently used buffer (except current-buffer). This should work fine as long as you don't switch buffers in the windows, because then other-buffer will no longer return the buffer in the other window, but the buffer you switched from in current window.
So instead of using other-buffer lets walk the buffer-list ourself to find the best candidate:
(defun switch-to-the-window-that-displays-the-most-recently-selected-buffer ()
(interactive)
(let* ((buflist (buffer-list (selected-frame))) ; get buffer list in this frames ordered
(buflist (delq (current-buffer) buflist)) ; if there are multiple windows showing same buffer.
(winlist (mapcar 'get-buffer-window buflist)) ; buf->win
(winlist (delq nil winlist)) ; remove non displayed windows
(winlist (delq (selected-window) winlist))) ; remove current-window
(if winlist
(select-window (car winlist))
(message "Couldn't find a suitable window to switch to"))))
Hope this helps.
If the last window switch was done programmatically, then it is possible to select the previously selected window.
(defun your-function ()
(interactive)
(let ((sw (selected-window)))
(do-something-useful-and-switch-window)
(select-window sw)))
If the last window switch was done manually, then it should be possible to overload the window switching command to update a global list of window selection order, which is then used to switch back.
(defun gs/pop-to-previous-window ()
(interactive)
(let ((win (get-mru-window t t t)))
(select-window win)))