• 自制代码编辑器:CASM Editor


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

    源代码:

    1. import idlelib.colorizer as idc
    2. import idlelib.percolator as idp
    3. import os
    4. import sys
    5. import threading
    6. import time
    7. import tkinter as T_tk
    8. import tkinter.filedialog as tf
    9. import tkinter.messagebox as tm
    10. import tkinter.scrolledtext as ts
    11. import tkinter.font as font
    12. import tkinter.ttk
    13. import re
    14. import ttkbootstrap as tk
    15. # version
    16. version = '0.8.1'
    17. running = 0
    18. class SettingFont:
    19. def __init__(self):
    20. self.__name = r"tools\cgy-tool-stg.def"
    21. try:
    22. with open(self.__name, encoding='utf-8') as a:
    23. self.font = a.readline().replace('\n', '')
    24. self.size = int(a.readline().replace('\n', ''))
    25. if self.size > 250 or self.size < 5:
    26. raise ValueError
    27. self.bold = a.readline().replace('\n', '')
    28. if self.bold == '':
    29. raise ValueError
    30. except (ValueError, OSError):
    31. self.font = 'Consolas'
    32. self.size = 20
    33. self.bold = 'normal'
    34. try:
    35. with open(self.__name, 'w', encoding='utf-8') as a:
    36. a.write(f'{self.font}\n{int(self.size)}\n{self.bold}')
    37. except OSError:
    38. def a(path):
    39. b = os.path.basename(path)
    40. c = len(list(b))
    41. return path[:-1 * c]
    42. os.mkdir(f'{a(__file__)}tools\\')
    43. with open(self.__name, 'w', encoding='utf-8') as a:
    44. a.write(f'{self.font}\n{int(self.size)}\n{self.bold}')
    45. def sf_return(self):
    46. return self.font, self.size, self.bold
    47. def shange(self, _font, size, bold):
    48. with open(self.__name, 'w', encoding='utf-8') as a:
    49. a.write(f'{_font}\n{size}\n{bold}')
    50. self.font = _font
    51. self.size = size
    52. self.bold = bold
    53. def check(self):
    54. try:
    55. with open(self.__name, 'r', encoding='utf-8') as a:
    56. _a = a.readline().replace('\n', '')
    57. if self.font == _a:
    58. b = int(a.readline().replace('\n', ''))
    59. if self.size == b:
    60. if b > 250 or b < 5:
    61. raise ValueError
    62. c = a.readline().replace('\n', '')
    63. if self.bold == c:
    64. if c == '':
    65. raise ValueError
    66. return False
    67. else:
    68. self.bold = c
    69. return True
    70. else:
    71. self.size = b
    72. return True
    73. else:
    74. self.font = _a
    75. return True
    76. except (ValueError, Exception):
    77. self.font = 'Consolas'
    78. self.size = 20
    79. self.bold = 'normal'
    80. try:
    81. with open(self.__name, 'w', encoding='utf-8') as a:
    82. a.write(f'{self.font}\n{int(self.size)}\n{self.bold}')
    83. except OSError:
    84. def a(path):
    85. _b = os.path.basename(path)
    86. _c = len(list(_b))
    87. return path[:-1 * _c]
    88. os.mkdir(f'{a(__file__)}tools\\')
    89. with open(self.__name, 'w', encoding='utf-8') as a:
    90. a.write(f'{self.font}\n{int(self.size)}\n{self.bold}')
    91. return True
    92. class SettingColor:
    93. def __init__(self):
    94. pass
    95. class GUI:
    96. def __init__(self):
    97. # vars
    98. self.a = None
    99. self.b = None
    100. self.c = None
    101. self.d = None
    102. self.p = None
    103. self.i = 0
    104. # wgts
    105. self.root = T_tk.Tk()
    106. self.root.title('CASM 文本编辑器')
    107. # Settings about fonts
    108. self.fs = SettingFont()
    109. self.font, self.size, self.bold = self.fs.sf_return()
    110. # Settings about colors
    111. self.cs = SettingColor()
    112. self.bg = "#ffffff"
    113. self.normal = '#000000'
    114. self.numbers = "#FFA500"
    115. self.comment = "#C0C0C0"
    116. self.keywords = "#00BFFF"
    117. self.builtin = "#7B68EE"
    118. self.string = "#FFA500"
    119. self.definition = "#228B22"
    120. self.symbol = "#FF0000"
    121. self.classmode = "#DA70D6"
    122. self.line = "#717171"
    123. # self.root.geometry('1500x900')
    124. # self.root.minsize(1500, 0)
    125. self.sb = tk.Scrollbar(self.root, orient=tk.HORIZONTAL)
    126. self.sb.pack(side=tk.BOTTOM, fill=tk.X)
    127. self.sb2 = tk.Scrollbar(self.root)
    128. self.sb2.pack(side=tk.RIGHT, fill=tk.Y)
    129. self.fall = tk.IntVar(self.root)
    130. self.text = tk.Text(self.root, undo=True, xscrollcommand=self.sb.set, yscrollcommand=self.sb2.set, wrap='none')
    131. self.text.config(font=(self.font, self.size, self.bold), background=self.bg, foreground=self.normal)
    132. self.numl = tk.Canvas(self.root, width=60, bg='white', highlightthickness=0)
    133. self.numl.pack(side=tk.LEFT, fill=tk.BOTH)
    134. self.text.pack(side=tk.LEFT, fill=tk.BOTH, expand=tk.YES)
    135. self.colorful = idc.color_config(self.text)
    136. self.sb.config(command=self.text.xview)
    137. self.menu = tk.Menu(self.root)
    138. self.popup = tk.Menu(self.root, tearoff=0)
    139. self.filemenu = tk.Menu(self.menu, tearoff=False)
    140. self.editmenu = tk.Menu(self.menu, tearoff=False)
    141. self.elsemenu = tk.Menu(self.menu, tearoff=False, selectcolor='green')
    142. self.saved = False
    143. self.running = False
    144. self.myrun = True
    145. self.installing = False
    146. self.name = ''
    147. self.lineall = 0
    148. self.old = 0
    149. def loadfile(self, file):
    150. file = '\n'.join((item.decode('gbk') for item in file)).split('\n')[0]
    151. self.open(name=file)
    152. def edit(self, text):
    153. self.text.delete(1.0, tk.END)
    154. self.text.insert(tk.END, text)
    155. def get(self):
    156. return self.text.get(1.0, tk.END).rstrip()
    157. def adds(self):
    158. self.fall.set(1) # 0开1关,默认关
    159. idc.color_config(self.text)
    160. self.p = idp.Percolator(self.text)
    161. self.text.focus_set()
    162. # windnd.hook_dropfiles(self.root, func=self.loadfile)
    163. self.check()
    164. def the_function_that_which_is_running_at_tkinter_key_press(event):
    165. self.redraw()
    166. self.see()
    167. self.redraw()
    168. if self.saved:
    169. self.save()
    170. self.character_completion(event)
    171. def the_function_that_which_is_running_at_tkinter_ctrl_v_press(*args):
    172. self.text.event_generate("<>")
    173. self.see()
    174. self.root.bind("", lambda event: the_function_that_which_is_running_at_tkinter_key_press(event))
    175. self.text.bind('', self.tab)
    176. self.text.bind('', self.untab)
    177. self.text.bind("", self.enter)
    178. self.text.bind("", self.backspace)
    179. self.text.bind("", self.redraw)
    180. self.text.bind("", self.redraw)
    181. self.text.bind("", self.redraw)
    182. self.root.bind("", self.redraw)
    183. self.root.bind("", self.redraw)
    184. try:
    185. self.root.iconbitmap(r'images\lego.ico')
    186. except tkinter.TclError:
    187. pass
    188. font_ = font.Font(root=self.root, font=self.text['font'])
    189. tab_width = font_.measure(' ' * 4)
    190. self.text.config(tabs=(tab_width,))
    191. self.root.protocol("WM_DELETE_WINDOW", self.when_exit_do)
    192. self.text.tag_configure('Found', background='black', foreground='white', underline=True)
    193. self.menu.add_cascade(label='文件', menu=self.filemenu)
    194. self.menu.add_cascade(label='编辑', menu=self.editmenu)
    195. self.menu.add_cascade(label='其他', menu=self.elsemenu)
    196. self.filemenu.add_command(label='新建 Ctrl+n', command=self.mynew)
    197. self.filemenu.add_command(label='保存 Ctrl+s', command=self.save)
    198. self.filemenu.add_command(label='另存为 Ctrl+e', command=self.saveas)
    199. self.filemenu.add_command(label='打开文件 Ctrl+f', command=self.open)
    200. self.filemenu.add_command(label='运行 Ctrl+r', command=self.runtext)
    201. self.filemenu.add_command(label='退出 Ctrl+q', command=self.when_exit_do)
    202. self.editmenu.add_command(label='替换 Ctrl+Alt+r', command=self.replace)
    203. self.editmenu.add_command(label='寻找 Ctrl+Alt+f', command=self.find)
    204. self.editmenu.add_command(label='字数统计 Ctrl+Alt+t', command=self.count)
    205. self.editmenu.add_command(label='设置 Ctrl+Alt+s', command=self.changestg)
    206. self.elsemenu.add_command(label='快捷键 Ctrl+Alt+e', command=self.elsekey)
    207. self.elsemenu.add_command(label='关于 Ctrl+Alt+a',
    208. command=lambda: tm.showinfo('关于', '本编辑器由保定曹高远制作。原创。'))
    209. self.elsemenu.add_command(label='关于文件 Ctrl+Alt+f', command=self.about_file)
    210. self.elsemenu.add_checkbutton(label="全屏 F11", variable=self.fall, offvalue=0, onvalue=1,
    211. command=lambda: self._falls())
    212. self.root.bind('', lambda event: self.mynew())
    213. self.root.bind('', lambda event: self.save())
    214. self.root.bind('', lambda event: self.saveas())
    215. self.root.bind('', lambda event: self.runtext())
    216. self.root.bind('', lambda event: self.open())
    217. self.root.bind('', lambda event: self.when_exit_do())
    218. self.root.bind('', lambda event: self.replace())
    219. self.root.bind('', lambda event: self.find())
    220. self.root.bind('', lambda event: self.count())
    221. self.root.bind('', lambda event: self.changestg())
    222. self.root.bind('', lambda event: self.elsekey())
    223. self.root.bind('', lambda event: self.about_file())
    224. self.root.bind('', lambda event: tm.showinfo('关于', '本编辑器由伟大的天才曹高远制作。'))
    225. self.root.bind('', lambda event: self.bigorsmall_font(event))
    226. self.root.bind('', lambda event: self.falls())
    227. self.popup.add_command(label='复制', command=lambda: self.text.event_generate("<>"))
    228. self.popup.add_command(label='剪切', command=lambda: self.text.event_generate("<>"))
    229. self.popup.add_command(label='粘贴', command=the_function_that_which_is_running_at_tkinter_ctrl_v_press)
    230. self.root.bind("", self.popup_menu)
    231. self.root.config(menu=self.menu)
    232. def falls(self):
    233. a = self.fall.get()
    234. if a == 1:
    235. self.root.attributes("-fullscreen", False)
    236. self.fall.set(0) # 改变状态
    237. else:
    238. self.root.attributes("-fullscreen", True)
    239. self.fall.set(1)
    240. def _falls(self):
    241. a = self.fall.get()
    242. if a == 0:
    243. self.root.attributes("-fullscreen", False) # 不改变状态
    244. else:
    245. self.root.attributes("-fullscreen", True)
    246. def see(self):
    247. self.text.see(str(float(int(float(self.text.index('insert'))) + 2))) # 一直显示光标所在行
    248. def __update__(self, *args):
    249. while True:
    250. self.root.update()
    251. new = str(int(float(self.text.index('insert'))))
    252. if new != self.old:
    253. self.old = new
    254. self.redraw()
    255. try:
    256. if self.fs.check():
    257. self.font, self.size, self.bold = self.fs.sf_return()
    258. self.update()
    259. except RuntimeError:
    260. break
    261. def insert_get(self):
    262. start = tk.SEL_FIRST
    263. end = tk.SEL_LAST
    264. is_insert = True if self.text.get(start, end) != '' else False
    265. return is_insert, self.text.index(start), self.text.index(end)
    266. def update(self):
    267. self.text.config(font=(self.font, self.size, self.bold))
    268. self.redraw()
    269. def tab(self, *args):
    270. is_insert, start, end = self.insert_get()
    271. if not is_insert:
    272. self.text.insert('insert', ' ')
    273. else:
    274. start = int(float(start))
    275. end = int(float(end))
    276. for i in range(start, end + 1):
    277. self.text.insert(str(float(i)), ' ')
    278. return 'break'
    279. def untab(self, *args):
    280. is_insert, start, end = self.insert_get()
    281. if not is_insert:
    282. last = str(int(''.join(list(self.text.index('insert'))[
    283. (-1 * (len(os.path.splitext(self.text.index('insert'))[-1]) - 1)):])) - 4)
    284. all_insert = ''.join(list(self.text.index('insert'))[
    285. :(-1 * (len(os.path.splitext(self.text.index('insert'))[-1]) - 1))]) + last
    286. if self.text.get(all_insert, 'insert') == ' ':
    287. self.text.delete(all_insert, 'insert')
    288. else:
    289. start = self.text.index(start)
    290. end = self.text.index(end)
    291. for i in range(int(float(start)), int(float(end)) + 1):
    292. last = str(int(''.join(list(self.text.index(str(float(i))))[
    293. (-1 * (len(os.path.splitext(self.text.index(str(float(i))))[-1]) - 1)):])) + 4)
    294. all_insert = ''.join(list(self.text.index(str(float(i))))[
    295. :(-1 * (len(os.path.splitext(self.text.index(str(float(i))))[-1]) - 1))]) + last
    296. if self.text.get(str(float(i)), all_insert) == ' ':
    297. self.text.delete(str(float(i)), all_insert)
    298. return 'break'
    299. def popup_menu(self, event):
    300. self.popup.post(event.x_root, event.y_root) # 弹出右键菜单
    301. def mynew(self):
    302. GUI().run()
    303. def redraw(self, *args):
    304. try:
    305. global linenum
    306. self.numl.delete("all")
    307. i = self.text.index("@0,0")
    308. while True:
    309. dline = self.text.dlineinfo(i)
    310. if dline is None:
    311. break
    312. y = dline[1]
    313. linenum = str(i).split(".")[0]
    314. self.numl.create_text(2, y, anchor="nw", text=linenum, fill=self.line,
    315. font=(self.font, self.size, self.bold))
    316. i = self.text.index("%s+1line" % i)
    317. _font = font.Font(root=self.root, family=self.font, size=self.size)
    318. w = _font.measure('0')
    319. self.numl.config(width=len(linenum) * w + 5)
    320. self.lineall = linenum
    321. except RuntimeError:
    322. pass
    323. def save(self):
    324. if self.name == '':
    325. self.name = tf.asksaveasfilename(initialfile='main.casm', defaultextension='.casm',
    326. filetypes=(('CASM文件', ('*.casm', '*.txt')), ('所有文件', '*.*')))
    327. if self.name == '':
    328. return
    329. try:
    330. with open(self.name, 'w', encoding='utf-8') as casm:
    331. casm.write(self.text.get(1.0, tk.END)[:-1])
    332. except:
    333. self.name = ''
    334. else:
    335. self.saved = True
    336. self.root.title(self.name)
    337. else:
    338. try:
    339. with open(self.name, 'w', encoding='utf-8') as casm:
    340. casm.write(self.text.get(1.0, tk.END)[:-1])
    341. except OSError:
    342. pass
    343. def saveas(self):
    344. if self.saved:
    345. if self.running:
    346. tm.showerror('文本编辑器', '文件正在运行,请先关闭。')
    347. return
    348. self.name = tf.asksaveasfilename(initialfile='main.casm', defaultextension='.casm',
    349. filetypes=(('CASM文件', ('*.casm', '*.txt')), ('所有文件', '*.*')))
    350. if self.name == '':
    351. return
    352. try:
    353. with open(self.name, 'w', encoding='utf-8') as casm:
    354. casm.write(self.text.get(1.0, tk.END)[:-1])
    355. except:
    356. self.name = ''
    357. else:
    358. self.saved = True
    359. self.root.title(self.name)
    360. def highins(self, text: str):
    361. self.text.insert(tk.END, text)
    362. def open(self, name=''):
    363. if self.running:
    364. tm.showerror('文本编辑器', '文件正在运行,请先关闭。')
    365. return
    366. if name == '':
    367. if self.name == '':
    368. self.name = tf.askopenfilename(
    369. filetypes=(("CASM文件", ("*.casm", '*.txt')), ("所有文件", "*.*")))
    370. if self.name == '':
    371. return
    372. try:
    373. with open(self.name, encoding='utf-8') as casm:
    374. self.text.delete(1.0, tk.END)
    375. self.highins(casm.read())
    376. except UnicodeError:
    377. self.saved = False
    378. self.redraw()
    379. self.name = ''
    380. self.root.title('CASM 文本编辑器')
    381. tm.showerror('文本编辑器', '我们只支持编码为utf-8文件。')
    382. except PermissionError:
    383. self.saved = False
    384. self.redraw()
    385. self.name = ''
    386. self.root.title('CASM 文本编辑器')
    387. tm.showerror('Error', '权限不足,访问被拒绝')
    388. else:
    389. self.check()
    390. self.redraw()
    391. self.saved = True
    392. self.root.title(self.name)
    393. self.text.edit_reset() # 重置文本框的撤销功能
    394. else:
    395. a = tm.askokcancel(self.name, '你已打开了一个文件,要把它关闭并保存在打开新文件吗?')
    396. if a:
    397. self.name = tf.askopenfilename(
    398. filetypes=(("CASM文件", ("*.casm", '*.txt')), ("所有文件", "*.*")))
    399. if self.name == '':
    400. return
    401. try:
    402. with open(self.name, encoding='utf-8') as casm:
    403. self.text.delete(1.0, tk.END)
    404. self.highins(casm.read())
    405. except UnicodeError:
    406. self.saved = False
    407. self.redraw()
    408. self.name = ''
    409. self.root.title('CASM 文本编辑器')
    410. tm.showerror('文本编辑器', '我们只支持编码为utf-8文件。')
    411. except PermissionError:
    412. self.saved = False
    413. self.redraw()
    414. self.name = ''
    415. self.root.title('CASM 文本编辑器')
    416. tm.showerror('Error', '权限不足,访问被拒绝')
    417. else:
    418. self.check()
    419. self.redraw()
    420. self.saved = True
    421. self.root.title(self.name)
    422. self.text.edit_reset()
    423. else:
    424. if self.name == '':
    425. try:
    426. with open(name, encoding='utf-8') as casm:
    427. self.text.delete(1.0, tk.END)
    428. self.highins(casm.read())
    429. except UnicodeError:
    430. self.saved = False
    431. self.redraw()
    432. self.root.title('CASM 文本编辑器')
    433. tm.showerror('文本编辑器', '我们只支持编码为utf-8文件。')
    434. except PermissionError:
    435. self.saved = False
    436. self.redraw()
    437. self.root.title('CASM 文本编辑器')
    438. tm.showerror('Error', '权限不足,访问被拒绝')
    439. except OSError:
    440. self.saved = False
    441. self.redraw()
    442. self.text.delete(1.0, tk.END)
    443. self.text.insert(tk.END, name)
    444. else:
    445. self.name = name
    446. self.check()
    447. self.redraw()
    448. self.saved = True
    449. self.root.title(self.name)
    450. self.text.edit_reset()
    451. else:
    452. a = tm.askokcancel(self.name, '你已打开了一个文件,要把它关闭并保存在打开新文件吗?')
    453. if a:
    454. try:
    455. with open(name, encoding='utf-8') as casm:
    456. self.text.delete(1.0, tk.END)
    457. self.highins(casm.read())
    458. except UnicodeError:
    459. self.saved = False
    460. self.redraw()
    461. self.root.title('CASM 文本编辑器')
    462. tm.showerror('文本编辑器', '我们只支持编码为utf-8文件。')
    463. except PermissionError:
    464. self.saved = False
    465. self.redraw()
    466. self.root.title('CASM 文本编辑器')
    467. tm.showerror('Error', '权限不足,访问被拒绝')
    468. except OSError:
    469. self.saved = False
    470. self.redraw()
    471. self.text.delete(1.0, tk.END)
    472. self.text.insert(tk.END, name)
    473. else:
    474. self.name = name
    475. self.check()
    476. self.redraw()
    477. self.saved = True
    478. self.root.title(self.name)
    479. self.text.edit_reset()
    480. def make_pat(self):
    481. def _any(name, alternates):
    482. return "(?P<%s>" % name + "|".join(alternates) + ")"
    483. kwlist = ["FUNC", "VAR", "IFE", "IFB", "IFS", "GOTO", "IF", "RET"]
    484. kw = r"\b" + _any("KEYWORD", kwlist) + r"\b"
    485. builtinlist = ["TYPE", "PUSH", "OUT", "ENDL", "PUSHCOMMENT", "POP", "ADD", "SUB", "MUL", "DIV", "MOD", "IN",
    486. "GETVAR", "PUSHVAR", "EXIT", "RAND", "NOT", "CLEAR", "STR", "INT", "BOOL", "DOUBLE", "FLOAT",
    487. "CHAR"]
    488. # builtin = r"([^.'\"\\#]\b|^)" + _any("BUILTIN", builtinlist) + r"\b"
    489. builtin = r"\b" + _any("BUILTIN", builtinlist) + r"\b"
    490. comment = _any("COMMENT", [r";[^\n]*"])
    491. number = _any("NUM", [r"\b[0-9]+(?![0-9]+)\b"])
    492. prog = re.compile("|".join([
    493. builtin, comment, kw, number,
    494. _any("SYNC", [r"\n"]),
    495. ]),
    496. re.DOTALL | re.MULTILINE)
    497. return prog
    498. def check(self):
    499. if (os.path.splitext(self.name)[-1] in ['.casm', '.txt']) or self.name == '':
    500. try:
    501. self.p.removefilter(self.d)
    502. except AssertionError:
    503. pass
    504. self.d = idc.ColorDelegator()
    505. self.d.prog = self.make_pat()
    506. self.d.tagdefs['COMMENT'] = {'foreground': self.comment}
    507. self.d.tagdefs['KEYWORD'] = {'foreground': self.keywords}
    508. self.d.tagdefs['BUILTIN'] = {'foreground': self.builtin}
    509. self.d.tagdefs['NUM'] = {'foreground': self.numbers}
    510. try:
    511. self.p.insertfilter(self.d)
    512. except AssertionError:
    513. pass
    514. else:
    515. try:
    516. self.p.removefilter(self.d)
    517. except AssertionError:
    518. pass
    519. self.d = idc.ColorDelegator()
    520. self.d.prog = self.make_pat()
    521. self.d.tagdefs['COMMENT'] = {'foreground': self.normal}
    522. self.d.tagdefs['KEYWORD'] = {'foreground': self.normal}
    523. self.d.tagdefs['BUILTIN'] = {'foreground': self.normal}
    524. self.d.tagdefs['NUM'] = {'foreground': self.normal}
    525. try:
    526. self.p.insertfilter(self.d)
    527. except AssertionError:
    528. pass
    529. def runtext(self):
    530. if self.saved:
    531. if not self.running:
    532. self.save()
    533. print(self.name[-5:])
    534. if self.name[-5:] == '.casm':
    535. path = self.name.split('/')
    536. path = '\\'.join(path[:-1])
    537. cmd = f'{self.name[:2]} & cd \"{path}\\\" & casm.exe \"{self.name}\" & pause' # 加‘&’连续执行cmd命令
    538. elif self.name[-4:] == '.txt':
    539. path = self.name.split('/')
    540. path = '\\'.join(path[:-1])
    541. cmd = f'{self.name[:2]} & cd \"{path}\\\" & casm.exe \"{self.name}\"'
    542. else:
    543. cmd = ''
    544. def aa():
    545. self.running = True
    546. print("cmd:",cmd)
    547. os.system(cmd)
    548. self.running = False
    549. self.a = threading.Thread(target=aa)
    550. self.a.start()
    551. else:
    552. tm.showerror(self.name, '文件已运行')
    553. else:
    554. self.mycallsave()
    555. def mycallsave(self):
    556. tm.showinfo('文本编辑器', '你没有保存这个文件,请先保存。')
    557. self.save()
    558. def run(self):
    559. global running
    560. running += 1
    561. self.adds()
    562. self.redraw()
    563. self.falls()
    564. while True:
    565. self.__update__()
    566. def enter(self, *args):
    567. self.i = 0
    568. a = self.text.index('insert')
    569. aa = int(float(a))
    570. b = self.text.get(float(aa), a).replace('\n', '')
    571. c = b
    572. if b[0:5] == 'FUNC ':
    573. i = 0
    574. while True:
    575. if b[:4] == ' ':
    576. b = b[4:]
    577. i += 1
    578. else:
    579. break
    580. self.i = i + 1
    581. else:
    582. i = 0
    583. while True:
    584. if b[:4] == ' ':
    585. b = b[4:]
    586. i += 1
    587. else:
    588. break
    589. self.i = i
    590. try:
    591. a = c.strip().split()[0]
    592. except IndexError:
    593. a = ''
    594. self.text.insert('insert', '\n')
    595. for j in range(self.i):
    596. self.text.insert('insert', ' ')
    597. self.redraw()
    598. self.see()
    599. return 'break'
    600. def backspace(self, *args):
    601. _dict = {'(': ')', '{': '}', '[': ']', '"': '"', "'": "'"}
    602. last = str(int(''.join(list(self.text.index('insert'))[
    603. (-1 * (len(os.path.splitext(self.text.index('insert'))[-1]) - 1)):])) - 1)
    604. all_insert = ''.join(list(self.text.index('insert'))[
    605. :(-1 * (len(os.path.splitext(self.text.index('insert'))[-1]) - 1))]) + last
    606. a = self.text.get(all_insert, 'insert')
    607. if a in ['(', '{', '[', '"', "'"]:
    608. last = str(int(''.join(list(self.text.index('insert'))[
    609. (-1 * (len(os.path.splitext(self.text.index('insert'))[-1]) - 1)):])) + 1)
    610. all_insert = ''.join(list(self.text.index('insert'))[
    611. :(-1 * (len(os.path.splitext(self.text.index('insert'))[-1]) - 1))]) + last
    612. b = self.text.get('insert', all_insert)
    613. if b == _dict[a]: # 符合条件,删除2个
    614. last1 = str(int(''.join(list(self.text.index('insert'))[
    615. (-1 * (len(os.path.splitext(self.text.index('insert'))[-1]) - 1)):])) - 1)
    616. all_insert1 = ''.join(list(self.text.index('insert'))[
    617. :(-1 * (len(os.path.splitext(self.text.index('insert'))[-1]) - 1))]) + last1
    618. last2 = str(int(''.join(list(self.text.index('insert'))[
    619. (-1 * (len(os.path.splitext(self.text.index('insert'))[-1]) - 1)):])) + 1)
    620. all_insert2 = ''.join(list(self.text.index('insert'))[
    621. :(-1 * (len(os.path.splitext(self.text.index('insert'))[-1]) - 1))]) + last2
    622. self.text.delete(all_insert1, all_insert2)
    623. return 'break'
    624. else:
    625. last1 = str(int(''.join(list(self.text.index('insert'))[
    626. (-1 * (len(os.path.splitext(self.text.index('insert'))[-1]) - 1)):])) - 4)
    627. all_insert1 = ''.join(list(self.text.index('insert'))[
    628. :(-1 * (len(os.path.splitext(self.text.index('insert'))[-1]) - 1))]) + last1
    629. if self.text.get(all_insert1, 'insert') == ' ':
    630. self.text.delete(all_insert1, 'insert')
    631. return 'break'
    632. def character_completion(self, event: T_tk.Event): # 字符补全(对【(】、【[】、【{】等进行自动补全)
    633. a = event.keysym
    634. if a == 'parenleft': # (
    635. self.text.insert("insert", ')')
    636. last = str(int(''.join(list(self.text.index('insert'))[
    637. (-1 * (len(os.path.splitext(self.text.index('insert'))[-1]) - 1)):])) - 1)
    638. all_insert = ''.join(list(self.text.index('insert'))[
    639. :(-1 * (len(os.path.splitext(self.text.index('insert'))[-1]) - 1))]) + last
    640. self.text.mark_set('insert', all_insert)
    641. elif a == 'braceleft': # {
    642. self.text.insert("insert", '}')
    643. last = str(int(''.join(list(self.text.index('insert'))[
    644. (-1 * (len(os.path.splitext(self.text.index('insert'))[-1]) - 1)):])) - 1)
    645. all_insert = ''.join(list(self.text.index('insert'))[
    646. :(-1 * (len(os.path.splitext(self.text.index('insert'))[-1]) - 1))]) + last
    647. self.text.mark_set('insert', all_insert)
    648. elif a == 'bracketleft': # [
    649. self.text.insert("insert", ']')
    650. last = str(int(''.join(list(self.text.index('insert'))[
    651. (-1 * (len(os.path.splitext(self.text.index('insert'))[-1]) - 1)):])) - 1)
    652. all_insert = ''.join(list(self.text.index('insert'))[
    653. :(-1 * (len(os.path.splitext(self.text.index('insert'))[-1]) - 1))]) + last
    654. self.text.mark_set('insert', all_insert)
    655. elif a == 'quotedbl':
    656. self.text.insert("insert", '"')
    657. last = str(int(''.join(list(self.text.index('insert'))[
    658. (-1 * (len(os.path.splitext(self.text.index('insert'))[-1]) - 1)):])) - 1)
    659. all_insert = ''.join(list(self.text.index('insert'))[
    660. :(-1 * (len(os.path.splitext(self.text.index('insert'))[-1]) - 1))]) + last
    661. self.text.mark_set('insert', all_insert)
    662. elif a == "apostrophe":
    663. self.text.insert("insert", "'")
    664. last = str(int(''.join(list(self.text.index('insert'))[
    665. (-1 * (len(os.path.splitext(self.text.index('insert'))[-1]) - 1)):])) - 1)
    666. all_insert = ''.join(list(self.text.index('insert'))[
    667. :(-1 * (len(os.path.splitext(self.text.index('insert'))[-1]) - 1))]) + last
    668. self.text.mark_set('insert', all_insert)
    669. '''EDIT TOOLS'''
    670. def __replace(self, ta, tb, num):
    671. if ta and tb and num:
    672. num = int(num)
    673. if num == -1:
    674. a = self.get()
    675. a = a.replace(ta, tb)
    676. self.edit(a)
    677. elif num >= 0:
    678. pass
    679. else:
    680. a = self.get()
    681. a = a.replace(ta, tb, num)
    682. self.edit(a)
    683. else:
    684. tm.showerror('文本编辑器', '文本框不可留空!')
    685. def replace(self):
    686. if self.name != '':
    687. self.save()
    688. root = tk.Toplevel()
    689. root.title('替换')
    690. root.resizable(False, False)
    691. try:
    692. root.iconbitmap(r'images\lego.ico')
    693. except tkinter.TclError:
    694. pass
    695. label = tk.Label(root, text=u'原始内容:')
    696. label.grid(padx=10, pady=10, row=0, column=0)
    697. entry = tk.Entry(root)
    698. entry.grid(padx=10, pady=10, row=0, column=1)
    699. label2 = tk.Label(root, text=u'替换为:')
    700. label2.grid(padx=10, pady=10, row=1, column=0)
    701. entry2 = tk.Entry(root)
    702. entry2.grid(padx=10, pady=10, row=1, column=1)
    703. label3 = tk.Label(root, text='次数(-1为全部替换)')
    704. label3.grid(padx=10, pady=10, row=2, column=0)
    705. entry3 = tk.Entry(root)
    706. entry3.grid(padx=10, pady=10, row=2, column=1)
    707. btn = tk.Button(root, text='替换!',
    708. command=lambda: self.__replace(entry.get(), entry2.get(), entry3.get()))
    709. btn.grid(padx=10, pady=10, row=3, column=0)
    710. root.mainloop()
    711. else:
    712. self.mycallsave()
    713. def __find(self, msg: str):
    714. if self.name:
    715. if msg:
    716. i = 0
    717. self.text.tag_remove('Found', '1.0', tk.END)
    718. start = '1.0'
    719. if len(msg.rstrip()) == 0:
    720. return 0
    721. while True:
    722. pos = self.text.search(msg, start, tk.END)
    723. if pos == '':
    724. break
    725. i += 1
    726. self.text.tag_add('Found', pos, '%s+%dc' % (pos, len(msg)))
    727. start = '%s+%dc' % (pos, len(msg))
    728. return i
    729. else:
    730. tm.showerror('文本编辑器', '文本框不可留空!')
    731. else:
    732. self.mycallsave()
    733. def delatefind(self):
    734. self.text.tag_remove('Found', '1.0', tk.END)
    735. def runfind(self, msg):
    736. a = self.__find(msg)
    737. tm.showinfo(self.name, f'共找到"{msg}"{a}个。')
    738. def find(self):
    739. if self.name != '':
    740. self.save()
    741. root = tk.Toplevel()
    742. root.title('查找')
    743. try:
    744. root.iconbitmap(r'images\lego.ico')
    745. except tkinter.TclError:
    746. pass
    747. root.resizable(False, False)
    748. entry = tk.Entry(root)
    749. entry.grid(row=1, column=0, pady=10, padx=10)
    750. btn1 = tk.Button(root, text='寻找', command=lambda: self.runfind(entry.get().rstrip()))
    751. btn1.grid(row=1, column=1, padx=10, pady=10)
    752. btn2 = tk.Button(root, text='清空', command=self.delatefind)
    753. btn2.grid(row=1, column=2, padx=10, pady=10)
    754. root.mainloop()
    755. def count(self):
    756. '''字数统计'''
    757. if self.name != '':
    758. self.save()
    759. a = self.get()
    760. a = len(list(a))
    761. tm.showinfo('字数统计', f'文件{self.name}有字符{a}个')
    762. else:
    763. self.mycallsave()
    764. def bigorsmall_font(self, event):
    765. if event.delta > 0:
    766. if self.size < 250:
    767. self.size += 1
    768. self.text.config(font=(self.font, self.size, self.bold))
    769. self.redraw()
    770. font_ = font.Font(root=self.root, font=self.text['font'])
    771. tab_width = font_.measure(' ' * 4)
    772. self.text.config(tabs=tab_width)
    773. else:
    774. tm.showerror('CASM编辑器', '字体过大')
    775. else:
    776. if self.size > 5:
    777. self.size -= 1
    778. self.text.config(font=(self.font, self.size, self.bold))
    779. self.redraw()
    780. font_ = font.Font(root=self.root, font=self.text['font'])
    781. tab_width = font_.measure(' ' * 4)
    782. self.text.config(tabs=tab_width)
    783. else:
    784. tm.showerror('CASM编辑器', '字体过小')
    785. self.fs.shange(self.font, int(self.size), self.bold)
    786. def changestg(self):
    787. root = tk.Toplevel()
    788. root.title('设置')
    789. root.geometry('300x250')
    790. try:
    791. root.iconbitmap(r'images\lego.ico')
    792. except tkinter.TclError:
    793. pass
    794. root.resizable(False, False)
    795. notepad = tkinter.ttk.Notebook(root)
    796. fr1 = tk.Frame(root)
    797. notepad.add(fr1, text='设置')
    798. var = tk.StringVar(root)
    799. var3 = tk.BooleanVar(root)
    800. var3.set(True if self.bold == "bold" else False)
    801. fontsfam = sorted([i for i in font.families(root) if not i.startswith("@")], reverse=True)
    802. fontsfam = tuple(fontsfam)
    803. var.set(self.font)
    804. var2 = tk.IntVar(root)
    805. var2.set(self.size)
    806. label = tk.Label(fr1, text=u'字体:')
    807. label.grid(row=0, column=0, padx=10, pady=10)
    808. cb = tkinter.ttk.Combobox(fr1, textvariable=var, values=fontsfam, width=30,
    809. state='readonly') # state='readonly':将下拉列表设置成为只读模式
    810. cb.grid(row=0, column=1, pady=10, padx=10)
    811. label2 = tk.Label(fr1, text='大小')
    812. label2.grid(row=1, column=0, pady=10, padx=10)
    813. sl = tk.Scale(fr1, from_=1, to=100, orient=tk.HORIZONTAL, length=250, variable=var2)
    814. sl.grid(row=1, column=1, padx=10, pady=10)
    815. label3 = tk.Label(fr1, text='是否粗体')
    816. label3.grid(row=2, column=0, pady=10, padx=10)
    817. ck = tk.Checkbutton(fr1, text='使用粗体', variable=var3)
    818. ck.grid(row=2, column=1, padx=10, pady=10)
    819. def a():
    820. aa = var.get().rstrip()
    821. bb = var2.get()
    822. cc = var3.get()
    823. self.fs.shange(aa, bb, "bold" if cc else "normal")
    824. self.font = aa
    825. self.size = bb
    826. self.bold = "bold" if cc else "normal"
    827. self.text.config(font=(self.font, self.size, self.bold))
    828. font_ = font.Font(root=self.root, font=self.text['font'])
    829. tab_width = font_.measure(' ' * 4)
    830. self.text.config(tabs=(tab_width,))
    831. root.destroy()
    832. btn = tk.Button(fr1, text='确认', command=a)
    833. btn.grid(row=3, column=0, padx=10, pady=10)
    834. fr2 = tk.Frame(root)
    835. notepad.add(fr2, text='预览')
    836. sb = tk.Scrollbar(fr2, orient=tk.HORIZONTAL)
    837. sb.pack(side=tk.BOTTOM, fill=tk.X)
    838. text = ts.ScrolledText(fr2, width=300, height=200, wrap='none', xscrollcommand=sb.set)
    839. def textv(*args):
    840. text.config(font=(var.get().rstrip(), var2.get(), "bold" if var3.get() else "normal"))
    841. root.geometry('%dx%d' % (600, 550))
    842. def labelv(*args):
    843. root.geometry('%dx%d' % (350, 220))
    844. text.bind('', textv)
    845. label.bind('', labelv)
    846. text.insert(tk.END, '''
    847. abcdefghijklmnopqrstuvwxyz
    848. ABCDEFGHIJKLMNOPQRSTUVWXYZ
    849. CASM editor is a small and lightweight editor.
    850. CASM editor是一个小巧轻量的编辑器。
    851. CASM Editor - это небольшой и легкий редактор.
    852. CASM editorは小型軽量のエディタです。
    853. CASM editor는 작고 가벼운 편집기입니다.
    854. CASM တည်းဖြတ်ချက်ဟာ ချိတ်ဆက်နဲ့ လျှော့လင့်တဲ့ တည်းဖြတ်ချက်ပါ။
    855. Casm Editor est un éditeur petit et léger.
    856. Editor CASM editor compact and lightweight editor est.
    857. El editor casm es un editor pequeño y ligero.
    858. CASM editor é um editor compacto e leve.
    859.  المستخلصات المحرر هو صغير وخفيف الوزن المحرر . 
    860. CASM सम्पादकम्य सङ्केतं चित्रकं सम्पादकम्
    861. ເຄື່ອງມືແກ້ໄຂCAS ເປັນຜູ້ກ່ຽວກັບຄຳແກ້ກແລະຄຳແກ້ໄຫລາຍດິນ
    862. ''')
    863. text.config(font=(var.get().rstrip(), var2.get(), "bold" if var3.get() else "normal"))
    864. sb.config(command=text.xview)
    865. text.pack()
    866. notepad.pack()
    867. root.mainloop()
    868. def elsekey(self):
    869. root = tk.Toplevel()
    870. root.title('其他')
    871. text = ts.ScrolledText(root)
    872. try:
    873. root.iconbitmap(r'images\lego.ico')
    874. except tkinter.TclError:
    875. pass
    876. text.config(font=(self.font, self.size, self.bold))
    877. text.insert(1.0, '\n*****************快捷键*******************\n')
    878. text.insert(tk.END, '\n')
    879. text.insert(tk.END, '1. 复制 Ctrl+c\n')
    880. text.insert(tk.END, '\n')
    881. text.insert(tk.END, '2. 粘贴 Ctrl+v\n')
    882. text.insert(tk.END, '\n')
    883. text.insert(tk.END, '3. 剪切 Ctrl+x\n')
    884. text.insert(tk.END, '\n')
    885. text.insert(tk.END, '4. 重做 Ctrl+z\n')
    886. text.insert(tk.END, '\n')
    887. text.insert(tk.END, '5. 返回 Ctrl+y\n')
    888. text.insert(tk.END, '\n')
    889. text.insert(tk.END, '6. 全选 Ctrl+a\n')
    890. text.insert(tk.END, '\n')
    891. text.insert(tk.END, '\n')
    892. text.insert(tk.END, '\n')
    893. text.insert(tk.END, '\n')
    894. text.insert(tk.END, '******************作者*******************\n')
    895. text.insert(tk.END, '\n')
    896. text.insert(tk.END, '1. 他叫曹高远,来自河北保定\n')
    897. text.insert(tk.END, '\n')
    898. text.insert(tk.END, '\n')
    899. text.insert(tk.END, '\n')
    900. text.insert(tk.END, '\n')
    901. text.configure(state=tk.DISABLED)
    902. text.pack(side=tk.BOTTOM, fill=tk.BOTH)
    903. root.mainloop()
    904. def when_exit_do(self):
    905. global running
    906. if not self.running:
    907. if self.saved:
    908. self.save()
    909. if self.saved:
    910. self.root.destroy()
    911. self.myrun = False
    912. if running == 1:
    913. sys.exit(0)
    914. else:
    915. running -= 1
    916. else:
    917. a = tm.askyesnocancel('CASM文本编辑器', '你没有保存文件,是否保存后再退出?')
    918. if a:
    919. self.save()
    920. if self.saved:
    921. self.root.destroy()
    922. self.myrun = False
    923. if running == 1:
    924. sys.exit(0)
    925. else:
    926. running -= 1
    927. elif a is None:
    928. pass
    929. else:
    930. self.myrun = False
    931. self.root.destroy()
    932. self.myrun = False
    933. if running == 1:
    934. sys.exit(0)
    935. else:
    936. running -= 1
    937. else:
    938. tm.showerror('文本编辑器', '文件正在运行,请先关闭。')
    939. def about_file(self):
    940. if self.name != '':
    941. root = tk.Toplevel()
    942. root.title('关于文件')
    943. root.geometry('600x500')
    944. try:
    945. root.iconbitmap(r'images\lego.ico')
    946. except tkinter.TclError:
    947. pass
    948. label = tk.Label(root)
    949. string = f"""
    950. 文件名: {os.path.basename(self.name)}
    951. 文件路径: {self.name}
    952. 拓展名: {os.path.splitext(self.name)[-1]}
    953. 大小: {round(os.path.getsize(self.name) / 1024, 2)} kb ({round(os.path.getsize(self.name), 2)} b)
    954. """
    955. label.config(text=string)
    956. label.pack()
    957. root.mainloop()
    958. else:
    959. self.mycallsave()
    960. def check():
    961. system = os.name
    962. if system != 'nt':
    963. tm.showerror('ERROR!', '本程序只支持Microsoft Windows系统。')
    964. raise SystemExit('SYSTEM ERROR!')
    965. root = T_tk.Tk()
    966. root.withdraw()
    967. if 'casm.exe' in os.listdir(os.path.dirname(os.path.abspath(__file__))):
    968. tm.showinfo('恭喜!', '一切正常,您可以使用本编辑器!')
    969. else:
    970. tm.showerror('错误', '请确保您的电脑上已安装CASM。')
    971. sys.exit()
    972. root.destroy()
    973. def hello():
    974. root = T_tk.Tk()
    975. root.title('Hello-CASM editor %s' % version)
    976. root.resizable(False, False)
    977. root.attributes("-topmost", True)
    978. try:
    979. root.iconbitmap(r'images\lego.ico')
    980. except tkinter.TclError:
    981. pass
    982. try:
    983. img = tk.PhotoImage(file=r'23.4.1/images\lego.png')
    984. label = tk.Label(root, image=img)
    985. label.pack()
    986. except tkinter.TclError:
    987. pass
    988. label2 = tk.Label(root, text='正在加载中,请稍后……', font=('宋体', 25))
    989. label2.pack()
    990. pr = tkinter.ttk.Progressbar(root, length=700)
    991. pr['maximum'] = 100
    992. pr['value'] = 0
    993. pr.pack()
    994. def a():
    995. try:
    996. for i in range(100):
    997. pr['value'] += 1
    998. label2.configure(text=f'正在加载…… ( {i}% )')
    999. root.update()
    1000. time.sleep(0.01)
    1001. label2.configure(text=f'正在加载…… ( 100% ),完成!')
    1002. root.update()
    1003. time.sleep(0.001)
    1004. except (tkinter.TclError, RuntimeError, Exception):
    1005. return
    1006. label2.configure(text=f'按窗口内任意位置以继续……')
    1007. root.update()
    1008. def aa(*args, **kwargs):
    1009. root.destroy()
    1010. root.bind('', aa)
    1011. try:
    1012. a()
    1013. except tkinter.TclError:
    1014. return
    1015. root.mainloop()
    1016. def new():
    1017. gui = GUI()
    1018. gui.run()
    1019. def main():
    1020. try:
    1021. new()
    1022. T_tk.mainloop()
    1023. except (RuntimeError, tkinter.TclError, KeyboardInterrupt):
    1024. sys.exit()
    1025. if __name__ == '__main__':
    1026. main()

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

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

  • 相关阅读:
    base相关密码特征
    022-final关键字在 java 中的作用
    VS生成动态库(VS2022、CUDA、Lib)
    【Java多线程】你了解死锁吗?【Lock锁】
    解决node_modules\node-sassnpm ERR! command failed
    指针笔试题讲解(让指针变得简单易懂)
    openvpn crl.pem证书过期问题
    hive从入门到放弃(四)——分区与分桶
    文件打包下载excel导出和word导出
    将VOC数据格式转换为YOLO数据格式(附源码)
  • 原文地址:https://blog.csdn.net/cgy091107/article/details/133426112