1 ;;; em-alias.el --- creation and management of command aliases
3 ;; Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004,
4 ;; 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
6 ;; Author: John Wiegley <johnw@gnu.org>
8 ;; This file is part of GNU Emacs.
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 3, or (at your option)
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.
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., 51 Franklin Street, Fifth Floor,
23 ;; Boston, MA 02110-1301, USA.
27 ;; Command aliases greatly simplify the definition of new commands.
28 ;; They exist as an alternative to alias functions, which are
29 ;; otherwise quite superior, being more flexible and natural to the
30 ;; Emacs Lisp environment (if somewhat trickier to define; [Alias
33 ;;;_* Creating aliases
35 ;; The user interface is simple: type 'alias' followed by the command
36 ;; name followed by the definition. Argument references are made
37 ;; using '$1', '$2', etc., or '$*'. For example:
39 ;; alias ll 'ls -l $*'
41 ;; This will cause the command 'll NEWS' to be replaced by 'ls -l
42 ;; NEWS'. This is then passed back to the command parser for
43 ;; reparsing.{Only the command text specified in the alias definition
44 ;; will be reparsed. Argument references (such as '$*') are handled
45 ;; using variable values, which means that the expansion will not be
46 ;; reparsed, but used directly.}
48 ;; To delete an alias, specify its name without a definition:
52 ;; Aliases are written to disk immediately after being defined or
53 ;; deleted. The filename in which they are kept is defined by the
54 ;; variable eshell-aliases-file.
56 ;; The format of this file is quite basic. It specifies the alias
57 ;; definitions in almost exactly the same way that the user entered
58 ;; them, minus any argument quoting (since interpolation is not done
59 ;; when the file is read). Hence, it is possible to add new aliases
60 ;; to the alias file directly, using a text editor rather than the
61 ;; `alias' command. Or, this method can be used for editing aliases
62 ;; that have already defined.
64 ;; Here is an example of a few different aliases, and they would
65 ;; appear in the aliases file:
67 ;; alias clean rm -fr **/.#*~
68 ;; alias commit cvs commit -m changes $*
71 ;; alias reindex glimpseindex -o ~/Mail
72 ;; alias compact for i in ~/Mail/**/*~*.bz2(Lk+50) { bzip2 -9v $i }
74 ;;;_* Auto-correction of bad commands
76 ;; When a user enters the same unknown command many times during a
77 ;; session, it is likely that they are experiencing a spelling
78 ;; difficulty associated with a certain command. To combat this,
79 ;; Eshell will offer to automatically define an alias for that
80 ;; mispelled command, once a given tolerance threshold has been
83 ;; Whenever the same bad command name is encountered
84 ;; `eshell-bad-command-tolerance' times, the user will be prompted in
85 ;; the minibuffer to provide an alias name. An alias definition will
86 ;; then be created which will result in an equal call to the correct
87 ;; name. In this way, Eshell gradually learns about the commands that
88 ;; the user mistypes frequently, and will automatically correct them!
90 ;; Note that a '$*' is automatically appended at the end of the alias
91 ;; definition, so that entering it is unnecessary when specifying the
92 ;; corrected command name.
100 (defgroup eshell-alias nil
101 "Command aliases allow for easy definition of alternate commands."
102 :tag
"Command aliases"
103 ;; :link '(info-link "(eshell)Command aliases")
104 :group
'eshell-module
)
106 (defcustom eshell-aliases-file
(concat eshell-directory-name
"alias")
107 "*The file in which aliases are kept.
108 Whenever an alias is defined by the user, using the `alias' command,
109 it will be written to this file. Thus, alias definitions (and
110 deletions) are always permanent. This approach was chosen for the
111 sake of simplicity, since that's pretty much the only benefit to be
112 gained by using this module."
114 :group
'eshell-alias
)
116 (defcustom eshell-bad-command-tolerance
3
117 "*The number of failed commands to ignore before creating an alias."
119 ;; :link '(custom-manual "(eshell)Auto-correction of bad commands")
120 :group
'eshell-alias
)
122 (defcustom eshell-alias-load-hook
'(eshell-alias-initialize)
123 "*A hook that gets run when `eshell-alias' is loaded."
125 :group
'eshell-alias
)
127 (defvar eshell-command-aliases-list nil
128 "A list of command aliases currently defined by the user.
129 Each element of this alias is a list of the form:
133 Where NAME is the textual name of the alias, and DEFINITION is the
134 command string to replace that command with.
136 Note: this list should not be modified in your '.emacs' file. Rather,
137 any desired alias definitions should be declared using the `alias'
138 command, which will automatically write them to the file named by
139 `eshell-aliases-file'.")
141 (put 'eshell-command-aliases-list
'risky-local-variable t
)
143 (defvar eshell-failed-commands-alist nil
144 "An alist of command name failures.")
146 (defun eshell-alias-initialize ()
147 "Initialize the alias handling code."
148 (make-local-variable 'eshell-failed-commands-alist
)
149 (add-hook 'eshell-alternate-command-hook
'eshell-fix-bad-commands t t
)
150 (eshell-read-aliases-list)
151 (add-hook 'eshell-named-command-hook
'eshell-maybe-replace-by-alias t t
)
152 (make-local-variable 'eshell-complex-commands
)
153 (add-to-list 'eshell-complex-commands
'eshell-command-aliased-p
))
155 (defun eshell-command-aliased-p (name)
156 (assoc name eshell-command-aliases-list
))
158 (defun eshell/alias
(&optional alias
&rest definition
)
159 "Define an ALIAS in the user's alias list using DEFINITION."
161 (eshell-for alias eshell-command-aliases-list
162 (eshell-print (apply 'format
"alias %s %s\n" alias
)))
164 (setq eshell-command-aliases-list
165 (delq (assoc alias eshell-command-aliases-list
)
166 eshell-command-aliases-list
))
167 (and (stringp definition
)
168 (set-text-properties 0 (length definition
) nil definition
))
169 (let ((def (assoc alias eshell-command-aliases-list
))
170 (alias-def (list alias
171 (eshell-flatten-and-stringify definition
))))
173 (setq eshell-command-aliases-list
174 (delq def eshell-command-aliases-list
)))
175 (setq eshell-command-aliases-list
176 (cons alias-def eshell-command-aliases-list
))))
177 (eshell-write-aliases-list))
180 (defvar pcomplete-stub
)
181 (autoload 'pcomplete-here
"pcomplete")
183 (defun pcomplete/eshell-mode
/alias
()
184 "Completion function for Eshell's `alias' command."
185 (pcomplete-here (eshell-alias-completions pcomplete-stub
)))
187 (defun eshell-read-aliases-list ()
188 "Read in an aliases list from `eshell-aliases-file'."
189 (let ((file eshell-aliases-file
))
190 (when (file-readable-p file
)
191 (setq eshell-command-aliases-list
193 (let (eshell-command-aliases-list)
194 (insert-file-contents file
)
196 (if (re-search-forward
197 "^alias\\s-+\\(\\S-+\\)\\s-+\\(.+\\)")
198 (setq eshell-command-aliases-list
199 (cons (list (match-string 1)
201 eshell-command-aliases-list
)))
203 eshell-command-aliases-list
))))))
205 (defun eshell-write-aliases-list ()
206 "Write out the current aliases into `eshell-aliases-file'."
207 (if (file-writable-p (file-name-directory eshell-aliases-file
))
208 (let ((eshell-current-handles
209 (eshell-create-handles eshell-aliases-file
'overwrite
)))
211 (eshell-close-handles 0))))
213 (defsubst eshell-lookup-alias
(name)
214 "Check whether NAME is aliased. Return the alias if there is one."
215 (assoc name eshell-command-aliases-list
))
217 (defvar eshell-prevent-alias-expansion nil
)
219 (defun eshell-maybe-replace-by-alias (command args
)
220 "If COMMAND has an alias definition, call that instead using ARGS."
221 (unless (and eshell-prevent-alias-expansion
222 (member command eshell-prevent-alias-expansion
))
223 (let ((alias (eshell-lookup-alias command
)))
225 (throw 'eshell-replace-command
229 (list 'eshell-command-name
230 (list 'quote eshell-last-command-name
))
231 (list 'eshell-command-arguments
232 (list 'quote eshell-last-arguments
))
233 (list 'eshell-prevent-alias-expansion
236 eshell-prevent-alias-expansion
))))
237 (eshell-parse-command (nth 1 alias
))))))))
239 (defun eshell-alias-completions (name)
240 "Find all possible completions for NAME.
241 These are all the command aliases which begin with NAME."
243 (eshell-for alias eshell-command-aliases-list
244 (if (string-match (concat "^" name
) (car alias
))
245 (setq completions
(cons (car alias
) completions
))))
248 (defun eshell-fix-bad-commands (name)
249 "If the user repeatedly a bad command NAME, make an alias for them."
251 (unless (file-name-directory name
)
252 (let ((entry (assoc name eshell-failed-commands-alist
)))
254 (setq eshell-failed-commands-alist
255 (cons (cons name
1) eshell-failed-commands-alist
))
256 (if (< (cdr entry
) eshell-bad-command-tolerance
)
257 (setcdr entry
(1+ (cdr entry
)))
260 (format "Define alias for \"%s\": " name
))
262 (eshell/alias name alias
)
263 (throw 'eshell-replace-command
267 (list 'eshell-command-name
269 (list 'eshell-command-arguments
270 (list 'quote eshell-last-arguments
))
271 (list 'eshell-prevent-alias-expansion
274 eshell-prevent-alias-expansion
))))
275 (eshell-parse-command alias
))))))))))
279 ;; arch-tag: 8b018fc1-4e07-4ccc-aa73-c0a1ba361f82
280 ;;; em-alias.el ends here