[Idle-dev] IDLE 3000_a2 (fixed non-fatal error in script)

Mr. T rt8396 at gmail.com
Tue Jan 27 18:26:07 CET 2009


See revised code highlighted in yellow!

Proposal:
OK, so the python language has officially moved into the next level. I look
at IDLE and think, hmm great IDE but it could really use a spit shining. So
here is a very simple script showing my ideas to improve IDLE.
Reason for change:
The text widget and the prompt(>>>) should be separated. Trying to write a
conditional in the interactive IDLE is a real pain. Not to mention that when
you copy code from Interactive  IDLE to the IDLE editor window the indention
is eight spaces instead four and you've got that prompt(>>>) stuck in there.
I have a solution for the problem though.

I hope you are using fixed-width font

Lst|<----- Text Widget ---->|
   |                        |
>>>|if this:                |
...|    if that:            |
...|        ...             |
...|    elif that:          |
...|        ...             |
...|    else:               |
...|        ...             |
>>>|                        |
>>>|x = 10                  |
>>>|                        |


Basically you have a Listbox on the left for the prompt and a Text on the
right. Disable the Listbox highlight and key press events and now we have a
very friendly interactive IDLE! No more prompt hijacking your snippets, and
no more eigtht space indention! Hip-Hip-Hooray!

from Tkinter import *
import tkMessageBox as MB

class CMD(Toplevel):
    def __init__(self, master):
        Toplevel.__init__(self, master)
        self.master = master
        self.startidx = '1.0'
        self.backidx = '1.0'
        self.title('IDLE 3000')

        self.listbox = Listbox(self, width=3, relief=FLAT, font=('Courier
New',12), takefocus=0)
        self.listbox.pack(fill=Y, side=LEFT)
        self.listbox.insert(0, '>>>')

        self.text = Text(self, relief=FLAT, spacing3=1, wrap=NONE,
font=('Courier New',12))
        self.text.pack(fill=BOTH, side=LEFT, expand=1)
        self.text.config(width=50, height=20)
        self.text.focus_set()

        self.listbox.bind("<KeyPress>"          , lambda e: "break")
        self.listbox.bind("<Button-1>"          , lambda e: "break")
        self.listbox.bind("<B1-Motion>"         , lambda e: "break")
        self.listbox.bind("<ButtonRelease-1>"   , lambda e: "break")
        self.listbox.bind("<B2-Motion>"         , lambda e: "break")
        self.listbox.bind("<MouseWheel>"        , lambda e: "break")

        self.text.bind('<Next>'         , lambda e: "break")#pageup
        self.text.bind('<Prior>'        , lambda e: "break")#pagedown
        self.text.bind('<Delete>'       , lambda e: "break")
        self.text.bind('<Control-Home>' , lambda e: "break")
        self.text.bind('<Control-End>'  , lambda e: "break")
        self.text.bind("<B2-Motion>"    , lambda e: "break")
        self.text.bind('<Button-2>'     , lambda e: "break")
        self.text.bind("<MouseWheel>"   , lambda e: "break")

        self.text.bind("<Up>"       , self.onUp)
        self.text.bind("<Down>"     , self.onDown)
        self.text.bind("<Tab>"      , self.onTab)
        self.text.bind("<Return>"   , self.onReturn)
        self.text.bind("<BackSpace>", self.onBackSpace)

        self.protocol("WM_DELETE_WINDOW", self.onQuit)
        self.lift(master)
        self.master.withdraw()

    def fix_index(self, chars):
        self.backidx = '%d.0' %(int(self.backidx.split('.')[0])+1)
        self.text.insert(END, '\n')
        self.text.mark_set(INSERT, END)
        self.text.see(INSERT)
        self.listbox.insert(END, chars)
        self.listbox.see(self.listbox.size())

    def onQuit(self):
        self.grab_release()
        self.master.destroy()

    def onTab(self, event=None):
        curline, cursor = self.text.index(INSERT).split('.')[0]+'.0',
self.text.index(INSERT)
        self.text.insert(INSERT, '    ')
        return "break"

    def onDown(self, event):
        i = self.text.index(INSERT+'+1l') #;print 'New index: ', i
        self.text.mark_set(INSERT, i)
        self.text.see(i)
        self.listbox.see(int(i.split('.')[0])-1)
        return "break"

    def onUp(self, event=None):
        i = self.text.index(INSERT+'-1l') #;print 'New index: ', i
        self.text.mark_set(INSERT, i)
        self.text.see(i)
        self.listbox.see(int(i.split('.')[0])-1)
        return "break"

    def onBackSpace(self, event=None):
        if self.text.compare(self.text.index(INSERT), '!=', self.backidx):
            self.text.delete(self.text.index(INSERT+'-1c'))
        return "break"

    def onReturn(self, event=None):
        curline, cursor = self.text.index(INSERT).split('.')[0]+'.0',
self.text.index(INSERT)
        text = self.text.get(self.startidx, END).strip()
        if self.text.compare(curline, '<', self.startidx):#'Out Of Zone'
            self.text.mark_set(INSERT, END+'-1c')
            self.text.see(INSERT)
            self.listbox.see(END)
        elif '.0' in cursor: #nothing typed on this line, try to exec
command
            cmd = text.rstrip('\n')
            try:
                exec(cmd)
            except:
                self.master.bell()
                print '%s\n%s\n%s' %(sys.exc_traceback, sys.exc_type,
sys.exc_value)
            finally:
                self.fix_index('>>>')
                self.startidx = self.text.index(INSERT)
        elif text != '':#something typed
            self.fix_index('...')
        else: #insert newline
            self.fix_index('>>>')
        return "break"


if __name__ == '__main__':
    print 'main'
    root = Tk()

    MB.showinfo('IDLE 3000 Introduction','''
This Demo shows how i think the standard IDLE should behave.
You will notice the prompt is outside of the text widget. This
keeps the prompt from hijacking your code snippits when you
copy-paste to the main editor window. This also keeps all indention
at the Python recommended four spaces.

Please note this demo is to only show the layout, it does not include
syntax highlight, auto-tab, auto-dedent, or any other feature. This is
not even the correct way to write a good editor. My only intention is to
show a more user friendly layout

have fun :)
''')
    cmd = CMD(root)
    root.mainloop()



Issue #2:
When you press MMB and there is a highlighted selection in the text it gets
pasted over and over again @ the insertion cursor. This can be aggravating,
and turn a clean script into a bowl of "Cheerios" breakfast cereal in no
time.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/idle-dev/attachments/20090127/06df9ad6/attachment-0001.htm>


More information about the IDLE-dev mailing list