12

If I run M-x shell in emacs to get a terminal, it knows where to wrap lines automatically. For example, the output of ls is formatted into columns that fit the window properly.

My problem is if I then split the window vertically with C-x 3, shell-mode still thinks the window fills the whole frame. The result is ugly wrapping of command output. Is there a way to let shell-mode know it has to update the screen width?

EDIT:

Using HN's answer below, I came up with this fix:

(defun my-resize-window ()
  "Reset the COLUMNS environment variable to the current width of the window."
  (interactive)
  (let ((proc (get-buffer-process (current-buffer)))
        (str (format "export COLUMNS=%s" (window-width))))
    (funcall comint-input-sender proc str)))

(defun my-shell-mode-hook ()
  (local-set-key "\C-cw" 'my-resize-window))
Tyler
  • 9,872
  • 2
  • 33
  • 57

4 Answers4

14

I'm a bit late to the party, but COLUMNS isn't the way to do this. Here is an excerpt from my .emacs:

(defun comint-fix-window-size ()
  "Change process window size."
  (when (derived-mode-p 'comint-mode)
    (set-process-window-size (get-buffer-process (current-buffer))
                         (window-height)
                         (window-width))))

(defun my-shell-mode-hook ()
  ;; add this hook as buffer local, so it runs once per window.
  (add-hook 'window-configuration-change-hook 'comint-fix-window-size nil t))

(add-hook 'shell-mode-hook 'my-shell-mode-hook)

Unlike exporting COLUMNS each time, this method doesn't require you to be in bash at the moment and it doesn't spam your session with blank prompts. This code should probably be in comint itself, maybe I will file a bug report.

EDIT: If you modify window-configuration-change-hook in a buffer-local-way the hook runs once per window, as opposed once per frame.

event_jr
  • 17,467
  • 4
  • 47
  • 62
  • This is a really useful fix. Please do submit as a bug report! –  Feb 07 '13 at 15:32
  • 1
    Thanks for the useful function, however it will cause problems when the process is nil, so I added a nil check before set process window size - [see my answer](http://stackoverflow.com/a/20015336/554279) – Rangi Lin Nov 16 '13 at 06:04
6

Here is a slightly improved resize function from @Christopher Monsanto's answer. The original one will cause a problem due to nil process. (e.g exit in shell-mode)

(defun comint-fix-window-size ()
  "Change process window size."
  (when (derived-mode-p 'comint-mode)
    (let ((process (get-buffer-process (current-buffer))))
      (unless (eq nil process)
        (set-process-window-size process (window-height) (window-width))))))
Rangi Lin
  • 9,303
  • 6
  • 45
  • 71
2

This display is dictated by the COLUMNS environment variable. In my setup COLUMNS has a value of 202, after a vertical split ls displays correctly on shell-mode if I set columns to 80 via

export COLUMNS=80

There must be a way to code this up but I don't have enough elisp-fu to do that. If you'd rather avoid the hassle multi-term manages this automagically.

http://www.emacswiki.org/emacs/MultiTerm

carrutherji
  • 1,115
  • 10
  • 18
1

Try M-x eshell; it doesn't have this problem.

Teddy
  • 6,013
  • 3
  • 26
  • 38