##// END OF EJS Templates
added comment on reason for seperate ls_alias for OpenBSD/NetBSD
bsvh -
Show More
@@ -1,252 +1,253 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 IPython.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 IPython.utils.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 # OpenBSD, NetBSD
73 # OpenBSD, NetBSD. The ls implementation on these platforms do not support
74 # the -G switch and lack the ability to use colorized output.
74 75 ls_aliases = [('ls', 'ls -F'),
75 76 # long ls
76 77 ('ll', 'ls -F -l'),
77 78 # ls normal files only
78 79 ('lf', 'ls -F -l %l | grep ^-'),
79 80 # ls symbolic links
80 81 ('lk', 'ls -F -l %l | grep ^l'),
81 82 # directories or links to directories,
82 83 ('ldir', 'ls -F -l %l | grep /$'),
83 84 # things which are executable
84 85 ('lx', 'ls -F -l %l | grep ^-..x'),
85 86 ]
86 87 else:
87 88 # BSD, OSX, etc.
88 89 ls_aliases = [('ls', 'ls -F -G'),
89 90 # long ls
90 91 ('ll', 'ls -F -l -G'),
91 92 # ls normal files only
92 93 ('lf', 'ls -F -l -G %l | grep ^-'),
93 94 # ls symbolic links
94 95 ('lk', 'ls -F -l -G %l | grep ^l'),
95 96 # directories or links to directories,
96 97 ('ldir', 'ls -F -G -l %l | grep /$'),
97 98 # things which are executable
98 99 ('lx', 'ls -F -l -G %l | grep ^-..x'),
99 100 ]
100 101 default_aliases = default_aliases + ls_aliases
101 102 elif os.name in ['nt', 'dos']:
102 103 default_aliases = [('ls', 'dir /on'),
103 104 ('ddir', 'dir /ad /on'), ('ldir', 'dir /ad /on'),
104 105 ('mkdir', 'mkdir'), ('rmdir', 'rmdir'),
105 106 ('echo', 'echo'), ('ren', 'ren'), ('copy', 'copy'),
106 107 ]
107 108 else:
108 109 default_aliases = []
109 110
110 111 return default_aliases
111 112
112 113
113 114 class AliasError(Exception):
114 115 pass
115 116
116 117
117 118 class InvalidAliasError(AliasError):
118 119 pass
119 120
120 121 class Alias(object):
121 122 """Callable object storing the details of one alias.
122 123
123 124 Instances are registered as magic functions to allow use of aliases.
124 125 """
125 126
126 127 # Prepare blacklist
127 128 blacklist = {'cd','popd','pushd','dhist','alias','unalias'}
128 129
129 130 def __init__(self, shell, name, cmd):
130 131 self.shell = shell
131 132 self.name = name
132 133 self.cmd = cmd
133 134 self.nargs = self.validate()
134 135
135 136 def validate(self):
136 137 """Validate the alias, and return the number of arguments."""
137 138 if self.name in self.blacklist:
138 139 raise InvalidAliasError("The name %s can't be aliased "
139 140 "because it is a keyword or builtin." % self.name)
140 141 try:
141 142 caller = self.shell.magics_manager.magics['line'][self.name]
142 143 except KeyError:
143 144 pass
144 145 else:
145 146 if not isinstance(caller, Alias):
146 147 raise InvalidAliasError("The name %s can't be aliased "
147 148 "because it is another magic command." % self.name)
148 149
149 150 if not (isinstance(self.cmd, string_types)):
150 151 raise InvalidAliasError("An alias command must be a string, "
151 152 "got: %r" % self.cmd)
152 153
153 154 nargs = self.cmd.count('%s')
154 155
155 156 if (nargs > 0) and (self.cmd.find('%l') >= 0):
156 157 raise InvalidAliasError('The %s and %l specifiers are mutually '
157 158 'exclusive in alias definitions.')
158 159
159 160 return nargs
160 161
161 162 def __repr__(self):
162 163 return "<alias {} for {!r}>".format(self.name, self.cmd)
163 164
164 165 def __call__(self, rest=''):
165 166 cmd = self.cmd
166 167 nargs = self.nargs
167 168 # Expand the %l special to be the user's input line
168 169 if cmd.find('%l') >= 0:
169 170 cmd = cmd.replace('%l', rest)
170 171 rest = ''
171 172 if nargs==0:
172 173 # Simple, argument-less aliases
173 174 cmd = '%s %s' % (cmd, rest)
174 175 else:
175 176 # Handle aliases with positional arguments
176 177 args = rest.split(None, nargs)
177 178 if len(args) < nargs:
178 179 raise UsageError('Alias <%s> requires %s arguments, %s given.' %
179 180 (self.name, nargs, len(args)))
180 181 cmd = '%s %s' % (cmd % tuple(args[:nargs]),' '.join(args[nargs:]))
181 182
182 183 self.shell.system(cmd)
183 184
184 185 #-----------------------------------------------------------------------------
185 186 # Main AliasManager class
186 187 #-----------------------------------------------------------------------------
187 188
188 189 class AliasManager(Configurable):
189 190
190 191 default_aliases = List(default_aliases(), config=True)
191 192 user_aliases = List(default_value=[], config=True)
192 193 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC')
193 194
194 195 def __init__(self, shell=None, **kwargs):
195 196 super(AliasManager, self).__init__(shell=shell, **kwargs)
196 197 # For convenient access
197 198 self.linemagics = self.shell.magics_manager.magics['line']
198 199 self.init_aliases()
199 200
200 201 def init_aliases(self):
201 202 # Load default & user aliases
202 203 for name, cmd in self.default_aliases + self.user_aliases:
203 204 self.soft_define_alias(name, cmd)
204 205
205 206 @property
206 207 def aliases(self):
207 208 return [(n, func.cmd) for (n, func) in self.linemagics.items()
208 209 if isinstance(func, Alias)]
209 210
210 211 def soft_define_alias(self, name, cmd):
211 212 """Define an alias, but don't raise on an AliasError."""
212 213 try:
213 214 self.define_alias(name, cmd)
214 215 except AliasError as e:
215 216 error("Invalid alias: %s" % e)
216 217
217 218 def define_alias(self, name, cmd):
218 219 """Define a new alias after validating it.
219 220
220 221 This will raise an :exc:`AliasError` if there are validation
221 222 problems.
222 223 """
223 224 caller = Alias(shell=self.shell, name=name, cmd=cmd)
224 225 self.shell.magics_manager.register_function(caller, magic_kind='line',
225 226 magic_name=name)
226 227
227 228 def get_alias(self, name):
228 229 """Return an alias, or None if no alias by that name exists."""
229 230 aname = self.linemagics.get(name, None)
230 231 return aname if isinstance(aname, Alias) else None
231 232
232 233 def is_alias(self, name):
233 234 """Return whether or not a given name has been defined as an alias"""
234 235 return self.get_alias(name) is not None
235 236
236 237 def undefine_alias(self, name):
237 238 if self.is_alias(name):
238 239 del self.linemagics[name]
239 240 else:
240 241 raise ValueError('%s is not an alias' % name)
241 242
242 243 def clear_aliases(self):
243 244 for name, cmd in self.aliases:
244 245 self.undefine_alias(name)
245 246
246 247 def retrieve_alias(self, name):
247 248 """Retrieve the command to which an alias expands."""
248 249 caller = self.get_alias(name)
249 250 if caller:
250 251 return caller.cmd
251 252 else:
252 253 raise ValueError('%s is not an alias' % name)
General Comments 0
You need to be logged in to leave comments. Login now