SPACES_INSTEAD_OF_TABS = True TABS_WIDTH = 4 sourceview = None styled_languages = [] # keeps track of what languages have already been styled, so i don't repeat my work boolean_tag_property_names = ['bold', 'italic', 'strikethrough', 'underline'] get_tag_properties = lambda lingo, prop: [tag.get_property(prop) for tag in sourceview.Languages.get(lingo, lingo).get_tags()] get_tag_names = lambda lingo: get_tag_properties(sourceview.Languages.get(lingo, lingo), 'name') html_color_to_gdk_color = lambda color: flauxtext.gtk.gdk.Color(*[256 * int(color[i:i+2], 16) for i in range(0, 5, 2)]) gdk_color_to_html_color = lambda color: ''.join([hex(eval('color.' + i)/256)[2:].zfill(2) for i in ['red', 'green', 'blue']]) def set_language_tag_style(lang_name, tag_name, style_str): ''' eg. set_language_tag_style('Python', 'String', 'foreground="#0000ff", italic=True, bold=True') evals style_str as keyword arguments. valid keyword arguments in style_str: foreground # html hex rrggbb color string with optional preceding sharp/pound sign background # html hex rrggbb color string with optional preceding sharp/pound sign bold # boolean italic # boolean strikethrough # boolean underline # boolean ''' try: tag_style = sourceview.Languages[lang_name].get_tag_style(tag_name) tru = true = Tru = True fals = false = Fals = Nil = Null = NULL = nil = nill = null = False # excessive, yes, but makes my lispy fingers happy style = eval('(lambda **kw: kw)(' + style_str + ')', globals(), locals()) # turn the keyword arguments in style_str into a dictionary for prop in boolean_tag_property_names: if prop in style: exec 'tag_style.%s = style["%s"]' % (prop, prop) assert eval('tag_style.' + prop) == style[prop] if 'foreground' in style: tag_style.foreground = html_color_to_gdk_color(style['foreground'].lstrip('#').zfill(6)) assert style['foreground'].lstrip('#') == gdk_color_to_html_color(tag_style.foreground), 'foreground1' if 'background' in style: tag_style.background = html_color_to_gdk_color(style['background'].lstrip('#').zfill(6)) assert style['background'].lstrip('#') == gdk_color_to_html_color(tag_style.background), 'background1' sourceview.Languages[lang_name].set_tag_style(tag_name, tag_style) # now check that my changes stuck s = sourceview.Languages[lang_name].get_tag_style(tag_name) if 'background' in style: assert style['background'].lstrip('#') == gdk_color_to_html_color(s.background), 'background' if 'foreground' in style: assert style['foreground'].lstrip('#') == gdk_color_to_html_color(s.foreground), 'foreground' for prop in boolean_tag_property_names: if prop in style: assert eval('s.' + prop, locals()) == style[prop], prop print 'successfully styled', lang_name, tag_name except Exception, e: print 'badness10000', e, tag_name self.flash_info('unable to style ' + lang_name + ' ' + tag_name, 4e3, 'bad_source_style') def style_language(lang_name): ''' look for lang_name.style in plugindir, calls set_language_tag_style for each meaningful line in $plugin/$lang_name.style ''' fn = flauxtext.os.path.join(flauxtext.plugindir, lang_name + '.style') if flauxtext.os.path.exists(fn): for line in open(fn): if (len(line.strip()) > 0) and not line.lstrip().startswith('#'): line = line.split(':') set_language_tag_style(lang_name, line[0], ':'.join(line[1:])) else: self.flash_info(lang_name + ' has no style file.', 3e3, 'no_style_file') def new_buffer(action=None): ''' adds an empty page to self.notebk, adorns and focuses it. returns the new textbuffer, so you can say ft.new_buffer().set_text(open(fn).read()) also appends a dict to self.buffer_handler_ids mapping event names to handler_ids which can be passed to the "disconnect" method of the indicated widget textview # callback "key-press-event" # capslock_statbar_switch "populate-popup" # populatecontextmenu "expose_event" # line_numbers_expose "drag_data_received" # dnd_received_data textbuffer # callback "insert-text" # registerinsertionwithundo "delete-range" # registerdeletionwithundo "mark-set" # hiliteparens where textview can be gotten with current_textview() or self.notebk.get_nth_page(n).get_child() and textbuffer can be gotten with current_buffer() or textview.get_buffer() ''' pagestokeepunmodified = [] for i in range(self.notebk.get_n_pages()): tabtxt = self.notebk.get_tab_label_text(self.notebk.get_nth_page(i)) if (tabtxt[0] != '*') and (tabtxt[-1] != '*'): pagestokeepunmodified.append(i) # done cacheing state of current buffers, start making a new one handler_ids = {} sw = flauxtext.gtk.ScrolledWindow() sw.set_policy(flauxtext.gtk.POLICY_AUTOMATIC, flauxtext.gtk.POLICY_AUTOMATIC) textbuffer = sourceview.SourceBuffer() textview = sourceview.SourceView(textbuffer) textview.set_wrap_mode(flauxtext.wordwrappref) textview.set_smart_home_end(False) textbuffer.get_all_text = lambda:textbuffer.get_text(textbuffer.get_start_iter(), textbuffer.get_end_iter()) handler_ids["mark-set"] = textbuffer.connect("mark-set", self.hiliteparens) handler_ids["key-press-event"] = textview.connect("key-press-event", self.capslock_statbar_switch) handler_ids["populate-popup"] = textview.connect("populate-popup", self.populatecontextmenu) handler_ids["changed"] = textbuffer.connect("changed", self.autoindent) handler_ids["insert-text"] = textbuffer.connect("insert-text", self.registerwithundo) handler_ids["delete-range"] = textbuffer.connect("delete-range", self.registerwithundo) try: # allow drag-n-dropping stuff on me--like files from explorer.exe----REQUIRES PYGTK 2.6 handler_ids["drag_data_received"] = textview.connect("drag_data_received", self.dnd_received_data) textview.drag_dest_add_uri_targets() except: pass textview.modify_font(flauxtext.pango.FontDescription(flauxtext.font)) found_tag = flauxtext.gtk.TextTag('becky') for kee,val in flauxtext.foundtexttagstyle.items(): try: found_tag.set_property(kee, val) except: print kee, 'is an invalid gtk.TextTag property;', print 'please change "foundtexttagstyle" in config.flauxtext accordingly' textbuffer.tag_table.add(found_tag) for tagnym, styledict in flauxtext.findparenstyle.items(): temptag = flauxtext.gtk.TextTag(tagnym) for kee, val in styledict.items(): try: temptag.set_property(kee, val) except: print kee, 'is an invalid gtk.TextTag property; please change "findparenstyle" in config.flauxtext accordingly' textbuffer.tag_table.add(temptag) if not self.notebk.get_show_tabs(): self.notebk.set_show_tabs(True) textview.set_show_line_numbers(flauxtext.linenums in ['Left', 'Both']) textview.set_insert_spaces_instead_of_tabs(SPACES_INSTEAD_OF_TABS) textview.set_tabs_width(TABS_WIDTH) sw.add(textview) sw.show() textview.show() self.notebk.append_page(sw, flauxtext.gtk.Label(flauxtext.UNTITLED_FILENAME)) textbuffer.undostack = flauxtext.UndoStack() textbuffer.filename = flauxtext.UNTITLED_FILENAME textbuffer.handler_ids = handler_ids self.notebk.set_current_page(self.notebk.page_num(sw)) try: self.actiongroup.get_action('toggle_editable').set_active(True) except: pass # done making a new buffer, change the state of all pages to reflect cache [pagestokeepunmodified] zothbfr = self.notebk.get_nth_page(0).get_child().get_buffer() if ((self.notebk.get_n_pages() == 2) and (self.notebk.get_tab_label_text(self.notebk.get_nth_page(0)) == self[0].filename == flauxtext.UNTITLED_FILENAME) and (zothbfr.get_all_text() == '')): # if you just opened FlauxText and haven't edited the initial textbuffer, i'll remove it self.notebk.remove_page(0) if self.notebk.get_n_pages() > 1: for i in pagestokeepunmodified: pg_i = self.notebk.get_nth_page(i) tab_txt = self.notebk.get_tab_label_text(pg_i) if tab_txt[0] == tab_txt[-1] == '*': self.notebk.set_tab_label_text(pg_i, tab_txt[3:-3]) if flauxtext.tabshideifone and self.notebk.get_n_pages()==1: self.notebk.set_show_tabs(False) if (self.notebk.get_n_pages() > 1) and not self.notebk.get_show_tabs(): self.notebk.set_show_tabs(True) return textbuffer def toggle(*a): ''' toggles current buffer's highlighting. ''' b = self.current_buffer() b.set_highlight(not b.get_highlight()) def set_language(which, lang_name=None): ''' which is which buffer [can be number in range(len(self)), str(number) in range(len(self)), fn in self.all_files(), or None], and it defaults to the current buffer. lang_name is either a key or a value in sourceview.Languages [created in sourcehighlight at the bottom]. examples: set_language('Python') set_language(3, 'Python') set_language('/home/noob/test.py', 'Python') set_language('3', 'Python') ''' if lang_name is None: # first use-case in __doc__ which, lang_name = self.notebk.get_current_page(), which if hasattr(which, 'isdigit') and which.isdigit(): # last use-case in __doc__ which = int(which) b = self[which] if not hasattr(b, 'set_language'): replace_buffer(which) b = self[which] if lang_name not in styled_languages: style_language(lang_name) styled_languages.append(lang_name) b.set_language(sourceview.Languages.get(lang_name, lang_name)) b.set_highlight(True) def __init__(*a): global sourceview if sourceview == None: try: flauxtext.imp0rt('gtksourceview') sourceview = flauxtext.gtksourceview except: try: flauxtext.imp0rt('pysourceview') sourceview = flauxtext.pysourceview except: try: flauxtext.imp0rt('pygtksourceview') sourceview = flauxtext.pygtksourceview except: try: flauxtext.imp0rt('sourceview') sourceview = flauxtext.sourceview except: return False sourceview.Languages = dict([(lingo.get_name(), lingo) for lingo in sourceview.SourceLanguagesManager().get_available_languages()]) for k in sourceview.Languages: sourceview.Languages[k].get_tag_names = lambda: get_tag_names(sourceview.Languages[k]) return True ################################################################################ def sourcehighlight(*a, **kw): if sourceview == None: __init__() if sourceview != None: if len(a) > 0: if a[0] in sourceview.Languages: set_language(a[0]) elif a[0] in globals(): eval(a[0] + '(*a[1:])', globals(), locals())