Lee's SFSP Lisp Tweak

Lee's SFSP Lisp Tweak

ebsoares
Collaborator Collaborator
1,611 Views
12 Replies
Message 1 of 13

Lee's SFSP Lisp Tweak

ebsoares
Collaborator
Collaborator

Hi, all.

 

Found this great lisp routine called "Add Support File Search Paths at n" (by Lee Mac) that adds support file search paths at the desired index. This is a fantastic routine for adding paths for files related to different clients - so, every time we work for a different client we can load their own set of file paths.

 

The only problem when using that routine is that by simply adding paths, old ones stay there, and eventually piles up to a huge list of paths, most of which are not pertaining to the project/client that one is currently working on.

 

Is there a way to have the routine (perhaps the "Remove Support File Search Paths" routine also on that page) remove paths that, say, do not start with "C:" (or any other string). The reason for keeping paths from the C: drive is because some are much needed, regardless of which client we work with. We place our clients standard files in our server (different drive letter).

 

Thanks in advance for any input.

 

Edgar

0 Likes
Accepted solutions (2)
1,612 Views
12 Replies
Replies (12)
Message 2 of 13

stevor
Collaborator
Collaborator

Try:

[code]

 ;
 ; Parse String to List by 1 cHARACTER, Ommits 'PC
 (defun Pars_C ( S1 PC / S2 SQ CI L2 RC) ; Auscadd.com
  (setq SQ (strLen S1)  S2 ""  CI 0 ) ; 1st others
  (whiLe (< CI SQ) (setq CI (1+ CI)  RC (substr S1 CI 1) ) ;
   (if (not (= RC pc))  (setq S2 (strcat S2 RC))
    (if (/= "" S2) (setq L2 (cons S2 L2) S2 "" ) ) )  
  ) ; w
  (If (/= "" S2)  (setq L2 (cons S2 L2) S2 "") )  ;    
  (reverse L2) ) ; def
 

 ; mod of LeeMac's to remove paths containing the WildCardStr
(defun LM:sfsp-WCS ( WCS / PSP tmp NPS PS PSL)
  (setq PSP (strcat (vl-string-right-trim ";" (getenv "ACAD")) ";")
            tmp PSP WCS (strcase WCS)
            ; PSP (strcat PSP "c:\\1astr;c:\\3astr") ; for test
            NPS "" PSL (Pars_C PSP ";") ) ; str to list by ';
   (foreach PS PSL ;
    (if (vl-string-search WCS (strcase PS))
     (princ (strcat "\n Match: " PS )) ; or replace with (princ)
     (SETQ NPS (strcat NPS ";" PS) ) )  ) ; leading '; occurred here
  (setq NPS (substr NPS 2 )) ; leading '; removed here
  ; verify here before change?
  (if (/= tmp NPS) (setenv "ACAD" NPS) )
) ; def Auscadd.com

;

[/code]

 

Example:

 (LM:sfsp-WCS  "c:"  )

 

S
Message 3 of 13

Ranjit_Singh
Advisor
Advisor
Accepted solution

Try below for example

;;;Modify "ACAD" environment variable to eliminate
;;;all paths except those pointing to "C" drive (c:)
;;;Ranjit Singh 2/21/17

(defun c:somefunc  ()
 (setenv "ACAD" (apply 'strcat (mapcar '(lambda (x) (if (wcmatch x "c:\\*,C:\\*") x ""))
	                        (reverse (somefunc2 (getenv "ACAD") ()))))) (princ))

(defun somefunc2  (x y)
 (cond ((= x "") y)
       (t (somefunc2 (substr x (+ 2 (vl-string-position (ascii ";") x)))
                   (cons (substr x 1 (+ 1 (vl-string-position (ascii ";") x))) y)))))
Message 4 of 13

ebsoares
Collaborator
Collaborator

Thank you for your responses, Stevor and Ranjit.

 

Ranjit, I got your code to work as a standalone lisp, but when I incorporate it into LM's routine it gives me the following error:

; error: bad argument type: numberp: nil

 

Below is a copy of the routine built so far (the portions adopted from your code are in bold/blue):

 

(defun LM:sfsp+n ( lst idx / add )
    
    ; Start silent mode:
    (setq OldEcho (getvar "CmdEcho"))
    (setvar "CmdEcho" 0)
    
    ; Remove previous network paths (not on C:):
    (setenv "ACAD"
        (apply 'strcat
            (mapcar '
                (lambda (x) (if (wcmatch x "c:\\*,C:\\*") x ""))
                (reverse (RemoveCheck (getenv "ACAD") ()))
            )
        )
    )
    
    ; Main:
    (defun add ( str new idx / pos )
        (if (< 0 idx)
            (if (setq pos (vl-string-position 59 str))
                (strcat (substr str 1 (1+ pos)) (add (substr str (+ pos 2)) new (1- idx)))
                (strcat ";" new)
            )
            (strcat new str ";")
        )
    )
    (   (lambda ( str lst )
            (if (setq lst
                    (vl-remove-if
                       '(lambda ( x )
                            (or (vl-string-search (strcase x) (strcase str))
                                (not (findfile x))
                            )
                        )
                        lst
                    )
                )
                (setenv "ACAD" (add str (apply 'strcat (mapcar '(lambda ( x ) (strcat x ";")) lst)) idx))
            )
        )
        (vl-string-right-trim ";" (getenv "ACAD"))
        (mapcar '(lambda ( x ) (vl-string-right-trim "\\" (vl-string-translate "/" "\\" x))) lst)
    ) ; End of Main
    
    ; End silent mode:
    (setvar "CmdEcho" OldEcho)
    
    (princ "\nNetwork paths reset to appointed list. C: Drive maintained.")
    (princ)
)
; Build list of support paths to add tp SFSP:
(defun SFSPtest ()
    (LM:sfsp+n '(
        ; List of folders - one per line (do not forget double "\\" as opposed to single "\"):
        "E:\\Work\\CAD\\CAD Routines\\Support Paths"
        "E:\\Work\\CAD\\CAD Routines\\Microstation"
        )
        0 ; "0" means top of the list
    )
)
; Subfunction of network path removal:
(defun RemoveCheck  (x y)
    (cond
        ((= x "") y)
        (t
            (RemoveCheck
                (substr x (+ 2 (vl-string-position (ascii ";") x)))
                (cons 
                    (substr x 1 (+ 1 (vl-string-position (ascii ";") x)))
                    y
                )
            )
        )
    )
)

Any chance you can tell what the problem is or a work-around? Weird thing is that the first time I used this routine it worked, but after the second time I tried again it started giving that error message. I've been trying to figure it out all morning...

 

Thanks,

 

Edgar

 

0 Likes
Message 5 of 13

Ranjit_Singh
Advisor
Advisor

Try below

(defun LM:sfsp+n ( lst idx / add )
    
    ; Start silent mode:
    (setq OldEcho (getvar "CmdEcho"))
    (setvar "CmdEcho" 0)
    
    ; Remove previous network paths (not on C:):
    (setenv "ACAD" (apply 'strcat (mapcar '(lambda (x) (if (wcmatch x "c:\\*,C:\\*") x "")) (reverse (somefunc2 (getenv "ACAD") ())))))
    
    ; Main:
    (defun add ( str new idx / pos )
        (if (< 0 idx)
            (if (setq pos (vl-string-position 59 str))
                (strcat (substr str 1 (1+ pos)) (add (substr str (+ pos 2)) new (1- idx)))
                (strcat ";" new)
            )
            (strcat new str ";")
        )
    )
    (   (lambda ( str lst )
            (if (setq lst
                    (vl-remove-if
                       '(lambda ( x )
                            (or (vl-string-search (strcase x) (strcase str))
                                (not (findfile x))
                            )
                        )
                        lst
                    )
                )
                (setenv "ACAD" (add str (apply 'strcat (mapcar '(lambda ( x ) (strcat x ";")) lst)) idx))
            )
        )
        (vl-string-right-trim ";" (getenv "ACAD"))
        (mapcar '(lambda ( x ) (vl-string-right-trim "\\" (vl-string-translate "/" "\\" x))) lst)
    ) ; End of Main
    
    ; End silent mode:
    (setvar "CmdEcho" OldEcho)
    
    (princ "\nNetwork paths reset to appointed list. C: Drive maintained.")
    (princ)
)
; Build list of support paths to add tp SFSP:
(defun SFSPtest ()
    (LM:sfsp+n '(
        ; List of folders - one per line (do not forget double "\\" as opposed to single "\"):
        "E:\\Work\\CAD\\CAD Routines\\Support Paths"
        "E:\\Work\\CAD\\CAD Routines\\Microstation"
        )
        0 ; "0" means top of the list
    )
)
; Subfunction of network path removal:
(defun somefunc2  (x y)
 (cond ((= x "") y)
       (t (somefunc2 (substr x (+ 2 (vl-string-position (ascii ";") x)))
                   (cons (substr x 1 (+ 1 (vl-string-position (ascii ";") x))) y)))))

The above is working as expected on my machine. You should call the routine as follows for example

(LM:sfsp+n '("L:\\00-ACAD-SAMPLE" "C:\\New folder" "C:\\Users\\whatever\\Documents\\LISP") 0)
0 Likes
Message 6 of 13

ebsoares
Collaborator
Collaborator

Hi again, Ranjit.

 

There doesn't seem to be any change in your code, as you just removed some of the returns and renamed the functions...

 

Just for kicks I copied the exact, entire, unaltered code you posted back and ran it on my machine with the same result: ; error: bad argument type: numberp: nil

 

From my tests, it seems that the function is failing when it reaches somefunc2 - that's where it seems to give that error (it never returns to somefunc, which called it), but I'm not sure. It might be looking for something that shows up on your end but not on mine? I'm just not proficient enough with lisp code to figure this one out on my own...

0 Likes
Message 7 of 13

Ranjit_Singh
Advisor
Advisor

To keep things simple, I did not want go through your renaming of the function and any other edits that you had made. So I simply copied what I had coded and put it in the overall code for testing. That's the reason why you see the only change as formatting.

See attached screencast and notice how the routine works. Make sure to call Lee's routine with a list of paths and a number zero "0". Your error is making me suspicious that you are missing the 0. Just verify. If you call it exactly as I did in my screencast then post your "ACAD" env variable contents.

Why would you think it cannot find somefunc2? Did you save somefunc2 as a separate .lsp file?

0 Likes
Message 8 of 13

ebsoares
Collaborator
Collaborator

Wow, that's cool. I hadn't seen a video response before! Thanks for spending all this time helping me out, Ranjit Smiley Happy

 

The portion related to adding paths is working fine. The format I'm using just makes the encapsulation much more clear for me to understand what's under/inside what, but the sintax is intact (the 0 is definitely there, right after the list of paths).

 

It confounds me to see that your code works fine on your end but not on mine. I mentioned somefunc* because I placed a few "(princ "test")" in different places in the code (only once at a time, so as not to disrupt the code) and it seemed to have glitched somewhere inside somefunc2. If I remove your code from the rest everything else works fine... I liked your code 'cause it seemed so simple and to the point, especially since it worked the first time. This must be some glitch on my system.

I might try again tomorrow, but otherwise I'll give it another go at @stevor's code (couldn't get it to work before) - maybe it will provide a workaround.

 

Thanks again, Ranjit.

 

Edgar

0 Likes
Message 9 of 13

Ranjit_Singh
Advisor
Advisor

I tried but I can't help since I cannot recreate the problem at my end. Final advice. Whichever code you use, make sure to save your "ACAD" variable contents beforehand so you can restore it if something goes wrong or some routine accidentally wipes out your paths. Good luck.

P.S. Do not add anything in somefunc2 because it is a recursive function and adding print may cause issues when the function evaluates its way back out of the innermost function. 

0 Likes
Message 10 of 13

ebsoares
Collaborator
Collaborator

Right on. I noticed the recursive process when it printed "test" a whole bunch of times Smiley Very Happy

0 Likes
Message 11 of 13

ebsoares
Collaborator
Collaborator

Hi, @stevor.

 

Thanks again for taking the time and writing that code for me the other day.

 

I've been trying to use your routine but have been running into the following error: no function definition: LM:SFSP-WCS.

 

Searched it online and many people said to use VLIDE to try and figure out where the error is. While going through that debugging process (my first time doing so... ever) it seems that the program gets stuck in the while loop on line 3 of the code.

 

I'm not sure I did it correctly, but if you happen to have a few moments, would you mind checking into that?

 

Thanks in advance.

 

Edgar

0 Likes
Message 12 of 13

ebsoares
Collaborator
Collaborator
Accepted solution

Thanks for the help, Ranjit!

 

In case anyone else needs it, Ranjit also figured why it wasn't working in some instances - it was because sometimes the "ACAD" environment string did not add a final semicolon ";" to the end of the string (there should be one there).

 

Here's the final version of his code (change in bold/blue):

(defun SomeFunc ()
    ; First check "ACAD" env var and if there is no
    ; semi-colon at end of the last path (there should be) then add it:
    (if (/= 59 (last (vl-string->list (getenv "ACAD"))))
        (setenv "ACAD" (strcat (getenv "ACAD") ";"))
    )
    ; set "ACAD" environment string:
    (setenv "ACAD"
        (apply 'strcat
            (mapcar '(lambda (x) (if (wcmatch x "c:\\*,C:\\*") x ""))
                (reverse (SomeFunc2 (getenv "ACAD") ()))
            )
        )
    )
)
; Recursive subfunction of SomeFunc:
(defun SomeFunc2  (x y)
    (cond
        ((= x "") y)
        (t
            (SomeFunc2 (substr x (+ 2 (vl-string-position (ascii ";") x)))
                (cons 
                    (substr x 1 (+ 1 (vl-string-position (ascii ";") x)))
                    y
                )
            )
        )
    )
)

And that did it for me.

 

Thanks again, Ranjit.

 

Edgar

 

0 Likes
Message 13 of 13

Ranjit_Singh
Advisor
Advisor

You are welcome. Glad it worked for you. 

0 Likes