Visual LISP, AutoLISP and General Customization
cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Extract a folder name within dwgprefix

15 REPLIES 15
SOLVED
Reply
Message 1 of 16
smaher12
4044 Views, 15 Replies

Extract a folder name within dwgprefix

I’m looking to extract the second from the last directory within the dwgprefix of

"P:\Projects\66 Structural\666-4800-00 TPA\666-4815-00 Res\4815 Res Figures\"     (i.e. 666-4815-00 Res) 

 

This is what I have so far:

 

(defun c:tmp ( )

  (setq P1 (getpoint "\nPick point: "))

  (command "text" P1 "" ""

    (strcat

      (vl-filename-base

        (vl-string-subst "." "\\" (getvar 'dwgprefix) (vl-string-position (ascii "\\") (getvar 'dwgprefix) nil T))

   ))))

15 REPLIES 15
Message 2 of 16
balisteor
in reply to: smaher12

You would not want to try using  "vl-filename-base" because the prefix is all your using.

For what your doing I think its easier to use a global tool, like this string-split, because it works for so many other things, and for running through long strings, it can get messy writing code each time your in a situation lilke this.

and for paths its very nice because we have a common separator.

 

(defun string-split (stringin seperatortype / teststring listout)
(if (and
    stringin
    (setq teststring "")
    );a
(progn
(while  (> (strlen stringin) 0)
 (while (and (not (= seperatortype  (substr stringin 1 1))) (> (strlen stringin) 0))
  (setq teststring (strcat teststring (substr stringin 1 1)) stringin (substr stringin 2))
 )
(setq listout (cons teststring listout) teststring "" stringin (substr stringin 2))
)
(reverse listout)
);p
nil
);i
);d

;; get the 3rd directory down from drive letter.
(nth 4 (string-split (vl-string-translate "\\" "/" (getvar 'dwgprefix)) "/"))

 

we can also place getpoint right into the command function with no need for setq.

(defun c:tmp ( )
(command "text" (getpoint "\nPick point: ") "" "" (nth 4 (string-split (vl-string-translate "\\" "/" (getvar 'dwgprefix)) "/")))
(princ))

 

I hope this helps , sorry if I gave you too much info and confusion.

 

 

Message 3 of 16
smaher12
in reply to: balisteor

balisteor - how do you load the first one? I'm not familiar with Visual Lisp. The second one I received error no function definition: STRING-SPLIT.

Message 4 of 16
balisteor
in reply to: smaher12

Well first you need to just test it, copy and paste the string-split function into your command line.

then the tmp function will work, once that is done you can add the function somewhere into your startup files and we can work on that later.

Message 5 of 16
Kent1Cooper
in reply to: smaher12


@smaher12 wrote:

I’m looking to extract the second from the last directory within the dwgprefix of

"P:\Projects\66 Structural\666-4800-00 TPA\666-4815-00 Res\4815 Res Figures\"     (i.e. 666-4815-00 Res) 

....

This works for me:

 

(setq
  path (vl-string-right-trim "\\" (getvar 'dwgprefix))
  path (substr path 1 (vl-string-position (ascii "\\") path 0 T))
  penultimatefolder (substr path (+ 2 (vl-string-position (ascii "\\") path 0 T)))
)

Kent Cooper, AIA
Message 6 of 16
balisteor
in reply to: smaher12

Assuming you will only need this one thing to work you should use kens program above, it will work really well for the situation you have provided.  I have only gave you that program for future use in similar conditions.

Message 7 of 16
smaher12
in reply to: balisteor

Balisteor  - thank you very much as I was able to get your code to run and it does exactly what I need it to do.

Kent – thank you as well. Hats off for the tidy code. Works great!

Message 8 of 16
Kent1Cooper
in reply to: smaher12


@smaher12 wrote:

Balisteor  - thank you very much as I was able to get your code to run and it does exactly what I need it to do.

Kent – thank you as well. Hats off for the tidy code. Works great!


You're welcome.  It occurred to me that there have been several threads here about subdividing text strings with various delimiting characters, such as balisteor's (string-split) function -- do a Search and you'll find various approaches.  But [without digging them all out and comparing] I think they all needed single-character delimiters, which is why balisteor's code that calls up (string-split) has to translate all the "\\" pieces in the dwgprefix value to the one character "/" in order to apply (string-split) to it.  That's partly a result of its going through the string one character at a time.

 

I figured there ought to be a way to split up a string with the possibility of multiple-character delimiters, such as "\\", and I found a way to do it:

 

(defun sdtol (str del / step strlist); = String [Delimited] TO List [of partial strings]
  ; arguments: str = initial STRing; del = DELimiting character(s) [can be more than one]
  (defun step (/ pos)
    (setq
      pos (vl-string-search del str)
      strlist (append strlist (list (substr str 1 pos)))
      str (substr str (+ pos (strlen del) 1))
    ); setq
  ); defun -- step
  (while (and str (wcmatch str (strcat "*" del "*"))) (step))

    ; still something left in string, including at least one more delimiter
  (setq strlist (append strlist (if (/= str "") (list str))))
    ; add remaining end of original if string doesn't end with delimiter
); defun

 

So you can split up what (getvar 'dwgprefix) returns without translating the "\\" parts into single characters:

 

Command: (sdtol "P:\\Projects\\66 Structural\\666-4800-00 TPA\\666-4815-00 Res\\4815 Res Figures\\" "\\")

returns
("P:" "Projects" "66 Structural" "666-4800-00 TPA" "666-4815-00 Res" "4815 Res Figures")

 

But you can get even crazier than that:

 

Command: (sdtol "1Mickey Mouse2Mickey Mouse3Mickey Mouse4" "Mickey Mouse")

returns
("1" "2" "3" "4")

 

However, there's a quirk I need to fix, but it's time to go:  When I use a comma as the delimiter, it sets the divided-up string list properly [if you un-localize the strlist variable, and then read what's in it when it's done], but returns an error message:

 

Command: (sdtol "Layer1,Layer2,Layer3" ",")

results in the list ("Layer1" "Layer2" "Layer3"), but returns this:
; error: bad argument type: numberp: nil

 

I'm sure it has to do with comma as a separator of multiple patterns in (wcmatch), so it may be pretty easy to fix, but I'll have to look at it later.

Kent Cooper, AIA
Message 9 of 16


@Kent1Cooper wrote:
  But [without digging them all out and comparing] I think they all needed single-character delimiters, which is why balisteor's code that calls up (string-split) has to translate all the "\\" pieces in the dwgprefix value to the one character "/" in order to apply (string-split) to it.  That's partly a result of its going through the string one character at a time.

 

I figured there ought to be a way to split up a string with the possibility of multiple-character delimiters, such as "\\", and I found a way to do it:

 

------
Strictly speaking, in Lisp "\\" is a string containing only one character:
_$ (length (vl-string->list "\\"))
1
i.e. the first \ is the escape character, swallowed by the Lisp reader so it is not included in the data, though re-introduced when outputting with PRINT or PRIN1 (not with PRINC).
The reason to map \\  to / is probably just to handle paths like "P:\\Projects/66 Structural/666-4800-00 TPA\\",
which can easily occur when creating paths with STRCAT from several variables.
- apart from that, nice program if I ever need to use multi-char dividers.
 
--
 
 
 
 
 
Message 10 of 16
balisteor
in reply to: Kent1Cooper

yes, i did find out later and even tested to make sure but,  i did not need to translate the \\ to /, its just there.

 

But I too like your program, and will be adding it my my library, thanks. (Ill be sure to keep your name on it :D)

 

 

Message 11 of 16
bhull1985
in reply to: balisteor

Hey kent

Very nice routine here.

We'd be able to use the (car) (cadr) functions with this function to retrieve certain pieces of the resultant list of strings?

 

I just had to concatenate "-000" (a revision indicator) onto a set of drawings; their file names; and was successful in doing so via the following:

 

(defun c:dwgRename ( / OldDwgName NewDwgName ReDName)

 (setq OldDwgName (strcat (getvar "dwgprefix") (getvar "dwgname")))

 (setq NewDwgName  (substr OldDwgName 1 (- (strlen OldDwgName) 4)))

(setq ReDName (strcat NewDwgName "-000"))  

(command ".saveas" "" ReDName)

 (vl-file-delete OldDwgName)

 (princ)  )

 

which your statements here compare to:

 

Kent1Cooper"

(sdtol (substr (getvar 'dwgname) 1 (- (strlen (getvar 'dwgname)) 4)) "_")

returns a list of pieces of the drawing name [minus the ".dwg" at the end], split into separate text strings around the underscore delimiter, something like this: ("ABCDE" "FGH" "JKLMNO" "PQR")

 

You can use functions like (car), (cadr), (caddr), (cadddr), (nth), and (last) [see the AutoLISP Reference] to get the pieces you want out of that list."

 

 

 

but what im wondering is how we'd use your function to achieve the results of the one i did...it'd be the 2nd to last , or it'd be what's inbetween two separate delimeters / and .  (in path extensions and in the file type specification)

or perhaps i'm overlooking something that'd make this alot easier?

 

 

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Please use code tags and credit where credit is due. Accept as solution, if solved. Let's keep it trim people!
Message 12 of 16
BlackBox_
in reply to: bhull1985

FWIW - 

 

As an all pupose 'parser' there's nothing wrong with SDTOL at all (I have one of my own as well), however when specifcally dealing with file path strings, _FILEPATH->LIST is a bit more efficient:

 

(defun _FilePath->List (filePath / i folder folders)
  (setq filePath (vl-string-translate "\\" "/" filePath))
  (while (setq i (vl-string-search "/" filePath))
    (setq folders (cons (setq folder (substr filePath 1 i)) folders))
    (setq filePath (substr filePath (+ 2 i)))
  )
  (reverse folders)
)

 

 

... Results from console, in a quick speed comparison of SDTOL and _FILEPATH->LIST sub-functions:

 

_$ (bench '(sdtol) '("Z:\\foo\\bar\\bat\\" "\\") 10000)

SDTOL
Elapsed: 312
Average: 0.0312

 
_$ (bench '(_FilePath->List) '("Z:\\foo\\bar\\bat\\") 10000)

_FILEPATH->LIST
Elapsed: 171
Average: 0.0171


_$  

 

Cheers



"How we think determines what we do, and what we do determines what we get."

Message 13 of 16
bhull1985
in reply to: BlackBox_

Nice, thanks BlackBox

Would you mind to take a sec and explain how that one works?

If I were to take a stab....it locates the current drawing in the windows folder structure

Changes the \\ into / either for output or input hard to tell...

Searches for all "\\"s and "/"s within the previously mentioned folder structure

And here's where it becomes gobble-dey-goop.

What are those last few lines doing BB?

This appears as if it'd be more actual work for the system than simply pulling a system variable and applying a function to it but apparently not according to the benchmarks...

Hoping for your explinatory comments, and thanks!

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Please use code tags and credit where credit is due. Accept as solution, if solved. Let's keep it trim people!
Message 14 of 16
BlackBox_
in reply to: bhull1985


@bhull1985 wrote:

Nice, thanks BlackBox

Would you mind to take a sec and explain how that one works?

If I were to take a stab....it locates the current drawing in the windows folder structure

Changes the \\ into / either for output or input hard to tell...

Searches for all "\\"s and "/"s within the previously mentioned folder structure

And here's where it becomes gobble-dey-goop.

What are those last few lines doing BB?

This appears as if it'd be more actual work for the system than simply pulling a system variable and applying a function to it but apparently not according to the benchmarks...

Hoping for your explinatory comments, and thanks!


Both SDTOL and _FILEPATH->LIST effectively parse the supplied string argument. The primary source of efficiency gain in the latter, is by not defining an additional sub-function (STEP), which is common in many of my other routines.

 

Given the specificity, and frequency of the task of parsing a file path into a list of strings, I stopped using my general parsing function in favor of this method. 

 

How it works....

 

It translates all double-backslashes "\\" into single forward-slash "/" (which allows for either to be supplied as a validpath, i.e., C:\\foo\\, or C:/foo/, etc.), and then enters a WHILE loop to search for the index of the forward-slashes, each time parsing out that round's folder, storing it to a list variable (aptly named 'folders'), and then overwrites the filePath variable with a sub-string of same (minus the folder we just extracted and its forward-slash from the previous query).

 

When no more valid queries are found, the list of folders is reversed in order to place them in logical, or 'path' order and resturns any valid result, or Nil. This allows the code to also be used within a calling IF statement's test expression if needed.

 

This code puts the onus of validating the file path on the user, and simply focusses on the task of parsing any file path supplied (regardless of "\\" from things like DwgPrefix, or "/" for other functions), and while quite efficient for this task, does not serve as a general 'parser' in the way that SDTOL does (and I too have my own)... To paraphrase what Stephen or Fenton said in their DevBlog article series 'the right tool for the job'.

 

Hope that makes (more?) sense.

 

Cheers



"How we think determines what we do, and what we do determines what we get."

Message 15 of 16
bhull1985
in reply to: BlackBox_

Yessir it sure does.

Yeah, that made a good amount of sense as far as iterating over the string, yanking each "text" plus "//" or "\" piece at a time. Also I can see now why the incrementor is used, even if this isn't necessarily an "incrementor", but more of a "decrementor". Well now that's just sounding dirty, but yeah, it helped. Thanks BB 🙂

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Please use code tags and credit where credit is due. Accept as solution, if solved. Let's keep it trim people!
Message 16 of 16
BlackBox_
in reply to: bhull1985

Cheers, dude. :beer:



"How we think determines what we do, and what we do determines what we get."

Can't find what you're looking for? Ask the community or share your knowledge.

Post to forums  

Autodesk Design & Make Report

”Boost