(eudc-external-viewers): Do not use xv, it is not free.
[bpt/emacs.git] / lisp / novice.el
1 ;;; novice.el --- handling of disabled commands ("novice mode") for Emacs
2
3 ;; Copyright (C) 1985, 1986, 1987, 1994 Free Software Foundation, Inc.
4
5 ;; Maintainer: FSF
6 ;; Keywords: internal, help
7
8 ;; This file is part of GNU Emacs.
9
10 ;; GNU Emacs is free software; you can redistribute it and/or modify
11 ;; it under the terms of the GNU General Public License as published by
12 ;; the Free Software Foundation; either version 2, or (at your option)
13 ;; any later version.
14
15 ;; GNU Emacs is distributed in the hope that it will be useful,
16 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
17 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 ;; GNU General Public License for more details.
19
20 ;; You should have received a copy of the GNU General Public License
21 ;; along with GNU Emacs; see the file COPYING. If not, write to the
22 ;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
23 ;; Boston, MA 02111-1307, USA.
24
25 ;;; Commentary:
26
27 ;; This mode provides a hook which is, by default, attached to various
28 ;; putatively dangerous commands in a (probably futile) attempt to
29 ;; prevent lusers from shooting themselves in the feet.
30
31 ;;; Code:
32
33 ;; This function is called (by autoloading)
34 ;; to handle any disabled command.
35 ;; The command is found in this-command
36 ;; and the keys are returned by (this-command-keys).
37
38 ;;;###autoload
39 (defvar disabled-command-hook 'disabled-command-hook
40 "Function to call to handle disabled commands.
41 If nil, the feature is disabled, i.e., all commands work normally.")
42
43 ;;;###autoload
44 (defun disabled-command-hook (&rest ignore)
45 (let (char)
46 (save-window-excursion
47 (with-output-to-temp-buffer "*Help*"
48 (let ((keys (this-command-keys)))
49 (if (or (eq (aref keys 0)
50 (if (stringp keys)
51 (aref "\M-x" 0)
52 ?\M-x))
53 (and (>= (length keys) 2)
54 (eq (aref keys 0) meta-prefix-char)
55 (eq (aref keys 1) ?x)))
56 (princ "You have invoked the disabled command ")
57 (princ "You have typed ")
58 (princ (key-description keys))
59 (princ ", invoking disabled command ")))
60 (princ this-command)
61 (princ ":\n")
62 ;; Print any special message saying why the command is disabled.
63 (if (stringp (get this-command 'disabled))
64 (princ (get this-command 'disabled)))
65 ;; Keep only the first paragraph of the documentation.
66 (save-excursion
67 (set-buffer "*Help*")
68 (goto-char (point-max))
69 (save-excursion
70 (princ (or (condition-case ()
71 (documentation this-command)
72 (error nil))
73 "<< not documented >>")))
74 (if (search-forward "\n\n" nil t)
75 (delete-region (1- (point)) (point-max))
76 (goto-char (point-max))))
77 (princ "\n\n")
78 (princ "You can now type
79 Space to try the command just this once, but leave it disabled,
80 Y to try it and enable it (no questions if you use it again),
81 ! to try it and enable all commands in this session, or
82 N to do nothing (command remains disabled).")
83 (save-excursion
84 (set-buffer standard-output)
85 (help-mode)))
86 (message "Type y, n, ! or Space: ")
87 (let ((cursor-in-echo-area t))
88 (while (not (memq (setq char (downcase (read-char)))
89 '(?! ? ?y ?n)))
90 (ding)
91 (message "Please type y, n, ! or Space: "))))
92 (if (= char ?!)
93 (setq disabled-command-hook nil))
94 (if (= char ?y)
95 (if (and user-init-file
96 (not (string= "" user-init-file))
97 (y-or-n-p "Enable command for future editing sessions also? "))
98 (enable-command this-command)
99 (put this-command 'disabled nil)))
100 (if (/= char ?n)
101 (call-interactively this-command))))
102
103 ;;;###autoload
104 (defun enable-command (command)
105 "Allow COMMAND to be executed without special confirmation from now on.
106 The user's .emacs file is altered so that this will apply
107 to future sessions."
108 (interactive "CEnable command: ")
109 (put command 'disabled nil)
110 (let ((init-file user-init-file))
111 (when (or (not (stringp init-file))
112 (not (file-exists-p init-file)))
113 (setq init-file (if (eq system-type 'ms-dos) "~/_emacs" "~/.emacs"))
114 (if (and (not (file-exists-p init-file))
115 (eq system-type 'windows-nt)
116 (file-exists-p "~/_emacs"))
117 (setq init-file "~/_emacs")))
118 (save-excursion
119 (set-buffer (find-file-noselect
120 (substitute-in-file-name init-file)))
121 (goto-char (point-min))
122 (if (search-forward (concat "(put '" (symbol-name command) " ") nil t)
123 (delete-region
124 (progn (beginning-of-line) (point))
125 (progn (forward-line 1) (point))))
126 ;; Explicitly enable, in case this command is disabled by default
127 ;; or in case the code we deleted was actually a comment.
128 (goto-char (point-max))
129 (insert "\n(put '" (symbol-name command) " 'disabled nil)\n")
130 (save-buffer))))
131
132 ;;;###autoload
133 (defun disable-command (command)
134 "Require special confirmation to execute COMMAND from now on.
135 The user's .emacs file is altered so that this will apply
136 to future sessions."
137 (interactive "CDisable command: ")
138 (if (not (commandp command))
139 (error "Invalid command name `%s'" command))
140 (put command 'disabled t)
141 (save-excursion
142 (set-buffer (find-file-noselect
143 (substitute-in-file-name user-init-file)))
144 (goto-char (point-min))
145 (if (search-forward (concat "(put '" (symbol-name command) " ") nil t)
146 (delete-region
147 (progn (beginning-of-line) (point))
148 (progn (forward-line 1) (point))))
149 (goto-char (point-max))
150 (insert "\n(put '" (symbol-name command) " 'disabled t)\n")
151 (save-buffer)))
152
153 (provide 'novice)
154
155 ;;; novice.el ends here