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