Add 2012 to FSF copyright years for Emacs files
[bpt/emacs.git] / lisp / novice.el
CommitLineData
55535639 1;;; novice.el --- handling of disabled commands ("novice mode") for Emacs
6594deb0 2
acaf905b 3;; Copyright (C) 1985-1987, 1994, 2001-2012 Free Software Foundation, Inc.
9750e079 4
e5167999 5;; Maintainer: FSF
d7b4d18f 6;; Keywords: internal, help
e5167999 7
a2535589
JA
8;; This file is part of GNU Emacs.
9
eb3fa2cf 10;; GNU Emacs is free software: you can redistribute it and/or modify
a2535589 11;; it under the terms of the GNU General Public License as published by
eb3fa2cf
GM
12;; the Free Software Foundation, either version 3 of the License, or
13;; (at your option) any later version.
a2535589
JA
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
eb3fa2cf 21;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
a2535589 22
edbd2f74
ER
23;;; Commentary:
24
25;; This mode provides a hook which is, by default, attached to various
26;; putatively dangerous commands in a (probably futile) attempt to
27;; prevent lusers from shooting themselves in the feet.
28
aae56ea7 29;;; Code:
a2535589
JA
30
31;; This function is called (by autoloading)
32;; to handle any disabled command.
33;; The command is found in this-command
34;; and the keys are returned by (this-command-keys).
35
8d720a00
SM
36(eval-when-compile (require 'cl))
37
7229064d 38;;;###autoload
939a7761 39(defvar disabled-command-function 'disabled-command-function
4442951c
EN
40 "Function to call to handle disabled commands.
41If nil, the feature is disabled, i.e., all commands work normally.")
73fa8346 42
52e3545b 43;;;###autoload
6d9c9ad9 44(define-obsolete-variable-alias 'disabled-command-hook 'disabled-command-function "22.1")
939a7761 45
e3d47a15
RS
46;; It is ok here to assume that this-command is a symbol
47;; because we won't get called otherwise.
1c599895 48;;;###autoload
8d720a00
SM
49(defun disabled-command-function (&optional cmd keys)
50 (unless cmd (setq cmd this-command))
51 (unless keys (setq keys (this-command-keys)))
a2535589
JA
52 (let (char)
53 (save-window-excursion
8d720a00
SM
54 (help-setup-xref (list 'disabled-command-function cmd keys) nil)
55 (with-output-to-temp-buffer "*Disabled Command*" ;; (help-buffer)
be29d453
KH
56 (if (or (eq (aref keys 0)
57 (if (stringp keys)
58 (aref "\M-x" 0)
59 ?\M-x))
60 (and (>= (length keys) 2)
61 (eq (aref keys 0) meta-prefix-char)
62 (eq (aref keys 1) ?x)))
8d720a00 63 (princ (format "You have invoked the disabled command %s.\n" cmd))
606e6135 64 (princ (format "You have typed %s, invoking disabled command %s.\n"
8d720a00 65 (key-description keys) cmd)))
a2535589 66 ;; Print any special message saying why the command is disabled.
8d720a00
SM
67 (if (stringp (get cmd 'disabled))
68 (princ (get cmd 'disabled))
606e6135
RS
69 (princ "It is disabled because new users often find it confusing.\n")
70 (princ "Here's the first part of its description:\n\n")
71 ;; Keep only the first paragraph of the documentation.
8d720a00 72 (with-current-buffer "*Disabled Command*" ;; standard-output
606e6135
RS
73 (goto-char (point-max))
74 (let ((start (point)))
75 (save-excursion
76 (princ (or (condition-case ()
8d720a00 77 (documentation cmd)
606e6135
RS
78 (error nil))
79 "<< not documented >>")))
80 (if (search-forward "\n\n" nil t)
81 (delete-region (match-beginning 0) (point-max)))
82 (goto-char (point-max))
83 (indent-rigidly start (point) 3))))
84 (princ "\n\nDo you want to use this command anyway?\n\n")
a2535589 85 (princ "You can now type
eb4cb84f
PJ
86y to try it and enable it (no questions if you use it again).
87n to cancel--don't try the command, and it remains disabled.
606e6135
RS
88SPC to try the command just this once, but leave it disabled.
89! to try it, and enable all disabled commands for this session only.")
8d720a00
SM
90 ;; Redundant since with-output-to-temp-buffer will do it anyway.
91 ;; (with-current-buffer standard-output
92 ;; (help-mode))
93 )
0468beec 94 (fit-window-to-buffer (get-buffer-window "*Disabled Command*"))
eb4cb84f 95 (message "Type y, n, ! or SPC (the space bar): ")
a2535589 96 (let ((cursor-in-echo-area t))
72287c23
RS
97 (while (progn (setq char (read-event))
98 (or (not (numberp char))
99 (not (memq (downcase char)
2634a72a 100 '(?! ?y ?n ?\s ?\C-g)))))
a2535589 101 (ding)
eb4cb84f 102 (message "Please type y, n, ! or SPC (the space bar): "))))
72287c23 103 (setq char (downcase char))
8d720a00
SM
104 (case char
105 (?\C-g (setq quit-flag t))
106 (?! (setq disabled-command-function nil))
107 (?y
7435bd25
RS
108 (if (and user-init-file
109 (not (string= "" user-init-file))
110 (y-or-n-p "Enable command for future editing sessions also? "))
8d720a00 111 (enable-command cmd)
f0a698ab
GM
112 (put cmd 'disabled nil))))
113 (or (char-equal char ?n)
114 (call-interactively cmd))))
8d720a00
SM
115
116(defun en/disable-command (command disable)
117 (unless (commandp command)
118 (error "Invalid command name `%s'" command))
119 (put command 'disabled disable)
2308fe27
EZ
120 (let ((init-file user-init-file)
121 (default-init-file
122 (if (eq system-type 'ms-dos) "~/_emacs" "~/.emacs")))
8d720a00 123 (unless init-file
2308fe27
EZ
124 (if (or (file-exists-p default-init-file)
125 (and (eq system-type 'windows-nt)
126 (file-exists-p "~/_emacs")))
127 ;; Started with -q, i.e. the file containing
128 ;; enabled/disabled commands hasn't been read. Saving
129 ;; settings there would overwrite other settings.
130 (error "Saving settings from \"emacs -q\" would overwrite existing customizations"))
131 (setq init-file default-init-file)
49b1a638
EZ
132 (if (and (not (file-exists-p init-file))
133 (eq system-type 'windows-nt)
134 (file-exists-p "~/_emacs"))
135 (setq init-file "~/_emacs")))
7fdbcd83
SM
136 (with-current-buffer (find-file-noselect
137 (substitute-in-file-name init-file))
49b1a638
EZ
138 (goto-char (point-min))
139 (if (search-forward (concat "(put '" (symbol-name command) " ") nil t)
140 (delete-region
141 (progn (beginning-of-line) (point))
142 (progn (forward-line 1) (point))))
143 ;; Explicitly enable, in case this command is disabled by default
144 ;; or in case the code we deleted was actually a comment.
145 (goto-char (point-max))
8d720a00
SM
146 (unless (bolp) (newline))
147 (insert "(put '" (symbol-name command) " 'disabled "
148 (symbol-name disable) ")\n")
49b1a638 149 (save-buffer))))
a2535589 150
8d720a00
SM
151;;;###autoload
152(defun enable-command (command)
153 "Allow COMMAND to be executed without special confirmation from now on.
154COMMAND must be a symbol.
155This command alters the user's .emacs file so that this will apply
156to future sessions."
157 (interactive "CEnable command: ")
158 (en/disable-command command nil))
159
7229064d 160;;;###autoload
a2535589
JA
161(defun disable-command (command)
162 "Require special confirmation to execute COMMAND from now on.
7a4d608f
LT
163COMMAND must be a symbol.
164This command alters the user's .emacs file so that this will apply
a2535589
JA
165to future sessions."
166 (interactive "CDisable command: ")
8d720a00 167 (en/disable-command command t))
a2535589 168
896546cd
RS
169(provide 'novice)
170
6594deb0 171;;; novice.el ends here