Emacs remote shell - shell

I tend to run my shell in emacs, but when I use it to ssh into another computer this breaks tab-completion. Is there a way to fix this?

Try:
M-x cd /hostname:/current/path/in/the/shell
That should set up ange-ftp (or tramp), and then TAB completion for paths should work properly for that shell - until you log into a different machine.
You could set up a comint process filter to recognize when you type ssh to do that for you automatically, but that's difficult to get right as it should revert when you exit the ssh session, but not be tricked by other uses of exit.
For an automated solution, I'd suggest augmenting the approach I personally use to keep Emacs synchronized with the current working directory of the shell buffer. Just add an an extra bit of information with the hostname, and use that to set the hostname and path like shown above.

in another thread, someone mentioned eshell which I've never used but I tried it with SSH and all sorts of nice integration is happening. Time to learn eshell.

You could try M-x ansi-term to host your shell if your getting unexpected behavior with key mappings. Having said that I couldn't re-produce the problem your describing on your set-up.

I had a similar problem I think and solved it by editing my ~/.bash_login on the remove machine and append
export TERM=xterm
I use OS X and had problems when connecting to a Linux (Debian Lenny)

I just wrote a little function to open a shell on a remote host. The cd call before shell gets the tab completion working.
This may be different than you want, since it opens a new shell instead of ssh'ing in a local shell. Beyond that, you could look into hacking emacs Directory Tracking (or see who else has).
(defun remote-shell (&optional host)
"Open a remote shell to a host."
(interactive)
(with-temp-buffer
(let ((host (if host host (read-string "Host: "))))
(cd (concat "/scp:" host ":"))
(shell (concat "*" host "*")))))
(defun myserver-shell () (interactive) (remote-shell "myserver"))

M-x shell invoked in buffer A will switch to a shell buffer B; usually shell. Unsurprisingly it creates B if necessary. A prefix arg will cause it to ask for the name of B. If A is viewing something on a remote host then the shell will be run on the remote host. But only if it can't find an existing B. At that point file name completion will work.
There are some notes about how to tinker with this in the emacs wiki. See for example the function my-shell in this section, which will extend the default name for B so remote files get remote shells. I do that same thing by advising the shell function.
The filename auto completion will work fine. Command autocomplete? Less so. For me it blocks emacs and then doesn't actually work.

I use dired to access the remote machine and open a shell there.
Here is the function I use, taken and modified from Tikhon Jelviss' emacs configuration:
(defun anr-shell (buffer)
"Opens a new shell buffer where the given buffer is located."
(interactive "sBuffer: ")
(pop-to-buffer (concat "*" buffer "*"))
(unless (eq major-mode 'shell-mode)
(dired buffer)
(shell buffer)
(sleep-for 0 200)
(delete-region (point-min) (point-max))
(comint-simple-send (get-buffer-process (current-buffer))
(concat "export PS1=\"\033[33m" buffer "\033[0m:\033[35m\\W\033[0m>\""))))
Example:
(anr-shell "/vagrant#localhost#2222:/vagrant/")

Related

How do I handle password prompts when calling elisp from the terminal

I'm trying to use elisp as a shell script language. I'm writing a script where I need access to a file encrypted with gpg. I'm not sure how to handle the password prompt. In the examples below, he program is called from the command line (bash).
First try:
#!/usr/bin/emacs --script
(setq passwd-file "~/password.gpg")
(save-excursion
(let ((passwd-buffer (find-file passwd-file)))
(switch-to-buffer passwd-buffer)
(princ (buffer-substring 1 30))))
This lets me enter the password in the terminal, but the password is shown in plaintext.
Second try
#!/usr/bin/emacs --script
(setq passwd-file "~/password.gpg")
(setq pstring (shell-command-to-string (concat "gpg -d " passwd-file)))
(princ pstring)
This gives the error gpg: cannot open tty /dev/tty: No such device or address
You are likely out of luck. You first example suggests that even read-passwd does not hide the password input in a non-interactive session, as insert-file calls out to EPA for encrypted files, which in turn uses read-passwd for GPG password input.
Try to report this to the Emacs maintainers with M-x report-emacs-bug, asking them to suppress input echo in read-passwd in non-interactive sessions. That'd be the behaviour I'd expect.
For now, you cannot work around this limitation, because Emacs does not expose the underlying TTY to Emacs Lisp code, so you have no chance to manually disable input echo on the underlying TTY device.
From my experience in writing and contributing quite some non-interactive Emacs Lisp programs, I'd personally advise against using Emacs for non-interactive scripts. It's a poor platform for such programs. The API is limited, and there is a lot of implicit behaviour standing in the way of non-interactive programs, which you can't get rid of.
For instance, you cannot safely pass command line arguments to Emacs, since Emacs will automatically visit any existing file in its command line arguments, triggering all sorts of side effects such as prompts for unsafe local variables, etc.

Garbage characters in my Windows Emacs shell. . . not sure what's wrong

I'm running GNU Emacs (23.1.1) on Windows and when I run a cygwin shell inside emacs I get garbage like the following, after each command:
^[]0;/cygdrive/c/emacs-23.1/bin
^[[32user#HOST [33m/cygdrive/c/emacs-23.1/bin[0m
Note: I've replaced my real user and host name with user/HOST.
I've found a few links that describe how to set up emacs with cygwin on Windows including this one on SO:
How can I run Cygwin Bash Shell from within Emacs?
That hasn't helped. As of right now, I don't have anything referencing shells in my .emacs file except for this:
;; For the interactive shell
(setq explicit-shell-file-name "bash")
So I'm not even sure how emacs is finding my cygwin shell. Any help is appreciated. Thanks.
Try adding these lines to your .emacs file
(autoload 'ansi-color-for-comint-mode-on "ansi-color" nil t)
(add-hook 'shell-mode-hook 'ansi-color-for-comint-mode-on)
I'm not sure if these are the correct ones but let me know (as my .emacs file has gotten quite large over the years)

Getting Windows 7 SUA's bash shell working with emacs (EmacsW32)?

Having recently purchased Windows 7 Ultimate in order to gain access to the SUA - http://www.suacommunity.com - subsystem, I have been struggling to get SUA's bash utility (/usr/local/bin/bash) working with EmacsW32. SUA comes with ksh and csh by default, so I installed a community bundle to obtain the bash process.
M-x shell normally invokes a shell process and pipes stdio through an Emacs buffer. This works well with Cygwin. I have tried adjusting emacs variables like w32-shell-* to point it at the SUA bash executable, and also tried invoking bash via the posix.exe tool provided with SUA. I often see that the file descriptors associated with the bash process are deleted as soon as the process is created by EmacsW32.
Cygwin is very slow compared to SUA, so I am very keen to get this facility working with the EmacsW32 + SUA combo. Any tips, experience, solutions would be appreciated.
I don't know the w32-shell-* variables. Maybe you could show some code to illustrate what you mean.
I also don't know SUA.
I use GNU emacs v22 on Windows, and I run powershell as an inferior shell. I had some difficulties initially, similar to yours, and solved them with a better understanding of how to start the shell. Maybe this will help you.
I use these variables:
(setq explicit-shell-file-name
"c:\\windows\\system32\\WindowsPowerShell\\v1.0\\powershell.exe")
(setq explicit-powershell.exe-args
'("-Command" "-" )) ;; interactive, but no command prompt
I had difficulty until I realized two things:
if you don't specify command-line arguments for the shell process, emacs silently defaults to using -i. In the case of powershell, that argument was either not supported or it did something other than what I wanted (I forget). So I had to explicitly set the arguments to invoke the shell.
the name of the variable for specifying arguments to the shell, depends on the name of the program used to start the shell. This isn't documented as far as I know (unless you consider the source code to be documentation!). If you're on Linux and running sh, then the variable is explicit-sh-args. If bsh, then explicit-bsh-args. If you're on Windows, you need to use the proper name of the exe, including the .exe suffix. It makes for a strange looking variable name, but it works.
The full code to start powershell as an inferior emacs shell is like this:
;; get a name for the buffer
(setq buffer (get-buffer-create "*PowerShell*"))
(let ((tmp-shellfile explicit-shell-file-name))
(setq explicit-shell-file-name
"c:\\windows\\system32\\WindowsPowerShell\\v1.0\\powershell.exe")
(setq explicit-powershell.exe-args
'("-Command" "-" )) ; interactive, but no command prompt
;; launch the shell
(shell buffer)
; restore the original shell
(if tmp-shellfile
(setq explicit-shell-file-name tmp-shellfile)))
Maybe something like that would work for you.

Creating a Cygwin emacs macro

I have been researching how to get Cygwin to work under emacs. I have it working, but now I want to write a macro that will do the following:
Launch by typing M-x cygwin
Have the script stored in some obvious place (probably my .emacs file)
M-x shell
Rename the buffer to cygwin (or cygwin1, cygwin2, cygwin3, ... if cygwin exists) probably using M-x rename-buffer
M-x ansi-color-for-comint-mode-on
M-x set-buffer-process-coding-system 'undecided-unix 'undecided-unix
Open and run cygwin
It will basically do all of the above steps. I think most of the organization for this little project is done. How do I tie it all together so I can just type M-x cygwin and see a happy new cygwin buffer? What exactly needs to be added to .emacs? Also, where exactly is .emacs in Windows?
I still want the ability to run M-x shell for the windows shell for now. I may also make similar macros for MSYS and ssh'ing to my Linux boxes. How do I get started?
Many questions, here are some answers:
Your .emacs can exist many places, it depends, read here. In short try C-x C-f .emacs, or check the value of the variable 'user-init-file (C-h v user-init-file).
I think the command you want is something along the lines of this:
(require 'comint) ; this does require comint
(defun cygwin ()
"do what i want for cygwin"
(interactive)
(let ((buffer (get-buffer-create (generate-new-buffer-name "cygwin"))))
(pop-to-buffer buffer)
(unless (comint-check-proc buffer)
(apply 'make-comint-in-buffer (buffer-name buffer) buffer "c:/cygwin/Cygwin.bat"
nil
nil)
(ansi-color-for-comint-mode-on)
(set-buffer-process-coding-system 'undecided-unix 'undecided-unix))))
Note: I directly ran the process Cygwin.bat instead of running shell and then starting that batch program. I believe the effect is the same, and more straight forward. I did choose the easy way out for naming the buffer (using 'generate-new-buffer-name) - you'll want to customize to what you want.
You can dump the above command in your .emacs easiest by doing the C-x C-f .emacs and pasting it in the buffer that gets opened up. Save it and restart (or do M-x eval-defun when your cursor is in the body of that command. Then M-x cygwin will run the command.

Emacs and cygwin [duplicate]

I am running GNU Emacs on Windows so entering:
M-x shell
launches the Windows command-line DOS shell. However, I would like to instead be able to run the Cygwin Bash Shell (or any other non-Windows shell) from within Emacs. How can this be easily done?
shell-file-name is the variable that controls which shell Emacs uses when it wants to run a shell command.
explicit-shell-file-name is the variable that controls which shell M-x shell starts up.
Ken's answer changes both of those, which you may or may not want.
You can also have a function that starts a different shell by temporarily changing explicit-shell-file-name:
(defun cygwin-shell ()
"Run cygwin bash in shell mode."
(interactive)
(let ((explicit-shell-file-name "C:/cygwin/bin/bash"))
(call-interactively 'shell)))
You will probably also want to pass the --login argument to bash, because you're starting a new Cygwin session. You can do that by setting explicit-bash-args. (Note that M-x shell uses explicit-PROGRAM-args, where PROGRAM is the filename part of the shell's pathname. This is why you should not include the .exe when setting the shell.
The best solution I've found to this is the following:
;; When running in Windows, we want to use an alternate shell so we
;; can be more unixy.
(setq shell-file-name "C:/MinGW/msys/1.0/bin/bash")
(setq explicit-shell-file-name shell-file-name)
(setenv "PATH"
(concat ".:/usr/local/bin:/mingw/bin:/bin:"
(replace-regexp-in-string " " "\\\\ "
(replace-regexp-in-string "\\\\" "/"
(replace-regexp-in-string "\\([A-Za-z]\\):" "/\\1"
(getenv "PATH"))))))
The problem with passing "--login" as cjm suggests is your shell will always start in your home directory. But if you're editing a file and you hit "M-x shell", you want your shell in that file's directory. Furthermore, I've tested this setup with "M-x grep" and "M-x compile". I'm suspicious that other examples here wouldn't work with those due to directory and PATH problems.
This elisp snippet belongs in your ~/.emacs file. If you want to use Cygwin instead of MinGW, change the first string to C:/cygwin/bin/bash. The second string is prepended to your Windows PATH (after converting that PATH to an appropriately unixy form); in Cygwin you probably want "~/bin:/usr/local/bin:/usr/bin:" or something similar.
I use XEmacs with Cygwin, and can run bash from XEmacs relatively easily.
Here's the relevant section from init.el
;; Let's use CYGWIN bash...
;;
(setq binary-process-input t)
(setq w32-quote-process-args ?\")
(setq shell-file-name "bash") ;; or sh if you rename your bash executable to sh.
(setenv "SHELL" shell-file-name)
(setq explicit-shell-file-name shell-file-name)
(setq explicit-sh-args '("-login" "-i"))
One more important hint on this subject.
If you use Emacs shell mode and want both bash and cmd sometimes, set it up to use bash by default, because you can type cmd at bash and the resulting dos shell works just fine.
If you setup Emacs to use cmd as the shell (which is the way NT emacs installs), then dos shell works fine, but if you type bash or bash -i to run a bash shell, the resulting shell doesn't work right - see answer 0.
But it works fine if bash is the "first" shell emacs invokes.
You can run bash directly from the default Windows command-line shell within your Emacs *shell* buffer:
Microsoft Windows XP [Version 5.1.2600]
(C) Copyright 1985-2001 Microsoft Corp.
C:\temp>bash
bash
However, no command prompt is visible which can be disorienting resulting in your commands and their output results all blending together.
In addition, for some unknown reason, if you do enter a command and hit return, a return line character (\r) is appended to the end of your command statement causing a bash error:
ls
bash: line 1: $'ls\r': command not found
A workaround is to manually add a comment character (#) at the end of every command which effectively comments out the \r text:
ls #
myfile,txt
foo.bar
anotherfile.txt
This overall approach is far from ideal but might be useful if you want to drop into bash from Windows' native shell to do some quick operations and then exit out to continue working in Windows.
I'm using EmacsW32. C-h a shell$ gives a list of shell launching commands and the commands cmd-shell and cygwin-shell look interesting. Both commands need EmacsW32. They are also found in the menu: Tools > W&32 Shells.
If you run cygwin-shell for the first time, and if you have not setup cygwin path in Emacs, it leads you to the Customization page where you can setup the cygwin path by pressing Find button.
Since these approaches didn't work for me I got it the following way:
(I'm using NTEmacs which opens a dos shell by default, so perhaps your emacs behaves the same)
Create a windows environment variable named SHELL ('SHELL' not '$SHELL') and give it the path to bash.exe of your cygwin installation (for example c:\programs\cygwin\bin\bash.exe)
Now when doing M-x shell it opens a bash.
Regards,
Inno
In addition to #Chris Jones' answer about avoiding the --login argument to bash, I set the following command line arguments:
(setq explicit-bash-args '("--noediting" "-i"))
The --noediting option prevents interference with the GNU readline library and the -i option specifies that the shell is interactive. I also use the .emacs_bash file in my home directory for any emacs specific bash customizations.

Resources