From: Jeremy Whetzel
Subject: Need suggestions for menu system
Date: 
Message-ID: <87u1rhaxvi.fsf@toadmail.com>
Hi,

For one of my first projects to learn about CL, I'm creating a front end
for a couple of command line programs.  In trying to make a menu to
choose various options and actions, I'm having a bit of trouble as to
what part of CL to utilize to store the menu data.  I have about 3
different menus that will be used at various times.  Each menu will have
between 5 and 15 items.  Each menu item needs to have between 1 and 4
pieces of data associated with it:

1: The static text to display
2: The action to perform for that menu item
3: A variable to display the current status of that menu item. (optional
per item)
4: A "trigger" for that menu item.  (ie, choose "a" to start one item)


As an example of a menu item:

F) Choose a File: myfile.txt

In this, "F) Choose a File:" is the static text to display, "myfile.txt"
is the status variable, the trigger would be "f", and the action might
be something like (choose-new-file).

I've tried representing it with a traditional list, with arrays, with
vectors, with structures, with symbol properties, and various
combinations of these.  I've also considered using classes.  (although
for starting out, that one seems a bit advanced to me)

What I'd like to know is, what is the opinion of those of you that are
more experienced with CL?  How would you represent these menus in CL?

Any suggestions, pointers, constructive criticism on my way of thinking,
and the like are all welcome.  

Jeremy

From: Vebjorn Ljosa
Subject: Re: Need suggestions for menu system
Date: 
Message-ID: <cy3henh2eup.fsf@ljosa.com>
* Jeremy Whetzel <·····@toadmail.com>
| 
| For one of my first projects to learn about CL, I'm creating a front end
| for a couple of command line programs.  In trying to make a menu to
| choose various options and actions, I'm having a bit of trouble as to
| what part of CL to utilize to store the menu data.  I have about 3
| different menus that will be used at various times.  Each menu will have
| between 5 and 15 items.  Each menu item needs to have between 1 and 4
| pieces of data associated with it:
[...] 
| I've tried representing it with a traditional list, with arrays, with
| vectors, with structures, with symbol properties, and various
| combinations of these.  I've also considered using classes.  (although
| for starting out, that one seems a bit advanced to me)
| 
| What I'd like to know is, what is the opinion of those of you that are
| more experienced with CL?  How would you represent these menus in CL?

Here is one way of doing it.  I use a structure to represent each menu
item.  A menu is simply a list of those items.

(defstruct item
  (text)
  (action)
  (value)
  (trigger))

(defun menu (items)
  (catch 'return-from-menu
    (loop
      (dolist (item items)
	(format t "~&~A. ···@[: ~A~]" (item-trigger item) (item-text item)
		(item-value item)))
      (format t "~&> ")
      (let ((trigger (read-line)))
	(let ((item (find trigger items :key #'item-trigger
			  :test #'string-equal)))
	  (if item
	      (funcall (item-action item) item)
	    (format t "~&No menu item with this trigger: ~A" trigger)))))))

Then you can define and call a menu like this:

(defparameter *main-menu*
    (list (make-item 
	   :text "Choose a file"
	   :action (lambda (item)
		     (format "~&Filename: ")
		     (setf (item-value item) (read-line)))
	   :value "foo.lisp"
	   :trigger "f")
	  (make-item 
	   :text "More options"
	   :action (lambda (item)
		     (menu (list (make-item 
				  :text "Go back"
				  :action (lambda (item)
					    (throw 'return-from-menu))
				  :trigger "q"))))
	   :trigger "o")
	  (make-item 
	   :text "Quit"
	   :action (lambda (item)
		     (throw 'return-from-menu))
	   :value nil
	   :trigger "q")))

(menu *main-menu*)

-- 
Vebjorn Ljosa
From: Jeremy Whetzel
Subject: Re: Need suggestions for menu system
Date: 
Message-ID: <87lmcsjhby.fsf@toadmail.com>
Vebjorn Ljosa <·····@ljosa.com> writes:

> Here is one way of doing it.  I use a structure to represent each menu
> item.  A menu is simply a list of those items.

[snip]

Thanks for your suggestion.  I'll take a look at it and see how it
works.

Jeremy