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