custom user input at command line to exit from while

custom user input at command line to exit from while

christopher.l.evans
Advocate Advocate
1,698 Views
8 Replies
Message 1 of 9

custom user input at command line to exit from while

christopher.l.evans
Advocate
Advocate

I'm trying create an exit for while in gpts without resorting to esc creating the error: bad arguement type: point: nil.  Searching and reading about exiting while I'm here with my code but I still dont have an exit method and any input seems to continue gpts.

 

 

;Shorten pline start and end points by set value
(defun c:cl (/ cont pt1 pt2 d1 npt1 npt2 a1)
  (setq cont "Y")
  (while (= cont "Y")
    (gpts)
  )
) (defun gpts () (while (setq pt1 (getpoint "\nPick first point: ") pt2 (getpoint pt1 "\nPick second point: ")) (if (> (setq d1 (distance pt1 pt2)) 0.15) (progn (setq npt1 (polar pt1 (setq a1 (angle pt1 pt2)) (+ 0.05))) (setq npt2 (polar pt1 (setq a1 (angle pt1 pt2)) (- d1 0.05))) (command "_pline" npt1 npt2 "") ) ) (initget "Y N") (setq cont (getkword "n\Get more points? Y/N <Y>: ")) ) )

 

 

0 Likes
Accepted solutions (2)
1,699 Views
8 Replies
Replies (8)
Message 2 of 9

ВeekeeCZ
Consultant
Consultant
Accepted solution

Without the procedure...

 

(defun C:cl ( / cont pt1 pt2 d1 npt1 npt2 a1)
  (while
    (and (not (= cont "N"))
	 (setq pt1 (getpoint "\nPick first point: "))
	 (setq pt2 (getpoint pt1 "\nPick second point: ")))
    (if (> (setq d1 (distance pt1 pt2)) 0.15)
      (progn
	(setq npt1 (polar pt1 (setq a1 (angle pt1 pt2)) (+ 0.05)))
	(setq npt2 (polar pt1 (setq a1 (angle pt1 pt2)) (- d1 0.05)))
	(command "_pline" npt1 npt2 "")
      )
    )
    (initget "Y N")
    (if (/= "N" (setq cont (getkword "\nGet more points? Y/N <Y>: "))) ;After Enter getword returns nil
      (setq cont "Y"))
  )
(princ) )

 

 Or even without prompt for be continued

 

(defun C:cl ( / *error* cont pt1 pt2 d1 npt1 npt2 a1)

  (defun *error* (errmsg)
    (if (not (wcmatch errmsg "Function cancelled,quit / exit abort,console break"))
      (princ (strcat "\nError: " errmsg)))
    (princ)
  )
  
  (while
    (and (setq pt1 (getpoint "\nPick first point <exit>: "))
	 (setq pt2 (getpoint pt1 "\nPick second point: ")))
    (if (> (setq d1 (distance pt1 pt2)) 0.15)
      (progn
	(setq npt1 (polar pt1 (setq a1 (angle pt1 pt2)) (+ 0.05)))
	(setq npt2 (polar pt1 (setq a1 (angle pt1 pt2)) (- d1 0.05)))
	(command "_pline" npt1 npt2 ""))))
 (princ)
)

 

Message 3 of 9

Kent1Cooper
Consultant
Consultant
Accepted solution

The problem is that you're still in the (while) loop inside the (gpts) sub-routine, and there's nothing inside that to stop it so the CL command can get back out to its (while) loop to check on the 'cont' variable.  But since the (gpts) function contains only one internal function, it may as well be folded into the command directly, rather than be a sub-routine, so there can be only one (while) loop.

 

And you can do it in a way that doesn't require you to answer the question about whether to do more.  You can just have exiting be the default when it's asking for points, and you can keep picking more without answering the question, or hit Enter to stop.  One way:

 

;Shorten pline start and end points by set value
(defun c:cl (/ cont pt1 pt2 d1 npt1 npt2 a1)
  (setq cont "Y")
  (while (= cont "Y")
    (if
      (and
        (setq pt1 (getpoint "\nPick first point [or <exit>]: ")); returns nil on Enter/space
        (setq pt2 (getpoint pt1 "\nPick second point [or <exit>]: ")); returns nil on Enter/space
      ); and
      (if (> (setq d1 (distance pt1 pt2)) 0.15); then -- picked points for both -- draw it if long enough
        (progn
          (setq npt1 (polar pt1 (setq a1 (angle pt1 pt2)) (+ 0.05)))
          (setq npt2 (polar pt1 a1 (- d1 0.05)))
          (command "_pline" npt1 npt2 "")
        ); progn
      ); if
      (setq cont nil); else -- hit Enter/space for either point -- exit
    ); if
  ); while
  (princ)
); defun

 

[I also altered it slightly in a way that saves a little code by using the 'a1' variable, which was never used in the original.]

Kent Cooper, AIA
Message 4 of 9

Kent1Cooper
Consultant
Consultant

BeekeeCZ is right [second suggestion] that it can also be done without the 'cont' variable.  It can, in fact, be done with considerably fewer variables, since many are used only once and can just be calculated where they're used, without the variable middle-man:

 

;Shorten pline start and end points by set value
(defun c:cl (/ pt1 pt2)
  (while
    (and
      (setq pt1 (getpoint "\nPick first point [or <exit>]: "))
      (setq pt2 (getpoint pt1 "\nPick second point [or <exit>]: "))
    ); and
    (if (> (distance pt1 pt2) 0.15)
      (command
        "_pline"
        "_none" (polar pt1 (angle pt1 pt2) 0.05)
        "_none" (polar pt2 (angle pt2 pt1) 0.05)
        ""
      ); command
    ); if
  ); while
  (princ)
); defun

 

I also added the "_none" Osnap calls.  Without them, it would be advisable to set OSMODE to 0, which would also ideally mean saving its current value first and resetting it later, and an error handler that resets it on Escape -- none of the suggestions yet includes those.

 

BeekeeCZ's inclusion of an error handler is not a bad idea, though I think the only time it would suppress an error message is if the User stops the command with the Escape key.  You can decide whether it's worth suppressing a "Function cancelled" message, when that's not going to alarm anyone -- they knew that when they hit Esc.

Kent Cooper, AIA
0 Likes
Message 5 of 9

christopher.l.evans
Advocate
Advocate

Thank you for your explaination Kent.  It was helpful so I can understand what I was finding on exiting while earlier in context and not part of a large routine.

 

BeekeeCZ thanks for showing that with the error handler.  I had saw it mentioned in a reply to some of the stuff I was looking at but I wasn't certain how to use it.

 

 

Kent for the most part the point will be selected using an osnap setting so I'm not certain that will work for me.

0 Likes
Message 6 of 9

Kent1Cooper
Consultant
Consultant

@christopher.l.evans wrote:

.... 

Kent for the most part the point will be selected using an osnap setting so I'm not certain that will work for me.


If you would have running Osnap modes on for point selection, it's all the more important to have the routine "none"-ify the points it calculates to draw to.  Otherwise, depending on the relationship between the hold-back-the-ends size, the Zoom level, and the Osnap modes that are on, the ends might not be held back because they could Snap to the same points selected.  My latest one works great with Osnap used for selecting your reference locations, drawing the Plines with ends appropriately held back from them, whether the Osnap is in running modes that are on, or an individually-called-for mode at the time of a point selection.

Kent Cooper, AIA
0 Likes
Message 7 of 9

ВeekeeCZ
Consultant
Consultant

@christopher.l.evans wrote:

...

Kent for the most part the point will be selected using an osnap setting so I'm not certain that will work for me.


Kent's right. This using has no effect for picking your points pt1 and pt2. This is used just for "PLINE" and if OSNAP would be still running for PLINE it can accidentally meet some snap and it goes wrong even if you selected pt 1,2 before currently. Try it! Always turn off OSNAP or use _none as Kent did.

 

Since Kent was faster I post second way how to maintain OSNAPs. In this case is so much easier use _none and with some other benefits as noted.

 

(defun C:cl ( / *error* cont pt1 pt2 d1 npt1 npt2 a1 oldOSMODE)

  (defun *error* (errmsg)
    (if (not (wcmatch errmsg "Function cancelled,quit / exit abort,console break"))
      (princ (strcat "\nError: " errmsg)))
      (setvar 'OSMODE oldOSMODE) ;if error turn it back
    (princ)
  )

  (setq oldOSMODE 'OSMODE)
  
  (while
    (and (setq pt1 (getpoint "\nPick first point <exit>: "))
	 (setq pt2 (getpoint pt1 "\nPick second point: ")))
    (if (> (setq d1 (distance pt1 pt2)) 0.15)
      (progn
	(setq npt1 (polar pt1 (setq a1 (angle pt1 pt2)) (+ 0.05)))
	(setq npt2 (polar pt1 (setq a1 (angle pt1 pt2)) (- d1 0.05)))
	(setvar 'OSMODE 0)
	(command "_pline" npt1 npt2 "")
	(setvar 'OSMODE oldOSMODE))))

  (setvar 'OSMODE oldOSMODE) ;usually in the end of program turn it back - in this case redundant
  (princ)
)

 

0 Likes
Message 8 of 9

christopher.l.evans
Advocate
Advocate

I tried it and both work great, I was thinking of none by its actual definaition, sorry.  What does it do though?  Im on Product Design Suite Ultimate 2015 now and the only referance to _none in developers help is the DIMBLK system varible.

0 Likes
Message 9 of 9

Kent1Cooper
Consultant
Consultant

@christopher.l.evans wrote:

..., I was thinking of none by its actual definaition, sorry.  What does it do though?  ... the only referance to _none in developers help is the DIMBLK system varible.


It disables any "running" Object Snap mode(s) for just the immediately-next point.  Read about it in Help for the OSNAP command.  [It isn't listed among the modes under the OSMODE System Variable, because there's no point in having None as a "running" Osnap mode -- turning Osnap off does that.  And it would be kind of meaningless to have it combined with any other mode(s).]

Kent Cooper, AIA
0 Likes