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