0

I have very practically zero experience with elisp but after reading the intro to programming that comes with emacs and trying out things I was able to put together a function that will evaluate a shell command with a file buffer's content and append the result to another buffer.

The command is running wolframscript on some bits of source code but that is really immaterial to my problem, which is that I have been unable to make the output buffer redisplay in its window so that its end is in the middle. What happens is every time I execute the script, the output is correctly appended to the output buffer but the output buffer does not recenter.

Can anyone see what am I doing wrong (or not doing) and help me out here? I've tried for a couple days, incl. reading up on the window vs buffer point and how it works but I am clearly missing something. Below is my code:

(defun wolframscript-on-buffer-file () "Run a shell command on the current buffer's file and append output to a buffer." (interactive) (let* ((file-name (buffer-file-name))) (if (null file-name) (message "Current buffer is not visiting a file.") (let* ((file-buffer (current-buffer)) (command "/usr/local/bin/wolframscript -file") (output-buffer-name (concat "*" command "*")) (output-buffer (get-buffer-create output-buffer-name))) (with-current-buffer output-buffer ;; Make the buffer writable so we can append (setq buffer-read-only nil) ;; Move to the end of the buffer, and insert a header line. (goto-char (point-max)) (insert "\n--- New Command Output ---\n") (let ((process-environment (copy-sequence process-environment))) (setenv "EMACS_PWD" (file-name-directory file-name)) (call-process-shell-command (concat command " " (shell-quote-argument file-name)) nil (current-buffer) nil)) (goto-char (point-max)) ;; tried here first, not working: (setq buffer-read-only t) (pop-to-buffer (current-buffer)) ;; also tried (recenter -1), not working (recenter 0)) (pop-to-buffer file-buffer) (with-current-buffer output-buffer (setq buffer-read-only t)))))) 
2
  • 2
    Simplify your problem/question to a minimum - get rid of all that's extraneous. If the problem is just about displaying some text in a buffer with the window scrolled a certain way, then just start with a buffer, insert some text, or whatever. E.g., if using the shell to get the text to put in the buffer is irrelevant to your problem/question then get rid of that, etc. As it stands now, it's not even clear what you're asking. Commented Aug 20 at 19:59
  • 1
    Thanks for your comment, agree the reproducing example should have been minimal. Provided in my solution below. Commented Aug 23 at 19:59

2 Answers 2

0

I think you could calculate the center line and put your cursor there, then recenter. So something like this:

(defun center-buffer-vertically () "Centers the entire buffer by lines" (interactive) (let* ((start (point-min)) (end (point-max)) (total-lines (count-lines start end)) (middle-line (floor (/ total-lines 2)))) (goto-line middle-line) (recenter-top-bottom))) 
1
  • Thanks for your suggestion. It turned out to be simpler (looked like window had to be selected for recenter to work). Commented Aug 23 at 20:00
0

Here is a working example of how text can be appended to a buffer followed by recentering the buffer in its window such that the least line is in the middle. How the text to be appended is irrelevant—the example below uses a string it makes but it could really come from anywhere, e.g., the output of a shell command, etc.

(defun append-to-buffer-and-recenter () "Appends text to a buffer, displays the buffer without selecting its window, then recenters the window to show the last appended line in the middle." (interactive) (let ((output-buffer (get-buffer-create "**test buffer**"))) (with-current-buffer output-buffer ;; make buffer mutable (setq buffer-read-only nil) (goto-char (point-max)) (insert (format "---- %s ----\nappended this line after %d others\n\n" (format-time-string "%Y-%m-%d %H:%M:%S") (count-lines (point-min) (point-max)))) ;; make buffer read-only (setq buffer-read-only t) ;; capture the window that is created (let ((output-window (display-buffer output-buffer '((display-buffer-pop-up-window))))) ;; then use with-selected-window to make it current for calling recenter (with-selected-window output-window (goto-char (point-max)) (recenter)))))) 

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.