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