all messages for Emacs-related lists mirrored at yhetil.org
 help / color / mirror / code / Atom feed
* Re: cua-mode and the tutorial
       [not found] <44C8F069.1070002@student.lu.se>
@ 2006-08-22 13:12 ` Kim F. Storm
  2006-08-22 13:26   ` Kim F. Storm
  2006-08-22 14:05   ` Lennart Borgman
  0 siblings, 2 replies; 40+ messages in thread
From: Kim F. Storm @ 2006-08-22 13:12 UTC (permalink / raw)
  Cc: emacs-devel

Lennart Borgman <lennart.borgman.073@student.lu.se> writes:

> Hi Kim,
>
> I am trying to merge info about cua-mode and viper-mode into the
> tutorial. Can you please look at the attached file and give some
> comments? 

I don't see any problem with the things you have written about
cua-mode as such.

However, the statement "you have enabled cua-mode" may very
well be false  (if someone is able to enable cua-mode, they
are likely to be past tutorial state).  So maybe the text
should be "cua-mode is enabled".



>           Especially what should be said about the ESC key.

I don't use viper, so I prefer not to answer that question!

I tried to enter the tutorial after enabling viper-mode,
but I didn't see any information about VIPER in the help
buffer...  so I don't know how to activate the stuff about
vi in your patch...


In any case, I think that emacs should simply reject to run the
tutorial if VIPER is enabled (or turn it off in the tutorial and NOT
give the option to enable it in the tutorial).
  
The current code to deal with this is overly complex -- and
the tutorial is about learning to use basic Emacs bindings.

Does the tutorial make sense at all in viper mode???


BTW, the patch mixes two sets of changes ... for the key binding
stuff and for running multiple tutorials at the same time.

The latter part should IMO, never be installed -- it is just
too obscure for normal users!


>
> Best wishes,
> L
> (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)))))
>
> (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
>                                    '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"))
>                     ;; 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     ")
>                 (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 "  ")
>                 (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 "\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
>                                ;; 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"))
>             (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))
>       (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))))

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

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

* Re: cua-mode and the tutorial
  2006-08-22 13:12 ` cua-mode and the tutorial Kim F. Storm
@ 2006-08-22 13:26   ` Kim F. Storm
  2006-08-22 14:30     ` Lennart Borgman
  2006-08-23  4:06     ` Richard Stallman
  2006-08-22 14:05   ` Lennart Borgman
  1 sibling, 2 replies; 40+ messages in thread
From: Kim F. Storm @ 2006-08-22 13:26 UTC (permalink / raw)
  Cc: emacs-devel

storm@cua.dk (Kim F. Storm) writes:

> I tried to enter the tutorial after enabling viper-mode,
> but I didn't see any information about VIPER in the help
> buffer...  so I don't know how to activate the stuff about
> vi in your patch...

Well, I tried again, and now I see it -- and I still think
my objection below is valid.

> In any case, I think that emacs should simply reject to run the
> tutorial if VIPER is enabled (or turn it off in the tutorial and NOT
> give the option to enable it in the tutorial).
>   
> The current code to deal with this is overly complex -- and
> the tutorial is about learning to use basic Emacs bindings.
>
> Does the tutorial make sense at all in viper mode???

The first instruction is to type C-v ... and it doesn't work
as described!


However, in general, your changes have a big problem.
The new informational (yellow) area may take so much
space on the frame that the instructions:

    >>  Now type C-v (View next screen) to move to the next screen.
	(go ahead, do it by holding down the CONTROL key while typing v).
	From now on, you should do this again whenever you finish
	reading the screen.

is partially or even completely hidden, so the whole point of the
tutorial is lost (you have to know how to scroll before you can
learn how to scroll ...).


It would be much better if you just placed a few yellow lines
near the top with the following wording:

 Some of the standard key bindings described in this tutorial
 have been modified, so Emacs may behave differently from
 what you learn here.  Click here for more details: [Details]

And then restore all key bindings (if possible) to their default
inside the tutorial.


This way, you can also structure your code so there is:
- one function which simply checks if any keys are changed
- one function which setup the standard key bindings
- one function to show the details (in a *Help* buffer).


WDYT?  WDOT?


>
>
> BTW, the patch mixes two sets of changes ... for the key binding
> stuff and for running multiple tutorials at the same time.
>
> The latter part should IMO, never be installed -- it is just
> too obscure for normal users!

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

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

* Re: cua-mode and the tutorial
  2006-08-22 13:12 ` cua-mode and the tutorial Kim F. Storm
  2006-08-22 13:26   ` Kim F. Storm
@ 2006-08-22 14:05   ` Lennart Borgman
  1 sibling, 0 replies; 40+ messages in thread
From: Lennart Borgman @ 2006-08-22 14:05 UTC (permalink / raw)
  Cc: Michael Kifer, emacs-devel

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

Hi Kim,

I have made quite a few changes since I last sent this to you. Richard 
proposed different wordings and some rework which I have done. Currently 
I think that Richard is satisfied with the patch. Michael has said it is 
ok for Viper. (But I have made some changes after that. However I asked 
about his opinion about the idea of telling about some of the more 
important clashes with Viper and I think he thought that was good.)

I have attached the version which I sent last time to Richard (with just 
the small change in wording that Kim proposed below). The new version 
lives in a file of its own, tutorial.el.

I am sorry for the confusion that it raises that you did not get this 
version before. I somehow thought you were not interested since I did 
not hear from you.


Kim F. Storm wrote:
> I don't see any problem with the things you have written about
> cua-mode as such.
>
> However, the statement "you have enabled cua-mode" may very
> well be false  (if someone is able to enable cua-mode, they
> are likely to be past tutorial state).  So maybe the text
> should be "cua-mode is enabled".
>   
I have changed it.
> I tried to enter the tutorial after enabling viper-mode,
> but I didn't see any information about VIPER in the help
> buffer...  so I don't know how to activate the stuff about
> vi in your patch...
>   
I have made that explicit now.
>
> In any case, I think that emacs should simply reject to run the
> tutorial if VIPER is enabled (or turn it off in the tutorial and NOT
> give the option to enable it in the tutorial).
>   
Viper is not enabled in the tutorial buffer by default. However I now 
offer the possibility to enable it so that the user can see the more 
important key clashes.

I think this is good for Viper users. Users who does not use Viper is 
not affected by this at all.

> BTW, the patch mixes two sets of changes ... for the key binding
> stuff and for running multiple tutorials at the same time.
>
> The latter part should IMO, never be installed -- it is just
> too obscure for normal users!
>   
There are some more changes too.

Can you please tell me what is wrong with beeing able to run a tutorial 
in for example German and another in English? Is that really obscure? 
(Please look at the version I attach here.)

[-- Attachment #2: tutorial.el --]
[-- Type: text/plain, Size: 35615 bytes --]

;;; tutorial.el --- tutorial for Emacs

;; Copyright (C) 2006 Free Software Foundation, Inc.

;; Maintainer: FSF
;; Keywords: help, internal

;; This file is part of GNU Emacs.

;; GNU Emacs is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation; either version 2, or (at your option)
;; any later version.

;; GNU Emacs is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
;; GNU General Public License for more details.

;; You should have received a copy of the GNU General Public License
;; along with GNU Emacs; see the file COPYING.  If not, write to the
;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
;; Boston, MA 02110-1301, USA.


;;; Commentary:

;; Code for running the Emacs tutorial.


;;; History:

;; File was created 2006-08.


;;; Code:

(defun tutorial--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.

VALUE should have either of these formats:

  \(cua-mode)
  \(current-binding KEY-FUN DEF-FUN KEY WHERE)

Where
  KEY         is a key sequence whose standard binding has been changed
  KEY-FUN     is the actual binding for KEY
  DEF-FUN     is the standard binding of KEY
  WHERE       is a text describing the key sequences to which DEF-FUN is
              bound now (or, if it is remapped, a key sequence
              for the function it is remapped to)"
  (with-output-to-temp-buffer (help-buffer)
    (help-setup-xref (list #'tutorial--describe-nonstandard-key value)
                     (interactive-p))
    (with-current-buffer (help-buffer)
      (insert
       "Your Emacs customizations override the default binding for this key:"
       "\n\n")
      (let ((inhibit-read-only t))
        (cond
         ((eq (car value) 'cua-mode)
          (insert
           "CUA mode is enabled.

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
                (maps (current-active-maps))
                mapsym)
            ;; Look at the currently active keymaps and try to find
            ;; first the keymap where the current 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))))
            ;; Now, if a keymap was found we must found the symbol
            ;; name for it to display to the user.  This can not
            ;; always be found since all keymaps does not have a
            ;; symbol pointing to them, but here they should have
            ;; that:
            (when map
              (mapatoms (lambda (s)
                          (and
                           ;; If not already found
                           (not mapsym)
                           ;; and if s is a keymap
                           (and (boundp s)
                                (keymapp (symbol-value s)))
                           ;; and not the local symbol map
                           (not (eq s 'map))
                           ;; and the value of s is map
                           (eq map (symbol-value s))
                           ;; then save this value in mapsym
                           (setq mapsym s)))))
            (insert "The default Emacs binding for the key "
                    (key-description key)
                    " is the command `")
            (insert (format "%s" db))
            (insert "'.  "
                    "However, your customizations have rebound it to the command `")
            (insert (format "%s" cb))
            (insert "'.")
            (when mapsym
              (insert "  (For the more advanced user:"
                      " This binding is in the keymap `"
                      (format "%s" mapsym)
                      "'.)"))
            (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-chkeys))))

(defvar tutorial--default-keys
  (let (
        ;; On window system suspend Emacs is replaced in the
        ;; default keymap so honor this here.
        (suspend-emacs (if window-system
                           'iconify-or-deiconify-frame
                         'suspend-emacs)))
    `(
      ;; 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])
      (,suspend-emacs [?\C-z])
      ))
  "Default Emacs key bindings that the tutorial depends on.")

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

The sorting is for presentation purpose only and is done on the
key sequence.

LEFT and RIGHT are the elements to compare."
  (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
                (listp x) (listp y)
                (equal (car x) (car y)))
      (setq x (cdr x))
      (setq y (cdr y)))
    ;; Try to make a comparision that is useful for presentation (this
    ;; could be made nicer perhaps):
    (let ((cx (car x))
          (cy (car y)))
      ;;(message "x=%s, y=%s;;;; cx=%s, cy=%s" x y cx cy)
      (cond
       ;; Lists? Then call this again
       ((and cx cy
             (listp cx)
             (listp cy))
        (tutorial--sort-keys cx cy))
       ;; Are both numbers? Then just compare them
       ((and (wholenump cx)
             (wholenump cy))
        (> cx cy))
       ;; Is one of them a number? Let that be bigger then.
       ((wholenump cx)
        t)
       ((wholenump cy)
        nil)
       ;; Are both symbols? Compare the names then.
       ((and (symbolp cx)
             (symbolp cy))
        (string< (symbol-name cy)
                 (symbol-name cx)))
       ))))

(defun tutorial--find-changed-keys ()
  "Find the key bindings that have changed.
Check if the default Emacs key bindings that the tutorial depends
on have been changed.

Return a list with the keys that have been changed.  The element
of this list have the following format:

  \(list KEY DEF-FUN DEF-FUN-TXT WHERE REMARK)

Where
  KEY         is a key sequence whose standard binding has been changed
  DEF-FUN     is the standard binding of KEY
  DEF-FUN-TXT is a short descriptive text for DEF-FUN
  WHERE       is a text describing the key sequences to which DEF-FUN is
              bound now (or, if it is remapped, a key sequence
              for the function it is remapped to)
  REMARK      is a list with info about rebinding. It has either of these
              formats:

                \(TEXT cua-mode)
                \(TEXT current-binding KEY-FUN DEF-FUN KEY WHERE)

              Here TEXT is a link text to show to the user.  The
              rest of the list is used to show information when
              the user clicks the link.

              KEY-FUN is the actual binding for KEY."
  (let (changed-keys
        (default-keys (sort tutorial--default-keys
                            'tutorial--sort-keys)))
    (dolist (kdf default-keys)
      ;; The variables below corresponds to those with the same names
      ;; described in the doc string.
      (let* ((key     (nth 1 kdf))
             (def-fun (nth 0 kdf))
             (def-fun-txt (format "%s" def-fun))
             (rem-fun (command-remapping def-fun))
             (key-fun (key-binding key))
             (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)
                   ;; No rebinding, return t
                   t)
                  ((eq key-fun (command-remapping def-fun))
                   ;; Just a remapping, return t
                   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))))
                   ;; These bindings works as the default bindings,
                   ;; return t
                   t)
                  ((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))))
                   ;; This is the strange handling of C-delete and
                   ;; C-backspace, return t
                   t)
                  (t
                   ;; This key has indeed been rebound. Put information
                   ;; in `remark' and return nil
                   (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)))))
    changed-keys))

(defun tutorial--display-changes (changed-keys)
  "Display changes to some default key bindings.
If some of the default key bindings that the tutorial depends on
have been changed then display the changes in the tutorial buffer
with some explanatory links.

CHANGED-KEYS should be a list in the format returned by
`tutorial--find-changed-keys'."
  (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))
    (goto-char tutorial--point-before-chkeys)
    (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" "Standard Binding" "That's 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)))
                                 (tutorial--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))
         (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:
      (let ((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)))
        (put-text-property start end 'local-map tab-map))
      (setq tutorial--point-after-chkeys (point-marker))
      ;; Make this area read-only:
      (put-text-property start end 'read-only t))))

(defvar tutorial--point-before-chkeys 0
  "Point before display of key changes.")
(make-variable-buffer-local 'tutorial--point-before-chkeys)
(defvar tutorial--point-after-chkeys 0
  "Point after display of key changes.")
(make-variable-buffer-local 'tutorial--point-after-chkeys)

(defvar tutorial--lang nil
  "Tutorial language.")
(make-variable-buffer-local 'tutorial--lang)

(defun tutorial--saved-dir ()
  "Directory where to save tutorials."
  (expand-file-name ".emacstut" "~/"))

(defun tutorial--saved-file ()
  "File name in which to save tutorials."
  (let ((file-name tutorial--lang)
        (ext (file-name-extension tutorial--lang)))
    (when (or (not ext)
              (string= ext ""))
      (setq file-name (concat file-name ".tut")))
    (expand-file-name file-name (tutorial--saved-dir))))

(defun tutorial--save-tutorial ()
  "Save the tutorial buffer.
This saves the part of the tutorial before and after the area
showing changed keys.  It also saves the point position and the
position where the display of changed bindings was inserted."
  ;; Anything to save?
  (when (or (buffer-modified-p)
            (< 1 (point)))
    (let ((tutorial-dir (tutorial--saved-dir))
          save-err)
      ;; The tutorial is saved in a subdirectory in the user home
      ;; directory. Create this subdirectory first.
      (unless (file-directory-p tutorial-dir)
        (condition-case err
            (make-directory tutorial-dir nil)
          (error (setq save-err t)
                 (warn "Could not create directory %s: %s" tutorial-dir
                       (error-message-string err)))))
      ;; Make sure we have that directory.
      (if (file-directory-p tutorial-dir)
          (let ((tut-point (if (= 0 tutorial--point-after-chkeys)
                               ;; No area display changed keys
                               (point)
                             (if (< (point) tutorial--point-after-chkeys)
                                 (- (point))
                               (- (point) tutorial--point-after-chkeys))))
                (old-point (point))
                ;; Use a special undo list so that we easily can undo
                ;; the changes we make to the tutorial buffer.  This is
                ;; currently not needed since we now delete the buffer
                ;; after saving, but kept for possible future use of
                ;; this function.
                buffer-undo-list
                (inhibit-read-only t))
            ;; Delete the area displaying info about changed keys.
            (when (< 0 tutorial--point-after-chkeys)
              (delete-region tutorial--point-before-chkeys
                             tutorial--point-after-chkeys))
            ;; Put the value of point first in the buffer so we can
            ;; write it.
            (goto-char (point-min))
            (insert (number-to-string tut-point)
                    "\n"
                    (number-to-string (marker-position
                                       tutorial--point-before-chkeys))
                    "\n")
            (condition-case err
                (write-region nil nil (tutorial--saved-file))
              (error (setq save-err t)
                     (warn "Could not save tutorial to %s: %s"
                           (tutorial--saved-file)
                           (error-message-string err))))
            ;; Restore point
            ;; An error is raised here?? Is this a bug?
            (condition-case err
                (undo-only)
              (error nil))
            (goto-char old-point)
            (if save-err
                (message "Could not save tutorial state.")
              (message "Saved tutorial state.")))
        (message "Can't save tutorial: %s is not a directory"
                 tutorial-dir)))))

;;;###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.

If any of the standard Emacs key bindings that are used in the
tutorial have been changed then an explanatory note about this is
shown in the beginning of the tutorial buffer.

When the tutorial buffer is killed the content and the point
position in the buffer is saved so that the tutorial may be
resumed later."
  (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))))
         old-tut-file
         (old-tut-point 1))
    (setq tutorial--point-after-chkeys (point-min))
    ;; 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))))
      ;; Else, is there an old tutorial buffer? Then display it:
      (when old-tut-buf
        (switch-to-buffer old-tut-buf)))
    ;; Use whole frame for tutorial
    (delete-other-windows)
    ;; 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? ")))))
    ;; (Re)build the tutorial buffer if it is not ok
    (unless old-tut-is-ok
      (switch-to-buffer (get-buffer-create tut-buf-name))
      (unless lang (error "Variable lang is nil"))
      (setq tutorial--lang lang)
      (setq old-tut-file (file-exists-p (tutorial--saved-file)))
      (let ((inhibit-read-only t))
        (erase-buffer))
      (message "Preparing tutorial ...") (sit-for 0)

      ;; Do not associate the tutorial buffer with a file. Instead use
      ;; a hook to save it when the buffer is killed.
      (setq buffer-auto-save-file-name nil)
      (add-hook 'kill-buffer-hook 'tutorial--save-tutorial nil t)

      ;; Insert the tutorial. First offer to resume last tutorial
      ;; editing session.
      (when old-tut-file
        (setq old-tut-file
              (y-or-n-p "Resume your last saved tutorial? ")))
      (if old-tut-file
          (progn
            (insert-file-contents (tutorial--saved-file))
            (goto-char (point-min))
            (setq old-tut-point
                  (string-to-number
                   (buffer-substring-no-properties
                    (line-beginning-position) (line-end-position))))
            (forward-line)
            (setq tutorial--point-before-chkeys
                  (string-to-number
                   (buffer-substring-no-properties
                    (line-beginning-position) (line-end-position))))
            (forward-line)
            (delete-region (point-min) (point))
            (goto-char tutorial--point-before-chkeys)
            (setq tutorial--point-before-chkeys (point-marker)))
        (insert-file-contents (expand-file-name filename data-directory))
        (forward-line)
        (setq tutorial--point-before-chkeys (point-marker)))
      (hack-local-variables)


      ;; Check if there are key bindings that may disturb the
      ;; tutorial.  If so tell the user.
      (let ((changed-keys (tutorial--find-changed-keys)))
        (tutorial--display-changes changed-keys))


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


      (if old-tut-file
          ;; Just move to old point in saved tutorial.
          (let ((old-point
                 (if (> 0 old-tut-point)
                     (- old-tut-point)
                   (+ old-tut-point tutorial--point-after-chkeys))))
            (when (< old-point 1)
              (setq old-point 1))
            (goto-char old-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))))

(provide 'tutorial)

;;; tutorial.el ends here

[-- 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] 40+ messages in thread

* Re: cua-mode and the tutorial
  2006-08-22 13:26   ` Kim F. Storm
@ 2006-08-22 14:30     ` Lennart Borgman
  2006-08-22 15:02       ` Kim F. Storm
  2006-08-22 18:17       ` Richard Stallman
  2006-08-23  4:06     ` Richard Stallman
  1 sibling, 2 replies; 40+ messages in thread
From: Lennart Borgman @ 2006-08-22 14:30 UTC (permalink / raw)
  Cc: emacs-devel

Kim F. Storm wrote:
> The first instruction is to type C-v ... and it doesn't work
> as described!
>   
Do you mean that it does not work when cua-mode is enabled? Well, it is 
a problem. One solution would be to remove CUA mode from the tutorial 
buffer as you suggests. However I feel uncomfortable with that solution. 
It puts a burden on the user, "please learn this now, but later on you 
are going to use that".

A possible solution is perhaps to tell replace C-v in the tutorial with 
the actual key to use. However that requires rewriting the text since 
there are also sentences like "do it by holding down the CONTROL key 
while typing v". (And there are many languages to rewrite.) Maybe that 
sentence could be removed?

>
> However, in general, your changes have a big problem.
> The new informational (yellow) area may take so much
> space on the frame that the instructions:
>
>     >>  Now type C-v (View next screen) to move to the next screen.
> 	(go ahead, do it by holding down the CONTROL key while typing v).
> 	From now on, you should do this again whenever you finish
> 	reading the screen.
>
> is partially or even completely hidden, so the whole point of the
> tutorial is lost (you have to know how to scroll before you can
> learn how to scroll ...).
>   
That is a good point. However most users will still be able to scroll 
with the arrow keys and the mouse.


>
> It would be much better if you just placed a few yellow lines
> near the top with the following wording:
>
>  Some of the standard key bindings described in this tutorial
>  have been modified, so Emacs may behave differently from
>  what you learn here.  Click here for more details: [Details]
>   
Having less information there is maybe a solution, yes. And using help 
buffer for details. However I do believe that the tutorial should try to 
tell the actual key bindings that the user will use. Is not that much 
easier for those that use CUA mode for example?


> And then restore all key bindings (if possible) to their default
> inside the tutorial.
>   
This was my original thought, but now I think it is important to let 
users of CUA mode and Viper mode learn about basic key bindings 
differences. I think a lot of users will have CUA mode enabled.

>
> This way, you can also structure your code so there is:
> - one function which simply checks if any keys are changed
> - one function which setup the standard key bindings
> - one function to show the details (in a *Help* buffer).
>   
I have restructured the code in the version I sent in the last message. 
Sorry for the confusion.


I welcome ideas. It is not very easy to make this working well. I can 
see we have slightly different opinions about what the tutorial should 
do, teach actual bindings or default bindings or maybe both. I tried the 
last.

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

* Re: cua-mode and the tutorial
  2006-08-22 14:30     ` Lennart Borgman
@ 2006-08-22 15:02       ` Kim F. Storm
  2006-08-22 15:57         ` Lennart Borgman
  2006-08-22 18:17       ` Richard Stallman
  1 sibling, 1 reply; 40+ messages in thread
From: Kim F. Storm @ 2006-08-22 15:02 UTC (permalink / raw)
  Cc: emacs-devel

Lennart Borgman <lennart.borgman.073@student.lu.se> writes:

> Kim F. Storm wrote:
>> The first instruction is to type C-v ... and it doesn't work
>> as described!
>>   
> Do you mean that it does not work when cua-mode is enabled?

Yes, and neither with viper enabled.

> Well, it
> is a problem. One solution would be to remove CUA mode from the
> tutorial buffer as you suggests. However I feel uncomfortable with
> that solution. It puts a burden on the user, "please learn this now,
> but later on you are going to use that".

True.

>
> A possible solution is perhaps to tell replace C-v in the tutorial
> with the actual key to use. However that requires rewriting the text
> since there are also sentences like "do it by holding down the CONTROL
> key while typing v". (And there are many languages to rewrite.) Maybe
> that sentence could be removed?

It could.  But again there are many languages to consider, and
this is part of text files, not generated in Lisp.

>> is partially or even completely hidden, so the whole point of the
>> tutorial is lost (you have to know how to scroll before you can
>> learn how to scroll ...).
>>   
> That is a good point. However most users will still be able to scroll
> with the arrow keys and the mouse.

Yes.

>> It would be much better if you just placed a few yellow lines
>> near the top with the following wording:
>>
>>  Some of the standard key bindings described in this tutorial
>>  have been modified, so Emacs may behave differently from
>>  what you learn here.  Click here for more details: [Details]
>>   
> Having less information there is maybe a solution, yes. And using help
> buffer for details. However I do believe that the tutorial should try
> to tell the actual key bindings that the user will use. Is not that
> much easier for those that use CUA mode for example?

But it gives it in the wrong language (except for the English tutorial).

Having just a few lines in English is ok IMO.

>> And then restore all key bindings (if possible) to their default
>> inside the tutorial.
>>   
> This was my original thought, but now I think it is important to let
> users of CUA mode and Viper mode learn about basic key bindings
> differences. I think a lot of users will have CUA mode enabled.

I hope so :-)  but with cua-mode enabled, many basic things in 
the tutorial could be explained quite differently -- but there 
is no way to do than in >1 languages.

> I welcome ideas. It is not very easy to make this working well. I can
> see we have slightly different opinions about what the tutorial should
> do, teach actual bindings or default bindings or maybe both. I tried
> the last.

I don't really care that much (it's a long time since I needed to run
the tutorial, and I never got used to the native bindings anyway).

But I still think it is confusing to offer a tutorial where the first
instruction given doesn't work if either of cua-mode or viper-mode is
enabled.

Substituting the key with the actual key isn't good either.
E.g. printing <next> instead of C-v isn't really good either ... my
keyboard doesn't have a <next> key.  And we really do want to
teach the standard emacs bindings.

Maybe you could highlight [yellow background] C-v (and similar
bindings used in the tutorial) if they have non-standard bindings.
Then users will be alerted to the fact that they don't work as
expected and they should consult the instructions at the beginning of
the tutorial!  You could even put a tool-tip on them to show the
actual binding to use instead.


I agree that it is difficult to do this right -- given that the tutorial
exists in many languages.

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

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

* Re: cua-mode and the tutorial
  2006-08-22 15:02       ` Kim F. Storm
@ 2006-08-22 15:57         ` Lennart Borgman
  0 siblings, 0 replies; 40+ messages in thread
From: Lennart Borgman @ 2006-08-22 15:57 UTC (permalink / raw)
  Cc: emacs-devel

Kim F. Storm wrote:
>> A possible solution is perhaps to tell replace C-v in the tutorial
>> with the actual key to use. However that requires rewriting the text
>> since there are also sentences like "do it by holding down the CONTROL
>> key while typing v". (And there are many languages to rewrite.) Maybe
>> that sentence could be removed?
>>     
>
> It could.  But again there are many languages to consider, and
> this is part of text files, not generated in Lisp.
>
>   
>>> It would be much better if you just placed a few yellow lines
>>> near the top with the following wording:
>>>
>>>   
>>>       
>> Having less information there is maybe a solution, yes. And using help
>> buffer for details. However I do believe that the tutorial should try
>> to tell the actual key bindings that the user will use. Is not that
>> much easier for those that use CUA mode for example?
>>     
>
> But it gives it in the wrong language (except for the English tutorial).
>
> Having just a few lines in English is ok IMO.
>   
Or maybe have them in the language choosen in form of some specially 
marked text in the text file?

I would like some more feedback from other on your suggestion above 
before I proceed.


> I hope so :-)  but with cua-mode enabled, many basic things in 
> the tutorial could be explained quite differently -- but there 
> is no way to do than in >1 languages.
>   
I would like pointers to CUA mode att relevant places (but not on too 
many places) in the manual.

> I don't really care that much (it's a long time since I needed to run
> the tutorial, and I never got used to the native bindings anyway).
>   
I think we might be a bit biased.

> Maybe you could highlight [yellow background] C-v (and similar
> bindings used in the tutorial) if they have non-standard bindings.
> Then users will be alerted to the fact that they don't work as
> expected and they should consult the instructions at the beginning of
> the tutorial!  You could even put a tool-tip on them to show the
> actual binding to use instead.
>   
I did that in one version. I made links going to the yellow part at the 
top. I could put it back.

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

* Re: cua-mode and the tutorial
  2006-08-22 14:30     ` Lennart Borgman
  2006-08-22 15:02       ` Kim F. Storm
@ 2006-08-22 18:17       ` Richard Stallman
  1 sibling, 0 replies; 40+ messages in thread
From: Richard Stallman @ 2006-08-22 18:17 UTC (permalink / raw)
  Cc: emacs-devel, storm

    Do you mean that it does not work when cua-mode is enabled? Well, it is 
    a problem. One solution would be to remove CUA mode from the tutorial 
    buffer as you suggests. However I feel uncomfortable with that solution. 
    It puts a burden on the user, "please learn this now, but later on you 
    are going to use that".

I think we just need to warn people that the tutorial is not useful
for learning to use Emacs with CUA mode.

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

* Re: cua-mode and the tutorial
  2006-08-22 13:26   ` Kim F. Storm
  2006-08-22 14:30     ` Lennart Borgman
@ 2006-08-23  4:06     ` Richard Stallman
  2006-08-23  4:37       ` Lennart Borgman
  2006-08-23  7:21       ` Kim F. Storm
  1 sibling, 2 replies; 40+ messages in thread
From: Richard Stallman @ 2006-08-23  4:06 UTC (permalink / raw)
  Cc: lennart.borgman.073, emacs-devel

    In any case, I think that emacs should simply reject to run the
    tutorial if VIPER is enabled

I tend to agree.  And I think it should be the same for CUA mode.

    It would be much better if you just placed a few yellow lines
    near the top with the following wording:

     Some of the standard key bindings described in this tutorial
     have been modified, so Emacs may behave differently from
     what you learn here.  Click here for more details: [Details]

    And then restore all key bindings (if possible) to their default
    inside the tutorial.

I don't see much point in teaching an absolute beginner standard Emacs
if that is not what he will get when he runs Emacs normally.

Another idea occurs to me: display the list of changed bindings
together with a message like this:

    The tutorial won't work for you, because someone
    has customized your Emacs, changing these basic commands.
    Probably whoever set up Emacs for you did it in a nonstandard way.
    Please ask him to teach you to use this nonstandard Emacs
    or else ask him to change your Emacs setup back to standard.

That has the benefit of being simple, avoiding all the problems
people are talking about now, and encouraging people not to
customize Emacs when they set it up for others.

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

* Re: cua-mode and the tutorial
  2006-08-23  4:06     ` Richard Stallman
@ 2006-08-23  4:37       ` Lennart Borgman
  2006-08-24  5:20         ` Richard Stallman
  2006-08-23  7:21       ` Kim F. Storm
  1 sibling, 1 reply; 40+ messages in thread
From: Lennart Borgman @ 2006-08-23  4:37 UTC (permalink / raw)
  Cc: emacs-devel, Kim F. Storm

Richard Stallman wrote:
> I don't see much point in teaching an absolute beginner standard Emacs
> if that is not what he will get when he runs Emacs normally.
>   
Maybe this is wishful thinking? That new users will use Emacs standard 
key bindings only? It is hard for me to believe they will.

Is it not plausible that they have been using CUA keys and want to use 
that in Emacs? I was one of the new users that would not have been using 
Emacs without CUA mode. A usability expert gave these three simple rules 
of thumb:

    Ease of use:
    how efficient is the software when used 40 hours a week.
    Ease of learning:
    how quickly can the user build an overview and feel in control of
    the software, when used for the first time.
    Ease of remembering:
    how familiar and reassuring is the software for the user, when it is
    used only occasionally.

The second rule seems to apply here.

Another big potential user base is of course those who used VIM or vi 
before. (I happen to be one of those too.)

> Another idea occurs to me: display the list of changed bindings
> together with a message like this:
>
>     The tutorial won't work for you, because someone
>     has customized your Emacs, changing these basic commands.
>     Probably whoever set up Emacs for you did it in a nonstandard way.
>     Please ask him to teach you to use this nonstandard Emacs
>     or else ask him to change your Emacs setup back to standard.
>   
Is it not quite likely that the person who set up Emacs is the user 
himself? He might have read some advice on how to get started and 
customized Emacs to use CUA mode.

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

* Re: cua-mode and the tutorial
  2006-08-23  4:06     ` Richard Stallman
  2006-08-23  4:37       ` Lennart Borgman
@ 2006-08-23  7:21       ` Kim F. Storm
  2006-08-24  5:20         ` Richard Stallman
  1 sibling, 1 reply; 40+ messages in thread
From: Kim F. Storm @ 2006-08-23  7:21 UTC (permalink / raw)
  Cc: lennart.borgman.073, emacs-devel

Richard Stallman <rms@gnu.org> writes:

>     In any case, I think that emacs should simply reject to run the
>     tutorial if VIPER is enabled
>
> I tend to agree.  And I think it should be the same for CUA mode.

The only key-binding in the tutorial which CUA mode really messes up
is C-v.  But that is the first key which the user is asked to type.

Other than that, the tutorial is quite useful even for users of CUA!
So one approach is to just bind locally bind cua-enable-cua-keys to
nil in the tutorial buffer and make a note like this:

  The purpose of the tutorial is to teach you the basic, standard
  Emacs key bindings.  Therefore, CUA mode's C-z C-x C-c and C-v
  bindinds have been disabled in this tutorial buffer.  [Details]

We could do similar things for viper, ie.

  The purpose of the tutorial is to teach you the basic, standard
  Emacs key bindings.  Therefore, VIPER mode's key bindinds have been
  disabled in this tutorial buffer.  [Details]

And if both viper and cua are enabled, something like

  The purpose of the tutorial is to teach you the basic, standard
  Emacs key bindings.  Therefore, CUA and VIPER mode's key bindinds
  have been disabled in this tutorial buffer.  [Details]


And if other key bindings have been disabled:

  The purpose of the tutorial is to teach you the basic, standard
  Emacs key bindings.  Therefore, some non-standard key bindinds
  have been disabled in this tutorial buffer.  [Details]

The [Details] button will open a *Help* window which shows all the
differences in key bindings.

> I don't see much point in teaching an absolute beginner standard Emacs
> if that is not what he will get when he runs Emacs normally.

True, but it is still good to know about C-b C-f C-n and C-p !!!


> Another idea occurs to me: display the list of changed bindings
> together with a message like this:
>
>     The tutorial won't work for you, because someone
>     has customized your Emacs, changing these basic commands.
>     Probably whoever set up Emacs for you did it in a nonstandard way.
>     Please ask him to teach you to use this nonstandard Emacs
>     or else ask him to change your Emacs setup back to standard.
>
> That has the benefit of being simple, avoiding all the problems
> people are talking about now, and encouraging people not to
> customize Emacs when they set it up for others.


Actually the last example I gave above may cover all cases, i.e.
show the following paragraph at the beginning of the tutorial
and disable all non-standard bindings in the tutorial:

  The purpose of the tutorial is to teach you the basic, standard
  Emacs key bindings.  Therefore, some non-standard key bindinds
  have been disabled in this tutorial buffer.  [Details]

The [Details] button will open a *Help* window which shows all the
non-standard key bindings.

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

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

* Re: cua-mode and the tutorial
  2006-08-23  4:37       ` Lennart Borgman
@ 2006-08-24  5:20         ` Richard Stallman
  0 siblings, 0 replies; 40+ messages in thread
From: Richard Stallman @ 2006-08-24  5:20 UTC (permalink / raw)
  Cc: emacs-devel, storm

    > I don't see much point in teaching an absolute beginner standard Emacs
    > if that is not what he will get when he runs Emacs normally.
    >   
    Maybe this is wishful thinking? That new users will use Emacs standard 
    key bindings only? It is hard for me to believe they will.

New users won't know about nonstandard bindings.  Until they learn
to customize, they will use the standard ones.

The exception is when someone starts a new user off with nontrivial
customizations.  We want to discourage that.

    Is it not plausible that they have been using CUA keys and want to use 
    that in Emacs?

I don't know, but people who start others off with Emacs are not
supposed to customize it for them.

The tutorial is written to teach the standard bindings.  To teach
the use of Emacs with the CUA keys is a different job, one which
the current tutorial is not designed to do.

    Is it not quite likely that the person who set up Emacs is the user 
    himself? He might have read some advice on how to get started and 
    customized Emacs to use CUA mode.

It seems rather unlikely.

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

* Re: cua-mode and the tutorial
  2006-08-23  7:21       ` Kim F. Storm
@ 2006-08-24  5:20         ` Richard Stallman
  2006-08-24  7:30           ` Kim F. Storm
  0 siblings, 1 reply; 40+ messages in thread
From: Richard Stallman @ 2006-08-24  5:20 UTC (permalink / raw)
  Cc: lennart.borgman.073, emacs-devel

    Other than that, the tutorial is quite useful even for users of CUA!
    So one approach is to just bind locally bind cua-enable-cua-keys to
    nil in the tutorial buffer and make a note like this:

      The purpose of the tutorial is to teach you the basic, standard
      Emacs key bindings.  Therefore, CUA mode's C-z C-x C-c and C-v
      bindinds have been disabled in this tutorial buffer.  [Details]

I have no objection to that.  If you think it does a good job of
dealing with CUA mode, then let's do it.

But we should make it offer to delete the customization
in case the user was not asked about it.

    If you did not make this customization yourself, or request it,
    that means someone has decided to send you down the path of
    learning a non-standard way of using Emacs.  You might prefer to
    learn the standard Emacs commands.

    You can remove the customizations that were set up for you
    by typing `s' now.  That will rename your Emacs init file
    so that it doesn't take effect.


    We could do similar things for viper, ie.

In theory we could do this, but is it adequate for learning to use
Emacs with viper?  I doubt it.

    And if other key bindings have been disabled:

      The purpose of the tutorial is to teach you the basic, standard
      Emacs key bindings.  Therefore, some non-standard key bindinds
      have been disabled in this tutorial buffer.  [Details]

No, in general this is not a useful way to deal with the situation.
For instance, it is not useful to teach a user to type C-d to delete
forward if in his ordinary editing it will do something else.

CUA mode is a special case only because you, an expert on it, affirm
that the difference is not important, that using the ordinary tutorial
with CUA's C-v disabled is ok as a way to learn the basics of using
Emacs in CUA mode.  That is not true for nonstandard bindings in
general.

So I reject this approach in general, but I will accept it for CUA mode.

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

* Re: cua-mode and the tutorial
  2006-08-24  5:20         ` Richard Stallman
@ 2006-08-24  7:30           ` Kim F. Storm
  2006-08-25 20:25             ` Richard Stallman
  2006-08-27  8:35             ` Lennart Borgman
  0 siblings, 2 replies; 40+ messages in thread
From: Kim F. Storm @ 2006-08-24  7:30 UTC (permalink / raw)
  Cc: lennart.borgman.073, emacs-devel

Richard Stallman <rms@gnu.org> writes:

>     Other than that, the tutorial is quite useful even for users of CUA!
>     So one approach is to just bind locally bind cua-enable-cua-keys to
>     nil in the tutorial buffer and make a note like this:
>
>       The purpose of the tutorial is to teach you the basic, standard
>       Emacs key bindings.  Therefore, CUA mode's C-z C-x C-c and C-v
>       bindinds have been disabled in this tutorial buffer.  [Details]
>
> I have no objection to that.  If you think it does a good job of
> dealing with CUA mode, then let's do it.

IMO, it is ok.

> But we should make it offer to delete the customization
> in case the user was not asked about it.

Too complex for very little benefit IMHO.

We don't know what method was used to enable CUA-mode.  It could be a
customization, but it could also be an explicit call to CUA-mode in
emacs.  So that is not trivial to do right in all cases.

> In theory we could do this, but is it adequate for learning to use
> Emacs with viper?  I doubt it.

Ok, I agree.  So we seem to agree that the tutorial should not start
at all if viper is enabled, but just list the differences in 
key bindings.

>       The purpose of the tutorial is to teach you the basic, standard
>       Emacs key bindings.  Therefore, some non-standard key bindinds
>       have been disabled in this tutorial buffer.  [Details]
>
> No, in general this is not a useful way to deal with the situation.

Ok.

> So I reject this approach in general, but I will accept it for CUA mode.

Ok.

Lennart, comments?

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

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

* Re: cua-mode and the tutorial
  2006-08-24  7:30           ` Kim F. Storm
@ 2006-08-25 20:25             ` Richard Stallman
  2006-08-25 22:12               ` Kim F. Storm
  2006-08-27  8:35             ` Lennart Borgman
  1 sibling, 1 reply; 40+ messages in thread
From: Richard Stallman @ 2006-08-25 20:25 UTC (permalink / raw)
  Cc: lennart.borgman.073, emacs-devel

    > But we should make it offer to delete the customization
    > in case the user was not asked about it.

    Too complex for very little benefit IMHO.

    We don't know what method was used to enable CUA-mode.  It could be a
    customization, but it could also be an explicit call to CUA-mode in
    emacs.  So that is not trivial to do right in all cases.

It is pretty easy to recognize those two methods and DTRT for them.
It is also pretty easy to recognize when neither of those methods was used,
and say "I can't figure out how to delete it".

    > In theory we could do this, but is it adequate for learning to use
    > Emacs with viper?  I doubt it.

    Ok, I agree.  So we seem to agree that the tutorial should not start
    at all if viper is enabled, but just list the differences in 
    key bindings.

In the case of Viper, I would rather have it say "You enabled Viper
mode" and not list the specific differences (there would be too many
of them, right?).

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

* Re: cua-mode and the tutorial
  2006-08-25 20:25             ` Richard Stallman
@ 2006-08-25 22:12               ` Kim F. Storm
  2006-08-26 12:22                 ` Richard Stallman
  0 siblings, 1 reply; 40+ messages in thread
From: Kim F. Storm @ 2006-08-25 22:12 UTC (permalink / raw)
  Cc: lennart.borgman.073, emacs-devel

Richard Stallman <rms@gnu.org> writes:

>     > But we should make it offer to delete the customization
>     > in case the user was not asked about it.
>
>     Too complex for very little benefit IMHO.
>
>     We don't know what method was used to enable CUA-mode.  It could be a
>     customization, but it could also be an explicit call to CUA-mode in
>     emacs.  So that is not trivial to do right in all cases.
>
> It is pretty easy to recognize those two methods and DTRT for them.

In one case, it is set system wide in site-load.el.

In another case, it is set in a shared file loaded from .emacs.

In a third case, it is set in another user's .emacs file invoked
through --user option.

Besides, I doubt that very many users would want to disable CUA-mode
if they got their .emacs file from a collegue or friend -- such persons
are often "in sync" with respect to their tools and habits.

I still think this is too complex for very little benefit.

In any case, I will definitely not write the necessary code!

> It is also pretty easy to recognize when neither of those methods was used,
> In the case of Viper, I would rather have it say "You enabled Viper
> mode" and not list the specific differences (there would be too many
> of them, right?).

I suppose so, and the message would only list those keys which correspond
to keys used in the tutorial, so it would not be complete anyway.

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

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

* Re: cua-mode and the tutorial
  2006-08-25 22:12               ` Kim F. Storm
@ 2006-08-26 12:22                 ` Richard Stallman
  2006-08-26 12:44                   ` David Kastrup
                                     ` (2 more replies)
  0 siblings, 3 replies; 40+ messages in thread
From: Richard Stallman @ 2006-08-26 12:22 UTC (permalink / raw)
  Cc: lennart.borgman.073, emacs-devel

    In one case, it is set system wide in site-load.el.

No one should do that!  People are not supposed to start off
new users with nonstandard Emacs settings.

I think I will put something into startup.el to make this
cease to take effect.

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

* Re: cua-mode and the tutorial
  2006-08-26 12:22                 ` Richard Stallman
@ 2006-08-26 12:44                   ` David Kastrup
  2006-08-27 14:34                     ` Richard Stallman
  2006-08-26 14:19                   ` Stefan Monnier
  2006-08-26 21:14                   ` Kim F. Storm
  2 siblings, 1 reply; 40+ messages in thread
From: David Kastrup @ 2006-08-26 12:44 UTC (permalink / raw)
  Cc: lennart.borgman.073, emacs-devel, Kim F. Storm

Richard Stallman <rms@gnu.org> writes:

>     In one case, it is set system wide in site-load.el.
>
> No one should do that!  People are not supposed to start off
> new users with nonstandard Emacs settings.
>
> I think I will put something into startup.el to make this
> cease to take effect.

I think that would be a bad idea because it is would be obscure.  We
should not artificially hamper the freedom of people to decide how
Emacs is best used at their site.  The best we can do is educate them.
Everything else leads to an arms' race of technical measures trying to
thwart the other's intentions.

We don't want to do that.  Really.

-- 
David Kastrup, Kriemhildstr. 15, 44793 Bochum

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

* Re: cua-mode and the tutorial
  2006-08-26 12:22                 ` Richard Stallman
  2006-08-26 12:44                   ` David Kastrup
@ 2006-08-26 14:19                   ` Stefan Monnier
  2006-08-26 15:07                     ` Drew Adams
  2006-08-26 21:15                     ` Kim F. Storm
  2006-08-26 21:14                   ` Kim F. Storm
  2 siblings, 2 replies; 40+ messages in thread
From: Stefan Monnier @ 2006-08-26 14:19 UTC (permalink / raw)
  Cc: lennart.borgman.073, emacs-devel, Kim F. Storm

>     In one case, it is set system wide in site-load.el.
> No one should do that!  People are not supposed to start off
> new users with nonstandard Emacs settings.

> I think I will put something into startup.el to make this
> cease to take effect.

I think trying to prevent people from shooting in their foot is the wrong
way to go, since it'll also prevent them from doing other things.

I'd rather we put some kind of loud warning on the splash page if we detect
something like viper or cua enabled before .emacs gets loaded.


        Stefan

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

* RE: cua-mode and the tutorial
  2006-08-26 14:19                   ` Stefan Monnier
@ 2006-08-26 15:07                     ` Drew Adams
  2006-08-26 21:15                     ` Kim F. Storm
  1 sibling, 0 replies; 40+ messages in thread
From: Drew Adams @ 2006-08-26 15:07 UTC (permalink / raw)


    >     In one case, it is set system wide in site-load.el.
    > No one should do that!  People are not supposed to start off
    > new users with nonstandard Emacs settings.

    > I think I will put something into startup.el to make this
    > cease to take effect.

    I think trying to prevent people from shooting in their foot is
    the wrong way to go, since it'll also prevent them from doing
    other things.

    I'd rather we put some kind of loud warning on the splash page
    if we detect something like viper or cua enabled before .emacs
    gets loaded.

Just a loud warning? Take over their keyboard and mouse, fill their Inbox
with spam mail, and send mea-culpa mail from their account to everyone in
their address list. Teach the &*^$!!#'s a lesson. ;-)

Kidding aside, I agree with Stefan and David here: in this case, at least,
educate, don't try to prevent or punish.

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

* Re: cua-mode and the tutorial
  2006-08-26 12:22                 ` Richard Stallman
  2006-08-26 12:44                   ` David Kastrup
  2006-08-26 14:19                   ` Stefan Monnier
@ 2006-08-26 21:14                   ` Kim F. Storm
  2006-08-28  9:52                     ` Richard Stallman
  2 siblings, 1 reply; 40+ messages in thread
From: Kim F. Storm @ 2006-08-26 21:14 UTC (permalink / raw)
  Cc: lennart.borgman.073, emacs-devel

Richard Stallman <rms@gnu.org> writes:

>     In one case, it is set system wide in site-load.el.
>

(sorry, I meant site-start.el).

> No one should do that!  People are not supposed to start off
> new users with nonstandard Emacs settings.

So why do we have site-start.el and site-lisp/default.el ?


I have a my own personal PC running GNU/Linux.  Nobody else uses it.
Yet, I run it as different users for different purposes.

The easiest way for me to ensure that all these "pseudo users"
have the same emacs setup is to use site-start.el FOR ME AND ONLY ME.

So, it's not "people" doing that -- it's "me".

>
> I think I will put something into startup.el to make this
> cease to take effect.

Excuse me, but that is SILLY!!  Please don't do that!

Don't we have better things to do?

And what exactly do you intend to change?  Enabling cua-mode,
viper-mode, delete-selection-mode, pc-selection-mode, glasses-mode,
.. any minor mode?


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

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

* Re: cua-mode and the tutorial
  2006-08-26 14:19                   ` Stefan Monnier
  2006-08-26 15:07                     ` Drew Adams
@ 2006-08-26 21:15                     ` Kim F. Storm
  2006-08-27 14:34                       ` Richard Stallman
  1 sibling, 1 reply; 40+ messages in thread
From: Kim F. Storm @ 2006-08-26 21:15 UTC (permalink / raw)
  Cc: lennart.borgman.073, rms, emacs-devel

Stefan Monnier <monnier@iro.umontreal.ca> writes:

>>     In one case, it is set system wide in site-load.el.
>> No one should do that!  People are not supposed to start off
>> new users with nonstandard Emacs settings.
>
>> I think I will put something into startup.el to make this
>> cease to take effect.
>
> I think trying to prevent people from shooting in their foot is the wrong
> way to go, since it'll also prevent them from doing other things.

Agree!!


> I'd rather we put some kind of loud warning on the splash page if we detect
> something like viper or cua enabled before .emacs gets loaded.

That's ok with me (I know how to inhibit the splash screen for the machines
where I do this).

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

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

* Re: cua-mode and the tutorial
  2006-08-24  7:30           ` Kim F. Storm
  2006-08-25 20:25             ` Richard Stallman
@ 2006-08-27  8:35             ` Lennart Borgman
  2006-08-28  9:52               ` Richard Stallman
  1 sibling, 1 reply; 40+ messages in thread
From: Lennart Borgman @ 2006-08-27  8:35 UTC (permalink / raw)
  Cc: rms, emacs-devel

Kim F. Storm wrote:
> Richard Stallman <rms@gnu.org> writes:
>
>   
>>     Other than that, the tutorial is quite useful even for users of CUA!
>>     So one approach is to just bind locally bind cua-enable-cua-keys to
>>     nil in the tutorial buffer and make a note like this:
>>
>>       The purpose of the tutorial is to teach you the basic, standard
>>       Emacs key bindings.  Therefore, CUA mode's C-z C-x C-c and C-v
>>       bindinds have been disabled in this tutorial buffer.  [Details]
>>
>> I have no objection to that.  If you think it does a good job of
>> dealing with CUA mode, then let's do it.
>>     
>
> IMO, it is ok.
>
>   
>> But we should make it offer to delete the customization
>> in case the user was not asked about it.
>>     
>
> Too complex for very little benefit IMHO.
>
> We don't know what method was used to enable CUA-mode.  It could be a
> customization, but it could also be an explicit call to CUA-mode in
> emacs.  So that is not trivial to do right in all cases.
>
>   
>> In theory we could do this, but is it adequate for learning to use
>> Emacs with viper?  I doubt it.
>>     
>
> Ok, I agree.  So we seem to agree that the tutorial should not start
> at all if viper is enabled, but just list the differences in 
> key bindings.
>
>   
>>       The purpose of the tutorial is to teach you the basic, standard
>>       Emacs key bindings.  Therefore, some non-standard key bindinds
>>       have been disabled in this tutorial buffer.  [Details]
>>
>> No, in general this is not a useful way to deal with the situation.
>>     
>
> Ok.
>
>   
>> So I reject this approach in general, but I will accept it for CUA mode.
>>     
>
> Ok.
>
> Lennart, comments?
>   
Sorry, I have not had time to comment for some days. I have however 
followed the discussion. Based on this and my own thoughts I suggest the 
following solution for the tutorial:

1) Remove all non-default key bindings in the tutorial. I used that 
approach from the beginning so I have code for that.

2) If there were non-default key bindings then put a note with yellow 
background like in my latest tutorial.el I sent. However make this note 
shorter. As Kim pointed out a long note can make the first steps in the 
tutorial non-working.

3) From this note make a link called "Details" that shows the 
non-standard key bindings in a help buffer in a way similar to those in 
my latest tutorial.el.

4) Since there has also been some concern about telling the user how to 
disable CUA mode and Viper I think it will be good to put some 
information in the help buffer about this if anyone of those has been 
turned on. This could tell about customization as the best approach to 
turn them on/off if the user has not been using that.

What do you think about this solution?

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

* Re: cua-mode and the tutorial
  2006-08-26 12:44                   ` David Kastrup
@ 2006-08-27 14:34                     ` Richard Stallman
  0 siblings, 0 replies; 40+ messages in thread
From: Richard Stallman @ 2006-08-27 14:34 UTC (permalink / raw)
  Cc: lennart.borgman.073, emacs-devel, storm

    I think that would be a bad idea because it is would be obscure.  We
    should not artificially hamper the freedom of people to decide how
    Emacs is best used at their site.

Each user is supposed to decide how to best use Emacs.  These people
are (according to what we've been told) being taught to use a
nonstandard version without being asked whether they want that,
without even being told.

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

* Re: cua-mode and the tutorial
  2006-08-26 21:15                     ` Kim F. Storm
@ 2006-08-27 14:34                       ` Richard Stallman
  2006-08-27 15:06                         ` David Kastrup
  2006-08-27 21:30                         ` Kim F. Storm
  0 siblings, 2 replies; 40+ messages in thread
From: Richard Stallman @ 2006-08-27 14:34 UTC (permalink / raw)
  Cc: lennart.borgman.073, monnier, emacs-devel

    > I think trying to prevent people from shooting in their foot is the wrong
    > way to go, since it'll also prevent them from doing other things.

The problem here is a matter of one expert shooting multiple newbies
in the foot.

    > I'd rather we put some kind of loud warning on the splash page if we detect
    > something like viper or cua enabled before .emacs gets loaded.

    That's ok with me (I know how to inhibit the splash screen for the machines
    where I do this).

It sounds like you're saying that the splash screen warning won't
solve the problem.

But perhaps I have misunderstood.  Does "do this" refer to setting up
your PC for you to use it under various different names, or does it
refer to getting Emacs newcomers started using nonstandard bindings?

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

* Re: cua-mode and the tutorial
  2006-08-27 14:34                       ` Richard Stallman
@ 2006-08-27 15:06                         ` David Kastrup
  2006-08-28 22:09                           ` Richard Stallman
  2006-08-27 21:30                         ` Kim F. Storm
  1 sibling, 1 reply; 40+ messages in thread
From: David Kastrup @ 2006-08-27 15:06 UTC (permalink / raw)
  Cc: lennart.borgman.073, emacs-devel, monnier, Kim F. Storm

Richard Stallman <rms@gnu.org> writes:

>     > I think trying to prevent people from shooting in their foot
>     > is the wrong way to go, since it'll also prevent them from
>     > doing other things.
>
> The problem here is a matter of one expert shooting multiple newbies
> in the foot.

We would not know that this is the case.

-- 
David Kastrup, Kriemhildstr. 15, 44793 Bochum

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

* Re: cua-mode and the tutorial
  2006-08-27 14:34                       ` Richard Stallman
  2006-08-27 15:06                         ` David Kastrup
@ 2006-08-27 21:30                         ` Kim F. Storm
  1 sibling, 0 replies; 40+ messages in thread
From: Kim F. Storm @ 2006-08-27 21:30 UTC (permalink / raw)
  Cc: lennart.borgman.073, monnier, emacs-devel

Richard Stallman <rms@gnu.org> writes:

>     > I think trying to prevent people from shooting in their foot is the wrong
>     > way to go, since it'll also prevent them from doing other things.
>
> The problem here is a matter of one expert shooting multiple newbies
> in the foot.

And that same expert shooting multiple other experts in various other
part of their body :-)

>
>     > I'd rather we put some kind of loud warning on the splash page if we detect
>     > something like viper or cua enabled before .emacs gets loaded.
>
>     That's ok with me (I know how to inhibit the splash screen for the machines
>     where I do this).
>
> It sounds like you're saying that the splash screen warning won't
> solve the problem.

It will solve the problem for me.

> But perhaps I have misunderstood.  Does "do this" refer to setting up
> your PC for you to use it under various different names, 

Yes.

>                                                          or does it
> refer to getting Emacs newcomers started using nonstandard bindings?

NO.  There are no other users on this system than myself.

I would never setup a system with CUA or viper enabled by default.
But I would tell users how to enable them, if they ask!

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

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

* Re: cua-mode and the tutorial
  2006-08-27  8:35             ` Lennart Borgman
@ 2006-08-28  9:52               ` Richard Stallman
  2006-08-28 10:17                 ` Slawomir Nowaczyk
  2006-08-28 22:32                 ` Lennart Borgman
  0 siblings, 2 replies; 40+ messages in thread
From: Richard Stallman @ 2006-08-28  9:52 UTC (permalink / raw)
  Cc: emacs-devel, storm

    1) Remove all non-default key bindings in the tutorial. I used that 
    approach from the beginning so I have code for that.

I don't like the approach of having the tutorial teach standard
bindings in an Emacs where they won't work.

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

* Re: cua-mode and the tutorial
  2006-08-26 21:14                   ` Kim F. Storm
@ 2006-08-28  9:52                     ` Richard Stallman
  2006-08-28 10:07                       ` David Kastrup
  0 siblings, 1 reply; 40+ messages in thread
From: Richard Stallman @ 2006-08-28  9:52 UTC (permalink / raw)
  Cc: lennart.borgman.073, emacs-devel

    > No one should do that!  People are not supposed to start off
    > new users with nonstandard Emacs settings.

    So why do we have site-start.el and site-lisp/default.el ?

For things other than changing the user's key bindings.

    The easiest way for me to ensure that all these "pseudo users"
    have the same emacs setup is to use site-start.el FOR ME AND ONLY ME.

    So, it's not "people" doing that -- it's "me".

You're the only one involved, in this scenario, so you're
not treating anyone else badly.

But this is a special case, and you're the one who has told me that
some sysadmins set up Emacs in a nonstandard way for _other people_.

    And what exactly do you intend to change?  Enabling cua-mode,
    viper-mode, delete-selection-mode, pc-selection-mode, glasses-mode,
    .. any minor mode?

Perhaps this should be done for whichever modes we find are often
being imposed on other users in this way.

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

* Re: cua-mode and the tutorial
  2006-08-28  9:52                     ` Richard Stallman
@ 2006-08-28 10:07                       ` David Kastrup
  2006-08-28 11:21                         ` Kim F. Storm
  0 siblings, 1 reply; 40+ messages in thread
From: David Kastrup @ 2006-08-28 10:07 UTC (permalink / raw)
  Cc: lennart.borgman.073, emacs-devel, Kim F. Storm

Richard Stallman <rms@gnu.org> writes:

> You're the only one involved, in this scenario, so you're
> not treating anyone else badly.
>
> But this is a special case, and you're the one who has told me that
> some sysadmins set up Emacs in a nonstandard way for _other people_.
>
>     And what exactly do you intend to change?  Enabling cua-mode,
>     viper-mode, delete-selection-mode, pc-selection-mode, glasses-mode,
>     .. any minor mode?
>
> Perhaps this should be done for whichever modes we find are often
> being imposed on other users in this way.

We are interfering in that manner with the freedom of adapting Emacs
to one's wishes.  What next?  Will we use DRM to ensure that all
variables we consider worthy are left at standard settings?

Emacs is free software.  Part of the freedom is being able to do
things that upstream did not think a good idea.  I am strictly opposed
to booby-trapping Emacs with code that reverts a consciously made
decision downstream.

-- 
David Kastrup, Kriemhildstr. 15, 44793 Bochum

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

* Re: cua-mode and the tutorial
  2006-08-28  9:52               ` Richard Stallman
@ 2006-08-28 10:17                 ` Slawomir Nowaczyk
  2006-08-29 17:18                   ` Richard Stallman
  2006-08-28 22:32                 ` Lennart Borgman
  1 sibling, 1 reply; 40+ messages in thread
From: Slawomir Nowaczyk @ 2006-08-28 10:17 UTC (permalink / raw)


On Mon, 28 Aug 2006 05:52:19 -0400
Richard Stallman <rms@gnu.org> wrote:

#>     1) Remove all non-default key bindings in the tutorial. I used that 
#>     approach from the beginning so I have code for that.
#> 
#> I don't like the approach of having the tutorial teach standard
#> bindings in an Emacs where they won't work.

Well, the right solution would, then, be to have tutorial talk about key
bindings that are determined dynamically, so they match whatever works
in a particular Emacs installation. Which is a problem ATM, because,
IIRC, there is no way to specify which key binding is a "preferred" one
for a given command -- and it seems that "dynamic tutorial" would need
to know this.

We might even have a special, human-adapted versions of the tutorial for
things which are vastly different than normal, like viper and maybe also
cua-mode.

But that is after the release, I suppose. For now, maybe Lennart's
suggestion is good enough?

-- 
 Best wishes,
   Slawomir Nowaczyk
     ( slawomir.nowaczyk.847@student.lu.se )

Make backups before you try something new or interesting or experimental
or radical or if the day has a "y" in it.

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

* Re: cua-mode and the tutorial
  2006-08-28 10:07                       ` David Kastrup
@ 2006-08-28 11:21                         ` Kim F. Storm
  2006-08-29 17:18                           ` Richard Stallman
  0 siblings, 1 reply; 40+ messages in thread
From: Kim F. Storm @ 2006-08-28 11:21 UTC (permalink / raw)
  Cc: lennart.borgman.073, rms, emacs-devel

David Kastrup <dak@gnu.org> writes:

> Richard Stallman <rms@gnu.org> writes:
>
>> You're the only one involved, in this scenario, so you're
>> not treating anyone else badly.
>>
>> But this is a special case, and you're the one who has told me that
>> some sysadmins set up Emacs in a nonstandard way for _other people_.

I didn't mean to say anyone actually does this.

We discussed whether it was worth the trouble to write code which
specifically tries to _remove_ CUA setting that the user may
not have installed himself.

So I tried to give examples where of ways it _can_ be done, that would
be non-trivial to remove (hoping that we could drop that idea and do
more important work).

>>
>>     And what exactly do you intend to change?  Enabling cua-mode,
>>     viper-mode, delete-selection-mode, pc-selection-mode, glasses-mode,
>>     .. any minor mode?
>>
>> Perhaps this should be done for whichever modes we find are often
>> being imposed on other users in this way.

I honestly don't think that there are any such modes which are _often_
imposed on other users through site-start.el etc.  

In most cases, people who want to introduce someone to emacs may
give the newbee a copy of their own .emacs to look at and use
initially.  We neither can nor should try to control what people
share in this way.

> We are interfering in that manner with the freedom of adapting Emacs
> to one's wishes.  What next?  Will we use DRM to ensure that all
> variables we consider worthy are left at standard settings?
>
> Emacs is free software.  Part of the freedom is being able to do
> things that upstream did not think a good idea.  I am strictly opposed
> to booby-trapping Emacs with code that reverts a consciously made
> decision downstream.

I agree with David -- but even if I didn't, I wouldn't spend as much
as one second writing the code necessary to impose such restrictions.

[and I've already spent way too much time discussion this (non-)issue].


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

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

* Re: cua-mode and the tutorial
  2006-08-27 15:06                         ` David Kastrup
@ 2006-08-28 22:09                           ` Richard Stallman
  0 siblings, 0 replies; 40+ messages in thread
From: Richard Stallman @ 2006-08-28 22:09 UTC (permalink / raw)
  Cc: lennart.borgman.073, emacs-devel, monnier, storm

    > The problem here is a matter of one expert shooting multiple newbies
    > in the foot.

    We would not know that this is the case.

Yes, that's right.  Sometimes perfection is not feasible.

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

* Re: cua-mode and the tutorial
  2006-08-28  9:52               ` Richard Stallman
  2006-08-28 10:17                 ` Slawomir Nowaczyk
@ 2006-08-28 22:32                 ` Lennart Borgman
  2006-08-29 17:18                   ` Richard Stallman
  1 sibling, 1 reply; 40+ messages in thread
From: Lennart Borgman @ 2006-08-28 22:32 UTC (permalink / raw)
  Cc: storm, emacs-devel

Richard Stallman wrote:
>     1) Remove all non-default key bindings in the tutorial. I used that 
>     approach from the beginning so I have code for that.
>
> I don't like the approach of having the tutorial teach standard
> bindings in an Emacs where they won't work.
>   
I can see four main possibilities:

1) Like above, but you do not like that option

2) Keep the nonstandard bindings and tell the user about it. This can be 
done the way Kim suggested (a small yellow screen with a details link). 
The changed bindings can be marked in the tutorial text or they can be 
marked and replaced.

3) A combination of 1 and 2. Let the user decide. (This is perhaps a bit 
complicated for a tutorial.)

4) Stop the user from running the tutorial. I do not like this option.

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

* Re: cua-mode and the tutorial
  2006-08-28 10:17                 ` Slawomir Nowaczyk
@ 2006-08-29 17:18                   ` Richard Stallman
  2006-08-29 17:55                     ` Drew Adams
  0 siblings, 1 reply; 40+ messages in thread
From: Richard Stallman @ 2006-08-29 17:18 UTC (permalink / raw)
  Cc: emacs-devel

    Well, the right solution would, then, be to have tutorial talk about key
    bindings that are determined dynamically, so they match whatever works
    in a particular Emacs installation.

That is a hard problem.  It would have to work with the various
translations of the tutorial.  You could try to work on it, and if you
get it working, we could consider installing it.  But I would not
recommend you work on this, because I think it is more trouble than it
is worth.

In the mean time, this solution is not available.

Since this does not change the immediate situation, I continue to
reject the approaches I have already rejected.

    But that is after the release, I suppose. For now, maybe Lennart's
    suggestion is good enough?

I do not remember who suggested what.

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

* Re: cua-mode and the tutorial
  2006-08-28 11:21                         ` Kim F. Storm
@ 2006-08-29 17:18                           ` Richard Stallman
  0 siblings, 0 replies; 40+ messages in thread
From: Richard Stallman @ 2006-08-29 17:18 UTC (permalink / raw)
  Cc: lennart.borgman.073, emacs-devel

    So I tried to give examples where of ways it _can_ be done, that would
    be non-trivial to remove (hoping that we could drop that idea and do
    more important work).

Those hypothetical examples are not real objections.

    In most cases, people who want to introduce someone to emacs may
    give the newbee a copy of their own .emacs to look at and use
    initially.  We neither can nor should try to control what people
    share in this way.

That is not what I proposed--it is a straw man.

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

* Re: cua-mode and the tutorial
  2006-08-28 22:32                 ` Lennart Borgman
@ 2006-08-29 17:18                   ` Richard Stallman
  2006-08-31 15:10                     ` Lennart Borgman
  0 siblings, 1 reply; 40+ messages in thread
From: Richard Stallman @ 2006-08-29 17:18 UTC (permalink / raw)
  Cc: storm, emacs-devel

    >     1) Remove all non-default key bindings in the tutorial. I used that 
    >     approach from the beginning so I have code for that.
    >
    > I don't like the approach of having the tutorial teach standard
    > bindings in an Emacs where they won't work.
    >   
    I can see four main possibilities:

    1) Like above, but you do not like that option

It is not a very useful thing to do.  Anyway, the user can turn off
the nonstandard bindings and run the tutorial, by running `emacs -q'.

    2) Keep the nonstandard bindings and tell the user about it. This can be 
    done the way Kim suggested (a small yellow screen with a details link). 
    The changed bindings can be marked in the tutorial text or they can be 
    marked and replaced.

There is nothing inherently bad about offering this possibility is no
harm in itself.  But people pointed out various inconveniences of the
attempt to do it.

    3) A combination of 1 and 2. Let the user decide. (This is perhaps a bit 
    complicated for a tutorial.)

My response is a combination of the two responses above.

    4) Stop the user from running the tutorial. I do not like this option.

If practical inconveniences makes #2 a bad idea, #4 is what we are
left with.

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

* RE: cua-mode and the tutorial
  2006-08-29 17:18                   ` Richard Stallman
@ 2006-08-29 17:55                     ` Drew Adams
  2006-08-29 18:13                       ` Lennart Borgman
  0 siblings, 1 reply; 40+ messages in thread
From: Drew Adams @ 2006-08-29 17:55 UTC (permalink / raw)


I haven't been following this closely, so, please, no flames if I'm off the
mark or if this has already been suggested.

Would this be a good approach?

1. Mention in the Emacs tutorial that it applies to the standard (default)
key bindings.

2. Perhaps detect non-standard bindings, and draw attention to #1 with an
explicit message.

3. Perhaps point out again, in specific sections, that the bindings used
there are the standard ones. Perhaps mention the corresponding commands by
name, so users can nevertheless try them (if appropriate).

4. Provide a separate tutorial for CUA, which complements the Emacs tutorial
and covers the parts of the Emacs tutorial that don't make sense for CUA.

IOW:

1. Not try to make the Emacs tutorial work for CUA mode and such, but have
it at least point out that it is not for CUA mode.

2. Have CUA mode be responsible for teaching CUA mode.

Again, I didn't follow the thread, and I'm not very familiar with CUA mode.
If this suggestion helps, fine; if not, ignore it.

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

* Re: cua-mode and the tutorial
  2006-08-29 17:55                     ` Drew Adams
@ 2006-08-29 18:13                       ` Lennart Borgman
  0 siblings, 0 replies; 40+ messages in thread
From: Lennart Borgman @ 2006-08-29 18:13 UTC (permalink / raw)
  Cc: Kim F. Storm, Richard M. Stallman, emacs-devel

Drew Adams wrote:
> I haven't been following this closely, so, please, no flames if I'm off the
> mark or if this has already been suggested.
>
> Would this be a good approach?
>
> 1. Mention in the Emacs tutorial that it applies to the standard (default)
> key bindings.
>
> 2. Perhaps detect non-standard bindings, and draw attention to #1 with an
> explicit message.
>
> 3. Perhaps point out again, in specific sections, that the bindings used
> there are the standard ones. Perhaps mention the corresponding commands by
> name, so users can nevertheless try them (if appropriate).
>   
Thanks for the suggestions. I think however that these are already 
covered in the suggestions made earlier.

> 4. Provide a separate tutorial for CUA, which complements the Emacs tutorial
> and covers the parts of the Emacs tutorial that don't make sense for CUA.
>   
Unless the region is active there is only a few keys (C-v and M-v) that 
are really different when CUA mode is used. When the region is visible 
C-x and C-c also works differently. S-C-x and S-C-c can be used instead 
and this should be explained.

Those differences are small so there is no need for a separate tutorial. 
Instead it should be enough to point them out in the beginning of the 
tutorial and mark those keys in the tutorial text. At least I think we 
have come close to an agreement upon this in the discussion.


You are welcome to try the tutorial.el that I have sent earlier. However 
at least two things should be changed there:

1) The yellow part at the top that is shown when some of the standard 
keys mentioned in the tutorial have been changed should be smaller. To 
show the more detailed picture a "Details" link should be implemented as 
suggested by Kim.

2) Those keys changed changed should be marked or replaced in the 
tutorial text. Probably marking is best.

I will work on this and some more smaller changes.

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

* Re: cua-mode and the tutorial
  2006-08-29 17:18                   ` Richard Stallman
@ 2006-08-31 15:10                     ` Lennart Borgman
  2006-09-21 14:24                       ` Kim F. Storm
  0 siblings, 1 reply; 40+ messages in thread
From: Lennart Borgman @ 2006-08-31 15:10 UTC (permalink / raw)
  Cc: storm, Michael Kifer, emacs-devel

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

Richard Stallman wrote:
>     >     1) Remove all non-default key bindings in the tutorial. I used that 
>     >     approach from the beginning so I have code for that.
>     >
>     > I don't like the approach of having the tutorial teach standard
>     > bindings in an Emacs where they won't work.
>     >   
>     I can see four main possibilities:
>
>     1) Like above, but you do not like that option
>
> It is not a very useful thing to do.  Anyway, the user can turn off
> the nonstandard bindings and run the tutorial, by running `emacs -q'.
>
>     2) Keep the nonstandard bindings and tell the user about it. This can be 
>     done the way Kim suggested (a small yellow screen with a details link). 
>     The changed bindings can be marked in the tutorial text or they can be 
>     marked and replaced.
>
> There is nothing inherently bad about offering this possibility is no
> harm in itself.  But people pointed out various inconveniences of the
> attempt to do it.
>
>     3) A combination of 1 and 2. Let the user decide. (This is perhaps a bit 
>     complicated for a tutorial.)
>
> My response is a combination of the two responses above.
>
>     4) Stop the user from running the tutorial. I do not like this option.
>
> If practical inconveniences makes #2 a bad idea, #4 is what we are
> left with.
>   

I have attempted to make a new solution in accordance with our 
discussion. This new solution has the following changes:

1) The yellow area in the tutorial buffer is now small and has a 
"Details"-link (Kim's suggestion)

2) The "Details"-link displays information in the help buffer.

3) Changed keys are now marked in the tutorial buffer in two ways:
    a) The key (like C-v) has yellow background
    b) There is a line under the key telling what can be used instead 
(in English)

4) The yellow areas in 3 are readonly.

5) There is a link called "Explain" in the yellow areas in 3 that moves 
the point to (point-min)

The support for Viper is still there. I see no reason to remove it since 
I do believe it is useful for Viper users and it does not in any way 
disturb those not using Viper. (Except that the code is more complicated 
of course, but that is only loaded when the tutorial is run.)

The new tutorial.el is attached.


[-- Attachment #2: tutorial.el --]
[-- Type: text/plain, Size: 39954 bytes --]

;;; tutorial.el --- tutorial for Emacs

;; Copyright (C) 2006 Free Software Foundation, Inc.

;; Maintainer: FSF
;; Keywords: help, internal

;; This file is part of GNU Emacs.

;; GNU Emacs is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation; either version 2, or (at your option)
;; any later version.

;; GNU Emacs is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
;; GNU General Public License for more details.

;; You should have received a copy of the GNU General Public License
;; along with GNU Emacs; see the file COPYING.  If not, write to the
;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
;; Boston, MA 02110-1301, USA.


;;; Commentary:

;; Code for running the Emacs tutorial.


;;; History:

;; File was created 2006-08.


;;; Code:

(defun tutorial--detailed-help (button)
  "Give detailed help about changed keys."
  (with-output-to-temp-buffer (help-buffer)
    (help-setup-xref (list #'tutorial--detailed-help button)
                     (interactive-p))
    (with-current-buffer (help-buffer)
      (let* ((tutorial-buffer (button-get button 'tutorial-buffer))
             (tutorial-arg    (button-get button 'tutorial-arg))
             (changed-keys (with-current-buffer tutorial-buffer
                             (tutorial--find-changed-keys))))
        ;;(insert (format "some help: %s, %s" (bufferp tutorial-buffer) tutorial-buffer))

        (when changed-keys
          (insert
           "The following key bindings used in the tutorial had been changed
from Emacs default in the " (buffer-name tutorial-buffer) " buffer:\n\n" )
          (let ((frm "   %-9s %-27s %-11s %s\n"))
            (insert (format frm "Key" "Standard 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 (with-current-buffer tutorial-buffer (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)
                (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)))
                                   (tutorial--describe-nonstandard-key value)))
                               'value (cdr remark)
                               'follow-link t)
                (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)
                   (with-current-buffer tutorial-buffer
                     viper-mode))
          (insert "\n   Information About Viper\n")
          (cond
           ((with-current-buffer tutorial-buffer
              (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 in tutorial! "
                           'action
                           (lambda(b) (interactive)
                             (let ((arg (button-get b 'tutorial-arg))
                                   (buf (button-get b 'tutorial-buffer)))
                               (with-current-buffer buf
                                 (viper-mode)
                                 (set-buffer-modified-p t))
                               (help-with-tutorial arg t)))
                           'tutorial-arg tutorial-arg
                           'tutorial-buffer tutorial-buffer
                           'follow-link t
                           'face 'custom-button
                           'mouse-face 'custom-button-mouse))
           (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 in tutorial! "
                           'action
                           (lambda(b) (interactive)
                             (let ((arg (button-get b 'tutorial-arg))
                                   (buf (button-get b 'tutorial-buffer)))
                               (kill-buffer buf)
                               (help-with-tutorial arg t)))
                           'tutorial-arg tutorial-arg
                           'tutorial-buffer tutorial-buffer
                           '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 'tutorial-arg))
                                     (buf (button-get b 'tutorial-buffer)))
                                 (with-current-buffer buf
                                   (viper-insert nil)
                                   (set-buffer-modified-p t))
                                 (help-with-tutorial arg t)))
                             'tutorial-arg tutorial-arg
                             'tutorial-buffer tutorial-buffer
                             '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 'tutorial-arg))
                                     (buf (button-get b 'tutorial-buffer)))
                                 (with-current-buffer buf
                                   (let ((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))))
                             'tutorial-arg tutorial-arg
                             'tutorial-buffer tutorial-buffer
                             '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)
          (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)
          (insert ".)\n\n")
          (print-help-return-message)
          )))))

(defun tutorial--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.

VALUE should have either of these formats:

  \(cua-mode)
  \(current-binding KEY-FUN DEF-FUN KEY WHERE)

Where
  KEY         is a key sequence whose standard binding has been changed
  KEY-FUN     is the actual binding for KEY
  DEF-FUN     is the standard binding of KEY
  WHERE       is a text describing the key sequences to which DEF-FUN is
              bound now (or, if it is remapped, a key sequence
              for the function it is remapped to)"
  (with-output-to-temp-buffer (help-buffer)
    (help-setup-xref (list #'tutorial--describe-nonstandard-key value)
                     (interactive-p))
    (with-current-buffer (help-buffer)
      (insert
       "Your Emacs customizations override the default binding for this key:"
       "\n\n")
      (let ((inhibit-read-only t))
        (cond
         ((eq (car value) 'cua-mode)
          (insert
           "CUA mode is enabled.

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
                (maps (current-active-maps))
                mapsym)
            ;; Look at the currently active keymaps and try to find
            ;; first the keymap where the current 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))))
            ;; Now, if a keymap was found we must found the symbol
            ;; name for it to display to the user.  This can not
            ;; always be found since all keymaps does not have a
            ;; symbol pointing to them, but here they should have
            ;; that:
            (when map
              (mapatoms (lambda (s)
                          (and
                           ;; If not already found
                           (not mapsym)
                           ;; and if s is a keymap
                           (and (boundp s)
                                (keymapp (symbol-value s)))
                           ;; and not the local symbol map
                           (not (eq s 'map))
                           ;; and the value of s is map
                           (eq map (symbol-value s))
                           ;; then save this value in mapsym
                           (setq mapsym s)))))
            (insert "The default Emacs binding for the key "
                    (key-description key)
                    " is the command `")
            (insert (format "%s" db))
            (insert "'.  "
                    "However, your customizations have rebound it to the command `")
            (insert (format "%s" cb))
            (insert "'.")
            (when mapsym
              (insert "  (For the more advanced user:"
                      " This binding is in the keymap `"
                      (format "%s" mapsym)
                      "'.)"))
            (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))))

(defconst tutorial--default-keys
  (let (
        ;; On window system suspend Emacs is replaced in the
        ;; default keymap so honor this here.
        (suspend-emacs (if window-system
                           'iconify-or-deiconify-frame
                         'suspend-emacs)))
    `(
      ;; 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])
      (,suspend-emacs [?\C-z])
      ))
  "Default Emacs key bindings that the tutorial depends on.")

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

The sorting is for presentation purpose only and is done on the
key sequence.

LEFT and RIGHT are the elements to compare."
  (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
                (listp x) (listp y)
                (equal (car x) (car y)))
      (setq x (cdr x))
      (setq y (cdr y)))
    ;; Try to make a comparision that is useful for presentation (this
    ;; could be made nicer perhaps):
    (let ((cx (car x))
          (cy (car y)))
      ;;(message "x=%s, y=%s;;;; cx=%s, cy=%s" x y cx cy)
      (cond
       ;; Lists? Then call this again
       ((and cx cy
             (listp cx)
             (listp cy))
        (tutorial--sort-keys cx cy))
       ;; Are both numbers? Then just compare them
       ((and (wholenump cx)
             (wholenump cy))
        (> cx cy))
       ;; Is one of them a number? Let that be bigger then.
       ((wholenump cx)
        t)
       ((wholenump cy)
        nil)
       ;; Are both symbols? Compare the names then.
       ((and (symbolp cx)
             (symbolp cy))
        (string< (symbol-name cy)
                 (symbol-name cx)))
       ))))

(defun tutorial--find-changed-keys ()
  "Find the key bindings that have changed.
Check if the default Emacs key bindings that the tutorial depends
on have been changed.

Return a list with the keys that have been changed.  The element
of this list have the following format:

  \(list KEY DEF-FUN DEF-FUN-TXT WHERE REMARK)

Where
  KEY         is a key sequence whose standard binding has been changed
  DEF-FUN     is the standard binding of KEY
  DEF-FUN-TXT is a short descriptive text for DEF-FUN
  WHERE       is a text describing the key sequences to which DEF-FUN is
              bound now (or, if it is remapped, a key sequence
              for the function it is remapped to)
  REMARK      is a list with info about rebinding. It has either of these
              formats:

                \(TEXT cua-mode)
                \(TEXT current-binding KEY-FUN DEF-FUN KEY WHERE)

              Here TEXT is a link text to show to the user.  The
              rest of the list is used to show information when
              the user clicks the link.

              KEY-FUN is the actual binding for KEY."
  (let (changed-keys
        (default-keys (sort tutorial--default-keys
                            'tutorial--sort-keys)))
    (dolist (kdf default-keys)
      ;; The variables below corresponds to those with the same names
      ;; described in the doc string.
      (let* ((key     (nth 1 kdf))
             (def-fun (nth 0 kdf))
             (def-fun-txt (format "%s" def-fun))
             (rem-fun (command-remapping def-fun))
             (key-fun (key-binding key))
             (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)
                   ;; No rebinding, return t
                   t)
                  ((eq key-fun (command-remapping def-fun))
                   ;; Just a remapping, return t
                   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))))
                   ;; These bindings works as the default bindings,
                   ;; return t
                   t)
                  ((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))))
                   ;; This is the strange handling of C-delete and
                   ;; C-backspace, return t
                   t)
                  (t
                   ;; This key has indeed been rebound. Put information
                   ;; in `remark' and return nil
                   (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)))))
    changed-keys))

(defun tutorial--display-changes (changed-keys arg)
  "Display changes to some default key bindings.
If some of the default key bindings that the tutorial depends on
have been changed then display the changes in the tutorial buffer
with some explanatory links.

CHANGED-KEYS should be a list in the format returned by
`tutorial--find-changed-keys'."
  (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))
    (goto-char tutorial--point-before-chkeys)
    (let ((start (point))
          end
          (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)))
      (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 some key
 bindings used in the tutorial had been changed from Emacs
 default. Those key bindings have been marked below. [")
      (insert-button "Details"
                     'tutorial-buffer
                     (current-buffer)
                     'tutorial-arg arg
                     'action
                     'tutorial--detailed-help
                     'follow-link t
                     'face '(:inherit link :background "yellow"))
      (insert "]\n\n" )
      (when changed-keys
        (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)
              ;; Mark the key in the tutorial text
              (unless (string= "Same key" where)
                (let ((here (point))
                      (key-desc (key-description key)))
                  (while (search-forward key-desc nil t)
                    (put-text-property (match-beginning 0)
                                       (match-end 0)
                                       'face '(:background "yellow"))
                    (forward-line)
                    (let ((s (concat
                              "** The key "
                              key-desc
                              " has been rebound, but you can use "
                              where " instead ["))
                          (start (point))
                          end)
                      (insert s)
                      (insert-button "Explain"
                                   'action
                                   (lambda(button) (interactive)
                                     (goto-char (point-min)))
                                   'follow-link t
                                   'help-echo
                                   "Click to go to explanation at top of buffer"
                                   'face '(:inherit 'link :background "yellow"))
                      (insert "] **")
                      (setq end (point))
                      (insert "\n")
                      (put-text-property start end 'local-map tab-map)
                      (put-text-property start end
                                         'face '(:background "yellow" :foreground "#c00"))
                      (put-text-property start end 'read-only t)))
                  (goto-char here)))))))


      (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)
      (setq tutorial--point-after-chkeys (point-marker))
      ;; Make this area read-only:
      (put-text-property start end 'read-only t))))

(defvar tutorial--point-before-chkeys 0
  "Point before display of key changes.")
(make-variable-buffer-local 'tutorial--point-before-chkeys)
(defvar tutorial--point-after-chkeys 0
  "Point after display of key changes.")
(make-variable-buffer-local 'tutorial--point-after-chkeys)

(defvar tutorial--lang nil
  "Tutorial language.")
(make-variable-buffer-local 'tutorial--lang)

(defun tutorial--saved-dir ()
  "Directory where to save tutorials."
  (expand-file-name ".emacstut" "~/"))

(defun tutorial--saved-file ()
  "File name in which to save tutorials."
  (let ((file-name tutorial--lang)
        (ext (file-name-extension tutorial--lang)))
    (when (or (not ext)
              (string= ext ""))
      (setq file-name (concat file-name ".tut")))
    (expand-file-name file-name (tutorial--saved-dir))))

(defun tutorial--save-tutorial ()
  "Save the tutorial buffer.
This saves the part of the tutorial before and after the area
showing changed keys.  It also saves the point position and the
position where the display of changed bindings was inserted."
  ;; Anything to save?
  (when (or (buffer-modified-p)
            (< 1 (point)))
    (let ((tutorial-dir (tutorial--saved-dir))
          save-err)
      ;; The tutorial is saved in a subdirectory in the user home
      ;; directory. Create this subdirectory first.
      (unless (file-directory-p tutorial-dir)
        (condition-case err
            (make-directory tutorial-dir nil)
          (error (setq save-err t)
                 (warn "Could not create directory %s: %s" tutorial-dir
                       (error-message-string err)))))
      ;; Make sure we have that directory.
      (if (file-directory-p tutorial-dir)
          (let ((tut-point (if (= 0 tutorial--point-after-chkeys)
                               ;; No area display changed keys
                               (point)
                             (if (< (point) tutorial--point-after-chkeys)
                                 (- (point))
                               (- (point) tutorial--point-after-chkeys))))
                (old-point (point))
                ;; Use a special undo list so that we easily can undo
                ;; the changes we make to the tutorial buffer.  This is
                ;; currently not needed since we now delete the buffer
                ;; after saving, but kept for possible future use of
                ;; this function.
                buffer-undo-list
                (inhibit-read-only t))
            ;; Delete the area displaying info about changed keys.
            (when (< 0 tutorial--point-after-chkeys)
              (delete-region tutorial--point-before-chkeys
                             tutorial--point-after-chkeys))
            ;; Put the value of point first in the buffer so we can
            ;; write it.
            (goto-char (point-min))
            (insert (number-to-string tut-point)
                    "\n"
                    (number-to-string (marker-position
                                       tutorial--point-before-chkeys))
                    "\n")
            (condition-case err
                (write-region nil nil (tutorial--saved-file))
              (error (setq save-err t)
                     (warn "Could not save tutorial to %s: %s"
                           (tutorial--saved-file)
                           (error-message-string err))))
            ;; Restore point
            ;; An error is raised here?? Is this a bug?
            (condition-case err
                (undo-only)
              (error nil))
            (goto-char old-point)
            (if save-err
                (message "Could not save tutorial state.")
              (message "Saved tutorial state.")))
        (message "Can't save tutorial: %s is not a directory"
                 tutorial-dir)))))

;;;###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.

If any of the standard Emacs key bindings that are used in the
tutorial have been changed then an explanatory note about this is
shown in the beginning of the tutorial buffer.

When the tutorial buffer is killed the content and the point
position in the buffer is saved so that the tutorial may be
resumed later."
  (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))))
         old-tut-file
         (old-tut-point 1))
    (setq tutorial--point-after-chkeys (point-min))
    ;; 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))))
      ;; Else, is there an old tutorial buffer? Then display it:
      (when old-tut-buf
        (switch-to-buffer old-tut-buf)))
    ;; Use whole frame for tutorial
    (delete-other-windows)
    ;; 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? ")))))
    ;; (Re)build the tutorial buffer if it is not ok
    (unless old-tut-is-ok
      (switch-to-buffer (get-buffer-create tut-buf-name))
      (unless lang (error "Variable lang is nil"))
      (setq tutorial--lang lang)
      (setq old-tut-file (file-exists-p (tutorial--saved-file)))
      (let ((inhibit-read-only t))
        (erase-buffer))
      (message "Preparing tutorial ...") (sit-for 0)

      ;; Do not associate the tutorial buffer with a file. Instead use
      ;; a hook to save it when the buffer is killed.
      (setq buffer-auto-save-file-name nil)
      (add-hook 'kill-buffer-hook 'tutorial--save-tutorial nil t)

      ;; Insert the tutorial. First offer to resume last tutorial
      ;; editing session.
      (when dont-ask-for-revert
        (setq old-tut-file nil))
      (when old-tut-file
        (setq old-tut-file
              (y-or-n-p "Resume your last saved tutorial? ")))
      (if old-tut-file
          (progn
            (insert-file-contents (tutorial--saved-file))
            (goto-char (point-min))
            (setq old-tut-point
                  (string-to-number
                   (buffer-substring-no-properties
                    (line-beginning-position) (line-end-position))))
            (forward-line)
            (setq tutorial--point-before-chkeys
                  (string-to-number
                   (buffer-substring-no-properties
                    (line-beginning-position) (line-end-position))))
            (forward-line)
            (delete-region (point-min) (point))
            (goto-char tutorial--point-before-chkeys)
            (setq tutorial--point-before-chkeys (point-marker)))
        (insert-file-contents (expand-file-name filename data-directory))
        (forward-line)
        (setq tutorial--point-before-chkeys (point-marker)))
      (hack-local-variables)


      ;; Check if there are key bindings that may disturb the
      ;; tutorial.  If so tell the user.
      (let ((changed-keys (tutorial--find-changed-keys)))
        (tutorial--display-changes changed-keys arg))


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


      (if old-tut-file
          ;; Just move to old point in saved tutorial.
          (let ((old-point
                 (if (> 0 old-tut-point)
                     (- old-tut-point)
                   (+ old-tut-point tutorial--point-after-chkeys))))
            (when (< old-point 1)
              (setq old-point 1))
            (goto-char old-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))))

(provide 'tutorial)

;;; tutorial.el ends here

[-- 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] 40+ messages in thread

* Re: cua-mode and the tutorial
  2006-08-31 15:10                     ` Lennart Borgman
@ 2006-09-21 14:24                       ` Kim F. Storm
  0 siblings, 0 replies; 40+ messages in thread
From: Kim F. Storm @ 2006-09-21 14:24 UTC (permalink / raw)
  Cc: rms, Michael Kifer, emacs-devel


Sorry for not following up before ...


Lennart Borgman <lennart.borgman.073@student.lu.se> writes:

> I have attempted to make a new solution in accordance with our
> discussion. This new solution has the following changes:
>
> 1) The yellow area in the tutorial buffer is now small and has a
> "Details"-link (Kim's suggestion)

Looks good!

>
> 2) The "Details"-link displays information in the help buffer.

Good.

> 3) Changed keys are now marked in the tutorial buffer in two ways:
>    a) The key (like C-v) has yellow background

Looks good.  Perhaps the shade of yellow could be a little less LOUD ?

>    b) There is a line under the key telling what can be used instead
> (in English)

BAD!  (sorry!)

This is very distracting and really makes it difficult to follow the
ordinary text.  Also, on some pages, the same text is shown several
times.

What about giving a combined help in the echo area about the "yellow
keys":

For example:

** Rebound keys: C-v: <next>  M-v: <prior>

You can color the keys in yellow too.

Of course, you would have to somehow regenerate that message as the
user moves through the tutorial to reflect the yellow keys on the
current page (can't bee too hard with a buffer-local post-command-hook
which scans the buffer from (window-start) to (window-end nil t)).


> 4) The yellow areas in 3 are readonly.
>
> 5) There is a link called "Explain" in the yellow areas in 3 that
> moves the point to (point-min)

This is very confusing too.  I tried it and would have expected it to
tell me something about the specific binding (in the echo area or Help
buffer).  But it would go along with the yellow line, so it's not a
big deal.

Maybe you could show the details buffer if the user clicks on any
of the "yellow keys" (like an anonymouse button).

> The support for Viper is still there. I see no reason to remove it
> since I do believe it is useful for Viper users and it does not in any
> way disturb those not using Viper. (Except that the code is more
> complicated of course, but that is only loaded when the tutorial is
> run.)

Ok.

One problem:

When CUA is enabled, your code doesn't detect that M-v is rebound.


I don't know whether this should be installed before the release,
but in any case it is not (IMHO) ready yet.

WDOT?

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

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

end of thread, other threads:[~2006-09-21 14:24 UTC | newest]

Thread overview: 40+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
     [not found] <44C8F069.1070002@student.lu.se>
2006-08-22 13:12 ` cua-mode and the tutorial Kim F. Storm
2006-08-22 13:26   ` Kim F. Storm
2006-08-22 14:30     ` Lennart Borgman
2006-08-22 15:02       ` Kim F. Storm
2006-08-22 15:57         ` Lennart Borgman
2006-08-22 18:17       ` Richard Stallman
2006-08-23  4:06     ` Richard Stallman
2006-08-23  4:37       ` Lennart Borgman
2006-08-24  5:20         ` Richard Stallman
2006-08-23  7:21       ` Kim F. Storm
2006-08-24  5:20         ` Richard Stallman
2006-08-24  7:30           ` Kim F. Storm
2006-08-25 20:25             ` Richard Stallman
2006-08-25 22:12               ` Kim F. Storm
2006-08-26 12:22                 ` Richard Stallman
2006-08-26 12:44                   ` David Kastrup
2006-08-27 14:34                     ` Richard Stallman
2006-08-26 14:19                   ` Stefan Monnier
2006-08-26 15:07                     ` Drew Adams
2006-08-26 21:15                     ` Kim F. Storm
2006-08-27 14:34                       ` Richard Stallman
2006-08-27 15:06                         ` David Kastrup
2006-08-28 22:09                           ` Richard Stallman
2006-08-27 21:30                         ` Kim F. Storm
2006-08-26 21:14                   ` Kim F. Storm
2006-08-28  9:52                     ` Richard Stallman
2006-08-28 10:07                       ` David Kastrup
2006-08-28 11:21                         ` Kim F. Storm
2006-08-29 17:18                           ` Richard Stallman
2006-08-27  8:35             ` Lennart Borgman
2006-08-28  9:52               ` Richard Stallman
2006-08-28 10:17                 ` Slawomir Nowaczyk
2006-08-29 17:18                   ` Richard Stallman
2006-08-29 17:55                     ` Drew Adams
2006-08-29 18:13                       ` Lennart Borgman
2006-08-28 22:32                 ` Lennart Borgman
2006-08-29 17:18                   ` Richard Stallman
2006-08-31 15:10                     ` Lennart Borgman
2006-09-21 14:24                       ` Kim F. Storm
2006-08-22 14:05   ` Lennart Borgman

Code repositories for project(s) associated with this external index

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

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