dirname wanted

For the Compleat Fan
Locked
scratchy
Posts: 14
Joined: Sat Aug 14, 2004 10:41 pm

dirname wanted

Post by scratchy »

Ok, here is a question:

If I am writing several scripts, and I want to put reusable definitions into a separate file, for instance:

/home/scratchy/bin/a.lsp <-- one script
/home/scratchy/bin/b.lsp <-- another script
/home/scratchy/lib/common.lsp <-- reusable stuff

Obviously, in a.lsp and b.lsp I need to locate common.lsp, soft of:

(load (sting (dirname (nth 1 (main-args))) "../lib/common.lsp"))

[correct me if I'm wrong]. However, I wasn't able to find any built-in "dirname" function. If it's not built-in => I would have to implement it myself => I can't put it into common.lsp because I need it before any file is loaded. Duplicating dirname in the beginning of each script is plain ugly. So is there an elegant solution to this problem?

Lutz
Posts: 5289
Joined: Thu Sep 26, 2002 4:45 pm
Location: Pasadena, California
Contact:

Post by Lutz »

newLISP looks for init.lsp in /usr/share/newlisp/init.lsp on Linux/UNIX or in the newLISP startup directory on Win32. The stuff you find in init.lsp from the distribution is not really required and you can throw it out and replace it with your own stuff.

You could put (load "common.lsp") into your init.lsp file or put those common functions directly into it. This would be one of many ways to get dirname:

(define (dirname path) (if (regex "(.*/).*" path) $1 "./"))

(dirname "/usr/etc/bashrc") => "/usr/etc/")

by default regex is 'greedy' so it will always get as much as it can toward the end of the path. To pick out the filename you could use:

(define (basename path) (last (parse path "/")))

(basename "/usr/etc/bashrc") => "bashrc")

Lutz

Ps: here is another one

(define (dirname path) (join (chop (parse path "/")) "/"))
Last edited by Lutz on Mon Aug 16, 2004 5:25 pm, edited 2 times in total.

Lutz
Posts: 5289
Joined: Thu Sep 26, 2002 4:45 pm
Location: Pasadena, California
Contact:

Post by Lutz »

... and of course you always can do:

(first (exec (append "direname " pathFile))) => "/home/scratchy"

(exec ...) can run any program/tool chains and returns stdout in a list of strings

Lutz

scratchy
Posts: 14
Joined: Sat Aug 14, 2004 10:41 pm

Post by scratchy »

So it would take something like this:

    (define (dirname path)
        (if (= (& (nth 7 (sys-info)) 0x0F) 6)
            (if (regex "(.*\\\\).*" path) $1 ".\\")
            (if (regex "(.*/).*" path) $1 "./")))

    (define *script-dir* (dirname (nth 1 (main-args))))

in the beginning of each script to be able to include an external script:

    (load (string *script-dir* "../lib/common.lsp"))

I haven't tested this implementation of dirname enough to guarantee that it works everywhere, but having to duplicate the code it is not cool. What else can I do to convince you that dirname should be a built-in?

Lutz
Posts: 5289
Joined: Thu Sep 26, 2002 4:45 pm
Location: Pasadena, California
Contact:

Post by Lutz »

Actually you don't need to use backslash on Win32. Even with drive specifiers it is ok as in "c:/somedir/somefile" . Although the Win32 command shell does not allow forward slash for directory specs it is perfectly legal to do it from programs.

Lutz

scratchy
Posts: 14
Joined: Sat Aug 14, 2004 10:41 pm

Post by scratchy »

Lutz wrote:Actually you don't need to use backslash on Win32...
Lutz
??? This information does not help. How about the dirname built-in?

Lutz
Posts: 5289
Joined: Thu Sep 26, 2002 4:45 pm
Location: Pasadena, California
Contact:

Post by Lutz »

I think it is just not used frequently enough. You far more compose path-filenames from their parts, than the other way around. Most popular scripting languages only offer it in a module. In Perl you have to use the File:Basename module, in Python you would have to use the OS.path module. Just put it in your init.lsp.

Lutz

HPW
Posts: 1390
Joined: Thu Sep 26, 2002 9:15 am
Location: Germany
Contact:

Post by HPW »

>but having to duplicate the code it is not cool.

What's wrong with Lutz advice? When you put your own tools in the initialisation lsp, then you can use it from every of your own scripts.
No duplicate code neccesary. I use this technic to load a compatibility layer to another lisp-dialect.


"Lisp is a programmable programming language."
- John Foderaro, CACM, September 1991

from http://www.paulgraham.com/quotes.html
Hans-Peter

scratchy
Posts: 14
Joined: Sat Aug 14, 2004 10:41 pm

Post by scratchy »

What's wrong with Lutz advice is that I don't want to write scripts that will work only with my init.lsp.[/quote]

nigelbrown
Posts: 429
Joined: Tue Nov 11, 2003 2:11 am
Location: Brisbane, Australia

Post by nigelbrown »

I would put the define at the front of the script in that case.

Nigel

scratchy
Posts: 14
Joined: Sat Aug 14, 2004 10:41 pm

Post by scratchy »

Thank you. That brings us back to my point #2 above.

nigelbrown
Posts: 429
Joined: Tue Nov 11, 2003 2:11 am
Location: Brisbane, Australia

Post by nigelbrown »

Hi Scratchy
I guess I'm not clear on why you want dirname.
(load "./lib/common.lsp") will load from the current directory's lib subdirectory.
Where do you want common.lsp to be? (Apologies for being a bit dense here
I've not thought through your above code completely)

Regards
Nigel

Lutz
Posts: 5289
Joined: Thu Sep 26, 2002 4:45 pm
Location: Pasadena, California
Contact:

Post by Lutz »

This one works for both \ and / as path separator and on Win32 and Linux/UNIX OS:

(define (dirname path)
(join (chop (parse path "/|\\\\" 0)) "/"))

Just put it in whatever file you need it. 'dirname' is just not used and asked for enough to include in newLISP.

Lutz

scratchy
Posts: 14
Joined: Sat Aug 14, 2004 10:41 pm

Post by scratchy »

(load "./lib/common.lsp") will load from the current directory's lib subdirectory.
Current directory is variable. But the script should be able to figure out where it is located in the filesystem, and without 'dirname', it's impossible to do.
Where do you want common.lsp to be?
Anywhere, at a <i>fixed relative path</i> (e.g. "../lib") to a.lsp and b.lsp. Equivalent functionality in sh can be achieved via:

#!/bin/sh
source `dirname $0`/../lib/common.sh

The philosophy of sh is to use external programs as much as possible, that is why dirname is not a built-in function in sh.

scratchy
Posts: 14
Joined: Sat Aug 14, 2004 10:41 pm

Post by scratchy »

By the way, clisp has a built-in 'directory-namestring', which is essentially 'dirname', I was asking for in newLISP:

(defconstant *script-dir* (directory-namestring *LOAD-PATHNAME*))

(load (concatenate 'string *script-dir* "../lib/common.lsp"))

There you go.

nigelbrown
Posts: 429
Joined: Tue Nov 11, 2003 2:11 am
Location: Brisbane, Australia

Post by nigelbrown »

I note:
[nigel@p800 nigel]$ clisp
i i i i i i i ooooo o ooooooo ooooo ooooo
I I I I I I I 8 8 8 8 8 o 8 8
I \ `+' / I 8 8 8 8 8 8
\ `-+-' / 8 8 8 ooooo 8oooo
`-__|__-' 8 8 8 8 8
| 8 o 8 8 o 8 8
------+------ ooooo 8oooooo ooo8ooo ooooo 8

Copyright (c) Bruno Haible, Michael Stoll 1992, 1993
Copyright (c) Bruno Haible, Marcus Daniels 1994-1997
Copyright (c) Bruno Haible, Pierpaolo Bernardi, Sam Steingold 1998
Copyright (c) Bruno Haible, Sam Steingold 1999-2000
Copyright (c) Sam Steingold, Bruno Haible 2001-2004


[1]> (directory-namestring *LOAD-PATHNAME*)
""
[2]>

and from newlisp

> (exec "dirname $0")
(".")

both in Mandrake 9.1 - they don't seem to add much?

Nigel

PS re *LOAD-PATHNAME* it looks loke a load into the lisp
environment is needed to set it - not the starting of lisp itself?
viz: from hyperpsec
Variable *LOAD-PATHNAME*, *LOAD-TRUENAME*

Value Type:


The value of *load-pathname* must always be a pathname or nil. The value of *load-truename* must always be a physical pathname or nil.


Initial Value:


nil.


Description:


During a call to load, *load-pathname* is bound to the pathname denoted by the the first argument to load, merged against the defaults; that is, it is bound to (pathname (merge-pathnames filespec)). During the same time interval, *load-truename* is bound to the truename of the file being loaded.

scratchy
Posts: 14
Joined: Sat Aug 14, 2004 10:41 pm

Post by scratchy »

Of course, in an interactive session *LOAD-PATHNAME* is meaningless.

nigelbrown
Posts: 429
Joined: Tue Nov 11, 2003 2:11 am
Location: Brisbane, Australia

Post by nigelbrown »

Hi Scratchy,
Could you post clisp code that uses/prints it?
I can't get it to return anything non-interactive viz if test2.lsp

(load "/home/nigel/test.lsp")
(defconstant *script-dir* (directory-namestring *LOAD-PATHNAME*))
(print "Value is <")
(print *script-dir*)
(print ">")
(exit)

I get

[nigel@p800 nigel]$ clisp test2.lsp

"Value is <"
""
">"
[nigel@p800 nigel]$

same if test2.lsp is

(defconstant *script-dir* (directory-namestring *LOAD-PATHNAME*))
(print "Value is <")
(print *script-dir*)
(print ">")
(exit)

Nigel

Locked