~ellisonbg/ipython/bugfixes0411409

« back to all changes in this revision

Viewing changes to IPython/Extensions/ipy_profile_sh.py

  • Committer: ville
  • Date: 2008-02-16 09:50:47 UTC
  • mto: (0.12.1 ipython_main)
  • mto: This revision was merged to the branch mainline in revision 990.
  • Revision ID: ville@ville-pc-20080216095047-500x6dluki1iz40o
initialization (no svn history)

Show diffs side-by-side

added added

removed removed

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