[comp.emacs] Lisp Programming: Substring Searches, etc.

chris@lxn.eds.com (Christopher D. Orr) (07/09/89)

I am trying to write an extention to GNU Emacs that will perform a
function based upon characteristics of the filename.  Mainly, what I
want to be able to do is to perform a case statment such as the
following shell extract:

    case $FILE_EXT in
         c)  SUBBASE=`echo $1 | cut -c1-3 | tr [a-z] [A-Z]`;;
         h)  SUBBASE=`echo $1 | cut -c1-3 | tr [a-z] [A-Z]`;;
         f)  SUBBASE=FILESPEC;;
         s)  SUBBASE=`echo $1 | cut -c1-3 | tr [a-z] [A-Z]`;;
         m)  SUBBASE=MENUSPEC;;
         *)  SUBBASE=MISC
             FILE=$1;;

where FILE_EXT is set to the extention of the file being operated on.

My questions are:

	1)  How do I set up a case statement in GNU Lisp to perform
	    this?
	2)  How do you extract a substring from a string object (i.e.
            buffer-file-name) ?	 I need to be able to scan for the
	    period "." and then operate on the remaining portion of
            the string in the case statement.

Any help that anybody can provide will be very helpfull!!!

			--Chris

-- 
Christopher D. Orr                  | US MAIL: Electronic Data Systems (EDS)
UUCP: vu-vlsi!lxn!chris             |          Lanark Building
 or   chris%lxn.uucp@rutgers.edu    |          Center Valley, PA  18034
 or   lehi3b15!lxn!chris            | Voice:   (215) 282-1213

Duchier-Denys@cs.yale.edu (Denys Duchier) (07/10/89)

(defun extract-file-extension (filename)
  (and (string-match ".+\\.\\(.*\\)$" filename)
       (substring filename (match-beginning 1) (match-end 1))))

after setting file-ext to the proper file extension you could do
something like this:

(cond ((string-equal file-ext "c") ...)
      ((string-equal file-ext "h") ...)
      ...
      (t ...))

Perhaps it would be best to define a function like the following

(defun act-according-to-extension ()
  (let ((file-ext (extract-file-extension buffer-file-name)))
    (cond ((string-equal file-ext "c") ...)
          ((string-equal file-ext "h") ...)
          ...
          (t ...))))

and then do

(setq find-file-hooks (cons 'act-according-to-extension find-file-hooks))

You should look up the documentation for find-file-hooks and auto-mode-alist

--Denys

spencer@eecs.umich.edu (Spencer W. Thomas) (07/10/89)

In article <65891@yale-celray.yale.UUCP> Duchier-Denys@cs.yale.edu (Denys Duchier) writes:
   (defun extract-file-extension (filename)
     (and (string-match ".+\\.\\(.*\\)$" filename)
	  (substring filename (match-beginning 1) (match-end 1))))

Actually, probably better would be
	 (string-match ".+\\.\\([^.]*\\)$" filename)
This pattern will match the last ".", while the given pattern will
match the first one.

--
=Spencer (spencer@eecs.umich.edu)

Duchier-Denys@cs.yale.edu (Denys Duchier) (07/10/89)

In article <SPENCER.89Jul9162408@spline.eecs.umich.edu>, spencer@eecs (Spencer W. Thomas) writes:
> In article <65891@yale-celray.yale.UUCP> Duchier-Denys@cs.yale.edu (Denys Duchier) writes:
>    (defun extract-file-extension (filename)
>      (and (string-match ".+\\.\\(.*\\)$" filename)
> 	  (substring filename (match-beginning 1) (match-end 1))))
> 
> Actually, probably better would be
> 	 (string-match ".+\\.\\([^.]*\\)$" filename)
> This pattern will match the last ".", while the given pattern will
> match the first one.
> 
> --
> =Spencer (spencer@eecs.umich.edu)

Wrong, .+ eats up as much of the string as possible. The version you
propose can be simplified to "\\.\\([^.]*\\)$", but I rejected it when
I wrote the proposed solution because I didn't want files like .login
to be mistaken for files with an empty name and just an extension.

--Denys

julian@uhccux.uhcc.hawaii.edu (Julian Cowley) (07/10/89)

In article <SPENCER.89Jul9162408@spline.eecs.umich.edu> spencer@eecs.umich.edu (Spencer W. Thomas) writes:
>In article <65891@yale-celray.yale.UUCP> Duchier-Denys@cs.yale.edu (Denys Duchier) writes:
>   (defun extract-file-extension (filename)
>     (and (string-match ".+\\.\\(.*\\)$" filename)
>	  (substring filename (match-beginning 1) (match-end 1))))
>
>Actually, probably better would be
>	 (string-match ".+\\.\\([^.]*\\)$" filename)
>This pattern will match the last ".", while the given pattern will
>match the first one.

This has kind of regexp has come up before, I think.  Two things
need pointing out:

1) The above regexps incorrectly return the names of hidden
files.  E.g.,
	(extract-file-extension "~/.letter")
returns
	"letter".
The correct result should be nil.

2) They also don't work with directories.  E.g.,
	(extract-file-extension "/usr/lib/sccs.help/cmds")
returns
	"help/cmds".
Again, the correct result should be nil.

So, here is an improved regexp that correctly handles the above
cases:

	(string-match "[^/]\\.\\([^/.]*\\)$" filename)

julian@uhccux.uhcc.hawaii.edu	| "Hawaii has always been a very pivotal role 
uunet!ucsd!nosc!uhccux!julian	|  in the Pacific.  It is in the Pacific.
julian@uhccux.bitnet		|  It is part of the United States that is an
University of Hawaii at Manoa	|  island that is right here." - Quayle