diff -r d86214c98a9c Lib/idlelib/EditorWindow.py --- a/Lib/idlelib/EditorWindow.py Wed Jun 18 23:07:46 2014 -0400 +++ b/Lib/idlelib/EditorWindow.py Thu Jun 19 18:40:07 2014 +0530 @@ -13,6 +13,7 @@ import webbrowser from idlelib.MultiCall import MultiCallCreator +from idlelib.LineNumber import LineNumberCanvas, Text from idlelib import idlever from idlelib import WindowList from idlelib import SearchDialog @@ -227,6 +228,10 @@ vbar['command'] = text.yview vbar.pack(side=RIGHT, fill=Y) text['yscrollcommand'] = vbar.set + if self.__class__.__name__ != 'PyShell': + self.linenumber_canvas = LineNumberCanvas(text_frame) + self.linenumber_canvas.attach(text=self.text, side=LEFT, fill=Y) + fontWeight = 'normal' if idleConf.GetOption('main', 'EditorWindow', 'font-bold', type='bool'): fontWeight='bold' diff -r d86214c98a9c Lib/idlelib/LineNumber.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Lib/idlelib/LineNumber.py Thu Jun 19 18:40:07 2014 +0530 @@ -0,0 +1,72 @@ +import tkinter as tk + +class LineNumberCanvas(tk.Canvas): + + def __init__(self, *args, **kwargs): + tk.Canvas.__init__(self, *args, **kwargs) + + def attach(self, text, *arg, **kwargs): + self.text = text + self.text.bind('<>', self.re_render) + self.text.bind('', self.re_render) + self.number_of_digits = 0 + self.pack(*arg, **kwargs) + + def detach(self): + pass + + def re_render(self, event): + """Re-render the line canvas""" + self.delete('all') + number_of_digits = len(self.text.index('end').split('.')[0]) + if self.number_of_digits != number_of_digits: + self.number_of_digits = number_of_digits + self['width'] = self.number_of_digits * 8 + + linenum = int(self.text.index('@0,0').split('.')[0]) + while True: + dline = self.text.tk.call(self.text, 'dlineinfo', '%d.0' % linenum) + if not dline: + break + y, height = dline[1], dline[4] + self.create_text( + self['width'], y + height * 0.75, anchor="e", text=linenum) + linenum += 1 + + +class Text(tk.Text): + """ + Modified Text widget to support custom <> virtual event + to be genereated when the following actions take place: + insert, delete, replace, cursor position change and scroll. + The original event is re-generated. + """ + + def __init__(self, *args, **kwargs): + tk.Text.__init__(self, *args, **kwargs) + self.tk.eval(""" + proc widget_interceptor {widget command args} { + + set orig_call [uplevel [linsert $args 0 $command]] + + if { + ([lindex $args 0] == "insert") || + ([lindex $args 0] == "delete") || + ([lindex $args 0] == "replace") || + ([lrange $args 0 2] == {mark set insert}) || + ([lrange $args 0 1] == {xview moveto}) || + ([lrange $args 0 1] == {xview scroll}) || + ([lrange $args 0 1] == {yview moveto}) || + ([lrange $args 0 1] == {yview scroll})} { + + event generate $widget <> -when tail + } + + #return original command + return $orig_call + } + """) + self.tk.eval(""" + rename {widget} new_{widget} + interp alias {{}} ::{widget} {{}} widget_interceptor {widget} new_{widget} + """.format(widget=str(self)))

AltStyle によって変換されたページ (->オリジナル) /