Exemple #1
0
class EditorMain(object):
    def __init__(self):
        self.root = tk.Tk(className="PyNestML IDE")
        self.after_id = None

        self.text_frame = tk.Frame(self.root,
                                   width=self.root.winfo_screenwidth(),
                                   height=self.root.winfo_screenheight() *
                                   0.70)
        self.text_frame.pack_propagate(False)
        self.textPad = ScrolledText(self.text_frame,
                                    height=1,
                                    width=1,
                                    undo=True)
        self.textPad.pack(side="top", fill="both", expand=True)
        self.text_frame.pack(side="top", fill="both", expand=True)

        self.line_nr_frame = tk.Frame(self.root,
                                      width=self.root.winfo_screenwidth())
        self.line_nr_frame.pack_propagate(False)
        self.line_nr = tk.Text(self.root,
                               width=self.root.winfo_screenwidth(),
                               height=1)
        self.line_nr.pack(side="top", fill="both", expand=True)
        self.line_nr_frame.pack(side="top", fill="both", expand=True)

        self.console_frame = tk.Frame(self.root,
                                      width=self.root.winfo_screenwidth(),
                                      height=self.root.winfo_screenheight() *
                                      0.20)
        self.console_frame.pack_propagate(False)
        self.console = ScrolledText(self.console_frame, width=1, height=1)
        self.console.pack(side="top", fill="both", expand=True)
        self.console_frame.pack(side="top", fill="both", expand=True)

        self.menu = Menu(root=self.root, text_pad=self.textPad, editor=self)
        self.highlighter = Highlighter(self.textPad, self)

        # insert empty model
        self.textPad.insert('1.0', 'PyNestML             \n')
        self.textPad.insert('2.0', '         Model       \n')
        self.textPad.insert('3.0', '               Editor\n')
        self.textPad.tag_add("l1", "%s.%s" % (1, 0),
                             "%s.%s" % (1, len('PyNestML')))
        self.textPad.tag_add("l2", "%s.%s" % (2, 0),
                             "%s.%s" % (2, len('         Model')))
        self.textPad.tag_add("l3", "%s.%s" % (3, 0),
                             "%s.%s" % (3, len('               Editor')))
        self.textPad.tag_config("l1", background="white", foreground="blue")
        self.textPad.tag_config("l2", background="white", foreground="red")
        self.textPad.tag_config("l3", background="white", foreground="green")
        self.last = self.textPad.get('0.0', tk.END)
        # insert start position of cursor
        self.console.pack(side=tk.BOTTOM)
        self.console.configure(state='disabled')
        self.line_nr.insert('1.0', 'Position: 0:0')
        self.line_nr.configure(state='disabled')
        # bind keys
        self.bind_keys()
        self.root.mainloop()

    def change_button_state(self, active=True):
        if not active:
            self.menu.modelmenu.entryconfig('Check CoCos', state=tk.DISABLED)
            self.menu.modelmenu.entryconfig('Compile Model', state=tk.DISABLED)
        else:
            self.menu.modelmenu.entryconfig('Check CoCos', state=tk.NORMAL)
            self.menu.modelmenu.entryconfig('Compile Model', state=tk.NORMAL)

    def exit_editor(self, _):
        self.menu.exit_command()

    def store_command(self, _):
        self.menu.save_command()

    def check_model(self):
        self.change_button_state(False)
        thread = threading.Thread(target=self.check_model_in_separate_thread)
        thread.start()
        return thread  # returns immediately after the thread starts

    def check_model_in_separate_thread(self):
        self.textPad.configure(state='disabled')
        ModelChecker.check_model_with_cocos(self.textPad.get('0.0', tk.END))
        self.report_findings()
        self.textPad.configure(state='normal')

    def check_syntax_in_separate_thread(self):
        ModelChecker.check_model_syntax(self.textPad.get('0.0', tk.END))
        self.report_findings()

    def check_model_syntax(self, _):
        self.update_line_number()
        # cancel the old job
        if self.after_id is not None:
            self.textPad.after_cancel(self.after_id)

        # create a new job
        self.after_id = self.textPad.after(800, self.do_check_model_syntax)

    def do_check_model_syntax(self):
        if self.textPad.get('0.0', tk.END) != self.last:
            if self.last is None or "".join(
                    self.textPad.get('0.0', tk.END).split()) != "".join(
                        self.last.split()):
                thread = threading.Thread(
                    target=self.check_syntax_in_separate_thread)
                thread.start()
                self.last = self.textPad.get('0.0', tk.END)
                return thread  # returns immediately after the thread starts

    def update_line_number(self):
        self.line_nr.configure(state='normal')
        self.line_nr.delete('1.0', tk.END)
        pos = self.textPad.index(tk.INSERT).split('.')
        self.line_nr.insert('1.0', 'Position: %s:%s' % (pos[0], pos[1]))
        self.line_nr.configure(state='disabled')

    def report_findings(self):
        # print('process complete!')
        self.highlighter.process_report()
        self.change_button_state(True)

    def bind_keys(self):
        # bind the events
        self.textPad.bind('<Control-q>', self.exit_editor)
        self.textPad.bind('<KeyRelease>', self.check_model_syntax)
        self.textPad.bind('<Control-s>', self.store_command)

    def clear_console(self):
        self.console.delete('1.0', tk.END)

    def report(self, text):
        if self.menu.show_syntax_errors_var.get() == 1:
            self.console.configure(state='normal')
            self.console.insert(tk.END, text + '\n')
            self.console.configure(state='disabled')

    def inc_font_size(self):
        f = tkFont.Font(self.textPad, self.textPad.cget('font'))
        self.textPad.configure(font=("Courier", f.configure()['size'] + 1))

    def dec_font_size(self):
        f = tkFont.Font(self.textPad, self.textPad.cget('font'))
        if not f.configure()['size'] - 1 < 4:
            self.textPad.configure(font=("Courier", f.configure()['size'] - 1))
Exemple #2
0
class TkApp(tk.Tk):
    def __init__(self, className=" TextMate"):
        tk.Tk.__init__(self, className=className)
        self.textPad = ScrolledText(self, width=50, height=30, font=("Monospace Regular", 13), highlightthickness=0, bd=4, undo="True")
        self.iconbitmap(r'te.ico')
        self.textPad.pack()

        menu = tk.Menu(self)
        self.textPad.tag_config("bt", background="yellow")
        self.textPad.tag_config("kw", foreground="medium sea green")
        self.textPad.tag_config("com", foreground="red")
        self.textPad.tag_config("str", foreground="purple")
        self.config(menu=menu)
                      
        filemenu = tk.Menu(menu)
        menu.add_cascade(label="File", menu=filemenu)
        filemenu.add_command(label="New File", command=self.new_command, accelerator="Ctrl+N")
        self.bind_all("<Control-n>",self.new_command)
        filemenu.add_command(label="Open", command=self.open_command, accelerator="Ctrl+O")
        self.bind_all("<Control-o>",self.open_command)
        filemenu.add_separator()
        filemenu.add_command(label="Save", command=self.save_command, accelerator="Ctrl+S")
        self.bind_all("<Control-s>",self.save_command)
        filemenu.add_command(label="Save As", command=self.saveas_command, accelerator="Ctrl+Shift+S")
        self.bind_all("<Control-Shift-S>",self.saveas_command)
        filemenu.add_separator()
        filemenu.add_command(label="Exit", command=self.exit_command, accelerator="Ctrl+Q")
        self.bind_all("<Control-q>",self.exit_command)

        editmenu=tk.Menu(menu)
        menu.add_cascade(label="Edit", menu=editmenu)
        editmenu.add_command(label="Undo", command=self.undo_command, accelerator="Ctrl+Z")
        editmenu.add_command(label="Redo", command=self.redo_command, accelerator="Ctrl+Shift+Z")
        self.bind_all("<Control-Shift-Z>",self.redo_command)
        editmenu.add_separator()
        editmenu.add_command(label="Cut", command=self.cut_command, accelerator="Ctrl+X")
        editmenu.add_command(label="Copy", command=self.copy_command, accelerator="Ctrl+C")
        editmenu.add_command(label="Paste", command=self.paste_command, accelerator="Ctrl+V")
        editmenu.add_separator()
        editmenu.add_command(label="Select All", command=self.selectall_command, accelerator="Ctrl+A")
        self.bind_all("<Control-a>",self.selectall_command)
        editmenu.add_command(label="Delete All", command=self.deleteall_command, accelerator="Ctrl+D")
        self.bind_all("<Control-d>",self.deleteall_command)

        formatmenu = tk.Menu(menu)
        menu.add_cascade(label="Format", menu=formatmenu)
        formatmenu.add_command(label="Font", command=self.font_command, accelerator="Ctrl+M")
        self.bind_all("<Control-m>",self.font_command)
        formatmenu.add_separator()
        formatmenu.add_command(label="Bold", command=self.bold_command, accelerator="Ctrl+B")
        self.bind_all("<Control-b>",self.bold_command)
        formatmenu.add_command(label="Italics", command=self.italic_command, accelerator="Ctrl+I")
        self.bind_all("<Control-i>",self.italic_command)
        formatmenu.add_command(label="Underline", command=self.underline_command, accelerator="Ctrl+U")
        self.bind_all("<Control-u>",self.underline_command)
        formatmenu.add_command(label="Bold-Italic", command=self.bolditalic_command)
        
        preferences = tk.Menu(menu)
        menu.add_cascade(label="Preferences", menu=preferences)
        preferences.add_radiobutton(label="Text Mode", command =self.text_command)
        preferences.add_radiobutton(label="Code Mode", command =self.code_command)
        
        toolsmenu = tk.Menu(menu)
        menu.add_cascade(label="Tools", menu=toolsmenu)
        toolsmenu.add_command(label="Find", command=self.find_command, accelerator="Ctrl+F")
        self.bind_all("<Control-f>",self.find_command)
        toolsmenu.add_command(label="Replace", command=self.replace_command, accelerator="Ctrl+H")
        self.bind_all("<Control-h>",self.replace_command)
        toolsmenu.add_separator()      
        toolsmenu.add_command(label="Spell Check", command=self.spellcheck_command)
        toolsmenu.add_command(label="Translate", command=self.translate_command)
        toolsmenu.add_command(label="Brace Matching", command=self.braces_command)
        toolsmenu.add_command(label="Document Comparision", command=self.comparedoc_command)
        
        helpmenu = tk.Menu(menu)
        menu.add_cascade(label="Help", menu=helpmenu)
        helpmenu.add_command(label="About", command=self.about_command)
        
    def new_command(self,*args):
        new=TkApp()

    def open_command(self,*args):
        data = self.textPad.get('1.0', 'end-1c')
        flag=0
        for i in data:
            if(i!='\n'):
                flag=1
                break
        if(not(flag)):
            file = askopenfile(mode='rb',title='Select a file')
            if file != None:
                self.deleteall_command(self,*args)
                contents = file.read()
                self.textPad.insert('1.0',contents)
                file.close()
        else:
            if(askokcancel("Save", "You have unsaved changes. Save?")):
                self.save_command(self,*args)
            file = askopenfile(mode='rb',title='Select a file')
            if file != None:
                self.deleteall_command(self,*args)
                contents = file.read()
                self.textPad.insert('1.0',contents)
                file.close()
        global filename
        if(file!=None):
            a=[x for x in str(file).split("'")]
            filename=a[1]

    def save_command(self,*args):
        contents = self.textPad.get('1.0','end-1c')
        global filename
        try:
            with open(filename, 'w') as outputFile:  
                outputFile.write(contents)         
        except IOError:                     
            self.saveas_command()    

    def saveas_command(self,*args):
        file = asksaveasfile(mode = 'w', title='Save As')
        if file != None:
            data = self.textPad.get('1.0', 'end-1c')
            file.write(data)
            file.close()
            global filename
            a=[x for x in str(file).split("'")]
            filename=a[1]
            
    def exit_command(self,*args):
        data = self.textPad.get('1.0', 'end-1c')
        flag=0
        for i in data:
            if(i!='\n'):
                flag=1
                break
        if(flag):
            if(askokcancel("Save", "Save before closing?")):
                self.save_command(self,*args)
            self.destroy()
        else:
            if(askokcancel("Quit", "Are you sure you want to quit?")):
                self.destroy()

    def code_command(self,*args):
        self.bind("<Key>",self.auto_indent,add="+")
        self.bind("<Return>",self.keep_indent)
        self.bind("<Key>",self.keywords_command,add="+")
        self.bind("<Key>",self.comment_command,add="+")
        self.bind("<Key>",self.string_command,add="+")

    def text_command(self,*args):
        self.unbind("<Key>")
        self.unbind("<Return>")

    def copy_command(self,*args):
        try:
            self.clipboard_clear()
            text = self.textPad.get("sel.first", "sel.last")
            self.clipboard_append(text)
        except:
            pass

    def paste_command(self,*args):
        try:
            text = self.selection_get(selection='CLIPBOARD')
            self.textPad.insert('insert', text)
        except:
            pass

    def cut_command(self,*args):
        try:
            self.copy_command()
            self.textPad.delete("sel.first", "sel.last")
        except:
            pass

    def selectall_command(self,*args):
        self.textPad.tag_add('sel','1.0', 'end')
        
    def deleteall_command(self,*args):
        self.textPad.delete('1.0', 'end')

    def undo_command(self,*args):
        try:
            self.textPad.edit_undo()
        except:
            pass

    def redo_command(self,*args):
        try:
            self.textPad.edit_redo()
        except:
            pass

    def find_command(self,*args):
        search=askstring("Find", "")
        if(search==None):
            return
        l=len(search)
        data = self.textPad.get('1.0', 'end-1c')
        ind=[m.start() for m in finditer(search,data)]
        for i in ind:
            corpus=data[:i]
            last=0
            line_no=1
            k=0
            for j in corpus:
                k+=1
                if(j=='\n'):
                    line_no+=1
                    last=k
            st=str(line_no)+'.'+str(i-last)
            end=str(line_no)+'.'+str(i-last+l)
            self.textPad.tag_add('bt',st,end)

    def replace_command(self,*args):
        search=askstring("Find", "")
        rep=askstring("Replace with", "")
        if(search==None or rep==None):
            return
        l=len(search)
        data = self.textPad.get('1.0', 'end-1c')
        ind=[m.start() for m in finditer(search,data)]
        for count in range(len(ind)):
            data = self.textPad.get('1.0', 'end-1c')
            if(search in data):
                i=data.index(search)
            corpus=data[:i]
            last=0
            line_no=1
            k=0
            for j in corpus:
                k+=1
                if(j=='\n'):
                    line_no+=1
                    last=k
            st=str(line_no)+'.'+str(i-last)
            end=str(line_no)+'.'+str(i-last+l)
            self.textPad.delete(st,end)
            self.textPad.insert(st,rep)
                
    def about_command(self,*args):
        label = showinfo("TextMate", "A small and lightweight text editor.\n© 2017. All rights reserved.")

    def braces_command(self,*args):
        data = self.textPad.get('1.0', 'end-1c')
        a=[]
        for i in data:
            if(i=='(' or i=='{' or i=='['):
                a.append(i)
            if(i==')'):
                if(a==[] or a[-1]!='('):
                    label = showinfo("Brace Matching","Parenthesis don't match")
                    return
                else:
                    a.pop()
            if(i=='}'):
                if(a==[] or a[-1]!='{'):
                    label = showinfo("Brace Matching","Curly braces don't match")
                    return
                else:
                    a.pop()
            if(i==']'):
                if(a==[] or a[-1]!='['):
                    label = showinfo("Brace Matching","Square braces don't match")
                    return
                else:
                    a.pop()
        if(a==[]):
            label = showinfo("Brace Matching","All braces match!")
        else:
            ch=a[-1]
            if(ch=='('):
                label = showinfo("Brace Matching","Parenthesis don't match")
                return
            elif(ch=='{'):
                label = showinfo("Brace Matching","Curly braces don't match")
                return
            else:
                label = showinfo("Brace Matching","Square braces don't match")
                return

    def spellcheck_command(self,*args):
        dic=Dict("en_US")
        data=word_tokenize(self.textPad.get('1.0', 'end-1c'))
        for word in data:
                if not dic.check(word) and word.isalpha():
                        suggestions_list=dic.suggest(word)
                        suggestions_str=""
                        for w in suggestions_list:
                                suggestions_str+=w+" "
                        showinfo("Suggestions for '"+word+"'\n",suggestions_str)
        showinfo("Spell Check","Finished checking!")
        
    def translate_command(self,*args):
        try:
                translator = Translator()
                text = self.textPad.get("sel.first", "sel.last")
                language = askstring("Translate", "Kannada | Hindi | Tamil | Telugu | English")
                if language.lower() == "kannada":
                        language = "kn"
                elif language.lower() == "hindi":
                        language = "hi"
                elif language.lower() == "telugu":
                        language = "te"
                elif language.lower() == "tamil":
                        language = "ta"
                elif language.lower() == "english":
                        language = "en"
                s = translator.translate(text, dest = language)
                self.textPad.delete("sel.first", "sel.last")
                self.textPad.insert('insert', s.text)
        except:
                pass

    def keywords_command(self,event):
        C_keywords=["auto","double","int","struct","break","else","long",
                    "switch","case","enum","register","typedef","char","extern",
                    "return","union","const","float","short","unsigned","do",
                    "continue","for","signed","void","default","goto","sizeof",
                    "volatile","if","static","while","printf","scanf","include"]
        for key in C_keywords:
            l=len(key)
            data = self.textPad.get('1.0', 'end-1c')
            ind=[m.start() for m in finditer(key,data)]
            for i in ind:
                corpus=data[:i]
                last=0
                line_no=1
                k=0
                for j in corpus:
                    k+=1
                    if(j=='\n'):
                        line_no+=1
                        last=k
                st=str(line_no)+'.'+str(i-last)
                end=str(line_no)+'.'+str(i-last+l)
                self.textPad.tag_add('kw',st,end)

    def comparedoc_command(self,*args):
        cmpfile = askopenfile(mode='rb',title='Select a file to compare with')
        if cmpfile != None:
            contents = cmpfile.read()
            cmpfile.close()
            data = self.textPad.get('1.0', 'end-1c')
            line=[x for x in contents.split("\n")]
            line1=[x for x in data.split("\n")]
            num=min(len(line),len(line1))
            x=1
            for i in range(num):
                s=str(line[i])
                s1=str(line1[i])
                s=sub(r'\s','',s)
                s1=sub(r'\s','',s1)
                if(s==s1):
                    xy=str(x)+'.0'
                    xy1=str(x)+'.54'
                    self.textPad.tag_add('sel',xy,xy1)
                x+=1

    def keep_indent(self,event):
        try:
            if self.brace_count != 0:
                text = self.brace_count*"	"
                self.textPad.insert('insert', text)
        except:
            pass

    brace_count = 0    
    def auto_indent(self,event):
        try:
            if event.char == '{':
                self.brace_count += 1
                text = "\n"+(self.brace_count*"	")		
                self.textPad.insert('insert', text)
            if event.char == '}':
                self.brace_count -= 1
                text = "\n"+(self.brace_count*"	")
                self.textPad.insert('insert', text)
        except:
                pass

    def comment_command(self,event):
        data = self.textPad.get('1.0', 'end-1c')
        search="\/\*"
        ind=[m.start() for m in finditer(search,data)]
        for i in ind:
            corpus=data[:i]
            last=0
            line_no=1
            k=0
            for j in corpus:
                k+=1
                if(j=='\n'):
                    line_no+=1
                    last=k
            st=str(line_no)+'.'+str(i-last)
            find=data[i+2:]
            flag=0
            if("*/" in find):
                la=(find.index("*/"))+1
                last1=0
                k=0
                for j in range(la):
                    k+=1
                    if(find[j]=='\n'):
                        flag=1
                        line_no+=1
                        last1=k
                if(flag==0):
                    end=str(line_no)+'.'+str(la+i-last+3)
                else:
                    end=str(line_no)+'.'+str(la-last1+1)
            else:
                end='end-1c'
            self.textPad.tag_add('com',st,end)

        data = self.textPad.get('1.0', 'end-1c')    
        ind1=[m.start() for m in finditer("//",data)]
        for i in ind1:
            corpus=data[:i]
            last=0
            line_no=1
            k=0
            for j in corpus:
                k+=1
                if(j=='\n'):
                    line_no+=1
                    last=k
            st=str(line_no)+'.'+str(i-last)
            end=str(line_no)+'.100'
            self.textPad.tag_add('com',st,end)

    def string_command(self,event):
        data = self.textPad.get('1.0', 'end-1c')
        search="\""
        ind=[m.start() for m in finditer(search,data)]
        bool=0
        for i in ind:
            bool+=1
            if(bool%2==0):
                continue
            corpus=data[:i]
            last=0
            line_no=1
            k=0
            for j in corpus:
                k+=1
                if(j=='\n'):
                    line_no+=1
                    last=k
            st=str(line_no)+'.'+str(i-last)
            find=data[i+1:]
            flag=0
            if("\"" in find):
                la=(find.index("\""))
                last1=0
                k=0
                for j in range(la):
                    k+=1
                    if(find[j]=='\n'):
                        flag=1
                        line_no+=1
                        last1=k
                if(flag==0):
                    end=str(line_no)+'.'+str(la+i-last+2)
                else:
                    end=str(line_no)+'.'+str(la-last1+1)
            else:
                end='end-1c'
            self.textPad.tag_add('str',st,end)
            
    def bold_command(self,*args):
        current_tags = self.textPad.tag_names()
        bold = Font(self.textPad, self.textPad.cget("font"))
        bold.config(weight="bold")
        self.textPad.tag_config("bld", font=bold)
        if "bld" in current_tags:
                self.textPad.tag_delete("bld", '1.0', 'end-1c')
        else:
                self.textPad.tag_add("bld", '1.0', 'end-1c') 	
                
    def italic_command(self,*args):
        current_tags = self.textPad.tag_names()
        italics = Font(self.textPad, self.textPad.cget("font"))
        italics.config(slant="italic")
        self.textPad.tag_config("ita", font=italics)
        if "ita" in current_tags:
                self.textPad.tag_delete("ita", '1.0', 'end-1c')
        else:
                self.textPad.tag_add("ita", '1.0', 'end-1c')

    def underline_command(self,*args):
        current_tags = self.textPad.tag_names()
        underline = Font(self.textPad, self.textPad.cget("font"))
        underline.config(underline=True)
        self.textPad.tag_config("und", font=underline)
        if "und" in current_tags:
                self.textPad.tag_delete("und", '1.0', 'end-1c')
        else:
                self.textPad.tag_add("und", '1.0', 'end-1c')
                
    def bolditalic_command(self,*args):
        current_tags = self.textPad.tag_names()
        bold_italic = Font(self.textPad, self.textPad.cget("font"))
        bold_italic.config(weight="bold",slant="italic")
        self.textPad.tag_config("bldita", font=bold_italic)
        if "bldita" in current_tags:
                self.textPad.tag_delete("bldita", '1.0', 'end-1c')
        else:
                self.textPad.tag_add("bldita", '1.0', 'end-1c')
           
    def font_command(self,*args):
        try:
                font_specs = askstring("Font", "Font Style-Font Size")
                font_specs = font_specs.split('-')
                new_font = Font(self.textPad, self.textPad.cget("font"))
                new_font.config(family=font_specs[0], size=font_specs[1])
                self.textPad.tag_config("newfont", font=new_font)
                self.textPad.tag_add("newfont", '1.0', 'end-1c')
        except:
                pass