emacs --daemon with --batch and input file - emacs

I would like to create a script that simply cleans up the whitespace and tabs on several files in a folder for me. I have created a bash file with among other things:
emacsclient -t -e '(progn (prelude-cleanup-buffer-or-region) (save-buffer-kill-terminal))' $FILE
Now this doesn't seem to work as it interprets ALL the file arguments as functions to be run (so $FILE is executed as a function). (P.S. prelude-cleanup-buffer-or-region is from here)
Now what I really want appears to be --batch described here (since I don't actually want to display anything on the screen) but this isn't one of the options of emacsclient. The reason I want to use emacsclient rather than just using emacs --batch is that I have a lot of startup files so want all of this to stay loaded otherwise my script would take too long.
Does anyone have any advice on how to go about this?
Thanks in advance.

emacsclient -e means evaluate lisp forms, do not edit files
from the man page
-e, --eval
do not visit files but instead evaluate the arguments as Emacs
Lisp expressions.
I guess you could add a (find-file "file") to your list of forms to execute
I just tried this snippet -
/opt/local/bin/emacsclient -e '(progn (find-file "./tmpfoo")
(end-of-buffer) (insert "ffff") (save-buffer))'
and it edits the file silently like you'd expect.
you could use shell globbing and a script to expand an argument filename into the list of forms.
do not run with the -t switch either, -e doesn't expect to have a persistent editor window, and you don't need the kill-terminal. The client will just run your elisp and exit.
I think I would probably write a lisp function that took a filename argument, that I loaded into emacs at startup time, and then just call that with a filename via emacsclient,
e.g. FILENAME="somefile"; emacsclient -e "(now-do-my-thing $FILENAME)"

Related

Emacsclient called by applescript can't find emacs server socket

The shell command
emacsclient -n -e '(make-remember-frame)'
works.
But the applescript
do shell script "emacsclient -n -e '(make-remember-frame)'"
just returns
emacsclient: can't find socket; have you started the server?
To start the server in Emacs, type \"M-x server-start\".
emacsclient: No socket or alternate editor. Please use:
--socket-name
--server-file (or environment variable EMACS_SERVER_FILE)
--alternate-editor (or environment variable ALTERNATE_EDITOR)
I rarely use this, but it has worked successfully in the past for various purposes. Perhaps you can modify it to suit your needs. The init.el or .emacs file must have (server-start) inside in order to make everything work. I have lots of stuff that loads when Emacs is activated for the first time, so I need a 5 second delay before emacsclient is called -- you can adjust the delay downward if your Emacs loads faster. If Emacs is already running, there is no need for a delay. You can comment out the verbal messages generated by say -- I used them this morning to test the conditions and make a minor adjustment to the script. The script contains a command-line example on line 4, which calls two Emacs functions. Of course, the path to your Emacs and emacsclient will need to be adjusted to wherever you have installed them on your computer.
# `(server-start)` must be inside `init.el` or `.emacs` file.
# This script can be used in the terimal: osascript path-to-script arguments
# Terminal Example:
# osascript /Users/HOME/.0.data/.0.emacs/.emacsclient.applescript "-e '(progn (dired \"/Applications\") (message \"Hello-World\!\"))'"
on run argv
set arg to item 1 of argv
set emacs to application "Emacs"
set appIsRunning to emacs is running
if appIsRunning then
say "Emacs is already running."
do shell script "/Users/HOME/.0.data/.0.emacs/Emacs_06_01_2014.app/Contents/MacOS/bin/emacsclient " & arg
else
tell application "/Users/HOME/.0.data/.0.emacs/Emacs_06_01_2014.app/Contents/MacOS/Emacs" to activate
say "Please wait five seconds for Emacs to load."
delay 5
do shell script "/Users/HOME/.0.data/.0.emacs/Emacs_06_01_2014.app/Contents/MacOS/bin/emacsclient " & arg
end if
end run

How to stop Emacs from rendering junk characters in shell?

In my emacs shell, I see this output:
^[[J~% echo $PS1
%2c%%
On my other machine, this stuff doesn't show up at all. Can anyone suggest a reason why and how to fix it?
It's related to your PS1 setting. Basically Emacs will not accept TOO fancy settings of PS1. I used the following code in ~/.bashrc to distinguish PS1 between xterm and other term simulators such as Emacs. You can give it a try.
case $TERM in
xterm)
export PS1='\[\e]0;\u#\h: \W\a\]\[\e[31;1m\]\w\n\[\e[0m\]'
;;
*)
export PS1='\[\e[31;1m\]\w\n\[\e[0m\]'
;;
esac

How to view man pages using emacs when invoking man command in command line?

I would like to view man pages using emacs when invoking man command.
I modified the pager parameter in /etc/man.conf PAGER to emacs.
But, it doesn't work. Is there anything I should modify ?
Indeed, emacs cannot read STDIN into a buffer, meaning
cat foobar | emacs
does not work in any case. So setting your PAGER variable to 'emacs', or 'emacs -nw' does not do the job.
Only way around I see is to write the man output into a tmp-file and then load that file into emacs:
man find > tmp-file; emacs tmp-file
You could alias this.
For example, assuming a tc-shell, and a directory called 'tmp' in your home-path, you can put the following line into your ~/.tcshrc file:
alias man '/usr/bin/man \!* > ~/tmp/tmp-file; emacs ~/tmp/tmp-file; rm ~/tmp/tmp-file'
So next time you call man find, emacs will fire up.
Emacs has a "Man mode", which can be invoked by M-x man RET and then typing in your command.
You can profit from emacs's function man. Just define a function in bash that will run emacs that will call it:
function man () {
emacs -e '(man "'"$1"'")'
}
You might want to call emacs -nw or even emacsclient instead.

Running emacs from the command line and handling locked files

I'm using org-mode and am looking to export my agenda (example of an agenda) to a text file so that I can display it with conky. The org-mode manual features this command line example to do this:
emacs -batch -l ~/.emacs -eval '(org-batch-agenda "t")' | lpr
I've modified this like so:
emacs -batch -l ~/.emacs -eval '(org-batch-agenda "e")' \
> ~/org/aux/agenda-export.txt
I have this set as a cron job to run every 5 minutes. It works great unless I actually have emacs open. Then I noticed that the file agenda-export.txt was empty. In running this manually from the coammand line vs. through cron, I get this error (or similar depending on the files I have open):
...~/org/file.org locked by jwhendy (pid 10935): (s, q, p, ?)?
I was going to write a script to perhaps export to agenda-export-test.txt, then perhaps check for an empty file or no lines (wc -l == 0 maybe?). If true, leave the existing file alone and delete agenda-export-test.txt. If not, then move agenda-export-test.txt to agenda-export.txt.
But... when I try to run such a script, I'm met with the same emacs inquiry about whether to steal the lock, proceed, or quit. I'm fine with proceeding, as I don't think org-agenda does anything to the files and thus it wouldn't harm anything... but I don't know how to tell emacs to "force" or choose "proceed" if problems are encountered. I need something non-interactive.
So, to summarize, my thoughts were to try:
passing a --force option or similar to emacs to make it proceed at the pause
see if the exported tmp file has any lines and deal with it accordingly
tell emacs to run in "read only mode" (but I don't think it exists)
The main issue is that with cron, I'm not there to tell the process what to do, and so it just just make an empty file as the exported results. How can I handle this locked file business with a "blind" process like cron that can't respond?
I've tried asking the mailing list as well without a working outcome. [1] I wondered if someone here might have ideas.
[1] http://www.mail-archive.com/emacs-orgmode#gnu.org/msg45056.html
Have you tried copying file without using emacs?
put in your crontab:
cp ~/org/file.org /tmp/export.org && emacs -batch .... /tmp/export.org ..
A regular "cp" command should not copy emacs locks. Of course, once in a while you might get a damaged file if you save agenda just during cp command, but this should not be too bad.

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.