Get tab completion in custom comint mode - emacs

I usually try to start CLI's (might not be defining it properly) using commands like:
(make-comint-in-buffer "PUTTY" nil "./plink.exe" nil "dbserver")
(make-comint-in-buffer "Python" nil "c:/Python26/python.exe" nil "-i")
(make-comint-in-buffer "Python" nil "c:/Python27/python.exe" nil "-i")
(make-comint-in-buffer "git" nil "C:/Program Files (x86)/Git/bin/sh.exe" nil "--login" "-i")
Starting the above specially the first and the last in command prompt provides the facility of tab completion. But in comint-mode I don't seem to get this feature.
Entering tab adds a simple tab character under the point instead of passing it to the process and getting back the completion candidates. comint-dynamic-complete and C-qtab doesn't produce the desired result.
How can I utilize in above said feature in comint-mode running different processes?

Short answer
You need to write your own completion functions inside Emacs. These may pull info in from the external program, but you can't have direct access to the tab-completion provided by python or git etc.
Long answer:
When you run make-comint-in-buffer, you are setting up the most basic setup for interactively sending and receiving data from an external process. Whenever you press enter, Emacs sends the current line to the underlying process, and then prints back the output from the process. The external process doesn't know what you're doing until Emacs sends a full line to it - no single characters are passed directly.
This is different from running the external program directly in a terminal. When you run python in a terminal, it interprets every character as you type it (or at least it can). So when you hit tab it knows to try to complete something. When you run python inside Emacs, Emacs is processing all of your input until you hit enter. Which means when you hit tab, Emacs just inserts a tab character, and python doesn't know to try and complete something.
Emacs can provide tab-completion for comint modes, but you need to build the completion targets on the Emacs side, you can't rely on the native completion of the external program. To get an idea of how this works, take a look at the completion functions in shell.el, which you can open with M-x find-library shell.
This isn't something you can do with a line or two of elisp. It's an important part of major-modes written to interact with external processes - things like ESS for R http://ess.r-project.org/
That said, if you dig into the guts of shell.el you may find enough code you can modify to get you started.

Related

Tab completion, rlcompleter in Emacs

I have a Python program which uses rlcompleter to provide custom Tab-completion. The completion works when it is run under a bash terminal. However, it does not work under emacs, in shell mode, nor in eshell mode.
I noticed that Tab is really bound to completion-at-point, eshell-pcomplete, and so on, so I tried an (insert "\t"), supposing that this would trigger the completion, which I understand happens when the child process reads a "\t" character. But this does not work either. Perhaps input is buffered until a "RET"?
Completion for commands like service, which define their own candidates, does not work as expected either.
How can I access these candidates within Emacs?
Try using M-x ansi-term. I find it behaves a bit more like what I have come to expect from a *nix terminal.

Why does emacs' comint-send-string behave differently in different derived modes?

I've been fooling around with comint-mode lately and I'm noticing some weird behaviors. Its very poorly documented, so I'm wondering if anyone has any insight on this.
In some modes, comint-send-string causes whatever is sent to be inserted into the comint buffer and then sent to the associated process, whereas in others, the input is send directly to the process without being placed into the buffer. For example, do run-python with the new (24.3) python.el and then do (comint-send-string "*Python*" "x=3\n"), the string x=3 is inserted into the buffer and then executed. If you do M-x shell, however, and then (comint-send-string "*shell*" "x=3\n"), no text is inserted into the buffer, the input is simply sent to the shell process directly to be executed.
Does anyone know why this difference in behavior exists or how I can change it?
I observe identical behavior on linux (emacs-version == "24.3.50.7", both GUI and emacs -Q -nw): neither
(comint-send-string "*Python*" "x=3\n")
nor
(comint-send-string "*shell*" "x=3\n")
insert anything in the comint buffer (i.e., the next prompt appears
right after the previous prompt - without even a newline between them).
I eventually figured it out. For some reason the system python on OSX causes this behavior, installing python from homebrew fixed it.

Running python interpreter or language X in Emacs

Every time I start the interpreter for a programming language (lets consider python in this case) emacs opens the interpreter in the window which is not current. Note that I have two windows open, so the interpreter is always opening in the opposite window that I am currently in. This is annoying because then I always have to switch windows after I open an interpreter...
How can I get the python interpreter to open in the current window inside emacs?
Can I solve this problem generally for other programs/shells/buffers that do not open in the current window?
I note that this also happens frequently with other emacs commands (such as C-h v and the description of the variable opens in the window that is not current)
All help is greatly appreciated!
Interpreter-buffers connect with a process. If not already there, it must be a different one than the buffer called from - otherwise the current buffers contents is lost.
You might be interested in org-mode, org-babel, which provides a way to insert results in current buffer when executing source-code.
With python-mode.el, set py-switch-buffers-on-execute-p to non-nil. After M-x py-shell, cursor is in new shell.
If py-split-windows-on-execute-p is nil, M-x py-shell should switch to Python shell without splitting the window. See more options if re-using an existing py-shell etc.
With python.el, M-x run-python switches into the Python-shell.
See also customizable variable pop-up-windows.

How to have find-file's prompt match Emacs shell's $PWD?

With Emacs, if the current buffer is one that's "visiting" a normal file (for example), whose full pathname is /path/to/somefile, and one runs find-file (C-x C-f), the prompt that appears in the mini-buffer is something like
Find file: /path/to/▮
...with the cursor placed as indicated above by ▮. IOW, the suggested path shown by default is always to the directory containing the file that the current buffer is visiting.
If, however, the current buffer is an Emacs shell process, and one runs find-file, then, AFAICT, the path shown in the prompt remains fixed at the value of $PWD when the shell process was started, irrespective of the current value of $PWD:
Find file: /pwd/at/startup/▮
This behavior is not so useful, because the $PWD at startup often becomes irrelevant later on. It would be really nice if the directory shown in find-file's prompt were instead the shell process's current $PWD.
Is there a simple way to modify find-file to behave this way whenever the current buffer is a shell process?
You want "shell directory tracking". E.g. check dirtrack-mode or shell-dirtrack-mode.
shell-dirtrack-mode tries to parse "cd" commands, (event_jr: which in my experience does not work consistently). dirtrack-mode uses the prompt regexp, which works very well.
There are a number of ways to manage this. As Stefan notes, there are a couple of built in packages that manage it.
My preferred way is to alter your prompt (when in Emacs) to have the $PWD embedded in it, and then Emacs strips it out and uses it. This has the benefit of always being up to date. I've found that dirtrack-mode sometimes gets out of sync.
Check out my solution here, which is a modification of a similar implementation on the Emacs Wiki.

Properly invoking an interactive script from elisp

I have an external command line program that I would like to invoke from elisp. This is easy enough with shell-command, but it doesn't work correctly when the command line program is interactive, which in my particular case it is: The invoked script sees EOF when it reads stdin when I call it like this:
;; upload command is a string with the name of
;; a python script and some args
(shell-command upload-command
(get-buffer-create "*upload output*")))))
The python script identified by upload-command may ask some yes/no questions and it may prompt for a password, for which I'd like masked input. Ideally, all of this interaction would occur within the minibuffer.
How can I arrange things so that my external interactive command interacts with the user via minibuffer when called via elisp?
The easiest way is to use either make-comint or make-comint-in-buffer:
(make-comint-in-buffer "upload-script-process" "*upload output*" upload-command)
This will runs the script in a buffer like a shell buffer, so it doesn't fulfill the requirement of having all interaction happen in the minibuffer. It will, however, automatically read passwords in masked form from the minibuffer, provided the password prompt matches comint-password-prompt-regexp.
Note that upload-command in this example here needs to be the name of an executable file on exec-path. Any extra switches or other arguments to the script have to be passed as string arguments to make-comint:
(make-comint-in-buffer "upload-script-process" "*upload output*"
upload-command nil "--verbose" "--other-option")
See the Emacs documentation for more details.