##// END OF EJS Templates
set `__doc__` for aliases...
Min RK -
Show More
@@ -1,256 +1,257 b''
1 1 # encoding: utf-8
2 2 """
3 3 System command aliases.
4 4
5 5 Authors:
6 6
7 7 * Fernando Perez
8 8 * Brian Granger
9 9 """
10 10
11 11 #-----------------------------------------------------------------------------
12 12 # Copyright (C) 2008-2011 The IPython Development Team
13 13 #
14 14 # Distributed under the terms of the BSD License.
15 15 #
16 16 # The full license is in the file COPYING.txt, distributed with this software.
17 17 #-----------------------------------------------------------------------------
18 18
19 19 #-----------------------------------------------------------------------------
20 20 # Imports
21 21 #-----------------------------------------------------------------------------
22 22
23 23 import os
24 24 import re
25 25 import sys
26 26
27 27 from traitlets.config.configurable import Configurable
28 28 from IPython.core.error import UsageError
29 29
30 30 from IPython.utils.py3compat import string_types
31 31 from traitlets import List, Instance
32 32 from IPython.utils.warn import error
33 33
34 34 #-----------------------------------------------------------------------------
35 35 # Utilities
36 36 #-----------------------------------------------------------------------------
37 37
38 38 # This is used as the pattern for calls to split_user_input.
39 39 shell_line_split = re.compile(r'^(\s*)()(\S+)(.*$)')
40 40
41 41 def default_aliases():
42 42 """Return list of shell aliases to auto-define.
43 43 """
44 44 # Note: the aliases defined here should be safe to use on a kernel
45 45 # regardless of what frontend it is attached to. Frontends that use a
46 46 # kernel in-process can define additional aliases that will only work in
47 47 # their case. For example, things like 'less' or 'clear' that manipulate
48 48 # the terminal should NOT be declared here, as they will only work if the
49 49 # kernel is running inside a true terminal, and not over the network.
50 50
51 51 if os.name == 'posix':
52 52 default_aliases = [('mkdir', 'mkdir'), ('rmdir', 'rmdir'),
53 53 ('mv', 'mv'), ('rm', 'rm'), ('cp', 'cp'),
54 54 ('cat', 'cat'),
55 55 ]
56 56 # Useful set of ls aliases. The GNU and BSD options are a little
57 57 # different, so we make aliases that provide as similar as possible
58 58 # behavior in ipython, by passing the right flags for each platform
59 59 if sys.platform.startswith('linux'):
60 60 ls_aliases = [('ls', 'ls -F --color'),
61 61 # long ls
62 62 ('ll', 'ls -F -o --color'),
63 63 # ls normal files only
64 64 ('lf', 'ls -F -o --color %l | grep ^-'),
65 65 # ls symbolic links
66 66 ('lk', 'ls -F -o --color %l | grep ^l'),
67 67 # directories or links to directories,
68 68 ('ldir', 'ls -F -o --color %l | grep /$'),
69 69 # things which are executable
70 70 ('lx', 'ls -F -o --color %l | grep ^-..x'),
71 71 ]
72 72 elif sys.platform.startswith('openbsd') or sys.platform.startswith('netbsd'):
73 73 # OpenBSD, NetBSD. The ls implementation on these platforms do not support
74 74 # the -G switch and lack the ability to use colorized output.
75 75 ls_aliases = [('ls', 'ls -F'),
76 76 # long ls
77 77 ('ll', 'ls -F -l'),
78 78 # ls normal files only
79 79 ('lf', 'ls -F -l %l | grep ^-'),
80 80 # ls symbolic links
81 81 ('lk', 'ls -F -l %l | grep ^l'),
82 82 # directories or links to directories,
83 83 ('ldir', 'ls -F -l %l | grep /$'),
84 84 # things which are executable
85 85 ('lx', 'ls -F -l %l | grep ^-..x'),
86 86 ]
87 87 else:
88 88 # BSD, OSX, etc.
89 89 ls_aliases = [('ls', 'ls -F -G'),
90 90 # long ls
91 91 ('ll', 'ls -F -l -G'),
92 92 # ls normal files only
93 93 ('lf', 'ls -F -l -G %l | grep ^-'),
94 94 # ls symbolic links
95 95 ('lk', 'ls -F -l -G %l | grep ^l'),
96 96 # directories or links to directories,
97 97 ('ldir', 'ls -F -G -l %l | grep /$'),
98 98 # things which are executable
99 99 ('lx', 'ls -F -l -G %l | grep ^-..x'),
100 100 ]
101 101 default_aliases = default_aliases + ls_aliases
102 102 elif os.name in ['nt', 'dos']:
103 103 default_aliases = [('ls', 'dir /on'),
104 104 ('ddir', 'dir /ad /on'), ('ldir', 'dir /ad /on'),
105 105 ('mkdir', 'mkdir'), ('rmdir', 'rmdir'),
106 106 ('echo', 'echo'), ('ren', 'ren'), ('copy', 'copy'),
107 107 ]
108 108 else:
109 109 default_aliases = []
110 110
111 111 return default_aliases
112 112
113 113
114 114 class AliasError(Exception):
115 115 pass
116 116
117 117
118 118 class InvalidAliasError(AliasError):
119 119 pass
120 120
121 121 class Alias(object):
122 122 """Callable object storing the details of one alias.
123 123
124 124 Instances are registered as magic functions to allow use of aliases.
125 125 """
126 126
127 127 # Prepare blacklist
128 128 blacklist = {'cd','popd','pushd','dhist','alias','unalias'}
129 129
130 130 def __init__(self, shell, name, cmd):
131 131 self.shell = shell
132 132 self.name = name
133 133 self.cmd = cmd
134 self.__doc__ = "Alias for `!{}`".format(cmd)
134 135 self.nargs = self.validate()
135 136
136 137 def validate(self):
137 138 """Validate the alias, and return the number of arguments."""
138 139 if self.name in self.blacklist:
139 140 raise InvalidAliasError("The name %s can't be aliased "
140 141 "because it is a keyword or builtin." % self.name)
141 142 try:
142 143 caller = self.shell.magics_manager.magics['line'][self.name]
143 144 except KeyError:
144 145 pass
145 146 else:
146 147 if not isinstance(caller, Alias):
147 148 raise InvalidAliasError("The name %s can't be aliased "
148 149 "because it is another magic command." % self.name)
149 150
150 151 if not (isinstance(self.cmd, string_types)):
151 152 raise InvalidAliasError("An alias command must be a string, "
152 153 "got: %r" % self.cmd)
153 154
154 155 nargs = self.cmd.count('%s') - self.cmd.count('%%s')
155 156
156 157 if (nargs > 0) and (self.cmd.find('%l') >= 0):
157 158 raise InvalidAliasError('The %s and %l specifiers are mutually '
158 159 'exclusive in alias definitions.')
159 160
160 161 return nargs
161 162
162 163 def __repr__(self):
163 164 return "<alias {} for {!r}>".format(self.name, self.cmd)
164 165
165 166 def __call__(self, rest=''):
166 167 cmd = self.cmd
167 168 nargs = self.nargs
168 169 # Expand the %l special to be the user's input line
169 170 if cmd.find('%l') >= 0:
170 171 cmd = cmd.replace('%l', rest)
171 172 rest = ''
172 173
173 174 if nargs==0:
174 175 if cmd.find('%%s') >= 1:
175 176 cmd = cmd.replace('%%s', '%s')
176 177 # Simple, argument-less aliases
177 178 cmd = '%s %s' % (cmd, rest)
178 179 else:
179 180 # Handle aliases with positional arguments
180 181 args = rest.split(None, nargs)
181 182 if len(args) < nargs:
182 183 raise UsageError('Alias <%s> requires %s arguments, %s given.' %
183 184 (self.name, nargs, len(args)))
184 185 cmd = '%s %s' % (cmd % tuple(args[:nargs]),' '.join(args[nargs:]))
185 186
186 187 self.shell.system(cmd)
187 188
188 189 #-----------------------------------------------------------------------------
189 190 # Main AliasManager class
190 191 #-----------------------------------------------------------------------------
191 192
192 193 class AliasManager(Configurable):
193 194
194 195 default_aliases = List(default_aliases(), config=True)
195 196 user_aliases = List(default_value=[], config=True)
196 197 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC', allow_none=True)
197 198
198 199 def __init__(self, shell=None, **kwargs):
199 200 super(AliasManager, self).__init__(shell=shell, **kwargs)
200 201 # For convenient access
201 202 self.linemagics = self.shell.magics_manager.magics['line']
202 203 self.init_aliases()
203 204
204 205 def init_aliases(self):
205 206 # Load default & user aliases
206 207 for name, cmd in self.default_aliases + self.user_aliases:
207 208 self.soft_define_alias(name, cmd)
208 209
209 210 @property
210 211 def aliases(self):
211 212 return [(n, func.cmd) for (n, func) in self.linemagics.items()
212 213 if isinstance(func, Alias)]
213 214
214 215 def soft_define_alias(self, name, cmd):
215 216 """Define an alias, but don't raise on an AliasError."""
216 217 try:
217 218 self.define_alias(name, cmd)
218 219 except AliasError as e:
219 220 error("Invalid alias: %s" % e)
220 221
221 222 def define_alias(self, name, cmd):
222 223 """Define a new alias after validating it.
223 224
224 225 This will raise an :exc:`AliasError` if there are validation
225 226 problems.
226 227 """
227 228 caller = Alias(shell=self.shell, name=name, cmd=cmd)
228 229 self.shell.magics_manager.register_function(caller, magic_kind='line',
229 230 magic_name=name)
230 231
231 232 def get_alias(self, name):
232 233 """Return an alias, or None if no alias by that name exists."""
233 234 aname = self.linemagics.get(name, None)
234 235 return aname if isinstance(aname, Alias) else None
235 236
236 237 def is_alias(self, name):
237 238 """Return whether or not a given name has been defined as an alias"""
238 239 return self.get_alias(name) is not None
239 240
240 241 def undefine_alias(self, name):
241 242 if self.is_alias(name):
242 243 del self.linemagics[name]
243 244 else:
244 245 raise ValueError('%s is not an alias' % name)
245 246
246 247 def clear_aliases(self):
247 248 for name, cmd in self.aliases:
248 249 self.undefine_alias(name)
249 250
250 251 def retrieve_alias(self, name):
251 252 """Retrieve the command to which an alias expands."""
252 253 caller = self.get_alias(name)
253 254 if caller:
254 255 return caller.cmd
255 256 else:
256 257 raise ValueError('%s is not an alias' % name)
General Comments 0
You need to be logged in to leave comments. Login now