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

lisp and osmode

6 REPLIES 6
Reply
Message 1 of 7
mrkaplan
6739 Views, 6 Replies

lisp and osmode

i use a few lisp scripts for drawing, that have the same code for managing osnaps .

1 - set variable V for current osmode

2 - set osmode to 0 before performing drawing commands

3 - perform drawing commands

4 - revert osmode to V


this works good when the scripts runs until the end .

however , if script interrupted by hitting escape during step 3 , which happens often ,
osmode stays at 0 . I have to manually turn on osnaps.


i suppose something in my code is missing to handle that problem .

?

thanks .
6 REPLIES 6
Message 2 of 7
d2cad
in reply to: mrkaplan

You have to program an error-function. This will reset your settings to the starting position. It is in Lisp, but useable in a script.

For example:

(defun myerror (e)
(if V (setvar "OSMODE" V))(setq *error* err_old))
(setq err_old *error* *error* myerror)
(setq V (getvar "OSMODE")) <<1>>
(setvar "OSMODE" 0) <<2>>

<<3 - perform drawing commands >>

(setvar "OSMODE" V) <<4>>
(setq *error* err_old)
Message 3 of 7
mrkaplan
in reply to: mrkaplan

you are right . my lisps did not have error handling . i will try your suggestion . thanks.
Message 4 of 7
Kent1Cooper
in reply to: mrkaplan

There is, for several versions of AutoCAD now, a simpler way to do this, by defining *error* as a localized variable subroutine. See:

http://discussion.autodesk.com/forums/message.jspa?messageID=6245546&tstart=0

That one doesn't involve OSMODE, but to make it do so in something like what the OP describes, within a larger routine (defun):

{code}
(defun C:YourCommand (/ *error* V)
(defun *error* (errmsg)
(princ errmsg)
(setvar 'osmode V)
); end defun - *error*
(setq V (getvar 'orthomode))
(setvar 'osmode 0)
....perform drawing commands....
(setvar 'osmode V)
(princ)
); end defun
{code}

You'll find countless examples on this Discussion Group of routines with more sophisticated error handlers, for example ones that will only print the error message if it's other than what you get if you hit Escape, many that include lots of other resets, etc., etc. But in simplest terms, making *error* into a localized variable means you don't need (setq err_old *error* *error* myerror) or (setq *error* err_old) [that second line twice], or the myerror or err_old variables, at all.

--
Kent Cooper


d2cad wrote...
....
(defun myerror (e)
(if V (setvar "OSMODE" V))
(setq *error* err_old)
)
(setq err_old *error* *error* myerror)
(setq V (getvar "OSMODE")) >
(setvar "OSMODE" 0) >
....
(setvar "OSMODE" V) >
(setq *error* err_old)
Kent Cooper, AIA
Message 5 of 7
scot-65
in reply to: mrkaplan

I agree 100% with one exception:

Inside the local error handler I check if the local variable is
present before employing onto the SETVAR.

(defun *error* (msg)
(if V (setvar 'osmode V) );if
;Then I clear the local variable:
(setq V nil)
(princ)
);end**

This prevents possible gremlins from migrating to other programs
AND if the next program restores the previous error handler, there will
be nothing to do other than setting the local variables to nil (again).

By the way, I have been using this local error handling structure since
R12 and it has not interfered in any way with the AutoCAD editor;
provided one uses the structure described above.

Why did I employ this structure such a long time ago?
The pretense was when a new command is entered, a new error
handler is written, which overwrites the one I created. Why set the
previous error handler in my routine when AutoCAD keeps writing
new error handlers?

Hummmmmmmm..........................

Scot-65
A gift of extraordinary Common Sense does not require an Acronym Suffix to be added to my given name.


Message 6 of 7
Kent1Cooper
in reply to: mrkaplan

In some circumstances, it may be worth doing what you suggest, but I don't think so in this case. Not that it would cause any problems or anything, but I just think it serves no purpose.

It's not possible for there to be no V variable. Setting it is the first thing that happens after the *error* definition, and before any User input or opportunity to hit Escape or anything, and it's getting the OSMODE value, of which there always is one. So there is no circumstance that I can imagine under which (if V) would not return True, and therefore no reason to bother with an (if) function to run a test with only one possible result.

Putting V in the localized variables list is what "prevents possible gremlins from migrating to other programs" -- after all, that's the most important *purpose* of localizing variables, which causes them to disappear when the routine is done. So there is no reason to set it to nil in the error handler -- the ending of the routine does that. Even if there was, coincidentally, some value assigned to that same variable *name* by something else before, this routine will [again, if the variable is localized] only use its own internal value for it, ignoring the external prior value, and that prior value will be what remains when this routine is done, unaffected by its use inside this routine -- again, that's part of the purpose of localizing variables. In such a case, even setting a localized variable to nil inside the routine will not set that external variable with the same name to nil, but its prior value will remain.

The one set of circumstances under which I would agree that setting a variable to nil in an error handler is worth doing is this combination:
A. The variable is [and only for some really good reason] *not* localized within the function, such as if it needs to be retained for use by other calling functions or commands;
B. The variable is set by or after some opportunity for User input [meaning that the function might be cancelled, such as with Escape, or the User might give it some invalid value, which can usually be prevented anyway];
C. The variable could possibly contain a "wrong" value that could throw off another function, or possibly another running of the containing function [not just *no* value, because in that case it would already be nil].

All that about "the next program restores the previous error handler" and "a new error handler...overwrites the one I created" and "AutoCAD keeps writing new error handlers" is entirely irrelevant, if *error* is defined as a localized subroutine within functions that need error handling. Each function uses its own internally, resetting only what it needs to, and because they're localized, they disappear at the end of the running of each function, and AutoCAD's native error handler takes over again. Nothing from one routine overwrites anything from another.

--
Kent Cooper
Kent Cooper, AIA
Message 7 of 7
Anonymous
in reply to: mrkaplan

Hi,

Assigning those variables to nil makes sense only if you define the error
routine outside the main function, thus being forced to leave the variables
global. But if you define the error handler *inside* the main function, then
you can declare the variables as local to the main function, so that no
assigning to nil is necessary:

(defun main ( / *error* old_cmdecho)

(defun *error* (s)
(setvar 'cmdecho old_cmdecho)
(princ)
)

(setq old_cmdecho (getvar 'cmdecho'))
(do_some_stuff_here)
(setvar 'cmdecho old_cmdecho)
(princ)
)

Regards

a écrit dans le message de news:
6353473@discussion.autodesk.com...
I agree 100% with one exception:

Inside the local error handler I check if the local variable is
present before employing onto the SETVAR.

(defun *error* (msg)
(if V (setvar 'osmode V) );if
;Then I clear the local variable:
(setq V nil)
(princ)
);end**

This prevents possible gremlins from migrating to other programs
AND if the next program restores the previous error handler, there will
be nothing to do other than setting the local variables to nil (again).

By the way, I have been using this local error handling structure since
R12 and it has not interfered in any way with the AutoCAD editor;
provided one uses the structure described above.

Why did I employ this structure such a long time ago?
The pretense was when a new command is entered, a new error
handler is written, which overwrites the one I created. Why set the
previous error handler in my routine when AutoCAD keeps writing
new error handlers?

Hummmmmmmm..........................

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

Post to forums  

Autodesk Design & Make Report

”Boost