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

DCL-LISP Debugging(Xrefs to back, Raster images to back, Raster images to front)

13 REPLIES 13
SOLVED
Reply
Message 1 of 14
TVirks
1545 Views, 13 Replies

DCL-LISP Debugging(Xrefs to back, Raster images to back, Raster images to front)

I am new to LISP, I have some basic programming knowledge which helps me to understand for the most part what the LISP is saying. 

My end goal is to create a button which runs this LISP.

When the LISP runs a dialog box should open with three options:

  1. Send XRefs to back
  2. Send Raster Images to back
  3. Bring Raster Images to front

I considered using layers, but that would require anyone who uses the LISP to put everything on the same layer (I'd have better luck programming Revit from scratch)

With my limited knowledge of LISP, I've found various ones on the forums and stitched them together to the best of my knowledge. However, when I try to run the LISP, the command I set, X2B, doesn't even appear, which leads me to believe there is a break in the code somewhere causing some issues. Is there anyone who would be able to help debug this and sort out the issue?

I've attached the LISP and the DCL file. 

Secondary question, for the DCL file to be referenced, does it only need to be in the same folder? (Another potential issue)

Thank you in advance for your help.

Tags (4)
13 REPLIES 13
Message 2 of 14
dlanorh
in reply to: TVirks

Your DCL file has two mutually exclusive toggles ; "Images to the Back" and "Images to the Front"

 

Using toggles allows both to be selected so what happens if they are both checked?

Google "autocad dcl mode_tile" and from that you can also get to and look at "set_tile"

 

Your command is not showing because your lisp has structural errors and is therefore not loading.


An (if statement) can only be followed by one or two lines of code

(if (>= a 1)
  (princ "A is greater than or equal to 1")
  (princ "A is less than 1")
);end_if

If you want more you have to include the within a (progn ... )

 

(if (>= a 1) 
  (progn
    (princ "A is greater than or equal to 1")
.........
);end_progn
(progn
(princ "A is less than 1")
.........
);end_progn
);end_if

This is incorrect as it has three branches

 

(if (>= a 1) 
  (progn 
    (princ "A is greater than or equal to 1")
    .........
  );end_progn
(progn (princ "A is less than 1") ......... );end_progn
(princ "Hallo")
);end_if

 

This is where your code is structurally incorrect and why it won't load.

 

In answer to your second question, I store all my lisps and dcl's on a separate drive to autocad, and ensure that the dcl folder has its own entry in the options-files- support files search path folder.

command: _options <enter> files tab

 

This prevents loss of files on upgrades etc and is neater than having everything in a single folder

 

If you can't resolve your problems, re-post in this thread.

 

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

Message 3 of 14
TVirks
in reply to: dlanorh

Very helpful. I believe I've resolved the "if" issue by adjusting the parentheses. In regards to the dialog box, is there an option for one or the other? I assumed that they would act in sequential order, so if both image boxes were checked they would be sent to back and then brought to the front again. The ideal case, I guess would be to have an option for xrefs which could be checked or un-checked, and then an option for images to be either sent to the back or brought to the front. But as long as it doesn't create critical errors in the program I am happy for it to remain a little contradicting.

 

I've attached the edited file. The command is still not appearing. have I missed something?

Message 4 of 14
dlanorh
in reply to: TVirks

In your dcl you have a boxed radio column, but you've populated it with toggles (check boxes) instead of radio buttons. And yes we have all at some stage made similar errors.

1. If you are serious about lisp programming use a decent code editor. Notepad++ is free, has the option to set lisp as a programming language and will recognise most of the syntax, has auto-indent and parentheses checking, but there are others free and paid for. Find what suits you.

2. You can load a dcl file in the vlide and then using the interface tool to display the dcl as it would appear in autocad. vlide is great for debugging code so learn how to use it.

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

Message 5 of 14
dlanorh
in reply to: TVirks

(if (= tg1Flag "1")
  (setq c-tab (getvar "ctab");Get tab name << this setq is not closed (two open brackets one close bracket)
    (setq funclist ;<<<< You cannot have a setq within a setq
	(cons (strcat ;<<<< cons is used to add items to a list, strcat to join strings. 
		;Select raster images
		"imageselect"
		;Bring to front
		"draworder" "front"
		(funclist);<<<<if this is the list you're adding to you haven't finished the strcat
	      )
	  )
	)
        ;Return to starting tab
	(setvar "ctab" tab);<<<< You cannot have a setvar within a setq and you saved "ctab" in c-tab not tab
  );<<<< I think this closes the first setq
)

See above. This happens a couple of times. I'm assuming you want to do all of this if (= tg1Flag "1") is true. Then they need to be enclosed within a (progn ... );end_progn, or read up on the condition statement (cond)

 

(strcat "imageselect" "draworder" "front")

I've remove the inline comments for clarity and the above produces ""imageselectdraworderfront"

 

It's now 02:00 here and i have to push out some Zzzzz's. I'll be back in the morning Robot Happy

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

Message 6 of 14
TVirks
in reply to: dlanorh

;X-Refs to Back		
	(if (= tg3Flag "1")
		; Get tab name
		(progn
			(setq ctab (getvar "ctab"))
			(setq funclist (cons 	(strcat 
									"getxrf" " "
									"draworder" " "
									"back" " ");strcat
									funclist);cons 
							);setq
			(setvar "ctab" tab)
		);progn
	);if

--------------------------------------------------------------------------------------------

;X-Refs to Back		
	(if (= tg3Flag "1")
		; Get tab name
		(progn
			(setq ctab (getvar "ctab"))
				(strcat
						;Select X-ref
						"getxrf"
						;Sent to back
						"draworder" "back"
				);strcat
		;Return to starting tab
		(setvar "ctab" tab)
		);progn
	);if

I have been using Notepad++, makes things easier for sure.

The top code is taken directly from another LISP which features a dialog box, and I've adjusted it to suit the correct information. The bottom code is the changes I've made based on your comments. Am I getting anywhere?

However, it appears that the main error in the LISP is in the first half, where it references the DCL file, or possibly in the DCL file itself. I am still unable to create the command, and therefore actually see what the LISP is doing and where it is at fault!

I haven't used Visual LISP editor much, and I don't have admin rights on my computer so I can't write the tmp file in order to test a DCL file. 

I've researched about DCL's a bit and I think I've made some good corrections to it. Although failing to be able to test does make it difficult.

I've gotten the program into cad, the command works, the dialog box appears (with tick boxes), but the task does not work. It appears I have an error in the ctab variable, which I haven't explained yet. A key aspect of this program is that it will run will in paperspace, and then return to paperspace, specifically the tab you started in. My thinking here was to retrieve the tab name, set it to a variable, and then recall that name at the end of the function. Any thoughts on this process? The tab names will vary depending on the drawing revision so it needs to work universally in any drawing.

Message 7 of 14
dlanorh
in reply to: TVirks

Let us forget about the lisp doing anything at the moment.

 

Attached are your renamed dcl file and lisp.

 

DCL File : I've changed the radio button keys to reflect that they are radio buttons. Keys are rb1 and rb2, and I've placed them into a non visible radio-column. This allows the layout to look the same but groups the radio buttons together so that only one can be checked. I have changed the external container to a boxed-column.

The reason the file is renamed, is so that it reflects the name of the lisp function that calls it.

 

LISP File : I've changed your variables names. There are now only two tg1flag and rbflag. These are boolean flags and should only have a value of either T or nil to reflect the two states. The toggle is either checked (T) or unchecked (nil).

Only one of the radio buttons can be checked, therefore rbflag reflects which button is currently checked.

(images to the back checked) rbflag is T

(images to the front checked) rbflag is nil

 

These allows a simple code branches depending on the flag value.

I have commented out the (do stuff) code and replaced them with alert statements. I have removed the userclick stuff as you can return a state using the (done_dialog). In this case 0 for cancelled and 1 for OK. The return is collected by e_val in the (setq e_val (start_dialog)) statement

 

Note the simple implementation in the action_tile's to toggle the flags. Only the toggle code is different as this contains text within text strings and would require escaping double quotes. This can be a pain and is a source of a lot of dcl code errors. The (vl-prin1-to-string  (quote (code) ) )  allows the code to be written normally and converted to the string dcl needs. Be aware that the action_tile expects a single statement, so multiple lines of code must be enclosed in a (progn) i.e. (vl-prin1-to-string  (quote (progn (code)... ) ) )

 

example below

 

(action_tile "f_stns" 
   (vl-prin1-to-string
      (quote
        (progn
          (if (= (get_tile "f_stns") "1")
            (setq f_stns T)
            (setq f_stns nil)
          )
          (if f_stns
            (mode_tile "ctable" 0)
            (mode_tile "ctable" 1)
          )
        )  
      );end_quote
    );end_vl-prin1-to-string
  );end_action_tile

Note that there are no code comments between the (quote ...);end_quote as these could be confused as code once a text string has been written as dcl comments and lisp comments use two differing formats.

 

The code works, so if the dialog doesn't load, the most likely cause is that autocad can't find it.

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

Message 8 of 14
scot-65
in reply to: TVirks

If one wishes to have Images to Back, Images to Front -OR- no image handling,

there are two methods you can try.

 

Method 1:

Cluster three radio_buttons together. "Back", "Front", "None".

Apply a key to the radio_column "tg0" and "talk" to the radio_column.

;*** Set Tile ***

(set_tile "tg0" "tg1")

Communication goes both ways.

;*** Get Tile ***

(setq a (get_tile "tg0"))

Possible returns are (using your example): "tg2" and "tg3".

 

Method 2 (advanced users):

Replace the radio buttons with toggles. Remove the radio_column.

In the action tile section of your LSP code:

(action_tile "tg2" "(if (= $value \"1\") (set_tile \"tg3\" \"0\"))")

(action_tile "tg3" "(if (= $value \"1\") (set_tile \"tg2\" \"0\"))")

Note the escaped quotes inside the if statement. These are

necessary for action_tile (only 2 sets of quotes are allowed

inside action_tile).

 

Remove "value=" from the DCL.

Use set_tile in your LSP file to do this.

 

???

 


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


Message 9 of 14
TVirks
in reply to: dlanorh

Thank you for your help, so far, you've been great.

I've added in two other functions which I've found on other forums that I'm using for the actions of this. One which selects all xrefs, and one which selects the images and sends them to back. I've added those above, and in the function for the action of each tile (replacing the alert that you filled in) added the change to tilemode and command to call up those functions. I've also copied the image function and changed to bring to front as well. However, at some point in my adjusting, I've reached an error. When I run the function I receive the following message in the text window:


Command: XDO
; error: bad argument type: (or stringp symbolp): nil 

 

Maybe you can see what I'm missing?

The other functions do work on their own, it's just the execution in XDO that I'm losing

Message 10 of 14
TVirks
in reply to: TVirks

Actually, that wasn't so bad. I had forgotten the quotes after my setvar variable. The function runs now, however it doesn't recognise the commands within the progn cond function. It says I2B, I2F, and getxrf are all not known commands, even though they work fine independently.

 

Error message is:

getxrf Unknown command "GETXRF". Press F1 for help.

 

or the like.

Is the command function not able to run within progn cond? or am I skipping a step?

 

(cond ( (= e_val 1);this is accept pressed
	;Images to Back
       
        (cond ( rbflag                      ;Images to back
				(setvar "tilemode" 1)
				(command "I2B")
				(setvar "tilemode" 0)
			  )
              ( (not rbflag)                ;Images to front
				(setvar "tilemode" 1)
				(command "I2f")
				(setvar "tilemode" 0)
			  )
        );end_cond
        (cond (tg1flag                      ;dwgs to back
				(setvar "tilemode" 1)
				(command "getxrf" ".draworder" "" "back")
				(setvar "tilemode" 0)
              )
	      (                             ;dwgs to back
				(alert "DWG to back unchecked")
          )
        );end_cond
      )        
);end_cond

 

Message 11 of 14
martti.halminen
in reply to: TVirks

>It says I2B, I2F, and getxrf are all not known commands, even though they work fine independently.

 

Command (or vl-cmdf or command-s) can be called pretty much anywhere in a Lisp program, it has no special behaviour regarding cond.

 

Either there is something wrong with your I2B etc. definitions, or you are not loading them correctly when calling them in the program.

 

For using with the command interpreter, you need to have definitions like

(defun C:I2B ( ) ...) etc. (either empty parameter list or just local variable definitions: () or ( / some names))

 

If you define them as ordinary Lisp functions, then you call them like that: (I2B) instead of (command ...)

 

Regarding style: a professional Common Lisp programmer would indent your function this way:

 

(cond ((= e_val 1);this is accept pressed
       (cond (rbflag                      ;Images to back
              (setvar "tilemode" 1)
              (command "I2B")
              (setvar "tilemode" 0))
             ((not rbflag)                ;Images to front
              (setvar "tilemode" 1)
              (command "I2f")
              (setvar "tilemode" 0)));end_cond
       (cond (tg1flag                      ;dwgs to back
              (setvar "tilemode" 1)
              (command "getxrf" ".draworder" "" "back")
              (setvar "tilemode" 0))
             ((alert "DWG to back unchecked")))))

- That is GNU Emacs default indentation for Lisp

 

-- 

 

 

Message 12 of 14
dlanorh
in reply to: TVirks

I've distilled everything into a single lisp. The images to front/back were in essence a single line of code, so I have removed the (c:...) lisp routines and just incorporated the code into the relevant sub cond statement.

 

I have updated get_xrefs lisp to use visual lisp. (rh:get_xrefs) This is now a sub_routine that can be called from the main lisp and returns a value. In this case it returns a selection set or nil (no xrefs found).

 

Using visual lisp makes it easier than methods using autolisp. This however neccessitates loading visual lisp which is the (vl-load-com) statement at the top of the file. A lot of lisps use visual lisp, so if you are going to program or run lisps, it would be a good idea to incorporate (vl-load-com) into something that loads with autocad. That way it is always there.

 

Attached are the revised xdo.lsp and xdo.dcl

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

Message 13 of 14
TVirks
in reply to: dlanorh

Thanks a ton. I hadn't thought about combining them straight into the lisp. I also haven't worked much with visual lisp. I really appreciate the assistance.

Cheers.

Message 14 of 14
dlanorh
in reply to: TVirks

No problem. If you need more help as you progress someone will always lend a hand.

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

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

Post to forums  

Forma Design Contest


AutoCAD Beta