CADsite forum

AutoCAD => Autolisp => Topic gestart door: EddyBeerke op di 26 06 2012, 09:07:31

Titel: Controleren wat laatste commando was
Bericht door: EddyBeerke op di 26 06 2012, 09:07:31
Ik wil een *error* vang functie maken.
Nu wil ik die voor meerdere functies in 1 bestand (.lsp) dit opvangen maar loop tegen het volgende aan:
Wanneer ik een (eigen) commando start wil ik met (getvar "cmdnames") het active commando uit lezen als er een fout optreed maar ik krijg "".

(defun *error* (errmsg)
  (princ "\nEr is een fout opgetreden! \n")
  (prompt errmsg)
  (princ (strcat "\nActive commando: " (getvar "CMDNAMES")));   <--- hier gaat het om
  (princ)
);end error


Als ik dus het laatst gebruikte commano kan vinden dan kan ik op elk commando verschillende errors afhandelen.

Alvast bedankt.
Titel: Re: Controleren wat laatste commando was
Bericht door: roy_043 op di 26 06 2012, 11:28:40
Dit is volgens mij op twee manieren te implementeren.

1.
Pas alle lisp-commando's aan en voeg aan het begin van de code steeds een dergelijke regel toe:
(setq *LastLispCommand* "C:MyFunction")
De (*error*) functie kan deze globale variabele gebruiken.

2.
Gebruik een reactor om een globale lijst van alle lisp-aanroepen bij te houden. Bedenk daarbij dat de (*error*) functie ook een lisp-functie is. In elke tekening die wordt geopend moet (StartLispReactor) worden uitgevoerd om de reactor op te starten.

(defun StartLispReactor ()
  (if (not *StartLispReactor*)
    (setq *StartLispReactor*
      (vlr-lisp-reactor
        nil
        '((:vlr-lispwillstart . CallBackLispWillStart))
      )
    )
  )
  (princ "\n*StartLispReactor* is active ")
  (princ)
)

(defun CallBackLispWillStart (rea lst)
  (setq *LispCallsList* (cons (car lst) *LispCallsList*))
  (princ)
)

De (*error*) functie kan (cadr *LispCallsList*) gebruiken.

Maar...
Ik zou geen van deze twee methodes gebruiken...

3.
Het alternatief is om aan het begin van elke lisp-functie een globale lijst van oude instelling op te slaan. En deze lijst te gebruiken om oude instellingen te herstellen. Je kunt dezelfde lijst gebruiken voor de (*error*) functie en bij het correct afsluiten van de lisp-functie.
Titel: Re: Controleren wat laatste commando was
Bericht door: EddyBeerke op do 28 06 2012, 07:59:38
Ik zal voor de laatst versie gaan proberen.
Ik laat nog wat horen.
Titel: Re: Controleren wat laatste commando was
Bericht door: Reimer op do 28 06 2012, 08:49:20
Ik was gisteren aan het lezen over error afhandeling. In het voorbeeld dat ik tegenkwam wordt per lisproutine een eigen *error* aangemaakt. De oude wordt tijdelijk opgeslagen. Ik heb dit nog niet zelf getest maar het klinkt voor mij interessant.

(defun errorvanmij1 (bericht)
  (prompt "\nEr is een fout opgetreden! ")
  (prompt "\nDe fout was: ")
  (princ bericht " ")
  (setvar "OSMODE" osold)
  ...
  (setq *error* olderr)
)

(defun c:mijnlisp (/ olderr osold  ...)
  (setq olderr  *error*
          *error* errorvanmij1
           osold  (getvar "osmode")
  (setvar "osmode" 0)
  ...
  (setvar "osmode" osold)
  (setq *error* olderr)
)


Eerst wordt een eigen error-code aangemaakt.
In de lisproutine wordt *error* opgeslagen als OLDERR. Vervolgens wordt de eigen error opgeslagen als *error*. Wanneer de routine vastloopt wordt de eigen error afgehandeld en aan het einde OLDERR teruggezet.
Zo kun je voor iedere lisproutine een eigen *error* maken.
Misschien kun je hier iets mee?

Reimer
Titel: Re: Controleren wat laatste commando was
Bericht door: roy_043 op do 28 06 2012, 09:21:31
Citaat van: Reimer op do 28 06 2012, 08:49:20en aan het einde OLDERR teruggezet.
Dit moet via de globale lijst van punt 3 uit mijn vorige bericht vanzelfsprekend ook opgelost worden.
Het doel is een universele (*error*) functie. Dit werkt op de lange duur het beste.
Titel: Re: Controleren wat laatste commando was
Bericht door: Reimer op do 28 06 2012, 09:58:48
Roy, je hebt gelijk. Een universele *error* functie lijkt mij ook het beste werken.

PS, dankzij jouw uitleg over variabelen blijven er ook geen gevulde variabelen hangen.
http://www.cadsite.be/smf/index.php?topic=3564.msg18264#msg18264 (http://www.cadsite.be/smf/index.php?topic=3564.msg18264#msg18264)

Reimer
Titel: Re: Controleren wat laatste commando was
Bericht door: roy_043 op do 28 06 2012, 11:50:20
Hieronder een gestripte versie van de oplossing die ik gebruik.

De kern van de oplossing word gevormd door twee functies:
Cadsite_VarStackPush:
Slaat variabelen op en stelt ze meteen in op nieuwe waarden.
Cadsite_VarStackPop:
Herstelt variabelen.

Deze functies worden aangeroepen door:
Cadsite_ErrorHandlerStart
Cadsite_ErrorHandlerEnd
Cadsite_Error

Ik gebruik dit principe nu een aantal jaren. Het werkt goed. Het is met name handig dat de "Push" en "Pop" functies ook apart van (Cadsite_ErrorHandlerStart) en (Cadsite_ErrorHandlerEnd) kunnen worden gebruikt. Zie het voorbeeld (c:MyCommand).

Op het WWW zijn overigens diverse varianten van dit principe te vinden.


;;; Cadsite_VarStackPush stelt variabelen in op basis van een lijst met
;;; "dotted pairs". De oude waarden worden opgeslagen als sublijst in de
;;; globale variabele *cadsite_varStack*.
;;; lst - Lijst met "dotted pairs".
;;;       Formaat van een "dotted pair":
;;;         ("naamVanEenVariabele" . inTeStellenWaarde)
;;;       Als de in te stellen waarde ontbreekt dan wordt de oude waarde
;;;       alleen opgeslagen. Om de error-functie in te stellen wordt
;;;       "*error*" i.p.v. de naam van een variabele gebruikt.
;;;       Voorbeeld van zo'n lijst:
;;;         '(("*error*" . Cadsite_Error) ("cmdecho" . 0) ("clayer"))
;;;       De sublijst die hierdoor wordt toegevoegd aan *cadsite_varStack*
;;;       kan er zo uitzien:
;;;         (("*error*" . #<<FUNCTION> #x33 @6c290bd6>) ("cmdecho" . 1) ("clayer" . "0"))
(defun Cadsite_VarStackPush (lst)
  (setq *cadsite_varStack*
    (cons
      (mapcar
        '(lambda (a / old)
          (if (= (car a) "*error*")
            (progn
              (setq old *error*)
              (if (cdr a)
                (setq *error*
                  (if (= (type (cdr a)) 'sym)
                    (eval (cdr a))
                    (cdr a)
                  )
                )
              )
              (cons "*error*" old)
            )
            (progn
              (setq old (getvar (car a)))
              (if (cdr a)
                (setvar (car a) (cdr a))
              )
              (cons (car a) old)
            )
          )
        )
        lst
      )
      *cadsite_varStack*
    )
  )
)

;;; Cadsite_VarStackPop herstelt de variabelen in de eerste sublijst (deze
;;; is het laatst toegevoegd) van de globale variabele *cadsite_varStack*.
;;; Deze sublijst wordt verwijderd uit *cadsite_varStack*.
(defun Cadsite_VarStackPop ()
  (mapcar
    '(lambda (a)
      (if (= (car a) "*error*")
        (setq *error* (cdr a))
        (setvar (car a) (cdr a))
      )
    )
    (car *cadsite_varStack*)
  )
  (setq *cadsite_varStack* (cdr *cadsite_varStack*))
)

(defun Cadsite_Error (message)
  ;; Alle lopende (transparante) commando's annuleren:
  (while (> (getvar 'cmdactive) 0)
    (command nil)
  )
  ;; Alle variabelen in *cadsite_varStack* terugzetten:
  (repeat (length *cadsite_varStack*)
    (Cadsite_VarStackPop)
  )
  ;; Undo mark zetten:
  (vla-endundomark (vla-get-activedocument (vlax-get-acad-object)))
  ;; Message selectief weergeven:
  (if
    (not
      (member
        (strcase message)
        '(
          ""
          "FUNCTION CANCELLED"
          "QUIT / EXIT ABORT"
          "CONSOLE BREAK"
        )
      )
    )
    (princ (strcat "\nError: " message))
  )
  (princ)
)

(defun Cadsite_ErrorHandlerStart (lst)
  (vla-startundomark (vla-get-activedocument (vlax-get-acad-object)))
  (Cadsite_VarStackPush (cons '("*error*" . Cadsite_Error) lst))
)

(defun Cadsite_ErrorHandlerEnd ()
  (Cadsite_VarStackPop)
  (vla-endundomark (vla-get-activedocument (vlax-get-acad-object)))
)

;;; Voorbeeld hoe de functies gebruikt kunnen worden:
(defun c:MyCommand ( / pt)
  (Cadsite_ErrorHandlerStart '(("cmdecho" . 0)))
  ; ...
  ; ...
  (setq pt (getpoint "\nPoint please: "))
  (Cadsite_VarStackPush '(("osmode" . 0)))
  ; *cadsite_varStack* ziet er nu bijvoorbeeld zo uit:
  ; (
  ;   (("osmode" . 135))
  ;   (("*error*" . #<<FUNCTION> #x33 @6c290bd6>) ("cmdecho" . 1))
  ; )
  (command "_.point" pt)
  (Cadsite_VarStackPop) ; Herstelt osmode.
  ; ...
  ; ...
  (Cadsite_ErrorHandlerEnd) ; Herstelt *error* en cmdecho.
  (princ)
)






Titel: Re: Controleren wat laatste commando was
Bericht door: Reimer op do 28 06 2012, 12:04:49
De opzet klinkt goed doordacht. Als ik tijd heb zal ik de code eens doornemen.
Bedankt voor het delen!  :vreegoe:

Reimer
Titel: Re: Controleren wat laatste commando was
Bericht door: EddyBeerke op do 28 06 2012, 13:00:52
Citaat van: Reimer op do 28 06 2012, 12:04:49
De opzet klinkt goed doordacht. Als ik tijd heb zal ik de code eens doornemen.
Bedankt voor het delen!  :vreegoe:

Reimer


Ik zal ook daar de tijd voor nemen.
Eens kijken of ik het snap. :vreegoe: