def __init__(self, parent, filename): "Configure tags and feed file to parser." uwide = idleConf.GetOption('main', 'EditorWindow', 'width', type='int') uhigh = idleConf.GetOption('main', 'EditorWindow', 'height', type='int') uhigh = 3 * uhigh // 4 # Lines average 4/3 of editor line height. Text.__init__(self, parent, wrap='word', highlightthickness=0, padx=5, borderwidth=0, width=uwide, height=uhigh) normalfont = self.findfont(['TkDefaultFont', 'arial', 'helvetica']) fixedfont = self.findfont(['TkFixedFont', 'monaco', 'courier']) self['font'] = (normalfont, 12) self.tag_configure('em', font=(normalfont, 12, 'italic')) self.tag_configure('h1', font=(normalfont, 20, 'bold')) self.tag_configure('h2', font=(normalfont, 18, 'bold')) self.tag_configure('h3', font=(normalfont, 15, 'bold')) self.tag_configure('pre', font=(fixedfont, 12), background='#f6f6ff') self.tag_configure('preblock', font=(fixedfont, 10), lmargin1=25, borderwidth=1, relief='solid', background='#eeffcc') self.tag_configure('l1', lmargin1=25, lmargin2=25) self.tag_configure('l2', lmargin1=50, lmargin2=50) self.tag_configure('l3', lmargin1=75, lmargin2=75) self.tag_configure('l4', lmargin1=100, lmargin2=100) self.parser = HelpParser(self) with open(filename, encoding='utf-8') as f: contents = f.read() self.parser.feed(contents) self['state'] = 'disabled'
def altered_idle_config(): """ Inject the appropriate font settings into the idle config file. Note that this will ignore any specific config files (eg, config-unix.cfg). It's very unlikely that students will be using these. """ from idlelib.config import idleConf # save originals font_name = idleConf.GetOption('main', 'EditorWindow', 'font-name') font_size = idleConf.GetOption('main', 'EditorWindow', 'font-size') # replace them name, size, _ = map(str, FIXED_FONT) idleConf.SetOption('main', 'EditorWindow', 'font-name', name) idleConf.SetOption('main', 'EditorWindow', 'font-size', size) # save the config file idleConf.SaveUserCfgFiles() yield # replace the values if font_name is not None: idleConf.SetOption('main', 'EditorWindow', 'font-name', font_name) if font_size is not None: idleConf.SetOption('main', 'EditorWindow', 'font-size', font_size) if font_name is not None or font_size is not None: idleConf.SaveUserCfgFiles()
def __init__(self, master=None, **kwargs): """ Initializer. Get default settings from user's IDLE configuration. """ currentTheme = idleConf.CurrentTheme() textcf = { 'padx': 5, 'wrap': 'word', 'undo': 'True', 'foreground': idleConf.GetHighlight( currentTheme, 'normal', fgBg='fg'), 'background': idleConf.GetHighlight( currentTheme, 'normal', fgBg='bg'), 'highlightcolor': idleConf.GetHighlight( currentTheme, 'hilite', fgBg='fg'), 'highlightbackground': idleConf.GetHighlight( currentTheme, 'hilite', fgBg='bg'), 'insertbackground': idleConf.GetHighlight( currentTheme, 'cursor', fgBg='fg'), 'width': idleConf.GetOption('main', 'EditorWindow', 'width'), 'height': idleConf.GetOption('main', 'EditorWindow', 'height'), } fontWeight = 'normal' if idleConf.GetOption('main', 'EditorWindow', 'font-bold', type='bool'): fontWeight = 'bold' textcf['font'] = (idleConf.GetOption('main', 'EditorWindow', 'font'), idleConf.GetOption('main', 'EditorWindow', 'font-size'), fontWeight) # override defaults with any user-specified settings textcf.update(kwargs) ScrolledText.__init__(self, master, **textcf)
def _initialize_config(self, Theme): """Fix idleConf.GetHighlight method for different Python releases.""" config = { 'padx': 5, 'wrap': 'word', 'undo': 'True', 'width': idleConf.GetOption('main', 'EditorWindow', 'width'), 'height': idleConf.GetOption('main', 'EditorWindow', 'height'), } if PYTHON_VERSION >= (3, 7, 4): # T241216 config['foreground'] = idleConf.GetHighlight( Theme, 'normal')['foreground'] config['background'] = idleConf.GetHighlight( Theme, 'normal')['background'] config['highlightcolor'] = idleConf.GetHighlight( Theme, 'hilite')['foreground'] config['highlightbackground'] = idleConf.GetHighlight( Theme, 'hilite')['background'] config['insertbackground'] = idleConf.GetHighlight( Theme, 'cursor')['foreground'] else: config['foreground'] = idleConf.GetHighlight( Theme, 'normal', fgBg='fg') config['background'] = idleConf.GetHighlight( Theme, 'normal', fgBg='bg') config['highlightcolor'] = idleConf.GetHighlight( Theme, 'hilite', fgBg='fg') config['highlightbackground'] = idleConf.GetHighlight( Theme, 'hilite', fgBg='bg') config['insertbackground'] = idleConf.GetHighlight( Theme, 'cursor', fgBg='fg') return config
def reload(cls): cls.STYLE = idleConf.GetOption( 'extensions','ParenMatch','style', default='opener') cls.FLASH_DELAY = idleConf.GetOption( 'extensions','ParenMatch','flash-delay', type='int',default=500) cls.BELL = idleConf.GetOption( 'extensions','ParenMatch','bell', type='bool', default=1) cls.HILITE_CONFIG = idleConf.GetHighlight(idleConf.CurrentTheme(), 'hilite')
def create_linenumbers(self): """ Create the widget for displaying line numbers. """ colors = idleConf.GetHighlight(idleConf.CurrentTheme(), 'stdout') editwin = self.editwin text = self.text text_frame = editwin.text_frame self.textln = textln = Text(text_frame, bg=colors['background'], fg=colors['foreground'], width=self.width, height=1, wrap=NONE, highlightthickness=0) # adjust font textln.config( font=(idleConf.GetOption('main', 'EditorWindow', 'font'), idleConf.GetOption('main', 'EditorWindow', 'font-size'))) textln.bind("<FocusIn>", self.focus_in_event) textln.bind('<Button-1>', self.button_ignore) textln.bind('<Button-2>', self.button_ignore) textln.bind('<Button-3>', self.button_ignore) textln.bind('<B1-Motion>', self.button_ignore) textln.bind('<B2-Motion>', self.button_ignore) textln.bind('<B3-Motion>', self.button_ignore) textln.bind("<Button-4>", self.button4) textln.bind("<Button-5>", self.button5) textln.tag_config('LINE', justify=RIGHT) textln.insert(END, '1') textln.tag_add('LINE', '1.0', END) # start the line numbers self.per = per = Percolator(textln) self.line_delegator = LineDelegator() per.insertfilter(self.line_delegator) textln._insert = self.line_delegator.delegate.insert textln._delete = self.line_delegator.delegate.delete lines = LineNumberDelegator(self) if _AFTER_UNDO: # idlelib.percolator's .insertfilter should have an # "after=" argument lines.setdelegate(editwin.undo.delegate) editwin.undo.setdelegate(lines) else: editwin.per.insertfilter(lines) editwin.vbar['command'] = self.vbar_split editwin.text['yscrollcommand'] = self.yscroll_split
def print_window(self, event): confirm = tkMessageBox.askokcancel(title="Print", message="Print to Default Printer", default=tkMessageBox.OK, parent=self.text) if not confirm: self.text.focus_set() return "break" tempfilename = None saved = self.get_saved() if saved: filename = self.filename # shell undo is reset after every prompt, looks saved, probably isn't if not saved or filename is None: (tfd, tempfilename) = tempfile.mkstemp(prefix='IDLE_tmp_') filename = tempfilename os.close(tfd) if not self.writefile(tempfilename): os.unlink(tempfilename) return "break" platform = os.name printPlatform = True if platform == 'posix': #posix platform command = idleConf.GetOption('main', 'General', 'print-command-posix') command = command + " 2>&1" elif platform == 'nt': #win32 platform command = idleConf.GetOption('main', 'General', 'print-command-win') else: #no printing for this platform printPlatform = False if printPlatform: #we can try to print for this platform command = command % shlex.quote(filename) pipe = os.popen(command, "r") # things can get ugly on NT if there is no printer available. output = pipe.read().strip() status = pipe.close() if status: output = "Printing failed (exit status 0x%x)\n" % \ status + output if output: output = "Printing command: %s\n" % repr(command) + output tkMessageBox.showerror("Print status", output, parent=self.text) else: #no printing for this platform message = "Printing is not enabled for this platform: %s" % platform tkMessageBox.showinfo("Print status", message, parent=self.text) if tempfilename: os.unlink(tempfilename) return "break"
def print_window(self, event): confirm = tkMessageBox.askokcancel(title='Print', message= 'Print to Default Printer', default=tkMessageBox.OK, parent= self.text) if not confirm: self.text.focus_set() return 'break' tempfilename = None saved = self.get_saved() if saved: filename = self.filename if not saved or filename is None: tfd, tempfilename = tempfile.mkstemp(prefix='IDLE_tmp_') filename = tempfilename os.close(tfd) if not self.writefile(tempfilename): os.unlink(tempfilename) return 'break' platform = os.name printPlatform = True if platform == 'posix': command = idleConf.GetOption('main', 'General', 'print-command-posix') command = command + ' 2>&1' elif platform == 'nt': command = idleConf.GetOption('main', 'General', 'print-command-win' ) else: printPlatform = False if printPlatform: command = command % shlex.quote(filename) pipe = os.popen(command, 'r') output = pipe.read().strip() status = pipe.close() if status: output = ('Printing failed (exit status 0x%x)\n' % status + output) if output: output = 'Printing command: %s\n' % repr(command) + output tkMessageBox.showerror('Print status', output, parent=self.text ) else: message = ('Printing is not enabled for this platform: %s' % platform) tkMessageBox.showinfo('Print status', message, parent=self.text) if tempfilename: os.unlink(tempfilename) return 'break'
def test_init(self): self.assertIs(self.history.text, self.text) self.assertEqual(self.history.history, []) self.assertIsNone(self.history.prefix) self.assertIsNone(self.history.pointer) self.assertEqual(self.history.cyclic, idleConf.GetOption('main', 'History', 'cyclic', 1, 'bool'))
def reload(cls): cls.context_depth = idleConf.GetOption("extensions", "CodeContext", "numlines", type="int", default=3) cls.bgcolor = idleConf.GetOption("extensions", "CodeContext", "bgcolor", type="str", default="LightGray") cls.fgcolor = idleConf.GetOption("extensions", "CodeContext", "fgcolor", type="str", default="Black")
def getfilename(self): """Get source filename. If not saved, offer to save (or create) file The debugger requires a source file. Make sure there is one, and that the current version of the source buffer has been saved. If the user declines to save or cancels the Save As dialog, return None. If the user has configured IDLE for Autosave, the file will be silently saved if it already exists and is dirty. """ filename = self.editwin.io.filename if not self.editwin.get_saved(): autosave = idleConf.GetOption('main', 'General', 'autosave', type='bool') if autosave and filename: self.editwin.io.save(None) else: confirm = self.ask_save_dialog() self.editwin.text.focus_set() if confirm: self.editwin.io.save(None) filename = self.editwin.io.filename else: filename = None return filename
def reload(cls): "Load class variables from config." cls.context_depth = idleConf.GetOption("extensions", "CodeContext", "maxlines", type="int", default=15)
def load_idlex_extensions(self, userExt=None): """ Load extensions. Returns number of extensions loaded. """ if userExt is None: userExt = self.IDLEX_EXTENSIONS # get already-saved settings d = idleConf.GetUserCfgDir() usercfgfile = os.path.join(d, 'idlex-config-extensions.cfg') if os.path.isfile(usercfgfile): U = open(usercfgfile).read() else: U = '' count = 0 userConfParser = make_config_parser(U) key_isdefault = idleConf.GetOption('main', 'Keys', 'default', type="bool") for extName in userExt: if self.reload_cfg(extName): count += 1 # transfer already-saved settings, otherwise IDLE forgets them # when idleConf.SaveUserCfgFiles is called from within IDLE. Bug? self.transfer_cfg(extName, userConfParser, keys=not key_isdefault ) # Overwrite defaults with user config idleConf.SaveUserCfgFiles() return count
def reload(cls): "Load class variables from config." cls.context_depth = idleConf.GetOption("extensions", "CodeContext", "maxlines", type="int", default=15) cls.colors = idleConf.GetHighlight(idleConf.CurrentTheme(), 'context')
def test_init(self): self.assertIs(self.history.text, self.text) self.assertEqual(self.history.history, []) self.assertIsNone(self.history.prefix) self.assertIsNone(self.history.pointer) self.assertEqual( self.history.cyclic, idleConf.GetOption("main", "History", "cyclic", 1, "bool"))
def reload(cls): """Load class variables from config.""" cls.auto_squeeze_min_lines = idleConf.GetOption( "main", "PyShell", "auto-squeeze-min-lines", type="int", default=50, )
def __init__(self, master=None, **kwargs): """ Initializer. Get default settings from user's IDLE configuration. """ textcf = self._initialize_config(idleConf.CurrentTheme()) if idleConf.GetOption('main', 'EditorWindow', 'font-bold', type='bool'): font_weight = 'bold' else: font_weight = 'normal' textcf['font'] = (idleConf.GetOption('main', 'EditorWindow', 'font'), idleConf.GetOption('main', 'EditorWindow', 'font-size'), font_weight) # override defaults with any user-specified settings textcf.update(kwargs) super().__init__(master, **textcf)
def __init__(self, editwin): self._MAX_NUM_OF_LINES = idleConf.GetOption("extensions", "Squeezer", "max-num-of-lines", type="int", default=30) self._PREVIEW_COMMAND = idleConf.GetOption( "extensions", "Squeezer", "preview-command-" + {"nt": "win"}.get(os.name, os.name), default="", raw=True) self.editwin = editwin self.text = text = editwin.text self.expandingbuttons = [] if isinstance(editwin, PyShell): # If we get a PyShell instance, replace its write method with a # wrapper, which inserts an ExpandingButton instead of a long text. def mywrite(s, tags=(), write=editwin.write): if tags != "stdout": return write(s, tags) else: numoflines = self.count_lines(s) if numoflines < self._MAX_NUM_OF_LINES: return write(s, tags) else: expandingbutton = ExpandingButton( s, tags, numoflines, self) text.mark_gravity("iomark", Tkinter.RIGHT) text.window_create("iomark", window=expandingbutton, padx=2, pady=5) text.see("iomark") text.update() text.mark_gravity("iomark", Tkinter.LEFT) self.expandingbuttons.append(expandingbutton) editwin.write = mywrite
def build_subprocess_arglist(self): assert self.port != 0, 'Socket should have been assigned a port number.' w = [('-W' + s) for s in sys.warnoptions] del_exitf = idleConf.GetOption('main', 'General', 'delete-exitfunc', default=False, type='bool') if __name__ == 'idlelib.pyshell': command = "__import__('idlelib.run').run.main(%r)" % (del_exitf, ) else: command = "__import__('run').main(%r)" % (del_exitf, ) return [sys.executable] + w + ['-c', command, str(self.port)]
def reload(cls): """Load class variables from config.""" cls.auto_squeeze_min_lines = idleConf.GetOption( "main", "PyShell", "auto-squeeze-min-lines", type="int", default=50, ) # Loading the font info requires a Tk root. IDLE doesn't rely # on Tkinter's "default root", so the instance will reload # font info using its editor windows's Tk root. if cls._instance_weakref is not None: instance = cls._instance_weakref() if instance is not None: instance.load_font()
def set_subcode_colors(self): # This is a HACK to allow for sane coloring with other # color themes. Patches are welcome! from . import SubCode theme = idleConf.GetOption('main', 'Theme', 'name') normal_colors = idleConf.GetHighlight(theme, 'normal') background = normal_colors['background'] def rgb_h2d(c): # Take a '#RRGGBB' and convert to integer tuple R = c[1:3] G = c[3:5] B = c[5:7] return tuple([int(x, 16) for x in (R, G, B)]) def rgb_d2h(c): # (R, B, G) -> '#RRGGBB' c = [min((255, int(x))) for x in c] c = [max((0, int(x))) for x in c] return '#%02X%02X%02X' % tuple(c) def colorhack(rgb, target): # apply some DC offset and "gamma" correction R, G, B = map(float, rgb) mR, mG, mB = target m = lambda x, y: (x + y[0])**y[1] if x < 128 else (x - y[0])**( 1 / y[1]) R = m(R, mR) G = m(G, mG) B = m(B, mB) return (R, G, B) def average(a, b): return [(x[0] + x[1]) / 2.0 for x in zip(a, b)] BACK = rgb_h2d(background) a = (10, 1.03) SubCode.SUBCODE_BACKGROUND = rgb_d2h(colorhack(BACK, (a, a, a))) a = (10, 1.019) b = (10, .98) c = colorhack(BACK, (a, b, a)) HL = rgb_d2h(c) SubCode.SUBCODE_HIGHLIGHT = HL d = average(BACK, c) SubCode.SUBCODE_HIGHLIGHT_OUT = rgb_d2h(d) self.tag_config('ACTIVE', background=SUBCODE_HIGHLIGHT)
def init_pyshell(self): if not PyShell.use_subprocess: print('EventLoop.py only works with a subprocess.') return EventLoop.shell_instance = self # set class variable - it is singleton anyways self.is_shell = True text = self.text = self.editwin.text text.bind('<<eventloop-toggle>>', self.eventloop_toggle) self.after_id = None self.delay_id = None self.install_socket = None self.active = False self.active = idleConf.GetOption("extensions", "EventLoop", "active", type="bool", default=True) self.kit = idleConf.GetOption("extensions", "EventLoop", "toolkit", type="raw", default="TK") if self.kit == 'CUSTOM': self.active = False # avoid needless startup message self.init_status_bar() for menu, event, kit_id in EventLoop.TOOLKITS: text.bind(event, lambda ev, kit=kit_id: self.use_kit(kit)) self.use_kit(self.kit, install=False) self.eventloop_enable(self.active)
def toggle(self, ev=None): """ Toggle the selected extension's enable status """ sel = self.get_sel() if sel is None: return item = self.extensions[sel] en = not idleConf.GetOption( 'extensions', item, 'enable', type='bool', default=True) en = int(en) idleConf.SetOption('extensions', item, 'enable', '%s' % en) idleConf.SaveUserCfgFiles() self.repopulate_list() self.restart = True
def config_colors(self): if COLOR_ADAPT: try: self.set_subcode_colors() except Exception as err: print('color_adapt', err) font = (idleConf.GetOption('main', 'EditorWindow', 'font'), idleConf.GetOption('main', 'EditorWindow', 'font-size'), 'bold') self.tagdefs['SUBCODE'] = self.tagdefs['COMMENT'].copy() self.tagdefs['SUBCODE'].update({ 'background': SUBCODE_BACKGROUND, 'font': font, }) self.tagdefs['MAYBESUBCODE'] = self.tagdefs['COMMENT'] ColorDelegator.config_colors(self) self.tag_raise('SUBCODE') self.tag_raise('sel') # 2011-12-29 - bug fix for highlighting
def __init__(self, editwin): self.editwin = editwin self.text = self.editwin.text self.textfont = None self.width = 2 self.after_id = None self.create_linenumbers() e = idleConf.GetOption("extensions", "LineNumbers", "visible", type="bool", default=True) self.set_visible(e)
def __init__(self, text): '''Initialize data attributes and bind event methods. .text - Idle wrapper of tk Text widget, with .bell(). .history - source statements, possibly with multiple lines. .prefix - source already entered at prompt; filters history list. .pointer - index into history. .cyclic - wrap around history list (or not). ''' self.text = text self.history = [] self.prefix = None self.pointer = None self.cyclic = idleConf.GetOption("main", "History", "cyclic", 1, "bool") text.bind("<<history-previous>>", self.history_prev) text.bind("<<history-next>>", self.history_next)
def __init__(self, editwin): if not isinstance(editwin, PyShell.PyShell): print('Not a PyShell instance - not running Persistent History') self.close = lambda *args, **kwargs: None return self.editwin = editwin self.text = text = editwin.text self.history = None self.text.bind('<<history-clear>>', self.history_clear_event) self.keep = idleConf.GetOption('extensions', 'PersistentHistory', 'keep', type='int', default=500) self.delay_init()
def __init__(self, editwin): self.editwin = editwin self.text = editwin.text self.textfont = self.text['font'] self.label = None self.info = [(0, -1, '', False)] self.topvisible = 1 visible = idleConf.GetOption('extensions', 'CodeContext', 'visible', type='bool', default=False) if visible: self.toggle_code_context_event() self.editwin.setvar('<<toggle-code-context>>', True) self.text.after(UPDATEINTERVAL, self.timer_event) self.text.after(FONTUPDATEINTERVAL, self.font_timer_event)
def format_paragraph_event(self, event, limit=None): """Formats paragraph to a max width specified in idleConf. If text is selected, format_paragraph_event will start breaking lines at the max width, starting from the beginning selection. If no text is selected, format_paragraph_event uses the current cursor location to determine the paragraph (lines of text surrounded by blank lines) and formats it. The length limit parameter is for testing with a known value. """ if limit is None: # The default length limit is that defined by pep8 limit = idleConf.GetOption('extensions', 'FormatParagraph', 'max-width', type='int', default=72) text = self.editwin.text first, last = self.editwin.get_selection_indices() if first and last: data = text.get(first, last) comment_header = get_comment_header(data) else: first, last, comment_header, data = \ find_paragraph(text, text.index("insert")) if comment_header: newdata = reformat_comment(data, limit, comment_header) else: newdata = reformat_paragraph(data, limit) text.tag_remove("sel", "1.0", "end") if newdata != data: text.mark_set("insert", first) text.undo_block_start() text.delete(first, last) text.insert(first, newdata) text.undo_block_stop() else: text.mark_set("insert", last) text.see("insert") return "break"
def __init__(self, editwin): self.editwin = editwin self.text = self.editwin.text self.enabled = idleConf.GetOption("extensions", "Terminal", "terminal", type="bool", default=True) self.editwin.setvar("<<terminal-toggle>>", not not self.enabled) # this extension is loaded from idlelib.editor, but before # idlelib.pyshell makes its changes. Will use tk .after to make # changes self.last_insert = 'end-1c' if self.enabled: self.text.after(10, self.delay_init)