unofficial mirror of emacs-devel@gnu.org 
 help / color / mirror / code / Atom feed
* Patch to remove minor modes in tutorial
@ 2006-06-24 14:09 Lennart Borgman
  2006-06-25 15:34 ` Richard Stallman
  0 siblings, 1 reply; 29+ messages in thread
From: Lennart Borgman @ 2006-06-24 14:09 UTC (permalink / raw)


[-- Attachment #1: Type: text/plain, Size: 231 bytes --]

Some while ago I complained that the tutorial did not work if some minor 
modes where enabled. Attached is a patch for that. (I am not sure if I 
have sent this before. I asked for help installing them, but I did not 
get that.)



[-- Attachment #2: patch-for-tutorial.diff --]
[-- Type: text/plain, Size: 3884 bytes --]

Index: lisp/help-fns.el
===================================================================
RCS file: /cvsroot/emacs/emacs/lisp/help-fns.el,v
retrieving revision 1.89
diff -u -r1.89 help-fns.el
--- lisp/help-fns.el	11 May 2006 11:10:45 -0000	1.89
+++ lisp/help-fns.el	16 Jun 2006 22:07:02 -0000
@@ -98,7 +98,86 @@
 	  (newline (- n (/ n 2)))))
       (goto-char (point-min))
       (setq buffer-undo-list nil)
-      (set-buffer-modified-p nil))))
+      (set-buffer-modified-p nil)))
+
+  ;; Check if minor modes may disturb
+  (let (minor-modes-on minor-modes unknown)
+    (dolist (m minor-mode-list)
+      (let ((fmode (or (get m :minor-mode-function) m)))
+      (when (and (boundp m) (symbol-value m)
+                 (fboundp fmode)
+                 (condition-case err
+                     (progn
+                       (unless
+                           (equal '(keymap)
+                                  (symbol-value
+                                   (read (concat (symbol-name m) "-map"))))
+                         t))
+                   (error nil)))
+        (add-to-list 'minor-modes m))))
+    (dolist (m minor-mode-alist)
+      (add-to-list 'minor-modes (car m)))
+    (dolist (m minor-modes)
+      (when (symbol-value m)
+        (add-to-list 'minor-modes-on m)))
+
+    ;; Default minor modes
+    (dolist (m '(auto-compression-mode
+                 blink-cursor-mode
+                 encoded-kbd-mode
+                 file-name-shadow-mode
+                 font-lock-mode
+                 global-font-lock-mode
+                 line-number-mode
+                 menu-bar-mode
+                 mouse-wheel-mode
+                 tool-bar-mode
+                 tooltip-mode
+                 unify-8859-on-encoding-mode
+                 utf-translate-cjk-mode))
+      (setq minor-modes-on (delete m minor-modes-on)))
+
+    ;; Special
+    (when cua-mode
+      (add-to-list 'minor-modes-on 'cua-mode))
+
+    (when minor-modes-on
+      (setq minor-modes-on (sort minor-modes-on 'string<))
+      (let (remove-minor
+            (modes-on (copy-seq minor-modes-on))
+            )
+        (with-temp-buffer
+          (insert "\nYou are using some minor modes (")
+          (dolist (m modes-on)
+            (insert (format "%s" (car modes-on)))
+            (setq modes-on (cdr modes-on))
+            (if (= 1 (length modes-on))
+                (insert " and ")
+              (when modes-on (insert ", "))))
+          (insert
+           ") which can possibly override global key bindings."
+           "  The behavior of Emacs with these modes may"
+           " not match what the tutorial teaches.\n\n"
+           "Do you want to disable these modes when you are in the tutorial?"
+           "(y-or-n)"
+           )
+          (fill-region (point-min) (point-max))
+          (let ((use-dialog-box nil))
+            (setq remove-minor
+                  (y-or-n-p (format "%s " (buffer-substring
+                                           (point-min)
+                                           (- (point-max) 8)))))))
+        (if remove-minor
+            (progn
+              (make-local-variable 'emulation-mode-map-alists)
+              (setq emulation-mode-map-alists nil)
+              (dolist (m minor-modes-on)
+                (make-local-variable m)
+                (set m nil))
+              (message "Removed those bindings for the tutorial only."))
+          (message
+           "Please note that the tutorial may not work with this choice.")
+          )))))
 
 \f
 ;; Functions
@@ -325,6 +404,8 @@
 		 "a Lisp macro")
 		((eq (car-safe def) 'autoload)
 		 (setq file-name (nth 1 def))
+		 (let ((loc (locate-library file-name)))
+                   (when loc (setq file-name loc)))
 		 (format "%s autoloaded %s"
 			 (if (commandp def) "an interactive" "an")
 			 (if (eq (nth 4 def) 'keymap) "keymap"

[-- Attachment #3: Type: text/plain, Size: 142 bytes --]

_______________________________________________
Emacs-devel mailing list
Emacs-devel@gnu.org
http://lists.gnu.org/mailman/listinfo/emacs-devel

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: Patch to remove minor modes in tutorial
  2006-06-24 14:09 Patch to remove minor modes in tutorial Lennart Borgman
@ 2006-06-25 15:34 ` Richard Stallman
  2006-06-25 21:27   ` Lennart Borgman
  0 siblings, 1 reply; 29+ messages in thread
From: Richard Stallman @ 2006-06-25 15:34 UTC (permalink / raw)
  Cc: emacs-devel

    +  ;; Check if minor modes may disturb

That is not an accurate description of what the new code does.
It only describes a _part_ of what the code does.
It ought to describe the _overall action_.

    +                 (condition-case err
    +                     (progn
    +                       (unless
    +                           (equal '(keymap)
    +                                  (symbol-value
    +                                   (read (concat (symbol-name m) "-map"))))
    +                         t))
    +                   (error nil)))

What is that code supposed to do?  And why?

    +    ;; Default minor modes
    +    (dolist (m '(auto-compression-mode

That comment makes no sense to me.  What was the reason
for choosing which modes to put in this list?

    +          (insert
    +           ") which can possibly override global key bindings."
    +           "  The behavior of Emacs with these modes may"
    +           " not match what the tutorial teaches.\n\n"
    +           "Do you want to disable these modes when you are in the tutorial?"
    +           "(y-or-n)"
    +           )

Why ask?  Why not just do it?

    +              (make-local-variable 'emulation-mode-map-alists)
    +              (setq emulation-mode-map-alists nil)
    +              (dolist (m minor-modes-on)
    +                (make-local-variable m)
    +                (set m nil))

Nowadays there are minor modes that can't be turned off this way.
You need to call the function.


    @@ -325,6 +404,8 @@
		     "a Lisp macro")
		    ((eq (car-safe def) 'autoload)
		     (setq file-name (nth 1 def))
    +		 (let ((loc (locate-library file-name)))
    +                   (when loc (setq file-name loc)))
		     (format "%s autoloaded %s"
			     (if (commandp def) "an interactive" "an")

What is that for?

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: Patch to remove minor modes in tutorial
  2006-06-25 15:34 ` Richard Stallman
@ 2006-06-25 21:27   ` Lennart Borgman
  2006-06-26 11:33     ` Richard Stallman
  0 siblings, 1 reply; 29+ messages in thread
From: Lennart Borgman @ 2006-06-25 21:27 UTC (permalink / raw)
  Cc: emacs-devel

Richard Stallman wrote:
>     +  ;; Check if minor modes may disturb
>
> That is not an accurate description of what the new code does.
> It only describes a _part_ of what the code does.
> It ought to describe the _overall action_.
>   
Thanks. I will enhance the description.

>     +                 (condition-case err
>     +                     (progn
>     +                       (unless
>     +                           (equal '(keymap)
>     +                                  (symbol-value
>     +                                   (read (concat (symbol-name m) "-map"))))
>     +                         t))
>     +                   (error nil)))
>
> What is that code supposed to do?  And why?
>   
Some minor modes have no keybindings so they can not disturb the 
tutorial (recentf-mode for example). Well, at least I hope they can not. 
I think this is very important!

>     +    ;; Default minor modes
>     +    (dolist (m '(auto-compression-mode
>
> That comment makes no sense to me.  What was the reason
> for choosing which modes to put in this list?
>   
I will change that. The modes I am referring to are those that are on 
when starting Emacs with -Q.

>     +          (insert
>     +           ") which can possibly override global key bindings."
>     +           "  The behavior of Emacs with these modes may"
>     +           " not match what the tutorial teaches.\n\n"
>     +           "Do you want to disable these modes when you are in the tutorial?"
>     +           "(y-or-n)"
>     +           )
>
> Why ask?  Why not just do it?
>   
To make the user aware of that Emacs will work differently in the 
tutorial buffer than in other buffer (if the user answers Y).

>     +              (make-local-variable 'emulation-mode-map-alists)
>     +              (setq emulation-mode-map-alists nil)
>     +              (dolist (m minor-modes-on)
>     +                (make-local-variable m)
>     +                (set m nil))
>
> Nowadays there are minor modes that can't be turned off this way.
> You need to call the function.
>   
I have changed that.

>
>     @@ -325,6 +404,8 @@
> 		     "a Lisp macro")
> 		    ((eq (car-safe def) 'autoload)
> 		     (setq file-name (nth 1 def))
>     +		 (let ((loc (locate-library file-name)))
>     +                   (when loc (setq file-name loc)))
> 		     (format "%s autoloaded %s"
> 			     (if (commandp def) "an interactive" "an")
>
> What is that for?
>   
I did not think of that patch. I noticed that in some cases file-name 
here is not a file name at all but the library name (or was it the file 
name without the path??). This part of the patch may not be the correct 
cure for those cases though and unfortunately I do not remember which 
autoloaded function I saw this for. I should have made a note of course, 
but I thought I would have had time to finish this earlier.


------------------------
Here is a new patch:

Index: help-fns.el
===================================================================
RCS file: /cvsroot/emacs/emacs/lisp/help-fns.el,v
retrieving revision 1.89
diff -u -r1.89 help-fns.el
--- help-fns.el    11 May 2006 11:10:45 -0000    1.89
+++ help-fns.el    25 Jun 2006 21:16:22 -0000
@@ -98,7 +98,98 @@
       (newline (- n (/ n 2)))))
       (goto-char (point-min))
       (setq buffer-undo-list nil)
-      (set-buffer-modified-p nil))))
+      (set-buffer-modified-p nil)))
+
+  ;; Check if there are minor modes that may disturb the tutorial. If
+  ;; so show them to the user and ask if they should be disabled in
+  ;; the tutorial buffer.
+  (let (minor-modes-on minor-modes unknown)
+    (dolist (m minor-mode-list)
+      (let ((fmode (or (get m :minor-mode-function) m)))
+      (when (and (boundp m) (symbol-value m)
+                 (fboundp fmode)
+                 ;; Some minor modes have no bindings in the keymaps
+                 ;; so ignore them:
+                 (condition-case err
+                     (progn
+                       (unless
+                           (equal '(keymap)
+                                  (symbol-value
+                                   (read (concat (symbol-name m) "-map"))))
+                         t))
+                   (error nil)))
+        (add-to-list 'minor-modes m))))
+    (dolist (m minor-mode-alist)
+      (add-to-list 'minor-modes (car m)))
+    (dolist (m minor-modes)
+      (when (symbol-value m)
+        (add-to-list 'minor-modes-on m)))
+
+    ;; Minor modes that are on by default (ie when starting with
+    ;; "emacs -Q"):
+    (dolist (m '(auto-compression-mode
+                 blink-cursor-mode
+                 encoded-kbd-mode
+                 file-name-shadow-mode
+                 font-lock-mode
+                 global-font-lock-mode
+                 line-number-mode
+                 menu-bar-mode
+                 mouse-wheel-mode
+                 tool-bar-mode
+                 tooltip-mode
+                 unify-8859-on-encoding-mode
+                 utf-translate-cjk-mode))
+      (setq minor-modes-on (delete m minor-modes-on)))
+
+    ;; Special
+    (when cua-mode
+      (add-to-list 'minor-modes-on 'cua-mode))
+
+    (when minor-modes-on
+      (setq minor-modes-on (sort minor-modes-on 'string<))
+      (let (remove-minor
+            (modes-on (copy-seq minor-modes-on))
+            )
+        ;; Ask the user if the possibly disturbing minor modes should
+        ;; be disabled. This is to avoid confusing the user with the
+        ;; different behaviour in the tutorial buffer when those modes
+        ;; are disabled:
+        (with-temp-buffer
+          (insert "\nYou are using some minor modes (")
+          (dolist (m modes-on)
+            (insert (format "%s" (car modes-on)))
+            (setq modes-on (cdr modes-on))
+            (if (= 1 (length modes-on))
+                (insert " and ")
+              (when modes-on (insert ", "))))
+          (insert
+           ") which can possibly override global key bindings."
+           "  The behavior of Emacs with these modes may"
+           " not match what the tutorial teaches.\n\n"
+           "Do you want to disable these modes when you are in the 
tutorial?"
+           "(y-or-n)"
+           )
+          (fill-region (point-min) (point-max))
+          (let ((use-dialog-box nil))
+            (setq remove-minor
+                  (y-or-n-p (format "%s " (buffer-substring
+                                           (point-min)
+                                           (- (point-max) 8)))))))
+        (if remove-minor
+            (progn
+              (make-local-variable 'emulation-mode-map-alists)
+              (setq emulation-mode-map-alists nil)
+              (dolist (m minor-modes-on)
+                (make-local-variable m)
+                ;; (set m nil) Better call the minor mode function
+                ;; according to RMS:
+                (funcall m 0)
+                )
+              (message "Removed those bindings for the tutorial only."))
+          (message
+           "Please note that the tutorial may not work with this choice.")
+          )))))
 
 \f
 ;; Functions
@@ -325,6 +416,8 @@
          "a Lisp macro")
         ((eq (car-safe def) 'autoload)
          (setq file-name (nth 1 def))
+         (let ((loc (locate-library file-name)))
+                   (when loc (setq file-name loc)))
          (format "%s autoloaded %s"
              (if (commandp def) "an interactive" "an")
              (if (eq (nth 4 def) 'keymap) "keymap"

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: Patch to remove minor modes in tutorial
  2006-06-25 21:27   ` Lennart Borgman
@ 2006-06-26 11:33     ` Richard Stallman
  2006-06-26 13:48       ` Lennart Borgman
  0 siblings, 1 reply; 29+ messages in thread
From: Richard Stallman @ 2006-06-26 11:33 UTC (permalink / raw)
  Cc: emacs-devel

    Some minor modes have no keybindings so they can not disturb the 
    tutorial (recentf-mode for example). Well, at least I hope they can not. 
    I think this is very important!

I think it is safer to turn them all off, aside from a specific
list of exceptions.

    > Why ask?  Why not just do it?
    >   
    To make the user aware of that Emacs will work differently in the 
    tutorial buffer than in other buffer (if the user answers Y).

I agree it is useful to do that, but I think that asking a question
will be confusing in a different way, since it will suggest that it is
reasonable to answer N.  Displaying a message which ends in "Type
SPACE to proceed" is a better way to make sure the user notices the
message.

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: Patch to remove minor modes in tutorial
  2006-06-26 11:33     ` Richard Stallman
@ 2006-06-26 13:48       ` Lennart Borgman
  2006-06-26 16:31         ` Kevin Rodgers
  2006-06-27 16:14         ` Richard Stallman
  0 siblings, 2 replies; 29+ messages in thread
From: Lennart Borgman @ 2006-06-26 13:48 UTC (permalink / raw)
  Cc: emacs-devel

Richard Stallman wrote:
>     Some minor modes have no keybindings so they can not disturb the 
>     tutorial (recentf-mode for example). Well, at least I hope they can not. 
>     I think this is very important!
>
> I think it is safer to turn them all off, aside from a specific
> list of exceptions.
>   
Then I would be glad if those who knows about minor modes that will not 
disturb the turorial would mail the names of them to me.


>     > Why ask?  Why not just do it?
>     >   
>     To make the user aware of that Emacs will work differently in the 
>     tutorial buffer than in other buffer (if the user answers Y).
>
> I agree it is useful to do that, but I think that asking a question
> will be confusing in a different way, since it will suggest that it is
> reasonable to answer N.  Displaying a message which ends in "Type
> SPACE to proceed" is a better way to make sure the user notices the
> message.
>   
Yes, that is better.

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: Patch to remove minor modes in tutorial
  2006-06-26 13:48       ` Lennart Borgman
@ 2006-06-26 16:31         ` Kevin Rodgers
  2006-06-26 16:45           ` Lennart Borgman
  2006-06-27 16:14         ` Richard Stallman
  1 sibling, 1 reply; 29+ messages in thread
From: Kevin Rodgers @ 2006-06-26 16:31 UTC (permalink / raw)


Lennart Borgman wrote:
> Richard Stallman wrote:
>>     Some minor modes have no keybindings so they can not disturb the 
>>     tutorial (recentf-mode for example). Well, at least I hope they 
>> can not.     I think this is very important!
>>
>> I think it is safer to turn them all off, aside from a specific
>> list of exceptions.
>>   
> Then I would be glad if those who knows about minor modes that will not 
> disturb the turorial would mail the names of them to me.

C-h v minor-mode-map-alist

-- 
Kevin

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: Patch to remove minor modes in tutorial
  2006-06-26 16:31         ` Kevin Rodgers
@ 2006-06-26 16:45           ` Lennart Borgman
  2006-06-27 15:44             ` Kevin Rodgers
  0 siblings, 1 reply; 29+ messages in thread
From: Lennart Borgman @ 2006-06-26 16:45 UTC (permalink / raw)
  Cc: emacs-devel

Kevin Rodgers wrote:
> Lennart Borgman wrote:
>> Richard Stallman wrote:
>>>     Some minor modes have no keybindings so they can not disturb the 
>>>     tutorial (recentf-mode for example). Well, at least I hope they 
>>> can not.     I think this is very important!
>>>
>>> I think it is safer to turn them all off, aside from a specific
>>> list of exceptions.
>>>   
>> Then I would be glad if those who knows about minor modes that will 
>> not disturb the turorial would mail the names of them to me.
>
> C-h v minor-mode-map-alist
>
Thanks, but how can that help?

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: Patch to remove minor modes in tutorial
  2006-06-26 16:45           ` Lennart Borgman
@ 2006-06-27 15:44             ` Kevin Rodgers
  2006-06-27 16:41               ` Lennart Borgman
  2006-06-28 17:25               ` Richard Stallman
  0 siblings, 2 replies; 29+ messages in thread
From: Kevin Rodgers @ 2006-06-27 15:44 UTC (permalink / raw)


Lennart Borgman wrote:
> Kevin Rodgers wrote:
>> Lennart Borgman wrote:
>>> Richard Stallman wrote:
>>>>     Some minor modes have no keybindings so they can not disturb the 
>>>>     tutorial (recentf-mode for example). Well, at least I hope they 
>>>> can not.     I think this is very important!
>>>>
>>>> I think it is safer to turn them all off, aside from a specific
>>>> list of exceptions.
>>>>   
>>> Then I would be glad if those who knows about minor modes that will 
>>> not disturb the turorial would mail the names of them to me.
>>
>> C-h v minor-mode-map-alist
>>
> Thanks, but how can that help?

A minor mode that doesn't have an entry in minor-mode-map-alist has
no keybindings (assuming it is not autoloaded -- but if it has not
been loaded yet, it's definitely not turned on and has no effect).

-- 
Kevin

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: Patch to remove minor modes in tutorial
  2006-06-26 13:48       ` Lennart Borgman
  2006-06-26 16:31         ` Kevin Rodgers
@ 2006-06-27 16:14         ` Richard Stallman
  1 sibling, 0 replies; 29+ messages in thread
From: Richard Stallman @ 2006-06-27 16:14 UTC (permalink / raw)
  Cc: emacs-devel

    Then I would be glad if those who knows about minor modes that will not 
    disturb the turorial would mail the names of them to me.

Don't worry about completeness!  Just put the ones you can think of.
If we encounter others in the future, we can add them to the list
then.

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: Patch to remove minor modes in tutorial
  2006-06-27 15:44             ` Kevin Rodgers
@ 2006-06-27 16:41               ` Lennart Borgman
  2006-06-28 17:25               ` Richard Stallman
  1 sibling, 0 replies; 29+ messages in thread
From: Lennart Borgman @ 2006-06-27 16:41 UTC (permalink / raw)
  Cc: emacs-devel

Kevin Rodgers wrote:
> Lennart Borgman wrote:
>> Kevin Rodgers wrote:
>>> Lennart Borgman wrote:
>>>> Richard Stallman wrote:
>>>>>     Some minor modes have no keybindings so they can not disturb 
>>>>> the     tutorial (recentf-mode for example). Well, at least I hope 
>>>>> they can not.     I think this is very important!
>>>>>
>>>>> I think it is safer to turn them all off, aside from a specific
>>>>> list of exceptions.
>>>>>   
>>>> Then I would be glad if those who knows about minor modes that will 
>>>> not disturb the turorial would mail the names of them to me.
>>>
>>> C-h v minor-mode-map-alist
>>>
>> Thanks, but how can that help?
>
> A minor mode that doesn't have an entry in minor-mode-map-alist has
> no keybindings (assuming it is not autoloaded -- but if it has not
> been loaded yet, it's definitely not turned on and has no effect).
>
Ah, I see the idea. But a little bit more have to be checked, there is 
also emulation-mode-map-alists (and minor-mode-overriding-map-alist but 
that does not apply here).

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: Patch to remove minor modes in tutorial
  2006-06-27 15:44             ` Kevin Rodgers
  2006-06-27 16:41               ` Lennart Borgman
@ 2006-06-28 17:25               ` Richard Stallman
  2006-06-29  8:41                 ` Kim F. Storm
  1 sibling, 1 reply; 29+ messages in thread
From: Richard Stallman @ 2006-06-28 17:25 UTC (permalink / raw)
  Cc: emacs-devel

    A minor mode that doesn't have an entry in minor-mode-map-alist has
    no keybindings (assuming it is not autoloaded -- but if it has not
    been loaded yet, it's definitely not turned on and has no effect).

It is conceivable that a minor mode has other effects that would interfere
with the tutorial.  For instance Abbrev mode.

At the same time, it is possible that a minor mode alters only keys
that the tutorial does not talk about, in which case it does not
interfere with the tutorial.

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: Patch to remove minor modes in tutorial
  2006-06-28 17:25               ` Richard Stallman
@ 2006-06-29  8:41                 ` Kim F. Storm
  2006-06-29 12:07                   ` Mathias Dahl
  2006-06-29 17:57                   ` Richard Stallman
  0 siblings, 2 replies; 29+ messages in thread
From: Kim F. Storm @ 2006-06-29  8:41 UTC (permalink / raw)
  Cc: Kevin Rodgers, emacs-devel

Richard Stallman <rms@gnu.org> writes:

>     A minor mode that doesn't have an entry in minor-mode-map-alist has
>     no keybindings (assuming it is not autoloaded -- but if it has not
>     been loaded yet, it's definitely not turned on and has no effect).
>
> It is conceivable that a minor mode has other effects that would interfere
> with the tutorial.  For instance Abbrev mode.
>
> At the same time, it is possible that a minor mode alters only keys
> that the tutorial does not talk about, in which case it does not
> interfere with the tutorial.

In general, there is a problem with the tutorial and minor-modes:

Suppose you get a .emacs from someone, which changes some key bindings.

Then you run the tutorial with those minor modes enabled.  This may
cause the examples/instructions in the tutorial to fail in mysterious
ways.  That's no good.


Now, suppose you run the tutorial with the minor modes temporarily
disabled.  The tutorial will work just fine, and you will learn the
basic commands etc.  But when you exit the tutorial, the minor modes
are back -- and the stuff that worked in the tutorial no longer works
the way the tutorial taught you...   That's no good either!


Maybe it be better to simply issue a warning at the start of the
tutorial if "affecting" minor modes are enabled -- something like
this:

  NOTE:  This instance of Emacs has local customizations which may
  cause some instructions in the tutorial to fail.  If that happens,
  review the local customizations in the file ~/.emacs.

-- 
Kim F. Storm <storm@cua.dk> http://www.cua.dk

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: Patch to remove minor modes in tutorial
  2006-06-29  8:41                 ` Kim F. Storm
@ 2006-06-29 12:07                   ` Mathias Dahl
  2006-06-29 12:27                     ` David Kastrup
  2006-06-29 17:57                   ` Richard Stallman
  1 sibling, 1 reply; 29+ messages in thread
From: Mathias Dahl @ 2006-06-29 12:07 UTC (permalink / raw)
  Cc: Kevin Rodgers, rms, emacs-devel

> In general, there is a problem with the tutorial and minor-modes:

> ...

> Maybe it be better to simply issue a warning at the start of the
> tutorial if "affecting" minor modes are enabled -- something like
> this:
>
>  NOTE:  This instance of Emacs has local customizations which may
>  cause some instructions in the tutorial to fail.  If that happens,
>  review the local customizations in the file ~/.emacs.

I like this idea.  It seems we can never protect the user from all
problems in this area so the best thing is to inform him about that.

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: Patch to remove minor modes in tutorial
  2006-06-29 12:07                   ` Mathias Dahl
@ 2006-06-29 12:27                     ` David Kastrup
  2006-06-30 11:06                       ` Richard Stallman
  0 siblings, 1 reply; 29+ messages in thread
From: David Kastrup @ 2006-06-29 12:27 UTC (permalink / raw)
  Cc: Kevin Rodgers, emacs-devel, rms, Kim F. Storm

"Mathias Dahl" <mathias.dahl@gmail.com> writes:

>> In general, there is a problem with the tutorial and minor-modes:
>
>> ...
>
>> Maybe it be better to simply issue a warning at the start of the
>> tutorial if "affecting" minor modes are enabled -- something like
>> this:
>>
>>  NOTE:  This instance of Emacs has local customizations which may
>>  cause some instructions in the tutorial to fail.  If that happens,
>>  review the local customizations in the file ~/.emacs.
>
> I like this idea.  It seems we can never protect the user from all
> problems in this area so the best thing is to inform him about that.

We could recommend to start a session with emacs -q if one suspects
stuff in the tutorial to fail because of customizations.

-- 
David Kastrup, Kriemhildstr. 15, 44793 Bochum

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: Patch to remove minor modes in tutorial
  2006-06-29  8:41                 ` Kim F. Storm
  2006-06-29 12:07                   ` Mathias Dahl
@ 2006-06-29 17:57                   ` Richard Stallman
  2006-07-01  0:38                     ` Lennart Borgman
  1 sibling, 1 reply; 29+ messages in thread
From: Richard Stallman @ 2006-06-29 17:57 UTC (permalink / raw)
  Cc: ihs_4664, emacs-devel

    Suppose you get a .emacs from someone, which changes some key bindings.

It is a bad thing to start off a new user with a .emacs file that
changes key bindings.  Regardless of what documentation the user
learns from, it will be wrong; but it's worse than that.  Users should
decide for themselves whether to change key bindings.

    Maybe it be better to simply issue a warning at the start of the
    tutorial if "affecting" minor modes are enabled -- something like
    this:

      NOTE:  This instance of Emacs has local customizations which may
      cause some instructions in the tutorial to fail.  If that happens,
      review the local customizations in the file ~/.emacs.

You have convinced me.

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: Patch to remove minor modes in tutorial
  2006-06-29 12:27                     ` David Kastrup
@ 2006-06-30 11:06                       ` Richard Stallman
  0 siblings, 0 replies; 29+ messages in thread
From: Richard Stallman @ 2006-06-30 11:06 UTC (permalink / raw)
  Cc: ihs_4664, storm, emacs-devel, mathias.dahl

    We could recommend to start a session with emacs -q if one suspects
    stuff in the tutorial to fail because of customizations.

We could, but Kim is right in point out that this isn't really useful.
The tutorial exists for using Emacs, not vice versa.
Making the tutorial "work right" in teaching standard Emacs
won't enable the user to use his non-standard Emacs.

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: Patch to remove minor modes in tutorial
  2006-06-29 17:57                   ` Richard Stallman
@ 2006-07-01  0:38                     ` Lennart Borgman
  2006-07-01 23:55                       ` Richard Stallman
  0 siblings, 1 reply; 29+ messages in thread
From: Lennart Borgman @ 2006-07-01  0:38 UTC (permalink / raw)
  Cc: ihs_4664, emacs-devel, Kim F. Storm

Richard Stallman wrote:
>     Suppose you get a .emacs from someone, which changes some key bindings.
>
> It is a bad thing to start off a new user with a .emacs file that
> changes key bindings.  Regardless of what documentation the user
> learns from, it will be wrong; but it's worse than that.  Users should
> decide for themselves whether to change key bindings.
>
>     Maybe it be better to simply issue a warning at the start of the
>     tutorial if "affecting" minor modes are enabled -- something like
>     this:
>
>       NOTE:  This instance of Emacs has local customizations which may
>       cause some instructions in the tutorial to fail.  If that happens,
>       review the local customizations in the file ~/.emacs.
>
> You have convinced me.
>   

Here is a new version of help-with-tutorial for testing. This new 
version behaves like this:

- It checks the actual keybindings and tries to find those in minor modes.
- It asks the user if the disturbing key bindings should be removed.
- It inserts a warning in the tutorial text. Eh, in English.


(defun help-with-tutorial (&optional arg)
  "Select the Emacs learn-by-doing tutorial.
If there is a tutorial version written in the language
of the selected language environment, that version is used.
If there's no tutorial in that language, `TUTORIAL' is selected.
With ARG, you are asked to choose which language."
  (interactive "P")
  (let ((lang (if arg
                  (let ((minibuffer-setup-hook minibuffer-setup-hook))
                    (add-hook 'minibuffer-setup-hook
                              'minibuffer-completion-help)
                    (read-language-name 'tutorial "Language: " "English"))
        (if (get-language-info current-language-environment 'tutorial)
            current-language-environment
          "English")))
    file filename
        (point-after-message 1))
    (setq filename (get-language-info lang 'tutorial))
    (setq file (expand-file-name (concat "~/" filename)))
    (delete-other-windows)
    (if (get-file-buffer file)
    (switch-to-buffer (get-file-buffer file))
      (switch-to-buffer (create-file-buffer file))
      (setq buffer-file-name file)
      (setq default-directory (expand-file-name "~/"))
      (setq buffer-auto-save-file-name nil)
      (insert-file-contents (expand-file-name filename data-directory))
      (setq buffer-file-name nil)
      (hack-local-variables)


      ;; Check if there are key bindings or minor modes that may disturb
      ;; the tutorial. If so show them to the user and ask if they should
      ;; be disabled in the tutorial buffer.
      (let (minor-modes-added
            minor-modes
            minor-modes-disturbing
            other-disturbed-keys
            unknown
            (tutorial-keys
             '(
               (save-buffers-kill-emacs [(control ?x)(control ?c)])


               ;; * SUMMARY
               (scroll-up [(control ?v)])
               (scroll-down [(meta ?v)])
               (recenter [(control ?l)])


               ;; * BASIC CURSOR CONTROL
               (forward-char [(control ?f)])
               (backward-char [(control ?b)])

               (forward-word [(meta ?f)])
               (backward-word [(meta ?b)])

               (next-line [(control ?n)])
               (previous-line [(control ?p)])

               (move-beginning-of-line [(control ?a)])
               (move-end-of-line [(control ?e)])

               (backward-sentence [(meta ?a)])
               (forward-sentence [(meta ?e)])


               (beginning-of-buffer [(meta ?<)])
               (end-of-buffer [(meta ?>)])

               (universal-argument [(control ?u)])


               ;; * WHEN EMACS IS HUNG
               (keyboard-quit [(control ?g)])


               ;; * DISABLED COMMANDS
               (downcase-region [(control ?x)(control ?l)])


               ;; * WINDOWS
               (delete-other-windows [(control ?x) ?1])
               ;; C-u 0 C-l
               ;; Type CONTROL-h k CONTROL-f.


               ;; * INSERTING AND DELETING
               ;; C-u 8 * to insert ********.

               (delete-backward-char [backspace])
               (delete-char [(control ?d)])

               (backward-kill-word [(meta backspace)])
               (kill-word [(meta ?d)])

               (kill-line [(control ?k)])
               (kill-sentence [(meta ?k)])

               ;; You can also kill any part of the text with one 
uniform method.  Move
               (set-mark-command [(control ?@)])
               (set-mark-command [(control ? )])
               (kill-region [(control ?w)])
               (yank [(control ?y)])
               (yank-pop [(meta ?y)])


               ;; * UNDO
               (advertised-undo [(control ?x) ?u])
               (advertised-undo [(control ?x) ?u])


               ;; * FILES
               (find-file [(control ?x)(control ?f)])
               (save-buffer [(control ?x)(control ?s)])


               ;; * BUFFERS
               (list-buffers [(control ?x)(control ?b)])
               (switch-to-buffer [(control ?x) ?b])
               (save-some-buffers [(control ?x) ?s])


               ;; * EXTENDING THE COMMAND SET
               ;; C-x    Character eXtend.  Followed by one character.
               (execute-extended-command [(meta ?x)])

               ;; C-x C-f        Find file
               ;; C-x C-s        Save file
               ;; C-x s        Save some buffers
               ;; C-x C-b        List buffers
               ;; C-x b        Switch buffer
               ;; C-x C-c        Quit Emacs
               ;; C-x 1        Delete all but one window
               ;; C-x u        Undo


               ;; * MODE LINE
               (describe-mode [(control ?h) ?m])

               (set-fill-column [(control ?x) ?f])
               (fill-paragraph [(meta ?q)])


               ;; * SEARCHING
               (isearch-forward [(control ?s)])
               (isearch-backward [(control ?r)])


               ;; * MULTIPLE WINDOWS
               (split-window-vertically [(control ?x) ?2])
               (scroll-other-window [(control meta ?v)])
               ;; (list "<ESC> C-v" 'scroll-other-window [escape 
(control-v)])
               (other-window [(control ?x) ?o])
               (find-file-other-window [(control ?x) ?4 (control ?f)])


               ;; * RECURSIVE EDITING LEVELS
               ;;(list "<ESC> <ESC> <ESC>" 'keyboard-escape-quit [escape 
escape escape])


               ;; * GETTING MORE HELP
               ;; The most basic HELP feature is C-h c
               (describe-key-briefly [(control ?h) ?c])
               (describe-key [(control ?h) ?k])


               ;; * MORE FEATURES
               ;; F10


               ;; * CONCLUSION
               (iconify-or-deiconify-frame [(control ?z)])
               )
             )
            failed-keys
            still-failed-keys
            )

        (dolist (m minor-mode-list)
          (let ((fmode (or (get m :minor-mode-function) m)))
            (when (and (boundp m) (symbol-value m)
                       (fboundp fmode)
                       ;; Some minor modes have no bindings in the keymaps
                       ;; so ignore them:
                       (condition-case err
                           (progn
                             (unless
                                 (equal '(keymap)
                                        (symbol-value
                                         (read (concat (symbol-name m) 
"-map"))))
                               t))
                         (error nil)))
              (add-to-list 'minor-modes m))))
        (dolist (m minor-mode-alist)
          (add-to-list 'minor-modes (car m)))
        (dolist (m minor-modes)
          (when (symbol-value m)
            (add-to-list 'minor-modes-added m)))

        ;; Minor modes that are on by default (ie when starting with
        ;; "emacs -Q"):
        (dolist (m '(auto-compression-mode
                     blink-cursor-mode
                     encoded-kbd-mode
                     file-name-shadow-mode
                     font-lock-mode
                     global-font-lock-mode
                     line-number-mode
                     menu-bar-mode
                     mouse-wheel-mode
                     tool-bar-mode
                     tooltip-mode
                     unify-8859-on-encoding-mode
                     utf-translate-cjk-mode))
          (setq minor-modes-added (delete m minor-modes-added)))

        ;; What default key bindings used in the tutorial are
        ;; disturbed?
        (let ((initial-failings))
          (with-temp-buffer
            (fundamental-mode)
            (dolist (tk tutorial-keys)
              (let* ((b (cadr tk))
                     (f (key-binding b))
                     (cp-tk (copy-sequence tk)))
                (unless (eq (car tk) f)
                  (add-to-list 'failed-keys tk)
                  (setq cp-tk (cons f cp-tk))
                  (add-to-list 'initial-failings cp-tk)))))

          ;; Which minor modes are disturbing the key bindings above?
          (dolist (m minor-modes-added)
            (let ((m-failings))
              (with-temp-buffer
                (fundamental-mode)
                (make-local-variable m)
                (funcall m 0)
                (dolist (tk tutorial-keys)
                  (let* ((b (cadr tk))
                         (f (key-binding b))
                         (cp-tk (copy-sequence tk)))
                    (unless (eq (car tk) f)
                      (setq cp-tk (cons f cp-tk))
                      (add-to-list 'm-failings cp-tk)))))
              (unless (equal m-failings initial-failings)
                (add-to-list 'minor-modes-disturbing m))))

          ;; Does it help removing all these keys and those in
          ;; emulation-mode-map-alist?
          (with-temp-buffer
            (fundamental-mode)
            (make-local-variable 'emulation-mode-map-alists)
            (setq emulation-mode-map-alists nil)
            (dolist (m minor-modes-disturbing)
              (make-local-variable m)
              (funcall m 0))
            (dolist (tk tutorial-keys)
              (let* ((b (cadr tk))
                     (f (key-binding b)))
                (unless (eq (car tk) f)
                  (add-to-list 'still-failed-keys tk))))))

        ;; Those are in emulation-mode-map-alists
        (when cua-mode
          (add-to-list 'minor-modes-disturbing 'cua-mode))
        (when viper-mode
          (add-to-list 'minor-modes-disturbing 'viper-mode))

        (when (or minor-modes-disturbing still-failed-keys)
          (setq minor-modes-disturbing (sort minor-modes-disturbing 
'string<))
          (let (remove-minor
                (modes-disturbing (copy-seq minor-modes-disturbing))
                )
            ;; Ask the user if the possibly disturbing minor modes should
            ;; be disabled. This is to avoid confusing the user with the
            ;; different behaviour in the tutorial buffer when those modes
            ;; are disabled:
            (with-temp-buffer
              (insert "\nYou are using some minor modes (")
              (dolist (m modes-disturbing)
                (insert (format "%s" (car modes-disturbing)))
                (setq modes-disturbing (cdr modes-disturbing))
                (if (= 1 (length modes-disturbing))
                    (insert " and ")
                  (when modes-disturbing (insert ", "))))
              (insert
               ") which are overriding some default key bindings."
               "  The behavior of Emacs with these modes may"
               " not match what the tutorial teaches.\n\n"
               "Do you want to disable these modes when you are in the 
tutorial? ")
              (when still-failed-keys
                (insert "(Unfortunately in your case some key bindings"
                        " will still be overriden."
                        " You get more information about this later.)\n\n"))
              (insert
               "(y-or-n)"
               )
              (fill-region (point-min) (point-max))
              (let ((use-dialog-box nil))
                (setq remove-minor
                      (y-or-n-p (format "%s " (buffer-substring
                                               (point-min)
                                               (- (point-max) 8)))))))
            (if remove-minor
                (progn
                  (make-local-variable 'emulation-mode-map-alists)
                  (setq emulation-mode-map-alists nil)
                  (setq minor-modes-disturbing (delete 'cua-mode 
minor-modes-disturbing))
                  (setq minor-modes-disturbing (delete 'viper-mode 
minor-modes-disturbing))
                  (dolist (m minor-modes-disturbing)
                    (make-local-variable m)
                    ;; (set m nil) Better call the minor mode function
                    ;; according to RMS:
                    (funcall m 0)
                    )
                  (message "Disabled those minor modes for the tutorial 
only."))
              (message
               "Please note that the tutorial may not work with this 
choice.")
              )
            (when (or still-failed-keys
                      (not remove-minor))
              (forward-line)
              (let ((start (point)))
                (insert "
 NOTICE: One of the main purposes of the tutorial is that You
 should be able to learn some important Emacs default key
 bindings.  However when you run the tutorial now the following
 key bindings have been changed from default:\n\n")

                (let ((frm "   %-14s %-26s %s\n"))
                  (insert (format frm "KEY SEQUENCE" "DEFAULT BINDING" 
"CURRENT BINDING"))
                  (dolist (tk tutorial-keys)
                    (let* ((d (car tk))
                           (k (cadr tk))
                           (f (key-binding k)))
                      (unless (eq (car tk) f)
                        (insert (format frm (key-description k) d f))))))

                (insert "\n")
                (put-text-property start (point)
                                   'face
                                   (list :background "yellow")))

              (setq point-after-message (point))

              (goto-char (point-min))
              (set-buffer-modified-p nil)))))



      (goto-char (point-min))
      (search-forward "\n<<")
      (beginning-of-line)
      ;; Convert the <<...>> line to the proper [...] line,
      ;; or just delete the <<...>> line if a [...] line follows.
      (cond ((save-excursion
           (forward-line 1)
           (looking-at "\\["))
         (delete-region (point) (progn (forward-line 1) (point))))
        ((looking-at "<<Blank lines inserted.*>>")
         (replace-match "[Middle of page left blank for didactic 
purposes.   Text continues below]"))
        (t
         (looking-at "<<")
         (replace-match "[")
         (search-forward ">>")
         (replace-match "]")))
      (beginning-of-line)
      (message "")(sit-for 0) ;; Shrinks mini-buffer window
      (let ((n (- (window-height (selected-window))
          (count-lines (point-min) (point))
          6
          ;;(/ (count-lines (point-min) point-after-message) 2)
                  )))
    (if (< n 8)
        (progn
          ;; For a short gap, we don't need the [...] line,
          ;; so delete it.
          (delete-region (point) (progn (end-of-line) (point)))
          (newline n))
      ;; Some people get confused by the large gap.
      (newline (/ n 2))

      ;; Skip the [...] line (don't delete it).
      (forward-line 1)
      (newline (- n (/ n 2)))))
      (goto-char (point-min))
      (setq buffer-undo-list nil)
      (set-buffer-modified-p nil))))

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: Patch to remove minor modes in tutorial
  2006-07-01  0:38                     ` Lennart Borgman
@ 2006-07-01 23:55                       ` Richard Stallman
  2006-07-02  8:54                         ` Lennart Borgman
  0 siblings, 1 reply; 29+ messages in thread
From: Richard Stallman @ 2006-07-01 23:55 UTC (permalink / raw)
  Cc: ihs_4664, storm, emacs-devel

    - It asks the user if the disturbing key bindings should be removed.

As Kim pointed out, it should not ask.  And it probably should not
turn off the modes, either.  It should just display a warning.

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: Patch to remove minor modes in tutorial
  2006-07-01 23:55                       ` Richard Stallman
@ 2006-07-02  8:54                         ` Lennart Borgman
  2006-07-02 22:30                           ` Richard Stallman
  0 siblings, 1 reply; 29+ messages in thread
From: Lennart Borgman @ 2006-07-02  8:54 UTC (permalink / raw)
  Cc: ihs_4664, emacs-devel, storm

Richard Stallman wrote:
>     - It asks the user if the disturbing key bindings should be removed.
>
> As Kim pointed out, it should not ask.  And it probably should not
> turn off the modes, either.  It should just display a warning.
>   
Here is a new version where the question is still there but it is easy 
to turn off to test wether it feels right with the question or not. Just 
look for ask-user in the code.

I have also tried to take care of remapped functions.



(defun help-with-tutorial (&optional arg)
  "Select the Emacs learn-by-doing tutorial.
If there is a tutorial version written in the language
of the selected language environment, that version is used.
If there's no tutorial in that language, `TUTORIAL' is selected.
With ARG, you are asked to choose which language."
  (interactive "P")
  (let ((lang (if arg
                  (let ((minibuffer-setup-hook minibuffer-setup-hook))
                    (add-hook 'minibuffer-setup-hook
                              'minibuffer-completion-help)
                    (read-language-name 'tutorial "Language: " "English"))
        (if (get-language-info current-language-environment 'tutorial)
            current-language-environment
          "English")))
    file filename
        (point-after-message 1))
    (setq filename (get-language-info lang 'tutorial))
    (setq file (expand-file-name (concat "~/" filename)))
    (delete-other-windows)
    (if (get-file-buffer file)
    (switch-to-buffer (get-file-buffer file))
      (switch-to-buffer (create-file-buffer file))
      (setq buffer-file-name file)
      (setq default-directory (expand-file-name "~/"))
      (setq buffer-auto-save-file-name nil)
      (insert-file-contents (expand-file-name filename data-directory))
      (setq buffer-file-name nil)
      (hack-local-variables)


      ;; Check if there are key bindings or minor modes that may disturb
      ;; the tutorial. If so show them to the user and ask if they should
      ;; be disabled in the tutorial buffer.
      (let (minor-modes-added
            minor-modes
            minor-modes-disturbing
            other-disturbed-keys
            unknown
            (tutorial-keys
             '(
               (save-buffers-kill-emacs [(control ?x)(control ?c)])


               ;; * SUMMARY
               (scroll-up [(control ?v)])
               (scroll-down [(meta ?v)])
               (recenter [(control ?l)])


               ;; * BASIC CURSOR CONTROL
               (forward-char [(control ?f)])
               (backward-char [(control ?b)])

               (forward-word [(meta ?f)])
               (backward-word [(meta ?b)])

               (next-line [(control ?n)])
               (previous-line [(control ?p)])

               (move-beginning-of-line [(control ?a)])
               (move-end-of-line [(control ?e)])

               (backward-sentence [(meta ?a)])
               (forward-sentence [(meta ?e)])


               (beginning-of-buffer [(meta ?<)])
               (end-of-buffer [(meta ?>)])

               (universal-argument [(control ?u)])


               ;; * WHEN EMACS IS HUNG
               (keyboard-quit [(control ?g)])


               ;; * DISABLED COMMANDS
               (downcase-region [(control ?x)(control ?l)])


               ;; * WINDOWS
               (delete-other-windows [(control ?x) ?1])
               ;; C-u 0 C-l
               ;; Type CONTROL-h k CONTROL-f.


               ;; * INSERTING AND DELETING
               ;; C-u 8 * to insert ********.

               (delete-backward-char [backspace])
               (delete-char [(control ?d)])

               (backward-kill-word [(meta backspace)])
               (kill-word [(meta ?d)])

               (kill-line [(control ?k)])
               (kill-sentence [(meta ?k)])

               ;; You can also kill any part of the text with one 
uniform method.  Move
               (set-mark-command [(control ?@)])
               (set-mark-command [(control ? )])
               (kill-region [(control ?w)])
               (yank [(control ?y)])
               (yank-pop [(meta ?y)])


               ;; * UNDO
               (advertised-undo [(control ?x) ?u])
               (advertised-undo [(control ?x) ?u])


               ;; * FILES
               (find-file [(control ?x)(control ?f)])
               (save-buffer [(control ?x)(control ?s)])


               ;; * BUFFERS
               (list-buffers [(control ?x)(control ?b)])
               (switch-to-buffer [(control ?x) ?b])
               (save-some-buffers [(control ?x) ?s])


               ;; * EXTENDING THE COMMAND SET
               ;; C-x    Character eXtend.  Followed by one character.
               (execute-extended-command [(meta ?x)])

               ;; C-x C-f        Find file
               ;; C-x C-s        Save file
               ;; C-x s        Save some buffers
               ;; C-x C-b        List buffers
               ;; C-x b        Switch buffer
               ;; C-x C-c        Quit Emacs
               ;; C-x 1        Delete all but one window
               ;; C-x u        Undo


               ;; * MODE LINE
               (describe-mode [(control ?h) ?m])

               (set-fill-column [(control ?x) ?f])
               (fill-paragraph [(meta ?q)])


               ;; * SEARCHING
               (isearch-forward [(control ?s)])
               (isearch-backward [(control ?r)])


               ;; * MULTIPLE WINDOWS
               (split-window-vertically [(control ?x) ?2])
               (scroll-other-window [(control meta ?v)])
               ;; (list "<ESC> C-v" 'scroll-other-window [escape 
(control-v)])
               (other-window [(control ?x) ?o])
               (find-file-other-window [(control ?x) ?4 (control ?f)])


               ;; * RECURSIVE EDITING LEVELS
               ;;(list "<ESC> <ESC> <ESC>" 'keyboard-escape-quit [escape 
escape escape])


               ;; * GETTING MORE HELP
               ;; The most basic HELP feature is C-h c
               (describe-key-briefly [(control ?h) ?c])
               (describe-key [(control ?h) ?k])


               ;; * MORE FEATURES
               ;; F10


               ;; * CONCLUSION
               (iconify-or-deiconify-frame [(control ?z)])
               )
             )
            failed-keys
            still-failed-keys
            )

        (dolist (m minor-mode-list)
          (let ((fmode (or (get m :minor-mode-function) m)))
            (when (and (boundp m) (symbol-value m)
                       (fboundp fmode)
                       ;; Some minor modes have no bindings in the keymaps
                       ;; so ignore them:
                       (condition-case err
                           (progn
                             (unless
                                 (equal '(keymap)
                                        (symbol-value
                                         (read (concat (symbol-name m) 
"-map"))))
                               t))
                         (error nil)))
              (add-to-list 'minor-modes m))))
        (dolist (m minor-mode-alist)
          (add-to-list 'minor-modes (car m)))
        (dolist (m minor-modes)
          (when (symbol-value m)
            (add-to-list 'minor-modes-added m)))

        ;; Minor modes that are on by default (ie when starting with
        ;; "emacs -Q"):
        (dolist (m '(auto-compression-mode
                     blink-cursor-mode
                     encoded-kbd-mode
                     file-name-shadow-mode
                     font-lock-mode
                     global-font-lock-mode
                     line-number-mode
                     menu-bar-mode
                     mouse-wheel-mode
                     tool-bar-mode
                     tooltip-mode
                     unify-8859-on-encoding-mode
                     utf-translate-cjk-mode))
          (setq minor-modes-added (delete m minor-modes-added)))

        ;; What default key bindings used in the tutorial are
        ;; disturbed?
        (let ((initial-failing-keys))
          (with-temp-buffer
            (fundamental-mode)
            (dolist (tk tutorial-keys)
              (let* ((key (cadr tk))
                     (def-fun (car tk))
                     (rem-fun (command-remapping def-fun))
                     (key-fun (key-binding key))
                     (cp-tk (copy-sequence tk)))
                (unless (or (eq def-fun key-fun)
                            (eq rem-fun key-fun))
                  (add-to-list 'failed-keys tk)
                  (add-to-list 'initial-failing-keys cp-tk)))))

          ;; Which minor modes are disturbing the key bindings above?
          (dolist (m minor-modes-added)
            (let ((m-failing-keys))
              (with-temp-buffer
                (fundamental-mode)
                (make-local-variable m)
                (funcall m 0)
                (dolist (tk tutorial-keys)
                  (let* ((key (cadr tk))
                         (def-fun (car tk))
                         (rem-fun (command-remapping def-fun))
                         (key-fun (key-binding key))
                         (cp-tk (copy-sequence tk)))
                    (unless (or (eq def-fun key-fun)
                                (eq rem-fun key-fun))
                      ;;(setq cp-tk (cons key-fun cp-tk))
                      (add-to-list 'm-failing-keys cp-tk)))))
              (unless (equal m-failing-keys initial-failing-keys)
                (add-to-list 'minor-modes-disturbing m))))

          ;; Does it help removing all these keys and those in
          ;; emulation-mode-map-alist?
          (with-temp-buffer
            (fundamental-mode)
            (make-local-variable 'emulation-mode-map-alists)
            (setq emulation-mode-map-alists nil)
            (dolist (m minor-modes-disturbing)
              (make-local-variable m)
              (funcall m 0))
            (dolist (tk tutorial-keys)
              (let* ((key (cadr tk))
                     (def-fun (car tk))
                     (rem-fun (command-remapping def-fun))
                     (key-fun (key-binding key)))
                (unless (or (eq def-fun key-fun)
                            (eq rem-fun key-fun))
                  (add-to-list 'still-failed-keys tk)))))

        ;; Those are in emulation-mode-map-alists
        (when cua-mode
          (add-to-list 'minor-modes-disturbing 'cua-mode))
        (when viper-mode
          (add-to-list 'minor-modes-disturbing 'viper-mode))

        (when (or minor-modes-disturbing still-failed-keys)
          (setq minor-modes-disturbing (sort minor-modes-disturbing 
'string<))
          (let (remove-minor
                (ask-user t)
                (modes-disturbing (copy-seq minor-modes-disturbing))
                )
            (when ask-user
              ;; Ask the user if the possibly disturbing minor modes should
              ;; be disabled. This is to avoid confusing the user with the
              ;; different behaviour in the tutorial buffer when those modes
              ;; are disabled:
              (with-temp-buffer
                (insert "\nYou are using some minor modes (")
                (dolist (m modes-disturbing)
                  (insert (format "%s" (car modes-disturbing)))
                  (setq modes-disturbing (cdr modes-disturbing))
                  (if (= 1 (length modes-disturbing))
                      (insert " and ")
                    (when modes-disturbing (insert ", "))))
                (insert
                 ") which are overriding some default key bindings."
                 "  The behavior of Emacs with these modes may"
                 " not match what the tutorial teaches.\n\n"
                 "Do you want to disable these modes when you are in the 
tutorial? ")
                (when still-failed-keys
                  (insert "(Unfortunately in your case some key bindings"
                          " will still be overriden."
                          " You get more information about this 
later.)\n\n"))
                (insert
                 "(y-or-n)"
                 )
                (fill-region (point-min) (point-max))
                (let ((use-dialog-box nil))
                  (setq remove-minor
                        (y-or-n-p (format "%s " (buffer-substring
                                                 (point-min)
                                                 (- (point-max) 8))))))))
            (message "") ;; Shrinks mini-buffer window
            (if remove-minor
                (progn
                  (make-local-variable 'emulation-mode-map-alists)
                  (setq emulation-mode-map-alists nil)
                  (setq minor-modes-disturbing (delete 'cua-mode 
minor-modes-disturbing))
                  (setq minor-modes-disturbing (delete 'viper-mode 
minor-modes-disturbing))
                  (dolist (m minor-modes-disturbing)
                    (make-local-variable m)
                    ;; (set m nil) Better call the minor mode function
                    ;; according to RMS:
                    (funcall m 0)
                    )
                  (message "Disabled those minor modes for the tutorial 
only."))
              (when ask-user
                (message
                 "Please note that the tutorial may not work with this 
choice."))
              )
            (when (or still-failed-keys
                      (not remove-minor))
              (forward-line)
              (let ((start (point)))
                (cond
                 (remove-minor
                  (insert "
 NOTICE: One of the main purposes of the tutorial is that You
 should be able to learn some important Emacs default key
 bindings.  Even though you agreed to turn off minor modes with
 key bindings conflicting with the tutorial there are
 unfortunately still some conflicting key bindings left.  Those
 are probably set in your initialization files (~/.emacs etc).
 The folloing key bindings have still values that are changed
 from Emacs default:\n\n"
                          ))
                 ((not remove-minor)
                  (insert "
 NOTICE: One of the main purposes of the tutorial is that You
 should be able to learn some important Emacs default key
 bindings.  However it was found that when you started the
 tutorial the following key bindings had been changed from
 Emacs default:\n\n"
                          ))
                 (t
                  (insert "
 INTERNAL ERROR! There was an internal error when starting the
 tutorial.\n\n"
                          ))
                 )
                (let ((frm "   %-14s %-26s %-18s %s\n")
                      (keys (if remove-minor still-failed-keys 
initial-failing-keys)))
                  (insert (format frm "KEY SEQUENCE" "DEFAULT BINDING" 
"USE NOW" "CURRENT BINDING"))
                  (dolist (tk keys)
                    (let* ((def-fun (car tk))
                           (key (cadr tk))
                           (rem-fun (command-remapping def-fun))
                           (use-key "")
                           (key-txt (key-description key))
                           (key-fun (key-binding key)))
                      (unless (eq def-fun key-fun)
                        (if rem-fun
                          (progn
                            (if (eq (key-binding key) rem-fun)
                                (setq use-key "Use same")
                              (let ((where (where-is-internal rem-fun)))
                                (when where
                                  (setq use-key (key-description (car 
where)))))))
                          (let ((where (where-is-internal def-fun)))
                            (when where
                              (setq use-key (key-description (car 
where))))))
                        (insert (format frm key-txt def-fun use-key 
(format "%s: %s" key-txt key-fun)))))))

                (insert "
 Please understand that it is quite ok to change key bindings in
 Emacs, but the tutorial may not work when you do that.\n\n"
                        )
                (put-text-property start (point)
                                   'face
                                   ;;'font-lock-warning-face
                                   (list :background "yellow"
                                         :foreground "#c00")
                                   )))

              (setq point-after-message (point))

              (goto-char (point-min))
              (set-buffer-modified-p nil)))))



      (goto-char (point-min))
      (search-forward "\n<<")
      (beginning-of-line)
      ;; Convert the <<...>> line to the proper [...] line,
      ;; or just delete the <<...>> line if a [...] line follows.
      (cond ((save-excursion
           (forward-line 1)
           (looking-at "\\["))
         (delete-region (point) (progn (forward-line 1) (point))))
        ((looking-at "<<Blank lines inserted.*>>")
         (replace-match "[Middle of page left blank for didactic 
purposes.   Text continues below]"))
        (t
         (looking-at "<<")
         (replace-match "[")
         (search-forward ">>")
         (replace-match "]")))
      (beginning-of-line)
      (let ((n (- (window-height (selected-window))
          (count-lines (point-min) (point))
          6)))
    (if (< n 8)
        (progn
          ;; For a short gap, we don't need the [...] line,
          ;; so delete it.
          (delete-region (point) (progn (end-of-line) (point)))
          (newline n))
      ;; Some people get confused by the large gap.
      (newline (/ n 2))

      ;; Skip the [...] line (don't delete it).
      (forward-line 1)
      (newline (- n (/ n 2)))))
      (goto-char (point-min))
      (setq buffer-undo-list nil)
      (set-buffer-modified-p nil))))

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: Patch to remove minor modes in tutorial
  2006-07-02  8:54                         ` Lennart Borgman
@ 2006-07-02 22:30                           ` Richard Stallman
  2006-07-07  0:01                             ` Lennart Borgman
  0 siblings, 1 reply; 29+ messages in thread
From: Richard Stallman @ 2006-07-02 22:30 UTC (permalink / raw)
  Cc: emacs-devel

Please delete the ask-user code, and also the remove-minor code.  I am
convinced that we don't want to do either of those things.

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: Patch to remove minor modes in tutorial
  2006-07-02 22:30                           ` Richard Stallman
@ 2006-07-07  0:01                             ` Lennart Borgman
  2006-07-07 19:31                               ` Richard Stallman
                                                 ` (2 more replies)
  0 siblings, 3 replies; 29+ messages in thread
From: Lennart Borgman @ 2006-07-07  0:01 UTC (permalink / raw)
  Cc: emacs-devel

Richard Stallman wrote:
> Please delete the ask-user code, and also the remove-minor code.  I am
> convinced that we don't want to do either of those things.
>   
Here is a new version of help-with-tutorial then. I have added some 
information instead that could be useful:

(defun help-describe-nonstandard-key(value)
  (let ((maps (current-active-maps t)))
    (with-output-to-temp-buffer (help-buffer)
      (help-setup-xref (list #'help-describe-nonstandard-key value)
                       (interactive-p))
      (with-current-buffer (help-buffer)
        (insert "Default key binding has been changed:\n\n")
        (let ((inhibit-read-only t))
          (cond
           ((eq (car value) 'cua-mode)
            (insert "You are using `cua-mode'."
                    "  In this mode the C-c prefix is rebound so"
                    " that it copies the region if it is active."
                    "  If the region is not active then C-c will"
                    " work as it normally does in Emacs."))
           ((eq (car value) 'current-binding)
            (let ((cb    (nth 1 value))
                  (db    (nth 2 value))
                  (key   (nth 3 value))
                  (where (nth 4 value))
                  map
                  mapsym)
              (while maps
                (let* ((m (car maps))
                       (mb (lookup-key m key t)))
                  (setq maps (cdr maps))
                  (when (eq mb cb)
                    (setq map m)
                    (setq maps nil))))
              (when map
                (if (eq map global-map)
                    (setq mapsym 'global-map)
                  (mapatoms (lambda (s)
                              (when (and (boundp s)
                                         (keymapp (symbol-value s)))
                                (unless (eq s 'map)
                                  (when (equal map (symbol-value s))
                                    (when (member map (current-active-maps))
                                      (setq mapsym s)))))))))
              (insert "Emacs default binding for the key "
                      (key-description key)
                      " is the function `")
              (insert (format "%s" db))
              (insert "'.  This key has however been rebound to the 
function `")
              (insert (format "%s" cb))
              (insert "'.")
              (when mapsym
                (insert "  This binding is in the keymap variable `")
                (insert (format "%s" mapsym))
                (insert "'."))
              (when where
                (insert "\n\nYou can use the key "
                        where
                        " to get the function `"
                        (format "%s" db)
                        "'."))
              ))))
        (fill-region (point-min)(point))
        (print-help-return-message)))))

(defun help-with-tutorial (&optional arg)
  "Select the Emacs learn-by-doing tutorial.
If there is a tutorial version written in the language
of the selected language environment, that version is used.
If there's no tutorial in that language, `TUTORIAL' is selected.
With ARG, you are asked to choose which language."
  (interactive "P")
  (let ((lang (if arg
                  (let ((minibuffer-setup-hook minibuffer-setup-hook))
                    (add-hook 'minibuffer-setup-hook
                              'minibuffer-completion-help)
                    (read-language-name 'tutorial "Language: " "English"))
        (if (get-language-info current-language-environment 'tutorial)
            current-language-environment
          "English")))
    file filename
        (point-after-message 1))
    (setq filename (get-language-info lang 'tutorial))
    (setq file (expand-file-name (concat "~/" filename)))
    (delete-other-windows)
    (if (get-file-buffer file)
    (switch-to-buffer (get-file-buffer file))
      (switch-to-buffer (create-file-buffer file))
      (setq buffer-file-name file)
      (setq default-directory (expand-file-name "~/"))
      (setq buffer-auto-save-file-name nil)
      (insert-file-contents (expand-file-name filename data-directory))
      (setq buffer-file-name nil)
      (hack-local-variables)


      ;; Check if there are key bindings that may disturb the
      ;; tutorial. If so tell the user.
      (let (initial-bad-keys)
        (with-temp-buffer
          (insert-file (locate-library "bindings.el"))
          (let (expr
                key
                def-fun
                def-fun-txt
                rem-fun
                key-fun
                where
                remark
                )
            (while (condition-case err
                       (setq expr (read (current-buffer)))
                     (error nil))
              (cond ((and (eq (nth 0 expr) 'define-key)
                          (eq (nth 1 expr) 'global-map))
                     (setq key (nth 2 expr))
                     (setq def-fun (nth 3 expr)))
                    ((eq (nth 0 expr) 'global-set-key)
                     (setq key (nth 1 expr))
                     (setq def-fun (nth 2 expr)))
                    (t
                     (setq key nil)))
              (when key
                (assert (eq (nth 0 def-fun) 'quote))
                (setq def-fun (nth 1 def-fun))
                (setq def-fun-txt (format "%s" def-fun))
                (setq rem-fun (command-remapping def-fun))
                (setq key-fun (key-binding key))
                (setq where (where-is-internal (if rem-fun rem-fun 
def-fun)))
                (if where
                    (setq where (key-description (car where)))
                  (setq where ""))
                (setq remark nil)
                (unless
                    (cond ( (eq key-fun def-fun)
                            t)
                          ( (eq key-fun (command-remapping def-fun))
                            (setq remark (list "Remapped" nil))
                            t)
                          ;; cua-mode special:
                          ( (and cua-mode
                                 (eq def-fun 'mode-specific-command-prefix)
                                 (equal key-fun
                                        '(keymap (timeout . 
copy-region-as-kill))))
                            (setq remark (list "cua-mode replacement" 
'cua-mode))
                            (setq def-fun-txt "\"C-c prefix\"")
                            (setq where "Same key")
                            nil)
                          ;; The strange handling of C-delete and
                          ;; C-backspace:
                          ( (when normal-erase-is-backspace
                              (or (and (equal key [C-delete])
                                       (equal key-fun 'kill-word))
                                  (and (equal key [C-backspace])
                                       (equal key-fun 
'backward-kill-word))))
                            t)
                          ( t
                            (setq remark
                                  (list "More info" 'current-binding
                                        key-fun def-fun key where))
                            nil))
                  (add-to-list 'initial-bad-keys
                               (list def-fun key def-fun-txt where 
remark)))))))

        (when initial-bad-keys
          (forward-line)
          (let ((start (point))
                fun-buttons
                remark-buttons)
            (insert "
 NOTICE: One of the main purposes of the tutorial is that You
 should be able to learn some important Emacs default key
 bindings.  However when you started the tutorial the following
 key bindings had been changed from Emacs default:\n\n"
                    )
            (let ((frm "   %-9s %-25s %-11s %s\n")
                  (keys initial-bad-keys))
              (insert (format frm "KEY" "DEFAULT BINDING" "IS NOW ON" 
"REMARK"))
              (dolist (tk keys)
                (let* ((def-fun     (nth 0 tk))
                       (key         (nth 1 tk))
                       (def-fun-txt (nth 2 tk))
                       (where       (nth 3 tk))
                       (remark      (nth 4 tk))
                       (rem-fun (command-remapping def-fun))
                       (key-txt (key-description key))
                       (key-fun (key-binding key)))
                  (unless (eq def-fun key-fun)
                    (insert (format "   %-9s " key-txt))
                    (let ((beg (point))
                          end
                          len)
                      (insert def-fun-txt)
                      (setq end (point))
                      (setq len (- 25 (length def-fun-txt)))
                      (when (>= 0 len) (setq len 1))
                      (insert (make-string len ? ))
                      (add-to-list 'fun-buttons (list beg end def-fun))
                      (insert (format " %-11s " where))
                      (setq beg (point))
                      (insert (format "%s" (car remark)))
                      (setq end (point))
                      (add-to-list 'remark-buttons (list beg end (cdr 
remark)))
                      (insert "\n")
                      )))))

            (insert "
 Please understand that it is ok to change key bindings, but the
 tutorial may not work correctly. (See also "  )
            (setq link-beg (point))
            (insert "Key Binding Conventions")
            (setq link-end (point))
            (insert ".)\n\n")
            (put-text-property start (point)
                               'face
                               ;;'font-lock-warning-face
                               (list :background "yellow"
                                     :foreground "#c00")
                               )
            (dolist (b remark-buttons)
              (let ((beg (nth 0 b))
                     (end (nth 1 b))
                     (remark (nth 2 b)))
                (make-text-button beg end
                                  'action
                                  (lambda(b) (interactive)
                                    (let ((value (button-get b 'value)))
                                      (help-describe-nonstandard-key 
value)))
                                  'value remark
                                  'follow-link t
                                  'face '(:inherit link
                                                   :background "yellow"))))
            (dolist (b fun-buttons)
              (let ((beg (nth 0 b))
                    (end (nth 1 b))
                    (fun (nth 2 b)))
                (make-text-button beg end
                                  'value fun
                                  'action
                                  (lambda(button) (interactive)
                                    (describe-function
                                     (button-get button 'value)))
                                  'follow-link t
                                  'face '(:inherit link
                                                   :background "yellow"))))
            (make-text-button link-beg link-end
                              'action
                              (lambda(button) (interactive)
                                (info "(elisp) Key Binding Conventions"))
                              'follow-link t
                              'face '(:inherit link
                                               :background "yellow")))))

      (setq point-after-message (point))

      (goto-char (point-min))
      (set-buffer-modified-p nil))

    (goto-char (point-min))
    (search-forward "\n<<")
    (beginning-of-line)
    ;; Convert the <<...>> line to the proper [...] line,
    ;; or just delete the <<...>> line if a [...] line follows.
    (cond ((save-excursion
             (forward-line 1)
             (looking-at "\\["))
           (delete-region (point) (progn (forward-line 1) (point))))
          ((looking-at "<<Blank lines inserted.*>>")
           (replace-match "[Middle of page left blank for didactic 
purposes.   Text continues below]"))
          (t
           (looking-at "<<")
           (replace-match "[")
           (search-forward ">>")
           (replace-match "]")))
    (beginning-of-line)
    (let ((n (- (window-height (selected-window))
                (count-lines (point-min) (point))
                6)))
      (if (< n 8)
          (progn
            ;; For a short gap, we don't need the [...] line,
            ;; so delete it.
            (delete-region (point) (progn (end-of-line) (point)))
            (newline n))
        ;; Some people get confused by the large gap.
        (newline (/ n 2))

        ;; Skip the [...] line (don't delete it).
        (forward-line 1)
        (newline (- n (/ n 2)))))
    (goto-char (point-min))
    (setq buffer-undo-list nil)
    (set-buffer-modified-p nil)))

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: Patch to remove minor modes in tutorial
  2006-07-07  0:01                             ` Lennart Borgman
@ 2006-07-07 19:31                               ` Richard Stallman
  2006-07-08  3:14                               ` Giorgos Keramidas
  2006-07-08 20:57                               ` Richard Stallman
  2 siblings, 0 replies; 29+ messages in thread
From: Richard Stallman @ 2006-07-07 19:31 UTC (permalink / raw)
  Cc: emacs-devel

Could you send the change log entry for this change?

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: Patch to remove minor modes in tutorial
  2006-07-07  0:01                             ` Lennart Borgman
  2006-07-07 19:31                               ` Richard Stallman
@ 2006-07-08  3:14                               ` Giorgos Keramidas
  2006-07-08 20:57                               ` Richard Stallman
  2 siblings, 0 replies; 29+ messages in thread
From: Giorgos Keramidas @ 2006-07-08  3:14 UTC (permalink / raw)
  Cc: emacs-devel

Lennart Borgman <lennart.borgman.073@student.lu.se> wrote:
> 
> Here is a new version of help-with-tutorial then. I have added some 
> information instead that could be useful:
> 
> (defun help-describe-nonstandard-key(value)
>  ...
>              (when map
>                (if (eq map global-map)
>                    (setq mapsym 'global-map)
>                  (mapatoms (lambda (s)
>                              (when (and (boundp s)
>                                         (keymapp (symbol-value s)))
>                                (unless (eq s 'map)
>                                  (when (equal map (symbol-value s))
>                                    (when (member map (current-active-maps))
>                                      (setq mapsym s)))))))))

Phew!  That was a long patch :)

Only a minor detail I noticed while trying to read it all:
Isn't

    (when condition
      (when condition2
        expr))

the same as:

    (when (and condition condition2)
      expr)

The nested (unless c (when c1 (when c2))) stuff is also probably
equivalent to:

    (when (and (not (eq s 'map))
               (equal map (symbol-value s))
               (member map (current-active-maps)))
      (setq mapsym s))

Then, there are also two (when c (when c2 ...)) expressions,
where we can save yet another nesting level:

    (when (and (boundp s)
               (keymapp (symbol-value s))
               (not (eq s 'map))
               (equal map (symbol-value s))
               (member map (current-active-maps)))
      (setq mapsym s))
               
unless I'm reading this in a very bogus manner :)

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: Patch to remove minor modes in tutorial
  2006-07-07  0:01                             ` Lennart Borgman
  2006-07-07 19:31                               ` Richard Stallman
  2006-07-08  3:14                               ` Giorgos Keramidas
@ 2006-07-08 20:57                               ` Richard Stallman
  2006-07-09  8:44                                 ` Lennart Borgman
  2006-07-17 16:12                                 ` Lennart Borgman
  2 siblings, 2 replies; 29+ messages in thread
From: Richard Stallman @ 2006-07-08 20:57 UTC (permalink / raw)
  Cc: emacs-devel

	       ((eq (car value) 'cua-mode)
		(insert "You are using `cua-mode'."

"You have enabled CUA mode" would be clearer.

			"  If the region is not active then C-c will"
			" work as it normally does in Emacs."))

Please stick to present tense except when present tense is incorrect.

     Please understand that it is ok to change key bindings, but the
     tutorial may not work correctly. (See also "  )

Change that to

     It is legitimate to change key bindings, but changed bindings 
     do not correspond to what the tutorial says.  (See also "  )


This code

      (let (initial-bad-keys)
        (with-temp-buffer
          (insert-file (locate-library "bindings.el"))
          (let (expr
                key
                def-fun
                def-fun-txt
                rem-fun
                key-fun
                where
                remark
                )
            (while (condition-case err
                       (setq expr (read (current-buffer)))
                     (error nil))
              (cond ((and (eq (nth 0 expr) 'define-key)
                          (eq (nth 1 expr) 'global-map))
                     (setq key (nth 2 expr))
                     (setq def-fun (nth 3 expr)))
                    ((eq (nth 0 expr) 'global-set-key)
                     (setq key (nth 1 expr))
                     (setq def-fun (nth 2 expr)))
                    (t
                     (setq key nil)))
              (when key
                (assert (eq (nth 0 def-fun) 'quote))
                (setq def-fun (nth 1 def-fun))
                (setq def-fun-txt (format "%s" def-fun))
                (setq rem-fun (command-remapping def-fun))
                (setq key-fun (key-binding key))
                (setq where (where-is-internal (if rem-fun rem-fun 
def-fun)))
                (if where
                    (setq where (key-description (car where)))
                  (setq where ""))
                (setq remark nil)
                (unless
                    (cond ( (eq key-fun def-fun)
		...

is awfully complex, and most of the job it does is irrelevant.  The
tutorial describes a small set of keys, perhaps 40.  I think this code
should not concern itself with keys that the tutorial does not teach.

It should simply have a list of those keys and their standard
bindings.  That way it would not need to read bindings.el.

(Not all the default bindings are in bindings.el, so this code won't
get them all.)

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: Patch to remove minor modes in tutorial
  2006-07-08 20:57                               ` Richard Stallman
@ 2006-07-09  8:44                                 ` Lennart Borgman
  2006-07-17 16:12                                 ` Lennart Borgman
  1 sibling, 0 replies; 29+ messages in thread
From: Lennart Borgman @ 2006-07-09  8:44 UTC (permalink / raw)
  Cc: emacs-devel

Richard Stallman wrote:
> 	       ((eq (car value) 'cua-mode)
> 		(insert "You are using `cua-mode'."
>
> "You have enabled CUA mode" would be clearer.
>
> 			"  If the region is not active then C-c will"
> 			" work as it normally does in Emacs."))
>
> Please stick to present tense except when present tense is incorrect.
>
>      Please understand that it is ok to change key bindings, but the
>      tutorial may not work correctly. (See also "  )
>
> Change that to
>
>      It is legitimate to change key bindings, but changed bindings 
>      do not correspond to what the tutorial says.  (See also "  )
>
>
> This code
>
>       (let (initial-bad-keys)
>         (with-temp-buffer
> ...
>                 (unless
>                     (cond ( (eq key-fun def-fun)
> 		...
>
> is awfully complex, and most of the job it does is irrelevant.  The
> tutorial describes a small set of keys, perhaps 40.  I think this code
> should not concern itself with keys that the tutorial does not teach.
>
> It should simply have a list of those keys and their standard
> bindings.  That way it would not need to read bindings.el.
>
> (Not all the default bindings are in bindings.el, so this code won't
> get them all.)
>   
I will fix these issues in a couple of days.

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: Patch to remove minor modes in tutorial
  2006-07-08 20:57                               ` Richard Stallman
  2006-07-09  8:44                                 ` Lennart Borgman
@ 2006-07-17 16:12                                 ` Lennart Borgman
  2006-07-17 17:32                                   ` Lennart Borgman
  1 sibling, 1 reply; 29+ messages in thread
From: Lennart Borgman @ 2006-07-17 16:12 UTC (permalink / raw)
  Cc: emacs-devel

[-- Attachment #1: Type: text/plain, Size: 1109 bytes --]

Richard Stallman wrote:
> "You have enabled CUA mode" would be clearer.
>
>
>   
Done.
> Change that to
>
>      It is legitimate to change key bindings, but changed bindings 
>      do not correspond to what the tutorial says.  (See also "  )
>   
Done.
> It should simply have a list of those keys and their standard
> bindings.  That way it would not need to read bindings.el.
>   
I changed it to that (again).

I send the changes both as a standalone file and a patch this time. I 
have added this:

- The tutorial buffer is no longer associated with a file. I believe 
that is better.
- The tutorial can easily be restarted. A check is made for changes.
- The tutorial window is searched for.
- If any of the key bindings mentioned in the tutorial is changed then a 
list with those changes
  are shown in a special area in the beginning of the tutorial buffer.
- This area is read-only and have a yellow background.
- I have tried to explain what has happened to the key bindings. There 
are links to the
  explanations.
- I have taken special care of cua-mode (and a little bit of viper-mode 
too).



[-- Attachment #2: help-tutorial5.el --]
[-- Type: text/plain, Size: 21492 bytes --]

(defun help--describe-nonstandard-key(value)
  (let ((maps (current-active-maps t)))
    (with-output-to-temp-buffer (help-buffer)
      (help-setup-xref (list #'help-describe-nonstandard-key value)
                       (interactive-p))
      (with-current-buffer (help-buffer)
        (insert "Emacs default key binding has been changed in your setup:\n\n")
        (let ((inhibit-read-only t))
          (cond
           ((eq (car value) 'cua-mode)
            (insert
             "You have enabled `cua-mode'.

When `cua-mode' is enabled, you can use C-z, C-x, C-c, and C-v to
undo, cut, copy, and paste in addition to the normal Emacs
bindings.  The C-x and C-c keys only do cut and copy when the
region is active, so in most cases, they do not conflict with the
normal function of these prefix keys.

If you really need to perform a command which starts with one of
the prefix keys even when the region is active, you have three
options:
- press the prefix key twice very quickly (within 0.2 seconds),
- press the prefix key and the following key within 0.2 seconds, or
- use the SHIFT key with the prefix key, i.e. C-S-x or C-S-c."))
           ((eq (car value) 'current-binding)
            (let ((cb    (nth 1 value))
                  (db    (nth 2 value))
                  (key   (nth 3 value))
                  (where (nth 4 value))
                  map
                  mapsym)
              ;; Try to find the map where the binding occurs
              (while maps
                (let* ((m (car maps))
                       (mb (lookup-key m key t)))
                  (setq maps (cdr maps))
                  (when (eq mb cb)
                    (setq map m)
                    (setq maps nil))))
              (when map
                (if (eq map global-map)
                    (setq mapsym 'global-map)
                  (mapatoms (lambda (s)
                              (when (and (boundp s)
                                         (keymapp (symbol-value s)))
                                (unless (eq s 'map)
                                  (when (equal map (symbol-value s))
                                    (when (member map (current-active-maps))
                                      (setq mapsym s)))))))))
              (insert "Emacs default binding for the key "
                      (key-description key)
                      " is the function `")
              (insert (format "%s" db))
              (insert "'.  "
                      "This key has however been rebound to the function `")
              (insert (format "%s" cb))
              (insert "'.")
              (when mapsym
                (insert "  This binding is in the keymap variable `")
                (insert (format "%s" mapsym))
                (insert "'."))
              (if (string= where "")
                  (unless (keymapp db)
                    (insert "\n\nYou can use M-x "
                            (format "%s" db)
                            " RET instead."))
                (insert "\n\nWith you current key bindings"
                        " you can use the key "
                        where
                        " to get the function `"
                        (format "%s" db)
                        "'."))
              ))))
        (fill-region (point-min)(point))
        (print-help-return-message)))))

;;;###autoload
(defun help-with-tutorial (&optional arg)
  "Select the Emacs learn-by-doing tutorial.
If there is a tutorial version written in the language
of the selected language environment, that version is used.
If there's no tutorial in that language, `TUTORIAL' is selected.
With ARG, you are asked to choose which language."
  (interactive "P")
  (let* ((lang (if arg
                   (let ((minibuffer-setup-hook minibuffer-setup-hook))
                     (add-hook 'minibuffer-setup-hook
                               'minibuffer-completion-help)
                     (read-language-name 'tutorial "Language: " "English"))
                 (if (get-language-info current-language-environment 'tutorial)
                     current-language-environment
                   "English")))
         (filename (get-language-info lang 'tutorial))
         (tut-buf-name (concat "TUTORIAL (" lang ")"))
         (old-tut-buf (get-buffer tut-buf-name))
         (old-tut-win (when old-tut-buf (get-buffer-window old-tut-buf t)))
         (old-tut-is-ok (when old-tut-buf
                          (not (buffer-modified-p old-tut-buf))))
         (point-after-message 1))
    (when old-tut-win
      (raise-frame
       (window-frame
        (select-window (get-buffer-window old-tut-buf t)))))
    (when (and old-tut-buf
               (not old-tut-is-ok))
      (setq old-tut-is-ok
            (not (y-or-n-p
                  "You have changed the Tutorial buffer.  Revert it? "))))
    (delete-other-windows)
    (if old-tut-is-ok
        (switch-to-buffer (get-buffer tut-buf-name))
      (switch-to-buffer (get-buffer-create tut-buf-name))
      (let ((inhibit-read-only t))
        (erase-buffer))
      (message "Preparing tutorial ...")(sit-for 0)

      (setq default-directory (expand-file-name "~/"))
      (setq buffer-auto-save-file-name nil)
      (insert-file-contents (expand-file-name filename data-directory))
      (hack-local-variables)


      ;; Check if there are key bindings that may disturb the
      ;; tutorial.  If so tell the user.
      (let* (changed-keys
             (suspend-emacs (if window-system
                                'iconify-or-deiconify-frame
                              'suspend-emacs))
             (default-keys
               '(
                 ;; These are not mentioned but are basic:
                 (ESC-prefix [27])
                 (Control-X-prefix [?\C-x])
                 (mode-specific-command-prefix [?\C-c])

                 (save-buffers-kill-emacs [?\C-x ?\C-c])


                 ;; * SUMMARY
                 (scroll-up [?\C-v])
                 (scroll-down [?\M-v])
                 (recenter [?\C-l])


                 ;; * BASIC CURSOR CONTROL
                 (forward-char [?\C-f])
                 (backward-char [?\C-b])

                 (forward-word [?\M-f])
                 (backward-word [?\M-b])

                 (next-line [?\C-n])
                 (previous-line [?\C-p])

                 (move-beginning-of-line [?\C-a])
                 (move-end-of-line [?\C-e])

                 (backward-sentence [?\M-a])
                 (forward-sentence [?\M-e])


                 (beginning-of-buffer [?\M-<])
                 (end-of-buffer [?\M->])

                 (universal-argument [?\C-u])


                 ;; * WHEN EMACS IS HUNG
                 (keyboard-quit [?\C-g])


                 ;; * DISABLED COMMANDS
                 (downcase-region [?\C-x ?\C-l])


                 ;; * WINDOWS
                 (delete-other-windows [?\C-x ?1])
                 ;; C-u 0 C-l
                 ;; Type CONTROL-h k CONTROL-f.


                 ;; * INSERTING AND DELETING
                 ;; C-u 8 * to insert ********.

                 (delete-backward-char [backspace])
                 (delete-char [?\C-d])

                 (backward-kill-word [(meta backspace)])
                 (kill-word [?\M-d])

                 (kill-line [?\C-k])
                 (kill-sentence [?\M-k])

                 (set-mark-command [?\C-@])
                 (set-mark-command [?\C- ])
                 (kill-region [?\C-w])
                 (yank [?\C-y])
                 (yank-pop [?\M-y])


                 ;; * UNDO
                 (advertised-undo [?\C-x ?u])
                 (advertised-undo [?\C-x ?u])


                 ;; * FILES
                 (find-file [?\C-x ?\C-f])
                 (save-buffer [?\C-x ?\C-s])


                 ;; * BUFFERS
                 (list-buffers [?\C-x ?\C-b])
                 (switch-to-buffer [?\C-x ?b])
                 (save-some-buffers [?\C-x ?s])


                 ;; * EXTENDING THE COMMAND SET
                 ;; C-x	Character eXtend.  Followed by one character.
                 (execute-extended-command [?\M-x])

                 ;; C-x C-f		Find file
                 ;; C-x C-s		Save file
                 ;; C-x s		Save some buffers
                 ;; C-x C-b		List buffers
                 ;; C-x b		Switch buffer
                 ;; C-x C-c		Quit Emacs
                 ;; C-x 1		Delete all but one window
                 ;; C-x u		Undo


                 ;; * MODE LINE
                 (describe-mode [?\C-h ?m])

                 (set-fill-column [?\C-x ?f])
                 (fill-paragraph [?\M-q])


                 ;; * SEARCHING
                 (isearch-forward [?\C-s])
                 (isearch-backward [?\C-r])


                 ;; * MULTIPLE WINDOWS
                 (split-window-vertically [?\C-x ?2])
                 (scroll-other-window [?\C-\M-v])
                 (other-window [?\C-x ?o])
                 (find-file-other-window [?\C-x ?4 ?\C-f])


                 ;; * RECURSIVE EDITING LEVELS
                 (keyboard-escape-quit [27 27 27])


                 ;; * GETTING MORE HELP
                 ;; The most basic HELP feature is C-h c
                 (describe-key-briefly [?\C-h ?c])
                 (describe-key [?\C-h ?k])


                 ;; * MORE FEATURES
                 ;; F10


                 ;; * CONCLUSION
                 (iconify-or-deiconify-frame [?\C-z])
                 ))
             (sort-keys
              (lambda(left right)
                (let ((x (append (cadr left)  nil))
                      (y (append (cadr right) nil)))
                  (while (and x y
                              (equal (car x) (car y)))
                    (setq x (cdr x))
                    (setq y (cdr y)))
                  (let ((cx (car x))
                        (cy (car y)))
                    (cond ((and (listp cx)
                                (listp cy))
                           (> (length cx)(length cy)))
                          ((listp cx)
                           nil)
                          ((listp cy)
                           t)
                          ((and (symbolp cx)
                                (symbolp cy))
                           (string< (symbol-name cy)
                                    (symbol-name cx)))
                          ((symbolp cx)
                           nil)
                          ((symbolp cy)
                           t)
                          (t
                           (> (car x)(car y))))))))
             (tab-map (let ((map (make-sparse-keymap)))
                        (define-key map [tab] 'forward-button)
                        (define-key map [(shift tab)] 'backward-button)
                        (define-key map [(meta tab)] 'backward-button)
                        map)))
        (setq default-keys (sort default-keys sort-keys))

        (let (expr
              key
              def-fun
              def-fun-txt
              rem-fun
              key-fun
              where
              remark
              )
          (dolist (kdf default-keys)
            (setq key     (nth 1 kdf))
            (setq def-fun (nth 0 kdf))
            (setq def-fun-txt (format "%s" def-fun))
            (setq rem-fun (command-remapping def-fun))
            (setq key-fun (key-binding key))
            (setq where (where-is-internal (if rem-fun rem-fun def-fun)))
            (if where
                (progn
                  (setq where (key-description (car where)))
                  (when (and (< 10 (length where))
                             (string= (substring where 0 (length "<menu-bar>"))
                                      "<menu-bar>"))
                    (setq where "The menus")))
              (setq where ""))
            (setq remark nil)
            (unless
                (cond ( (eq key-fun def-fun)
                        t)
                      ( (eq key-fun (command-remapping def-fun))
                        (setq remark (list "Remapped" nil))
                        t)
                      ;; cua-mode specials:
                      ( (and cua-mode
                             (or (and
                                  (equal key [?\C-v])
                                  (eq key-fun 'cua-paste))
                                 (and
                                  (equal key [?\C-z])
                                  (eq key-fun 'undo))))
                        (setq remark (list "cua-mode, more info" 'cua-mode))
                        nil)
                      ( (and cua-mode
                             (or
                              (and (eq def-fun 'ESC-prefix)
                                   (equal key-fun
                                          `(keymap
                                            (118 . cua-repeat-replace-region))))
                              (and (eq def-fun 'mode-specific-command-prefix)
                                   (equal key-fun
                                          '(keymap
                                            (timeout . copy-region-as-kill))))
                              (and (eq def-fun 'Control-X-prefix)
                                   (equal key-fun
                                          '(keymap (timeout . kill-region))))))
                        (setq remark (list "cua-mode replacement" 'cua-mode))
                        (cond
                         ((eq def-fun 'mode-specific-command-prefix)
                          (setq def-fun-txt "\"C-c prefix\""))
                         ((eq def-fun 'Control-X-prefix)
                          (setq def-fun-txt "\"C-x prefix\""))
                         ((eq def-fun 'ESC-prefix)
                          (setq def-fun-txt "\"ESC prefix\"")))
                        (setq where "Same key")
                        nil)
                      ;; viper-mode specials:
                      ( (and viper-mode
                             (eq viper-current-state 'vi-state)
                             (or (and (eq def-fun 'isearch-forward)
                                      (eq key-fun 'viper-isearch-forward))
                                 (and (eq def-fun 'isearch-backward)
                                      (eq key-fun 'viper-isearch-backward))))
                        t)
                      ;; The strange handling of C-delete and
                      ;; C-backspace:
                      ( (when normal-erase-is-backspace
                          (or (and (equal key [C-delete])
                                   (equal key-fun 'kill-word))
                              (and (equal key [C-backspace])
                                   (equal key-fun 'backward-kill-word))))
                        t)
                      ( t
                        (setq remark
                              (list "more info" 'current-binding
                                    key-fun def-fun key where))
                        nil))
              (add-to-list 'changed-keys
                           (list key def-fun def-fun-txt where remark)))))

        (message "")(sit-for 0)
        (when changed-keys
          (forward-line)
          (let ((start (point))
                end)
            (insert "
 NOTICE: One of the main purposes of the tutorial is that You should
 be able to learn some important Emacs default key bindings.  However
 when you started the tutorial the following key bindings used in the
 tutorial had been changed from Emacs default:\n\n" )
            (let ((frm "   %-9s %-27s %-11s %s\n"))
              (insert (format frm "KEY" "DEFAULT BINDING" "IS NOW ON" "REMARK")))
            (dolist (tk changed-keys)
              (let* ((def-fun     (nth 1 tk))
                     (key         (nth 0 tk))
                     (def-fun-txt (nth 2 tk))
                     (where       (nth 3 tk))
                     (remark      (nth 4 tk))
                     (rem-fun (command-remapping def-fun))
                     (key-txt (key-description key))
                     (key-fun (key-binding key))
                     tot-len)
                (unless (eq def-fun key-fun)
                  (insert "   " key-txt " ")
                  (setq tot-len (length key-txt))
                  (when (> 9 tot-len)
                    (insert (make-string (- 9 tot-len) ? ))
                    (setq tot-len 9))
                  (insert-button def-fun-txt
                                 'value def-fun
                                 'action
                                 (lambda(button) (interactive)
                                   (describe-function
                                    (button-get button 'value)))
                                 'follow-link t
                                 'read-only t
                                 'face '(:inherit link
                                                  :background "yellow"))
                  (setq tot-len (+ tot-len (length def-fun-txt)))
                  (when (> 36 tot-len)
                    (insert (make-string (- 36 tot-len) ? )))
                  (when (listp where)
                    (setq where "list"))
                  (insert (format " %-11s " where))
                  (insert-button (car remark)
                                 'action
                                 (lambda(b) (interactive)
                                   (let ((value (button-get b 'value)))
                                     (help--describe-nonstandard-key value)))
                                 'value (cdr remark)
                                 'follow-link t
                                 'face '(:inherit link
                                                  :background "yellow"))
                  (insert "\n"))))

            (when (and (boundp 'viper-mode)
                       viper-mode)
              (cond
               ((eq viper-current-state 'emacs-state)
                (insert "
   You have enabled viper mode, but in the tutorial buffer viper
   mode is currently turned off."))
               (t
                (insert "
   You have enabled viper mode. Some Emacs default key bindings
   will be unavailable. This is dependent on the state Viper is
   in.")))
              (insert "\n   If you want to learn viper keys please see the ")
              (insert-button "viper manual"
                             'action
                             (lambda(button) (interactive)
                               (info-other-window "(viper)")
                               (message "Type C-x 0 to close the new window"))
                             'follow-link t
                             'read-only t
                             'face '(:inherit link
                                              :background "yellow"))
              (insert ".\n"))

            (insert "
 It is legitimate to change key bindings, but changed bindings do not
 correspond to what the tutorial says.  (See also " )
            (insert-button "Key Binding Conventions"
                           'action
                           (lambda(button) (interactive)
                             (info-other-window
                              "(elisp) Key Binding Conventions")
                             (message "Type C-x 0 to close the new window"))
                           'follow-link t
                           'read-only t
                           'face '(:inherit link
                                            :background "yellow"))
            (insert ".)\n\n")
            (setq end (point))
            (put-text-property start end
                               'face
                               ;;'font-lock-warning-face
                               (list :background "yellow"
                                     :foreground "#c00"))
            (put-text-property start end 'local-map tab-map)
            (let ((inhibit-read-only t))
              (put-text-property start end 'read-only t)))))

      (setq point-after-message (point))

      (goto-char (point-min))

      (goto-char (point-min))
      (search-forward "\n<<")
      (beginning-of-line)
      ;; Convert the <<...>> line to the proper [...] line,
      ;; or just delete the <<...>> line if a [...] line follows.
      (cond ((save-excursion
               (forward-line 1)
               (looking-at "\\["))
             (delete-region (point) (progn (forward-line 1) (point))))
            ((looking-at "<<Blank lines inserted.*>>")
             (replace-match "[Middle of page left blank for didactic purposes.   Text continues below]"))
            (t
             (looking-at "<<")
             (replace-match "[")
             (search-forward ">>")
             (replace-match "]")))
      (beginning-of-line)
      (let ((n (- (window-height (selected-window))
                  (count-lines (point-min) (point))
                  6)))
        (if (< n 8)
            (progn
              ;; For a short gap, we don't need the [...] line,
              ;; so delete it.
              (delete-region (point) (progn (end-of-line) (point)))
              (newline n))
          ;; Some people get confused by the large gap.
          (newline (/ n 2))

          ;; Skip the [...] line (don't delete it).
          (forward-line 1)
          (newline (- n (/ n 2)))))
      (goto-char (point-min))
      (setq buffer-undo-list nil)
      (set-buffer-modified-p nil))))

[-- Attachment #3: help-fns.diff --]
[-- Type: text/plain, Size: 27187 bytes --]

Index: help-fns.el
===================================================================
RCS file: /cvsroot/emacs/emacs/lisp/help-fns.el,v
retrieving revision 1.90
diff -u -r1.90 help-fns.el
--- help-fns.el	12 Jul 2006 15:58:10 -0000	1.90
+++ help-fns.el	17 Jul 2006 15:31:08 -0000
@@ -36,6 +36,83 @@
 (require 'help-mode)
 
 
+(defun help--describe-nonstandard-key(value)
+  (let ((maps (current-active-maps t)))
+    (with-output-to-temp-buffer (help-buffer)
+      (help-setup-xref (list #'help-describe-nonstandard-key value)
+                       (interactive-p))
+      (with-current-buffer (help-buffer)
+        (insert "Emacs default key binding has been changed in your setup:\n\n")
+        (let ((inhibit-read-only t))
+          (cond
+           ((eq (car value) 'cua-mode)
+            (insert
+             "You have enabled `cua-mode'.
+
+When `cua-mode' is enabled, you can use C-z, C-x, C-c, and C-v to
+undo, cut, copy, and paste in addition to the normal Emacs
+bindings.  The C-x and C-c keys only do cut and copy when the
+region is active, so in most cases, they do not conflict with the
+normal function of these prefix keys.
+
+If you really need to perform a command which starts with one of
+the prefix keys even when the region is active, you have three
+options:
+- press the prefix key twice very quickly (within 0.2 seconds),
+- press the prefix key and the following key within 0.2 seconds, or
+- use the SHIFT key with the prefix key, i.e. C-S-x or C-S-c."))
+           ((eq (car value) 'current-binding)
+            (let ((cb    (nth 1 value))
+                  (db    (nth 2 value))
+                  (key   (nth 3 value))
+                  (where (nth 4 value))
+                  map
+                  mapsym)
+              ;; Try to find the map where the binding occurs
+              (while maps
+                (let* ((m (car maps))
+                       (mb (lookup-key m key t)))
+                  (setq maps (cdr maps))
+                  (when (eq mb cb)
+                    (setq map m)
+                    (setq maps nil))))
+              (when map
+                (if (eq map global-map)
+                    (setq mapsym 'global-map)
+                  (mapatoms (lambda (s)
+                              (when (and (boundp s)
+                                         (keymapp (symbol-value s)))
+                                (unless (eq s 'map)
+                                  (when (equal map (symbol-value s))
+                                    (when (member map (current-active-maps))
+                                      (setq mapsym s)))))))))
+              (insert "Emacs default binding for the key "
+                      (key-description key)
+                      " is the function `")
+              (insert (format "%s" db))
+              (insert "'.  "
+                      "This key has however been rebound to the function `")
+              (insert (format "%s" cb))
+              (insert "'.")
+              (when mapsym
+                (insert "  This binding is in the keymap variable `")
+                (insert (format "%s" mapsym))
+                (insert "'."))
+              (if (string= where "")
+                  (unless (keymapp db)
+                    (insert "\n\nYou can use M-x "
+                            (format "%s" db)
+                            " RET instead."))
+                (insert "\n\nWith you current key bindings"
+                        " you can use the key "
+                        where
+                        " to get the function `"
+                        (format "%s" db)
+                        "'."))
+              ))))
+        (fill-region (point-min)(point))
+        (print-help-return-message)))))
+
 ;;;###autoload
 (defun help-with-tutorial (&optional arg)
   "Select the Emacs learn-by-doing tutorial.
@@ -44,58 +121,449 @@
 If there's no tutorial in that language, `TUTORIAL' is selected.
 With ARG, you are asked to choose which language."
   (interactive "P")
-  (let ((lang (if arg
-                  (let ((minibuffer-setup-hook minibuffer-setup-hook))
-                    (add-hook 'minibuffer-setup-hook
-                              'minibuffer-completion-help)
-                    (read-language-name 'tutorial "Language: " "English"))
-		(if (get-language-info current-language-environment 'tutorial)
-		    current-language-environment
-		  "English")))
-	file filename)
-    (setq filename (get-language-info lang 'tutorial))
-    (setq file (expand-file-name (concat "~/" filename)))
+  (let* ((lang (if arg
+                   (let ((minibuffer-setup-hook minibuffer-setup-hook))
+                     (add-hook 'minibuffer-setup-hook
+                               'minibuffer-completion-help)
+                     (read-language-name 'tutorial "Language: " "English"))
+                 (if (get-language-info current-language-environment 'tutorial)
+                     current-language-environment
+                   "English")))
+         (filename (get-language-info lang 'tutorial))
+         (tut-buf-name (concat "TUTORIAL (" lang ")"))
+         (old-tut-buf (get-buffer tut-buf-name))
+         (old-tut-win (when old-tut-buf (get-buffer-window old-tut-buf t)))
+         (old-tut-is-ok (when old-tut-buf
+                          (not (buffer-modified-p old-tut-buf))))
+         (point-after-message 1))
+    (when old-tut-win
+      (raise-frame
+       (window-frame
+        (select-window (get-buffer-window old-tut-buf t)))))
+    (when (and old-tut-buf
+               (not old-tut-is-ok))
+      (setq old-tut-is-ok
+            (not (y-or-n-p
+                  "You have changed the Tutorial buffer.  Revert it? "))))
     (delete-other-windows)
-    (if (get-file-buffer file)
-	(switch-to-buffer (get-file-buffer file))
-      (switch-to-buffer (create-file-buffer file))
-      (setq buffer-file-name file)
+    (if old-tut-is-ok
+        (switch-to-buffer (get-buffer tut-buf-name))
+      (switch-to-buffer (get-buffer-create tut-buf-name))
+      (let ((inhibit-read-only t))
+        (erase-buffer))
+      (message "Preparing tutorial ...")(sit-for 0)
+
       (setq default-directory (expand-file-name "~/"))
       (setq buffer-auto-save-file-name nil)
       (insert-file-contents (expand-file-name filename data-directory))
       (hack-local-variables)
+
+
+      ;; Check if there are key bindings that may disturb the
+      ;; tutorial.  If so tell the user.
+      (let* (changed-keys
+             (suspend-emacs (if window-system
+                                'iconify-or-deiconify-frame
+                              'suspend-emacs))
+             (default-keys
+               '(
+                 ;; These are not mentioned but are basic:
+                 (ESC-prefix [27])
+                 (Control-X-prefix [?\C-x])
+                 (mode-specific-command-prefix [?\C-c])
+
+                 (save-buffers-kill-emacs [?\C-x ?\C-c])
+
+
+                 ;; * SUMMARY
+                 (scroll-up [?\C-v])
+                 (scroll-down [?\M-v])
+                 (recenter [?\C-l])
+
+
+                 ;; * BASIC CURSOR CONTROL
+                 (forward-char [?\C-f])
+                 (backward-char [?\C-b])
+
+                 (forward-word [?\M-f])
+                 (backward-word [?\M-b])
+
+                 (next-line [?\C-n])
+                 (previous-line [?\C-p])
+
+                 (move-beginning-of-line [?\C-a])
+                 (move-end-of-line [?\C-e])
+
+                 (backward-sentence [?\M-a])
+                 (forward-sentence [?\M-e])
+
+
+                 (beginning-of-buffer [?\M-<])
+                 (end-of-buffer [?\M->])
+
+                 (universal-argument [?\C-u])
+
+
+                 ;; * WHEN EMACS IS HUNG
+                 (keyboard-quit [?\C-g])
+
+
+                 ;; * DISABLED COMMANDS
+                 (downcase-region [?\C-x ?\C-l])
+
+
+                 ;; * WINDOWS
+                 (delete-other-windows [?\C-x ?1])
+                 ;; C-u 0 C-l
+                 ;; Type CONTROL-h k CONTROL-f.
+
+
+                 ;; * INSERTING AND DELETING
+                 ;; C-u 8 * to insert ********.
+
+                 (delete-backward-char [backspace])
+                 (delete-char [?\C-d])
+
+                 (backward-kill-word [(meta backspace)])
+                 (kill-word [?\M-d])
+
+                 (kill-line [?\C-k])
+                 (kill-sentence [?\M-k])
+
+                 (set-mark-command [?\C-@])
+                 (set-mark-command [?\C- ])
+                 (kill-region [?\C-w])
+                 (yank [?\C-y])
+                 (yank-pop [?\M-y])
+
+
+                 ;; * UNDO
+                 (advertised-undo [?\C-x ?u])
+                 (advertised-undo [?\C-x ?u])
+
+
+                 ;; * FILES
+                 (find-file [?\C-x ?\C-f])
+                 (save-buffer [?\C-x ?\C-s])
+
+
+                 ;; * BUFFERS
+                 (list-buffers [?\C-x ?\C-b])
+                 (switch-to-buffer [?\C-x ?b])
+                 (save-some-buffers [?\C-x ?s])
+
+
+                 ;; * EXTENDING THE COMMAND SET
+                 ;; C-x	Character eXtend.  Followed by one character.
+                 (execute-extended-command [?\M-x])
+
+                 ;; C-x C-f		Find file
+                 ;; C-x C-s		Save file
+                 ;; C-x s		Save some buffers
+                 ;; C-x C-b		List buffers
+                 ;; C-x b		Switch buffer
+                 ;; C-x C-c		Quit Emacs
+                 ;; C-x 1		Delete all but one window
+                 ;; C-x u		Undo
+
+
+                 ;; * MODE LINE
+                 (describe-mode [?\C-h ?m])
+
+                 (set-fill-column [?\C-x ?f])
+                 (fill-paragraph [?\M-q])
+
+
+                 ;; * SEARCHING
+                 (isearch-forward [?\C-s])
+                 (isearch-backward [?\C-r])
+
+
+                 ;; * MULTIPLE WINDOWS
+                 (split-window-vertically [?\C-x ?2])
+                 (scroll-other-window [?\C-\M-v])
+                 (other-window [?\C-x ?o])
+                 (find-file-other-window [?\C-x ?4 ?\C-f])
+
+
+                 ;; * RECURSIVE EDITING LEVELS
+                 (keyboard-escape-quit [27 27 27])
+
+
+                 ;; * GETTING MORE HELP
+                 ;; The most basic HELP feature is C-h c
+                 (describe-key-briefly [?\C-h ?c])
+                 (describe-key [?\C-h ?k])
+
+
+                 ;; * MORE FEATURES
+                 ;; F10
+
+
+                 ;; * CONCLUSION
+                 (iconify-or-deiconify-frame [?\C-z])
+                 ))
+             (sort-keys
+              (lambda(left right)
+                (let ((x (append (cadr left)  nil))
+                      (y (append (cadr right) nil)))
+                  (while (and x y
+                              (equal (car x) (car y)))
+                    (setq x (cdr x))
+                    (setq y (cdr y)))
+                  (let ((cx (car x))
+                        (cy (car y)))
+                    (cond ((and (listp cx)
+                                (listp cy))
+                           (> (length cx)(length cy)))
+                          ((listp cx)
+                           nil)
+                          ((listp cy)
+                           t)
+                          ((and (symbolp cx)
+                                (symbolp cy))
+                           (string< (symbol-name cy)
+                                    (symbol-name cx)))
+                          ((symbolp cx)
+                           nil)
+                          ((symbolp cy)
+                           t)
+                          (t
+                           (> (car x)(car y))))))))
+             (tab-map (let ((map (make-sparse-keymap)))
+                        (define-key map [tab] 'forward-button)
+                        (define-key map [(shift tab)] 'backward-button)
+                        (define-key map [(meta tab)] 'backward-button)
+                        map)))
+        (setq default-keys (sort default-keys sort-keys))
+
+        (let (expr
+              key
+              def-fun
+              def-fun-txt
+              rem-fun
+              key-fun
+              where
+              remark
+              )
+          (dolist (kdf default-keys)
+            (setq key     (nth 1 kdf))
+            (setq def-fun (nth 0 kdf))
+            (setq def-fun-txt (format "%s" def-fun))
+            (setq rem-fun (command-remapping def-fun))
+            (setq key-fun (key-binding key))
+            (setq where (where-is-internal (if rem-fun rem-fun def-fun)))
+            (if where
+                (progn
+                  (setq where (key-description (car where)))
+                  (when (and (< 10 (length where))
+                             (string= (substring where 0 (length "<menu-bar>"))
+                                      "<menu-bar>"))
+                    (setq where "The menus")))
+              (setq where ""))
+            (setq remark nil)
+            (unless
+                (cond ( (eq key-fun def-fun)
+                        t)
+                      ( (eq key-fun (command-remapping def-fun))
+                        (setq remark (list "Remapped" nil))
+                        t)
+                      ;; cua-mode specials:
+                      ( (and cua-mode
+                             (or (and
+                                  (equal key [?\C-v])
+                                  (eq key-fun 'cua-paste))
+                                 (and
+                                  (equal key [?\C-z])
+                                  (eq key-fun 'undo))))
+                        (setq remark (list "cua-mode, more info" 'cua-mode))
+                        nil)
+                      ( (and cua-mode
+                             (or
+                              (and (eq def-fun 'ESC-prefix)
+                                   (equal key-fun
+                                          `(keymap
+                                            (118 . cua-repeat-replace-region))))
+                              (and (eq def-fun 'mode-specific-command-prefix)
+                                   (equal key-fun
+                                          '(keymap
+                                            (timeout . copy-region-as-kill))))
+                              (and (eq def-fun 'Control-X-prefix)
+                                   (equal key-fun
+                                          '(keymap (timeout . kill-region))))))
+                        (setq remark (list "cua-mode replacement" 'cua-mode))
+                        (cond
+                         ((eq def-fun 'mode-specific-command-prefix)
+                          (setq def-fun-txt "\"C-c prefix\""))
+                         ((eq def-fun 'Control-X-prefix)
+                          (setq def-fun-txt "\"C-x prefix\""))
+                         ((eq def-fun 'ESC-prefix)
+                          (setq def-fun-txt "\"ESC prefix\"")))
+                        (setq where "Same key")
+                        nil)
+                      ;; viper-mode specials:
+                      ( (and viper-mode
+                             (eq viper-current-state 'vi-state)
+                             (or (and (eq def-fun 'isearch-forward)
+                                      (eq key-fun 'viper-isearch-forward))
+                                 (and (eq def-fun 'isearch-backward)
+                                      (eq key-fun 'viper-isearch-backward))))
+                        t)
+                      ;; The strange handling of C-delete and
+                      ;; C-backspace:
+                      ( (when normal-erase-is-backspace
+                          (or (and (equal key [C-delete])
+                                   (equal key-fun 'kill-word))
+                              (and (equal key [C-backspace])
+                                   (equal key-fun 'backward-kill-word))))
+                        t)
+                      ( t
+                        (setq remark
+                              (list "more info" 'current-binding
+                                    key-fun def-fun key where))
+                        nil))
+              (add-to-list 'changed-keys
+                           (list key def-fun def-fun-txt where remark)))))
+
+        (message "")(sit-for 0)
+        (when changed-keys
+          (forward-line)
+          (let ((start (point))
+                end)
+            (insert "
+ NOTICE: One of the main purposes of the tutorial is that You should
+ be able to learn some important Emacs default key bindings.  However
+ when you started the tutorial the following key bindings used in the
+ tutorial had been changed from Emacs default:\n\n" )
+            (let ((frm "   %-9s %-27s %-11s %s\n"))
+              (insert (format frm "KEY" "DEFAULT BINDING" "IS NOW ON" "REMARK")))
+            (dolist (tk changed-keys)
+              (let* ((def-fun     (nth 1 tk))
+                     (key         (nth 0 tk))
+                     (def-fun-txt (nth 2 tk))
+                     (where       (nth 3 tk))
+                     (remark      (nth 4 tk))
+                     (rem-fun (command-remapping def-fun))
+                     (key-txt (key-description key))
+                     (key-fun (key-binding key))
+                     tot-len)
+                (unless (eq def-fun key-fun)
+                  (insert "   " key-txt " ")
+                  (setq tot-len (length key-txt))
+                  (when (> 9 tot-len)
+                    (insert (make-string (- 9 tot-len) ? ))
+                    (setq tot-len 9))
+                  (insert-button def-fun-txt
+                                 'value def-fun
+                                 'action
+                                 (lambda(button) (interactive)
+                                   (describe-function
+                                    (button-get button 'value)))
+                                 'follow-link t
+                                 'read-only t
+                                 'face '(:inherit link
+                                                  :background "yellow"))
+                  (setq tot-len (+ tot-len (length def-fun-txt)))
+                  (when (> 36 tot-len)
+                    (insert (make-string (- 36 tot-len) ? )))
+                  (when (listp where)
+                    (setq where "list"))
+                  (insert (format " %-11s " where))
+                  (insert-button (car remark)
+                                 'action
+                                 (lambda(b) (interactive)
+                                   (let ((value (button-get b 'value)))
+                                     (help--describe-nonstandard-key value)))
+                                 'value (cdr remark)
+                                 'follow-link t
+                                 'face '(:inherit link
+                                                  :background "yellow"))
+                  (insert "\n"))))
+
+            (when (and (boundp 'viper-mode)
+                       viper-mode)
+              (cond
+               ((eq viper-current-state 'emacs-state)
+                (insert "
+   You have enabled viper mode, but in the tutorial buffer viper
+   mode is currently turned off."))
+               (t
+                (insert "
+   You have enabled viper mode. Some Emacs default key bindings
+   will be unavailable. This is dependent on the state Viper is
+   in.")))
+              (insert "\n   If you want to learn viper keys please see the ")
+              (insert-button "viper manual"
+                             'action
+                             (lambda(button) (interactive)
+                               (info-other-window "(viper)")
+                               (message "Type C-x 0 to close the new window"))
+                             'follow-link t
+                             'read-only t
+                             'face '(:inherit link
+                                              :background "yellow"))
+              (insert ".\n"))
+
+            (insert "
+ It is legitimate to change key bindings, but changed bindings do not
+ correspond to what the tutorial says.  (See also " )
+            (insert-button "Key Binding Conventions"
+                           'action
+                           (lambda(button) (interactive)
+                             (info-other-window
+                              "(elisp) Key Binding Conventions")
+                             (message "Type C-x 0 to close the new window"))
+                           'follow-link t
+                           'read-only t
+                           'face '(:inherit link
+                                            :background "yellow"))
+            (insert ".)\n\n")
+            (setq end (point))
+            (put-text-property start end
+                               'face
+                               ;;'font-lock-warning-face
+                               (list :background "yellow"
+                                     :foreground "#c00"))
+            (put-text-property start end 'local-map tab-map)
+            (let ((inhibit-read-only t))
+              (put-text-property start end 'read-only t)))))
+
+      (setq point-after-message (point))
+
+      (goto-char (point-min))
+
       (goto-char (point-min))
       (search-forward "\n<<")
       (beginning-of-line)
       ;; Convert the <<...>> line to the proper [...] line,
       ;; or just delete the <<...>> line if a [...] line follows.
       (cond ((save-excursion
-	       (forward-line 1)
-	       (looking-at "\\["))
-	     (delete-region (point) (progn (forward-line 1) (point))))
-	    ((looking-at "<<Blank lines inserted.*>>")
-	     (replace-match "[Middle of page left blank for didactic purposes.   Text continues below]"))
-	    (t
-	     (looking-at "<<")
-	     (replace-match "[")
-	     (search-forward ">>")
-	     (replace-match "]")))
+               (forward-line 1)
+               (looking-at "\\["))
+             (delete-region (point) (progn (forward-line 1) (point))))
+            ((looking-at "<<Blank lines inserted.*>>")
+             (replace-match "[Middle of page left blank for didactic purposes.   Text continues below]"))
+            (t
+             (looking-at "<<")
+             (replace-match "[")
+             (search-forward ">>")
+             (replace-match "]")))
       (beginning-of-line)
       (let ((n (- (window-height (selected-window))
-		  (count-lines (point-min) (point))
-		  6)))
-	(if (< n 8)
-	    (progn
-	      ;; For a short gap, we don't need the [...] line,
-	      ;; so delete it.
-	      (delete-region (point) (progn (end-of-line) (point)))
-	      (newline n))
-	  ;; Some people get confused by the large gap.
-	  (newline (/ n 2))
-
-	  ;; Skip the [...] line (don't delete it).
-	  (forward-line 1)
-	  (newline (- n (/ n 2)))))
+                  (count-lines (point-min) (point))
+                  6)))
+        (if (< n 8)
+            (progn
+              ;; For a short gap, we don't need the [...] line,
+              ;; so delete it.
+              (delete-region (point) (progn (end-of-line) (point)))
+              (newline n))
+          ;; Some people get confused by the large gap.
+          (newline (/ n 2))
+
+          ;; Skip the [...] line (don't delete it).
+          (forward-line 1)
+          (newline (- n (/ n 2)))))
       (goto-char (point-min))
       (setq buffer-undo-list nil)
       (set-buffer-modified-p nil))))
@@ -252,8 +720,8 @@
                          "\\)"
                          "\\(?:es\\|s\\|th\\)?"  ; for ARGth, ARGs
                          "\\(?:-[a-z0-9-]+\\)?"  ; for ARG-xxx, ARG-n
-                         "\\(?:-[{([<`\"].*?\\)?"; for ARG-{x}, (x), <x>, [x], `x'
-                         "\\>")                  ; end of word
+                         "\\(?:-[{([<`\"].*?\\)?" ; for ARG-{x}, (x), <x>, [x], `x'
+                         "\\>")                   ; end of word
                  (help-default-arg-highlight arg)
                  doc t t 1)))))
 
@@ -419,23 +887,23 @@
         ;; If definition is a keymap, skip arglist note.
         (unless (keymapp def)
           (let* ((use (cond
-                        (usage (setq doc (cdr usage)) (car usage))
-                        ((listp arglist)
-                         (format "%S" (help-make-usage function arglist)))
-                        ((stringp arglist) arglist)
-                        ;; Maybe the arglist is in the docstring of the alias.
-                        ((let ((fun function))
-                           (while (and (symbolp fun)
-                                       (setq fun (symbol-function fun))
-                                       (not (setq usage (help-split-fundoc
-                                                         (documentation fun)
-                                                         function)))))
-                           usage)
-                         (car usage))
-                        ((or (stringp def)
-                             (vectorp def))
-                         (format "\nMacro: %s" (format-kbd-macro def)))
-                        (t "[Missing arglist.  Please make a bug report.]")))
+                       (usage (setq doc (cdr usage)) (car usage))
+                       ((listp arglist)
+                        (format "%S" (help-make-usage function arglist)))
+                       ((stringp arglist) arglist)
+                       ;; Maybe the arglist is in the docstring of the alias.
+                       ((let ((fun function))
+                          (while (and (symbolp fun)
+                                      (setq fun (symbol-function fun))
+                                      (not (setq usage (help-split-fundoc
+                                                        (documentation fun)
+                                                        function)))))
+                          usage)
+                        (car usage))
+                       ((or (stringp def)
+                            (vectorp def))
+                        (format "\nMacro: %s" (format-kbd-macro def)))
+                       (t "[Missing arglist.  Please make a bug report.]")))
                  (high (help-highlight-arguments use doc)))
             (let ((fill-begin (point)))
 	      (insert (car high) "\n")
@@ -628,8 +1096,8 @@
 
  	    ;; Mention if it's an alias
             (let* ((alias (condition-case nil
-                             (indirect-variable variable)
-                           (error variable)))
+                              (indirect-variable variable)
+                            (error variable)))
                    (obsolete (get variable 'byte-obsolete-variable))
 		   (safe-var (get variable 'safe-local-variable))
                    (doc (or (documentation-property variable 'variable-documentation)

[-- Attachment #4: Type: text/plain, Size: 142 bytes --]

_______________________________________________
Emacs-devel mailing list
Emacs-devel@gnu.org
http://lists.gnu.org/mailman/listinfo/emacs-devel

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: Patch to remove minor modes in tutorial
  2006-07-17 16:12                                 ` Lennart Borgman
@ 2006-07-17 17:32                                   ` Lennart Borgman
  2006-07-24 14:42                                     ` Richard Stallman
  0 siblings, 1 reply; 29+ messages in thread
From: Lennart Borgman @ 2006-07-17 17:32 UTC (permalink / raw)
  Cc: rms, emacs-devel

[-- Attachment #1: Type: text/plain, Size: 237 bytes --]

Lennart Borgman wrote:
> I send the changes both as a standalone file and a patch this time. I 
> have added this:
There was a small problem with variables. Sending the standalone file 
again only since this message will be quite big.



[-- Attachment #2: help-tutorial5.el --]
[-- Type: text/plain, Size: 21542 bytes --]

(defun help--describe-nonstandard-key(value)
  (let ((maps (current-active-maps t)))
    (with-output-to-temp-buffer (help-buffer)
      (help-setup-xref (list #'help-describe-nonstandard-key value)
                       (interactive-p))
      (with-current-buffer (help-buffer)
        (insert "Emacs default key binding has been changed in your setup:\n\n")
        (let ((inhibit-read-only t))
          (cond
           ((eq (car value) 'cua-mode)
            (insert
             "You have enabled `cua-mode'.

When `cua-mode' is enabled, you can use C-z, C-x, C-c, and C-v to
undo, cut, copy, and paste in addition to the normal Emacs
bindings.  The C-x and C-c keys only do cut and copy when the
region is active, so in most cases, they do not conflict with the
normal function of these prefix keys.

If you really need to perform a command which starts with one of
the prefix keys even when the region is active, you have three
options:
- press the prefix key twice very quickly (within 0.2 seconds),
- press the prefix key and the following key within 0.2 seconds, or
- use the SHIFT key with the prefix key, i.e. C-S-x or C-S-c."))
           ((eq (car value) 'current-binding)
            (let ((cb    (nth 1 value))
                  (db    (nth 2 value))
                  (key   (nth 3 value))
                  (where (nth 4 value))
                  map
                  mapsym)
              ;; Try to find the map where the binding occurs
              (while maps
                (let* ((m (car maps))
                       (mb (lookup-key m key t)))
                  (setq maps (cdr maps))
                  (when (eq mb cb)
                    (setq map m)
                    (setq maps nil))))
              (when map
                (if (eq map global-map)
                    (setq mapsym 'global-map)
                  (mapatoms (lambda (s)
                              (when (and (boundp s)
                                         (keymapp (symbol-value s)))
                                (unless (eq s 'map)
                                  (when (equal map (symbol-value s))
                                    (when (member map (current-active-maps))
                                      (setq mapsym s)))))))))
              (insert "Emacs default binding for the key "
                      (key-description key)
                      " is the function `")
              (insert (format "%s" db))
              (insert "'.  "
                      "This key has however been rebound to the function `")
              (insert (format "%s" cb))
              (insert "'.")
              (when mapsym
                (insert "  This binding is in the keymap variable `")
                (insert (format "%s" mapsym))
                (insert "'."))
              (if (string= where "")
                  (unless (keymapp db)
                    (insert "\n\nYou can use M-x "
                            (format "%s" db)
                            " RET instead."))
                (insert "\n\nWith you current key bindings"
                        " you can use the key "
                        where
                        " to get the function `"
                        (format "%s" db)
                        "'."))
              ))))
        (fill-region (point-min)(point))
        (print-help-return-message)))))

;;;###autoload
(defun help-with-tutorial (&optional arg)
  "Select the Emacs learn-by-doing tutorial.
If there is a tutorial version written in the language
of the selected language environment, that version is used.
If there's no tutorial in that language, `TUTORIAL' is selected.
With ARG, you are asked to choose which language."
  (interactive "P")
  (let* ((lang (if arg
                   (let ((minibuffer-setup-hook minibuffer-setup-hook))
                     (add-hook 'minibuffer-setup-hook
                               'minibuffer-completion-help)
                     (read-language-name 'tutorial "Language: " "English"))
                 (if (get-language-info current-language-environment 'tutorial)
                     current-language-environment
                   "English")))
         (filename (get-language-info lang 'tutorial))
         (tut-buf-name (concat "TUTORIAL (" lang ")"))
         (old-tut-buf (get-buffer tut-buf-name))
         (old-tut-win (when old-tut-buf (get-buffer-window old-tut-buf t)))
         (old-tut-is-ok (when old-tut-buf
                          (not (buffer-modified-p old-tut-buf))))
         (point-after-message 1))
    (when old-tut-win
      (raise-frame
       (window-frame
        (select-window (get-buffer-window old-tut-buf t)))))
    (when (and old-tut-buf
               (not old-tut-is-ok))
      (setq old-tut-is-ok
            (not (y-or-n-p
                  "You have changed the Tutorial buffer.  Revert it? "))))
    (delete-other-windows)
    (if old-tut-is-ok
        (switch-to-buffer (get-buffer tut-buf-name))
      (switch-to-buffer (get-buffer-create tut-buf-name))
      (let ((inhibit-read-only t))
        (erase-buffer))
      (message "Preparing tutorial ...")(sit-for 0)

      (setq default-directory (expand-file-name "~/"))
      (setq buffer-auto-save-file-name nil)
      (insert-file-contents (expand-file-name filename data-directory))
      (hack-local-variables)


      ;; Check if there are key bindings that may disturb the
      ;; tutorial.  If so tell the user.
      (let* (changed-keys
             (suspend-emacs (if window-system
                                'iconify-or-deiconify-frame
                              'suspend-emacs))
             (default-keys
               '(
                 ;; These are not mentioned but are basic:
                 (ESC-prefix [27])
                 (Control-X-prefix [?\C-x])
                 (mode-specific-command-prefix [?\C-c])

                 (save-buffers-kill-emacs [?\C-x ?\C-c])


                 ;; * SUMMARY
                 (scroll-up [?\C-v])
                 (scroll-down [?\M-v])
                 (recenter [?\C-l])


                 ;; * BASIC CURSOR CONTROL
                 (forward-char [?\C-f])
                 (backward-char [?\C-b])

                 (forward-word [?\M-f])
                 (backward-word [?\M-b])

                 (next-line [?\C-n])
                 (previous-line [?\C-p])

                 (move-beginning-of-line [?\C-a])
                 (move-end-of-line [?\C-e])

                 (backward-sentence [?\M-a])
                 (forward-sentence [?\M-e])


                 (beginning-of-buffer [?\M-<])
                 (end-of-buffer [?\M->])

                 (universal-argument [?\C-u])


                 ;; * WHEN EMACS IS HUNG
                 (keyboard-quit [?\C-g])


                 ;; * DISABLED COMMANDS
                 (downcase-region [?\C-x ?\C-l])


                 ;; * WINDOWS
                 (delete-other-windows [?\C-x ?1])
                 ;; C-u 0 C-l
                 ;; Type CONTROL-h k CONTROL-f.


                 ;; * INSERTING AND DELETING
                 ;; C-u 8 * to insert ********.

                 (delete-backward-char [backspace])
                 (delete-char [?\C-d])

                 (backward-kill-word [(meta backspace)])
                 (kill-word [?\M-d])

                 (kill-line [?\C-k])
                 (kill-sentence [?\M-k])

                 (set-mark-command [?\C-@])
                 (set-mark-command [?\C- ])
                 (kill-region [?\C-w])
                 (yank [?\C-y])
                 (yank-pop [?\M-y])


                 ;; * UNDO
                 (advertised-undo [?\C-x ?u])
                 (advertised-undo [?\C-x ?u])


                 ;; * FILES
                 (find-file [?\C-x ?\C-f])
                 (save-buffer [?\C-x ?\C-s])


                 ;; * BUFFERS
                 (list-buffers [?\C-x ?\C-b])
                 (switch-to-buffer [?\C-x ?b])
                 (save-some-buffers [?\C-x ?s])


                 ;; * EXTENDING THE COMMAND SET
                 ;; C-x	Character eXtend.  Followed by one character.
                 (execute-extended-command [?\M-x])

                 ;; C-x C-f		Find file
                 ;; C-x C-s		Save file
                 ;; C-x s		Save some buffers
                 ;; C-x C-b		List buffers
                 ;; C-x b		Switch buffer
                 ;; C-x C-c		Quit Emacs
                 ;; C-x 1		Delete all but one window
                 ;; C-x u		Undo


                 ;; * MODE LINE
                 (describe-mode [?\C-h ?m])

                 (set-fill-column [?\C-x ?f])
                 (fill-paragraph [?\M-q])


                 ;; * SEARCHING
                 (isearch-forward [?\C-s])
                 (isearch-backward [?\C-r])


                 ;; * MULTIPLE WINDOWS
                 (split-window-vertically [?\C-x ?2])
                 (scroll-other-window [?\C-\M-v])
                 (other-window [?\C-x ?o])
                 (find-file-other-window [?\C-x ?4 ?\C-f])


                 ;; * RECURSIVE EDITING LEVELS
                 (keyboard-escape-quit [27 27 27])


                 ;; * GETTING MORE HELP
                 ;; The most basic HELP feature is C-h c
                 (describe-key-briefly [?\C-h ?c])
                 (describe-key [?\C-h ?k])


                 ;; * MORE FEATURES
                 ;; F10


                 ;; * CONCLUSION
                 (iconify-or-deiconify-frame [?\C-z])
                 ))
             (sort-keys
              (lambda(left right)
                (let ((x (append (cadr left)  nil))
                      (y (append (cadr right) nil)))
                  (while (and x y
                              (equal (car x) (car y)))
                    (setq x (cdr x))
                    (setq y (cdr y)))
                  (let ((cx (car x))
                        (cy (car y)))
                    (cond ((and (listp cx)
                                (listp cy))
                           (> (length cx)(length cy)))
                          ((listp cx)
                           nil)
                          ((listp cy)
                           t)
                          ((and (symbolp cx)
                                (symbolp cy))
                           (string< (symbol-name cy)
                                    (symbol-name cx)))
                          ((symbolp cx)
                           nil)
                          ((symbolp cy)
                           t)
                          (t
                           (> (car x)(car y))))))))
             (tab-map (let ((map (make-sparse-keymap)))
                        (define-key map [tab] 'forward-button)
                        (define-key map [(shift tab)] 'backward-button)
                        (define-key map [(meta tab)] 'backward-button)
                        map)))
        (setq default-keys (sort default-keys sort-keys))

        (let (expr
              key
              def-fun
              def-fun-txt
              rem-fun
              key-fun
              where
              remark
              )
          (dolist (kdf default-keys)
            (setq key     (nth 1 kdf))
            (setq def-fun (nth 0 kdf))
            (setq def-fun-txt (format "%s" def-fun))
            (setq rem-fun (command-remapping def-fun))
            (setq key-fun (key-binding key))
            (setq where (where-is-internal (if rem-fun rem-fun def-fun)))
            (if where
                (progn
                  (setq where (key-description (car where)))
                  (when (and (< 10 (length where))
                             (string= (substring where 0 (length "<menu-bar>"))
                                      "<menu-bar>"))
                    (setq where "The menus")))
              (setq where ""))
            (setq remark nil)
            (unless
                (cond ( (eq key-fun def-fun)
                        t)
                      ( (eq key-fun (command-remapping def-fun))
                        (setq remark (list "Remapped" nil))
                        t)
                      ;; cua-mode specials:
                      ( (and cua-mode
                             (or (and
                                  (equal key [?\C-v])
                                  (eq key-fun 'cua-paste))
                                 (and
                                  (equal key [?\C-z])
                                  (eq key-fun 'undo))))
                        (setq remark (list "cua-mode, more info" 'cua-mode))
                        nil)
                      ( (and cua-mode
                             (or
                              (and (eq def-fun 'ESC-prefix)
                                   (equal key-fun
                                          `(keymap
                                            (118 . cua-repeat-replace-region))))
                              (and (eq def-fun 'mode-specific-command-prefix)
                                   (equal key-fun
                                          '(keymap
                                            (timeout . copy-region-as-kill))))
                              (and (eq def-fun 'Control-X-prefix)
                                   (equal key-fun
                                          '(keymap (timeout . kill-region))))))
                        (setq remark (list "cua-mode replacement" 'cua-mode))
                        (cond
                         ((eq def-fun 'mode-specific-command-prefix)
                          (setq def-fun-txt "\"C-c prefix\""))
                         ((eq def-fun 'Control-X-prefix)
                          (setq def-fun-txt "\"C-x prefix\""))
                         ((eq def-fun 'ESC-prefix)
                          (setq def-fun-txt "\"ESC prefix\"")))
                        (setq where "Same key")
                        nil)
                      ;; viper-mode specials:
                      ( (and (boundp 'viper-mode)
                             viper-mode
                             (eq viper-current-state 'vi-state)
                             (or (and (eq def-fun 'isearch-forward)
                                      (eq key-fun 'viper-isearch-forward))
                                 (and (eq def-fun 'isearch-backward)
                                      (eq key-fun 'viper-isearch-backward))))
                        t)
                      ;; The strange handling of C-delete and
                      ;; C-backspace:
                      ( (when normal-erase-is-backspace
                          (or (and (equal key [C-delete])
                                   (equal key-fun 'kill-word))
                              (and (equal key [C-backspace])
                                   (equal key-fun 'backward-kill-word))))
                        t)
                      ( t
                        (setq remark
                              (list "more info" 'current-binding
                                    key-fun def-fun key where))
                        nil))
              (add-to-list 'changed-keys
                           (list key def-fun def-fun-txt where remark)))))

        (message "")(sit-for 0)
        (when changed-keys
          (forward-line)
          (let ((start (point))
                end)
            (insert "
 NOTICE: One of the main purposes of the tutorial is that You should
 be able to learn some important Emacs default key bindings.  However
 when you started the tutorial the following key bindings used in the
 tutorial had been changed from Emacs default:\n\n" )
            (let ((frm "   %-9s %-27s %-11s %s\n"))
              (insert (format frm "KEY" "DEFAULT BINDING" "IS NOW ON" "REMARK")))
            (dolist (tk changed-keys)
              (let* ((def-fun     (nth 1 tk))
                     (key         (nth 0 tk))
                     (def-fun-txt (nth 2 tk))
                     (where       (nth 3 tk))
                     (remark      (nth 4 tk))
                     (rem-fun (command-remapping def-fun))
                     (key-txt (key-description key))
                     (key-fun (key-binding key))
                     tot-len)
                (unless (eq def-fun key-fun)
                  (insert "   " key-txt " ")
                  (setq tot-len (length key-txt))
                  (when (> 9 tot-len)
                    (insert (make-string (- 9 tot-len) ? ))
                    (setq tot-len 9))
                  (insert-button def-fun-txt
                                 'value def-fun
                                 'action
                                 (lambda(button) (interactive)
                                   (describe-function
                                    (button-get button 'value)))
                                 'follow-link t
                                 'read-only t
                                 'face '(:inherit link
                                                  :background "yellow"))
                  (setq tot-len (+ tot-len (length def-fun-txt)))
                  (when (> 36 tot-len)
                    (insert (make-string (- 36 tot-len) ? )))
                  (when (listp where)
                    (setq where "list"))
                  (insert (format " %-11s " where))
                  (insert-button (car remark)
                                 'action
                                 (lambda(b) (interactive)
                                   (let ((value (button-get b 'value)))
                                     (help--describe-nonstandard-key value)))
                                 'value (cdr remark)
                                 'follow-link t
                                 'face '(:inherit link
                                                  :background "yellow"))
                  (insert "\n"))))

            (when (and (boundp 'viper-mode)
                       viper-mode)
              (cond
               ((eq viper-current-state 'emacs-state)
                (insert "
   You have enabled viper mode, but in the tutorial buffer viper
   mode is currently turned off."))
               (t
                (insert "
   You have enabled viper mode. Some Emacs default key bindings
   will be unavailable. This is dependent on the state Viper is
   in.")))
              (insert "\n   If you want to learn viper keys please see the ")
              (insert-button "viper manual"
                             'action
                             (lambda(button) (interactive)
                               (info-other-window "(viper)")
                               (message "Type C-x 0 to close the new window"))
                             'follow-link t
                             'read-only t
                             'face '(:inherit link
                                              :background "yellow"))
              (insert ".\n"))

            (insert "
 It is legitimate to change key bindings, but changed bindings do not
 correspond to what the tutorial says.  (See also " )
            (insert-button "Key Binding Conventions"
                           'action
                           (lambda(button) (interactive)
                             (info-other-window
                              "(elisp) Key Binding Conventions")
                             (message "Type C-x 0 to close the new window"))
                           'follow-link t
                           'read-only t
                           'face '(:inherit link
                                            :background "yellow"))
            (insert ".)\n\n")
            (setq end (point))
            (put-text-property start end
                               'face
                               ;;'font-lock-warning-face
                               (list :background "yellow"
                                     :foreground "#c00"))
            (put-text-property start end 'local-map tab-map)
            (let ((inhibit-read-only t))
              (put-text-property start end 'read-only t)))))

      (setq point-after-message (point))

      (goto-char (point-min))

      (goto-char (point-min))
      (search-forward "\n<<")
      (beginning-of-line)
      ;; Convert the <<...>> line to the proper [...] line,
      ;; or just delete the <<...>> line if a [...] line follows.
      (cond ((save-excursion
               (forward-line 1)
               (looking-at "\\["))
             (delete-region (point) (progn (forward-line 1) (point))))
            ((looking-at "<<Blank lines inserted.*>>")
             (replace-match "[Middle of page left blank for didactic purposes.   Text continues below]"))
            (t
             (looking-at "<<")
             (replace-match "[")
             (search-forward ">>")
             (replace-match "]")))
      (beginning-of-line)
      (let ((n (- (window-height (selected-window))
                  (count-lines (point-min) (point))
                  6)))
        (if (< n 8)
            (progn
              ;; For a short gap, we don't need the [...] line,
              ;; so delete it.
              (delete-region (point) (progn (end-of-line) (point)))
              (newline n))
          ;; Some people get confused by the large gap.
          (newline (/ n 2))

          ;; Skip the [...] line (don't delete it).
          (forward-line 1)
          (newline (- n (/ n 2)))))
      (goto-char (point-min))
      (setq buffer-undo-list nil)
      (set-buffer-modified-p nil))))

[-- Attachment #3: Type: text/plain, Size: 142 bytes --]

_______________________________________________
Emacs-devel mailing list
Emacs-devel@gnu.org
http://lists.gnu.org/mailman/listinfo/emacs-devel

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: Patch to remove minor modes in tutorial
  2006-07-17 17:32                                   ` Lennart Borgman
@ 2006-07-24 14:42                                     ` Richard Stallman
  2006-07-30 20:38                                       ` Lennart Borgman
  0 siblings, 1 reply; 29+ messages in thread
From: Richard Stallman @ 2006-07-24 14:42 UTC (permalink / raw)
  Cc: lennart.borgman.073, emacs-devel

		 (default-keys
		   '(
		     ;; These are not mentioned but are basic:
		     (ESC-prefix [27])
		     (Control-X-prefix [?\C-x])
		     (mode-specific-command-prefix [?\C-c])


Please put that constant list into a variable
instead of embedding it inside the function.

		 (sort-keys
		  (lambda(left right)
		    (let ((x (append (cadr left)  nil))
			  (y (append (cadr right) nil)))
		      (while (and x y
				  (equal (car x) (car y)))
			(setq x (cdr x))
			(setq y (cdr y)))

Please give this a defun and give it a doc string that explains
precisely what it tests.

                  (insert-button (car remark)
                                 'action
                                 (lambda(b) (interactive)
                                   (let ((value (button-get b 'value)))
                                     (help--describe-nonstandard-key value)))
                                 'value (cdr remark)
                                 'follow-link t
                                 'face '(:inherit link
                                                  :background "yellow"))

What is the purpose of presenting that button?
What does it do when the user clicks on it?
Comments have to say such things.

In general, your code has hardly any comments.  Please add comments enough
to make it _clear_.

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: Patch to remove minor modes in tutorial
  2006-07-24 14:42                                     ` Richard Stallman
@ 2006-07-30 20:38                                       ` Lennart Borgman
  0 siblings, 0 replies; 29+ messages in thread
From: Lennart Borgman @ 2006-07-30 20:38 UTC (permalink / raw)
  Cc: emacs-devel

[-- Attachment #1: Type: text/plain, Size: 1974 bytes --]

Richard Stallman wrote:
> 		 (default-keys
> 		   '(
> 		     ;; These are not mentioned but are basic:
> 		     (ESC-prefix [27])
> 		     (Control-X-prefix [?\C-x])
> 		     (mode-specific-command-prefix [?\C-c])
>
>
> Please put that constant list into a variable
> instead of embedding it inside the function.
>   
Done.
> 		 (sort-keys
> 		  (lambda(left right)
> 		    (let ((x (append (cadr left)  nil))
> 			  (y (append (cadr right) nil)))
> 		      (while (and x y
> 				  (equal (car x) (car y)))
> 			(setq x (cdr x))
> 			(setq y (cdr y)))
>
> Please give this a defun and give it a doc string that explains
> precisely what it tests.
>   
Done.
>                   (insert-button (car remark)
>                                  'action
>                                  (lambda(b) (interactive)
>                                    (let ((value (button-get b 'value)))
>                                      (help--describe-nonstandard-key value)))
>                                  'value (cdr remark)
>                                  'follow-link t
>                                  'face '(:inherit link
>                                                   :background "yellow"))
>
> What is the purpose of presenting that button?
> What does it do when the user clicks on it?
> Comments have to say such things.
>   
Done now - I hope the comments tell what is needed now.
> In general, your code has hardly any comments.  Please add comments enough
> to make it _clear_.
>   
Done.

I have attached the new version.

However I noticed a strange thing when testing this on w32 from 
2006-07-02. If I start with "emacs -Q", then load the attached file and 
evaluate it with eval-buffer, then the old `help-with-tutorial' from 
help-fns.el may still be bound to C-h t. (I actually used F1 t.)

I check this with "F1 k F1 t". If I now call eval-buffer again and "F1 k 
F1 t" the new definition of help-with-tutorial from the attached file 
will be shown.

[-- Attachment #2: help-tutorial6.el --]
[-- Type: text/plain, Size: 27413 bytes --]

(defun help--describe-nonstandard-key(value)
  "Give more information about a changed key binding.
This is used in `help-with-tutorial'.  The information includes
the key sequence that no longer has a default binding, the
default binding and the current binding.  It also tells in what
keymap the new binding has been done and how to access the
function in the default binding from the keyboard.

For cua-mode key bindings that try to combine CUA key bindings
with default Emacs bindings information about this is shown."
  (let ((maps (current-active-maps t)))
    (with-output-to-temp-buffer (help-buffer)
      (help-setup-xref (list #'help-describe-nonstandard-key value)
                       (interactive-p))
      (with-current-buffer (help-buffer)
        (insert "Emacs default key binding has been changed in your setup:\n\n")
        (let ((inhibit-read-only t))
          (cond
           ((eq (car value) 'cua-mode)
            (insert
             "You have enabled `cua-mode'.

When `cua-mode' is enabled, you can use C-z, C-x, C-c, and C-v to
undo, cut, copy, and paste in addition to the normal Emacs
bindings.  The C-x and C-c keys only do cut and copy when the
region is active, so in most cases, they do not conflict with the
normal function of these prefix keys.

If you really need to perform a command which starts with one of
the prefix keys even when the region is active, you have three
options:
- press the prefix key twice very quickly (within 0.2 seconds),
- press the prefix key and the following key within 0.2 seconds, or
- use the SHIFT key with the prefix key, i.e. C-S-x or C-S-c."))
           ((eq (car value) 'current-binding)
            (let ((cb    (nth 1 value))
                  (db    (nth 2 value))
                  (key   (nth 3 value))
                  (where (nth 4 value))
                  map
                  mapsym)
              ;; Try to find the map where the binding occurs
              (while maps
                (let* ((m (car maps))
                       (mb (lookup-key m key t)))
                  (setq maps (cdr maps))
                  (when (eq mb cb)
                    (setq map m)
                    (setq maps nil))))
              (when map
                (if (eq map global-map)
                    (setq mapsym 'global-map)
                  (mapatoms (lambda (s)
                              (when (and (boundp s)
                                         (keymapp (symbol-value s)))
                                (unless (eq s 'map)
                                  (when (equal map (symbol-value s))
                                    (when (member map (current-active-maps))
                                      (setq mapsym s)))))))))
              (insert "Emacs default binding for the key "
                      (key-description key)
                      " is the function `")
              (insert (format "%s" db))
              (insert "'.  "
                      "This key has however been rebound to the function `")
              (insert (format "%s" cb))
              (insert "'.")
              (when mapsym
                (insert "  This binding is in the keymap variable `")
                (insert (format "%s" mapsym))
                (insert "'."))
              (if (string= where "")
                  (unless (keymapp db)
                    (insert "\n\nYou can use M-x "
                            (format "%s" db)
                            " RET instead."))
                (insert "\n\nWith you current key bindings"
                        " you can use the key "
                        where
                        " to get the function `"
                        (format "%s" db)
                        "'."))
              ))))
        (fill-region (point-min)(point))
        (print-help-return-message)))))

(defvar help-tutorial-default-keys
  '(
    ;; These are not mentioned but are basic:
    (ESC-prefix [27])
    (Control-X-prefix [?\C-x])
    (mode-specific-command-prefix [?\C-c])

    (save-buffers-kill-emacs [?\C-x ?\C-c])


    ;; * SUMMARY
    (scroll-up [?\C-v])
    (scroll-down [?\M-v])
    (recenter [?\C-l])


    ;; * BASIC CURSOR CONTROL
    (forward-char [?\C-f])
    (backward-char [?\C-b])

    (forward-word [?\M-f])
    (backward-word [?\M-b])

    (next-line [?\C-n])
    (previous-line [?\C-p])

    (move-beginning-of-line [?\C-a])
    (move-end-of-line [?\C-e])

    (backward-sentence [?\M-a])
    (forward-sentence [?\M-e])


    (beginning-of-buffer [?\M-<])
    (end-of-buffer [?\M->])

    (universal-argument [?\C-u])


    ;; * WHEN EMACS IS HUNG
    (keyboard-quit [?\C-g])


    ;; * DISABLED COMMANDS
    (downcase-region [?\C-x ?\C-l])


    ;; * WINDOWS
    (delete-other-windows [?\C-x ?1])
    ;; C-u 0 C-l
    ;; Type CONTROL-h k CONTROL-f.


    ;; * INSERTING AND DELETING
    ;; C-u 8 * to insert ********.

    (delete-backward-char [backspace])
    (delete-char [?\C-d])

    (backward-kill-word [(meta backspace)])
    (kill-word [?\M-d])

    (kill-line [?\C-k])
    (kill-sentence [?\M-k])

    (set-mark-command [?\C-@])
    (set-mark-command [?\C- ])
    (kill-region [?\C-w])
    (yank [?\C-y])
    (yank-pop [?\M-y])


    ;; * UNDO
    (advertised-undo [?\C-x ?u])
    (advertised-undo [?\C-x ?u])


    ;; * FILES
    (find-file [?\C-x ?\C-f])
    (save-buffer [?\C-x ?\C-s])


    ;; * BUFFERS
    (list-buffers [?\C-x ?\C-b])
    (switch-to-buffer [?\C-x ?b])
    (save-some-buffers [?\C-x ?s])


    ;; * EXTENDING THE COMMAND SET
    ;; C-x	Character eXtend.  Followed by one character.
    (execute-extended-command [?\M-x])

    ;; C-x C-f		Find file
    ;; C-x C-s		Save file
    ;; C-x s		Save some buffers
    ;; C-x C-b		List buffers
    ;; C-x b		Switch buffer
    ;; C-x C-c		Quit Emacs
    ;; C-x 1		Delete all but one window
    ;; C-x u		Undo


    ;; * MODE LINE
    (describe-mode [?\C-h ?m])

    (set-fill-column [?\C-x ?f])
    (fill-paragraph [?\M-q])


    ;; * SEARCHING
    (isearch-forward [?\C-s])
    (isearch-backward [?\C-r])


    ;; * MULTIPLE WINDOWS
    (split-window-vertically [?\C-x ?2])
    (scroll-other-window [?\C-\M-v])
    (other-window [?\C-x ?o])
    (find-file-other-window [?\C-x ?4 ?\C-f])


    ;; * RECURSIVE EDITING LEVELS
    (keyboard-escape-quit [27 27 27])


    ;; * GETTING MORE HELP
    ;; The most basic HELP feature is C-h c
    (describe-key-briefly [?\C-h ?c])
    (describe-key [?\C-h ?k])


    ;; * MORE FEATURES
    ;; F10


    ;; * CONCLUSION
    (iconify-or-deiconify-frame [?\C-z])
    )
  "Default Emacs key bindings that are used in the tutorial")

(defun help-tutorial-sort-keys (left right)
  "Sort predicate for use with `help-tutorial-default-keys'.
This is a predicate function to `sort'.

The sorting is for presentation purpose only and is done on the
key sequence."
  (let ((x (append (cadr left)  nil))
        (y (append (cadr right) nil)))
    ;; Skip the front part of the key sequences if they are equal:
    (while (and x y
                (equal (car x) (car y)))
      (setq x (cdr x))
      (setq y (cdr y)))
    ;; Try to make a comparition that is useful for presentation (this
    ;; could be made nicer perhaps):
    (let ((cx (car x))
          (cy (car y)))
      (cond ((and (listp cx)
                  (listp cy))
             (> (length cx)(length cy)))
            ((listp cx)
             nil)
            ((listp cy)
             t)
            ((and (symbolp cx)
                  (symbolp cy))
             (string< (symbol-name cy)
                      (symbol-name cx)))
            ((symbolp cx)
             nil)
            ((symbolp cy)
             t)
            (t
             (> (car x)(car y)))))))

;;;###autoload
(defun help-with-tutorial (&optional arg dont-ask-for-revert)
  "Select the Emacs learn-by-doing tutorial.
If there is a tutorial version written in the language
of the selected language environment, that version is used.
If there's no tutorial in that language, `TUTORIAL' is selected.
With ARG, you are asked to choose which language.
If DONT-ASK-FOR-REVERT is non-nil the buffer is reverted without
any question when restarting the tutorial."
  (interactive "P")
  (let* ((lang (if arg
                   (let ((minibuffer-setup-hook minibuffer-setup-hook))
                     (add-hook 'minibuffer-setup-hook
                               'minibuffer-completion-help)
                     (read-language-name 'tutorial "Language: " "English"))
                 (if (get-language-info current-language-environment 'tutorial)
                     current-language-environment
                   "English")))
         (filename (get-language-info lang 'tutorial))
         ;; Choose a buffer name including the language so that
         ;; several languages can be tested simultaneously:
         (tut-buf-name (concat "TUTORIAL (" lang ")"))
         (old-tut-buf (get-buffer tut-buf-name))
         (old-tut-win (when old-tut-buf (get-buffer-window old-tut-buf t)))
         (old-tut-is-ok (when old-tut-buf
                          (not (buffer-modified-p old-tut-buf))))
         (point-after-message 1))
    ;; Try to display the tutorial buffer before asking to revert it.
    ;; If the tutorial buffer is shown in some window make sure it is
    ;; selected and displayed:
    (if old-tut-win
        (raise-frame
         (window-frame
          (select-window (get-buffer-window old-tut-buf t))))
      ;; Is there an old tutorial buffer? Then display it:
      (when old-tut-buf
        (switch-to-buffer old-tut-buf)))
    ;; If the tutorial buffer has been changed then ask if it should
    ;; be reverted:
    (when (and old-tut-buf
               (not old-tut-is-ok))
      (setq old-tut-is-ok
            (if dont-ask-for-revert
                nil
              (not (y-or-n-p
                    "You have changed the Tutorial buffer.  Revert it? ")))))
    ;; Use whole frame for tutorial
    (delete-other-windows)
    ;; (Re)build the tutorial buffer if it is not ok
    (unless old-tut-is-ok
      (switch-to-buffer (get-buffer-create tut-buf-name))
      (let ((inhibit-read-only t))
        (erase-buffer))
      (message "Preparing tutorial ...")(sit-for 0)

      (setq default-directory (expand-file-name "~/"))
      (setq buffer-auto-save-file-name nil)
      (insert-file-contents (expand-file-name filename data-directory))
      (hack-local-variables)


      ;; Check if there are key bindings that may disturb the
      ;; tutorial.  If so tell the user.
      (let* (changed-keys
             (default-keys (sort help-tutorial-default-keys
                                 'help-tutorial-sort-keys))
             ;; On window system suspend Emacs is replaced in the
             ;; default keymap so honor this here. (Is this true for
             ;; all window-system?  It is at least done in mac-win.el,
             ;; w32-win.el and x-win.el.)
             (suspend-emacs (if window-system
                                'iconify-or-deiconify-frame
                              'suspend-emacs))
             ;; Make key bindings for moving between link fields in
             ;; the list of changed key bindings.
             (tab-map (let ((map (make-sparse-keymap)))
                        (define-key map [tab] 'forward-button)
                        (define-key map [(shift tab)] 'backward-button)
                        (define-key map [(meta tab)] 'backward-button)
                        map)))

        (let (expr
              key
              def-fun
              def-fun-txt
              rem-fun
              key-fun
              where
              remark
              )
          ;; Check if the default Emacs key bindings that are used in
          ;; the tutorial have been changed.:
          (dolist (kdf default-keys)
            (setq key     (nth 1 kdf))
            (setq def-fun (nth 0 kdf))
            (setq def-fun-txt (format "%s" def-fun))
            (setq rem-fun (command-remapping def-fun))
            (setq key-fun (key-binding key))
            (setq where (where-is-internal (if rem-fun rem-fun def-fun)))
            (if where
                (progn
                  (setq where (key-description (car where)))
                  (when (and (< 10 (length where))
                             (string= (substring where 0 (length "<menu-bar>"))
                                      "<menu-bar>"))
                    (setq where "The menus")))
              (setq where ""))
            (setq remark nil)
            (unless
                (cond ( (eq key-fun def-fun)
                        t)
                      ( (eq key-fun (command-remapping def-fun))
                        (setq remark (list "Remapped" nil))
                        t)
                      ;; cua-mode specials:
                      ( (and cua-mode
                             (or (and
                                  (equal key [?\C-v])
                                  (eq key-fun 'cua-paste))
                                 (and
                                  (equal key [?\C-z])
                                  (eq key-fun 'undo))))
                        (setq remark (list "cua-mode, more info" 'cua-mode))
                        nil)
                      ( (and cua-mode
                             (or
                              (and (eq def-fun 'ESC-prefix)
                                   (equal key-fun
                                          `(keymap
                                            (118 . cua-repeat-replace-region))))
                              (and (eq def-fun 'mode-specific-command-prefix)
                                   (equal key-fun
                                          '(keymap
                                            (timeout . copy-region-as-kill))))
                              (and (eq def-fun 'Control-X-prefix)
                                   (equal key-fun
                                          '(keymap (timeout . kill-region))))))
                        (setq remark (list "cua-mode replacement" 'cua-mode))
                        (cond
                         ((eq def-fun 'mode-specific-command-prefix)
                          (setq def-fun-txt "\"C-c prefix\""))
                         ((eq def-fun 'Control-X-prefix)
                          (setq def-fun-txt "\"C-x prefix\""))
                         ((eq def-fun 'ESC-prefix)
                          (setq def-fun-txt "\"ESC prefix\"")))
                        (setq where "Same key")
                        nil)
                      ;; viper-mode specials:
                      ( (and (boundp 'viper-mode)
                             viper-mode
                             (eq viper-current-state 'vi-state)
                             (or (and (eq def-fun 'isearch-forward)
                                      (eq key-fun 'viper-isearch-forward))
                                 (and (eq def-fun 'isearch-backward)
                                      (eq key-fun 'viper-isearch-backward))))
                        t)
                      ;; The strange handling of C-delete and
                      ;; C-backspace:
                      ( (when normal-erase-is-backspace
                          (or (and (equal key [C-delete])
                                   (equal key-fun 'kill-word))
                              (and (equal key [C-backspace])
                                   (equal key-fun 'backward-kill-word))))
                        t)
                      ( t
                        (setq remark
                              (list "more info" 'current-binding
                                    key-fun def-fun key where))
                        nil))
              (add-to-list 'changed-keys
                           (list key def-fun def-fun-txt where remark)))))

        ;; Clear message:
        (unless dont-ask-for-revert
          (message "")(sit-for 0))

        ;; If some Emacs default key bindings have been changed then
        ;; display the changes in the tutorial buffer with some
        ;; explanatory links:
        (when (or changed-keys
                  (and (boundp 'viper-mode)
                       viper-mode))
          ;; Need the custom button face for viper buttons:
          (when (and (boundp 'viper-mode)
                     viper-mode)
            (require 'cus-edit))
          (forward-line)
          (let ((start (point))
                end)
            (insert "
 NOTICE: One of the main purposes of the tutorial is that You should
 be able to learn some important Emacs default key bindings.  However
 when you started the tutorial the following key bindings used in the
 tutorial had been changed from Emacs default:\n\n" )
            (when changed-keys
              (let ((frm "   %-9s %-27s %-11s %s\n"))
                (insert (format frm "KEY" "DEFAULT BINDING" "IS NOW ON" "REMARK")))
              (dolist (tk changed-keys)
                (let* ((def-fun     (nth 1 tk))
                       (key         (nth 0 tk))
                       (def-fun-txt (nth 2 tk))
                       (where       (nth 3 tk))
                       (remark      (nth 4 tk))
                       (rem-fun (command-remapping def-fun))
                       (key-txt (key-description key))
                       (key-fun (key-binding key))
                       tot-len)
                  (unless (eq def-fun key-fun)
                    ;; Insert key binding description:
                    (insert "   " key-txt " ")
                    (setq tot-len (length key-txt))
                    (when (> 9 tot-len)
                      (insert (make-string (- 9 tot-len) ? ))
                      (setq tot-len 9))
                    ;; Insert a link describing the old binding:
                    (insert-button def-fun-txt
                                   'value def-fun
                                   'action
                                   (lambda(button) (interactive)
                                     (describe-function
                                      (button-get button 'value)))
                                   'follow-link t
                                   'face '(:inherit link
                                                    :background "yellow"))
                    (setq tot-len (+ tot-len (length def-fun-txt)))
                    (when (> 36 tot-len)
                      (insert (make-string (- 36 tot-len) ? )))
                    (when (listp where)
                      (setq where "list"))
                    ;; Tell where the old binding is now:
                    (insert (format " %-11s " where))
                    ;; Insert a link with more information, for example
                    ;; current binding and keymap or information about
                    ;; cua-mode replacements:
                    (insert-button (car remark)
                                   'action
                                   (lambda(b) (interactive)
                                     (let ((value (button-get b 'value)))
                                       (help--describe-nonstandard-key value)))
                                   'value (cdr remark)
                                   'follow-link t
                                   'face '(:inherit link
                                                    :background "yellow"))
                    (insert "\n")))))

            ;; Viper turns itself off in the tutorial buffer by
            ;; default. Explain this and add some more information
            ;; about it:
            (when (and (boundp 'viper-mode)
                       viper-mode)
              (insert "\n   INFORMATION ABOUT VIPER\n")
              (cond
               ((eq viper-current-state 'emacs-state)
                (insert "
   You have enabled Viper mode, but in the tutorial buffer Viper
   mode is currently turned off.  You can however turn it on if
   you want to.  This may enable you to see what key bindings
   that Viper conflicts with:\n     ")
                (insert-button " Turn on Viper here! "
                               'action
                               (lambda(b) (interactive)
                                 (let ((arg (button-get b 'value)))
                                   (viper-mode)
                                   (set-buffer-modified-p t)
                                   (help-with-tutorial arg t)))
                               'value arg
                               'follow-link t
                               'face 'custom-button
                               'mouse-face 'custom-button-mouse
                               )
                ;;(insert ")")
                )
               (t
                (insert "
   You have enabled Viper mode in the tutorial buffer.  Some of
   the changed key bindings above depends on the Viper state.
   When you started the tutorial the Viper state was ")
                (cond
                 ((eq viper-current-state 'vi-state)
                  (insert "vi."))
                 (t
                  (insert "some insert state.")))
                (insert "\n     ")
                (insert-button " Turn off Viper here! "
                               'action
                               (lambda(b) (interactive)
                                 (let ((arg (button-get b 'value)))
                                   (kill-buffer (current-buffer))
                                   (help-with-tutorial arg t)))
                               'value arg
                               'follow-link t
                               'face 'custom-button
                               'mouse-face 'custom-button-mouse)
                (insert "  ")
                (cond
                 ((eq viper-current-state 'vi-state)
                  (insert-button " Restart tutorial in Viper insert state! "
                                 'action
                                 (lambda(b) (interactive)
                                   (let ((arg (button-get b 'value)))
                                     (viper-insert nil)
                                     (set-buffer-modified-p t)
                                     (help-with-tutorial arg t)))
                                 'value arg
                                 'follow-link t
                                 'face 'custom-button
                                 'mouse-face 'custom-button-mouse))
                 ((not (eq viper-current-state 'vi-state))
                  (insert-button " Restart tutorial in Viper vi state! "
                                 'action
                                 (lambda(b) (interactive)
                                   (let ((arg (button-get b 'value))
                                         (cmd
                                          (cond ((eq viper-current-state 'vi-state)
                                                 'viper-ESC)
                                                ((eq viper-current-state 'insert-state)
                                                 'viper-exit-insert-state)
                                                ((eq viper-current-state 'replace-state)
                                                 'viper-replace-state-exit-cmd)
                                                (t 'viper-change-state-to-vi)
                                                )))
                                     (call-interactively cmd)
                                     (set-buffer-modified-p t)
                                     (help-with-tutorial arg t)))
                                 'value arg
                                 'follow-link t
                                 'face 'custom-button
                                 'mouse-face 'custom-button-mouse)))))
              (insert "\n   If you want to learn Viper keys please see the ")
              (insert-button "Viper manual"
                             'action
                             (lambda(button) (interactive)
                               (info-other-window "(viper)")
                               (message "Type C-x 0 to close the new window"))
                             'follow-link t
                             'face '(:inherit link
                                              :background "yellow"))
              (insert ".\n"))

            (insert "
 It is legitimate to change key bindings, but changed bindings do not
 correspond to what the tutorial says.  (See also " )
            (insert-button "Key Binding Conventions"
                           'action
                           (lambda(button) (interactive)
                             (info-other-window
                              "(elisp) Key Binding Conventions")
                             (message "Type C-x 0 to close the new window"))
                           'follow-link t
                           'face '(:inherit link
                                            :background "yellow"))
            (insert ".)\n\n")
            (setq end (point))
            ;; Make the area with information about change key
            ;; bindings stand out:
            (put-text-property start end
                               'face
                               ;; The default warning face does not
                               ;;look good in this situation. Instead
                               ;;try something that could be
                               ;;recognized from warnings in normal
                               ;;life:
                               ;; 'font-lock-warning-face
                               (list :background "yellow" :foreground "#c00"))
            ;; Make it possible to use Tab/S-Tab between fields in
            ;; this area:
            (put-text-property start end 'local-map tab-map)
            ;; Make this area read-only:
            (put-text-property start end 'read-only t))))

      (setq point-after-message (point))

      (goto-char (point-min))
      (search-forward "\n<<")
      (beginning-of-line)
      ;; Convert the <<...>> line to the proper [...] line,
      ;; or just delete the <<...>> line if a [...] line follows.
      (cond ((save-excursion
               (forward-line 1)
               (looking-at "\\["))
             (delete-region (point) (progn (forward-line 1) (point))))
            ((looking-at "<<Blank lines inserted.*>>")
             (replace-match "[Middle of page left blank for didactic purposes.   Text continues below]"))
            (t
             (looking-at "<<")
             (replace-match "[")
             (search-forward ">>")
             (replace-match "]")))
      (beginning-of-line)
      (let ((n (- (window-height (selected-window))
                  (count-lines (point-min) (point))
                  6)))
        (if (< n 8)
            (progn
              ;; For a short gap, we don't need the [...] line,
              ;; so delete it.
              (delete-region (point) (progn (end-of-line) (point)))
              (newline n))
          ;; Some people get confused by the large gap.
          (newline (/ n 2))

          ;; Skip the [...] line (don't delete it).
          (forward-line 1)
          (newline (- n (/ n 2)))))
      (goto-char (point-min))
      (setq buffer-undo-list nil)
      (set-buffer-modified-p nil))))

[-- Attachment #3: Type: text/plain, Size: 142 bytes --]

_______________________________________________
Emacs-devel mailing list
Emacs-devel@gnu.org
http://lists.gnu.org/mailman/listinfo/emacs-devel

^ permalink raw reply	[flat|nested] 29+ messages in thread

end of thread, other threads:[~2006-07-30 20:38 UTC | newest]

Thread overview: 29+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2006-06-24 14:09 Patch to remove minor modes in tutorial Lennart Borgman
2006-06-25 15:34 ` Richard Stallman
2006-06-25 21:27   ` Lennart Borgman
2006-06-26 11:33     ` Richard Stallman
2006-06-26 13:48       ` Lennart Borgman
2006-06-26 16:31         ` Kevin Rodgers
2006-06-26 16:45           ` Lennart Borgman
2006-06-27 15:44             ` Kevin Rodgers
2006-06-27 16:41               ` Lennart Borgman
2006-06-28 17:25               ` Richard Stallman
2006-06-29  8:41                 ` Kim F. Storm
2006-06-29 12:07                   ` Mathias Dahl
2006-06-29 12:27                     ` David Kastrup
2006-06-30 11:06                       ` Richard Stallman
2006-06-29 17:57                   ` Richard Stallman
2006-07-01  0:38                     ` Lennart Borgman
2006-07-01 23:55                       ` Richard Stallman
2006-07-02  8:54                         ` Lennart Borgman
2006-07-02 22:30                           ` Richard Stallman
2006-07-07  0:01                             ` Lennart Borgman
2006-07-07 19:31                               ` Richard Stallman
2006-07-08  3:14                               ` Giorgos Keramidas
2006-07-08 20:57                               ` Richard Stallman
2006-07-09  8:44                                 ` Lennart Borgman
2006-07-17 16:12                                 ` Lennart Borgman
2006-07-17 17:32                                   ` Lennart Borgman
2006-07-24 14:42                                     ` Richard Stallman
2006-07-30 20:38                                       ` Lennart Borgman
2006-06-27 16:14         ` Richard Stallman

Code repositories for project(s) associated with this public inbox

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

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).