Draw using LISP
In the first blog post we discussed and learned about LISP terminology, syntax, data types. We also looked at the basic use of some introductory functions and how to make use of these concepts. If you are new to this blog, I recommend at least reviewing that blog post, if not reading it in its entirety. But even if you chose not to review the previous post, I feel you will be able to follow along with this episode and pick up some of what was discussed previously.
This blog post (and a few future posts) we will:
- Use the BLADE editor "hands on" within BricsCAD
- Progress through a series of functions to enhance our knowledge of LISP
- Use the Help command to understand the syntax and their arguments of LISP functions
- Continue to work with functions from the previous post
- Build a new program and exploring numerous new functions along the way
- Discover numerous ways to get the same result
We ended Black LISP -- #01 with 6 lines of code that allowed the user to select a point and have a circle centered at that point with a specified radius and another circle also centered on the selected point with radius increased by a specified distance:
(setq CPT (getpoint "Select a center point: "))
(setq RAD (getreal "Enter a radius: "))
(setq OFF (getreal "Enter an offset value: "))
(setq NEWRAD (+ RAD OFF))
(command "circle" CPT RAD)
(command "circle" CPT NEWRAD)
HELP>Developer Tools>Developer Reference>LISP>Expand LISP (LISt Processing)>Expand BricsCAD LISP Functions
Not much time would be saved if we had to type in those lines of code each time we wanted to draw a double-offset circle. Storing our LISP programs as individual files is the beginning of the answer to that problem.
- Launch BricsCAD and type BLADE at the prompt. The following window will open:
- Copy the 6 lines of code above and paste them into the document window, like so:
Note: You will need to delete each of the 10 quotation marks, and retype them in. The font in the blog article is not compatible with the BLADE editor in respect to quotation marks.
We are not going to get into all the benefits of the BLADE editor in this episode but do note that there is some color-coding that occurs. This can be helpful, especially while getting started, as "typos" may stand out a bit.:
- Function names
- Text strings (in quotation marks)
We almost have a working program. We need to group these lines of code together as "one unit". The (defun) function does just that.
(defun list symbol expression expression expression...)
This function creates a user defined function that can be used just as the "built-in" functions or as a command. It requires at least three arguments.
- A list. This list can be empty. We will use an empty list until we are ready to discuss this more deeply, later.
- The function name we want to define. If the function name starts with "c:", the function name can be typed in directly at the prompt as any other defined command.
- Remaining arguments -- the expressions that you would like the defined function to perform.
Add the following code in the editor:
Note: If the colors in the graphic do not match your screen you may have forgotten to delete and retype the quotation marks.
We do not want to make one of the most common errors in programming and in CAD in general -- SAVE the file! Select the Save icon we all know and love (even though many of you may have never used a floppy disk!). The red bar between the line numbers on the left and the new code on the right means those lines have been modified since the last save. I created a folder on a USB drive called LISP, so I will navigate to that folder and use* OffsetCircles* for the file name. The editor will automatically attach the .lsp extension.
It is a good practice to use "indenting" to make code more readable/presentable. Do this appropriately and automatically with the BLADE editor. Select the "Reformat (beautify)" button:
We now have a working program and we need to test it. Select the "Load lisp file in BricsCAD" button, then select the "Switch to BricsCAD" button. The drawing file in BricsCAD should now be active.
At the prompt start to type "OffsetCircles". Notice that all commands starting with those first couple of characters appear in a shortcut list, and that "OffsetCircles" is already included in the list. You can use the arrow keys to highlight "OffsetCircles", and following the prompting of the program.
Another way to load a lisp program file and make it available for use is to use the (load) function directly at the Command: prompt, as such: Command: (load "offsetrcircles") The ".lsp" is not required, though you may add it if it makes you feel more comfortable. A path is not required if BricsCAD has the file's location within its search path. If the file is not in BricsCAD's search path, the syntax for including the path and the file name is:
Command: (load "c:\some-where-else\box1")
Our program will only continue to work while this drawing is open. LISP programs are only active in the drawings in which they are written or loaded. Once a new drawing is started or the BricsCAD program is closed and then reopened -- we lose our loaded lisp routines. In future posts we will discuss many ways to make LISP programs available all the time, automatically.
The BLADE Editor
Now that we have a feel for LISP and using the BLADE editor let's start a new program. We will create 7 or 8 versions of the program, with each version introducing a new function and concept.
- If not already open, open the BLADE editor: type BLADE at the : Enter command prompt.
- Select the "New" icon in the upper left corner of the editor.
The editor will ask for the name of the file to be created.
- Type "Box1" for the new name, and type the following lines of code:
Based on what we have learned, these lines of code should make sense.
- When you have entered all the code, select the Save tool.
- Select the "Load lisp..." tool, the "Switch to BricsCAD" tool, and type "BOX1" at the prompt. (It should appear in the shortcut list)
If your code does not run properly ("crashes"), compare the graphic above to your type code -- it must match exactly!
A new concept has been introduced in this code -- forcing text to appear on the next line. You may have noticed that with our OffsetCircles program, the prompts asking for user input were showing up successively, one after the other on the same line at the command prompt. With the prompt strings for the points in our new program, each prompt starts with a "control code" of "\n....". This forces BricsCAD to show the text on a new line or the next command prompt line.
Two things to keep in mind: it must be the backslash character and it must be a lower case "n".
This is an example of what is called "polite programming". The user comes to expect that the next thing to do is shown on the next line. This is the way nearly all BricsCAD commands "work", and as a programmer we should try to match the BricsCAD way of doing things.
More Polite Programming
The following are additional polite programming techniques and functions. Most of these will be used in almost any program you create.
(setvar str val)
Often a program will modify the settings within BricsCAD to allow the program to run more smoothly with less interaction from the user. It is common practice and common courtesy to store the values of the settings that will be modified, so that they can be restored upon completion of the program.
The prompt function is used to display the string argument on the Command line. Many of the user (getxxx) functions offer the option to include a prompt, but sometime the programmer wants to give the user a bit more information. This is when the (prompt) function can be used.
This function is a troubleshooting tool and can also be used as a "clean up" tool. It can be used with an optional string argument. The function name (princ) is used to "prin"t to the "c"onsole (the Command line). When used without the string argument, nothing happens. More on that in the next section.
Updating Our Program with These New Concepts
You may have noticed that when the new BOX1 command was executed everything that was performed within the line of code that included the (command) function was "echoed" to the Command line:
This can be beneficial when writing new programs. If the program contains an error you can see exactly what line portion of the command, things may have gone awry. Once a program is running correctly, it is a common practice to turn this command echoing off.
You also may have noticed that after the last thing that our program did -- typing in a "c" to close the polygon we drew -- that "nil" was echoed to the screen. We must remember that every function we use "returns" a value. In the case of the expression (+ 1 1), the addition function returns the result of adding 1 and 1 together, and 2 is returned. The (command) function always returns "nil"... think of it as code for "done"... It is good programming technique to not allow that "nil" to be echoed to the Command line.
Let us incorporate all these new concepts into our BOX routine. In the interest of review and learning, each time we make a change to our program we will save it as a sequentially numbered file, and sequentially change the name of the command name. Make the following code additions to the program:
When you have finished making the changes, use the Save As tool and use Box2.lsp as the new file name.
A line-by-line discussion of what we changed and added:
Changed the name of the command being defined to BOX2
Added the "getvar" function, nested within the (setq) function. This gets and stores the current value of the CMDECHO system variable.
Added the (setvar) function, setting the value of the CMDECHO system variable to 0 (off).
Added the (prompt) function, letting the user know what the program is going to be doing. (This is not always necessary and is probably a little "over the top" in this instance, but I wanted to show you how it works!)
Added the (setvar) function to change the CMDECHO system variable back to what it was before we changed it to 0.
Added the (princ) function with no argument. The (princ) function returns the value of whatever argument is passed to it. Our devious use is to pass "nothing" to it, so "nothing" is returned! Since it is the last line of our program, we have what is commonly referred to as a "clean exit".
This is simply the closing parenthesis for the opening defun function on line 1.
When you are confident with the line by line discussion:
- Select the "Format" tool
- Select the "Load lisp..." tool.
- Select the "Switch to BricsCAD" tool.
These three steps are always to be performed after each "edit" and will not be spelled out from now on.
Type BOX2 at the Command line and notice that the program runs a little more "cleanly":
So, there you have it -- a nice introduction to the BLADE editor and some polite programming techniques. Next post will cover more polite programming techniques and introduction to error trapping