##// END OF EJS Templates
sh profile: $LA can now be used in place of "last argument of previous command", like $! in bash
Ville M. Vainio -
Show More
@@ -1,226 +1,243 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
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:
121 """ Allow $LA work as "last argument of previous command, like $! in bash
122
123 """
124 def __str__(self):
125 ip = ipapi.get()
126 for cmd in reversed(ip.IP.input_hist_raw):
127 parts = cmd.strip().split()
128 if len(parts) < 2 or parts[-1] == '$LA':
129 continue
130 return parts[-1]
131 return ""
132
133
134
135
136
120 # XXX You do not need to understand the next function!
137 # XXX You do not need to understand the next function!
121 # This should probably be moved out of profile
138 # This should probably be moved out of profile
122
139
123 def extend_shell_behavior(ip):
140 def extend_shell_behavior(ip):
124
141
125 # Instead of making signature a global variable tie it to IPSHELL.
142 # Instead of making signature a global variable tie it to IPSHELL.
126 # In future if it is required to distinguish between different
143 # In future if it is required to distinguish between different
127 # shells we can assign a signature per shell basis
144 # shells we can assign a signature per shell basis
128 ip.IP.__sig__ = 0xa005
145 ip.IP.__sig__ = 0xa005
129 # mark the IPSHELL with this signature
146 # mark the IPSHELL with this signature
130 ip.IP.user_ns['__builtins__'].__dict__['__sig__'] = ip.IP.__sig__
147 ip.IP.user_ns['__builtins__'].__dict__['__sig__'] = ip.IP.__sig__
131
148
132 from IPython.Itpl import ItplNS
149 from IPython.Itpl import ItplNS
133 from IPython.genutils import shell
150 from IPython.genutils import shell
134 # utility to expand user variables via Itpl
151 # utility to expand user variables via Itpl
135 # xxx do something sensible with depth?
152 # xxx do something sensible with depth?
136 ip.IP.var_expand = lambda cmd, lvars=None, depth=2: \
153 ip.IP.var_expand = lambda cmd, lvars=None, depth=2: \
137 str(ItplNS(cmd, ip.IP.user_ns, get_locals()))
154 str(ItplNS(cmd, ip.IP.user_ns, get_locals()))
138
155
139 def get_locals():
156 def get_locals():
140 """ Substituting a variable through Itpl deep inside the IPSHELL stack
157 """ Substituting a variable through Itpl deep inside the IPSHELL stack
141 requires the knowledge of all the variables in scope upto the last
158 requires the knowledge of all the variables in scope upto the last
142 IPSHELL frame. This routine simply merges all the local variables
159 IPSHELL frame. This routine simply merges all the local variables
143 on the IPSHELL stack without worrying about their scope rules
160 on the IPSHELL stack without worrying about their scope rules
144 """
161 """
145 import sys
162 import sys
146 # note lambda expression constitues a function call
163 # note lambda expression constitues a function call
147 # hence fno should be incremented by one
164 # hence fno should be incremented by one
148 getsig = lambda fno: sys._getframe(fno+1).f_globals \
165 getsig = lambda fno: sys._getframe(fno+1).f_globals \
149 ['__builtins__'].__dict__['__sig__']
166 ['__builtins__'].__dict__['__sig__']
150 getlvars = lambda fno: sys._getframe(fno+1).f_locals
167 getlvars = lambda fno: sys._getframe(fno+1).f_locals
151 # trackback until we enter the IPSHELL
168 # trackback until we enter the IPSHELL
152 frame_no = 1
169 frame_no = 1
153 sig = ip.IP.__sig__
170 sig = ip.IP.__sig__
154 fsig = ~sig
171 fsig = ~sig
155 while fsig != sig :
172 while fsig != sig :
156 try:
173 try:
157 fsig = getsig(frame_no)
174 fsig = getsig(frame_no)
158 except (AttributeError, KeyError):
175 except (AttributeError, KeyError):
159 frame_no += 1
176 frame_no += 1
160 except ValueError:
177 except ValueError:
161 # stack is depleted
178 # stack is depleted
162 # call did not originate from IPSHELL
179 # call did not originate from IPSHELL
163 return {}
180 return {}
164 first_frame = frame_no
181 first_frame = frame_no
165 # walk further back until we exit from IPSHELL or deplete stack
182 # walk further back until we exit from IPSHELL or deplete stack
166 try:
183 try:
167 while(sig == getsig(frame_no+1)):
184 while(sig == getsig(frame_no+1)):
168 frame_no += 1
185 frame_no += 1
169 except (AttributeError, KeyError, ValueError):
186 except (AttributeError, KeyError, ValueError):
170 pass
187 pass
171 # merge the locals from top down hence overriding
188 # merge the locals from top down hence overriding
172 # any re-definitions of variables, functions etc.
189 # any re-definitions of variables, functions etc.
173 lvars = {}
190 lvars = {}
174 for fno in range(frame_no, first_frame-1, -1):
191 for fno in range(frame_no, first_frame-1, -1):
175 lvars.update(getlvars(fno))
192 lvars.update(getlvars(fno))
176 #print '\n'*5, first_frame, frame_no, '\n', lvars, '\n'*5 #dbg
193 #print '\n'*5, first_frame, frame_no, '\n', lvars, '\n'*5 #dbg
177 return lvars
194 return lvars
178
195
179 def _runlines(lines):
196 def _runlines(lines):
180 """Run a string of one or more lines of source.
197 """Run a string of one or more lines of source.
181
198
182 This method is capable of running a string containing multiple source
199 This method is capable of running a string containing multiple source
183 lines, as if they had been entered at the IPython prompt. Since it
200 lines, as if they had been entered at the IPython prompt. Since it
184 exposes IPython's processing machinery, the given strings can contain
201 exposes IPython's processing machinery, the given strings can contain
185 magic calls (%magic), special shell access (!cmd), etc."""
202 magic calls (%magic), special shell access (!cmd), etc."""
186
203
187 # We must start with a clean buffer, in case this is run from an
204 # We must start with a clean buffer, in case this is run from an
188 # interactive IPython session (via a magic, for example).
205 # interactive IPython session (via a magic, for example).
189 ip.IP.resetbuffer()
206 ip.IP.resetbuffer()
190 lines = lines.split('\n')
207 lines = lines.split('\n')
191 more = 0
208 more = 0
192 command = ''
209 command = ''
193 for line in lines:
210 for line in lines:
194 # skip blank lines so we don't mess up the prompt counter, but do
211 # skip blank lines so we don't mess up the prompt counter, but do
195 # NOT skip even a blank line if we are in a code block (more is
212 # NOT skip even a blank line if we are in a code block (more is
196 # true)
213 # true)
197 # if command is not empty trim the line
214 # if command is not empty trim the line
198 if command != '' :
215 if command != '' :
199 line = line.strip()
216 line = line.strip()
200 # add the broken line to the command
217 # add the broken line to the command
201 if line and line[-1] == '\\' :
218 if line and line[-1] == '\\' :
202 command += line[0:-1] + ' '
219 command += line[0:-1] + ' '
203 more = True
220 more = True
204 continue
221 continue
205 else :
222 else :
206 # add the last (current) line to the command
223 # add the last (current) line to the command
207 command += line
224 command += line
208 if command or more:
225 if command or more:
209 # push to raw history, so hist line numbers stay in sync
226 # push to raw history, so hist line numbers stay in sync
210 ip.IP.input_hist_raw.append("# " + command + "\n")
227 ip.IP.input_hist_raw.append("# " + command + "\n")
211
228
212 more = ip.IP.push(ip.IP.prefilter(command,more))
229 more = ip.IP.push(ip.IP.prefilter(command,more))
213 command = ''
230 command = ''
214 # IPython's runsource returns None if there was an error
231 # IPython's runsource returns None if there was an error
215 # compiling the code. This allows us to stop processing right
232 # compiling the code. This allows us to stop processing right
216 # away, so the user gets the error message at the right place.
233 # away, so the user gets the error message at the right place.
217 if more is None:
234 if more is None:
218 break
235 break
219 # final newline in case the input didn't have it, so that the code
236 # final newline in case the input didn't have it, so that the code
220 # actually does get executed
237 # actually does get executed
221 if more:
238 if more:
222 ip.IP.push('\n')
239 ip.IP.push('\n')
223
240
224 ip.IP.runlines = _runlines
241 ip.IP.runlines = _runlines
225
242
226 main()
243 main()
General Comments 0
You need to be logged in to leave comments. Login now