Show More
@@ -0,0 +1,191 b'' | |||||
|
1 | #!/usr/bin/env python | |||
|
2 | # encoding: utf-8 | |||
|
3 | """ | |||
|
4 | IPython's alias component | |||
|
5 | ||||
|
6 | Authors: | |||
|
7 | ||||
|
8 | * Brian Granger | |||
|
9 | """ | |||
|
10 | ||||
|
11 | #----------------------------------------------------------------------------- | |||
|
12 | # Copyright (C) 2008-2009 The IPython Development Team | |||
|
13 | # | |||
|
14 | # Distributed under the terms of the BSD License. The full license is in | |||
|
15 | # the file COPYING, distributed as part of this software. | |||
|
16 | #----------------------------------------------------------------------------- | |||
|
17 | ||||
|
18 | #----------------------------------------------------------------------------- | |||
|
19 | # Imports | |||
|
20 | #----------------------------------------------------------------------------- | |||
|
21 | ||||
|
22 | import __builtin__ | |||
|
23 | import keyword | |||
|
24 | import os | |||
|
25 | import sys | |||
|
26 | ||||
|
27 | from IPython.core.component import Component | |||
|
28 | ||||
|
29 | from IPython.utils.traitlets import CBool, List, Instance | |||
|
30 | from IPython.utils.genutils import error | |||
|
31 | ||||
|
32 | #----------------------------------------------------------------------------- | |||
|
33 | # Functions and classes | |||
|
34 | #----------------------------------------------------------------------------- | |||
|
35 | ||||
|
36 | def default_aliases(): | |||
|
37 | # Make some aliases automatically | |||
|
38 | # Prepare list of shell aliases to auto-define | |||
|
39 | if os.name == 'posix': | |||
|
40 | auto_alias = ('mkdir mkdir', 'rmdir rmdir', | |||
|
41 | 'mv mv -i','rm rm -i','cp cp -i', | |||
|
42 | 'cat cat','less less','clear clear', | |||
|
43 | # a better ls | |||
|
44 | 'ls ls -F', | |||
|
45 | # long ls | |||
|
46 | 'll ls -lF') | |||
|
47 | # Extra ls aliases with color, which need special treatment on BSD | |||
|
48 | # variants | |||
|
49 | ls_extra = ( # color ls | |||
|
50 | 'lc ls -F -o --color', | |||
|
51 | # ls normal files only | |||
|
52 | 'lf ls -F -o --color %l | grep ^-', | |||
|
53 | # ls symbolic links | |||
|
54 | 'lk ls -F -o --color %l | grep ^l', | |||
|
55 | # directories or links to directories, | |||
|
56 | 'ldir ls -F -o --color %l | grep /$', | |||
|
57 | # things which are executable | |||
|
58 | 'lx ls -F -o --color %l | grep ^-..x', | |||
|
59 | ) | |||
|
60 | # The BSDs don't ship GNU ls, so they don't understand the | |||
|
61 | # --color switch out of the box | |||
|
62 | if 'bsd' in sys.platform: | |||
|
63 | ls_extra = ( # ls normal files only | |||
|
64 | 'lf ls -lF | grep ^-', | |||
|
65 | # ls symbolic links | |||
|
66 | 'lk ls -lF | grep ^l', | |||
|
67 | # directories or links to directories, | |||
|
68 | 'ldir ls -lF | grep /$', | |||
|
69 | # things which are executable | |||
|
70 | 'lx ls -lF | grep ^-..x', | |||
|
71 | ) | |||
|
72 | auto_alias = auto_alias + ls_extra | |||
|
73 | elif os.name in ['nt','dos']: | |||
|
74 | auto_alias = ('ls dir /on', | |||
|
75 | 'ddir dir /ad /on', 'ldir dir /ad /on', | |||
|
76 | 'mkdir mkdir','rmdir rmdir','echo echo', | |||
|
77 | 'ren ren','cls cls','copy copy') | |||
|
78 | else: | |||
|
79 | auto_alias = () | |||
|
80 | return [s.split(None,1) for s in auto_alias] | |||
|
81 | ||||
|
82 | ||||
|
83 | class AliasError(Exception): | |||
|
84 | pass | |||
|
85 | ||||
|
86 | ||||
|
87 | class InvalidAliasError(AliasError): | |||
|
88 | pass | |||
|
89 | ||||
|
90 | ||||
|
91 | class AliasManager(Component): | |||
|
92 | ||||
|
93 | auto_alias = List(default_aliases()) | |||
|
94 | user_alias = List(default_value=[], config_key='USER_ALIAS') | |||
|
95 | ||||
|
96 | def __init__(self, parent, config=None): | |||
|
97 | super(AliasManager, self).__init__(parent, config=config) | |||
|
98 | self.shell = Component.get_instances( | |||
|
99 | root=self.root, | |||
|
100 | klass='IPython.core.iplib.InteractiveShell' | |||
|
101 | )[0] | |||
|
102 | self.alias_table = {} | |||
|
103 | self.exclude_aliases() | |||
|
104 | self.init_aliases() | |||
|
105 | ||||
|
106 | def __contains__(self, name): | |||
|
107 | if name in self.alias_table: | |||
|
108 | return True | |||
|
109 | else: | |||
|
110 | return False | |||
|
111 | ||||
|
112 | @property | |||
|
113 | def aliases(self): | |||
|
114 | return [(item[0], item[1][1]) for item in self.alias_table.iteritems()] | |||
|
115 | ||||
|
116 | def exclude_aliases(self): | |||
|
117 | # set of things NOT to alias (keywords, builtins and some magics) | |||
|
118 | no_alias = set(['cd','popd','pushd','dhist','alias','unalias']) | |||
|
119 | no_alias.update(set(keyword.kwlist)) | |||
|
120 | no_alias.update(set(__builtin__.__dict__.keys())) | |||
|
121 | self.no_alias = no_alias | |||
|
122 | ||||
|
123 | def init_aliases(self): | |||
|
124 | # Load default aliases | |||
|
125 | for name, cmd in self.auto_alias: | |||
|
126 | self.soft_define_alias(name, cmd) | |||
|
127 | ||||
|
128 | # Load user aliases | |||
|
129 | for name, cmd in self.user_alias: | |||
|
130 | self.soft_define_alias(name, cmd) | |||
|
131 | ||||
|
132 | def soft_define_alias(self, name, cmd): | |||
|
133 | """Define an alias, but don't raise on an AliasError.""" | |||
|
134 | try: | |||
|
135 | self.define_alias(name, cmd) | |||
|
136 | except AliasError, e: | |||
|
137 | error("Invalid alias: %s" % e) | |||
|
138 | ||||
|
139 | def define_alias(self, name, cmd): | |||
|
140 | """Define a new alias after validating it. | |||
|
141 | ||||
|
142 | This will raise an :exc:`AliasError` if there are validation | |||
|
143 | problems. | |||
|
144 | """ | |||
|
145 | nargs = self.validate_alias(name, cmd) | |||
|
146 | self.alias_table[name] = (nargs, cmd) | |||
|
147 | ||||
|
148 | def validate_alias(self, name, cmd): | |||
|
149 | """Validate an alias and return the its number of arguments.""" | |||
|
150 | if name in self.no_alias: | |||
|
151 | raise InvalidAliasError("The name %s can't be aliased " | |||
|
152 | "because it is a keyword or builtin." % name) | |||
|
153 | if not (isinstance(cmd, basestring)): | |||
|
154 | raise InvalidAliasError("An alias command must be a string, " | |||
|
155 | "got: %r" % name) | |||
|
156 | nargs = cmd.count('%s') | |||
|
157 | if nargs>0 and cmd.find('%l')>=0: | |||
|
158 | raise InvalidAliasError('The %s and %l specifiers are mutually ' | |||
|
159 | 'exclusive in alias definitions.') | |||
|
160 | return nargs | |||
|
161 | ||||
|
162 | def call_alias(self, alias, rest=''): | |||
|
163 | """Call an alias given its name and the rest of the line.""" | |||
|
164 | cmd = self.transform_alias(alias, rest) | |||
|
165 | try: | |||
|
166 | self.shell.system(cmd) | |||
|
167 | except: | |||
|
168 | self.shell.showtraceback() | |||
|
169 | ||||
|
170 | def transform_alias(self, alias,rest=''): | |||
|
171 | """Transform alias to system command string.""" | |||
|
172 | nargs, cmd = self.alias_table[alias] | |||
|
173 | ||||
|
174 | if ' ' in cmd and os.path.isfile(cmd): | |||
|
175 | cmd = '"%s"' % cmd | |||
|
176 | ||||
|
177 | # Expand the %l special to be the user's input line | |||
|
178 | if cmd.find('%l') >= 0: | |||
|
179 | cmd = cmd.replace('%l', rest) | |||
|
180 | rest = '' | |||
|
181 | if nargs==0: | |||
|
182 | # Simple, argument-less aliases | |||
|
183 | cmd = '%s %s' % (cmd, rest) | |||
|
184 | else: | |||
|
185 | # Handle aliases with positional arguments | |||
|
186 | args = rest.split(None, nargs) | |||
|
187 | if len(args) < nargs: | |||
|
188 | raise AliasError('Alias <%s> requires %s arguments, %s given.' % | |||
|
189 | (alias, nargs, len(args))) | |||
|
190 | cmd = '%s %s' % (cmd % tuple(args[:nargs]),' '.join(args[nargs:])) | |||
|
191 | return cmd |
@@ -228,6 +228,7 b' class Application(object):' | |||||
228 | self.print_traceback() |
|
228 | self.print_traceback() | |
229 | self.abort() |
|
229 | self.abort() | |
230 | elif action == 'exit': |
|
230 | elif action == 'exit': | |
|
231 | self.print_traceback() | |||
231 | self.exit() |
|
232 | self.exit() | |
232 |
|
233 | |||
233 | def print_traceback(self): |
|
234 | def print_traceback(self): |
@@ -36,13 +36,14 b' BuiltinUndefined = BuiltinUndefined()' | |||||
36 |
|
36 | |||
37 |
|
37 | |||
38 | class BuiltinTrap(Component): |
|
38 | class BuiltinTrap(Component): | |
39 | shell = Instance('IPython.core.iplib.InteractiveShell') |
|
|||
40 |
|
39 | |||
41 | def __init__(self, parent): |
|
40 | def __init__(self, parent): | |
42 | super(BuiltinTrap, self).__init__(parent, None, None) |
|
41 | super(BuiltinTrap, self).__init__(parent, None, None) | |
43 | # Don't just grab parent!!! |
|
42 | # Don't just grab parent!!! | |
44 |
self.shell = Component.get_instances( |
|
43 | self.shell = Component.get_instances( | |
45 | klass='IPython.core.iplib.InteractiveShell')[0] |
|
44 | root=self.root, | |
|
45 | klass='IPython.core.iplib.InteractiveShell' | |||
|
46 | )[0] | |||
46 | self._orig_builtins = {} |
|
47 | self._orig_builtins = {} | |
47 |
|
48 | |||
48 | def __enter__(self): |
|
49 | def __enter__(self): |
@@ -48,22 +48,55 b' class MetaComponentTracker(type):' | |||||
48 | cls.__numcreated = 0 |
|
48 | cls.__numcreated = 0 | |
49 |
|
49 | |||
50 | def __call__(cls, *args, **kw): |
|
50 | def __call__(cls, *args, **kw): | |
51 |
"""Called when |
|
51 | """Called when a class is called (instantiated)!!! | |
52 |
|
52 | |||
53 | When a Component or subclass is instantiated, this is called and |
|
53 | When a Component or subclass is instantiated, this is called and | |
54 | the instance is saved in a WeakValueDictionary for tracking. |
|
54 | the instance is saved in a WeakValueDictionary for tracking. | |
55 | """ |
|
55 | """ | |
56 | instance = cls.__new__(cls, *args, **kw) |
|
56 | instance = cls.__new__(cls, *args, **kw) | |
57 | # Do this before __init__ is called so get_instances works inside |
|
57 | ||
58 | # __init__ methods! |
|
58 | # Register the instance before __init__ is called so get_instances | |
|
59 | # works inside __init__ methods! | |||
|
60 | indices = cls.register_instance(instance) | |||
|
61 | ||||
|
62 | # This is in a try/except because of the __init__ method fails, the | |||
|
63 | # instance is discarded and shouldn't be tracked. | |||
|
64 | try: | |||
|
65 | if isinstance(instance, cls): | |||
|
66 | cls.__init__(instance, *args, **kw) | |||
|
67 | except: | |||
|
68 | # Unregister the instance because __init__ failed! | |||
|
69 | cls.unregister_instances(indices) | |||
|
70 | raise | |||
|
71 | else: | |||
|
72 | return instance | |||
|
73 | ||||
|
74 | def register_instance(cls, instance): | |||
|
75 | """Register instance with cls and its subclasses.""" | |||
|
76 | # indices is a list of the keys used to register the instance | |||
|
77 | # with. This list is needed if the instance needs to be unregistered. | |||
|
78 | indices = [] | |||
59 | for c in cls.__mro__: |
|
79 | for c in cls.__mro__: | |
60 | if issubclass(cls, c) and issubclass(c, Component): |
|
80 | if issubclass(cls, c) and issubclass(c, Component): | |
61 | c.__numcreated += 1 |
|
81 | c.__numcreated += 1 | |
|
82 | indices.append(c.__numcreated) | |||
62 | c.__instance_refs[c.__numcreated] = instance |
|
83 | c.__instance_refs[c.__numcreated] = instance | |
63 | if isinstance(instance, cls): |
|
84 | else: | |
64 | cls.__init__(instance, *args, **kw) |
|
85 | break | |
|
86 | return indices | |||
|
87 | ||||
|
88 | def unregister_instances(cls, indices): | |||
|
89 | """Unregister instance with cls and its subclasses.""" | |||
|
90 | for c, index in zip(cls.__mro__, indices): | |||
|
91 | try: | |||
|
92 | del c.__instance_refs[index] | |||
|
93 | except KeyError: | |||
|
94 | pass | |||
65 |
|
95 | |||
66 | return instance |
|
96 | def clear_instances(cls): | |
|
97 | """Clear all instances tracked by cls.""" | |||
|
98 | cls.__instance_refs.clear() | |||
|
99 | cls.__numcreated = 0 | |||
67 |
|
100 | |||
68 | def get_instances(cls, name=None, root=None, klass=None): |
|
101 | def get_instances(cls, name=None, root=None, klass=None): | |
69 | """Get all instances of cls and its subclasses. |
|
102 | """Get all instances of cls and its subclasses. | |
@@ -82,6 +115,9 b' class MetaComponentTracker(type):' | |||||
82 | if klass is not None: |
|
115 | if klass is not None: | |
83 | if isinstance(klass, basestring): |
|
116 | if isinstance(klass, basestring): | |
84 | klass = import_item(klass) |
|
117 | klass = import_item(klass) | |
|
118 | # Limit search to instances of klass for performance | |||
|
119 | if issubclass(klass, Component): | |||
|
120 | return klass.get_instances(name=name, root=root) | |||
85 | instances = cls.__instance_refs.values() |
|
121 | instances = cls.__instance_refs.values() | |
86 | if name is not None: |
|
122 | if name is not None: | |
87 | instances = [i for i in instances if i.name == name] |
|
123 | instances = [i for i in instances if i.name == name] | |
@@ -101,6 +137,26 b' class MetaComponentTracker(type):' | |||||
101 | return [i for i in cls.get_instances(name, root, klass) if call(i)] |
|
137 | return [i for i in cls.get_instances(name, root, klass) if call(i)] | |
102 |
|
138 | |||
103 |
|
139 | |||
|
140 | def masquerade_as(instance, cls): | |||
|
141 | """Let instance masquerade as an instance of cls. | |||
|
142 | ||||
|
143 | Sometimes, such as in testing code, it is useful to let a class | |||
|
144 | masquerade as another. Python, being duck typed, allows this by | |||
|
145 | default. But, instances of components are tracked by their class type. | |||
|
146 | ||||
|
147 | After calling this, cls.get_instances() will return ``instance``. This | |||
|
148 | does not, however, cause isinstance(instance, cls) to return ``True``. | |||
|
149 | ||||
|
150 | Parameters | |||
|
151 | ---------- | |||
|
152 | instance : an instance of a Component or Component subclass | |||
|
153 | The instance that will pretend to be a cls. | |||
|
154 | cls : subclass of Component | |||
|
155 | The Component subclass that instance will pretend to be. | |||
|
156 | """ | |||
|
157 | cls.register_instance(instance) | |||
|
158 | ||||
|
159 | ||||
104 | class ComponentNameGenerator(object): |
|
160 | class ComponentNameGenerator(object): | |
105 | """A Singleton to generate unique component names.""" |
|
161 | """A Singleton to generate unique component names.""" | |
106 |
|
162 | |||
@@ -245,4 +301,5 b' class Component(HasTraitlets):' | |||||
245 | self._children.append(child) |
|
301 | self._children.append(child) | |
246 |
|
302 | |||
247 | def __repr__(self): |
|
303 | def __repr__(self): | |
248 |
return "< |
|
304 | return "<%s('%s')>" % (self.__class__.__name__, "DummyName") | |
|
305 | # return "<Component('%s')>" % self.name |
@@ -307,7 +307,8 b' class IPythonApp(Application):' | |||||
307 | parent=None, |
|
307 | parent=None, | |
308 | config=self.master_config |
|
308 | config=self.master_config | |
309 | ) |
|
309 | ) | |
310 |
|
310 | print self.shell | ||
|
311 | ||||
311 | def start_app(self): |
|
312 | def start_app(self): | |
312 | self.shell.mainloop() |
|
313 | self.shell.mainloop() | |
313 |
|
314 |
@@ -40,6 +40,7 b' from IPython.core import debugger, oinspect' | |||||
40 | from IPython.core import shadowns |
|
40 | from IPython.core import shadowns | |
41 | from IPython.core import history as ipcorehist |
|
41 | from IPython.core import history as ipcorehist | |
42 | from IPython.core import prefilter |
|
42 | from IPython.core import prefilter | |
|
43 | from IPython.core.alias import AliasManager | |||
43 | from IPython.core.autocall import IPyAutocall |
|
44 | from IPython.core.autocall import IPyAutocall | |
44 | from IPython.core.builtin_trap import BuiltinTrap |
|
45 | from IPython.core.builtin_trap import BuiltinTrap | |
45 | from IPython.core.display_trap import DisplayTrap |
|
46 | from IPython.core.display_trap import DisplayTrap | |
@@ -62,6 +63,9 b' from IPython.utils.genutils import *' | |||||
62 | from IPython.utils.strdispatch import StrDispatch |
|
63 | from IPython.utils.strdispatch import StrDispatch | |
63 | from IPython.utils.platutils import toggle_set_term_title, set_term_title |
|
64 | from IPython.utils.platutils import toggle_set_term_title, set_term_title | |
64 |
|
65 | |||
|
66 | from IPython.utils import growl | |||
|
67 | growl.start("IPython") | |||
|
68 | ||||
65 | from IPython.utils.traitlets import ( |
|
69 | from IPython.utils.traitlets import ( | |
66 | Int, Float, Str, CBool, CaselessStrEnum, Enum, List, Unicode |
|
70 | Int, Float, Str, CBool, CaselessStrEnum, Enum, List, Unicode | |
67 | ) |
|
71 | ) | |
@@ -303,7 +307,7 b' class InteractiveShell(Component, Magic):' | |||||
303 | self.init_traceback_handlers(custom_exceptions) |
|
307 | self.init_traceback_handlers(custom_exceptions) | |
304 | self.init_user_ns() |
|
308 | self.init_user_ns() | |
305 | self.init_logger() |
|
309 | self.init_logger() | |
306 |
self.init_alias |
|
310 | self.init_alias() | |
307 | self.init_builtins() |
|
311 | self.init_builtins() | |
308 |
|
312 | |||
309 | # pre_config_initialization |
|
313 | # pre_config_initialization | |
@@ -1660,129 +1664,8 b' class InteractiveShell(Component, Magic):' | |||||
1660 | # Things related to aliases |
|
1664 | # Things related to aliases | |
1661 | #------------------------------------------------------------------------- |
|
1665 | #------------------------------------------------------------------------- | |
1662 |
|
1666 | |||
1663 |
def init_alias |
|
1667 | def init_alias(self): | |
1664 | # dict of things NOT to alias (keywords, builtins and some magics) |
|
1668 | self.alias_manager = AliasManager(self, config=self.config) | |
1665 | no_alias = {} |
|
|||
1666 | no_alias_magics = ['cd','popd','pushd','dhist','alias','unalias'] |
|
|||
1667 | for key in keyword.kwlist + no_alias_magics: |
|
|||
1668 | no_alias[key] = 1 |
|
|||
1669 | no_alias.update(__builtin__.__dict__) |
|
|||
1670 | self.no_alias = no_alias |
|
|||
1671 |
|
||||
1672 | # Make some aliases automatically |
|
|||
1673 | # Prepare list of shell aliases to auto-define |
|
|||
1674 | if os.name == 'posix': |
|
|||
1675 | auto_alias = ('mkdir mkdir', 'rmdir rmdir', |
|
|||
1676 | 'mv mv -i','rm rm -i','cp cp -i', |
|
|||
1677 | 'cat cat','less less','clear clear', |
|
|||
1678 | # a better ls |
|
|||
1679 | 'ls ls -F', |
|
|||
1680 | # long ls |
|
|||
1681 | 'll ls -lF') |
|
|||
1682 | # Extra ls aliases with color, which need special treatment on BSD |
|
|||
1683 | # variants |
|
|||
1684 | ls_extra = ( # color ls |
|
|||
1685 | 'lc ls -F -o --color', |
|
|||
1686 | # ls normal files only |
|
|||
1687 | 'lf ls -F -o --color %l | grep ^-', |
|
|||
1688 | # ls symbolic links |
|
|||
1689 | 'lk ls -F -o --color %l | grep ^l', |
|
|||
1690 | # directories or links to directories, |
|
|||
1691 | 'ldir ls -F -o --color %l | grep /$', |
|
|||
1692 | # things which are executable |
|
|||
1693 | 'lx ls -F -o --color %l | grep ^-..x', |
|
|||
1694 | ) |
|
|||
1695 | # The BSDs don't ship GNU ls, so they don't understand the |
|
|||
1696 | # --color switch out of the box |
|
|||
1697 | if 'bsd' in sys.platform: |
|
|||
1698 | ls_extra = ( # ls normal files only |
|
|||
1699 | 'lf ls -lF | grep ^-', |
|
|||
1700 | # ls symbolic links |
|
|||
1701 | 'lk ls -lF | grep ^l', |
|
|||
1702 | # directories or links to directories, |
|
|||
1703 | 'ldir ls -lF | grep /$', |
|
|||
1704 | # things which are executable |
|
|||
1705 | 'lx ls -lF | grep ^-..x', |
|
|||
1706 | ) |
|
|||
1707 | auto_alias = auto_alias + ls_extra |
|
|||
1708 | elif os.name in ['nt','dos']: |
|
|||
1709 | auto_alias = ('ls dir /on', |
|
|||
1710 | 'ddir dir /ad /on', 'ldir dir /ad /on', |
|
|||
1711 | 'mkdir mkdir','rmdir rmdir','echo echo', |
|
|||
1712 | 'ren ren','cls cls','copy copy') |
|
|||
1713 | else: |
|
|||
1714 | auto_alias = () |
|
|||
1715 | self.auto_alias = [s.split(None,1) for s in auto_alias] |
|
|||
1716 |
|
||||
1717 | # Load default aliases |
|
|||
1718 | for alias, cmd in self.auto_alias: |
|
|||
1719 | self.define_alias(alias,cmd) |
|
|||
1720 |
|
||||
1721 | # Load user aliases |
|
|||
1722 | for alias in self.alias: |
|
|||
1723 | self.magic_alias(alias) |
|
|||
1724 |
|
||||
1725 | def call_alias(self,alias,rest=''): |
|
|||
1726 | """Call an alias given its name and the rest of the line. |
|
|||
1727 |
|
||||
1728 | This is only used to provide backwards compatibility for users of |
|
|||
1729 | ipalias(), use of which is not recommended for anymore.""" |
|
|||
1730 |
|
||||
1731 | # Now call the macro, evaluating in the user's namespace |
|
|||
1732 | cmd = self.transform_alias(alias, rest) |
|
|||
1733 | try: |
|
|||
1734 | self.system(cmd) |
|
|||
1735 | except: |
|
|||
1736 | self.showtraceback() |
|
|||
1737 |
|
||||
1738 | def define_alias(self, name, cmd): |
|
|||
1739 | """ Define a new alias.""" |
|
|||
1740 |
|
||||
1741 | if callable(cmd): |
|
|||
1742 | self.alias_table[name] = cmd |
|
|||
1743 | from IPython.core import shadowns |
|
|||
1744 | setattr(shadowns, name, cmd) |
|
|||
1745 | return |
|
|||
1746 |
|
||||
1747 | if isinstance(cmd, basestring): |
|
|||
1748 | nargs = cmd.count('%s') |
|
|||
1749 | if nargs>0 and cmd.find('%l')>=0: |
|
|||
1750 | raise Exception('The %s and %l specifiers are mutually ' |
|
|||
1751 | 'exclusive in alias definitions.') |
|
|||
1752 |
|
||||
1753 | self.alias_table[name] = (nargs,cmd) |
|
|||
1754 | return |
|
|||
1755 |
|
||||
1756 | self.alias_table[name] = cmd |
|
|||
1757 |
|
||||
1758 | def ipalias(self,arg_s): |
|
|||
1759 | """Call an alias by name. |
|
|||
1760 |
|
||||
1761 | Input: a string containing the name of the alias to call and any |
|
|||
1762 | additional arguments to be passed to the magic. |
|
|||
1763 |
|
||||
1764 | ipalias('name -opt foo bar') is equivalent to typing at the ipython |
|
|||
1765 | prompt: |
|
|||
1766 |
|
||||
1767 | In[1]: name -opt foo bar |
|
|||
1768 |
|
||||
1769 | To call an alias without arguments, simply use ipalias('name'). |
|
|||
1770 |
|
||||
1771 | This provides a proper Python function to call IPython's aliases in any |
|
|||
1772 | valid Python code you can type at the interpreter, including loops and |
|
|||
1773 | compound statements. It is added by IPython to the Python builtin |
|
|||
1774 | namespace upon initialization.""" |
|
|||
1775 |
|
||||
1776 | args = arg_s.split(' ',1) |
|
|||
1777 | alias_name = args[0] |
|
|||
1778 | try: |
|
|||
1779 | alias_args = args[1] |
|
|||
1780 | except IndexError: |
|
|||
1781 | alias_args = '' |
|
|||
1782 | if alias_name in self.alias_table: |
|
|||
1783 | self.call_alias(alias_name,alias_args) |
|
|||
1784 | else: |
|
|||
1785 | error("Alias `%s` not found." % alias_name) |
|
|||
1786 |
|
1669 | |||
1787 | def expand_alias(self, line): |
|
1670 | def expand_alias(self, line): | |
1788 | """ Expand an alias in the command line |
|
1671 | """ Expand an alias in the command line | |
@@ -1817,81 +1700,25 b' class InteractiveShell(Component, Magic):' | |||||
1817 | while 1: |
|
1700 | while 1: | |
1818 | pre,fn,rest = prefilter.splitUserInput(line, |
|
1701 | pre,fn,rest = prefilter.splitUserInput(line, | |
1819 | prefilter.shell_line_split) |
|
1702 | prefilter.shell_line_split) | |
1820 | if fn in self.alias_table: |
|
1703 | if fn in self.alias_manager.alias_table: | |
1821 | if fn in done: |
|
1704 | if fn in done: | |
1822 | warn("Cyclic alias definition, repeated '%s'" % fn) |
|
1705 | warn("Cyclic alias definition, repeated '%s'" % fn) | |
1823 | return "" |
|
1706 | return "" | |
1824 | done.add(fn) |
|
1707 | done.add(fn) | |
1825 |
|
1708 | |||
1826 | l2 = self.transform_alias(fn,rest) |
|
1709 | l2 = self.alias_manager.transform_alias(fn, rest) | |
1827 | # dir -> dir |
|
|||
1828 | # print "alias",line, "->",l2 #dbg |
|
|||
1829 | if l2 == line: |
|
1710 | if l2 == line: | |
1830 | break |
|
1711 | break | |
1831 | # ls -> ls -F should not recurse forever |
|
1712 | # ls -> ls -F should not recurse forever | |
1832 | if l2.split(None,1)[0] == line.split(None,1)[0]: |
|
1713 | if l2.split(None,1)[0] == line.split(None,1)[0]: | |
1833 | line = l2 |
|
1714 | line = l2 | |
1834 | break |
|
1715 | break | |
1835 |
|
||||
1836 | line=l2 |
|
1716 | line=l2 | |
1837 |
|
||||
1838 |
|
||||
1839 | # print "al expand to",line #dbg |
|
|||
1840 | else: |
|
1717 | else: | |
1841 | break |
|
1718 | break | |
1842 |
|
1719 | |||
1843 | return line |
|
1720 | return line | |
1844 |
|
1721 | |||
1845 | def transform_alias(self, alias,rest=''): |
|
|||
1846 | """ Transform alias to system command string. |
|
|||
1847 | """ |
|
|||
1848 | trg = self.alias_table[alias] |
|
|||
1849 |
|
||||
1850 | nargs,cmd = trg |
|
|||
1851 | # print trg #dbg |
|
|||
1852 | if ' ' in cmd and os.path.isfile(cmd): |
|
|||
1853 | cmd = '"%s"' % cmd |
|
|||
1854 |
|
||||
1855 | # Expand the %l special to be the user's input line |
|
|||
1856 | if cmd.find('%l') >= 0: |
|
|||
1857 | cmd = cmd.replace('%l',rest) |
|
|||
1858 | rest = '' |
|
|||
1859 | if nargs==0: |
|
|||
1860 | # Simple, argument-less aliases |
|
|||
1861 | cmd = '%s %s' % (cmd,rest) |
|
|||
1862 | else: |
|
|||
1863 | # Handle aliases with positional arguments |
|
|||
1864 | args = rest.split(None,nargs) |
|
|||
1865 | if len(args)< nargs: |
|
|||
1866 | error('Alias <%s> requires %s arguments, %s given.' % |
|
|||
1867 | (alias,nargs,len(args))) |
|
|||
1868 | return None |
|
|||
1869 | cmd = '%s %s' % (cmd % tuple(args[:nargs]),' '.join(args[nargs:])) |
|
|||
1870 | # Now call the macro, evaluating in the user's namespace |
|
|||
1871 | #print 'new command: <%r>' % cmd # dbg |
|
|||
1872 | return cmd |
|
|||
1873 |
|
||||
1874 | def init_auto_alias(self): |
|
|||
1875 | """Define some aliases automatically. |
|
|||
1876 |
|
||||
1877 | These are ALL parameter-less aliases""" |
|
|||
1878 |
|
||||
1879 | for alias,cmd in self.auto_alias: |
|
|||
1880 | self.define_alias(alias,cmd) |
|
|||
1881 |
|
||||
1882 | def alias_table_validate(self,verbose=0): |
|
|||
1883 | """Update information about the alias table. |
|
|||
1884 |
|
||||
1885 | In particular, make sure no Python keywords/builtins are in it.""" |
|
|||
1886 |
|
||||
1887 | no_alias = self.no_alias |
|
|||
1888 | for k in self.alias_table.keys(): |
|
|||
1889 | if k in no_alias: |
|
|||
1890 | del self.alias_table[k] |
|
|||
1891 | if verbose: |
|
|||
1892 | print ("Deleting alias <%s>, it's a Python " |
|
|||
1893 | "keyword or builtin." % k) |
|
|||
1894 |
|
||||
1895 | #------------------------------------------------------------------------- |
|
1722 | #------------------------------------------------------------------------- | |
1896 | # Things related to the running of code |
|
1723 | # Things related to the running of code | |
1897 | #------------------------------------------------------------------------- |
|
1724 | #------------------------------------------------------------------------- | |
@@ -2513,9 +2340,10 b' class InteractiveShell(Component, Magic):' | |||||
2513 | - continue_prompt(False): whether this line is the first one or a |
|
2340 | - continue_prompt(False): whether this line is the first one or a | |
2514 | continuation in a sequence of inputs. |
|
2341 | continuation in a sequence of inputs. | |
2515 | """ |
|
2342 | """ | |
2516 |
|
2343 | growl.notify("raw_input: ", "prompt = %r\ncontinue_prompt = %s" % (prompt, continue_prompt)) | ||
2517 | # Code run by the user may have modified the readline completer state. |
|
2344 | # Code run by the user may have modified the readline completer state. | |
2518 | # We must ensure that our completer is back in place. |
|
2345 | # We must ensure that our completer is back in place. | |
|
2346 | ||||
2519 | if self.has_readline: |
|
2347 | if self.has_readline: | |
2520 | self.set_completer() |
|
2348 | self.set_completer() | |
2521 |
|
2349 | |||
@@ -2659,6 +2487,8 b' class InteractiveShell(Component, Magic):' | |||||
2659 |
|
2487 | |||
2660 | # save the line away in case we crash, so the post-mortem handler can |
|
2488 | # save the line away in case we crash, so the post-mortem handler can | |
2661 | # record it |
|
2489 | # record it | |
|
2490 | growl.notify("_prefilter: ", "line = %s\ncontinue_prompt = %s" % (line, continue_prompt)) | |||
|
2491 | ||||
2662 | self._last_input_line = line |
|
2492 | self._last_input_line = line | |
2663 |
|
2493 | |||
2664 | #print '***line: <%s>' % line # dbg |
|
2494 | #print '***line: <%s>' % line # dbg | |
@@ -2715,15 +2545,17 b' class InteractiveShell(Component, Magic):' | |||||
2715 | entry and presses enter. |
|
2545 | entry and presses enter. | |
2716 |
|
2546 | |||
2717 | """ |
|
2547 | """ | |
|
2548 | growl.notify("multiline_prefilter: ", "%s\n%s" % (line, continue_prompt)) | |||
2718 | out = [] |
|
2549 | out = [] | |
2719 | for l in line.rstrip('\n').split('\n'): |
|
2550 | for l in line.rstrip('\n').split('\n'): | |
2720 | out.append(self._prefilter(l, continue_prompt)) |
|
2551 | out.append(self._prefilter(l, continue_prompt)) | |
|
2552 | growl.notify("multiline_prefilter return: ", '\n'.join(out)) | |||
2721 | return '\n'.join(out) |
|
2553 | return '\n'.join(out) | |
2722 |
|
2554 | |||
2723 | # Set the default prefilter() function (this can be user-overridden) |
|
2555 | # Set the default prefilter() function (this can be user-overridden) | |
2724 | prefilter = multiline_prefilter |
|
2556 | prefilter = multiline_prefilter | |
2725 |
|
2557 | |||
2726 | def handle_normal(self,line_info): |
|
2558 | def handle_normal(self, line_info): | |
2727 | """Handle normal input lines. Use as a template for handlers.""" |
|
2559 | """Handle normal input lines. Use as a template for handlers.""" | |
2728 |
|
2560 | |||
2729 | # With autoindent on, we need some way to exit the input loop, and I |
|
2561 | # With autoindent on, we need some way to exit the input loop, and I | |
@@ -2742,10 +2574,9 b' class InteractiveShell(Component, Magic):' | |||||
2742 | self.log(line,line,continue_prompt) |
|
2574 | self.log(line,line,continue_prompt) | |
2743 | return line |
|
2575 | return line | |
2744 |
|
2576 | |||
2745 | def handle_alias(self,line_info): |
|
2577 | def handle_alias(self, line_info): | |
2746 | """Handle alias input lines. """ |
|
2578 | """Handle alias input lines. """ | |
2747 | tgt = self.alias_table[line_info.iFun] |
|
2579 | tgt = self.alias_manager.alias_table[line_info.iFun] | |
2748 | # print "=>",tgt #dbg |
|
|||
2749 | if callable(tgt): |
|
2580 | if callable(tgt): | |
2750 | if '$' in line_info.line: |
|
2581 | if '$' in line_info.line: | |
2751 | call_meth = '(_ip, _ip.var_expand(%s))' |
|
2582 | call_meth = '(_ip, _ip.var_expand(%s))' |
@@ -251,8 +251,8 b' def checkAlias(l_info,ip):' | |||||
251 | # Note: aliases can not contain '.' |
|
251 | # Note: aliases can not contain '.' | |
252 | head = l_info.iFun.split('.',1)[0] |
|
252 | head = l_info.iFun.split('.',1)[0] | |
253 |
|
253 | |||
254 |
if l_info.iFun not in ip.alias_ |
|
254 | if l_info.iFun not in ip.alias_manager \ | |
255 |
or head not in ip.alias_ |
|
255 | or head not in ip.alias_manager \ | |
256 | or isShadowed(head,ip): |
|
256 | or isShadowed(head,ip): | |
257 | return None |
|
257 | return None | |
258 |
|
258 |
@@ -18,7 +18,7 b' class Notifier(object):' | |||||
18 |
|
18 | |||
19 | def _notify(self, title, msg): |
|
19 | def _notify(self, title, msg): | |
20 | if self.g_notifier is not None: |
|
20 | if self.g_notifier is not None: | |
21 |
self.g_notifier.notify(' |
|
21 | self.g_notifier.notify('core', title, msg) | |
22 |
|
22 | |||
23 | def notify(self, title, msg): |
|
23 | def notify(self, title, msg): | |
24 | self._notify(title, msg) |
|
24 | self._notify(title, msg) |
General Comments 0
You need to be logged in to leave comments.
Login now