all messages for Emacs-related lists mirrored at yhetil.org
 help / color / mirror / code / Atom feed
From: Bill Atkins <atkinw@rpi.edu>
Subject: Keybindings and minor modes
Date: Thu, 29 Dec 2005 10:52:00 -0500	[thread overview]
Message-ID: <66b7e34b0512290752r5588df25t9ef2b5e615e17f5e@mail.gmail.com> (raw)

I apologize if this is the wrong place to post this, but it seemed
like the most appropriate list.

I'd like to bind a command to tab in a minor mode I'm writing, but I'd
also like to preserve any command that might have been attached to that
key before making my binding (such as indentation).  In other words,
I'd like to add functionality to an existing keybinding without
completely overwriting the binding.

The solution I came up with was to simply store the currently bound
command in a buffer-local variable whenever the minor mode is invoked.
Then the keys are bound to functions that provide my additional
functionality and then funcall the old bindings.  This works, but I
wonder if there isn't a cleaner way to pass a keychord event on to the
next handler.  The code I have now is pretty ugly, since a key bound to
self-insert-command has to be handled separately so that
self-insert-command will get an argument of 0.

I've attached my code below in case it's useful.

Thanks,
Bill Atkins

--

;; ehinter.el - echo lambda-lists when editing emacs lisp code

(defvar ehinter--old-space)
(defvar ehinter--old-tab)
(defvar ehinter--old-ret)

(make-variable-buffer-local 'ehinter--old-space)
(make-variable-buffer-local 'ehinter--old-tab)
(make-variable-buffer-local 'ehinter--old-ret)

(defvar ehinter-mode-map
  (let ((keymap (make-sparse-keymap)))
    (define-key keymap " "     'ehinter--space-cmd)
    (define-key keymap "\t"    'ehinter--tab-cmd)
    (define-key keymap "\C-m"  'ehinter--ret-cmd)
    keymap)
  "Keymap for the Elisp Hinter minor mode")

(define-minor-mode ehinter-mode
    "A minor mode that echoes an arglist for whatever Elisp function is
being
called at point.

\\{ehinter-mode-map}"
  :lighter " EHinter"
  :init-value nil
  (setq ehinter--old-space (ehinter--old-binding " "))
  (setq ehinter--old-tab (ehinter--old-binding "\t"))
  (setq ehinter--old-ret (ehinter--old-binding "\C-m")))

(defun ehinter--old-binding (key)
  (or (lookup-key (current-local-map) key)
      (lookup-key (current-global-map) key)))

(defun ehinter--invoke-binding (binding)
  (if (eq binding 'self-insert-command)
      (self-insert-command 1)
      (funcall binding)))

(defun ehinter--space-cmd ()
  (interactive)
  (ehinter-hint)
  (ehinter--invoke-binding ehinter--old-space))

(defun ehinter--ret-cmd ()
  (interactive)
  (ehinter-hint)
  (ehinter--invoke-binding ehinter--old-ret))

(defun ehinter--tab-cmd ()
  (interactive)
  (ehinter-hint)
  (ehinter--invoke-binding ehinter--old-tab))

(defun ehinter-hint ()
  (interactive)
  (when (and (function-called-at-point)
             (condition-case () (symbol-function (function-called-at-point))
               (void-function nil)))
    (message "%s" (lambda-list (function-called-at-point))))
  (self-insert-command 0))

(defun strip-ends (str)
  (substring str 1 (1- (length str))))

(defun lambda-list (func)
  (let ((fn (symbol-function func)))
    (cond ((and (consp fn)
                (eq (car-safe fn) 'lambda))
           (prin1-to-string (cons func (second fn))))
          ((and (consp fn)
                (eq (car-safe fn) 'macro))
           (prin1-to-string (cons func (svref (cdr fn) 0))))
          ((subrp fn)
           (strip-ends (downcase
                        (prin1-to-string
                         (first (help-split-fundoc (documentation func)
                                                   func))))))
          (t (error "%s" (type-of func))))))

--
Bill Atkins

             reply	other threads:[~2005-12-29 15:52 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2005-12-29 15:52 Bill Atkins [this message]
2005-12-29 18:41 ` Keybindings and minor modes Stefan Monnier
  -- strict thread matches above, loose matches on Subject: below --
2005-12-29  2:18 batkins57
2005-12-29 19:23 ` Kevin Rodgers
     [not found] ` <mailman.20813.1135884349.20277.help-gnu-emacs@gnu.org>
2005-12-29 22:02   ` batkins57
2006-01-01 16:26     ` albrns
2006-01-01 16:27 ` albrns

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=66b7e34b0512290752r5588df25t9ef2b5e615e17f5e@mail.gmail.com \
    --to=atkinw@rpi.edu \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this external index

	https://git.savannah.gnu.org/cgit/emacs.git
	https://git.savannah.gnu.org/cgit/emacs/org-mode.git

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.