##// END OF EJS Templates
check for both $LA and LA() in history crawling
Ville M. Vainio -
Show More
@@ -1,246 +1,246 b''
1 """Shell mode for IPython.
1 """Shell mode for IPython.
2
2
3 Start ipython in shell mode by invoking "ipython -p sh"
3 Start ipython in shell mode by invoking "ipython -p sh"
4
4
5 (the old version, "ipython -p pysh" still works but this is the more "modern"
5 (the old version, "ipython -p pysh" still works but this is the more "modern"
6 shell mode and is recommended for users who don't care about pysh-mode
6 shell mode and is recommended for users who don't care about pysh-mode
7 compatibility)
7 compatibility)
8 """
8 """
9
9
10 from IPython import ipapi
10 from IPython import ipapi
11 import os,textwrap
11 import os,textwrap
12
12
13 # The import below effectively obsoletes your old-style ipythonrc[.ini],
13 # The import below effectively obsoletes your old-style ipythonrc[.ini],
14 # so consider yourself warned!
14 # so consider yourself warned!
15
15
16 import ipy_defaults
16 import ipy_defaults
17
17
18 def main():
18 def main():
19 ip = ipapi.get()
19 ip = ipapi.get()
20 o = ip.options
20 o = ip.options
21 # autocall to "full" mode (smart mode is default, I like full mode)
21 # autocall to "full" mode (smart mode is default, I like full mode)
22
22
23 o.autocall = 2
23 o.autocall = 2
24
24
25 # Jason Orendorff's path class is handy to have in user namespace
25 # Jason Orendorff's path class is handy to have in user namespace
26 # if you are doing shell-like stuff
26 # if you are doing shell-like stuff
27 try:
27 try:
28 ip.ex("from IPython.external.path import path" )
28 ip.ex("from IPython.external.path import path" )
29 except ImportError:
29 except ImportError:
30 pass
30 pass
31
31
32 # beefed up %env is handy in shell mode
32 # beefed up %env is handy in shell mode
33 import envpersist
33 import envpersist
34
34
35 # To see where mycmd resides (in path/aliases), do %which mycmd
35 # To see where mycmd resides (in path/aliases), do %which mycmd
36 import ipy_which
36 import ipy_which
37
37
38 # tab completers for hg, svn, ...
38 # tab completers for hg, svn, ...
39 import ipy_app_completers
39 import ipy_app_completers
40
40
41 # To make executables foo and bar in mybin usable without PATH change, do:
41 # To make executables foo and bar in mybin usable without PATH change, do:
42 # %rehashdir c:/mybin
42 # %rehashdir c:/mybin
43 # %store foo
43 # %store foo
44 # %store bar
44 # %store bar
45 import ipy_rehashdir
45 import ipy_rehashdir
46 import ipy_signals
46 import ipy_signals
47
47
48 ip.ex('import os')
48 ip.ex('import os')
49 ip.ex("def up(): os.chdir('..')")
49 ip.ex("def up(): os.chdir('..')")
50 ip.user_ns['LA'] = LastArgFinder()
50 ip.user_ns['LA'] = LastArgFinder()
51 # Nice prompt
51 # Nice prompt
52
52
53 o.prompt_in1= r'\C_LightBlue[\C_LightCyan\Y2\C_LightBlue]\C_Green|\#> '
53 o.prompt_in1= r'\C_LightBlue[\C_LightCyan\Y2\C_LightBlue]\C_Green|\#> '
54 o.prompt_in2= r'\C_Green|\C_LightGreen\D\C_Green> '
54 o.prompt_in2= r'\C_Green|\C_LightGreen\D\C_Green> '
55 o.prompt_out= '<\#> '
55 o.prompt_out= '<\#> '
56
56
57 from IPython import Release
57 from IPython import Release
58
58
59 import sys
59 import sys
60 # Non-chatty banner
60 # Non-chatty banner
61 o.banner = "IPython %s [on Py %s]\n" % (Release.version,sys.version.split(None,1)[0])
61 o.banner = "IPython %s [on Py %s]\n" % (Release.version,sys.version.split(None,1)[0])
62
62
63
63
64 ip.IP.default_option('cd','-q')
64 ip.IP.default_option('cd','-q')
65 ip.IP.default_option('macro', '-r')
65 ip.IP.default_option('macro', '-r')
66 # If you only rarely want to execute the things you %edit...
66 # If you only rarely want to execute the things you %edit...
67 #ip.IP.default_option('edit','-x')
67 #ip.IP.default_option('edit','-x')
68
68
69
69
70 o.prompts_pad_left="1"
70 o.prompts_pad_left="1"
71 # Remove all blank lines in between prompts, like a normal shell.
71 # Remove all blank lines in between prompts, like a normal shell.
72 o.separate_in="0"
72 o.separate_in="0"
73 o.separate_out="0"
73 o.separate_out="0"
74 o.separate_out2="0"
74 o.separate_out2="0"
75
75
76 # now alias all syscommands
76 # now alias all syscommands
77
77
78 db = ip.db
78 db = ip.db
79
79
80 syscmds = db.get("syscmdlist",[] )
80 syscmds = db.get("syscmdlist",[] )
81 if not syscmds:
81 if not syscmds:
82 print textwrap.dedent("""
82 print textwrap.dedent("""
83 System command list not initialized, probably the first run...
83 System command list not initialized, probably the first run...
84 running %rehashx to refresh the command list. Run %rehashx
84 running %rehashx to refresh the command list. Run %rehashx
85 again to refresh command list (after installing new software etc.)
85 again to refresh command list (after installing new software etc.)
86 """)
86 """)
87 ip.magic('rehashx')
87 ip.magic('rehashx')
88 syscmds = db.get("syscmdlist")
88 syscmds = db.get("syscmdlist")
89
89
90 # lowcase aliases on win32 only
90 # lowcase aliases on win32 only
91 if os.name == 'posix':
91 if os.name == 'posix':
92 mapper = lambda s:s
92 mapper = lambda s:s
93 else:
93 else:
94 def mapper(s): return s.lower()
94 def mapper(s): return s.lower()
95
95
96 for cmd in syscmds:
96 for cmd in syscmds:
97 # print "sys",cmd #dbg
97 # print "sys",cmd #dbg
98 noext, ext = os.path.splitext(cmd)
98 noext, ext = os.path.splitext(cmd)
99 key = mapper(noext)
99 key = mapper(noext)
100 if key not in ip.IP.alias_table:
100 if key not in ip.IP.alias_table:
101 ip.defalias(key, cmd)
101 ip.defalias(key, cmd)
102
102
103 # mglob combines 'find', recursion, exclusion... '%mglob?' to learn more
103 # mglob combines 'find', recursion, exclusion... '%mglob?' to learn more
104 ip.load("IPython.external.mglob")
104 ip.load("IPython.external.mglob")
105
105
106 # win32 is crippled w/o cygwin, try to help it a little bit
106 # win32 is crippled w/o cygwin, try to help it a little bit
107 if sys.platform == 'win32':
107 if sys.platform == 'win32':
108 if 'cygwin' in os.environ['PATH'].lower():
108 if 'cygwin' in os.environ['PATH'].lower():
109 # use the colors of cygwin ls (recommended)
109 # use the colors of cygwin ls (recommended)
110 ip.defalias('d', 'ls -F --color=auto')
110 ip.defalias('d', 'ls -F --color=auto')
111 else:
111 else:
112 # get icp, imv, imkdir, igrep, irm,...
112 # get icp, imv, imkdir, igrep, irm,...
113 ip.load('ipy_fsops')
113 ip.load('ipy_fsops')
114
114
115 # and the next best thing to real 'ls -F'
115 # and the next best thing to real 'ls -F'
116 ip.defalias('d','dir /w /og /on')
116 ip.defalias('d','dir /w /og /on')
117
117
118 extend_shell_behavior(ip)
118 extend_shell_behavior(ip)
119
119
120 class LastArgFinder:
120 class LastArgFinder:
121 """ Allow $LA to work as "last argument of previous command", like $! in bash
121 """ Allow $LA to work as "last argument of previous command", like $! in bash
122
122
123 To call this in normal IPython code, do LA()
123 To call this in normal IPython code, do LA()
124 """
124 """
125 def __call__(self):
125 def __call__(self):
126 return str(self)
126 return str(self)
127 def __str__(self):
127 def __str__(self):
128 ip = ipapi.get()
128 ip = ipapi.get()
129 for cmd in reversed(ip.IP.input_hist_raw):
129 for cmd in reversed(ip.IP.input_hist_raw):
130 parts = cmd.strip().split()
130 parts = cmd.strip().split()
131 if len(parts) < 2 or parts[-1] == '$LA':
131 if len(parts) < 2 or parts[-1] in ['$LA', 'LA()']:
132 continue
132 continue
133 return parts[-1]
133 return parts[-1]
134 return ""
134 return ""
135
135
136
136
137
137
138
138
139
139
140 # XXX You do not need to understand the next function!
140 # XXX You do not need to understand the next function!
141 # This should probably be moved out of profile
141 # This should probably be moved out of profile
142
142
143 def extend_shell_behavior(ip):
143 def extend_shell_behavior(ip):
144
144
145 # Instead of making signature a global variable tie it to IPSHELL.
145 # Instead of making signature a global variable tie it to IPSHELL.
146 # In future if it is required to distinguish between different
146 # In future if it is required to distinguish between different
147 # shells we can assign a signature per shell basis
147 # shells we can assign a signature per shell basis
148 ip.IP.__sig__ = 0xa005
148 ip.IP.__sig__ = 0xa005
149 # mark the IPSHELL with this signature
149 # mark the IPSHELL with this signature
150 ip.IP.user_ns['__builtins__'].__dict__['__sig__'] = ip.IP.__sig__
150 ip.IP.user_ns['__builtins__'].__dict__['__sig__'] = ip.IP.__sig__
151
151
152 from IPython.Itpl import ItplNS
152 from IPython.Itpl import ItplNS
153 from IPython.genutils import shell
153 from IPython.genutils import shell
154 # utility to expand user variables via Itpl
154 # utility to expand user variables via Itpl
155 # xxx do something sensible with depth?
155 # xxx do something sensible with depth?
156 ip.IP.var_expand = lambda cmd, lvars=None, depth=2: \
156 ip.IP.var_expand = lambda cmd, lvars=None, depth=2: \
157 str(ItplNS(cmd, ip.IP.user_ns, get_locals()))
157 str(ItplNS(cmd, ip.IP.user_ns, get_locals()))
158
158
159 def get_locals():
159 def get_locals():
160 """ Substituting a variable through Itpl deep inside the IPSHELL stack
160 """ Substituting a variable through Itpl deep inside the IPSHELL stack
161 requires the knowledge of all the variables in scope upto the last
161 requires the knowledge of all the variables in scope upto the last
162 IPSHELL frame. This routine simply merges all the local variables
162 IPSHELL frame. This routine simply merges all the local variables
163 on the IPSHELL stack without worrying about their scope rules
163 on the IPSHELL stack without worrying about their scope rules
164 """
164 """
165 import sys
165 import sys
166 # note lambda expression constitues a function call
166 # note lambda expression constitues a function call
167 # hence fno should be incremented by one
167 # hence fno should be incremented by one
168 getsig = lambda fno: sys._getframe(fno+1).f_globals \
168 getsig = lambda fno: sys._getframe(fno+1).f_globals \
169 ['__builtins__'].__dict__['__sig__']
169 ['__builtins__'].__dict__['__sig__']
170 getlvars = lambda fno: sys._getframe(fno+1).f_locals
170 getlvars = lambda fno: sys._getframe(fno+1).f_locals
171 # trackback until we enter the IPSHELL
171 # trackback until we enter the IPSHELL
172 frame_no = 1
172 frame_no = 1
173 sig = ip.IP.__sig__
173 sig = ip.IP.__sig__
174 fsig = ~sig
174 fsig = ~sig
175 while fsig != sig :
175 while fsig != sig :
176 try:
176 try:
177 fsig = getsig(frame_no)
177 fsig = getsig(frame_no)
178 except (AttributeError, KeyError):
178 except (AttributeError, KeyError):
179 frame_no += 1
179 frame_no += 1
180 except ValueError:
180 except ValueError:
181 # stack is depleted
181 # stack is depleted
182 # call did not originate from IPSHELL
182 # call did not originate from IPSHELL
183 return {}
183 return {}
184 first_frame = frame_no
184 first_frame = frame_no
185 # walk further back until we exit from IPSHELL or deplete stack
185 # walk further back until we exit from IPSHELL or deplete stack
186 try:
186 try:
187 while(sig == getsig(frame_no+1)):
187 while(sig == getsig(frame_no+1)):
188 frame_no += 1
188 frame_no += 1
189 except (AttributeError, KeyError, ValueError):
189 except (AttributeError, KeyError, ValueError):
190 pass
190 pass
191 # merge the locals from top down hence overriding
191 # merge the locals from top down hence overriding
192 # any re-definitions of variables, functions etc.
192 # any re-definitions of variables, functions etc.
193 lvars = {}
193 lvars = {}
194 for fno in range(frame_no, first_frame-1, -1):
194 for fno in range(frame_no, first_frame-1, -1):
195 lvars.update(getlvars(fno))
195 lvars.update(getlvars(fno))
196 #print '\n'*5, first_frame, frame_no, '\n', lvars, '\n'*5 #dbg
196 #print '\n'*5, first_frame, frame_no, '\n', lvars, '\n'*5 #dbg
197 return lvars
197 return lvars
198
198
199 def _runlines(lines):
199 def _runlines(lines):
200 """Run a string of one or more lines of source.
200 """Run a string of one or more lines of source.
201
201
202 This method is capable of running a string containing multiple source
202 This method is capable of running a string containing multiple source
203 lines, as if they had been entered at the IPython prompt. Since it
203 lines, as if they had been entered at the IPython prompt. Since it
204 exposes IPython's processing machinery, the given strings can contain
204 exposes IPython's processing machinery, the given strings can contain
205 magic calls (%magic), special shell access (!cmd), etc."""
205 magic calls (%magic), special shell access (!cmd), etc."""
206
206
207 # We must start with a clean buffer, in case this is run from an
207 # We must start with a clean buffer, in case this is run from an
208 # interactive IPython session (via a magic, for example).
208 # interactive IPython session (via a magic, for example).
209 ip.IP.resetbuffer()
209 ip.IP.resetbuffer()
210 lines = lines.split('\n')
210 lines = lines.split('\n')
211 more = 0
211 more = 0
212 command = ''
212 command = ''
213 for line in lines:
213 for line in lines:
214 # skip blank lines so we don't mess up the prompt counter, but do
214 # skip blank lines so we don't mess up the prompt counter, but do
215 # NOT skip even a blank line if we are in a code block (more is
215 # NOT skip even a blank line if we are in a code block (more is
216 # true)
216 # true)
217 # if command is not empty trim the line
217 # if command is not empty trim the line
218 if command != '' :
218 if command != '' :
219 line = line.strip()
219 line = line.strip()
220 # add the broken line to the command
220 # add the broken line to the command
221 if line and line[-1] == '\\' :
221 if line and line[-1] == '\\' :
222 command += line[0:-1] + ' '
222 command += line[0:-1] + ' '
223 more = True
223 more = True
224 continue
224 continue
225 else :
225 else :
226 # add the last (current) line to the command
226 # add the last (current) line to the command
227 command += line
227 command += line
228 if command or more:
228 if command or more:
229 # push to raw history, so hist line numbers stay in sync
229 # push to raw history, so hist line numbers stay in sync
230 ip.IP.input_hist_raw.append("# " + command + "\n")
230 ip.IP.input_hist_raw.append("# " + command + "\n")
231
231
232 more = ip.IP.push(ip.IP.prefilter(command,more))
232 more = ip.IP.push(ip.IP.prefilter(command,more))
233 command = ''
233 command = ''
234 # IPython's runsource returns None if there was an error
234 # IPython's runsource returns None if there was an error
235 # compiling the code. This allows us to stop processing right
235 # compiling the code. This allows us to stop processing right
236 # away, so the user gets the error message at the right place.
236 # away, so the user gets the error message at the right place.
237 if more is None:
237 if more is None:
238 break
238 break
239 # final newline in case the input didn't have it, so that the code
239 # final newline in case the input didn't have it, so that the code
240 # actually does get executed
240 # actually does get executed
241 if more:
241 if more:
242 ip.IP.push('\n')
242 ip.IP.push('\n')
243
243
244 ip.IP.runlines = _runlines
244 ip.IP.runlines = _runlines
245
245
246 main()
246 main()
General Comments 0
You need to be logged in to leave comments. Login now