unofficial mirror of help-gnu-emacs@gnu.org
 help / color / mirror / Atom feed
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/

  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).