zsh completion will not work in emacs shell

Solution 1:

You can't use shell completion inside M-x shell. Emacs sends the input to the shell one line at a time when you press RET. When you press TAB, it's Emacs's built-in completion that's triggered. In shell mode, Emacs tries to keep track of your current directory and completes file names, but that's all.

Depending on what program you're interacting with, shell mode can be nice (because you get all of Emacs's edition features instead of whatever limited capabilities the shell or other program provides) or not so nice (because you don't get whatever nifty capabilities the shell or other program provides. When running zsh, you're in the latter category. Inside Emacs, you can run M-x term to run a more complete terminal emulator inside Emacs, where you interact directly with the underlying program. You gain some, but you also lose some: Term mode's scrollback capabilities are poor.

You can switch between Term mode and Shell mode in the same buffer. You must start the buffer in Term mode, then you can use these functions to toggle between the two. (Note: I didn't write these functions originally, it was contributed to the Emacs Wiki and I have not tracked down the source. I have slightly adapted it; warning: I haven't tested this code.)

(defun term-switch-to-shell-mode ()
  (interactive)
  (shell-mode)
  (set-process-filter
   (get-buffer-process (current-buffer)) 'comint-output-filter )
  (compilation-shell-minor-mode 1)
  (comint-send-input))
(defun shell-switch-to-term-mode ()
  (compilation-shell-minor-mode -1)
  (font-lock-mode -1)
  (set-process-filter
   (get-buffer-process (current-buffer)) 'term-emulate-terminal)
  (term-mode)
  (term-char-mode)
  (term-send-raw-string (kbd "C-l")))

Solution 2:

Try MultiTerm. Its the only Emacs terminal mode that seems to play nice with zsh.

With 'M-x shell' mode you can't use zle (the cool zsh tab completion stuff).

With 'M-x term' (and ansi-term), the terminal captures most of the emacs C- and M- commands that you want routed to emacs.

MultiTerm allows you to easily set which commands you want captured by emacs and which you want routed to the terminal. It comes preloaded with defaults that work very well.

One more tip: Add the following to your .zshrc to allow emacs to track your current directory as you cd around.

if [ -n "$INSIDE_EMACS" ]; then
  chpwd() { print -P "\033AnSiTc %d" }
  print -P "\033AnSiTu %n"
  print -P "\033AnSiTc %d"
fi

Solution 3:

This is a complex problem. Let's look at what really happens behind the sense.

According to Emacs Doc, <Tab> is bound to function completion-at-point. Here is what completion-at-point does:

Perform completion on the text around point.

The completion method is determined by `completion-at-point-functions'.

Check Emacs Doc, the variable completion-at-point-functions goes here:

completion-at-point-functions is a variable defined in `minibuffer.el'.

Its value is (comint-completion-at-point t)

Local in buffer shell; global value is

(tags-completion-at-point-function)

Then let's check out document of comint-completion-at-point

comint-completion-at-point is an alias for icicle-comint-dynamic-complete' inob-sh.el'.

(comint-completion-at-point)

Dynamically perform completion at point.

Calls the functions in `comint-dynamic-complete-functions', but with

Icicles functions substituted, to perform completion until a function

returns non-nil. Return that value.

So it's clear that you need to add your favourite complete functions to comint-dynamic-complete-functions variable.

      (add-to-list 'comint-dynamic-complete-functions 'icicle-shell-dynamic-complete-filename)
      (add-to-list 'comint-dynamic-complete-functions 'icicle-shell-dynamic-complete-command)