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