Evaluate emacs lisp expression on command line - emacs

I'm a newbie to emacs. I'm working with emacs-24.1 on redhat linux, and trying to evaluate an elisp expression. What I want emacs to do is to evaluate the elisp expression without launching emacs itself. I'm trying different things
emacs --eval '(+ 2 3)'
I do not know if emacs is evaluating the expression, but the result is not shown on console and emacs window comes up. Next I tried this
emacsclient --eval '(+ 2 3)'
Emacs client is expecting a server. It could not find the server and hence throwing an error (can't find socket. start server etc). So I launched a server (server-name is SERVER) and ran emacsclient again
emacsclient --server-file=SERVER -e '(+ 2 3)'
This time, emacs evaluated the expression and printed the result on console. That is because emacs is using the existing server to evaluate the expression. Now I get a problem when the server is not running.
emacsclient --server-file=ANOTHER_SERVER -e '(+ 2 3)' -a emacs
This time, I'm not getting any error on console. Emacs is launching a new window, because of -a (my .emacs has (server-start) command in it and server-name set to ANOTHER_SERVER). But emacs then is trying to edit the file (+ 2 3). It is shown on the mode line. I'm confused. emacsclient --help showed me this
-e, --eval Evaluate the FILE arguments as ELisp expressions
and emacs manual says this.
'-e'
'--eval'
Tell Emacs to evaluate some Emacs Lisp code, instead of visiting some files.
When this option is given, the arguments to emacsclient are interpreted as a
list of expressions to evaluate, not as a list of files to visit.
I do not know how to proceed on this. As I said, my goal is to evaluate an elisp expression without launching emacs. Is it possible?

After a bit of testing it looks like you can use --batch to have emacs dump any messages to stderr. Then you can call message to print things to stderr where you'll be able to see them. Your example would become emacs --batch --eval '(message (number-to-string (+ 2 3)))' and the result would be printed to stderr.
If you're trying to redirect the output to a file you'll need to redirect stderr instead of stdout by using 2> instead of just >.

Try
emacs --batch --eval '(print (+ 2 3))'

Related

Color printing in emacs without X11

I'm using ps-print-buffer-with-faces to print out code with colored syntax highlighting (in emacs).
This works fine if I call ps-print-buffer-with-faces interactively (using M-x for example). I've also got it working from a bash script so that I can print in color from the command line. No problem.
However, I want to be able to perform this from cron, or possibly from a Makefile (i.e. without X11)
I've tried using the emacs -nw option and it complains that stdin is not from a tty and will not continue.
When I use the emacs --batch option, it appears that it is working, but the resulting postscript file has no colors at all.
Does anyone know how I can get ps-print-buffer-with-faces to obtain colors without X11?
This really bring back some memories -- I wrote a package like that back in the 1990:s, unfortunately, I have lost the source code (this was long before I started using a version control system).
The key to using font-lock in batch mode is to fool it into believing that it's in interactive mode, by setting noninteractive to nil.
I just threw together the following, is saves a postscript file named ORIGINAL_BASENAME.ps. You can easily modify this to print to the printer directly, by not passing the file name parameter.
#!/usr/bin/emacs --script
(defun ps-batch-print (files)
(dolist (source files)
(unless (file-exists-p source)
(user-error "File not found: %s" source))
(find-file source)
(let ((noninteractive nil))
(font-lock-mode 1))
(ps-print-buffer-with-faces (concat (file-name-nondirectory
(file-name-sans-extension source))
".ps"))))
(ps-batch-print command-line-args-left)
As always, Emacs packages print tons of messages irrelevant when in batch mode. You can get rid of them by redirecting stderr using 2> /dev/null, if you are using a UNIX-like system.

How to start in the middle of command input

How can I have emacs start and be in the middle of a command input? Particularly, I want emacs to start in the middle of a command input find-file with a message in the small buffer saying:
Find file: ~/
and the cursor at the last character of it so that I can continue typing the remaining path to open the file I want.
You can execute one of the following commands on the command prompt or make a shell script containing it appropriately:
$ emacs -f find-file # if you want to start Emacs in the current direcoty
$ (cd ~; emacs -f find-file) # if you want to start Emacs in your home diretory
From the emacs(1) man page:
-f function, --funcall function
Excute the lisp function function
I have to admit that my lisp is a bit rusty, but this works for me. Drop it in your ~/.emacs file (or whatever init file you are using):
(add-hook 'emacs-startup-hook
(lambda ()
(if (= (length command-line-args) 1)
(call-interactively 'find-file))))
If you call emacs with no arguments, like this:
sawa#localhost:~$ emacs
It will invoke find-file for you. If, on the other hand, you invoke emacs with an argument, such as a filename, like this:
sawa#localhost:~$ emacs somefile.txt
It will default to just visiting somefile.txt

How can the *shell command output* buffer be kept in the background?

How can I tell emacs not to pop up the *Shell Command Output* buffer when calling a shell command like this?
(shell-command MY_COMMAND)
Currently emacs splits the current window into two, showing the (mostly irrelevant) output buffer. To me it would be completely sufficient if I could look it up later if I feel like it.
Maybe using shell-command was the root of the problem. I think I found a solution with call-process which works, although there may be a more elegant way:
(call-process-shell-command
"cat ~/.emacs.d/init.el"
nil "*Shell Command Output*" t
)
shell-command takes an optional argument OUTPUT-BUFFER where you can specify the buffer to output to. If it is t (actually not a buffer-name and not nil) it will be output in the current buffer. So we wrap this into a with-temp-buffer and will never have to bother with it:
(with-temp-buffer
(shell-command "cat ~/.emacs.d/init.el" t))
In my experience, if the shell command itself produces no output, then the emacs *Shell Command Output* buffer won't pop open.
Therefore, to avoid the output buffer, silence the output of the command.
One easy way is:
add " > /dev/null 2>&1" to the end of any shell command.
(Caveat: I'm unsure if /dev/null exists on 100% of platforms where one can run emacs, but on every Linux distro it should be fine.)
If the call to elisp function shell-command is in an elisp script, then you could change this:
(shell-command cmd)
to this:
(shell-command (concat cmd " > /dev/null 2>&1"))
If you occasionally do want to monitor the output, then you could create one wrapper function that suppresses the output via /dev/null, and one wrapper function with no suppression, and toggle between them as you wish.
The above advice was tested on: GNU Emacs 24.5.1 (x86_64-pc-linux-gnu, GTK+ Version 3.18.9) of 2017-09-20 on lcy01-07, modified by Debian
This utility function might help. It returns the actual value of the shell command
(defun shell-command-as-string (cmd)
(with-temp-buffer
(shell-command-on-region (point-min) (point-max)
cmd t)
(buffer-string)))
What's even better, is to use
(shell-command (concat cmd " 1>&2") t t)
This way, the output is saved in the error buffer, should you want to look at it. But it does not pop up automatically.

Emacs compilation mode won't see bash alias

Emacs M-x compile does not see any aliases set in .bashrc. If I use M-x shell then type the alias, it is fine. I tried sourcing .bashrc from /etc/profile, from ~/.profile, ~/bash_env, anything I can think of to no avail.
I am on Emacs 23 and Ubuntu 11. I start emacs using /usr/bin/emacs %F, from a desktop button.
Emacs inherits its environment from the parent process. How are you invoking Emacs - from the command line, or some other way?
What happens if you:
M-x compile RET C-a C-k bash -i -c your_alias RET
Invoking bash as an interactive shell (-i option) should read your .bashrc aliases.
Edit: I think both M-x shell-command and M-x compile execute commands in an inferior shell via call-process. Try the following in your .emacs (or just evaluate):
(setq shell-file-name "bash")
(setq shell-command-switch "-ic")
I notice that after evaluation of the above, .bashrc aliases are picked up for use by both M-x shell-command and M-x compile, i.e
M-x compile RET your_alias RET
should then work.
My environment: Emacs 24.1 (pretest rc1), OSX 10.7.3
Keith Flower's answer works but can result in some slowdowns due to .bashrc being unnecessarily loaded in other places (presumably many many times, my computer is not exactly under-powered but emacs was almost unusable when trying to use autocomplete.el).
An alternative way is to locally modify shell-command-switch only for the functions where it is needed. This can be done using emacs' "advice" feature to create a wrapper around those functions. Here's an example that modifies compile:
;; Define + active modification to compile that locally sets
;; shell-command-switch to "-ic".
(defadvice compile (around use-bashrc activate)
"Load .bashrc in any calls to bash (e.g. so we can use aliases)"
(let ((shell-command-switch "-ic"))
ad-do-it))
You need to write similar "advice" for each function that you want to use .bashrc (e.g. I also needed to define the same advice for recompile), just copy the above and replace compile in the above with another function name.
You may like emac's bash-completion :
https://github.com/szermatt/emacs-bash-completion
You'll be able to use tab completion of your aliases in the compilation minibuffer and in shell-mode.
Enjoy !
(they speak about it here Bash autocompletion in Emacs shell-mode )
I think compilation commands are not interpreted through a shell: they are juste exec'ed by emacs (which means aliases, shell functions and other shell-specific things are not taken into account).
Try to wrap you compilation command into a shell-script which would source the correct environment.
You can do this either with a full-fledged shell-script in the form
#!/bin/bash
source "~/.bashrc"
my_command
or directly in emacs with a compilation command of the form
bash -c "source ~/.bashrc; my_command"
See Is there a way to get my emacs to recognize my bash aliases and custom functions when I run a shell command? for a fix which doesn't run all your .bashrc and doesn't create these error messages:
bash: cannot set terminal process group (-1): Inappropriate ioctl for device
bash: no job control in this shell

I want to run the cygwin bash shell from native windows emacs app

I have followed instructions from How can I run Cygwin Bash Shell from within Emacs? this question and I have gone further and added the (setq explicit-bash-args '("--login" "-i")) command, however emacs continues to only display the dos prompt when I type M-x shell. In summery my .emacs file looks like this:
(defun cygwin-shell ()
"Run cygwin bash in shell mode."
(interactive)
(let ((explicit-shell-file-name "C:/cygwin/bin/bash"))
(call-interactively 'shell)))
(setq explicit-bash-args '("--login" "-i"))`
Please be gentle with the answers as I am right at the bottom of the famous vertical emacs learning curve!
If you implemented the answer from that question, note that you have to do M-x cygwin-shell to start bash. If you want to use it for every M-x shell you need to call
(setq explicit-shell-file-name "C:/cygwin/bin/bash")
Since you stated that you are learning, here's a few tips when trying this out.
type C-x C-f ~/.emacs to open your .emacs file in your user path.
Enter your function above at the end
M-x load-file [RET] .emacs: loads the buffer (no need to restart emacs)
C-h a: If you are interested in some specific action, you can look it up
C-h v [RET] variable: can inspect the variable, check the value of explicit-bash-args for instance
And, btw, I'm not sure what the "--login -i" does, but someone stated in a comment that you should have that so "ls" would work. If you have your cygwin bin path in your PATH environment variable, bash will find ls anyway. No need to escape the path variable either, this is handled by bash (do an echo $PATH in bash when you get it working and you'll see).