yoin

EddyBeerke

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.
Civil3d 2026, Blender 4.x gebruiker
Gebruiker sinds AutoCAD R12

http://eddylucas.c1.biz/
https://www.google.com/maps/contrib/109381066561676463628/photos/

roy_043

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.

EddyBeerke

Ik zal voor de laatst versie gaan proberen.
Ik laat nog wat horen.
Civil3d 2026, Blender 4.x gebruiker
Gebruiker sinds AutoCAD R12

http://eddylucas.c1.biz/
https://www.google.com/maps/contrib/109381066561676463628/photos/

Reimer

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

roy_043

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.

Reimer

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

Reimer

roy_043

#6
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)
)







Reimer

De opzet klinkt goed doordacht. Als ik tijd heb zal ik de code eens doornemen.
Bedankt voor het delen!  :vreegoe:

Reimer

EddyBeerke

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:
Civil3d 2026, Blender 4.x gebruiker
Gebruiker sinds AutoCAD R12

http://eddylucas.c1.biz/
https://www.google.com/maps/contrib/109381066561676463628/photos/

FastFiber