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