Eshell can't find script on eshell path - emacs

My goal
I'm trying to add "/opt/bin" to the list of paths eshell uses to find scripts. So far I've tried to do this in three ways
Attempts so far
1) (setenv "PATH" (concat "/opt/bin:" (getenv "PATH")))
2) (eshell/addpath "/opt/bin:")
3) (add-to-list 'exec-path "/opt/bin")
The first attempt does add "/opt/bin" to eshell's path (it shows up as the first instance of "/opt/bin:" in the output of calling "which lein" below)
The second attempt also adds "/opt/bin" to eshell's path (it shows up as the second instance of "/opt/bin:" in the output of calling "which lein" below)
I actually have had "/opt/bin" added to my exec-path for a while. I believe I did this so that /opt/bin would be on my path when running the term command to start a shell, this seems to work fine but doesn't help eshell find commands there.
Failing attempts and temporary workaround
You can see in the eshell output below that even though a command, lein, is available on the path eshell recognizes eshell doesn't find the command. However if I create a symbolic link from a directory that is in eshells default path to a script in /opt/bin eshell is then able to find it.
Eshell output
~ $ which lein
which: no lein in (/opt/bin:/usr/local/bin:/usr/bin:/bin:/usr/local/games:/usr/games:/usr/local/sbin:/usr/sbin:/sbin:/opt/bin:)
~ $ l /opt/bin/ | grep lein
-rwxr-xr-x 1 kevin kevin 12538 2019-01-17 07:32 lein
~ $ sudo ln -s /opt/bin/lein /usr/local/bin/lein
[sudo] password for kevin:
~ $
~ $ which lein
/usr/local/bin/lein
I would prefer not to have to create symbolic links in /usr/local/bin/ just so that eshell can find scripts in my /opt/bin. Note even after restarting emacs it finds the symbolic link not the script in /opt/bin. This is occurring in a GUI instance of emacs-25 on linux mint debian (v9.3) edition.
Question:
How do I get eshell to actually check eshell path instead of the some default list of directories? Should I be updating a different path variable?

Looking at the source of eshell/addpath, it uses setq on eshell-path-env, which is a buffer local var. This means that if you use eshell/addpath, it has to be executed in the context of each eshell buffer. The best way to do this is to use a mode hook.
(defun jpk/eshell-mode-hook ()
(eshell/addpath "/opt/bin"))
(add-hook 'eshell-mode-hook #'jpk/eshell-mode-hook)
I'm not super familiar with Eshell, so I'm not going to say this is the best way, but it should work. eshell-path-env is set from (getenv "PATH") initially, so it's weird that setting PATH env var doesn't work (unless you're doing that after loading eshell).

One way:
Assuming you are running emacs in a terminal emulator or tty; then you can just add /opt/bin to your $PATH. Eshell uses your $PATH to find external commands. Not sure how it works for GTK version.

Related

Define default compile command in Emacs

I have a project that uses a bash script to invoke cmake and make. I have successfully used this script from Emacs by using M-x compile, followed by typing:
cd ../..; ./build.sh
in the minibuffer. (The project organization is top/src/various_source_folders and build.sh is in top/.)
I am trying to define a directory variable to specify the default command to use for compile. I have tried the following (both with single or double quotes around the compile command) in .dir-locals.el:
((c++-mode
(compile-command 'cd ../..\; ./build.sh')))
Which gives no errors, but M-x compile still defaults to make -k.
((c++-mode
(set-variable 'compile-command' "cd ../../\; ./build.sh")))
Which gives a warning about unsafe variables. Even if I choose apply, compile still defaults to make -k
Simply using M-x eval-buffer with the second line ((set variable...) in *scratch* correctly sets the compile command.
Is there a different way I can/should be doing this?
Found an answer here.
Two periods and some parenthesis were missing from the syntax:
((c++-mode
. ((compile-command . "cd ../../\; ./build.sh"))))

How do I make Emacs recognize bash environment variables for compilation?

I'm trying to compile u-boot via Emacs' compilation mode, and it looks like Emacs doesn't know how to find bash environment variables. Even though I set them, and can compile via Emacs shell emulation, compilation mode still tries to compile as if they aren't there.
What do I need to do to make it more environment conscious?
You can try adding something like to your .emacs:
(let ((path (shell-command-to-string ". ~/.bashrc; echo -n $PATH")))
(setenv "PATH" path)
(setq exec-path
(append
(split-string-and-unquote path ":")
exec-path)))
Depending on whether you've set the env variables in .bash_profile or .bashrc you might need to slightly adjust this snippet. The example is for the PATH variable, which is a bit more special (since you have to set exec-path in Emacs as well), but can be extended to work for arbitrary variables - you could have a list of variables that have to be read from .bashrc and set into Emacs.
I'm not sure whether you're using OS X or GNU/Linux. Starting Emacs from the GUI's menu-bar in Linux will typically result in an Emacs that does not have the same PATH as one launched from the command line. This problem dates back to the first xdm Xsession scripts, and while they are fairly easy to fix (basically use an Xsessionwrapper script that does exec $SHELL -c Xsession so the shell gets run before running the user's Xsession), nobody has bother to do so in a very long time (and I doubt that anyone will). As far as I know the problem is present even into moder xdm descendants such as kdm and gdm.
On OS X the handling of the env variables is another problem entirely and to get your ENV variables you typically have to run Emacs from the command line like this /Applications/Emacs.app/Contents/MacOS/Emacs or play with ~/.MacOSX/environment.plist. The code snippet I've provided should cover you in both cases though.
Update
Recently this process was made easier by the exec-path-from-shell extension. It sets the emacs $PATH in more or less the same manner, but using an extension is generally preferable to hacking the solution yourself.
This is where the environment variables of the process that started emacs are:
— Command: getenv var
This function returns the value of the
environment variable var, as a string. var should be a string. If var
is undefined in the environment, getenv returns nil. It returns ‘""’
if var is set but null. Within Emacs, a list of environment variables
and their values is kept in the variable process-environment.
(getenv "USER")
⇒ "lewis"
— Variable: process-environment
This variable is a list of strings,
each describing one environment variable. The functions getenv and
setenv work by means of this variable.
process-environment
⇒ ("PATH=/usr/local/bin:/usr/bin:/bin"
"USER=lewis"
"TERM=xterm"
"SHELL=/bin/bash"
"HOME=/home/lewis"
...)
You seem to be assuming that emacs was started from a bash session. However, often processes under X are started from an sh session, which would not read the environment variables you had set in your ~/.bashrc script. One simple way to circumvent this is to change your ~/.xinitrc file to use bash instead of sh (it could be as simple as adding #!/bin/bash at the top of the file).
Source: gnu.org
It doesn't strictly answer your question, but you can always pass environment variables on the make command-line. For example : M-xcompileRETmake -k CXXFLAGS='-Wall'RET

remote debugging emacs 24 and gdb

I have code on a compute node of a cluster. I can't ssh directly to the compute node so I first set up an ssh tunnel with
ssh -f cluster.master.node -L 2222:cluster.compute.node:22 -N.
Next I visit the file with
C-x C-f /ssh:user#localhost#2222/path/to/blah.c.
Finally I do
M-x gdb.
In emacs 23 I would do
Run gdb (like this) gdb --annotate=3/ssh:localhost#2222:/path/to/program
but documentation for the gdb function in emacs 24 says "The command-line
options should include -i=mi to use gdb's MI text interface. Note that the old "--annotate" option is no longer supported."
Running
gdb (like this) gdb --i=mi /ssh:loalhost#2222:/path/to/program
seems to work, but when I try to run the program I get "Starting program: /misc/home/joey/git/proteus/proteus /dev/pts/5: No such file or directory." The problems seems to be with the non-existent /misc/ directory prepended to the path of the executable. Even when I do a cd to /home/joey/git/proteus/ the response is "Working directory /home/joey/git/proteus (canonically /misc/home/joey/git/proteus)."
Can I remotely debug my program in Emacs 24 or should I go back to 23?
Try M-x gud-gdb RET: it will give you the old Emacs-22 behavior.

Emacs: Tramp doesn't work

I tried to open a remote file via Emacs via Tramp.
(require 'tramp)
(setq tramp-default-method "ssh")
I get a message from Emacs
Tramp: Waiting for prompts from remote shell
Emacs hung and did not respond to any action after that
Emacs was installed on Windows; the remote file was on a Linux machine.
If the account you're connecting to uses some weird fancy shell prompt, then there is a good chance that this is what makes tramp trip.
Log in as root, then enter
PS1="> "
(that's a normal, standard shell (ZSH, BASH, younameit) prompt, one that tramp will understand)
then switch to the user account, and launch emacs -q (to make sure that your .emacs is not causing this mess) and try to C-x C-f /sudo:root#localhost:/etc/hosts and see what's what.
You can (not recommended) also customize the regexp that defines what tramp expects :
M-x customize-variable RET tramp-terminal-prompt-regexp
My approach :
Make sure the variable tramp-terminal-type is set to "dumb"
M-x customize-variable RET tramp-terminal-type
Test that in your .*shrc and serve the correct prompt :
case "$TERM" in
"dumb")
PS1="> "
;;
xterm*|rxvt*|eterm*|screen*)
PS1="my fancy multi-line \n prompt > "
;;
*)
PS1="> "
;;
esac
Your Windows ssh client is the key here, and the 'ssh' Tramp method is almost certainly wrong.
If you're using Cygwin, then you need to use the 'sshx' method, and you probably need to use ssh-agent to handle authentication. Details are here:
Using tramp with EmacsW32 and cygwin, possible?
I imagine the same applies to any stand-alone ssh client which does not require a full Cygwin installation, but does use the Cygwin DLLs. (I mention this, because I'm pretty sure I remember seeing such a thing.)
If you're using PuTTY then you want the 'plink' method, as Alex Ott pointed out. If the Wiki doesn't suffice, a search here will probably turn up solutions for configuring that approach.
Other alternatives I can suggest are:
Use the Cygwin-native Emacs. That will be slower than NTEmacs, but Tramp seems to work well with the 'ssh' method, and password-prompting works as well.
Host a Linux VM on your Windows box, and run Emacs on that. That's a fairly large hoop to jump through, but it's my preferred way of using Tramp when working in Windows.
Well, this is a defect of tramp.
The real solution is to prevent loading .bashrc when tramp is used. (because now it is PS1, but it can be PATH, or any other thing that your .bashrc will do that will displease tramp...).
This can be done by asking ssh to set an environment variable, and testing it in .bashrc:
Add this to ~/.emacs:
(require 'tramp-sh nil t)
(setf tramp-ssh-controlmaster-options (concat "-o SendEnv TRAMP=yes " tramp-ssh-controlmaster-options))
and that at the beginning of ~/.bashrc:
if [ ! -z ${TRAMP-x} ] ; then
return
fi
Another default of tramp is that it doesn't have a variable to pass random arguments to the ssh command, we have to piggy-back on tramp-ssh-controlmaster-options.
Had you checked Emacs wiki for solution? ssh is in PATH? It's also recommended to use plink on MS Windows - see section "Inline methods" in Tramp documentation
If the problem is your fancy custom prompt in the remote shell, an easy workaround is to add to your .bashrc or equivalent:
if [[ $TERM == "dumb" ]]; then
export PS1="$ "
fi
After you define your PS1.
Note: the credit goes to ChasingLogic as this is their suggestion in this thread.
By the way -- if You need tramp to sudo -- You can actually sudo without tramp using sudoedit.
Currently I'm using this bash function:
erf () { SUDO_EDITOR="emacsclient -a emacs" sudoedit $#; }

Commands from .bashrc not available in Emacs

I have some aliases and functions defined in ~/.bashrc.
I start emacs from a terminal window using emacs -nw
When I execute M-x shell-command, the aliases and functions from ~/.bashrc are not available, but give a "command not found".
I've googled quite a bit but all the posts I come across say, if I understand them correctly, that ~/.bashrc is the place where this should work (rather than ~/.profile or ~/.bash_profile).
What am I missing?
Aliases are available only in interactive shell - a snapshot from bash man page:
Aliases are not expanded when the
shell is not interactive, unless the
expand_aliases shell option is set
using shopt
(see the description of shopt under SHELL BUILTIN COMMANDS below).
If you start Emacs from an interactive shell (in which .bashrc, etc. have executed), then the commands from your .bashrc should be available for both shell-command and shell, at least that's how it works for me.
But yeah as the other answer says, there is not real way to get a .bashrc environment in emacs. There are some documentation about a .emacs_bash file, but that never worked for me.
Okay misread your question here. If you are looking for functions and aliases instead of commands by changing paths in .bashrc, the non-interactiveness is the problem. I guess you can change the default argument to shell-command (take a look at explicit-bash-args) to make bash interactive, but that probably has unintended consequences.
The accepted answer correctly states that "aliases are available only in interactive shell".
This means that in order to load (rightly located indeed) aliases from ~/.bashrc, an interactive shell would have to be launched with Emacs's M-x shell-command (M-!).
To achieve this, add -i (interactive) switch to the M-x shell-command with:
(setq shell-command-switch "-ic")
Side Note, not Emacs related:
On some operating systems users would need to add the line source ~/.bashrc to ~/.bash_profile (or similar), since ~/.bashrc is not always auto-read by a system.