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

[Vlisp] What to do with 'command-s'

31 REPLIES 31
SOLVED
Reply
Message 1 of 32
Simon_Weel
32637 Views, 31 Replies

[Vlisp] What to do with 'command-s'

There's a post about the behavior of AutoCAD 2015 and (command ...) functions in custom *error* functions. AutoCAD 2015 displays this message if it encounters this situation: "Cannot invoke (command) from *error* without prior call to (*push-error-using-command*). Converting (command) calls to (command-s) is recommended." So I edited all LISP files and changed (command ...) to (command-s ...). And then I found out this doesn't work in AutoCAD 2010. Command-s was introduced in release 2012. We use different versions of AutoCAD and they all use the same LISP routines. I would like to keep it that way, so I wonder if I can either get rid of the 2015-message or tweak things to get (command-s ...) working in release 2010. Any ideas? Simon
31 REPLIES 31
Message 21 of 32
Kent1Cooper
in reply to: Anonymous


@Anonymous wrote:

.... I have AutoCAD 2015 and would like to try edit all LISP files and change (command ...) to (command-s ...). ....


It is not at all necessary to change all (command) functions to (command-s) functions!  Only those inside *error* handlers.

Kent Cooper, AIA
Message 22 of 32
JamesMaeding
in reply to: Kent1Cooper

well, I think you also have to when compiling to vlx.

I forget the exact rule, but something like "if the command will not finish in one statement, use command-s..."

I bet most beginners just try it without, then switch if they get problems...


internal protected virtual unsafe Human() : mostlyHarmless
I'm just here for the Shelties

Message 23 of 32
dlanorh
in reply to: roland.r71

Why use command in an error routine at all?

(command "_.undo" "_end")

can be replaced with

(vla-endundomark doc); where doc is the current document 

My basic localised error routine is

(vl-load-com)
(defun c:test (/ *error* c_doc) (defun *error* ( msg ) (if (and c_doc (= 8 (logand 8 (getvar 'UNDOCTL)))) (vla-endundomark c_doc)); if c_doc set & undo mark started then end undo mark (if (not (wcmatch (strcase msg) "*BREAK*,*CANCEL*,*EXIT*")) (princ (strcat "\nAn Error : " msg " occurred."))) (princ) );_end_*error*_defun

(setq c_doc (vla-get-activedocument (vlax-get-acad-object)))

I am not one of the robots you're looking for

Message 24 of 32
roland.r71
in reply to: dlanorh


@dlanorh wrote:

Why use command in an error routine at all?

 

I can think of a few reason, why or why not,

but i'll stick to the one most people can relate to: I'm just happy when I get it to work. By whatever means. Smiley Wink

Message 25 of 32
dlanorh
in reply to: roland.r71


@roland.r71 wrote:

I can think of a few reason, why or why not,

but i'll stick to the one most people can relate to: I'm just happy when I get it to work. By whatever means. Smiley Wink


I can relate to that Robot LOL

I am not one of the robots you're looking for

Message 26 of 32
Kent1Cooper
in reply to: dlanorh


@dlanorh wrote:

Why use command in an error routine at all? ....


 

Because Undo-End and resetting of System Variables are not the only things you might want to do in an *error* handler that can be done with (command) or (command-s) functions.  One example is LayIsoStep.lsp with its LIS command, available >here<, which stores the current Layer conditions in a temporary Layer stAte, and at the end, restores the original state of things and deletes that temporary stAte definition, by way of Layer commands.  In the event of some kind of failure, the *error* handler does those same things, also with Layer commands.  I'm not sure whether there's a way to do that without them, but if so, I imagine it would take much more code to do it.

 

And there are some System Variables  that can't be reset with (setvar).  For example, if a routine changes the view direction, and thereby the VIEWDIR System Variable, that's read-only, so it can't be restored to what it was originally in an *error* handler with (setvar 'viewdir ....), but requires a VPOINT or perhaps DVIEW command  to do it.

Kent Cooper, AIA
Message 27 of 32
john.uhden
in reply to: dbroad

I've done this before.  At the beginning of each applicable routine...

(if (not defun-q) (setq defun-q defun))

so...

(if (not command-s)(setq command-s command))

John F. Uhden

Message 28 of 32
dlanorh
in reply to: Kent1Cooper


@Kent1Cooper wrote:

Because Undo-End and resetting of System Variables are not the only things you might want to do in an *error* handler that can be done with (command) or (command-s) functions.  One example is LayIsoStep.lsp with its LIS command, available >here<, which stores the current Layer conditions in a temporary Layer stAte, and at the end, restores the original state of things and deletes that temporary stAte definition, by way of Layer commands.  In the event of some kind of failure, the *error* handler does those same things, also with Layer commands.  I'm not sure whether there's a way to do that without them, but if so, I imagine it would take much more code to do it.

 

And there are some System Variables  that can't be reset with (setvar).  For example, if a routine changes the view direction, and thereby the VIEWDIR System Variable, that's read-only, so it can't be restored to what it was originally in an *error* handler with (setvar 'viewdir ....), but requires a VPOINT or perhaps DVIEW command  to do it.


 

It relatively easy to get the state of all the layers and store them in a list by iterating the layer table. Yes the code would be longer, but you would only have to write it once, thats the beauty of cut and paste.

I see your point with reference to read only sysvars, but I've notice in my 26+ years of using Autocad, that when an error occurs in a lisp; the first action, 99 times out of 100, is to restore the drawing to the pre lisp state using undo that is usually followed by saving the drawing. Therefore I don't see the point in doing complicated restores within the local error function when the user is going to undo everything. Providing them with a one step undo is at the top of my list.

I am not one of the robots you're looking for

Message 29 of 32
john.uhden
in reply to: owenwengerd

Hi, Owen.  Glad to see another old-timer show up here.

Readability is an issue.  I've been looking over work I did 12 years ago to adapt to a new project.  There has never been any bugs in the work, but I'm having a helluva time following it.  😕

In it, I found my first published usage of xrecords.  With vlax-ldata-put and vlax-ldata-get I am able to store program entries as defaults in the drawing file so if someone enters one wrong piece of data, they can run it again without having to fill in all the other data again, even if cancelled.  Of course, it disappears with an Undo or without a save, but it's way better than the old way.  These pool liners generally have about 16 numbers (architectural lengths) to input for each shape.  To me, typing feet and inches vaccuums.

John F. Uhden

Message 30 of 32
john.uhden
in reply to: dlanorh

There are some disadvantages to "restoring" things via Undo.

I think it's this same thread where I recently mentioned saving lisp inputs in the drawing in case one of them was a mistake.  So that when run again, all the previous inputs would be the defaults and the user need only to change the errant one.  An Undo would destroy that saved data thereby wasting the user's time.

I think I recall other ways around setting and restoring views, though I would have to search for them in my files.  ActiveX gives us a lot more control than we used to have with just DXF entity data.  Sometimes we just need to dig and find it.

John F. Uhden

Message 31 of 32
Anonymous
in reply to: roland.r71

Hi all,

 

this is my last attempt to solve this issue, I have tried everything in the book, I have pestered Kent, I have asked a coder friend for help, and still no dice.

I have AutoCAD 2015, I have been using WobblyPline lisp provided by Kent for a year, until about 2 months ago, after a Windows automatic update (that's my best guess) the WPL command suddenly started showing this messagelarge (1).png

Following Kent's (very patient guy, btw) advice, I added (vl-load-com) at the end of the code of the lisp but it did nothing for the restoration of the lisp. I have shut down CAD, opened it up again, reloaded the lisp, same issue: once I get to the select objects, I get the error shown above.

I'll even throw in the lisp code here, both as a pasted in text and an attachment, if anyone has any genius ideas, I'm all ears!  

 

Lisp code with (vl-load-com) at the end.

;;;  WobblyPline.LSP [Command name: WPL]
;;;  To draw a Polyline that wobbles "randomly" from the plain path created or selected.
;;;  Options:
;;;    1.  create new, or select EXisting, path of any appropriate type;
;;;    2.  number of line segments in resulting polyline;
;;;    3.  degree of randomization [as a percentage of average segment length];
;;;    4.  after first use, re-use PRevious path [changing any or all choices], or
;;;    5.  after first use, Redo wholesale, using previous path and all previous choices;
;;;    6.  Retain or Delete base path.
;;;  Under Existing-path option, asks User to select again if nothing selected, or selected object
;;;    is an inappropriate entity type, or is on a locked Layer under Delete-path option.
;;;  Draws 3DPolyline [randomized only in X-Y direction] if path is one; otherwise draws 2D
;;;    ["lightweight"] Pline.
;;;  Draws on current Layer, unless Deleting Existing path; if so, draws on its Layer.
;;;  Remembers choices and offers them as defaults for subsequent use.
;;;
;;;  Kent Cooper, October 2008
;
(defun C:WPL (/ *error* cmde osm typetemp pathsel deltemp 3Dpath segtemp pcttemp
  segavg maxdis intpt blips base angdisp distdisp)
;
  (defun *error* (errmsg)
    (if (/= errmsg "Function cancelled") (princ (strcat "\nError: " errmsg)))
    (setvar 'osmode osm)
    (setvar 'blipmode blips)
    (command "_.undo" "_end")
    (setvar 'cmdecho cmde)
  ); end defun *error*
;
  (setq cmde (getvar 'cmdecho))
  (setvar 'cmdecho 0)
  (command "_.undo" "_begin")
  (setq
    blips (getvar 'blipmode)
    osm (getvar 'osmode)
  ); end setq
  (setvar 'osmode 0)
;
  (if *wpl*
    (initget "Line Arc Circle Pline 3dpoly Ellipse Spline EXisting PRevious Redo")
    (initget "Line Arc Circle Pline 3dpoly Ellipse Spline EXisting"); no PR/R options on first use
  ); end if
  (setq typetemp
    (getkword
      (strcat
        "\nPath type [new Line(single)/Arc/Circle/Pline(2D)/3dpoly/Spline/Ellipse, or EXisting"
        (if *wpl*
          "/PRevious/Redo"
          ""
        ); end if
        "] <"
        (if *wpl* *wpltype* "Pline"); at first use, Polyline default; otherwise, previous type
        ">: "
      ); end strcat
    ); end getkword
    *wpltype*
      (cond
        (typetemp); if User typed something other than Enter, use it
        (*wpltype*); if Enter and there's a previous type, use that
        (T "Pline"); otherwise [Enter on first use], Polyline default
      ); end cond & *wpltype*
  ); end setq
;
  (if (= *wpltype* "PRevious") (entdel *wpl*)); if re-using Previous path with option
    ;  of new choices [but not wholesale Redo], delete previous wobbly Polyline
  (if (and (= *wpltype* "PRevious") (= *wpldel* "Delete")) (entdel *wplpath*)); bring back Previous path
;
  (if (/= *wpltype* "Redo"); if not Redoing,
    (progn
      (initget "Retain Delete")
      (setq
        deltemp
          (getkword
            (strcat
              "\nRetain or Delete base path [R/D] <"
              (if *wpl* (substr *wpldel* 1 1) "D"); at first use, Delete default; otherwise, previous type
              ">: "
            ); end strcat
          ); end getkword
        *wpldel*
          (cond
            (deltemp); if User typed something, use it
            (*wpldel*); if Enter and there's a previous choice, use that
            (T "Delete"); otherwise [Enter on first use], Delete
          ); end cond & *wpldel*
      ); end setq
    ); end progn
  ); end if
;
  (cond ; select or make path
    ((and (= *wpltype* "EXisting") (= *wpldel* "Delete")); check selected object for locked Layer if Delete option
      (prompt "\nTo make an EXisting path wobbly,")
      (while
        (not
          (and
            (setq pathsel (ssget ":S" '((0 . "LINE,ARC,CIRCLE,LWPOLYLINE,POLYLINE,ELLIPSE,SPLINE"))))
            (= (cdr (assoc 70 (tblsearch "layer" (cdr (assoc 8 (entget (ssname pathsel 0))))))) 0); 0 for Unlocked, 4 for Locked
          ); end and
        ); end not
        (prompt "\nNothing selected, or object is not a finite path type, or is on a Locked Layer; try again:")
      ); end while
    ); end first condition - EXisting with Delete
    ((= *wpltype* "EXisting")
      (prompt "\nTo make an EXisting path wobbly,")
      (while
        (not (setq pathsel (ssget ":S" '((0 . "LINE,ARC,CIRCLE,LWPOLYLINE,POLYLINE,ELLIPSE,SPLINE")))))
        (prompt "\nNothing selected, or object is not a finite path type; try again:")
      ); end while
    ); end second condition - EXisting with Retain
    ((and (= *wpltype* "Redo") (= *wpldel* "Delete")) (entdel *wplpath*)); bring back path
    ((= *wpltype* "Line") (setvar 'cmdecho 1) (command "_.line" pause pause "") (setvar 'cmdecho 0))
    ((not (or (= *wpltype* "Redo") (= *wpltype* "PRevious"))); all other entity types
      (setvar 'cmdecho 1)
      (command *wpltype*)
      (while (> (getvar 'cmdactive) 0) (command pause))
      (setvar 'cmdecho 0)
    ); end fourth condition
  ); end cond
;
  (setq
    *wplpath* ; set object as base path
      (cond
        ((= *wpltype* "EXisting") (ssname pathsel 0))
        ((or (= *wpltype* "Redo") (= *wpltype* "PRevious")) *wplpath*)
        ((entlast)); newly created path
      ); end cond & *wplpath*
    pathlength (vlax-curve-getDistAtParam *wplpath* (vlax-curve-getEndParam *wplpath*))
    3Dpath (= (cdr (assoc 0 (entget *wplpath*))) "POLYLINE")
  ); end setq
;
  (if (/= *wpltype* "Redo"); if not Redoing,
    (progn ; then - ask for other input
;
      (if *wpl* (initget 6) (initget 7)); no Enter on first use, no 0, no negative
      (setq
        segtemp
          (getint
            (strcat
              "\nNumber of segments"
              (if *wplseg* (strcat " <" (itoa *wplseg*) ">") ""); no default on first use
              ": "
            ); end strcat
          ); end getint
        *wplseg* (if segtemp segtemp *wplseg*)
      ); end setq
;
      (if *wplpct* (initget 4) (initget 5)); no Enter on first use, 0 allowed, no negative
      (setq
        pcttemp
          (getreal
            (strcat
              "\nMaximum displacement as percentage of average segment length"
              (if *wplpct* (strcat " <" (rtos *wplpct* 2 2) ">") ""); no default on first use
              ": "
            ); end strcat
          ); end getreal
        *wplpct* (if pcttemp pcttemp *wplpct*)
      ); end setq
;
    ); end progn - not Redoing
    (entdel *wpl*); else - if Redoing, eliminate previous one
  ); end if
;
  (setq
    segavg (/ pathlength *wplseg*)
    maxdis (* segavg *wplpct* 0.01); maximum displacement
    intpt 1 ; starting value for intermediate point
  ); end setq
  (setvar 'blipmode 0)
;
  (if (not 3Dpath) (command "_.ucs" "_new" "_object" *wplpath*)) ; set UCS to match object if appropriate
  (if (= *wpldel* "Delete") (setvar 'clayer (cdr (assoc 8 (entget *wplpath*))))) ; if Deleting Existing path, draw on same Layer
;
  (command
    (if 3Dpath "3dpoly" "_.pline"); command type - Pline for all but 3D Polylines
    (trans (vlax-curve-getStartPoint *wplpath*) 0 1)
    (while (< intpt *wplseg*)
      (setq
        base (vlax-curve-getPointAtDist *wplpath* (* segavg intpt)); un-randomized intermediate location
        angdisp (* 2 pi (/ (atoi (substr (rtos (rem (getvar 'cdate) 1) 2 16) (- 17 (fix (rem (cadr base) 3)) (fix (abs (* (sin intpt) 10)))) 2)) 100.0))
          ; randomized angle
        distdisp (* maxdis (/ (atoi (substr (rtos (rem (getvar 'date) 1) 2 16) (- 18 (rem (fix (sqrt (abs (car base)))) 5) (rem intpt 3)) 2)) 100.0))
          ; randomized distance
        intpt (1+ intpt); increment intermediate point number
      ); end setq
      (command (polar (trans base 0 1) angdisp distdisp)); feed randomized location out to Pline or 3dpoly command
      (if (vlax-curve-isClosed *wplpath*)
        "_close"
        (trans (vlax-curve-getEndPoint *wplpath*) 0 1); last point for open path
      ); end if
    ); end while
    (if (not (vlax-curve-isClosed *wplpath*)) ""); end Pline or 3dpoly for open path
  ); end command - pline or 3dpoly
;
  (if (not 3Dpath) (command "_.ucs" "_prev")); reset UCS if appropriate
  (if (and (or (= *wpltype* "EXisting") (= *wpltype* "PRevious") (= *wpltype* "Redo")) (= *wpldel* "Delete")) (command "_.layerp"))
    ; reset Layer if appropriate
;
  (if (= *wpldel* "Delete") (entdel *wplpath*))
  (setq *wpl* (entlast))
  (setvar 'osmode osm)
  (setvar 'blipmode blips)
  (command "_.undo" "_end")
  (setvar 'cmdecho cmde)
  (princ)
); end defun
(prompt "Type WPL to make a Wobbly PolyLine.")
(vl-load-com)

 Does anyone spot anything that seems off or just plain wrong? missing semicolon? My sanity?

It's ridiculous how much time and energy this has already taken, a simple squiggly line. But my boss wants it, therefore I have to provide Man Frustrated

Message 32 of 32
Kent1Cooper
in reply to: Anonymous

You can change the  (command)  function to  (command-s)  or switch to what I've been using in more recent routines -- VLA methods of starting and ending the Undo "wrapper."  But that's only an issue because of the failure to recognize that (vlax-curve-getEndParam) function -- if it knew what that meant, there would be no call to the *error* function, so it wouldn't matter that it has the problematic (command) function in it.  Unfortunately, if (vl-load-com) doesn't get it to recognize that function name, I don't have any other ideas.  But there have been other threads about such functions not being recognized despite (vl-load-com) being loaded.  I don't recall what solution(s) have been suggested, but with a little Searching you might find some options.

Kent Cooper, AIA

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

Post to forums  

Autodesk Design & Make Report

”Boost