Emacs shell scripts - how to put initial options i

2019-01-08 12:55发布

Inspired by Stack Overflow question Idomatic batch processing of text in Emacs? I tried out an Emacs shell script with the following headline:

#!/usr/bin/emacs --script 

I put some Emacs Lisp code in it, and saved it as textfile rcat.

Since the --script option does not prevent the loading of the site-start file, I had a lot of

Loading /etc/emacs/site-start.d/20apel.el (source)...
Loading /etc/emacs23/site-start.d/35elib-startup.el (source)...
Loading /etc/emacs23/site-start.d/50auctex.el (source)...

messages in the Bash shell (stdout). I can prevent that by calling

rcat --no-site-file

or

rcat -Q

but not by changing the headline in the script:

 #!/usr/bin/emacs --script --no-site-file

Is there a way to pass additional options to Emacs inside such a script file instead of doing it later on the commandline?

3条回答
【Aperson】
2楼-- · 2019-01-08 13:42

You could always change #!/usr/bin/emacs to something like #!/home/thorsten/bin/emacs-no-site-file, and set that up as:

#!/bin/sh
exec /usr/bin/emacs --no-site-file "$@"

If this doesn't work for you, or if you wish your script to be portable, then see Gilles' answer below for a more robust (and slightly funky :) approach.

查看更多
男人必须洒脱
3楼-- · 2019-01-08 13:47

Many unix variants only allow a single argument to the program on the shebang line. Sad, but true. If you use #!/usr/bin/env emacs so as not to depend on the location of the emacs executable, you can't pass an argument at all.

Chaining scripts is a possibility on some systems, but that too is not supported everywhere.

You can go the time-honored route of writing a polyglot script: a script that is both a shell script and an Emacs Lisp script (like Perl's if $running_under_some_shell, for example). It sure looks hackish, but it works.

Elisp comments begin with ;, which in the shell separates two commands. So we can use a ; followed by a shell instruction to switch over to Emacs, with the actual Lisp code beginning on the next line. Most shells don't like an empty command though, so we need to find something that both the shell and Emacs treat as a no-op, to put before the ;. The shell no-op command is :; you can write it ":" as far as the shell is concerned, and Emacs parses that as a constant at top level which is also a no-op.

#! /bin/sh
":"; exec emacs --no-site-file --script "$0" -- "$@" # -*-emacs-lisp-*-
(print (+ 2 2))
查看更多
冷血范
4楼-- · 2019-01-08 13:47

If you run emacs in script mode, I would recommend to reset "argv" variable to nil in the end of your script, otherwise emacs will try interpret "argv" after script is finished.

Let's assume you have a file named "test-emacs-script.el" with the following content:

#!/usr/bin/emacs --script
(print argv)
(setq argv nil)

Try running this script as "./test-emacs-script.el -a". If you run this script without resettings "argv" (last line in the script) then the output will be:

("-a")
Unknown option `-a'

Resetting "argv" gets rid of "unknown option" error message

查看更多
登录 后发表回答