I'm opened to reformating the list, as long as my non lisper collegues are able to edit if required without stepping into the lsp files. I also wanted my function to "autoupdate" if the file containing the grades is updated without having to make everyone restart autocad (since everytime the lisp reopen the file)
My intentions were to store its content into a lisp list (importedgradelist) to later on retrieve the informations regarding the grade with function like (nth y (nth x (importedgradelist)))
First attempt: I opened the file and used read-line
(defun C:RREAD () (setq desc_grade_file (findfile "grades.txt") IMPORTEDGRADELIST NIL) (if (setq f (open desc_grade_file "r")) ;open the file in read mode (while (setq txtLine(read-line f)) ;while lines of text exist in file; (ALERT txtLine) ;print the text into an alert. Works! (SETQ IMPORTEDGRADELIST (append IMPORTEDGRADELIST (list txtLine))) );close the while statement (princ "\n Error - Could not find file");print a message on the else statement ) )
as the items composing it are strings, I ended up with that
("((Plate)(STEEL ASTM A572 GR.42)(STEEL CSA G40.21 300W (44W)))" "((W-beam)(STEEL ASTM A992 or A572 GR.50)(STEEL CSA G40.21 350W))" "((I-beam)(STEEL ASTM A36)(STEEL ASTM A36))"..... and cant use it. (I think)
Then I thought the way to go would be to use the (setq txtchar(chr(read-char f))) function. I know the char retrieving works, the pain in my finger reminds me of it... Ive added (alert txtchar) and had to click on "ok" a billion times for each char on that list (Yeah, newbie mistake. Very funny one thought!) Heres the code I made
(defun C:READchar () (setq desc_grade_file (findfile "grades.txt") IMPORTEDGRADELIST NIL) (if (setq f (open desc_grade_file "r")) ;open the file in read mode (while (setq txtchar(chr(read-char f))) ;while lines of text exist in file; (ALERT txtchar) ;print char to an alert... works but don't. seriously ^±^' (SETQ IMPORTEDGRADELIST (append IMPORTEDGRADELIST (txtchar))) );close the while statement (princ "\n Error - Could not find file");print a message on the else statement ) )
Of course now I can't append since I dont have a list anymore. I'm kind of stuck here and not sure what to do next. I'm not even sure if I'm heading in the correct direction. I'd be glad to receive any comments, suggestions and/or advices!
I would take a different tack and only have a single line per entry but have it set up with known parameters. Something like this
1234567890123456789012345678901234567890
Newname my name Col Line Type
ceiling--2 ceiling--2 6 continuous
ceiling--3 ceiling--3 6 continuous
Then using the substr command you can read each individual variable without using lots of nth's
Thanks for sharing your thougths on that one
@Lee Mac: Special thank to you, for your site that is a great reference that helped me learn so much, thank you for your HUGE commitment toward many forums. That being said, despite the fact that I could find many tutorials for real-line and read-char functions, I didn't find much about the read function. From what i've seen, only the first expression is returned, so I don't see how it could suit my needs.
@Bigal: I think I see where your going, but with substr functions, if someone modify the list, the parameters for the substr would also have to be change accordingly.. and making the values dynamic would be complicated.
Yesterday I was trying to use append with strings, I think I was tired...
Ok, now I've manage to populate my lisp list with read-char and strcat and using autolisp string-handling functions (like vl-string-trim) seems the easiest way to complete the formating...
When I monitor !importedgradelist I can see that it gets populated but can't figure why nothing get executed after my while function. Did I misplaced the close?
[code](defun C:READchar () (setq desc_grade_file (findfile "grades.txt") IMPORTEDGRADELIST ""); "" instead of nil to be able to strcat (if (setq f (open desc_grade_file "r")) (while (setq txtchar(chr(read-char f))) (SETQ IMPORTEDGRADELIST (strcat IMPORTEDGRADELIST txtchar)) );close the while statement (princ "\n Error - Could not find file");print a message on the else statement );close if (close desc_grade_file); -> is this close at the correct place? This alert is not being processed..why?
Thank you Jef! -
I really appreciate your gratitude for the time & effort that I invest in my site and in my contributions across the various CAD forums.
Thanks for the link, this is one of the documentation that I read that made me say "From what i've seen, only the first expression is returned, so I don't see how it could suit my needs.", and reading your more-than-concrete example I realized that read-line or read-char also send the first line/char. This is why we use them nested in a while function. That is the kind of thing that I never get looking at Autodesk's not-so-concrete-examples.
So the close and the manipulation of the lst (print (reverse lst)) are in the progn. Understood. 3 questions tho
-if your var lst is local, how can you use its content when the execution is completed?
-(not the first time i've seen it but don'T understand) why do you reverse the list?
I always put and use alerts (like everywhere) when I'm creating lisps to follow the execution and also to monitor the value of variables.. So i'm very curious to know: Why if I substitute (print (reverse lst)) for (alert (reverse lst)), I don't get any popup alert executing the lisp?
edit: If I remove lst from local variables (and make it global), execute the command readit it then look at it (!lst) I get nil as a result...
Yes, since these expressions are to be evaluated as part of the 'then' argument for the if function.
Since the if function can only accept three parameters: the test expression, the 'then' expression and the 'else' expression, in order to evaluate multiple expressions for the 'then' parameter, I pass the expressions to the progn function (which simply evaluates all supplied expressions and returns the value of the last evaluated expression) so that this single progn expression can be passed to the if function to constitute the 'then' argument.
This was only an example, the program could be written as a function to return the list data for use by the calling program, e.g.:
Just a bit more on a 1 liner you are right setting up a column arrangement is a bit of a pain, an alternative is to use a CSV comma seperated file, you make a search for comma defun by reading a line then stepping 1 character a time till you find the "," it then just require setting a variable and calling the defun, nice thing is once done you can use it again no matter how many variables as you know the maximum No of characters.
; example not tested(setq x 1)(setq var1 (csvstr newline x)) ; 1 is the 1st character in the readline (setq var2 (csvstr newline x)) ; x is the number of the last character just found(setq var3 (csvstr newline x)) ; just repeat (defun csvstr ( ) (setq ans "") (setq char_found "") (while (/= x y) (setq char_found (substr new_line x 1)) (setq x (+ x 1)) (if (= char_found ",") (setq x y) (setq ans (strcat ans char_found)) ) ))
I totally understand the progn function, I was not sure if I had to put the close within the if. A Wise man wrote somewhere "With Mathematics there is the possibility of perfect rigour, so why settle for less?" The close function belong in the if and is required only if the file is opened. (So logic I am almost ashamed that I asked! lol) 100% understood.
Right! Cons combine a single element to a list puting it before the list. totally understood.
Alert only accept strings! That was one piece missing in my puzzle! Even with that part I cant figure why in your first example (c:readit ) , after closing the file the "(print (reverse lst))" was not printing anything. I need to have a lisp var containing the list to use it, so I tried to replace the (print (reverse lst)) for (setq templst (reverse lst)) but unfortunately !templst returns nil. My brain is totally fried at the moment. /me almost sad
Even tho I must admit the way I did may not be the optimal and fastest one, (I did it with read-char and strcat), but I have gathered all the information required.
For now, I would settle for something that works... The only problem left in that direction is that I have it in a string and need to transfer it somehow in a list... haven't found how. Can it be done?
edit: I just had to reconnect and after refreshing saw Bigal's reply. Before beginning this task I thought about using cvs, and without digging further I wasn't sure if I could manage a list of lists in a csv. I'm starting to have an headache, I'll take a deeper look tomorrow in the morning.
Looking over the code for my original example, I see no reason why the code should fail, unless the file is empty. Though note that the scope of the lst variable is limited to the c:readit function, since it has been declared local to this function.
Rather than using a global variable 'templst', I would recommend using the return of the function as shown in my last post ('readit') in your main program. Hence, your main program would call the function:
Though, be aware that points (periods) in variable symbols will be ignored by the read function, since the function will attempt to retrieve a numerical value or dotted list pair when encountering a point.