Emacs shell: command history lost after restart - shell

A very useful time-saver for working with shell is that you can search for command history using Ctrl - r. Emacs has the same functionality in its shell mode: C-S-r. However, the shell's history is cleared every time emacs is restarted. Any idea how to persist the history?

In general the answer would be:
M-x customize-group RET savehist RET
Enable savehist-mode and configure the variables you wish to persist between sessions.
However in this case I think you'll find that it's your shell which is tracking its command history; not Emacs.
e.g. for bash, commands are stored in $HISTFILE (by default ~/.bash_history), but depending on your settings, the history from one shell may be clobbered by another shell, depending on which one exits last. For bash, read the HISTORY section of its man page.
Edit: For comint-mode and derivatives (including shell-mode) the searchable history is read in via comint-read-input-ring, which uses comint-input-ring-file-name which you can set in a mode hook. However I would suggest that you actually set your HISTFILE environment variable to ~/.zsh_history because shell-mode automatically defers to that.
It seems a little odd to me that zsh doesn't already do this, mind (assuming you're starting Emacs from a zsh shell?). If you use some kind of GUI launcher, OTOH, the environment Emacs starts in may not be what you want? I couldn't say for sure.
Failing that, the documentation suggests that this ought to work:
(add-hook 'shell-mode-hook 'my-shell-mode-hook)
(defun my-shell-mode-hook ()
(setq comint-input-ring-file-name "~/.zsh_history")
(comint-read-input-ring t))
(but using HISTFILE would be better).
n.b. I'm using Emacs 24.3 and the keybindings are different to those you have described (M-r to search the history in shell-mode; C-S-r is unbound for me), so YMMV. I always run my shells inside ansi-term, so I couldn't tell you whether this functionality has changed recently.

Related

How to prevent Emacs from duplicating shell commands?

I always use Emacs's shell. I create 2 buffers (C-x 2) and use one of them as a terminal (M-x shell).
Sometimes I use a command a lot of times (e. g. python3 test.py). I use shortcut <C-up> to repeat the last command. And it's very inconvenient that Emacs saves duplicates of commands. I have to press <C-up> many times so that I can run any other command.
The problems is only in Emacs's shell. I have setting HISTCONTROL=ignoreboth in .bashrc and in usual terminal it works very well.
Is it possible to configure Emacs so that it ignores duplicates?
It's customizable
(setq comint-input-ignoredups t)
Setting 'comint-input-ignoredups' as suggested by Jürgen Hötzel will of course solve the immediate, but here are some alternatives.
You could choose to use the command 'ansi-term' instead of 'shell', this will run a bash (or whatever you choose) so you get the same control as in (say) an xterm. As an added bonus, you also get a rather capable terminal so applications that depend on this will work.
Another possibility, if you have something you want to repeatedly run, is to use the 'compile' command. This can run any shell command, it does not have to be a compiler. The advantage here is that you keep the running of the test out of your shell command history (no matter how you run your shell) and you get the output in a separate buffer. If the output is suitably organised and/or the compilation buffer is suitably configured, you could also use the 'next-error' command to jump back to the appropriate part of the source.
Finally, I would like to mention that the 'shell' command supports searching the command history. It is by default bound to M-r (comint-history-isearch-backward-regexp).

Getting GNU Make to parse shell config files in OSX?

I've got a makefile for installing my personal repo of config files, part of which is compiling my emacs scripts:
compile:
emacs -batch --eval "(progn (load \"~/.emacs\") (byte-recompile-directory \"~/.emacs.d\" 0))"
The problem is, on OSX, I have an alias called "emacs" that points to the Emacs.app binary for use in a terminal, this is defined in my ~/.bash_profile.
Now, no matter what I do, I can't seem to get the shell that Make is calling to read a startup file to load that alias, so that compilation step always fails.
Does anyone know how to do this?
.bash_profile is only read by interactive login shells. Exported environment variables set in it are inherited through the process environment, which means that these settings are generally available to all programs the user starts (if bash is indeed the login shell, of course).
No such inheritance happens for aliases, though. Bash supports exported functions, but that's an obscure feature which can easily break other programs (for example, those which assume that environment variable values do not contain newlines). If you go that route, you may have to use .bashrc instead, to make sure that these functions are exported by interactive bash shells which are not login shells.
I expected the easiest solution is to put a directory like $HOME/bin on the PATH (in .bash_profile or .bashrc, whatever works best) and put an emacs wrapper script into that directory which invokes the actual binary using exec /path/to/Emacs.app "$#" (or maybe just a symbolic link would do).
That is very strange. Aliases are not exported to sub-shells, and the .bash_profile script is only run by interactive shells: make doesn't invoke an interactive shell (by default). So, it's hard to understand how the shell make invokes would see that alias based on the information you've provided.
Maybe you set the BASH_ENV shell variable somewhere? You should never do that, unless you really know what you're doing.
Maybe you reset make's .SHELLFLAGS variable to force a login shell? You shouldn't to that either.
Anyway, you can try using command which avoids aliases etc. Unfortunately make doesn't know this is a shell-built in, so you have to convince it to run a shell. This will be fixed in the next release of GNU make but Apple will never ship that.
compile:
command emacs -batch --eval "(progn (load \"~/.emacs\") (byte-recompile-directory \"~/.emacs.d\" 0))" && true

How to open a file in linux without specifiying editor?

I have emacs as my defualt editor in linux, and I also have alias in my .cshrc file.
alias e "emacs -mm"
Sometime I just want to hit the file name in the command line and open it in emacs directly with out the editor beign metioned.
Example instead of
$ e foo.cc&
What I want is to open
$foo.cc
May be this is lazy to do but it saves a lot time if you have so many files to handle. Thanks for the help.
You probably cannot open a file with $foo.cc (and that would be ambiguous for a shell script script.sh: would script.sh means "edit the file script.sh" or "run the shell script script.sh" ?). However,
You might want to use xdg-open, or the $EDITOR variable (see environ(7)). If you always have a single emacs running, you might set EDITOR to emacsclient in your ~/.bashrc (if using /bin/bash) or your ~/.zshrc (if using /bin/zsh)
BTW many editors (including emacs, gedit, vim) are able to edit several files, i.e. $EDITOR *.c
And depending upon your login shell (zsh, fish, or bash) you could set up a shell function or alias to simply type e foo.c; I feel that it is not worth the effort, since with autocompletion I just have to type 3 keys e m tab to get emacs (and often the up arrows are enough)
Actually I start only once every day emacs then open many files inside it (and also I compile inside emacs)
BTW, you should avoid csh since it is considered harmful. Install a good interactive shell (e.g. with sudo aptitude install zsh zsh-doc) and use once chsh(1) to make it your login shell.

Running Windows batch files from Emacs

I'm somewhat new to gnu emacs, and so perhaps this is a noob question, but I have a few batch files I use a lot when coding in emacs to compile/build/execute/debug/etc. I am wondering how I could A) run these batch files from emacs without having to keep opening a cmd prompt window or going to windows explorer and B) bind this to a key shortcut (perhaps I could specify the file?) I have seen several things online about running emacs in batch-mode, but I don't believe this is what I'm looking for. And I know it is possible because I have seen others run batch from emacs (output and everything would appear in a new buffer adjacent to the current as if you did C-x 3)
Thanks in advance!
To run an arbitrary shell command in Emacs, you call shell-command which is bound to M-!
See C-hf shell-command (or C-hkM-!) for details.
I believe in the Windows-native Emacs, the default shell is cmd (or some alias thereof), so I'm reasonably confident that this is what you're thinking of.
I'm not sure whether all of the following work in Windows, but related commands are:
M-& - async-shell-command
M-| - shell-command-on-region
And with a prefix argument (e.g. C-uM-!) any of those commands will insert the shell command's output into the current buffer. (In the case of shell-command-on-region, that replaces the region.)

What's the difference between .bashrc, .bash_profile, and .environment?

Locked. This question and its answers are locked because the question is off-topic but has historical significance. It is not currently accepting new answers or interactions.
I've used a number of different *nix-based systems of the years, and it seems like every flavor of Bash I use has a different algorithm for deciding which startup scripts to run. For the purposes of tasks like setting up environment variables and aliases and printing startup messages (e.g. MOTDs), which startup script is the appropriate place to do these?
What's the difference between putting things in .bashrc, .bash_profile, and .environment? I've also seen other files such as .login, .bash_login, and .profile; are these ever relevant? What are the differences in which ones get run when logging in physically, logging in remotely via ssh, and opening a new terminal window? Are there any significant differences across platforms (including Mac OS X (and its Terminal.app) and Cygwin Bash)?
The main difference with shell config files is that some are only read by "login" shells (eg. when you login from another host, or login at the text console of a local unix machine). these are the ones called, say, .login or .profile or .zlogin (depending on which shell you're using).
Then you have config files that are read by "interactive" shells (as in, ones connected to a terminal (or pseudo-terminal in the case of, say, a terminal emulator running under a windowing system). these are the ones with names like .bashrc, .tcshrc, .zshrc, etc.
bash complicates this in that .bashrc is only read by a shell that's both interactive and non-login, so you'll find most people end up telling their .bash_profile to also read .bashrc with something like
[[ -r ~/.bashrc ]] && . ~/.bashrc
Other shells behave differently - eg with zsh, .zshrc is always read for an interactive shell, whether it's a login one or not.
The manual page for bash explains the circumstances under which each file is read. Yes, behaviour is generally consistent between machines.
.profile is simply the login script filename originally used by /bin/sh. bash, being generally backwards-compatible with /bin/sh, will read .profile if one exists.
That's simple. It's explained in man bash:
/bin/bash
The bash executable
/etc/profile
The systemwide initialization file, executed for login shells
~/.bash_profile
The personal initialization file, executed for login shells
~/.bashrc
The individual per-interactive-shell startup file
~/.bash_logout
The individual login shell cleanup file, executed when a login shell exits
~/.inputrc
Individual readline initialization file
Login shells are the ones that are read one you login (so, they are not executed when merely starting up xterm, for example). There are other ways to login. For example using an X display manager. Those have other ways to read and export environment variables at login time.
Also read the INVOCATION chapter in the manual. It says "The following paragraphs describe how bash executes its startup files.", i think that's a spot-on :) It explains what an "interactive" shell is too.
Bash does not know about .environment. I suspect that's a file of your distribution, to set environment variables independent of the shell that you drive.
Classically, ~/.profile is used by Bourne Shell, and is probably supported by Bash as a legacy measure. Again, ~/.login and ~/.cshrc were used by C Shell - I'm not sure that Bash uses them at all.
The ~/.bash_profile would be used once, at login. The ~/.bashrc script is read every time a shell is started. This is analogous to /.cshrc for C Shell.
One consequence is that stuff in ~/.bashrc should be as lightweight (minimal) as possible to reduce the overhead when starting a non-login shell.
I believe the ~/.environment file is a compatibility file for Korn Shell.
I found information about .bashrc and .bash_profile here to sum it up:
.bash_profile is executed when you
login. Stuff you put in there might be
your PATH and other important
environment variables.
.bashrc is used for non login shells.
I'm not sure what that means. I know
that RedHat
executes it everytime you start
another shell (su to this user or
simply calling bash again) You might
want to put aliases in there but again
I am not sure what that means. I
simply ignore it myself.
.profile is the equivalent of
.bash_profile for the root. I think
the name is changed to let other
shells (csh, sh, tcsh) use it as well.
(you don't need one as a user)
There is also .bash_logout wich
executes at, yeah good guess...logout.
You might want to stop deamons or even
make a little housekeeping . You can
also add "clear" there if you want to
clear the screen when you log out.
Also there is a complete follow up on each of the configurations files here
These are probably even distro.-dependant, not all distros choose to have each configuraton with them and some have even more. But when they have the same name, they usualy include the same content.
According to Josh Staiger, Mac OS X's Terminal.app actually runs a login shell rather than a non-login shell by default for each new terminal window, calling .bash_profile instead of .bashrc.
He recommends:
Most of the time you don’t want to maintain two separate config files
for login and non-login shells — when you set a PATH, you want it to
apply to both. You can fix this by sourcing .bashrc from your
.bash_profile file, then putting PATH and common settings in .bashrc.
To do this, add the following lines to .bash_profile:
if [ -f ~/.bashrc ]; then
source ~/.bashrc
fi
Now when you login to your
machine from a console .bashrc will be called.
A good place to look at is the man page of bash. Here's an online version. Look for "INVOCATION" section.
I have used Debian-family distros which appear to execute .profile, but not .bash_profile,
whereas RHEL derivatives execute .bash_profile before .profile.
It seems to be a mess when you have to set up environment variables to work in any Linux OS.

Resources