From: Pascal Bourguignon <spam@thalassa.informatimago.com>
Subject: Re: Cool and Useful LISP for the .emacs file
Date: 12 Nov 2003 19:21:19 +0100 [thread overview]
Message-ID: <873cctih28.fsf@thalassa.informatimago.com> (raw)
In-Reply-To: m3islqw4kq.fsf@batcave.m198-149.dsl.rawbw.com
David Masterson <dsm@rawbw.com> writes:
> >>>>> Artur Hefczyc writes:
>
> > Kin Cho <kin@techie.com> writes:
> >> I used to carry around a collection of shell, sed, awk, and perl
> >> scripts to do various text/file/directory processing, as well as
> >> doing cvs/rcs stuff, running compilation and gdb etc... Now I do
> >> (almost) all these things in elisp.
>
> > I like this idea! I would like to use elisp as scripting language
> > also. However I would like to know if it is possible to use it that
> > way. I mean, lets assume I create elisp script to update my Linux box
> > system with new releases of some packages.
>
> > Is it possible to run it from command line like all other scripts,
> > bash, perl etc.?
>
> > I mean file script starting from:
> > #!/usr/bin/emacs
>
> > Or any other elisp interpreter?
>
> Given how big Emacs is, I would think that it would be best to start
> emacs in background (say, from your .login) and then use something
> like gnudoit or emacsclient to send your elisp to the background
> Emacs. Done correctly, I would think that it would execute your
> scripts much faster, no?
No.
emacs IS NOT big.
$ ls -l emacs perl
-rwxr-xr-t 1 pascal regular 4433296 2003-11-12 19:08 emacs*
-rwxr-xr-x 1 pascal regular 1113248 2003-11-12 19:08 perl*
emacs is already in core memory so forking additionnal emacs processes
does not cost anything significant.
Starting a script in perl or in emacs takes the same time. (Any time
below 0.7 s IS the same time).
#!/bin/bash
echo =================================================
time emacs -batch -no-site-file -q \
-eval '(progn (message "Hello from emacs") (kill-emacs))'
echo =================================================
time clisp -q -ansi -norc \
-x '(progn (format t "Hello from clisp!~%") (ext:quit))'
echo =================================================
time sbcl --noinform --noprint --sysinit /dev/null --userinit /dev/null \
--eval '(progn (format t "Hello from sbcl!~%") (SB-EXT:QUIT))'
echo =================================================
echo '(display "Hello from scsh\n") ,exit' | bash -c 'time scsh'
echo =================================================
time perl -e 'printf "Hello from perl\n";exit'
echo =================================================
exit 0
./script-times
=================================================
Hello from emacs
real 0m0.060s
user 0m0.040s
sys 0m0.010s
=================================================
Hello from clisp!
real 0m0.023s
user 0m0.010s
sys 0m0.010s
=================================================
Hello from sbcl!
real 0m0.024s
user 0m0.010s
sys 0m0.010s
=================================================
Scsh 0.5.3
> Hello from scsh
#f
>
real 0m0.076s
user 0m0.030s
sys 0m0.020s
=================================================
Hello from perl
real 0m0.009s
user 0m0.000s
sys 0m0.000s
=================================================
To allow the use of #! for emacs, I implemented this small wrapper:
lisp-script.c:
------------------------------------------------------------------------
/******************************************************************************
FILE: lisp-script.c
LANGUAGE: ANSI-C
SYSTEM: POSIX
USER-INTERFACE: POSIX
DESCRIPTION
This is a simple tool that encapsulate clisp or emacs invokation as
script interpreters.
USAGE
Insert #!/usr/local/bin/emacs-script
or #!/usr/local/bin/clisp-script
as the first line of a lisp program, and run it.
AUTHORS
<PJB> Pascal J. Bourguignon
MODIFICATIONS
2003-10-27 <PJB> Added SBCL.
2002-04-06 <PJB> Creation.
BUGS
LEGAL
GPL
Copyright Pascal J. Bourguignon 2002 - 2003
This file is part of lisp script tools.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; see the file COPYING; if not, write to
the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
Boston, MA 02111-1307 USA
******************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sysexits.h>
#ifndef EMACS
#define EMACS "/usr/local/bin/emacs"
#endif
#ifndef CLISP
#define CLISP "/usr/local/bin/clisp"
#endif
#ifndef SBCL
#define SBCL "/usr/local/bin/sbcl"
#endif
#ifdef MACOSX
/* Not exactly correct. We should grab GNU dirname/basename.*/
static const char* basename(const char* path)
{
const char* slash=strrchr(path,'/');
if(slash==0){
return(path);
}else{
return(slash+1);
}
}/*basename*/
#else
#include <libgen.h>
#endif
const char* pname="lisp-script";
void usage(const char* pname)
{
fprintf(stderr,
"%s usage:\n"\
" %s -h|--help | script-file [script-arguments...]\n",
pname,pname);
}/*usage*/
int main(int argc,char** argv)
{
int i;
int length;
int position;
char* script_file=0;
char* script_option;
char* init_file;
enum { emacs, clisp, sbcl } kind;
pname=basename(argv[0]);
if(strcmp(pname,"emacs-script")==0){
kind=emacs;
}else if(strcmp(pname,"clisp-script")==0){
kind=clisp;
}else if(strcmp(pname,"sbcl-script")==0){
kind=sbcl;
}else{
lisp_script:
fprintf(stderr,"%s: should be invoked either as emacs-script, "
"clisp-script or sbcl-script.\n",pname);
return(EX_USAGE);
}
if((strcmp(argv[1],"-h")==0)||(strcmp(argv[1],"--help")==0)){
usage(pname);
return(EX_OK);
}
if(1<argc){
script_file=argv[1];
}else{
fprintf(stderr,"%s: missing script-file argument.\n",pname);
usage(pname);
return(EX_USAGE);
}
if(0!=access(script_file,R_OK)){
fprintf(stderr,"Can't read script file '%s'.\n",script_file);
return(EX_NOINPUT);
}
init_file=(char*)malloc(strlen(argv[0])+8);
switch(kind){
case emacs:
sprintf(init_file,"%s.el",argv[0]);
break;
case clisp:
case sbcl:
sprintf(init_file,"%s.lisp",argv[0]);
break;
default:
goto lisp_script;
}
if(0!=access(init_file,R_OK)){
fprintf(stderr,"Can't read %s init file '%s'.\n",argv[0],init_file);
return(EX_UNAVAILABLE);
}
length=0;
for(i=1;i<argc;i++){
length+=3+strlen(argv[i]);
}
script_option=(char*)malloc(length+16);
position=0;
position+=sprintf(script_option+position,"(script ");
for(i=1;i<argc;i++){
position+=sprintf(script_option+position,"\"%s\" ",argv[i]);
}
position+=sprintf(script_option+position,")");
/*
fprintf(stderr,"init_file=%s\n",init_file);
fprintf(stderr,"script_option=%s\n",script_option);
*/
switch(kind){
case emacs:
execl(EMACS,"emacs","--batch","--no-site-file","--no-init-file",
"--load",init_file,
"--eval",script_option,
0);
fprintf(stderr,"Can't execl '%s'.\n",EMACS);
break;
case clisp:
execl(CLISP,"clisp","-q",
"-i",init_file,
"-x",script_option,
0);
fprintf(stderr,"Can't execl '%s'.\n",CLISP);
break;
case sbcl:
execl(SBCL,"sbcl","--noinform",
"--userinit",init_file,
"--eval",script_option,
0);
fprintf(stderr,"Can't execl '%s'.\n",SBCL);
break;
default:
goto lisp_script;
}
return(EX_UNAVAILABLE);
}/*main*/
/*** lisp-script.c -- 2003-10-27 22:57:16 -- pascal ***/
------------------------------------------------------------------------
emacs-script.el:
------------------------------------------------------------------------
;;
;; elisp initialization for emacs scripts.
;; We try to install some stuff to make it more like Common-Lisp.
;; GPL
;; (add-to-list 'load-path "")
(require 'cl)
(defun script (file &rest arguments)
"
DO: reads the FILE, skip the first line if it begins with '#!' and
"
(unless (file-readable-p file)
(error "Can't read file %S." file))
(setq ext:*args* arguments)
(setq *load-pathname* file)
(setq *LOAD-PATHNAME* *load-pathname*
EXT:*ARGS* ext:*args*)
(find-file file)
(let ((buf (current-buffer)))
(unwind-protect
(progn
(toggle-read-only 1)
(goto-char (point-min))
(if (looking-at "#!")
(forward-line 1))
(narrow-to-region (point) (point-max))
(eval-buffer)
)
(kill-buffer buf)))
);;script
;; Exit status from <sysexit.h>
(defconst EX_OK 0 "successful termination")
(defconst EX__BASE 64 "base value for error messages")
(defconst EX_USAGE 64 "command line usage error")
(defconst EX_DATAERR 65 "data format error")
(defconst EX_NOINPUT 66 "cannot open input")
(defconst EX_NOUSER 67 "addressee unknown")
(defconst EX_NOHOST 68 "host name unknown")
(defconst EX_UNAVAILABLE 69 "service unavailable")
(defconst EX_SOFTWARE 70 "internal software error")
(defconst EX_OSERR 71 "system error (e.g., can't fork)")
(defconst EX_OSFILE 72 "critical OS file missing")
(defconst EX_CANTCREAT 73 "can't create (user) output file")
(defconst EX_IOERR 74 "input/output error")
(defconst EX_TEMPFAIL 75 "temp failure; user is invited to retry")
(defconst EX_PROTOCOL 76 "remote error in protocol")
(defconst EX_NOPERM 77 "permission denied")
(defconst EX_CONFIG 78 "configuration error")
(defconst EX__MAX 78 "maximum listed value")
(defun ext:exit (&optional status)
"
DO: stops the script, exiting with the given status.
"
(unless status (setq status EX_OK))
(kill-emacs status)
);;ext:exit
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Common-Lisp / Elisp
(defun read-line (&optional input-stream eof-error-p eof-value recursive-p)
"
DO: Implement partially Common-Lisp read-line function.
"
(unless input-stream (setq input-stream standard-input))
(let ( (standard-input input-stream)
(line nil)
(char (read-char)) )
(while (not (member char '(10 13)))
(push char line)
(setq char (read-char)) )
(funcall 'concat (nreverse line))
);;let
);;read-line
(defalias 'EXT:EXIT 'ext:exit)
(defalias 'READ-LINE 'read-line)
;;;; emacs-script.el -- 2003-02-08 04:35:08 -- pascal ;;;;
------------------------------------------------------------------------
--
__Pascal_Bourguignon__
http://www.informatimago.com/
next prev parent reply other threads:[~2003-11-12 18:21 UTC|newest]
Thread overview: 61+ messages / expand[flat|nested] mbox.gz Atom feed top
[not found] <mailman.3343.1068146343.21628.help-gnu-emacs@gnu.org>
2003-11-06 23:45 ` Cool and Useful LISP for the .emacs file Kevin Rodgers
2003-11-07 4:10 ` Bruce Ingalls
2003-11-07 9:08 ` roodwriter
2003-11-07 16:58 ` Kevin Rodgers
2003-11-07 18:35 ` roodwriter
2003-11-08 18:01 ` roodwriter
2003-11-11 10:48 ` Oliver Scholz
2003-11-07 11:27 ` Gareth Rees
2003-11-07 14:06 ` Adam Hardy
[not found] ` <mailman.3403.1068214062.21628.help-gnu-emacs@gnu.org>
2003-11-07 14:28 ` David Kastrup
2003-11-07 16:54 ` Dan Anderson
2003-11-07 17:19 ` Rob Thorpe
[not found] ` <mailman.0.1068227823.2005.help-gnu-emacs@gnu.org>
2003-11-07 17:45 ` Jody M. Klymak
2003-11-07 18:20 ` Kevin Rodgers
2003-11-07 19:37 ` Dan Anderson
[not found] ` <mailman.11.1068237562.2005.help-gnu-emacs@gnu.org>
2003-11-07 22:17 ` Jody M. Klymak
2003-11-08 1:22 ` Jesper Harder
2003-11-08 3:23 ` Kin Cho
2003-11-08 10:34 ` Artur Hefczyc
2003-11-08 13:20 ` Thien-Thi Nguyen
2003-11-08 20:06 ` David Kastrup
2003-11-08 21:45 ` Artur Hefczyc
2003-11-08 22:02 ` Artur Hefczyc
2003-11-09 3:20 ` Kin Cho
2003-11-12 5:15 ` David Masterson
2003-11-12 8:12 ` Matthew Kennedy
2003-11-12 18:21 ` Pascal Bourguignon [this message]
2003-11-13 19:54 ` Artur Hefczyc
2003-11-23 8:08 ` Tim X
2003-11-08 23:15 ` Joe Fineman
2003-11-10 15:59 ` Stefan Monnier
2003-11-10 20:58 ` Thien-Thi Nguyen
2003-11-10 21:00 ` Burton Samograd
2003-11-11 10:34 ` Alan Mackenzie
2003-11-11 14:32 ` Jesper Harder
2003-11-11 17:00 ` Burton Samograd
2003-11-11 17:00 ` Burton Samograd
2003-11-11 20:04 ` Alan Mackenzie
2003-11-08 10:15 ` Oliver Scholz
2003-11-08 12:03 ` Orm Finnendahl
2003-11-08 1:28 ` Thien-Thi Nguyen
2003-11-08 14:09 ` Ole Laursen
2003-11-23 8:02 ` Tim X
2003-12-07 15:56 ` Kai Grossjohann
2003-11-07 18:09 ` Reiner Steib
2003-11-07 18:37 ` lawrence mitchell
2003-11-08 17:06 ` Reiner Steib
2003-11-07 23:41 ` Edward Dodge
2003-11-10 16:04 ` Stefan Monnier
2003-11-10 21:17 ` kgold
2003-11-11 10:43 ` Alan Mackenzie
2003-11-11 15:39 ` Eli Zaretskii
2003-11-11 15:52 ` Stefan Monnier
2003-11-11 17:35 ` Thien-Thi Nguyen
2003-11-12 7:25 ` Lars Brinkhoff
[not found] ` <mailman.197.1068625639.2005.help-gnu-emacs@gnu.org>
2003-11-12 10:22 ` Colin Marquardt
2003-11-12 11:15 ` David Kastrup
2003-11-12 13:47 ` Stefan Monnier
[not found] <E1AIRNX-0002YI-H9@monty-python.gnu.org>
2003-11-08 22:01 ` Joe Corneli
[not found] <E1AI57v-00032q-9p@monty-python.gnu.org>
2003-11-07 14:31 ` Joe Corneli
2003-11-06 19:18 Dan Anderson
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
List information: https://www.gnu.org/software/emacs/
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=873cctih28.fsf@thalassa.informatimago.com \
--to=spam@thalassa.informatimago.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).