##// END OF EJS Templates
set ls aliases according to colors configuration
Sha Liu -
Show More
@@ -1,256 +1,258 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 traitlets.config.configurable import Configurable
27 from traitlets.config.configurable import Configurable
28 from IPython.core.error import UsageError
28 from IPython.core.error import UsageError
29
29
30 from traitlets import List, Instance
30 from traitlets import List, Instance
31 from logging import error
31 from logging import error
32
32
33 #-----------------------------------------------------------------------------
33 #-----------------------------------------------------------------------------
34 # Utilities
34 # Utilities
35 #-----------------------------------------------------------------------------
35 #-----------------------------------------------------------------------------
36
36
37 # This is used as the pattern for calls to split_user_input.
37 # This is used as the pattern for calls to split_user_input.
38 shell_line_split = re.compile(r'^(\s*)()(\S+)(.*$)')
38 shell_line_split = re.compile(r'^(\s*)()(\S+)(.*$)')
39
39
40 def default_aliases():
40 def default_aliases():
41 """Return list of shell aliases to auto-define.
41 """Return list of shell aliases to auto-define.
42 """
42 """
43 # Note: the aliases defined here should be safe to use on a kernel
43 # Note: the aliases defined here should be safe to use on a kernel
44 # regardless of what frontend it is attached to. Frontends that use a
44 # regardless of what frontend it is attached to. Frontends that use a
45 # kernel in-process can define additional aliases that will only work in
45 # kernel in-process can define additional aliases that will only work in
46 # their case. For example, things like 'less' or 'clear' that manipulate
46 # their case. For example, things like 'less' or 'clear' that manipulate
47 # the terminal should NOT be declared here, as they will only work if the
47 # the terminal should NOT be declared here, as they will only work if the
48 # kernel is running inside a true terminal, and not over the network.
48 # kernel is running inside a true terminal, and not over the network.
49
49
50 if os.name == 'posix':
50 if os.name == 'posix':
51 default_aliases = [('mkdir', 'mkdir'), ('rmdir', 'rmdir'),
51 default_aliases = [('mkdir', 'mkdir'), ('rmdir', 'rmdir'),
52 ('mv', 'mv'), ('rm', 'rm'), ('cp', 'cp'),
52 ('mv', 'mv'), ('rm', 'rm'), ('cp', 'cp'),
53 ('cat', 'cat'),
53 ('cat', 'cat'),
54 ]
54 ]
55 # Useful set of ls aliases. The GNU and BSD options are a little
55 # Useful set of ls aliases. The GNU and BSD options are a little
56 # different, so we make aliases that provide as similar as possible
56 # different, so we make aliases that provide as similar as possible
57 # behavior in ipython, by passing the right flags for each platform
57 # behavior in ipython, by passing the right flags for each platform
58 if sys.platform.startswith('linux'):
58 if sys.platform.startswith('linux'):
59 ls_aliases = [('ls', 'ls -F --color'),
59 ls_aliases = [('ls', 'ls -F --color'),
60 # long ls
60 # long ls
61 ('ll', 'ls -F -o --color'),
61 ('ll', 'ls -F -o --color'),
62 # ls normal files only
62 # ls normal files only
63 ('lf', 'ls -F -o --color %l | grep ^-'),
63 ('lf', 'ls -F -o --color %l | grep ^-'),
64 # ls symbolic links
64 # ls symbolic links
65 ('lk', 'ls -F -o --color %l | grep ^l'),
65 ('lk', 'ls -F -o --color %l | grep ^l'),
66 # directories or links to directories,
66 # directories or links to directories,
67 ('ldir', 'ls -F -o --color %l | grep /$'),
67 ('ldir', 'ls -F -o --color %l | grep /$'),
68 # things which are executable
68 # things which are executable
69 ('lx', 'ls -F -o --color %l | grep ^-..x'),
69 ('lx', 'ls -F -o --color %l | grep ^-..x'),
70 ]
70 ]
71 elif sys.platform.startswith('openbsd') or sys.platform.startswith('netbsd'):
71 elif sys.platform.startswith('openbsd') or sys.platform.startswith('netbsd'):
72 # OpenBSD, NetBSD. The ls implementation on these platforms do not support
72 # OpenBSD, NetBSD. The ls implementation on these platforms do not support
73 # the -G switch and lack the ability to use colorized output.
73 # the -G switch and lack the ability to use colorized output.
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.__doc__ = "Alias for `!{}`".format(cmd)
133 self.__doc__ = "Alias for `!{}`".format(cmd)
134 self.nargs = self.validate()
134 self.nargs = self.validate()
135
135
136 def validate(self):
136 def validate(self):
137 """Validate the alias, and return the number of arguments."""
137 """Validate the alias, and return the number of arguments."""
138 if self.name in self.blacklist:
138 if self.name in self.blacklist:
139 raise InvalidAliasError("The name %s can't be aliased "
139 raise InvalidAliasError("The name %s can't be aliased "
140 "because it is a keyword or builtin." % self.name)
140 "because it is a keyword or builtin." % self.name)
141 try:
141 try:
142 caller = self.shell.magics_manager.magics['line'][self.name]
142 caller = self.shell.magics_manager.magics['line'][self.name]
143 except KeyError:
143 except KeyError:
144 pass
144 pass
145 else:
145 else:
146 if not isinstance(caller, Alias):
146 if not isinstance(caller, Alias):
147 raise InvalidAliasError("The name %s can't be aliased "
147 raise InvalidAliasError("The name %s can't be aliased "
148 "because it is another magic command." % self.name)
148 "because it is another magic command." % self.name)
149
149
150 if not (isinstance(self.cmd, str)):
150 if not (isinstance(self.cmd, str)):
151 raise InvalidAliasError("An alias command must be a string, "
151 raise InvalidAliasError("An alias command must be a string, "
152 "got: %r" % self.cmd)
152 "got: %r" % self.cmd)
153
153
154 nargs = self.cmd.count('%s') - self.cmd.count('%%s')
154 nargs = self.cmd.count('%s') - self.cmd.count('%%s')
155
155
156 if (nargs > 0) and (self.cmd.find('%l') >= 0):
156 if (nargs > 0) and (self.cmd.find('%l') >= 0):
157 raise InvalidAliasError('The %s and %l specifiers are mutually '
157 raise InvalidAliasError('The %s and %l specifiers are mutually '
158 'exclusive in alias definitions.')
158 'exclusive in alias definitions.')
159
159
160 return nargs
160 return nargs
161
161
162 def __repr__(self):
162 def __repr__(self):
163 return "<alias {} for {!r}>".format(self.name, self.cmd)
163 return "<alias {} for {!r}>".format(self.name, self.cmd)
164
164
165 def __call__(self, rest=''):
165 def __call__(self, rest=''):
166 cmd = self.cmd
166 cmd = self.cmd
167 nargs = self.nargs
167 nargs = self.nargs
168 # Expand the %l special to be the user's input line
168 # Expand the %l special to be the user's input line
169 if cmd.find('%l') >= 0:
169 if cmd.find('%l') >= 0:
170 cmd = cmd.replace('%l', rest)
170 cmd = cmd.replace('%l', rest)
171 rest = ''
171 rest = ''
172
172
173 if nargs==0:
173 if nargs==0:
174 if cmd.find('%%s') >= 1:
174 if cmd.find('%%s') >= 1:
175 cmd = cmd.replace('%%s', '%s')
175 cmd = cmd.replace('%%s', '%s')
176 # Simple, argument-less aliases
176 # Simple, argument-less aliases
177 cmd = '%s %s' % (cmd, rest)
177 cmd = '%s %s' % (cmd, rest)
178 else:
178 else:
179 # Handle aliases with positional arguments
179 # Handle aliases with positional arguments
180 args = rest.split(None, nargs)
180 args = rest.split(None, nargs)
181 if len(args) < nargs:
181 if len(args) < nargs:
182 raise UsageError('Alias <%s> requires %s arguments, %s given.' %
182 raise UsageError('Alias <%s> requires %s arguments, %s given.' %
183 (self.name, nargs, len(args)))
183 (self.name, nargs, len(args)))
184 cmd = '%s %s' % (cmd % tuple(args[:nargs]),' '.join(args[nargs:]))
184 cmd = '%s %s' % (cmd % tuple(args[:nargs]),' '.join(args[nargs:]))
185
185
186 self.shell.system(cmd)
186 self.shell.system(cmd)
187
187
188 #-----------------------------------------------------------------------------
188 #-----------------------------------------------------------------------------
189 # Main AliasManager class
189 # Main AliasManager class
190 #-----------------------------------------------------------------------------
190 #-----------------------------------------------------------------------------
191
191
192 class AliasManager(Configurable):
192 class AliasManager(Configurable):
193
193
194 default_aliases = List(default_aliases()).tag(config=True)
194 default_aliases = List(default_aliases()).tag(config=True)
195 user_aliases = List(default_value=[]).tag(config=True)
195 user_aliases = List(default_value=[]).tag(config=True)
196 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC', allow_none=True)
196 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC', allow_none=True)
197
197
198 def __init__(self, shell=None, **kwargs):
198 def __init__(self, shell=None, **kwargs):
199 super(AliasManager, self).__init__(shell=shell, **kwargs)
199 super(AliasManager, self).__init__(shell=shell, **kwargs)
200 # For convenient access
200 # For convenient access
201 self.linemagics = self.shell.magics_manager.magics['line']
201 self.linemagics = self.shell.magics_manager.magics['line']
202 self.init_aliases()
202 self.init_aliases()
203
203
204 def init_aliases(self):
204 def init_aliases(self):
205 # Load default & user aliases
205 # Load default & user aliases
206 for name, cmd in self.default_aliases + self.user_aliases:
206 for name, cmd in self.default_aliases + self.user_aliases:
207 if cmd.startswith('ls ') and self.shell.colors == 'NoColor':
208 cmd = cmd.replace(' --color', '')
207 self.soft_define_alias(name, cmd)
209 self.soft_define_alias(name, cmd)
208
210
209 @property
211 @property
210 def aliases(self):
212 def aliases(self):
211 return [(n, func.cmd) for (n, func) in self.linemagics.items()
213 return [(n, func.cmd) for (n, func) in self.linemagics.items()
212 if isinstance(func, Alias)]
214 if isinstance(func, Alias)]
213
215
214 def soft_define_alias(self, name, cmd):
216 def soft_define_alias(self, name, cmd):
215 """Define an alias, but don't raise on an AliasError."""
217 """Define an alias, but don't raise on an AliasError."""
216 try:
218 try:
217 self.define_alias(name, cmd)
219 self.define_alias(name, cmd)
218 except AliasError as e:
220 except AliasError as e:
219 error("Invalid alias: %s" % e)
221 error("Invalid alias: %s" % e)
220
222
221 def define_alias(self, name, cmd):
223 def define_alias(self, name, cmd):
222 """Define a new alias after validating it.
224 """Define a new alias after validating it.
223
225
224 This will raise an :exc:`AliasError` if there are validation
226 This will raise an :exc:`AliasError` if there are validation
225 problems.
227 problems.
226 """
228 """
227 caller = Alias(shell=self.shell, name=name, cmd=cmd)
229 caller = Alias(shell=self.shell, name=name, cmd=cmd)
228 self.shell.magics_manager.register_function(caller, magic_kind='line',
230 self.shell.magics_manager.register_function(caller, magic_kind='line',
229 magic_name=name)
231 magic_name=name)
230
232
231 def get_alias(self, name):
233 def get_alias(self, name):
232 """Return an alias, or None if no alias by that name exists."""
234 """Return an alias, or None if no alias by that name exists."""
233 aname = self.linemagics.get(name, None)
235 aname = self.linemagics.get(name, None)
234 return aname if isinstance(aname, Alias) else None
236 return aname if isinstance(aname, Alias) else None
235
237
236 def is_alias(self, name):
238 def is_alias(self, name):
237 """Return whether or not a given name has been defined as an alias"""
239 """Return whether or not a given name has been defined as an alias"""
238 return self.get_alias(name) is not None
240 return self.get_alias(name) is not None
239
241
240 def undefine_alias(self, name):
242 def undefine_alias(self, name):
241 if self.is_alias(name):
243 if self.is_alias(name):
242 del self.linemagics[name]
244 del self.linemagics[name]
243 else:
245 else:
244 raise ValueError('%s is not an alias' % name)
246 raise ValueError('%s is not an alias' % name)
245
247
246 def clear_aliases(self):
248 def clear_aliases(self):
247 for name, cmd in self.aliases:
249 for name, cmd in self.aliases:
248 self.undefine_alias(name)
250 self.undefine_alias(name)
249
251
250 def retrieve_alias(self, name):
252 def retrieve_alias(self, name):
251 """Retrieve the command to which an alias expands."""
253 """Retrieve the command to which an alias expands."""
252 caller = self.get_alias(name)
254 caller = self.get_alias(name)
253 if caller:
255 if caller:
254 return caller.cmd
256 return caller.cmd
255 else:
257 else:
256 raise ValueError('%s is not an alias' % name)
258 raise ValueError('%s is not an alias' % name)
General Comments 0
You need to be logged in to leave comments. Login now