[comp.emacs] toggling key definitions

southern@neit.cgd.ucar.edu (11/29/90)

As a new Emacs user coming from years in a CMS/Xedit environment, it
didn't take long for the level of the features that I am trying to
build into my .emacs file to outstripped my ability to correctly write
and impliment them.  So, I'm hoping to get some guidance on a couple of
definitions.

First, there are a number of complimentary commands that I would like
 to define in such a manner that they are toggled by a single key.
 These include:
 1.  moving between the beginning and end-of-line, 
 2.  moving between the beginning and end-of-buffer, 
 3.  issuing start and end-kbd-macro commands.

 For example, I currently define my 7 and 8 keypad keys to begin and end a
 keyboard macro definition as such:

 (define-key function-keymap "7" 'start-kbd-macro)         ;NCD [7]
 (define-key function-keymap "8" 'end-kbd-macro)           ;NCD [8]

 I would like to use only one key to toggle between the start-kbd-macro
 and end-kbd-macro commands such that:
  if I currently am not defining a keyboard macro, 7 maps to start-kbd-macro 
  if I currently am     defining a keyboard macro, 7 maps to end-kbd-macro.

 Similarly, I would like to define a single key which bounces me
 between the beginning and end-of-line and another to bounce between
 beginning and end-of-buffer.

 Can anyone show me a simple generic method to do this for the various
 cases that I'm currently working on as well as others which might crop
 up in the future.

The second definition I would like to make may be similar to the
 first.  When I scroll-down through a buffer and reach the last full
 screen, the cursor is left a number of lines up from the bottom of the
 buffer and I get a beep and a "End of buffer" message.  I would like
 to define the scroll-down such that when I reach the last full screen
 and issue another scroll-down, the cursor is placed at the
 end-of-buffer rather than being left a half screen up.


                                     Thanks,
                                     Lawrence Buja
                                     southern@ncar.ucar.edu

hollen@megatek (Dion Hollenbeck) (11/29/90)

In article <9322@ncar.ucar.edu> southern@neit.cgd.ucar.edu writes:
>
>  I would like to use only one key to toggle between the start-kbd-macro
>  and end-kbd-macro commands such that:
>   if I currently am not defining a keyboard macro, 7 maps to start-kbd-macro 
>   if I currently am     defining a keyboard macro, 7 maps to end-kbd-macro.
> 

Someone suggested a way to do this which required that inside the
function which is REALLY bound to the key, test the state of something
and then call the appropriate function.  Like this:

(defun toggle-kbd-macro ()
  "Start or end a keyboard macro."
  (if defining-kbd-macro
      (end-kbd-macro)
    (start-kbd-macro)))

This is fine when one has some sort of variable to test, but may
be difficult to implement in some cases.  I propose a more generic
method which will work in all cases regardless of whether variables
are present to be tested.  It also does not require such variables
to be created if not used for any other purposes.  The mere act
of calling a function indicates the state and from there, that
function knows the next state which should be set up.

(define-key function-keymap "7" 'my-start-kbd-macro)   ; "7"

(defun my-start-kbd-macro ()
	"Start keyboard macro and change key state."
	(define-key function-keymap "7" 'my-end-kbd-macro)   ; "7"
	(start-kbd-macro))

(defun my-end-kbd-macro ()
	"Start keyboard macro and change key state."
	(define-key function-keymap "7" 'my-start-kbd-macro)   ; "7"
	(end-kbd-macro))

This is used in edt.el to handle the ADVANCE/BACKUP keys.  You can 
look at the code there for more explicit examples if you need.
--
	Dion Hollenbeck             (619) 455-5590 x2814
	Megatek Corporation, 9645 Scranton Road, San Diego, CA  92121
        uunet!megatek!hollen       or  hollen@megatek.uucp

roland@ai.mit.edu (Roland McGrath) (11/30/90)

In article <9322@ncar.ucar.edu> southern@neit.cgd.ucar.edu writes:

   First, there are a number of complimentary commands that I would like
    to define in such a manner that they are toggled by a single key.
    These include:
    1.  moving between the beginning and end-of-line, 
    2.  moving between the beginning and end-of-buffer, 

These are pretty straightforward in Emacs Lisp.

(defun line-boundary ()
  "Go to the beginning of the line.  If already there, go to the end."
  (interactive)
  (if (bolp)
      (end-of-line)
    (beginning-of-line)))

(defun buffer-limit ()
  "Go to the beginning of the line.  If already there, go to the end."
  (interactive)
  (if (bobp)
      (end-of-buffer)
    (beginning-of-buffer)))


    3.  issuing start and end-kbd-macro commands.

    For example, I currently define my 7 and 8 keypad keys to begin and end a
    keyboard macro definition as such:

    (define-key function-keymap "7" 'start-kbd-macro)         ;NCD [7]
    (define-key function-keymap "8" 'end-kbd-macro)           ;NCD [8]

    I would like to use only one key to toggle between the start-kbd-macro
    and end-kbd-macro commands such that:
     if I currently am not defining a keyboard macro, 7 maps to start-kbd-macro 
     if I currently am     defining a keyboard macro, 7 maps to end-kbd-macro.

This can be done the same way as the others:


(defun toggle-kbd-macro ()
  "Start or end a keyboard macro.
Like \\[start-kbd-macro] when not defining a macro.
Like \\[end-kbd-macro] when defining a macro."
  (if defining-kbd-macro
      (end-kbd-macro)
    (start-kbd-macro)))

    Can anyone show me a simple generic method to do this for the various
    cases that I'm currently working on as well as others which might crop
    up in the future.

For all the things you have mentioned, which of the two alternatives can be a
thing decided in the body of the command.  This means, for example, that if
C-c l is line-boundary, C-a C-c l C-a C-l will get you to the end of the line,
which is where you want to be.  Using the method of having two commands, which
each rebind a key to the other, means that it always flip-flops, regardless of
what other commands you execute in the meantime.

   The second definition I would like to make may be similar to the
    first.  When I scroll-down through a buffer and reach the last full
    screen, the cursor is left a number of lines up from the bottom of the
    buffer and I get a beep and a "End of buffer" message.  I would like
    to define the scroll-down such that when I reach the last full screen
    and issue another scroll-down, the cursor is placed at the
    end-of-buffer rather than being left a half screen up.

(defun scroll-down-hard (arg)
  "Scroll down ARG number of lines, like \\[scroll-down].
If the end of the buffer is already on the screen, move point to it."
  (interactive "p")
  (if (or (numberp arg)
	  (not (pos-visible-in-window-p (point-max))))
      (scroll-down arg)
    (goto-char (point-max))))
--
	Roland McGrath
	Free Software Foundation, Inc.
roland@ai.mit.edu, uunet!ai.mit.edu!roland