##// END OF EJS Templates
ipy_profile_sh now has "depth" in the monkeypatch lambda for var_expand
vivainio -
Show More
@@ -1,182 +1,183 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 path import path" )
28 ip.ex("from path import path" )
29 except ImportError:
29 except ImportError:
30 pass
30 pass
31
31
32 ip.ex('import os')
32 ip.ex('import os')
33 ip.ex("def up(): os.chdir('..')")
33 ip.ex("def up(): os.chdir('..')")
34
34
35 # Get pysh-like prompt for all profiles.
35 # Get pysh-like prompt for all profiles.
36
36
37 o.prompt_in1= '\C_LightBlue[\C_LightCyan\Y1\C_LightBlue]\C_Green|\#> '
37 o.prompt_in1= '\C_LightBlue[\C_LightCyan\Y1\C_LightBlue]\C_Green|\#> '
38 o.prompt_in2= '\C_Green|\C_LightGreen\D\C_Green> '
38 o.prompt_in2= '\C_Green|\C_LightGreen\D\C_Green> '
39 o.prompt_out= '<\#> '
39 o.prompt_out= '<\#> '
40
40
41 from IPython import Release
41 from IPython import Release
42
42
43 import sys
43 import sys
44 # I like my banner minimal.
44 # I like my banner minimal.
45 o.banner = "Py %s IPy %s\n" % (sys.version.split('\n')[0],Release.version)
45 o.banner = "Py %s IPy %s\n" % (sys.version.split('\n')[0],Release.version)
46
46
47 # make 'd' an alias for ls -F
47 # make 'd' an alias for ls -F
48
48
49 ip.magic('alias d ls -F --color=auto')
49 ip.magic('alias d ls -F --color=auto')
50
50
51 # Make available all system commands through "rehashing" immediately.
51 # Make available all system commands through "rehashing" immediately.
52 # You can comment these lines out to speed up startup on very slow
52 # You can comment these lines out to speed up startup on very slow
53 # machines, and to conserve a bit of memory. Note that pysh profile does this
53 # machines, and to conserve a bit of memory. Note that pysh profile does this
54 # automatically
54 # automatically
55 ip.IP.default_option('cd','-q')
55 ip.IP.default_option('cd','-q')
56
56
57
57
58 o.prompts_pad_left="1"
58 o.prompts_pad_left="1"
59 # Remove all blank lines in between prompts, like a normal shell.
59 # Remove all blank lines in between prompts, like a normal shell.
60 o.separate_in="0"
60 o.separate_in="0"
61 o.separate_out="0"
61 o.separate_out="0"
62 o.separate_out2="0"
62 o.separate_out2="0"
63
63
64 # now alias all syscommands
64 # now alias all syscommands
65
65
66 db = ip.db
66 db = ip.db
67
67
68 syscmds = db.get("syscmdlist",[] )
68 syscmds = db.get("syscmdlist",[] )
69 if not syscmds:
69 if not syscmds:
70 print textwrap.dedent("""
70 print textwrap.dedent("""
71 System command list not initialized, probably the first run...
71 System command list not initialized, probably the first run...
72 running %rehashx to refresh the command list. Run %rehashx
72 running %rehashx to refresh the command list. Run %rehashx
73 again to refresh command list (after installing new software etc.)
73 again to refresh command list (after installing new software etc.)
74 """)
74 """)
75 ip.magic('rehashx')
75 ip.magic('rehashx')
76 syscmds = db.get("syscmdlist")
76 syscmds = db.get("syscmdlist")
77 for cmd in syscmds:
77 for cmd in syscmds:
78 #print "al",cmd
78 #print "al",cmd
79 noext, ext = os.path.splitext(cmd)
79 noext, ext = os.path.splitext(cmd)
80 ip.IP.alias_table[noext] = (0,cmd)
80 ip.IP.alias_table[noext] = (0,cmd)
81 extend_shell_behavior(ip)
81 extend_shell_behavior(ip)
82
82
83 def extend_shell_behavior(ip):
83 def extend_shell_behavior(ip):
84
84
85 # Instead of making signature a global variable tie it to IPSHELL.
85 # Instead of making signature a global variable tie it to IPSHELL.
86 # In future if it is required to distinguish between different
86 # In future if it is required to distinguish between different
87 # shells we can assign a signature per shell basis
87 # shells we can assign a signature per shell basis
88 ip.IP.__sig__ = 0xa005
88 ip.IP.__sig__ = 0xa005
89 # mark the IPSHELL with this signature
89 # mark the IPSHELL with this signature
90 ip.IP.user_ns['__builtins__'].__dict__['__sig__'] = ip.IP.__sig__
90 ip.IP.user_ns['__builtins__'].__dict__['__sig__'] = ip.IP.__sig__
91
91
92 from IPython.Itpl import ItplNS
92 from IPython.Itpl import ItplNS
93 from IPython.genutils import shell
93 from IPython.genutils import shell
94 # utility to expand user variables via Itpl
94 # utility to expand user variables via Itpl
95 ip.IP.var_expand = lambda cmd, lvars=None: \
95 # xxx do something sensible with depth?
96 ip.IP.var_expand = lambda cmd, lvars=None, depth=2: \
96 str(ItplNS(cmd.replace('#','\#'), ip.IP.user_ns, get_locals()))
97 str(ItplNS(cmd.replace('#','\#'), ip.IP.user_ns, get_locals()))
97
98
98 def get_locals():
99 def get_locals():
99 """ Substituting a variable through Itpl deep inside the IPSHELL stack
100 """ Substituting a variable through Itpl deep inside the IPSHELL stack
100 requires the knowledge of all the variables in scope upto the last
101 requires the knowledge of all the variables in scope upto the last
101 IPSHELL frame. This routine simply merges all the local variables
102 IPSHELL frame. This routine simply merges all the local variables
102 on the IPSHELL stack without worrying about their scope rules
103 on the IPSHELL stack without worrying about their scope rules
103 """
104 """
104 import sys
105 import sys
105 # note lambda expression constitues a function call
106 # note lambda expression constitues a function call
106 # hence fno should be incremented by one
107 # hence fno should be incremented by one
107 getsig = lambda fno: sys._getframe(fno+1).f_globals \
108 getsig = lambda fno: sys._getframe(fno+1).f_globals \
108 ['__builtins__'].__dict__['__sig__']
109 ['__builtins__'].__dict__['__sig__']
109 getlvars = lambda fno: sys._getframe(fno+1).f_locals
110 getlvars = lambda fno: sys._getframe(fno+1).f_locals
110 # trackback until we enter the IPSHELL
111 # trackback until we enter the IPSHELL
111 frame_no = 1
112 frame_no = 1
112 sig = ip.IP.__sig__
113 sig = ip.IP.__sig__
113 fsig = ~sig
114 fsig = ~sig
114 while fsig != sig :
115 while fsig != sig :
115 try:
116 try:
116 fsig = getsig(frame_no)
117 fsig = getsig(frame_no)
117 except (AttributeError, KeyError):
118 except (AttributeError, KeyError):
118 frame_no += 1
119 frame_no += 1
119 except ValueError:
120 except ValueError:
120 # stack is depleted
121 # stack is depleted
121 # call did not originate from IPSHELL
122 # call did not originate from IPSHELL
122 return {}
123 return {}
123 first_frame = frame_no
124 first_frame = frame_no
124 # walk further back until we exit from IPSHELL or deplete stack
125 # walk further back until we exit from IPSHELL or deplete stack
125 try:
126 try:
126 while(sig == getsig(frame_no+1)):
127 while(sig == getsig(frame_no+1)):
127 frame_no += 1
128 frame_no += 1
128 except (AttributeError, KeyError, ValueError):
129 except (AttributeError, KeyError, ValueError):
129 pass
130 pass
130 # merge the locals from top down hence overriding
131 # merge the locals from top down hence overriding
131 # any re-definitions of variables, functions etc.
132 # any re-definitions of variables, functions etc.
132 lvars = {}
133 lvars = {}
133 for fno in range(frame_no, first_frame-1, -1):
134 for fno in range(frame_no, first_frame-1, -1):
134 lvars.update(getlvars(fno))
135 lvars.update(getlvars(fno))
135 #print '\n'*5, first_frame, frame_no, '\n', lvars, '\n'*5 #dbg
136 #print '\n'*5, first_frame, frame_no, '\n', lvars, '\n'*5 #dbg
136 return lvars
137 return lvars
137
138
138 def _runlines(lines):
139 def _runlines(lines):
139 """Run a string of one or more lines of source.
140 """Run a string of one or more lines of source.
140
141
141 This method is capable of running a string containing multiple source
142 This method is capable of running a string containing multiple source
142 lines, as if they had been entered at the IPython prompt. Since it
143 lines, as if they had been entered at the IPython prompt. Since it
143 exposes IPython's processing machinery, the given strings can contain
144 exposes IPython's processing machinery, the given strings can contain
144 magic calls (%magic), special shell access (!cmd), etc."""
145 magic calls (%magic), special shell access (!cmd), etc."""
145
146
146 # We must start with a clean buffer, in case this is run from an
147 # We must start with a clean buffer, in case this is run from an
147 # interactive IPython session (via a magic, for example).
148 # interactive IPython session (via a magic, for example).
148 ip.IP.resetbuffer()
149 ip.IP.resetbuffer()
149 lines = lines.split('\n')
150 lines = lines.split('\n')
150 more = 0
151 more = 0
151 command = ''
152 command = ''
152 for line in lines:
153 for line in lines:
153 # skip blank lines so we don't mess up the prompt counter, but do
154 # skip blank lines so we don't mess up the prompt counter, but do
154 # NOT skip even a blank line if we are in a code block (more is
155 # NOT skip even a blank line if we are in a code block (more is
155 # true)
156 # true)
156 # if command is not empty trim the line
157 # if command is not empty trim the line
157 if command != '' :
158 if command != '' :
158 line = line.strip()
159 line = line.strip()
159 # add the broken line to the command
160 # add the broken line to the command
160 if line and line[-1] == '\\' :
161 if line and line[-1] == '\\' :
161 command += line[0:-1] + ' '
162 command += line[0:-1] + ' '
162 more = True
163 more = True
163 continue
164 continue
164 else :
165 else :
165 # add the last (current) line to the command
166 # add the last (current) line to the command
166 command += line
167 command += line
167 if command or more:
168 if command or more:
168 more = ip.IP.push(ip.IP.prefilter(command,more))
169 more = ip.IP.push(ip.IP.prefilter(command,more))
169 command = ''
170 command = ''
170 # IPython's runsource returns None if there was an error
171 # IPython's runsource returns None if there was an error
171 # compiling the code. This allows us to stop processing right
172 # compiling the code. This allows us to stop processing right
172 # away, so the user gets the error message at the right place.
173 # away, so the user gets the error message at the right place.
173 if more is None:
174 if more is None:
174 break
175 break
175 # final newline in case the input didn't have it, so that the code
176 # final newline in case the input didn't have it, so that the code
176 # actually does get executed
177 # actually does get executed
177 if more:
178 if more:
178 ip.IP.push('\n')
179 ip.IP.push('\n')
179
180
180 ip.IP.runlines = _runlines
181 ip.IP.runlines = _runlines
181
182
182 main()
183 main()
General Comments 0
You need to be logged in to leave comments. Login now