shailujp Posted September 17, 2013 Posted September 17, 2013 Hi all, I'm stuck inside the while loop and can't come out of it. Can someone help me on this (if possible please provide information on why its not closing). This is just a small function of a much larger lisp that I'm playing with and Esc to exit means complete program termination. Here is how I inteded it to be used for. Once user decides to use drawshapes, and if the answer is one of the keyword (eg. Rectangle) then user should be able draw as many rectangles he likes and if Enter is hit it should come back to main menu again ask for keyword to choose (circle or ellipse). Thanks in advance. (defun drawshapes (/ dtype) (setvar "cmdecho" 1) (setq dtype T) (while dtype (initget (+ 2 4) "R P C E") (prompt "\n*** Enter option R, P, C, E ***") (setq dtype (getkword "\nselect your option: Rectangle, Pline, Circle, Ellipse or hit Enter to close:")) (if dtype (cond ( (= dtype "R") (setq loop T) (while loop (command "_.rectang") (while (= 1 (logand 1 (getvar 'CMDACTIVE)))(command pause)) ); end while ) ( (= dtype "P") (setq loop T) (while loop (command "_.PLINE") (while (= 1 (logand 1 (getvar 'CMDACTIVE)))(command pause)) ); end while ) ( (= dtype "C") (setq loop T) (while loop (command "_.circle") (while (= 1 (logand 1 (getvar 'CMDACTIVE)))(command pause)) ); end while ) ( (= dtype "E") (setq loop T) (while loop (command "Ellipse") (while (= 1 (logand 1 (getvar 'CMDACTIVE)))(command pause)) ); end while ) ); end cond ); end if ); end while (setvar "cmdecho" 0) );end defun Quote
Bhull1985 Posted September 17, 2013 Posted September 17, 2013 (while dtype to (if dtype? Not a master who could tell you why and exactly why but those are my first thoughts, and what I would look into Quote
shailujp Posted September 17, 2013 Author Posted September 17, 2013 I already have (if dtype" ..below the getkword line. Isnt that the same thing? I tried changing the while to if and gives me syntax error. I think I have too many times Setq for Dtype. Not sure why...I'm confused Quote
David Bethel Posted September 17, 2013 Posted September 17, 2013 Some where, you will have to set loop to nil. Also, you can use: (while (setq dtype (getkword "\n.... -David Quote
David Bethel Posted September 17, 2013 Posted September 17, 2013 Also, AFAIK, getkword really only uses 1 or 0 in the ( initget ) call. -David Quote
Bhull1985 Posted September 17, 2013 Posted September 17, 2013 Well if you're going to use (while) most of the times I'll see an increment counter attached to the while.. (setq cntr 1) actions (setq cntr (1+ cntr)) ;increment the counter or like david said you can (setq dtype nil) after each of your ((= dtype) statements. That would exit the loop after one usage, but it says you want them to be able to enter many of these shapes...so you could maybe set a flag based from more user input. Um, noticing in your code these: (setq loop T) (while loop means that yes indeed they should stay inside that loop until your add something that closes/exits the loop usually it's (setq loop nil) for what you've got there. hth Quote
Bhull1985 Posted September 17, 2013 Posted September 17, 2013 also here's a snippet where i'm using a combination of initget and strcase to obtain the correct user input. The initget function will also ensure that the user selects from the predefined list, so testing for user input I didn't feel as necessary as normal (initget "Freeze Thaw On oFF Lock Unlock eXit") ;; establish controls (setq lstate (strcase (getkword "\nChoose layer control [Freeze/Thaw/On/oFF/Lock/Unlock/eXit]:"))) wasn't sure that the arithmetic in the initget was actually doing anything, because simply tacking a (strcase) onto the second half allowed for any capitalization of the choices given, and as thus....prog only proceedes if a correct selection is made, without use of arithmetic in the initget. Wether this is more or less correct i'm not sure but it worked well for my purposes Quote
Bhull1985 Posted September 17, 2013 Posted September 17, 2013 Another example, this one credit goes to Jeffery p sanders and his importxyz.lsp. just taking an excerpt to show some exiting methods ;;;--- Inform the user of progress (if(> cellCnt 99) (progn (princ "\n Currently retrieving cells in Row ") (princ (strcat (itoa stRow) " of " (itoa LsRow))) (setq cellCnt 0) ) ) ;;;--- Increment the column (setq stCol(+ stCol 1)) ;;;--- Make sure the column stays in the range (if(> stCol LsCol) (setq stCol copyCol stRow(+ stRow 1)) ) ) ;;;--- Return the list cellList ) play close attention to the variables in thatn, though.. Quote
Bhull1985 Posted September 17, 2013 Posted September 17, 2013 (edited) Annnnnd one more example, hoping it helps... (this one is Jeff Tippit, SPAUG President, www.spaug.org 's lisp) (setq DO_MORE "Y") (while (= DO_MORE "Y") (BIG_LOOP) ); End while (defun BIG_LOOP () (USER_INPUT) (setq FRAMUS_DONE 0) (while (/= FRAMUS_DONE 1) (SHOW_DIALOG) ); End while (I_OR_G) (initget "Y N") (setq DO_MORE (getkword "\nChange more blocks? Y/N <Y>: ")) (if (or (= DO_MORE "y") (= DO_MORE "") (= DO_MORE nil) ); End or (setq DO_MORE "Y") ); End if ); End BIG LOOP In this one just above you can see how he takes user input and decides wether to proceed the program based off of the user selection Edited September 17, 2013 by Bhull1985 additional comments Quote
neophoible Posted September 17, 2013 Posted September 17, 2013 (edited) I concur that the loop variable will keep you in the whiles forever unless you find a way to change it. Overall, your approach seems to be on the right track. I prefer things to look more AutoCADish to the user. Here is an edit that fleshes out your options, adds an explicit exit option, and requires a simple return/Enter to repeat the last option. It requires an extra variable as well, which should be added to the local list. UNTESTED. (setq dtype "eXit") (while (or (initget "Rectang Pline Circle Ellipse eXit") (/= "eXit" (setq dtypekey (getkword (strcat "[Rectang/Pline/Circle/Ellipse/eXit] <" dtype ">: " ) ) ) ) ) (if dtypekey (setq dtype dtypekey)) (cond ( (= "eXit" dtype) ) (T(command (strcat "_." dtype)) (while (= 1 (logand 1 (getvar 'CMDACTIVE))) (command pause) ) ) ) ) Well, after a quick review, I see that my cond isn't really necessary as is, since the loop should not get that far if dtype = "eXit". OOPS! Edited September 17, 2013 by neophoible oops! Quote
Bhull1985 Posted September 17, 2013 Posted September 17, 2013 (edited) Can you comment out those lines neo? Would like to know how some of them are used if you don't mind Comment out as in add comments to, not....take comments out. Thanks Edited September 17, 2013 by Bhull1985 clarification Quote
neophoible Posted September 17, 2013 Posted September 17, 2013 Can you comment out those lines neo? Would like to know how some of them are used if you don't mind Comment out as in add comments to, not....take comments out. Thanks I'll be happy to, but I've got to go right now. I'll try to get back to it later today. But if someone else feels up to explaining, that's fine by me. If you look at it closely and try it out, it's not that hard to figure, and the meat of it is really from the OP. I just tightened it up a bit. Quote
neophoible Posted September 17, 2013 Posted September 17, 2013 (edited) OK, I edited out the extraneous cond, adjusted for when getkword returns nil (used my precious cond for that!), and included a few comments. The overall goal is to provide the user a few options of what to draw using simple keywords formatted as one might find in standard AutoCAD commands. To exit, enter X (this is the initial default). Hit return to repeat the previous choice. ; initialize default value (exit seemed the obvious choice) (setq dtype "eXit") ; begin looping for input; stop only if user explicitly exits (while ; used [b][color=blue]or[/color][/b] to avoid repetition--[b][color=blue]initget [/color][/b]always returns nil, so won't change loop (or ; need to initialize for keywords (initget "Rectang Pline Circle Ellipse eXit") ; continue until explicit exit entered (except as first default) (/= "eXit" (setq dtype ; save the draw type variable explicitly using itself as the default (cond ( (getkword (strcat ; concatenate bracketed options with the saved default "\n[Rectang/Pline/Circle/Ellipse/eXit] <" dtype ">: " ) ) ) ; dtype is set to itself if user hits enter, otherwise to the new option ( dtype ) ) ; close /= & setq ) ) ; close or ) ; the options are all AutoCAD commands--add the _. prefix to make sure the ; native AutoCAD command is being used (command (strcat "_." dtype)) ; continue in the selected command pausing for user input until finished ; this is directly from the OP (while (= 1 (logand 1 (getvar 'CMDACTIVE))) (command pause) ) ) For those wanting to actually use this for commands, perhaps I should have noted that you will probably want to turn on the variable CMDECHO like shailujp did: (setvar "cmdecho" 1) Edited September 18, 2013 by neophoible added quick note about CMDECHO Quote
shailujp Posted September 18, 2013 Author Posted September 18, 2013 Hi Neo, Thanks for your complete explaination. I have incorporated this code and it works great. It took me a while to undestand it completely due to my inexperience. I also liked the use of strcat "_." along with standard AutoCAD commands. Just then I realized what you ment by AutoCADish. I prefer things to look more AutoCADish to the user. Thanks for your help. Quote
neophoible Posted September 18, 2013 Posted September 18, 2013 Hi Neo, Thanks for your complete explaination. I have incorporated this code and it works great. It took me a while to undestand it completely due to my inexperience. I also liked the use of strcat "_." along with standard AutoCAD commands. Just then I realized what you ment by AutoCADish. Thanks for your help. Glad to help, shailujp, and glad you were able to understand it. Note that part of making it more AutoCADish is putting the options in square brackets, as this can make them auto-interactive via menus, for those who prefer to pick it with the mouse. Quote
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.