all messages for Emacs-related lists mirrored at yhetil.org
 help / color / mirror / code / Atom feed
From: "Lennart Borgman (gmail)" <lennart.borgman@gmail.com>
To: rms@gnu.org
Cc: emacs-devel@gnu.org
Subject: Re: Feature request: permanent-local values in hooks buffer local values
Date: Fri, 07 Dec 2007 01:25:51 +0100	[thread overview]
Message-ID: <4758930F.4060308@gmail.com> (raw)
In-Reply-To: <E1J06DW-00007j-Tm@fencepost.gnu.org>

Richard Stallman wrote:
>     In a way, yes. But remember the goal. It is to let a minor mode that is 
>     turned on in the buffer survive changing major mode.
> 
>     There are two kind of things to survive:
> 
>     1) buffer local variable values, which are survived by using (put 
>     'VARIABLE 'permanent-local t)
> 
>     2) buffer local entries in hooks. Those are what I am asking about here.
> 
> I see.  I did not understand your aim before.
> Here's a possible implementation.
> 
> 1. Put a property on hook variables to identify them for this
> special processing.
> 
> 2. Put another property (as you suggested) on hook functions
> to indicate they should be preserved.
> 
> 3. Now it is possible for kill-all-local-variables
> to identify hook variables, scan their local values,
> and preserve specific hooks.


I have tested another solution, defining a macro instead for minor mode 
authors to use if they want their minor mode to survive changes in major 
mode. The advantage of that is that it makes it very clear what is 
needed. And I do not think there is any big performance penalty. A 
disadvantage is however that the minor mode initialization will be a bit 
different whether this macro is available or not. Therefore it would be 
good if the macro were added to Emacs.

Here is the macro:


(defmacro mumamo-make-change-major-survivor (name hook-fun-list var-list)
   "Define functions for major mode change survival.
Minor mode authors that want their buffer local
minor mode to survive when the major mode in the buffer is
changed can use this macro.

An example of such a minor mode may be flymake minor mode. For
flymake this call can be used:

   (eval-after-load 'mumamo
     (mumamo-make-change-major-survivor
      flymake
      '((after-change-functions flymake-after-change-function)
        (after-save-hook flymake-after-save-hook)
        (kill-buffer-hook flymake-kill-buffer-hook))
      '(flymake-mode
        flymake-is-running
        flymake-timer
        flymake-last-change-time
        flymake-check-start-time
        flymake-check-was-interrupted
        flymake-err-info
        flymake-new-err-info
        flymake-output-residual
        flymake-mode-line
        flymake-mode-line-e-w
        flymake-mode-line-status
        flymake-temp-source-file-name
        flymake-master-file-name
        flymake-temp-master-file-name
        flymake-base-dir
        )))

Then in `flymake-mode' a call to the functions
`flymake-add-survivor' and `flymake-remove-survivor \(which was defined 
by the macro called above) must be done.

The macro defines two functions for the user of this macro to
call, NAME-add-survivor and NAME-remove-survivor. A typical use
is for a minor mode to use the first when turning on and the
second when turning off.

NAME-add-survivor will add to local hooks according to the list
HOOK-FUN-LIST and arrange so that those additions to the local
hooks will be setup again after a major mode change. Also make
sure that the local values of the variables in VAR-LIST survives
a major mode change.

NAME-remove-survivor does the opposite of this.

NAME should be a symbol. HOOK-FUN-LIST should be a list where
each record has the format

   \(HOOK-NAME HOOK-FUNCTION)

where HOOK-NAME is the name of the hook to which HOOK-FUNCTION
should be added locally.

VAR-LIST should be a list of variable symbols."
   (let* ((sname (symbol-name name))
          (NAME-add-survivor    (intern (concat sname "-add-survivor")))
          (NAME-remove-survivor (intern (concat sname "-remove-survivor")))
          (NAME-acmmh-f         (intern (concat sname "-acmmh-f")))
          (NAME-cmmh-f          (intern (concat sname "-cmmh-f"))))

     `(progn

        (defun ,NAME-add-survivor ()
          "Add major mode change surviving.
This function should be called by the code that calls the macro
`make-change-major-survivor'."
          (dolist (rec ,hook-fun-list)
            (let ((hook (nth 0 rec))
                  (func (nth 1 rec)))
              (add-hook hook func nil t)))
          ;; Set up to survive major mode change
          (add-hook 'change-major-mode-hook ',NAME-cmmh-f nil t)
          ;;(lwarn t :warning "add survivor, cmmh=%S" 
change-major-mode-hook)
          )

        (defun ,NAME-remove-survivor ()
          "Remove major mode change surviving.
This function should be called by the code that calls the macro
`make-change-major-survivor'."
          (dolist (rec ,hook-fun-list)
            (let ((hook (nth 0 rec))
                  (func (nth 1 rec)))
              (remove-hook hook func t)))
          ;; Set up to survive major mode change
          (remove-hook 'change-major-mode-hook ',NAME-cmmh-f t)
          ;;(lwarn t :warning "rem survivor, cmmh=%S" 
change-major-mode-hook)
          )

        (defun ,NAME-acmmh-f ()
          "Restore after changing major mode.
This function is added locally to `after-change-major-mode-hook'."
          ;;(remove-hook 'after-change-major-mode-hook ',NAME-acmmh-f t)
          (,NAME-add-survivor)
          ;; Remove 'permanent-local t
          (dolist (sym ,var-list)
            (put sym 'permanent-local nil)))

        (defun ,NAME-cmmh-f ()
          "Set up to restore after changing major mode.
This function is added locally to `change-major-mode-hook'."
          (add-hook 'after-change-major-mode-hook ',NAME-acmmh-f nil t)
          ;;(lwarn t :warning "cmmh-f, acmmh=%S" 
after-change-major-mode-hook)
          (put 'after-change-major-mode-hook 'permanent-local t)
          ;; Note: I can see no way to later remove the
          ;; 'permanent-local property that is set here without
          ;; getting potential problems.
          ;;
          ;; Add 'permanent-local t
          (dolist (sym ,var-list)
            (put sym 'permanent-local t))))))

  reply	other threads:[~2007-12-07  0:25 UTC|newest]

Thread overview: 12+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2007-12-03 17:15 Feature request: permanent-local values in hooks buffer local values Lennart Borgman (gmail)
2007-12-03 18:22 ` Juanma Barranquero
2007-12-04  4:56 ` Richard Stallman
2007-12-04 18:13   ` Lennart Borgman (gmail)
2007-12-05  6:05     ` Richard Stallman
2007-12-05  7:21       ` Lennart Borgman (gmail)
2007-12-06  2:11         ` Richard Stallman
2007-12-07  0:25           ` Lennart Borgman (gmail) [this message]
2007-12-09 12:36             ` Richard Stallman
2007-12-09 14:21               ` Lennart Borgman (gmail)
2007-12-09 15:24                 ` Lennart Borgman (gmail)
2007-12-09 23:19                 ` Richard Stallman

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=4758930F.4060308@gmail.com \
    --to=lennart.borgman@gmail.com \
    --cc=emacs-devel@gnu.org \
    --cc=rms@gnu.org \
    /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.