Show More
@@ -1,271 +1,268 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.core import ipapi |
|
11 | 11 | from IPython.core.error import TryNext |
|
12 | 12 | import os,re,textwrap |
|
13 | 13 | |
|
14 | 14 | # The import below effectively obsoletes your old-style ipythonrc[.ini], |
|
15 | 15 | # so consider yourself warned! |
|
16 | 16 | |
|
17 | 17 | import ipy_defaults |
|
18 | 18 | |
|
19 | 19 | def main(): |
|
20 | 20 | ip = ipapi.get() |
|
21 | 21 | o = ip.options |
|
22 | 22 | # autocall to "full" mode (smart mode is default, I like full mode) |
|
23 | 23 | |
|
24 | 24 | o.autocall = 2 |
|
25 | 25 | |
|
26 | 26 | # Jason Orendorff's path class is handy to have in user namespace |
|
27 | 27 | # if you are doing shell-like stuff |
|
28 | 28 | try: |
|
29 | 29 | ip.ex("from IPython.external.path import path" ) |
|
30 | 30 | except ImportError: |
|
31 | 31 | pass |
|
32 | 32 | |
|
33 | 33 | # beefed up %env is handy in shell mode |
|
34 | 34 | import envpersist |
|
35 | 35 | |
|
36 | 36 | # To see where mycmd resides (in path/aliases), do %which mycmd |
|
37 | 37 | import ipy_which |
|
38 | 38 | |
|
39 | 39 | # tab completers for hg, svn, ... |
|
40 | 40 | import ipy_app_completers |
|
41 | 41 | |
|
42 | 42 | # To make executables foo and bar in mybin usable without PATH change, do: |
|
43 | 43 | # %rehashdir c:/mybin |
|
44 | 44 | # %store foo |
|
45 | 45 | # %store bar |
|
46 | 46 | import ipy_rehashdir |
|
47 | 47 | |
|
48 | 48 | # does not work without subprocess module! |
|
49 | 49 | #import ipy_signals |
|
50 | 50 | |
|
51 | 51 | ip.ex('import os') |
|
52 | 52 | ip.ex("def up(): os.chdir('..')") |
|
53 | 53 | ip.user_ns['LA'] = LastArgFinder() |
|
54 | 54 | |
|
55 | 55 | # You can assign to _prompt_title variable |
|
56 | 56 | # to provide some extra information for prompt |
|
57 | 57 | # (e.g. the current mode, host/username...) |
|
58 | 58 | |
|
59 | 59 | ip.user_ns['_prompt_title'] = '' |
|
60 | 60 | |
|
61 | 61 | # Nice prompt |
|
62 | 62 | o.prompt_in1= r'\C_Green${_prompt_title}\C_LightBlue[\C_LightCyan\Y2\C_LightBlue]\C_Green|\#> ' |
|
63 | 63 | o.prompt_in2= r'\C_Green|\C_LightGreen\D\C_Green> ' |
|
64 | 64 | o.prompt_out= '<\#> ' |
|
65 | 65 | |
|
66 | 66 | from IPython.core import release |
|
67 | 67 | |
|
68 | 68 | import sys |
|
69 | 69 | # Non-chatty banner |
|
70 | 70 | o.banner = "IPython %s [on Py %s]\n" % (release.version,sys.version.split(None,1)[0]) |
|
71 | 71 | |
|
72 | 72 | |
|
73 | 73 | ip.default_option('cd','-q') |
|
74 | 74 | ip.default_option('macro', '-r') |
|
75 | 75 | # If you only rarely want to execute the things you %edit... |
|
76 | 76 | #ip.default_option('edit','-x') |
|
77 | 77 | |
|
78 | 78 | |
|
79 | 79 | o.prompts_pad_left="1" |
|
80 | 80 | # Remove all blank lines in between prompts, like a normal shell. |
|
81 | 81 | o.separate_in="0" |
|
82 | 82 | o.separate_out="0" |
|
83 | 83 | o.separate_out2="0" |
|
84 | 84 | |
|
85 | 85 | # now alias all syscommands |
|
86 | 86 | |
|
87 | 87 | db = ip.db |
|
88 | 88 | |
|
89 | 89 | syscmds = db.get("syscmdlist",[] ) |
|
90 | 90 | if not syscmds: |
|
91 | 91 | print textwrap.dedent(""" |
|
92 | 92 | System command list not initialized, probably the first run... |
|
93 | 93 | running %rehashx to refresh the command list. Run %rehashx |
|
94 | 94 | again to refresh command list (after installing new software etc.) |
|
95 | 95 | """) |
|
96 | 96 | ip.magic('rehashx') |
|
97 | 97 | syscmds = db.get("syscmdlist") |
|
98 | 98 | |
|
99 | 99 | # lowcase aliases on win32 only |
|
100 | 100 | if os.name == 'posix': |
|
101 | 101 | mapper = lambda s:s |
|
102 | 102 | else: |
|
103 | 103 | def mapper(s): return s.lower() |
|
104 | 104 | |
|
105 | 105 | for cmd in syscmds: |
|
106 | 106 | # print "sys",cmd #dbg |
|
107 | 107 | noext, ext = os.path.splitext(cmd) |
|
108 | 108 | if ext.lower() == '.exe': |
|
109 | 109 | cmd = noext |
|
110 | 110 | |
|
111 | 111 | key = mapper(cmd) |
|
112 | 112 | if key not in ip.alias_manager.alias_table: |
|
113 | 113 | # Dots will be removed from alias names, since ipython |
|
114 | 114 | # assumes names with dots to be python code |
|
115 | 115 | |
|
116 | 116 | ip.define_alias(key.replace('.',''), cmd) |
|
117 | 117 | |
|
118 | # mglob combines 'find', recursion, exclusion... '%mglob?' to learn more | |
|
119 | ip.load("IPython.external.mglob") | |
|
120 | ||
|
121 | 118 | # win32 is crippled w/o cygwin, try to help it a little bit |
|
122 | 119 | if sys.platform == 'win32': |
|
123 | 120 | if 'cygwin' in os.environ['PATH'].lower(): |
|
124 | 121 | # use the colors of cygwin ls (recommended) |
|
125 | 122 | ip.define_alias('d', 'ls -F --color=auto') |
|
126 | 123 | else: |
|
127 | 124 | # get icp, imv, imkdir, igrep, irm,... |
|
128 | 125 | ip.load('ipy_fsops') |
|
129 | 126 | |
|
130 | 127 | # and the next best thing to real 'ls -F' |
|
131 | 128 | ip.define_alias('d','dir /w /og /on') |
|
132 | 129 | |
|
133 | 130 | ip.set_hook('input_prefilter', slash_prefilter_f) |
|
134 | 131 | extend_shell_behavior(ip) |
|
135 | 132 | |
|
136 | 133 | class LastArgFinder: |
|
137 | 134 | """ Allow $LA to work as "last argument of previous command", like $! in bash |
|
138 | 135 | |
|
139 | 136 | To call this in normal IPython code, do LA() |
|
140 | 137 | """ |
|
141 | 138 | def __call__(self, hist_idx = None): |
|
142 | 139 | ip = ipapi.get() |
|
143 | 140 | if hist_idx is None: |
|
144 | 141 | return str(self) |
|
145 | 142 | return ip.input_hist_raw[hist_idx].strip().split()[-1] |
|
146 | 143 | def __str__(self): |
|
147 | 144 | ip = ipapi.get() |
|
148 | 145 | for cmd in reversed(ip.input_hist_raw): |
|
149 | 146 | parts = cmd.strip().split() |
|
150 | 147 | if len(parts) < 2 or parts[-1] in ['$LA', 'LA()']: |
|
151 | 148 | continue |
|
152 | 149 | return parts[-1] |
|
153 | 150 | return "" |
|
154 | 151 | |
|
155 | 152 | def slash_prefilter_f(self,line): |
|
156 | 153 | """ ./foo, ~/foo and /bin/foo now run foo as system command |
|
157 | 154 | |
|
158 | 155 | Removes the need for doing !./foo, !~/foo or !/bin/foo |
|
159 | 156 | """ |
|
160 | 157 | from IPython.utils import genutils |
|
161 | 158 | if re.match('(?:[.~]|/[a-zA-Z_0-9]+)/', line): |
|
162 | 159 | return "get_ipython().system(" + genutils.make_quoted_expr(line)+")" |
|
163 | 160 | raise TryNext |
|
164 | 161 | |
|
165 | 162 | # XXX You do not need to understand the next function! |
|
166 | 163 | # This should probably be moved out of profile |
|
167 | 164 | |
|
168 | 165 | def extend_shell_behavior(ip): |
|
169 | 166 | |
|
170 | 167 | # Instead of making signature a global variable tie it to IPSHELL. |
|
171 | 168 | # In future if it is required to distinguish between different |
|
172 | 169 | # shells we can assign a signature per shell basis |
|
173 | 170 | ip.__sig__ = 0xa005 |
|
174 | 171 | # mark the IPSHELL with this signature |
|
175 | 172 | ip.user_ns['__builtins__'].__dict__['__sig__'] = ip.__sig__ |
|
176 | 173 | |
|
177 | 174 | from IPython.external.Itpl import ItplNS |
|
178 | 175 | from IPython.utils.genutils import shell |
|
179 | 176 | # utility to expand user variables via Itpl |
|
180 | 177 | # xxx do something sensible with depth? |
|
181 | 178 | ip.var_expand = lambda cmd, lvars=None, depth=2: \ |
|
182 | 179 | str(ItplNS(cmd, ip.user_ns, get_locals())) |
|
183 | 180 | |
|
184 | 181 | def get_locals(): |
|
185 | 182 | """ Substituting a variable through Itpl deep inside the IPSHELL stack |
|
186 | 183 | requires the knowledge of all the variables in scope upto the last |
|
187 | 184 | IPSHELL frame. This routine simply merges all the local variables |
|
188 | 185 | on the IPSHELL stack without worrying about their scope rules |
|
189 | 186 | """ |
|
190 | 187 | import sys |
|
191 | 188 | # note lambda expression constitues a function call |
|
192 | 189 | # hence fno should be incremented by one |
|
193 | 190 | getsig = lambda fno: sys._getframe(fno+1).f_globals \ |
|
194 | 191 | ['__builtins__'].__dict__['__sig__'] |
|
195 | 192 | getlvars = lambda fno: sys._getframe(fno+1).f_locals |
|
196 | 193 | # trackback until we enter the IPSHELL |
|
197 | 194 | frame_no = 1 |
|
198 | 195 | sig = ip.__sig__ |
|
199 | 196 | fsig = ~sig |
|
200 | 197 | while fsig != sig : |
|
201 | 198 | try: |
|
202 | 199 | fsig = getsig(frame_no) |
|
203 | 200 | except (AttributeError, KeyError): |
|
204 | 201 | frame_no += 1 |
|
205 | 202 | except ValueError: |
|
206 | 203 | # stack is depleted |
|
207 | 204 | # call did not originate from IPSHELL |
|
208 | 205 | return {} |
|
209 | 206 | first_frame = frame_no |
|
210 | 207 | # walk further back until we exit from IPSHELL or deplete stack |
|
211 | 208 | try: |
|
212 | 209 | while(sig == getsig(frame_no+1)): |
|
213 | 210 | frame_no += 1 |
|
214 | 211 | except (AttributeError, KeyError, ValueError): |
|
215 | 212 | pass |
|
216 | 213 | # merge the locals from top down hence overriding |
|
217 | 214 | # any re-definitions of variables, functions etc. |
|
218 | 215 | lvars = {} |
|
219 | 216 | for fno in range(frame_no, first_frame-1, -1): |
|
220 | 217 | lvars.update(getlvars(fno)) |
|
221 | 218 | #print '\n'*5, first_frame, frame_no, '\n', lvars, '\n'*5 #dbg |
|
222 | 219 | return lvars |
|
223 | 220 | |
|
224 | 221 | def _runlines(lines): |
|
225 | 222 | """Run a string of one or more lines of source. |
|
226 | 223 | |
|
227 | 224 | This method is capable of running a string containing multiple source |
|
228 | 225 | lines, as if they had been entered at the IPython prompt. Since it |
|
229 | 226 | exposes IPython's processing machinery, the given strings can contain |
|
230 | 227 | magic calls (%magic), special shell access (!cmd), etc.""" |
|
231 | 228 | |
|
232 | 229 | # We must start with a clean buffer, in case this is run from an |
|
233 | 230 | # interactive IPython session (via a magic, for example). |
|
234 | 231 | ip.resetbuffer() |
|
235 | 232 | lines = lines.split('\n') |
|
236 | 233 | more = 0 |
|
237 | 234 | command = '' |
|
238 | 235 | for line in lines: |
|
239 | 236 | # skip blank lines so we don't mess up the prompt counter, but do |
|
240 | 237 | # NOT skip even a blank line if we are in a code block (more is |
|
241 | 238 | # true) |
|
242 | 239 | # if command is not empty trim the line |
|
243 | 240 | if command != '' : |
|
244 | 241 | line = line.strip() |
|
245 | 242 | # add the broken line to the command |
|
246 | 243 | if line and line[-1] == '\\' : |
|
247 | 244 | command += line[0:-1] + ' ' |
|
248 | 245 | more = True |
|
249 | 246 | continue |
|
250 | 247 | else : |
|
251 | 248 | # add the last (current) line to the command |
|
252 | 249 | command += line |
|
253 | 250 | if command or more: |
|
254 | 251 | # push to raw history, so hist line numbers stay in sync |
|
255 | 252 | ip.input_hist_raw.append("# " + command + "\n") |
|
256 | 253 | |
|
257 | 254 | more = ip.push_line(ip.prefilter(command,more)) |
|
258 | 255 | command = '' |
|
259 | 256 | # IPython's runsource returns None if there was an error |
|
260 | 257 | # compiling the code. This allows us to stop processing right |
|
261 | 258 | # away, so the user gets the error message at the right place. |
|
262 | 259 | if more is None: |
|
263 | 260 | break |
|
264 | 261 | # final newline in case the input didn't have it, so that the code |
|
265 | 262 | # actually does get executed |
|
266 | 263 | if more: |
|
267 | 264 | ip.push_line('\n') |
|
268 | 265 | |
|
269 | 266 | ip.runlines = _runlines |
|
270 | 267 | |
|
271 | 268 | main() |
@@ -1,246 +1,254 b'' | |||
|
1 | 1 | """ File system operations |
|
2 | 2 | |
|
3 | 3 | Contains: Simple variants of normal unix shell commands (icp, imv, irm, |
|
4 | 4 | imkdir, igrep). |
|
5 | 5 | |
|
6 | 6 | Some "otherwise handy" utils ('collect' for gathering files to |
|
7 | 7 | ~/_ipython/collect, 'inote' for collecting single note lines to |
|
8 | 8 | ~/_ipython/note.txt) |
|
9 | 9 | |
|
10 | 10 | Mostly of use for bare windows installations where cygwin/equivalent is not |
|
11 | 11 | installed and you would otherwise need to deal with dos versions of the |
|
12 | 12 | commands (that e.g. don't understand / as path separator). These can |
|
13 | 13 | do some useful tricks on their own, though (like use 'mglob' patterns). |
|
14 | 14 | |
|
15 | 15 | Not to be confused with ipipe commands (ils etc.) that also start with i. |
|
16 | ||
|
17 | QUARANTINE, NEEDS UPDATING TO THE NEW IPYTHON API TO WORK | |
|
18 | ||
|
19 | this depends on mglob that used to be in externals, | |
|
20 | if this code is updated to run again with current IPython, you may need to | |
|
21 | reintroduce that file back. In doing so, look for the possibility of achieving | |
|
22 | the same effect only with the standard library (which may have improved by now, | |
|
23 | since we currently depend on Python 2.6). | |
|
16 | 24 | """ |
|
17 | 25 | |
|
18 | 26 | from IPython.core import ipapi |
|
19 | 27 | from IPython.core.error import TryNext |
|
20 | 28 | ip = ipapi.get() |
|
21 | 29 | |
|
22 | 30 | import shutil,os,shlex |
|
23 | 31 | from IPython.external import mglob |
|
24 | 32 | from IPython.external.path import path |
|
25 | 33 | from IPython.core.error import UsageError |
|
26 | 34 | import IPython.utils.generics |
|
27 | 35 | |
|
28 | 36 | def parse_args(args): |
|
29 | 37 | """ Given arg string 'CMD files... target', return ([files], target) """ |
|
30 | 38 | |
|
31 | 39 | tup = args.split(None, 1) |
|
32 | 40 | if len(tup) == 1: |
|
33 | 41 | raise UsageError("Expected arguments for " + tup[0]) |
|
34 | 42 | |
|
35 | 43 | tup2 = shlex.split(tup[1]) |
|
36 | 44 | |
|
37 | 45 | flist, trg = mglob.expand(tup2[0:-1]), tup2[-1] |
|
38 | 46 | if not flist: |
|
39 | 47 | raise UsageError("No files found:" + str(tup2[0:-1])) |
|
40 | 48 | return flist, trg |
|
41 | 49 | |
|
42 | 50 | def icp(ip,arg): |
|
43 | 51 | """ icp files... targetdir |
|
44 | 52 | |
|
45 | 53 | Copy all files to target, creating dirs for target if necessary |
|
46 | 54 | |
|
47 | 55 | icp srcdir dstdir |
|
48 | 56 | |
|
49 | 57 | Copy srcdir to distdir |
|
50 | 58 | |
|
51 | 59 | """ |
|
52 | 60 | import distutils.dir_util |
|
53 | 61 | |
|
54 | 62 | fs, targetdir = parse_args(arg) |
|
55 | 63 | if not os.path.isdir(targetdir) and len(fs) > 1: |
|
56 | 64 | distutils.dir_util.mkpath(targetdir,verbose =1) |
|
57 | 65 | for f in fs: |
|
58 | 66 | if os.path.isdir(f): |
|
59 | 67 | shutil.copytree(f, targetdir) |
|
60 | 68 | else: |
|
61 | 69 | shutil.copy2(f,targetdir) |
|
62 | 70 | return fs |
|
63 | 71 | ip.define_alias("icp",icp) |
|
64 | 72 | |
|
65 | 73 | def imv(ip,arg): |
|
66 | 74 | """ imv src tgt |
|
67 | 75 | |
|
68 | 76 | Move source to target. |
|
69 | 77 | """ |
|
70 | 78 | |
|
71 | 79 | fs, target = parse_args(arg) |
|
72 | 80 | if len(fs) > 1: |
|
73 | 81 | assert os.path.isdir(target) |
|
74 | 82 | for f in fs: |
|
75 | 83 | shutil.move(f, target) |
|
76 | 84 | return fs |
|
77 | 85 | ip.define_alias("imv",imv) |
|
78 | 86 | |
|
79 | 87 | def irm(ip,arg): |
|
80 | 88 | """ irm path[s]... |
|
81 | 89 | |
|
82 | 90 | Remove file[s] or dir[s] path. Dirs are deleted recursively. |
|
83 | 91 | """ |
|
84 | 92 | try: |
|
85 | 93 | paths = mglob.expand(arg.split(None,1)[1]) |
|
86 | 94 | except IndexError: |
|
87 | 95 | raise UsageError("%irm paths...") |
|
88 | 96 | import distutils.dir_util |
|
89 | 97 | for p in paths: |
|
90 | 98 | print "rm",p |
|
91 | 99 | if os.path.isdir(p): |
|
92 | 100 | distutils.dir_util.remove_tree(p, verbose = 1) |
|
93 | 101 | else: |
|
94 | 102 | os.remove(p) |
|
95 | 103 | |
|
96 | 104 | ip.define_alias("irm",irm) |
|
97 | 105 | |
|
98 | 106 | def imkdir(ip,arg): |
|
99 | 107 | """ imkdir path |
|
100 | 108 | |
|
101 | 109 | Creates dir path, and all dirs on the road |
|
102 | 110 | """ |
|
103 | 111 | import distutils.dir_util |
|
104 | 112 | targetdir = arg.split(None,1)[1] |
|
105 | 113 | distutils.dir_util.mkpath(targetdir,verbose =1) |
|
106 | 114 | |
|
107 | 115 | ip.define_alias("imkdir",imkdir) |
|
108 | 116 | |
|
109 | 117 | def igrep(ip,arg): |
|
110 | 118 | """ igrep PAT files... |
|
111 | 119 | |
|
112 | 120 | Very dumb file scan, case-insensitive. |
|
113 | 121 | |
|
114 | 122 | e.g. |
|
115 | 123 | |
|
116 | 124 | igrep "test this" rec:*.py |
|
117 | 125 | |
|
118 | 126 | """ |
|
119 | 127 | elems = shlex.split(arg) |
|
120 | 128 | dummy, pat, fs = elems[0], elems[1], mglob.expand(elems[2:]) |
|
121 | 129 | res = [] |
|
122 | 130 | for f in fs: |
|
123 | 131 | found = False |
|
124 | 132 | for l in open(f): |
|
125 | 133 | if pat.lower() in l.lower(): |
|
126 | 134 | if not found: |
|
127 | 135 | print "[[",f,"]]" |
|
128 | 136 | found = True |
|
129 | 137 | res.append(f) |
|
130 | 138 | print l.rstrip() |
|
131 | 139 | return res |
|
132 | 140 | |
|
133 | 141 | ip.define_alias("igrep",igrep) |
|
134 | 142 | |
|
135 | 143 | def collect(ip,arg): |
|
136 | 144 | """ collect foo/a.txt rec:bar=*.py |
|
137 | 145 | |
|
138 | 146 | Copies foo/a.txt to ~/_ipython/collect/foo/a.txt and *.py from bar, |
|
139 | 147 | likewise |
|
140 | 148 | |
|
141 | 149 | Without args, try to open ~/_ipython/collect dir (in win32 at least). |
|
142 | 150 | """ |
|
143 | 151 | from IPython.external.path import path |
|
144 | 152 | basedir = path(ip.ipython_dir + '/collect') |
|
145 | 153 | try: |
|
146 | 154 | fs = mglob.expand(arg.split(None,1)[1]) |
|
147 | 155 | except IndexError: |
|
148 | 156 | os.startfile(basedir) |
|
149 | 157 | return |
|
150 | 158 | for f in fs: |
|
151 | 159 | f = path(f) |
|
152 | 160 | trg = basedir / f.splitdrive()[1].lstrip('/\\') |
|
153 | 161 | if f.isdir(): |
|
154 | 162 | print "mkdir",trg |
|
155 | 163 | trg.makedirs() |
|
156 | 164 | continue |
|
157 | 165 | dname = trg.dirname() |
|
158 | 166 | if not dname.isdir(): |
|
159 | 167 | dname.makedirs() |
|
160 | 168 | print f,"=>",trg |
|
161 | 169 | shutil.copy2(f,trg) |
|
162 | 170 | |
|
163 | 171 | ip.define_alias("collect",collect) |
|
164 | 172 | |
|
165 | 173 | def inote(ip,arg): |
|
166 | 174 | """ inote Hello world |
|
167 | 175 | |
|
168 | 176 | Adds timestamp and Hello world to ~/_ipython/notes.txt |
|
169 | 177 | |
|
170 | 178 | Without args, opens notes.txt for editing. |
|
171 | 179 | """ |
|
172 | 180 | import time |
|
173 | 181 | fname = ip.ipython_dir + '/notes.txt' |
|
174 | 182 | |
|
175 | 183 | try: |
|
176 | 184 | entry = " === " + time.asctime() + ': ===\n' + arg.split(None,1)[1] + '\n' |
|
177 | 185 | f= open(fname, 'a').write(entry) |
|
178 | 186 | except IndexError: |
|
179 | 187 | ip.hooks.editor(fname) |
|
180 | 188 | |
|
181 | 189 | ip.define_alias("inote",inote) |
|
182 | 190 | |
|
183 | 191 | def pathobj_mangle(p): |
|
184 | 192 | return p.replace(' ', '__').replace('.','DOT') |
|
185 | 193 | def pathobj_unmangle(s): |
|
186 | 194 | return s.replace('__',' ').replace('DOT','.') |
|
187 | 195 | |
|
188 | 196 | |
|
189 | 197 | |
|
190 | 198 | class PathObj(path): |
|
191 | 199 | def __init__(self,p): |
|
192 | 200 | self.path = p |
|
193 | 201 | if p != '.': |
|
194 | 202 | self.ents = [pathobj_mangle(ent) for ent in os.listdir(p)] |
|
195 | 203 | else: |
|
196 | 204 | self.ents = None |
|
197 | 205 | def __complete__(self): |
|
198 | 206 | if self.path != '.': |
|
199 | 207 | return self.ents |
|
200 | 208 | self.ents = [pathobj_mangle(ent) for ent in os.listdir('.')] |
|
201 | 209 | return self.ents |
|
202 | 210 | def __getattr__(self,name): |
|
203 | 211 | if name in self.ents: |
|
204 | 212 | if self.path.endswith('/'): |
|
205 | 213 | sep = '' |
|
206 | 214 | else: |
|
207 | 215 | sep = '/' |
|
208 | 216 | |
|
209 | 217 | tgt = self.path + sep + pathobj_unmangle(name) |
|
210 | 218 | #print "tgt",tgt |
|
211 | 219 | if os.path.isdir(tgt): |
|
212 | 220 | return PathObj(tgt) |
|
213 | 221 | if os.path.isfile(tgt): |
|
214 | 222 | return path(tgt) |
|
215 | 223 | |
|
216 | 224 | raise AttributeError, name # <<< DON'T FORGET THIS LINE !! |
|
217 | 225 | def __str__(self): |
|
218 | 226 | return self.path |
|
219 | 227 | |
|
220 | 228 | def __repr__(self): |
|
221 | 229 | return "<PathObj to %s>" % self.path |
|
222 | 230 | |
|
223 | 231 | def __call__(self): |
|
224 | 232 | print "cd:",self.path |
|
225 | 233 | os.chdir(self.path) |
|
226 | 234 | |
|
227 | 235 | def complete_pathobj(obj, prev_completions): |
|
228 | 236 | if hasattr(obj,'__complete__'): |
|
229 | 237 | res = obj.__complete__() |
|
230 | 238 | if res: |
|
231 | 239 | return res |
|
232 | 240 | # just return normal attributes of 'path' object if the dir is empty |
|
233 | 241 | raise TryNext |
|
234 | 242 | |
|
235 | 243 | complete_pathobj = IPython.utils.generics.complete_object.when_type(PathObj)(complete_pathobj) |
|
236 | 244 | |
|
237 | 245 | def test_pathobj(): |
|
238 | 246 | #p = PathObj('c:/prj') |
|
239 | 247 | #p2 = p.cgi |
|
240 | 248 | #print p,p2 |
|
241 | 249 | rootdir = PathObj("/") |
|
242 | 250 | startmenu = PathObj("d:/Documents and Settings/All Users/Start Menu/Programs") |
|
243 | 251 | cwd = PathObj('.') |
|
244 | 252 | ip.push("rootdir startmenu cwd") |
|
245 | 253 | |
|
246 | 254 | #test_pathobj() |
@@ -1,294 +1,283 b'' | |||
|
1 | 1 | .. _ipython_as_shell: |
|
2 | 2 | |
|
3 | 3 | ========================= |
|
4 | 4 | IPython as a system shell |
|
5 | 5 | ========================= |
|
6 | 6 | |
|
7 | 7 | .. warning:: |
|
8 | 8 | |
|
9 | 9 | As of the 0.11 version of IPython, most of the APIs used by the shell |
|
10 | 10 | profile have been changed, so the profile currently does very little |
|
11 | 11 | beyond changing the IPython prompt. To help restore the shell |
|
12 | 12 | profile to past functionality described here, the old code is found in |
|
13 | 13 | :file:`IPython/deathrow`, which needs to be updated to use the |
|
14 | 14 | APIs in 0.11. |
|
15 | 15 | |
|
16 | 16 | Overview |
|
17 | 17 | ======== |
|
18 | 18 | |
|
19 | 19 | The 'sh' profile optimizes IPython for system shell usage. Apart from |
|
20 | 20 | certain job control functionality that is present in unix (ctrl+z does |
|
21 | 21 | "suspend"), the sh profile should provide you with most of the |
|
22 | 22 | functionality you use daily in system shell, and more. Invoke IPython |
|
23 | 23 | in 'sh' profile by doing 'ipython -p sh', or (in win32) by launching |
|
24 | 24 | the "pysh" shortcut in start menu. |
|
25 | 25 | |
|
26 | 26 | If you want to use the features of sh profile as your defaults (which |
|
27 | 27 | might be a good idea if you use other profiles a lot of the time but |
|
28 | 28 | still want the convenience of sh profile), add ``import ipy_profile_sh`` |
|
29 | 29 | to your $IPYTHONDIR/ipy_user_conf.py. |
|
30 | 30 | |
|
31 | 31 | The 'sh' profile is different from the default profile in that: |
|
32 | 32 | |
|
33 | 33 | * Prompt shows the current directory |
|
34 | 34 | * Spacing between prompts and input is more compact (no padding with |
|
35 | 35 | empty lines). The startup banner is more compact as well. |
|
36 | 36 | * System commands are directly available (in alias table) without |
|
37 | 37 | requesting %rehashx - however, if you install new programs along |
|
38 | 38 | your PATH, you might want to run %rehashx to update the persistent |
|
39 | 39 | alias table |
|
40 | 40 | * Macros are stored in raw format by default. That is, instead of |
|
41 | 41 | '_ip.system("cat foo"), the macro will contain text 'cat foo') |
|
42 | 42 | * Autocall is in full mode |
|
43 | 43 | * Calling "up" does "cd .." |
|
44 | 44 | |
|
45 | 45 | The 'sh' profile is different from the now-obsolete (and unavailable) |
|
46 | 46 | 'pysh' profile in that the ``$$var = command`` and ``$var = command`` syntax is |
|
47 | 47 | not supported anymore. Use ``var = !command`` instead (which is available in all |
|
48 | 48 | IPython profiles). |
|
49 | 49 | |
|
50 | 50 | Aliases |
|
51 | 51 | ======= |
|
52 | 52 | |
|
53 | 53 | All of your $PATH has been loaded as IPython aliases, so you should be |
|
54 | 54 | able to type any normal system command and have it executed. See |
|
55 | 55 | %alias? and %unalias? for details on the alias facilities. See also |
|
56 | 56 | %rehashx? for details on the mechanism used to load $PATH. |
|
57 | 57 | |
|
58 | 58 | |
|
59 | 59 | Directory management |
|
60 | 60 | ==================== |
|
61 | 61 | |
|
62 | 62 | Since each command passed by ipython to the underlying system is executed |
|
63 | 63 | in a subshell which exits immediately, you can NOT use !cd to navigate |
|
64 | 64 | the filesystem. |
|
65 | 65 | |
|
66 | 66 | IPython provides its own builtin '%cd' magic command to move in the |
|
67 | 67 | filesystem (the % is not required with automagic on). It also maintains |
|
68 | 68 | a list of visited directories (use %dhist to see it) and allows direct |
|
69 | 69 | switching to any of them. Type 'cd?' for more details. |
|
70 | 70 | |
|
71 | 71 | %pushd, %popd and %dirs are provided for directory stack handling. |
|
72 | 72 | |
|
73 | 73 | |
|
74 | 74 | Enabled extensions |
|
75 | 75 | ================== |
|
76 | 76 | |
|
77 | 77 | Some extensions, listed below, are enabled as default in this profile. |
|
78 | 78 | |
|
79 | 79 | envpersist |
|
80 | 80 | ---------- |
|
81 | 81 | |
|
82 | 82 | %env can be used to "remember" environment variable manipulations. Examples:: |
|
83 | 83 | |
|
84 | 84 | %env - Show all environment variables |
|
85 | 85 | %env VISUAL=jed - set VISUAL to jed |
|
86 | 86 | %env PATH+=;/foo - append ;foo to PATH |
|
87 | 87 | %env PATH+=;/bar - also append ;bar to PATH |
|
88 | 88 | %env PATH-=/wbin; - prepend /wbin; to PATH |
|
89 | 89 | %env -d VISUAL - forget VISUAL persistent val |
|
90 | 90 | %env -p - print all persistent env modifications |
|
91 | 91 | |
|
92 | 92 | ipy_which |
|
93 | 93 | --------- |
|
94 | 94 | |
|
95 | 95 | %which magic command. Like 'which' in unix, but knows about ipython aliases. |
|
96 | 96 | |
|
97 | 97 | Example:: |
|
98 | 98 | |
|
99 | 99 | [C:/ipython]|14> %which st |
|
100 | 100 | st -> start . |
|
101 | 101 | [C:/ipython]|15> %which d |
|
102 | 102 | d -> dir /w /og /on |
|
103 | 103 | [C:/ipython]|16> %which cp |
|
104 | 104 | cp -> cp |
|
105 | 105 | == c:\bin\cp.exe |
|
106 | 106 | c:\bin\cp.exe |
|
107 | 107 | |
|
108 | 108 | ipy_app_completers |
|
109 | 109 | ------------------ |
|
110 | 110 | |
|
111 | 111 | Custom tab completers for some apps like svn, hg, bzr, apt-get. Try 'apt-get install <TAB>' in debian/ubuntu. |
|
112 | 112 | |
|
113 | 113 | ipy_rehashdir |
|
114 | 114 | ------------- |
|
115 | 115 | |
|
116 | 116 | Allows you to add system command aliases for commands that are not along your path. Let's say that you just installed Putty and want to be able to invoke it without adding it to path, you can create the alias for it with rehashdir:: |
|
117 | 117 | |
|
118 | 118 | [~]|22> cd c:/opt/PuTTY/ |
|
119 | 119 | [c:opt/PuTTY]|23> rehashdir . |
|
120 | 120 | <23> ['pageant', 'plink', 'pscp', 'psftp', 'putty', 'puttygen', 'unins000'] |
|
121 | 121 | |
|
122 | 122 | Now, you can execute any of those commams directly:: |
|
123 | 123 | |
|
124 | 124 | [c:opt/PuTTY]|24> cd |
|
125 | 125 | [~]|25> putty |
|
126 | 126 | |
|
127 | 127 | (the putty window opens). |
|
128 | 128 | |
|
129 | 129 | If you want to store the alias so that it will always be available, do '%store putty'. If you want to %store all these aliases persistently, just do it in a for loop:: |
|
130 | 130 | |
|
131 | 131 | [~]|27> for a in _23: |
|
132 | 132 | |..> %store $a |
|
133 | 133 | |..> |
|
134 | 134 | |..> |
|
135 | 135 | Alias stored: pageant (0, 'c:\\opt\\PuTTY\\pageant.exe') |
|
136 | 136 | Alias stored: plink (0, 'c:\\opt\\PuTTY\\plink.exe') |
|
137 | 137 | Alias stored: pscp (0, 'c:\\opt\\PuTTY\\pscp.exe') |
|
138 | 138 | Alias stored: psftp (0, 'c:\\opt\\PuTTY\\psftp.exe') |
|
139 | 139 | ... |
|
140 | 140 | |
|
141 | mglob | |
|
142 | ----- | |
|
143 | ||
|
144 | Provide the magic function %mglob, which makes it easier (than the 'find' command) to collect (possibly recursive) file lists. Examples:: | |
|
145 | ||
|
146 | [c:/ipython]|9> mglob *.py | |
|
147 | [c:/ipython]|10> mglob *.py rec:*.txt | |
|
148 | [c:/ipython]|19> workfiles = %mglob !.svn/ !.hg/ !*_Data/ !*.bak rec:. | |
|
149 | ||
|
150 | Note that the first 2 calls will put the file list in result history (_, _9, _10), and the last one will assign it to 'workfiles'. | |
|
151 | ||
|
152 | 141 | |
|
153 | 142 | Prompt customization |
|
154 | 143 | ==================== |
|
155 | 144 | |
|
156 | 145 | The sh profile uses the following prompt configurations:: |
|
157 | 146 | |
|
158 | 147 | c.PromptManager.in_template = r'{color.LightGreen}\u@\h{color.LightBlue}[{color.LightCyan}\Y1{color.LightBlue}]{color.Green}|\#> ' |
|
159 | 148 | c.PromptManager.in2_template = r'{color.Green}|{color.LightGreen}\D{color.Green}> ' |
|
160 | 149 | c.PromptManager.out_template = r'<\#> ' |
|
161 | 150 | |
|
162 | 151 | You can change the prompt configuration to your liking by editing |
|
163 | 152 | ipython_config.py. |
|
164 | 153 | |
|
165 | 154 | .. _string_lists: |
|
166 | 155 | |
|
167 | 156 | String lists |
|
168 | 157 | ============ |
|
169 | 158 | |
|
170 | 159 | String lists (IPython.utils.text.SList) are handy way to process output |
|
171 | 160 | from system commands. They are produced by ``var = !cmd`` syntax. |
|
172 | 161 | |
|
173 | 162 | First, we acquire the output of 'ls -l':: |
|
174 | 163 | |
|
175 | 164 | [Q:doc/examples]|2> lines = !ls -l |
|
176 | 165 | == |
|
177 | 166 | ['total 23', |
|
178 | 167 | '-rw-rw-rw- 1 ville None 1163 Sep 30 2006 example-demo.py', |
|
179 | 168 | '-rw-rw-rw- 1 ville None 1927 Sep 30 2006 example-embed-short.py', |
|
180 | 169 | '-rwxrwxrwx 1 ville None 4606 Sep 1 17:15 example-embed.py', |
|
181 | 170 | '-rwxrwxrwx 1 ville None 1017 Sep 30 2006 example-gnuplot.py', |
|
182 | 171 | '-rwxrwxrwx 1 ville None 339 Jun 11 18:01 extension.py', |
|
183 | 172 | '-rwxrwxrwx 1 ville None 113 Dec 20 2006 seteditor.py', |
|
184 | 173 | '-rwxrwxrwx 1 ville None 245 Dec 12 2006 seteditor.pyc'] |
|
185 | 174 | |
|
186 | 175 | Now, let's take a look at the contents of 'lines' (the first number is |
|
187 | 176 | the list element number):: |
|
188 | 177 | |
|
189 | 178 | [Q:doc/examples]|3> lines |
|
190 | 179 | <3> SList (.p, .n, .l, .s, .grep(), .fields() available). Value: |
|
191 | 180 | |
|
192 | 181 | 0: total 23 |
|
193 | 182 | 1: -rw-rw-rw- 1 ville None 1163 Sep 30 2006 example-demo.py |
|
194 | 183 | 2: -rw-rw-rw- 1 ville None 1927 Sep 30 2006 example-embed-short.py |
|
195 | 184 | 3: -rwxrwxrwx 1 ville None 4606 Sep 1 17:15 example-embed.py |
|
196 | 185 | 4: -rwxrwxrwx 1 ville None 1017 Sep 30 2006 example-gnuplot.py |
|
197 | 186 | 5: -rwxrwxrwx 1 ville None 339 Jun 11 18:01 extension.py |
|
198 | 187 | 6: -rwxrwxrwx 1 ville None 113 Dec 20 2006 seteditor.py |
|
199 | 188 | 7: -rwxrwxrwx 1 ville None 245 Dec 12 2006 seteditor.pyc |
|
200 | 189 | |
|
201 | 190 | Now, let's filter out the 'embed' lines:: |
|
202 | 191 | |
|
203 | 192 | [Q:doc/examples]|4> l2 = lines.grep('embed',prune=1) |
|
204 | 193 | [Q:doc/examples]|5> l2 |
|
205 | 194 | <5> SList (.p, .n, .l, .s, .grep(), .fields() available). Value: |
|
206 | 195 | |
|
207 | 196 | 0: total 23 |
|
208 | 197 | 1: -rw-rw-rw- 1 ville None 1163 Sep 30 2006 example-demo.py |
|
209 | 198 | 2: -rwxrwxrwx 1 ville None 1017 Sep 30 2006 example-gnuplot.py |
|
210 | 199 | 3: -rwxrwxrwx 1 ville None 339 Jun 11 18:01 extension.py |
|
211 | 200 | 4: -rwxrwxrwx 1 ville None 113 Dec 20 2006 seteditor.py |
|
212 | 201 | 5: -rwxrwxrwx 1 ville None 245 Dec 12 2006 seteditor.pyc |
|
213 | 202 | |
|
214 | 203 | Now, we want strings having just file names and permissions:: |
|
215 | 204 | |
|
216 | 205 | [Q:doc/examples]|6> l2.fields(8,0) |
|
217 | 206 | <6> SList (.p, .n, .l, .s, .grep(), .fields() available). Value: |
|
218 | 207 | |
|
219 | 208 | 0: total |
|
220 | 209 | 1: example-demo.py -rw-rw-rw- |
|
221 | 210 | 2: example-gnuplot.py -rwxrwxrwx |
|
222 | 211 | 3: extension.py -rwxrwxrwx |
|
223 | 212 | 4: seteditor.py -rwxrwxrwx |
|
224 | 213 | 5: seteditor.pyc -rwxrwxrwx |
|
225 | 214 | |
|
226 | 215 | Note how the line with 'total' does not raise IndexError. |
|
227 | 216 | |
|
228 | 217 | If you want to split these (yielding lists), call fields() without |
|
229 | 218 | arguments:: |
|
230 | 219 | |
|
231 | 220 | [Q:doc/examples]|7> _.fields() |
|
232 | 221 | <7> |
|
233 | 222 | [['total'], |
|
234 | 223 | ['example-demo.py', '-rw-rw-rw-'], |
|
235 | 224 | ['example-gnuplot.py', '-rwxrwxrwx'], |
|
236 | 225 | ['extension.py', '-rwxrwxrwx'], |
|
237 | 226 | ['seteditor.py', '-rwxrwxrwx'], |
|
238 | 227 | ['seteditor.pyc', '-rwxrwxrwx']] |
|
239 | 228 | |
|
240 | 229 | If you want to pass these separated with spaces to a command (typical |
|
241 | 230 | for lists if files), use the .s property:: |
|
242 | 231 | |
|
243 | 232 | |
|
244 | 233 | [Q:doc/examples]|13> files = l2.fields(8).s |
|
245 | 234 | [Q:doc/examples]|14> files |
|
246 | 235 | <14> 'example-demo.py example-gnuplot.py extension.py seteditor.py seteditor.pyc' |
|
247 | 236 | [Q:doc/examples]|15> ls $files |
|
248 | 237 | example-demo.py example-gnuplot.py extension.py seteditor.py seteditor.pyc |
|
249 | 238 | |
|
250 | 239 | SLists are inherited from normal python lists, so every list method is |
|
251 | 240 | available:: |
|
252 | 241 | |
|
253 | 242 | [Q:doc/examples]|21> lines.append('hey') |
|
254 | 243 | |
|
255 | 244 | |
|
256 | 245 | Real world example: remove all files outside version control |
|
257 | 246 | ------------------------------------------------------------ |
|
258 | 247 | |
|
259 | 248 | First, capture output of "hg status":: |
|
260 | 249 | |
|
261 | 250 | [Q:/ipython]|28> out = !hg status |
|
262 | 251 | == |
|
263 | 252 | ['M IPython\\extensions\\ipy_kitcfg.py', |
|
264 | 253 | 'M IPython\\extensions\\ipy_rehashdir.py', |
|
265 | 254 | ... |
|
266 | 255 | '? build\\lib\\IPython\\Debugger.py', |
|
267 | 256 | '? build\\lib\\IPython\\extensions\\InterpreterExec.py', |
|
268 | 257 | '? build\\lib\\IPython\\extensions\\InterpreterPasteInput.py', |
|
269 | 258 | ... |
|
270 | 259 | |
|
271 | 260 | (lines starting with ? are not under version control). |
|
272 | 261 | |
|
273 | 262 | :: |
|
274 | 263 | |
|
275 | 264 | [Q:/ipython]|35> junk = out.grep(r'^\?').fields(1) |
|
276 | 265 | [Q:/ipython]|36> junk |
|
277 | 266 | <36> SList (.p, .n, .l, .s, .grep(), .fields() availab |
|
278 | 267 | ... |
|
279 | 268 | 10: build\bdist.win32\winexe\temp\_ctypes.py |
|
280 | 269 | 11: build\bdist.win32\winexe\temp\_hashlib.py |
|
281 | 270 | 12: build\bdist.win32\winexe\temp\_socket.py |
|
282 | 271 | |
|
283 | 272 | Now we can just remove these files by doing 'rm $junk.s'. |
|
284 | 273 | |
|
285 | 274 | The .s, .n, .p properties |
|
286 | 275 | ------------------------- |
|
287 | 276 | |
|
288 | 277 | The ``.s`` property returns one string where lines are separated by |
|
289 | 278 | single space (for convenient passing to system commands). The ``.n`` |
|
290 | 279 | property return one string where the lines are separated by a newline |
|
291 | 280 | (i.e. the original output of the function). If the items in string |
|
292 | 281 | list are file names, ``.p`` can be used to get a list of "path" objects |
|
293 | 282 | for convenient file manipulation. |
|
294 | 283 |
|
1 | NO CONTENT: file was removed |
|
1 | NO CONTENT: file was removed |
General Comments 0
You need to be logged in to leave comments.
Login now