TheSwamp
Code Red => AutoLISP (Vanilla / Visual) => Topic started by: rude dog on January 30, 2004, 11:56:54 AM
-
How would you accomplish writing a setq'd value (A1) to a file
(defun c:WT (\ A1 LOG)
(setq A1 '(HERE IT IS!))
(setq LOG (open "RC-WT.TXT" "w"))
(write-line A1 LOG)
(close LOG)
)
(PRINC)
-
(defun c:WT (\ A1 a) ;|LOG is a bad variable. It's a function and you will not get the desired results.|;
(setq A1 "HERE IT IS!");This will create a list of three empty items, HERE, IT & IS
(setq a (open "RC-WT.TXT" "w"));again, LOG
(write-line A1 a);Change LOG
(close a);same
)
-
didnt know...again :x ....thank you :D
-
Just remember every thing that goes to the open file must be a string.
Example:
Command: (setq fo (open "c:/str_test.txt" "w"))
#<file "c:/str_test.txt">
Command: (setq test (list 1 2 3))
(1 2 3)
Command: (write-line test fo) <-bad because 'test' is a list
; error: bad argument type: stringp (1 2 3)
Command: (write-line (vl-princ-to-string test) fo) <- good converted to a string
"(1 2 3)"
Command: (setq test (list "a" "b" "c"))
("a" "b" "c")
Command: (write-line test fo) <- bad it's still a list
; error: bad argument type: stringp ("a" "b" "c")
; write each item in the list to the open file since it is a string
Command: (foreach item test (write-line item fo)) <-good
; testing for a string
Command: (setq test "this is a string")
"this is a string"
(if (= (type test) 'STR)
(prompt "Yes it's a string")
(prompt "No it's not")
)
(princ)
Yes it's a string
Command: (setq test 123)
123
(if (= (type test) 'STR)
(prompt "Yes it's a string")
(prompt "No it's not")
)
(princ)
No it's not
-
Also keep in mind when you use (open "RC-WT.TXT" "w") and want to write to the same file the "w" switch will overwrite the original file. To add to a file use the "a" switch.
r Open for reading
w Open for writing. If filename does not exist, a new file is created and opened. If filename already exists, its existing data is overwritten. Data passed to an open file is not actually written until the file is closed with the close function.
a Open for appending. If filename does not exist, a new file is created and opened. If filename already exists, it is opened and the pointer is positioned at the end of the existing data, so new data you write to the file is appended to the existing data.
-
I was going to suggest that. If you do use append, you'll notice everything is on the same line. Use "\n" at the end or beginning of your code to move to the next line.
-
Mark
What a hand...excellent example..I really wanted to reply
to your newbie challenge (I think Im the only one) but I have been totally engulfed in a program im trying to put together I feel inclined to post what I have done on it so far because of the knowledge you share....." (vl-princ-to-string)" what tongue is this command...havent seen it in the book
(defun c:KLT (/ ES LG)
(princ "\nPick layer to keep thawed <Enter to exit>:")
(while
(setq ES (car (entsel)))
(setq ES (entget ES))
(setq EL (cdr (assoc 8 ES)))
(setq EL (strcat EL","))
(setq LG (append LG (LIST EL)))
(setq CS (vl-princ-to-string LG))
(princ "\n Layers to remain thawed:")
(prin1 CS)
)
(setq LL CS)
(setq LAY (open "c:/LAY-INFO.TXT" "w"))
(write-line LL LAY)
(close LAY)
(princ)
)
ultimate goal is to strip parenthisis and space from string extracted by the routine (ex.) (DIM, CENTER, WRK,) (TO:) DIM,CENTER,WRK,
so I can call these names from txt file back to command prompt for "thawing"......routine will freeze every layer except "0" go back and thaw these "extracted layer names" from txt file. do some collision checking and then thaw "*"
-
:oops: @###@**#@##Last post was from Rude Dog ....very tired
-
Now that I understand what you are doing. :D Take a look at the following code. You could add a lot more error checking to this but let's take it one step at a time.
(defun c:KLT (/ str ent lay_name LAY)
;; create empty string
(setq str "")
(while
;; loop while selection continues
(setq ent (car (entsel "\nSelect an item <enter to exit>: ")))
;; extact layer name from selected entity
(setq lay_name (cdr (assoc 8 (entget ent))))
;; show the user which layer they picked
(prompt lay_name)
;; create one long string of layer names
(setq str (strcat str (strcat lay_name ",")))
) ; end of loop
;; we need to make sure 'str' is not empty
(if (not (= str ""))
(progn
;; remove the last ',' from the string
(setq str (substr str 1 (1- (strlen str))))
(setq LAY (open "C:/LAY-INFO.TXT" "w"))
(write-line str LAY)
(close LAY)
)
)
(princ)
)
-
Mark,
How do you improve on perfection.....its not gonna happin this is beautiful...
;; create one long string of layer names
(setq str (strcat str (strcat lay_name ","))) :shock:
so small yet so resourceful....the last comma on the last layer name would not have hurt anything but why not take it out and have a flawess routine
I dont know what else to say dude...
Thanks,
Rudy
-
Does it all make sense or did I loose you on some of it?
-
I believe i got it....I'll finish the rest during the week some time..very busy with kids, work, family and of course super bowl :)
-
When I get the rest done I'll post it for critiquing
-
Spoke too soon...there is sumthin' I do not understand I didnt understand why the "if" statement and the "progn" statement where necessary in this program....I omitted them and it still seems to work fine...Are they in there because its just "good programming habits" that you have, that I dont understand or does omitting them sacrafice the integrity of the routine?
I hope this is not coming across wrong dude, just curious :wink:
(defun c:LTC (/ str ent lay_name LAY)
;; create empty string
(setq str "")
(while
;; loop while selection continues
(setq ent (car (entsel "\nSelect an item <enter to exit>: ")))
;; extact layer name from selected entity
(setq lay_name (cdr (assoc 8 (entget ent))))
;; show the user which layer they picked
(prompt lay_name)
;; create one long string of layer names
(setq str (strcat str (strcat lay_name ",")))
) ; end of loop
;; we need to make sure 'str' is not empty
;(if (not (= str ""))
;(progn
;; remove the last ',' from the string
(setq str (substr str 1 (1- (strlen str))))
(setq LAY (open "C:/LAY-INFO.TXT" "w"))
(write-line str LAY)
(close LAY)
;)
;)
(princ)
)
-
Can I ask why you want to write layer names to a file in such a manner?
-
Yes, I am curious too.
Here are some (if) examples
(if (this is true)
(do this)
); endif
(if (this is false)
(don't do this)
(do this)
); endif
(if (this is true)
(progn
do all of this
and this
and this
)
(don't do this)
); endif
(if (this is false)
(don't do this)
(progn
do all of this
and this
and this
)
); endif
So you see the progn is a way to group code together.
The (if) stmt will execute the group of code when true and
will execute the second group of code when false,
if there is a second group of code. If you forget the (progn) only the first
line of code will be executed if true and the rest skipped.
There are other ways to group code together and you will learn them in time.
The (cond) stmt on the other hand executes the all of code following
a true condition and then exits the condition stmt.
(cond
((= 1 0)
none of this will get executed
because the conditions is false
) ; end cond 1
((= 1 1)
do all of this because it is true
and this
and this
) ; end cond 2
((= 2 2)
none of this will get
executed even if it is true
because the prior stmt was true
) ; end cond 3
(T
This is often placed at the last position
in a condition statement and will be executed
if all the prior conditions are false
if any one of the above conditions are true
this will not be executed
) ; end cond 4
) ; end cond stmt
-
I followed this thread on and off and feel some comments should be made on the topic of outputting to files.
It's true that OPEN only streams ASCII files. It's also true that WRITE-LINE can only write strings to a file, but it is certainly possible to write any data type. It just depends on the function used to write the data. Let's take a look at them by using an example: WRITE-LINE, PRINC, PRINT and PRIN1.
First make some non-string data, in this case a list:
(setq alst '(1 2 3 4 5))
-> (1 2 3 4 5)
Then create a file:
(setq fn (open "C:\\abc.txt" "w"))
-> #<file "C:\\abc.txt">
Now try the various functions to write the data. To keep track of which function was used, we'll write the functions as a string before writing the data. We'll also use a newline character to see how they each treat control characters.
First WRITE-LINE. As Mark pointed out, it only handles strings so we'll need to convert the list to a string using VL-PRINC-TO-STRING:
(write-line "\nwrite-line:" fn)
-> "\nwrite-line:"
(write-line (vl-princ-to-string alst) fn)
-> "(1 2 3 4 5)"
Then PRINC, PRINT and PRIN1. These functions write any data types - just like they would at the command line:
(princ "\nprinc:" fn)
-> "\nprinc:"
(princ alst fn)
-> (1 2 3 4 5)
(print "\nprint:" fn)
-> "\nprint:"
(print alst fn)
-> (1 2 3 4 5)
(prin1 "\nprin1:" fn)
-> "\nprin1:"
(prin1 alst fn)
-> (1 2 3 4 5)
Now close the file and open it (here just using Notepad):
(close fn)
-> nil
(startapp "notepad.exe" "C:\\abc.txt")
-> 33
The file should look like this (first blank line included):
write-line
(1 2 3 4 5)
princ:(1 2 3 4 5)
"\nprint:"
(1 2 3 4 5) "\nprin1:"(1 2 3 4 5)
WRITE-LINE: Writes its string argument with a trailing newline character. Control characters are output as their ASCII representation; a newline character creates a linefeed, a tab character creates a tabulation etc.
Notice that the automatic newline character is put at the end of the string. The first blank line in the example came from the explicit "\n"-character, but the second blank line was caused by the combination of WRITE-LINE's newline and PRINC' explicit newline character.
PRINC: Works like WRITE-LINE except that it does not create a new line. Also, neither PRINC, PRINT nor PRIN1 are limited to outputting strings.
PRINT: Outputs the literal value of its argument, which means that strings become quoted and control characters are expanded into their control character codes. It also prints a leading newline character and a trailing space. Notice that "\nprint:" was output on a new line and that it has a trailing space (put the cursor at the end of the line to see it).
PRIN1: Works like PRINT, except that it doesn't print a leading newline character and a trailing space. Notice that the space before "\nprin1:" came from the previous PRINT statement and that PRIN1 did not jump to a new line.
-
Matt, I think Rude Dog is merely using this as a small tool to freeze and/or thaw some layers. The string is perfectly legal to submit at Thaw, Freeze, On and Off prompts in the layer command.
I also thought that, firstly, it should at least check for duplicate layer names and trailing commas and, secondly, that much more sophisticated methods could be used. But as a small fix it does the job.
Rude Dog, just don't pass it on to anyone :D
... I didnt understand why the "if" statement and the "progn" statement where necessary in this program....I omitted them and it still seems to work fine.
The IF statement that checks for an empty string is needed when the command is invoked but the user simply presses Enter and exits the command without doing anything.
It's not just 'good programming practice' - it prevents the file from being manipulated (and thereby overridden) without a reason to manipulate it.
-
Matt
just trying to use one continous string(of layer names) to only show the entities I pick for viewing and freezing everything else out. and practice
-
CAB,SMadsen thanks for your comments it ususallly takes me a day or two to absorb and try to retain practical hints and possibly stir up some questions.....I'm sure there is more complicated ways to do this but I'm sure after the code is written and after using it for a while I'll think of other facets to add....(with help of course :D )
-
Using what SMadsen has given us we could re-write the program using a list of collected layer names.
(defun c:KLT (/ fo ent lay_name lst)
;; open a file for writing
(setq fo (open "C:/LAY-INFO.TXT" "w"))
(if
(findfile "C:/LAY-INFO.TXT"); make sure the file exists, overkill?
(while
;; loop while selection continues
(setq ent (car (entsel "\nSelect an item <enter to exit>: ")))
;; extact layer name from selected entity
(setq lay_name (cdr (assoc 8 (entget ent))))
;; show the user which layer they picked
(prompt lay_name)
;; create a list of layer names
;; do not add 'lay_name' to list if it already exists
;; in 'lst'
(if
(not
(vl-position lay_name lst); could also use the 'member' function here
)
(setq lst (cons lay_name lst))
; else
(prompt " has already been selected...")
)
) ; end of loop
)
;; now process the list of layer names
;; test the length of the list to make sure it's
;; greater than 0 (in other words in contains something)
(if (> (length lst) 0)
;; for each item in the list
(foreach i lst (princ (strcat i ",") fo))
)
(close fo); close the open file handle
(princ)
)
-
Matt
just trying to use one continous string(of layer names) to only show the entities I pick for viewing and freezing everything else out. and practice
Well, yeah, I gathered that much, but are you actually writing the string to a file as a means of saving it for future use? Or are you writing to a file for sheer learning practice?
Generally speaking, if I was to use this in "production code," I would save it as a global variable or write it to the registry if I had to carry it over from one drawing to another. Not to be rude, but using file I/O for this task is kind of a waste of resources.
-
Matt
I guess what your thinking is why not just leave it in a list and loop the thawing process till the list is empty...huh...this would be good as well...this whole idea was sparked from a newbie challenge and just kinda grew for me from there...and man, I sure did get alot of info I did not previously know.
But this by no means was a waste for me and I hope anyone that gave a hand feels the same.....looking foward to seeing some of your ideas
RD
-
Matt
I guess what your thinking is why not just leave it in a list and loop the thawing process till the list is empty...huh...this would be good as well...
Well, I'm thinking that if you want to process the layer list in a drawing, you can create the string (with the "," delimeter) and feed it to the layer command just fine. I do that in my layer utilities myself.
What I would object to is writing the name to a file. File I/O is a lot more expensive from a processing standpoint and doesn't contribute to efficient code in this example.
The only tip I would give right now is, always strive to make your code leaner, cleaner and cool.