自制代码编辑器:CASM Editor

哔哩哔哩演示视频:我使用python自制了一个代码编辑器——CASM Editor_哔哩哔哩_bilibili

源代码:

import idlelib.colorizer as idc
import idlelib.percolator as idp
import os
import sys
import threading
import time
import tkinter as T_tk
import tkinter.filedialog as tf
import tkinter.messagebox as tm
import tkinter.scrolledtext as ts
import tkinter.font as font
import tkinter.ttk
import re
import ttkbootstrap as tk

# version
version = '0.8.1'
running = 0


class SettingFont:
    def __init__(self):
        self.__name = r"tools\cgy-tool-stg.def"
        try:
            with open(self.__name, encoding='utf-8') as a:
                self.font = a.readline().replace('\n', '')
                self.size = int(a.readline().replace('\n', ''))
                if self.size > 250 or self.size < 5:
                    raise ValueError
                self.bold = a.readline().replace('\n', '')
                if self.bold == '':
                    raise ValueError

        except (ValueError, OSError):
            self.font = 'Consolas'
            self.size = 20
            self.bold = 'normal'
            try:
                with open(self.__name, 'w', encoding='utf-8') as a:
                    a.write(f'{self.font}\n{int(self.size)}\n{self.bold}')
            except OSError:
                def a(path):
                    b = os.path.basename(path)
                    c = len(list(b))
                    return path[:-1 * c]

                os.mkdir(f'{a(__file__)}tools\\')
                with open(self.__name, 'w', encoding='utf-8') as a:
                    a.write(f'{self.font}\n{int(self.size)}\n{self.bold}')

    def sf_return(self):
        return self.font, self.size, self.bold

    def shange(self, _font, size, bold):
        with open(self.__name, 'w', encoding='utf-8') as a:
            a.write(f'{_font}\n{size}\n{bold}')
            self.font = _font
            self.size = size
            self.bold = bold

    def check(self):
        try:
            with open(self.__name, 'r', encoding='utf-8') as a:
                _a = a.readline().replace('\n', '')
                if self.font == _a:
                    b = int(a.readline().replace('\n', ''))
                    if self.size == b:
                        if b > 250 or b < 5:
                            raise ValueError
                        c = a.readline().replace('\n', '')
                        if self.bold == c:
                            if c == '':
                                raise ValueError
                            return False
                        else:
                            self.bold = c
                            return True
                    else:
                        self.size = b
                        return True
                else:
                    self.font = _a
                    return True
        except (ValueError, Exception):
            self.font = 'Consolas'
            self.size = 20
            self.bold = 'normal'
            try:
                with open(self.__name, 'w', encoding='utf-8') as a:
                    a.write(f'{self.font}\n{int(self.size)}\n{self.bold}')
            except OSError:
                def a(path):
                    _b = os.path.basename(path)
                    _c = len(list(_b))
                    return path[:-1 * _c]

                os.mkdir(f'{a(__file__)}tools\\')
                with open(self.__name, 'w', encoding='utf-8') as a:
                    a.write(f'{self.font}\n{int(self.size)}\n{self.bold}')
            return True


class SettingColor:
    def __init__(self):
        pass


class GUI:
    def __init__(self):
        # vars
        self.a = None
        self.b = None
        self.c = None
        self.d = None
        self.p = None
        self.i = 0
        # wgts

        self.root = T_tk.Tk()
        self.root.title('CASM 文本编辑器')
        # Settings about fonts
        self.fs = SettingFont()
        self.font, self.size, self.bold = self.fs.sf_return()
        # Settings about colors
        self.cs = SettingColor()
        self.bg = "#ffffff"
        self.normal = '#000000'
        self.numbers = "#FFA500"
        self.comment = "#C0C0C0"
        self.keywords = "#00BFFF"
        self.builtin = "#7B68EE"
        self.string = "#FFA500"
        self.definition = "#228B22"
        self.symbol = "#FF0000"
        self.classmode = "#DA70D6"
        self.line = "#717171"
        # self.root.geometry('1500x900')
        # self.root.minsize(1500, 0)
        self.sb = tk.Scrollbar(self.root, orient=tk.HORIZONTAL)
        self.sb.pack(side=tk.BOTTOM, fill=tk.X)
        self.sb2 = tk.Scrollbar(self.root)
        self.sb2.pack(side=tk.RIGHT, fill=tk.Y)
        self.fall = tk.IntVar(self.root)
        self.text = tk.Text(self.root, undo=True, xscrollcommand=self.sb.set, yscrollcommand=self.sb2.set, wrap='none')
        self.text.config(font=(self.font, self.size, self.bold), background=self.bg, foreground=self.normal)
        self.numl = tk.Canvas(self.root, width=60, bg='white', highlightthickness=0)
        self.numl.pack(side=tk.LEFT, fill=tk.BOTH)
        self.text.pack(side=tk.LEFT, fill=tk.BOTH, expand=tk.YES)
        self.colorful = idc.color_config(self.text)
        self.sb.config(command=self.text.xview)
        self.menu = tk.Menu(self.root)
        self.popup = tk.Menu(self.root, tearoff=0)
        self.filemenu = tk.Menu(self.menu, tearoff=False)
        self.editmenu = tk.Menu(self.menu, tearoff=False)
        self.elsemenu = tk.Menu(self.menu, tearoff=False, selectcolor='green')
        self.saved = False
        self.running = False
        self.myrun = True
        self.installing = False
        self.name = ''
        self.lineall = 0
        self.old = 0

    def loadfile(self, file):
        file = '\n'.join((item.decode('gbk') for item in file)).split('\n')[0]
        self.open(name=file)

    def edit(self, text):
        self.text.delete(1.0, tk.END)
        self.text.insert(tk.END, text)

    def get(self):
        return self.text.get(1.0, tk.END).rstrip()

    def adds(self):
        self.fall.set(1)  # 0开1关,默认关
        idc.color_config(self.text)
        self.p = idp.Percolator(self.text)
        self.text.focus_set()
        # windnd.hook_dropfiles(self.root, func=self.loadfile)
        self.check()

        def the_function_that_which_is_running_at_tkinter_key_press(event):
            self.redraw()
            self.see()
            self.redraw()
            if self.saved:
                self.save()
            self.character_completion(event)

        def the_function_that_which_is_running_at_tkinter_ctrl_v_press(*args):
            self.text.event_generate("<<Paste>>")
            self.see()

        self.root.bind("<Key>", lambda event: the_function_that_which_is_running_at_tkinter_key_press(event))
        self.text.bind('<Tab>', self.tab)
        self.text.bind('<Control-Tab>', self.untab)
        self.text.bind("<Return>", self.enter)
        self.text.bind("<BackSpace>", self.backspace)
        self.text.bind("<Button-1>", self.redraw)
        self.text.bind("<B2-Motion>", self.redraw)
        self.text.bind("<MouseWheel>", self.redraw)
        self.root.bind("<Configure>", self.redraw)
        self.root.bind("<B1-Motion>", self.redraw)
        try:
            self.root.iconbitmap(r'images\lego.ico')
        except tkinter.TclError:
            pass
        font_ = font.Font(root=self.root, font=self.text['font'])
        tab_width = font_.measure(' ' * 4)
        self.text.config(tabs=(tab_width,))
        self.root.protocol("WM_DELETE_WINDOW", self.when_exit_do)
        self.text.tag_configure('Found', background='black', foreground='white', underline=True)
        self.menu.add_cascade(label='文件', menu=self.filemenu)
        self.menu.add_cascade(label='编辑', menu=self.editmenu)
        self.menu.add_cascade(label='其他', menu=self.elsemenu)
        self.filemenu.add_command(label='新建     Ctrl+n', command=self.mynew)
        self.filemenu.add_command(label='保存     Ctrl+s', command=self.save)
        self.filemenu.add_command(label='另存为     Ctrl+e', command=self.saveas)
        self.filemenu.add_command(label='打开文件     Ctrl+f', command=self.open)
        self.filemenu.add_command(label='运行     Ctrl+r', command=self.runtext)
        self.filemenu.add_command(label='退出     Ctrl+q', command=self.when_exit_do)
        self.editmenu.add_command(label='替换     Ctrl+Alt+r', command=self.replace)
        self.editmenu.add_command(label='寻找     Ctrl+Alt+f', command=self.find)
        self.editmenu.add_command(label='字数统计     Ctrl+Alt+t', command=self.count)
        self.editmenu.add_command(label='设置     Ctrl+Alt+s', command=self.changestg)
        self.elsemenu.add_command(label='快捷键     Ctrl+Alt+e', command=self.elsekey)
        self.elsemenu.add_command(label='关于     Ctrl+Alt+a',
                                  command=lambda: tm.showinfo('关于', '本编辑器由保定曹高远制作。原创。'))
        self.elsemenu.add_command(label='关于文件     Ctrl+Alt+f', command=self.about_file)
        self.elsemenu.add_checkbutton(label="全屏     F11", variable=self.fall, offvalue=0, onvalue=1,
                                      command=lambda: self._falls())
        self.root.bind('<Control-n>', lambda event: self.mynew())
        self.root.bind('<Control-s>', lambda event: self.save())
        self.root.bind('<Control-e>', lambda event: self.saveas())
        self.root.bind('<Control-r>', lambda event: self.runtext())
        self.root.bind('<Control-f>', lambda event: self.open())
        self.root.bind('<Control-q>', lambda event: self.when_exit_do())
        self.root.bind('<Control-Alt-r>', lambda event: self.replace())
        self.root.bind('<Control-Alt-f>', lambda event: self.find())
        self.root.bind('<Control-Alt-t>', lambda event: self.count())
        self.root.bind('<Control-Alt-s>', lambda event: self.changestg())
        self.root.bind('<Control-Alt-e>', lambda event: self.elsekey())
        self.root.bind('<Control-Alt-f>', lambda event: self.about_file())
        self.root.bind('<Control-Alt-a>', lambda event: tm.showinfo('关于', '本编辑器由伟大的天才曹高远制作。'))
        self.root.bind('<Control-MouseWheel>', lambda event: self.bigorsmall_font(event))
        self.root.bind('<F11>', lambda event: self.falls())
        self.popup.add_command(label='复制', command=lambda: self.text.event_generate("<<Copy>>"))
        self.popup.add_command(label='剪切', command=lambda: self.text.event_generate("<<Cut>>"))
        self.popup.add_command(label='粘贴', command=the_function_that_which_is_running_at_tkinter_ctrl_v_press)
        self.root.bind("<Button-3>", self.popup_menu)
        self.root.config(menu=self.menu)

    def falls(self):
        a = self.fall.get()
        if a == 1:
            self.root.attributes("-fullscreen", False)
            self.fall.set(0)  # 改变状态
        else:
            self.root.attributes("-fullscreen", True)
            self.fall.set(1)

    def _falls(self):
        a = self.fall.get()
        if a == 0:
            self.root.attributes("-fullscreen", False)  # 不改变状态
        else:
            self.root.attributes("-fullscreen", True)

    def see(self):
        self.text.see(str(float(int(float(self.text.index('insert'))) + 2)))  # 一直显示光标所在行

    def __update__(self, *args):
        while True:
            self.root.update()
            new = str(int(float(self.text.index('insert'))))
            if new != self.old:
                self.old = new
                self.redraw()
            try:
                if self.fs.check():
                    self.font, self.size, self.bold = self.fs.sf_return()
                    self.update()
            except RuntimeError:
                break

    def insert_get(self):
        start = tk.SEL_FIRST
        end = tk.SEL_LAST
        is_insert = True if self.text.get(start, end) != '' else False
        return is_insert, self.text.index(start), self.text.index(end)

    def update(self):
        self.text.config(font=(self.font, self.size, self.bold))
        self.redraw()

    def tab(self, *args):
        is_insert, start, end = self.insert_get()
        if not is_insert:
            self.text.insert('insert', '    ')
        else:
            start = int(float(start))
            end = int(float(end))
            for i in range(start, end + 1):
                self.text.insert(str(float(i)), '    ')
        return 'break'

    def untab(self, *args):
        is_insert, start, end = self.insert_get()
        if not is_insert:
            last = str(int(''.join(list(self.text.index('insert'))[
                                   (-1 * (len(os.path.splitext(self.text.index('insert'))[-1]) - 1)):])) - 4)
            all_insert = ''.join(list(self.text.index('insert'))[
                                 :(-1 * (len(os.path.splitext(self.text.index('insert'))[-1]) - 1))]) + last
            if self.text.get(all_insert, 'insert') == '    ':
                self.text.delete(all_insert, 'insert')
        else:
            start = self.text.index(start)
            end = self.text.index(end)
            for i in range(int(float(start)), int(float(end)) + 1):
                last = str(int(''.join(list(self.text.index(str(float(i))))[
                                       (-1 * (len(os.path.splitext(self.text.index(str(float(i))))[-1]) - 1)):])) + 4)
                all_insert = ''.join(list(self.text.index(str(float(i))))[
                                     :(-1 * (len(os.path.splitext(self.text.index(str(float(i))))[-1]) - 1))]) + last
                if self.text.get(str(float(i)), all_insert) == '    ':
                    self.text.delete(str(float(i)), all_insert)
        return 'break'

    def popup_menu(self, event):
        self.popup.post(event.x_root, event.y_root)  # 弹出右键菜单

    def mynew(self):
        GUI().run()

    def redraw(self, *args):
        try:
            global linenum
            self.numl.delete("all")
            i = self.text.index("@0,0")
            while True:
                dline = self.text.dlineinfo(i)
                if dline is None:
                    break
                y = dline[1]
                linenum = str(i).split(".")[0]
                self.numl.create_text(2, y, anchor="nw", text=linenum, fill=self.line,
                                      font=(self.font, self.size, self.bold))
                i = self.text.index("%s+1line" % i)

            _font = font.Font(root=self.root, family=self.font, size=self.size)
            w = _font.measure('0')
            self.numl.config(width=len(linenum) * w + 5)
            self.lineall = linenum
        except RuntimeError:
            pass

    def save(self):
        if self.name == '':
            self.name = tf.asksaveasfilename(initialfile='main.casm', defaultextension='.casm',
                                             filetypes=(('CASM文件', ('*.casm', '*.txt')), ('所有文件', '*.*')))
            if self.name == '':
                return
            try:
                with open(self.name, 'w', encoding='utf-8') as casm:
                    casm.write(self.text.get(1.0, tk.END)[:-1])
            except:
                self.name = ''
            else:
                self.saved = True
                self.root.title(self.name)
        else:
            try:
                with open(self.name, 'w', encoding='utf-8') as casm:
                    casm.write(self.text.get(1.0, tk.END)[:-1])
            except OSError:
                pass

    def saveas(self):
        if self.saved:
            if self.running:
                tm.showerror('文本编辑器', '文件正在运行,请先关闭。')
                return
        self.name = tf.asksaveasfilename(initialfile='main.casm', defaultextension='.casm',
                                         filetypes=(('CASM文件', ('*.casm', '*.txt')), ('所有文件', '*.*')))
        if self.name == '':
            return
        try:
            with open(self.name, 'w', encoding='utf-8') as casm:
                casm.write(self.text.get(1.0, tk.END)[:-1])
        except:
            self.name = ''
        else:
            self.saved = True
            self.root.title(self.name)

    def highins(self, text: str):
        self.text.insert(tk.END, text)

    def open(self, name=''):
        if self.running:
            tm.showerror('文本编辑器', '文件正在运行,请先关闭。')
            return
        if name == '':
            if self.name == '':
                self.name = tf.askopenfilename(
                    filetypes=(("CASM文件", ("*.casm", '*.txt')), ("所有文件", "*.*")))
                if self.name == '':
                    return
                try:
                    with open(self.name, encoding='utf-8') as casm:
                        self.text.delete(1.0, tk.END)
                        self.highins(casm.read())
                except UnicodeError:
                    self.saved = False
                    self.redraw()
                    self.name = ''
                    self.root.title('CASM 文本编辑器')
                    tm.showerror('文本编辑器', '我们只支持编码为utf-8文件。')
                except PermissionError:
                    self.saved = False
                    self.redraw()
                    self.name = ''
                    self.root.title('CASM 文本编辑器')
                    tm.showerror('Error', '权限不足,访问被拒绝')
                else:

                    self.check()
                    self.redraw()
                    self.saved = True
                    self.root.title(self.name)
                    self.text.edit_reset()  # 重置文本框的撤销功能
            else:
                a = tm.askokcancel(self.name, '你已打开了一个文件,要把它关闭并保存在打开新文件吗?')
                if a:
                    self.name = tf.askopenfilename(
                        filetypes=(("CASM文件", ("*.casm", '*.txt')), ("所有文件", "*.*")))
                    if self.name == '':
                        return
                    try:
                        with open(self.name, encoding='utf-8') as casm:
                            self.text.delete(1.0, tk.END)
                            self.highins(casm.read())
                    except UnicodeError:
                        self.saved = False
                        self.redraw()
                        self.name = ''
                        self.root.title('CASM 文本编辑器')
                        tm.showerror('文本编辑器', '我们只支持编码为utf-8文件。')
                    except PermissionError:
                        self.saved = False
                        self.redraw()
                        self.name = ''
                        self.root.title('CASM 文本编辑器')
                        tm.showerror('Error', '权限不足,访问被拒绝')
                    else:
                        self.check()
                        self.redraw()
                        self.saved = True
                        self.root.title(self.name)
                        self.text.edit_reset()
        else:
            if self.name == '':
                try:
                    with open(name, encoding='utf-8') as casm:
                        self.text.delete(1.0, tk.END)
                        self.highins(casm.read())
                except UnicodeError:
                    self.saved = False
                    self.redraw()
                    self.root.title('CASM 文本编辑器')
                    tm.showerror('文本编辑器', '我们只支持编码为utf-8文件。')
                except PermissionError:
                    self.saved = False
                    self.redraw()
                    self.root.title('CASM 文本编辑器')
                    tm.showerror('Error', '权限不足,访问被拒绝')
                except OSError:
                    self.saved = False
                    self.redraw()
                    self.text.delete(1.0, tk.END)
                    self.text.insert(tk.END, name)
                else:
                    self.name = name
                    self.check()
                    self.redraw()
                    self.saved = True
                    self.root.title(self.name)
                    self.text.edit_reset()
            else:
                a = tm.askokcancel(self.name, '你已打开了一个文件,要把它关闭并保存在打开新文件吗?')
                if a:
                    try:
                        with open(name, encoding='utf-8') as casm:
                            self.text.delete(1.0, tk.END)
                            self.highins(casm.read())
                    except UnicodeError:
                        self.saved = False
                        self.redraw()
                        self.root.title('CASM 文本编辑器')
                        tm.showerror('文本编辑器', '我们只支持编码为utf-8文件。')
                    except PermissionError:
                        self.saved = False
                        self.redraw()
                        self.root.title('CASM 文本编辑器')
                        tm.showerror('Error', '权限不足,访问被拒绝')
                    except OSError:
                        self.saved = False
                        self.redraw()
                        self.text.delete(1.0, tk.END)
                        self.text.insert(tk.END, name)
                    else:
                        self.name = name
                        self.check()
                        self.redraw()
                        self.saved = True
                        self.root.title(self.name)
                        self.text.edit_reset()

    def make_pat(self):
        def _any(name, alternates):
            return "(?P<%s>" % name + "|".join(alternates) + ")"

        kwlist = ["FUNC", "VAR", "IFE", "IFB", "IFS", "GOTO", "IF", "RET"]
        kw = r"\b" + _any("KEYWORD", kwlist) + r"\b"
        builtinlist = ["TYPE", "PUSH", "OUT", "ENDL", "PUSHCOMMENT", "POP", "ADD", "SUB", "MUL", "DIV", "MOD", "IN",
                       "GETVAR", "PUSHVAR", "EXIT", "RAND", "NOT", "CLEAR", "STR", "INT", "BOOL", "DOUBLE", "FLOAT",
                       "CHAR"]
        # builtin = r"([^.'\"\\#]\b|^)" + _any("BUILTIN", builtinlist) + r"\b"
        builtin = r"\b" + _any("BUILTIN", builtinlist) + r"\b"
        comment = _any("COMMENT", [r";[^\n]*"])
        number = _any("NUM", [r"\b[0-9]+(?![0-9]+)\b"])
        prog = re.compile("|".join([
            builtin, comment, kw, number,
            _any("SYNC", [r"\n"]),
        ]),
            re.DOTALL | re.MULTILINE)
        return prog

    def check(self):
        if (os.path.splitext(self.name)[-1] in ['.casm', '.txt']) or self.name == '':
            try:
                self.p.removefilter(self.d)
            except AssertionError:
                pass
            self.d = idc.ColorDelegator()
            self.d.prog = self.make_pat()
            self.d.tagdefs['COMMENT'] = {'foreground': self.comment}
            self.d.tagdefs['KEYWORD'] = {'foreground': self.keywords}
            self.d.tagdefs['BUILTIN'] = {'foreground': self.builtin}
            self.d.tagdefs['NUM'] = {'foreground': self.numbers}
            try:
                self.p.insertfilter(self.d)
            except AssertionError:
                pass
        else:
            try:
                self.p.removefilter(self.d)
            except AssertionError:
                pass
            self.d = idc.ColorDelegator()
            self.d.prog = self.make_pat()
            self.d.tagdefs['COMMENT'] = {'foreground': self.normal}
            self.d.tagdefs['KEYWORD'] = {'foreground': self.normal}
            self.d.tagdefs['BUILTIN'] = {'foreground': self.normal}
            self.d.tagdefs['NUM'] = {'foreground': self.normal}
            try:
                self.p.insertfilter(self.d)
            except AssertionError:
                pass

    def runtext(self):
        if self.saved:
            if not self.running:
                self.save()
                print(self.name[-5:])
                if self.name[-5:] == '.casm':
                    path = self.name.split('/')
                    path = '\\'.join(path[:-1])
                    cmd = f'{self.name[:2]} & cd \"{path}\\\" & casm.exe \"{self.name}\" & pause'  # 加‘&’连续执行cmd命令
                elif self.name[-4:] == '.txt':
                    path = self.name.split('/')
                    path = '\\'.join(path[:-1])
                    cmd = f'{self.name[:2]} & cd \"{path}\\\" & casm.exe \"{self.name}\"'
                else:
                    cmd = ''

                def aa():
                    self.running = True
                    print("cmd:",cmd)
                    os.system(cmd)
                    self.running = False

                self.a = threading.Thread(target=aa)
                self.a.start()
            else:
                tm.showerror(self.name, '文件已运行')
        else:
            self.mycallsave()

    def mycallsave(self):
        tm.showinfo('文本编辑器', '你没有保存这个文件,请先保存。')
        self.save()

    def run(self):
        global running
        running += 1
        self.adds()
        self.redraw()
        self.falls()
        while True:
            self.__update__()

    def enter(self, *args):
        self.i = 0
        a = self.text.index('insert')
        aa = int(float(a))
        b = self.text.get(float(aa), a).replace('\n', '')
        c = b
        if b[0:5] == 'FUNC ':
            i = 0
            while True:
                if b[:4] == '    ':
                    b = b[4:]
                    i += 1
                else:
                    break
            self.i = i + 1
        else:
            i = 0
            while True:
                if b[:4] == '    ':
                    b = b[4:]
                    i += 1
                else:
                    break
            self.i = i
            try:
                a = c.strip().split()[0]
            except IndexError:
                a = ''
        self.text.insert('insert', '\n')
        for j in range(self.i):
            self.text.insert('insert', '    ')
        self.redraw()
        self.see()
        return 'break'

    def backspace(self, *args):
        _dict = {'(': ')', '{': '}', '[': ']', '"': '"', "'": "'"}
        last = str(int(''.join(list(self.text.index('insert'))[
                               (-1 * (len(os.path.splitext(self.text.index('insert'))[-1]) - 1)):])) - 1)
        all_insert = ''.join(list(self.text.index('insert'))[
                             :(-1 * (len(os.path.splitext(self.text.index('insert'))[-1]) - 1))]) + last
        a = self.text.get(all_insert, 'insert')
        if a in ['(', '{', '[', '"', "'"]:
            last = str(int(''.join(list(self.text.index('insert'))[
                                   (-1 * (len(os.path.splitext(self.text.index('insert'))[-1]) - 1)):])) + 1)
            all_insert = ''.join(list(self.text.index('insert'))[
                                 :(-1 * (len(os.path.splitext(self.text.index('insert'))[-1]) - 1))]) + last
            b = self.text.get('insert', all_insert)
            if b == _dict[a]:  # 符合条件,删除2个
                last1 = str(int(''.join(list(self.text.index('insert'))[
                                        (-1 * (len(os.path.splitext(self.text.index('insert'))[-1]) - 1)):])) - 1)
                all_insert1 = ''.join(list(self.text.index('insert'))[
                                      :(-1 * (len(os.path.splitext(self.text.index('insert'))[-1]) - 1))]) + last1
                last2 = str(int(''.join(list(self.text.index('insert'))[
                                        (-1 * (len(os.path.splitext(self.text.index('insert'))[-1]) - 1)):])) + 1)
                all_insert2 = ''.join(list(self.text.index('insert'))[
                                      :(-1 * (len(os.path.splitext(self.text.index('insert'))[-1]) - 1))]) + last2
                self.text.delete(all_insert1, all_insert2)
                return 'break'
        else:
            last1 = str(int(''.join(list(self.text.index('insert'))[
                                    (-1 * (len(os.path.splitext(self.text.index('insert'))[-1]) - 1)):])) - 4)
            all_insert1 = ''.join(list(self.text.index('insert'))[
                                  :(-1 * (len(os.path.splitext(self.text.index('insert'))[-1]) - 1))]) + last1
            if self.text.get(all_insert1, 'insert') == '    ':
                self.text.delete(all_insert1, 'insert')
                return 'break'

    def character_completion(self, event: T_tk.Event):  # 字符补全(对【(】、【[】、【{】等进行自动补全)
        a = event.keysym
        if a == 'parenleft':  # (
            self.text.insert("insert", ')')
            last = str(int(''.join(list(self.text.index('insert'))[
                                   (-1 * (len(os.path.splitext(self.text.index('insert'))[-1]) - 1)):])) - 1)
            all_insert = ''.join(list(self.text.index('insert'))[
                                 :(-1 * (len(os.path.splitext(self.text.index('insert'))[-1]) - 1))]) + last
            self.text.mark_set('insert', all_insert)
        elif a == 'braceleft':  # {
            self.text.insert("insert", '}')
            last = str(int(''.join(list(self.text.index('insert'))[
                                   (-1 * (len(os.path.splitext(self.text.index('insert'))[-1]) - 1)):])) - 1)
            all_insert = ''.join(list(self.text.index('insert'))[
                                 :(-1 * (len(os.path.splitext(self.text.index('insert'))[-1]) - 1))]) + last
            self.text.mark_set('insert', all_insert)
        elif a == 'bracketleft':  # [
            self.text.insert("insert", ']')
            last = str(int(''.join(list(self.text.index('insert'))[
                                   (-1 * (len(os.path.splitext(self.text.index('insert'))[-1]) - 1)):])) - 1)
            all_insert = ''.join(list(self.text.index('insert'))[
                                 :(-1 * (len(os.path.splitext(self.text.index('insert'))[-1]) - 1))]) + last
            self.text.mark_set('insert', all_insert)
        elif a == 'quotedbl':
            self.text.insert("insert", '"')
            last = str(int(''.join(list(self.text.index('insert'))[
                                   (-1 * (len(os.path.splitext(self.text.index('insert'))[-1]) - 1)):])) - 1)
            all_insert = ''.join(list(self.text.index('insert'))[
                                 :(-1 * (len(os.path.splitext(self.text.index('insert'))[-1]) - 1))]) + last
            self.text.mark_set('insert', all_insert)
        elif a == "apostrophe":
            self.text.insert("insert", "'")
            last = str(int(''.join(list(self.text.index('insert'))[
                                   (-1 * (len(os.path.splitext(self.text.index('insert'))[-1]) - 1)):])) - 1)
            all_insert = ''.join(list(self.text.index('insert'))[
                                 :(-1 * (len(os.path.splitext(self.text.index('insert'))[-1]) - 1))]) + last
            self.text.mark_set('insert', all_insert)

    '''EDIT TOOLS'''

    def __replace(self, ta, tb, num):
        if ta and tb and num:
            num = int(num)
            if num == -1:
                a = self.get()
                a = a.replace(ta, tb)
                self.edit(a)
            elif num >= 0:
                pass
            else:
                a = self.get()
                a = a.replace(ta, tb, num)
                self.edit(a)
        else:
            tm.showerror('文本编辑器', '文本框不可留空!')

    def replace(self):
        if self.name != '':
            self.save()
            root = tk.Toplevel()
            root.title('替换')
            root.resizable(False, False)
            try:
                root.iconbitmap(r'images\lego.ico')
            except tkinter.TclError:
                pass
            label = tk.Label(root, text=u'原始内容:')
            label.grid(padx=10, pady=10, row=0, column=0)
            entry = tk.Entry(root)
            entry.grid(padx=10, pady=10, row=0, column=1)
            label2 = tk.Label(root, text=u'替换为:')
            label2.grid(padx=10, pady=10, row=1, column=0)
            entry2 = tk.Entry(root)
            entry2.grid(padx=10, pady=10, row=1, column=1)
            label3 = tk.Label(root, text='次数(-1为全部替换)')
            label3.grid(padx=10, pady=10, row=2, column=0)
            entry3 = tk.Entry(root)
            entry3.grid(padx=10, pady=10, row=2, column=1)
            btn = tk.Button(root, text='替换!',
                            command=lambda: self.__replace(entry.get(), entry2.get(), entry3.get()))
            btn.grid(padx=10, pady=10, row=3, column=0)
            root.mainloop()
        else:
            self.mycallsave()

    def __find(self, msg: str):
        if self.name:
            if msg:
                i = 0
                self.text.tag_remove('Found', '1.0', tk.END)
                start = '1.0'
                if len(msg.rstrip()) == 0:
                    return 0
                while True:
                    pos = self.text.search(msg, start, tk.END)
                    if pos == '':
                        break
                    i += 1
                    self.text.tag_add('Found', pos, '%s+%dc' % (pos, len(msg)))
                    start = '%s+%dc' % (pos, len(msg))
                return i
            else:
                tm.showerror('文本编辑器', '文本框不可留空!')
        else:
            self.mycallsave()

    def delatefind(self):
        self.text.tag_remove('Found', '1.0', tk.END)

    def runfind(self, msg):
        a = self.__find(msg)
        tm.showinfo(self.name, f'共找到"{msg}"{a}个。')

    def find(self):
        if self.name != '':
            self.save()
            root = tk.Toplevel()
            root.title('查找')
            try:
                root.iconbitmap(r'images\lego.ico')
            except tkinter.TclError:
                pass
            root.resizable(False, False)
            entry = tk.Entry(root)
            entry.grid(row=1, column=0, pady=10, padx=10)
            btn1 = tk.Button(root, text='寻找', command=lambda: self.runfind(entry.get().rstrip()))
            btn1.grid(row=1, column=1, padx=10, pady=10)
            btn2 = tk.Button(root, text='清空', command=self.delatefind)
            btn2.grid(row=1, column=2, padx=10, pady=10)
            root.mainloop()

    def count(self):
        '''字数统计'''
        if self.name != '':
            self.save()
            a = self.get()
            a = len(list(a))
            tm.showinfo('字数统计', f'文件{self.name}有字符{a}个')
        else:
            self.mycallsave()

    def bigorsmall_font(self, event):
        if event.delta > 0:
            if self.size < 250:
                self.size += 1
                self.text.config(font=(self.font, self.size, self.bold))
                self.redraw()
                font_ = font.Font(root=self.root, font=self.text['font'])
                tab_width = font_.measure(' ' * 4)
                self.text.config(tabs=tab_width)
            else:
                tm.showerror('CASM编辑器', '字体过大')
        else:
            if self.size > 5:
                self.size -= 1
                self.text.config(font=(self.font, self.size, self.bold))
                self.redraw()
                font_ = font.Font(root=self.root, font=self.text['font'])
                tab_width = font_.measure(' ' * 4)
                self.text.config(tabs=tab_width)
            else:
                tm.showerror('CASM编辑器', '字体过小')
        self.fs.shange(self.font, int(self.size), self.bold)

    def changestg(self):
        root = tk.Toplevel()
        root.title('设置')
        root.geometry('300x250')
        try:
            root.iconbitmap(r'images\lego.ico')
        except tkinter.TclError:
            pass
        root.resizable(False, False)
        notepad = tkinter.ttk.Notebook(root)
        fr1 = tk.Frame(root)
        notepad.add(fr1, text='设置')
        var = tk.StringVar(root)
        var3 = tk.BooleanVar(root)
        var3.set(True if self.bold == "bold" else False)
        fontsfam = sorted([i for i in font.families(root) if not i.startswith("@")], reverse=True)
        fontsfam = tuple(fontsfam)

        var.set(self.font)
        var2 = tk.IntVar(root)
        var2.set(self.size)
        label = tk.Label(fr1, text=u'字体:')
        label.grid(row=0, column=0, padx=10, pady=10)
        cb = tkinter.ttk.Combobox(fr1, textvariable=var, values=fontsfam, width=30,
                                  state='readonly')  # state='readonly':将下拉列表设置成为只读模式
        cb.grid(row=0, column=1, pady=10, padx=10)
        label2 = tk.Label(fr1, text='大小')
        label2.grid(row=1, column=0, pady=10, padx=10)
        sl = tk.Scale(fr1, from_=1, to=100, orient=tk.HORIZONTAL, length=250, variable=var2)
        sl.grid(row=1, column=1, padx=10, pady=10)
        label3 = tk.Label(fr1, text='是否粗体')
        label3.grid(row=2, column=0, pady=10, padx=10)
        ck = tk.Checkbutton(fr1, text='使用粗体', variable=var3)
        ck.grid(row=2, column=1, padx=10, pady=10)

        def a():
            aa = var.get().rstrip()
            bb = var2.get()
            cc = var3.get()
            self.fs.shange(aa, bb, "bold" if cc else "normal")
            self.font = aa
            self.size = bb
            self.bold = "bold" if cc else "normal"
            self.text.config(font=(self.font, self.size, self.bold))
            font_ = font.Font(root=self.root, font=self.text['font'])
            tab_width = font_.measure(' ' * 4)
            self.text.config(tabs=(tab_width,))
            root.destroy()

        btn = tk.Button(fr1, text='确认', command=a)
        btn.grid(row=3, column=0, padx=10, pady=10)
        fr2 = tk.Frame(root)
        notepad.add(fr2, text='预览')
        sb = tk.Scrollbar(fr2, orient=tk.HORIZONTAL)
        sb.pack(side=tk.BOTTOM, fill=tk.X)
        text = ts.ScrolledText(fr2, width=300, height=200, wrap='none', xscrollcommand=sb.set)

        def textv(*args):
            text.config(font=(var.get().rstrip(), var2.get(), "bold" if var3.get() else "normal"))
            root.geometry('%dx%d' % (600, 550))

        def labelv(*args):
            root.geometry('%dx%d' % (350, 220))

        text.bind('<Visibility>', textv)
        label.bind('<Visibility>', labelv)
        text.insert(tk.END, '''
abcdefghijklmnopqrstuvwxyz
ABCDEFGHIJKLMNOPQRSTUVWXYZ
CASM editor is a small and lightweight editor.
CASM editor是一个小巧轻量的编辑器。
CASM Editor - это небольшой и легкий редактор.
CASM editorは小型軽量のエディタです。
CASM editor는 작고 가벼운 편집기입니다.
CASM တည်းဖြတ်ချက်ဟာ ချိတ်ဆက်နဲ့ လျှော့လင့်တဲ့ တည်းဖြတ်ချက်ပါ။
Casm Editor est un éditeur petit et léger.
Editor CASM editor compact and lightweight editor est.
El editor casm es un editor pequeño y ligero.
CASM editor é um editor compacto e leve.
 المستخلصات المحرر هو صغير وخفيف الوزن المحرر . 
CASM सम्पादकम्य सङ्केतं चित्रकं सम्पादकम्
ເຄື່ອງມືແກ້ໄຂCAS ເປັນຜູ້ກ່ຽວກັບຄຳແກ້ກແລະຄຳແກ້ໄຫລາຍດິນ
        ''')
        text.config(font=(var.get().rstrip(), var2.get(), "bold" if var3.get() else "normal"))
        sb.config(command=text.xview)
        text.pack()
        notepad.pack()
        root.mainloop()

    def elsekey(self):
        root = tk.Toplevel()
        root.title('其他')
        text = ts.ScrolledText(root)
        try:
            root.iconbitmap(r'images\lego.ico')
        except tkinter.TclError:
            pass
        text.config(font=(self.font, self.size, self.bold))
        text.insert(1.0, '\n*****************快捷键*******************\n')
        text.insert(tk.END, '\n')
        text.insert(tk.END, '1. 复制   Ctrl+c\n')
        text.insert(tk.END, '\n')
        text.insert(tk.END, '2. 粘贴   Ctrl+v\n')
        text.insert(tk.END, '\n')
        text.insert(tk.END, '3. 剪切   Ctrl+x\n')
        text.insert(tk.END, '\n')
        text.insert(tk.END, '4. 重做   Ctrl+z\n')
        text.insert(tk.END, '\n')
        text.insert(tk.END, '5. 返回   Ctrl+y\n')
        text.insert(tk.END, '\n')
        text.insert(tk.END, '6. 全选   Ctrl+a\n')
        text.insert(tk.END, '\n')
        text.insert(tk.END, '\n')
        text.insert(tk.END, '\n')
        text.insert(tk.END, '\n')
        text.insert(tk.END, '******************作者*******************\n')
        text.insert(tk.END, '\n')
        text.insert(tk.END, '1. 他叫曹高远,来自河北保定\n')
        text.insert(tk.END, '\n')
        text.insert(tk.END, '\n')
        text.insert(tk.END, '\n')
        text.insert(tk.END, '\n')
        text.configure(state=tk.DISABLED)
        text.pack(side=tk.BOTTOM, fill=tk.BOTH)
        root.mainloop()

    def when_exit_do(self):
        global running
        if not self.running:
            if self.saved:
                self.save()
                if self.saved:
                    self.root.destroy()
                    self.myrun = False
                    if running == 1:
                        sys.exit(0)
                    else:
                        running -= 1

            else:
                a = tm.askyesnocancel('CASM文本编辑器', '你没有保存文件,是否保存后再退出?')
                if a:
                    self.save()
                    if self.saved:
                        self.root.destroy()
                        self.myrun = False
                        if running == 1:
                            sys.exit(0)
                        else:
                            running -= 1
                elif a is None:
                    pass
                else:
                    self.myrun = False
                    self.root.destroy()
                    self.myrun = False
                    if running == 1:
                        sys.exit(0)
                    else:
                        running -= 1
        else:
            tm.showerror('文本编辑器', '文件正在运行,请先关闭。')

    def about_file(self):
        if self.name != '':
            root = tk.Toplevel()
            root.title('关于文件')
            root.geometry('600x500')
            try:
                root.iconbitmap(r'images\lego.ico')
            except tkinter.TclError:
                pass
            label = tk.Label(root)
            string = f"""
    文件名: {os.path.basename(self.name)}
    文件路径: {self.name}
    拓展名: {os.path.splitext(self.name)[-1]}
    大小: {round(os.path.getsize(self.name) / 1024, 2)} kb ({round(os.path.getsize(self.name), 2)} b)

    """
            label.config(text=string)
            label.pack()
            root.mainloop()

        else:
            self.mycallsave()


def check():
    system = os.name
    if system != 'nt':
        tm.showerror('ERROR!', '本程序只支持Microsoft Windows系统。')
        raise SystemExit('SYSTEM ERROR!')
    root = T_tk.Tk()
    root.withdraw()
    if 'casm.exe' in os.listdir(os.path.dirname(os.path.abspath(__file__))):

        tm.showinfo('恭喜!', '一切正常,您可以使用本编辑器!')
    else:
        tm.showerror('错误', '请确保您的电脑上已安装CASM。')
        sys.exit()
    root.destroy()


def hello():
    root = T_tk.Tk()
    root.title('Hello-CASM editor %s' % version)
    root.resizable(False, False)
    root.attributes("-topmost", True)
    try:
        root.iconbitmap(r'images\lego.ico')
    except tkinter.TclError:
        pass
    try:
        img = tk.PhotoImage(file=r'23.4.1/images\lego.png')
        label = tk.Label(root, image=img)
        label.pack()
    except tkinter.TclError:
        pass
    label2 = tk.Label(root, text='正在加载中,请稍后……', font=('宋体', 25))
    label2.pack()
    pr = tkinter.ttk.Progressbar(root, length=700)
    pr['maximum'] = 100
    pr['value'] = 0
    pr.pack()

    def a():
        try:
            for i in range(100):
                pr['value'] += 1
                label2.configure(text=f'正在加载……    (  {i}%  )')
                root.update()
                time.sleep(0.01)
            label2.configure(text=f'正在加载……    (  100%  ),完成!')
            root.update()
            time.sleep(0.001)
        except (tkinter.TclError, RuntimeError, Exception):
            return
        label2.configure(text=f'按窗口内任意位置以继续……')
        root.update()

        def aa(*args, **kwargs):
            root.destroy()

        root.bind('<Button-1>', aa)

    try:
        a()
    except tkinter.TclError:
        return
    root.mainloop()


def new():
    gui = GUI()
    gui.run()


def main():
    try:
        new()
        T_tk.mainloop()
    except (RuntimeError, tkinter.TclError, KeyboardInterrupt):
        sys.exit()


if __name__ == '__main__':
    main()

粘贴完直接成3万字“长文……”

下载链接:https://pan.baidu.com/s/1XNGPgbkfiu-vPXSRqzHtcw?pwd=cgy6 
提取码:cgy6

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值