自制代码编辑器:CASM Editor

news2025/1/20 1:58:54

哔哩哔哩演示视频:我使用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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1051691.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

计算机视觉: 可控的高质量人体生成

背景 关于人体动作的生成范式目前主流的方向可以分为以下两种: Sequence based motion generation: 给定控制信号然后一次性生成连续的动作&#xff0c;能生成一些连续高阶语义的动作信号&#xff0c;因为其能看到整个动作信号。eg: MDM: Human Motion Diffusion Model, Teve…

机器学习(20)---神经网络详解

神经网络 一、神经网络概述1.1 神经元模型1.2 激活函数 二、感知机2.1 概述2.2 实现逻辑运算2.3 多层感知机 三、神经网络3.1 工作原理3.2 前向传播3.3 Tensorflow实战演示3.3.1 导入数据集查看3.3.2 数据预处理3.3.3 建立模型3.3.4 评估模型 四、反向传播五、例题5.1 题15.2 题…

【SQL】Mysql 时区设置解决--20230928

https://blog.csdn.net/qq_44392492/article/details/108717616 输入命令show variables like “%time_zone%”;&#xff08;注意分号结尾&#xff09;设置时区&#xff0c;输入 set global time_zone “8:00”; 回车,然后退出重启&#xff08;一定记得重启&#xff0c;不然查…

Mysql 本地计算机无法启动 mysql 服务 错误 1067:进程意外终止

有时候一段时间本地mysql不用&#xff0c;在连接本地数据库的时候&#xff0c;会报mysql无法连接出现错误提示10061错误&#xff0c; 这时候一般是本地mysql服务没有启动 去左下角搜“服务”&#xff0c;进入后选择Mysql&#xff0c;点击启动&#xff08;我的截图是已经启动好…

C#,数值计算——Ranfib的计算方法与源程序

1 文本格式 using System; namespace Legalsoft.Truffer { /// <summary> /// Implements Knuths subtractive generator using only floating operations. See /// text for cautions. /// </summary> public class Ranfib { p…

通过茶叶酒水小程序商城的作用是什么?

茶叶酒水往往会在一起经营&#xff0c;同时又具备较强的送礼属性&#xff0c;需求度较高但经营商家同样不少&#xff0c;同行竞争激烈&#xff0c;加之同城生意有限、外地客户难以拓展、销售营销不足、品牌宣传效果差等痛点&#xff0c;传统酒水茶叶门店需要线上带来增长。 那…

大数据Flink(九十二):DML:集合操作

文章目录 DML:集合操作 DML:集合操作 集合操作支持 Batch\Streaming 任务。 UNION:将集合合并并且去重。

uni-app:js修改元素样式(宽度、外边距)

效果 代码 1、在<view>元素上添加一个ref属性&#xff0c;用于在JavaScript代码中获取对该元素的引用&#xff1a;<view ref"myView" id"mybox"></view> 2、获取元素引用 &#xff1a;const viewElement this.$refs.myView.$el; 3、修改…

【Flink】

事件驱动型应用 核心目标&#xff1a;数据流上的有状态计算 Apache Flink是一个框架和分布式处理引擎&#xff0c;用于对无界或有界数据流进行有状态计算。 运行逻辑 状态 把流处理需要的额外数据保存成一个“状态”,然后针对这条数据进行处理,并且更新状态。这就是所谓的“…

mrctf2020_shellcode_revenge

mrctf2020_shellcode_revenge Arch: amd64-64-little RELRO: Full RELRO Stack: No canary found NX: NX disabled PIE: PIE enabled RWX: Has RWX segments64位&#xff0c;开了PIE和RELRO&#xff0c;看到RWX出来&#xff0c;就感觉是shellcode了…

如何使用PyInstaller打包Python应用(包含参数详解,spec文件详解,反编译和防止反编译)

文章目录 介绍PyInstaller安装PyInstaller参数及使用方法PyInstaller打包技巧和注意事项反编译和防止反编译介绍PyInstaller PyInstaller是一个强大的Python打包工具,它可以将Python程序打包成独立的可执行文件,方便在不同的操作系统上分发和运行。使用PyInstaller,你可以将…

react.js在visual code 下的hello World

想学习reacr.js &#xff0c;就开始做一个hello world。 我的环境是visual code &#xff0c;所以我找这个环境下的例子。参照&#xff1a; https://code.visualstudio.com/docs/nodejs/reactjs-tutorial 要学习react.js &#xff0c;还得先安装node.js&#xff0c;我在visual …

Mysql高级语句(进阶查询语句、数据库函数、连接查询)

Mysql高级语句&#xff08;进阶查询语句、MySQL数据库函数、连接查询 一、mysql查询语句1.1、 select ----显示表格中一个或数个字段的所有数据记录1.2、 distinct ----不显示重复的数据记录1.3、where ----有条件查询1.4、 and or ----且 或1.5 、in----显示已知的值的数据记录…

9_分类算法—决策树

文章目录 1 信息熵1.1 比特化&#xff08;Bits&#xff09;1.2 一般化的比特化&#xff08;Bits&#xff09;1.3 信息熵&#xff08;Entropy&#xff09;1.3.1 熵越大混乱程度越大 1.4 条件熵H&#xff08;YIX&#xff09; 2 决策树2.1 什么是决策树2.2 决策树构建过程&#xf…

MySQL 索引的作用、索引结构及执行流程介绍(索引篇 一)

索引介绍 MySQL索引&#xff08;index&#xff09;是一种用于加快数据库中数据搜索和查询的数据结构。它类似于书籍的目录&#xff0c;可以帮助数据库快速定位和访问特定数据&#xff0c;而无需扫描整个数据表。 索引的作用和缺点 1. 加快数据搜索&#xff1a;通过使用索引&…

《C++ Primer》练习7.31:定义互相嵌套的类

类可以先声明再定义&#xff0c;可以用下面这个题目理解一下 class Y; class X {Y *y; };class Y {X x; };未出现的类类型要在前面声明。 参考 《C Primer》

0x84加密数据传输服务

为了在安全模式下实现一些诊断服务&#xff0c;在服务端和客户端应用程序之间添加了Security sub-layer。在客户端与服务端之间进行诊断服务数据传输有两种方法&#xff1a; 1、非安全模式下数据传输   应用程序使用诊断服务(diagnostic Services)和应用层服务原语(Applicati…

网络-跨域解决

文章目录 前言一、跨域是什么&#xff1f;二、跨域的解决1.JSONP2.前端代理dev环境3.后端设置请求头CORS4.运维nginx代理 总结 前言 本文主要介绍跨域问题介绍并提供了四种解决办法。 一、跨域是什么&#xff1f; 准确的来说是浏览器存在跨域问题&#xff0c;浏览器为了安全考…

pygame实现跳跃发射子弹打怪效果

import pygame import sys,time,random from pygame.locals import * pygame.init() # 设置按下鼠标的时候一直触发 pygame.key.set_repeat(10, 10) # 加载背景图片 bg pygame.image.load(./img/bg.png) # 加载左方向行走和站立图片 heroLStand pygame.image.load(img/heroLs…

IoT 物联网 JavaScript 全栈开发,构建家居环境监控系统实战

智能家居环境监测端到端场景&#xff0c;全栈JavaScript开发&#xff0c;串联Ruff硬件、温湿度和空气质量传感器、阿里云 IoT、Serverless函数计算、百度ECharts可视化、最终以微信小程序形式在微信里实时展示家中实时温度&#xff0c;湿度&#xff0c;PM2.5指数。 01 技术架构…