LISP: getkword differentiate between cancel and enter

Example code:

 

(defun c:TKW ( / )
(initget "Yes No")
(setq result (getkword "\nAre you sure? [Yes/No]: "))
(if (not result) (princ "\nYou pressed enter or cancelled "))
(princ)
)

I could of course do this: (initget 1 "Yes No"). But I also want to allow the user to press enter to accept a default option.

Note: I use BC7.

TIA.

 

Comments

  • Hi Roy,

    Not sure if this will help you but here is one way to handle Enter as a default action.

     

    (defun C:SAMP1 ( / kw )
    (initget "YES,Y NO,N")
    (setq kw (getkword "Yes/No/<Yes>: "))
    (cond
    ((not kw)
    (princ "I take your silence on the issue to mean YES!")
    )
    ((= (strcase kw) "YES")
    (princ "Ahhh... YES is a good choice...")
    )
    ((= (strcase kw) "NO")
    (princ "Hurumph! You take the NO option!")
    )
    (1
    (princ "Unknown command...")
    (princ "\nWe should never get here...")
    NIL
    )
    )

    (princ)
    )

    (princ "Run the sample with command: SAMP1")
    (princ)

    But the user hitting Esc will just jump to the error handler. I am unaware of a way to capture Esc with v7 other than with a custom error handler, but I don't think you can prevent the Esc from terminating the Lisp.

    I am no expert but I have not read a way to handle Esc and continue with plain Autolisp.

     

  • If that was any help you could use it like so:


    (defun nss:yes_no ( default_yes / msg def_ans kw )
    ;; Initialise the default
    (cond
    (default_yes
    (setq msg "Yes/No/<Yes>: ")
    (setq def_ans 1)
    )
    (1
    (setq msg "Yes/No/<No>: ")
    (setq def_ans NIL)
    )
    )

    ;; Get the choice
    (initget "YES,Y NO,N")
    (setq kw (getkword msg))
    (cond
    ((not kw)
    def_ans
    )
    ((= (strcase kw) "YES")
    1
    )
    ((= (strcase kw) "NO")
    NIL
    )
    (1
    (princ "ERR: nss:yes_no: Unknown command...")
    (exit)
    )
    )
    )

    (defun C:SAMP2 ( / )
    (princ "\nrunning nss:yes_no with default_yes = T...")
    (if (nss:yes_no T)
    (princ "It's a YES... Here we go...")
    (princ "Let's all go home... It's a big NO!")
    )
    (print)
    (princ "\nrunning nss:yes_no with default_yes = NIL...")
    (if (nss:yes_no NIL)
    (princ "It's a YES... Here we go...")
    (princ "Let's all go home... It's a big NO!")
    )
    (princ)
    )

    (princ "Run the sample with command: SAMP2")
    (princ)
  • Greg thank you for responding. But my problem is that getkword returns nil either if the user hits Enter or Escape (cancel).

    I need to differentiate between the two:

    1. Enter: The user accepts the default option.
    2. Escape: The user wants to quit the routine.
  • > But the user hitting Esc will just jump to the error handler

    Greg: this doesn't happen in BC7. Using my example code:

    : C:TKW
    : tkw

    Are you sure? [Yes/No]:
    Cancel
    You pressed enter or cancelled

  • Ah, sorry then. I posted without being able to check it until Monday... I had not noticed the difference with v7. I usually only run it together with a particular add-on.

    Something new for me so it was not a waste ;)

  • Hi Roy,

    Did you find a way to do this? It looks like you can use getstring, handle null input and still have the Esc key trigger the error handler...

  • That's a good idea Greg.

    ;;; AltGetKword uses getstring instead of getkword.
    ;;; Using getkword there is no way to differentiate between the user hitting Enter or Escape (Cancel).
    ;;; With AltGetKword, Enter equals choosing the default option and hitting Escape triggers an error
    ;;; that can be handled by an error-function.
    ;;;
    ;;; kWordLst can look like this:
    ;;; '("Y" "YES" "YE" "YES" "N" "NO")
    ;;; This will return "YES" or "NO"
    ;;; Or this:
    ;;; '("YES" "Y" "YE" "Y" "NO" "N")
    ;;; This will return "Y" or "N"
    ;;; Or this:
    ;;; '("Y" T "YE" T "YES" T "N" nil "NO" nil)
    ;;; This will return T or nil
    ;;; The first and second element in kWordLst belong together. If the user enters the first element
    ;;; (in the first example the string "Y") the second element (in the first example the string "YES")
    ;;; will be returned. The same goes for the third and fourth element etc. If the user enters the
    ;;; second or fourth element that element will simply be returned.
    ;;; Note that the strings inside kWordLst must be all caps. If default is a string it also should be all caps.
    ;;;
    ;;; Made by Roy Klein Gebbinck. Based on an idea by Greg Skelhorn.
    ;;; http://forum.bricsys.com/discussion/10864

    (defun AltGetKword (message kWordLst default / breakLoop result kWordLstSegment)
    (while (not breakLoop)
    (setq result (strcase (getstring message)))
    (cond
    ((= result "")
    (setq
    result default
    breakLoop T
    )
    )
    ((setq kWordLstSegment (member result kWordLst))
    (if (= (rem (length kWordLstSegment) 2) 0) (setq kWordLstSegment (cdr kWordLstSegment)))
    (setq
    result (car kWordLstSegment)
    breakLoop T
    )
    )
    (T
    (princ "\nUnable to recognize entry. Please try again. ")
    )
    )
    )
    result
    )

    (defun MyError (message / )
    (if (/= message "Function cancelled") (princ (strcat "\nError: " message)))
    (if oldError (setq *error* oldError))
    (princ "\nError handler has kicked in! ")
    (princ)
    )

    (defun c:test ( / )
    (setq
    oldError *error*
    *error* MyError
    )
    (setq answer (AltGetKword "\nAre you sure? [Yes/No] <Yes>: " '("Y" "YES" "YE" "YES" "N" "NO") "YES"))
    ; Just an alternative:
    ; (setq answer (AltGetKword "\nAre you sure? [Yes/No] <Yes>: " '("Y" T "YE" T "YES" T "N" nil "NO" nil) T))
    (princ answer)
    (princ)
    )

    Of course there is no dialog. And with getkword the user can enter any (significant) portion of a keyword.

This discussion has been closed.